blob: b310ca7baf25a9ea7ba40f6224fd7c39a31de546 [file] [log] [blame]
[email protected]94f206c12012-08-25 00:09:141// Copyright 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5
6#include "config.h"
7
8#if USE(ACCELERATED_COMPOSITING)
9#include "CCRendererGL.h"
10
11#include "CCDamageTracker.h"
12#include "CCLayerQuad.h"
13#include "CCMathUtil.h"
14#include "CCProxy.h"
15#include "CCRenderPass.h"
16#include "CCRenderSurfaceFilters.h"
17#include "CCScopedTexture.h"
18#include "CCSettings.h"
19#include "CCSingleThreadProxy.h"
20#include "CCVideoLayerImpl.h"
21#include "Extensions3D.h"
22#include "FloatQuad.h"
23#include "GeometryBinding.h"
24#include "GrTexture.h"
25#include "NotImplemented.h"
26#include "PlatformColor.h"
27#include "SkBitmap.h"
28#include "SkColor.h"
[email protected]94f206c12012-08-25 00:09:1429#include "TraceEvent.h"
[email protected]515e8d232012-09-10 19:15:2730#ifdef LOG
31#undef LOG
32#endif
33#include "base/string_split.h"
[email protected]231d7b5b2012-09-13 03:06:4934#include "base/string_util.h"
[email protected]94f206c12012-08-25 00:09:1435#include <public/WebGraphicsContext3D.h>
36#include <public/WebSharedGraphicsContext3D.h>
37#include <public/WebVideoFrame.h>
[email protected]515e8d232012-09-10 19:15:2738#include <set>
39#include <string>
40#include <vector>
[email protected]94f206c12012-08-25 00:09:1441#include <wtf/CurrentTime.h>
[email protected]702f703272012-09-15 02:57:2942#include <wtf/OwnArrayPtr.h>
[email protected]94f206c12012-08-25 00:09:1443
44using namespace std;
45using WebKit::WebGraphicsContext3D;
46using WebKit::WebGraphicsMemoryAllocation;
47using WebKit::WebSharedGraphicsContext3D;
48using WebKit::WebTransformationMatrix;
49
[email protected]9c88e562012-09-14 22:21:3050namespace cc {
[email protected]94f206c12012-08-25 00:09:1451
52namespace {
53
54bool needsIOSurfaceReadbackWorkaround()
55{
56#if OS(DARWIN)
57 return true;
58#else
59 return false;
60#endif
61}
62
63} // anonymous namespace
64
[email protected]ed4685982012-09-18 03:44:5865PassOwnPtr<CCRendererGL> CCRendererGL::create(CCRendererClient* client, CCResourceProvider* resourceProvider)
[email protected]94f206c12012-08-25 00:09:1466{
[email protected]ed4685982012-09-18 03:44:5867 OwnPtr<CCRendererGL> renderer(adoptPtr(new CCRendererGL(client, resourceProvider)));
[email protected]94f206c12012-08-25 00:09:1468 if (!renderer->initialize())
69 return nullptr;
70
71 return renderer.release();
72}
73
74CCRendererGL::CCRendererGL(CCRendererClient* client,
[email protected]ed4685982012-09-18 03:44:5875 CCResourceProvider* resourceProvider)
[email protected]94f206c12012-08-25 00:09:1476 : CCDirectRenderer(client, resourceProvider)
77 , m_offscreenFramebufferId(0)
78 , m_sharedGeometryQuad(FloatRect(-0.5f, -0.5f, 1.0f, 1.0f))
79 , m_context(resourceProvider->graphicsContext3D())
80 , m_isViewportChanged(false)
81 , m_isFramebufferDiscarded(false)
82 , m_isUsingBindUniform(false)
83 , m_visible(true)
[email protected]94f206c12012-08-25 00:09:1484{
85 ASSERT(m_context);
86}
87
88bool CCRendererGL::initialize()
89{
90 if (!m_context->makeContextCurrent())
91 return false;
92
93 m_context->setContextLostCallback(this);
94 m_context->pushGroupMarkerEXT("CompositorContext");
95
[email protected]515e8d232012-09-10 19:15:2796 std::string extensionsString = UTF16ToASCII(m_context->getString(GraphicsContext3D::EXTENSIONS));
97 std::vector<std::string> extensionsList;
98 base::SplitString(extensionsString, ' ', &extensionsList);
99 std::set<string> extensions(extensionsList.begin(), extensionsList.end());
[email protected]94f206c12012-08-25 00:09:14100
[email protected]515e8d232012-09-10 19:15:27101 if (settings().acceleratePainting && extensions.count("GL_EXT_texture_format_BGRA8888")
102 && extensions.count("GL_EXT_read_format_bgra"))
[email protected]94f206c12012-08-25 00:09:14103 m_capabilities.usingAcceleratedPainting = true;
104 else
105 m_capabilities.usingAcceleratedPainting = false;
106
107
[email protected]515e8d232012-09-10 19:15:27108 m_capabilities.contextHasCachedFrontBuffer = extensions.count("GL_CHROMIUM_front_buffer_cached");
[email protected]94f206c12012-08-25 00:09:14109
[email protected]515e8d232012-09-10 19:15:27110 m_capabilities.usingPartialSwap = CCSettings::partialSwapEnabled() && extensions.count("GL_CHROMIUM_post_sub_buffer");
[email protected]94f206c12012-08-25 00:09:14111
112 // Use the swapBuffers callback only with the threaded proxy.
113 if (CCProxy::hasImplThread())
[email protected]515e8d232012-09-10 19:15:27114 m_capabilities.usingSwapCompleteCallback = extensions.count("GL_CHROMIUM_swapbuffers_complete_callback");
[email protected]94f206c12012-08-25 00:09:14115 if (m_capabilities.usingSwapCompleteCallback)
116 m_context->setSwapBuffersCompleteCallbackCHROMIUM(this);
117
[email protected]515e8d232012-09-10 19:15:27118 m_capabilities.usingSetVisibility = extensions.count("GL_CHROMIUM_set_visibility");
[email protected]94f206c12012-08-25 00:09:14119
[email protected]515e8d232012-09-10 19:15:27120 if (extensions.count("GL_CHROMIUM_iosurface"))
121 ASSERT(extensions.count("GL_ARB_texture_rectangle"));
[email protected]94f206c12012-08-25 00:09:14122
[email protected]515e8d232012-09-10 19:15:27123 m_capabilities.usingGpuMemoryManager = extensions.count("GL_CHROMIUM_gpu_memory_manager");
[email protected]94f206c12012-08-25 00:09:14124 if (m_capabilities.usingGpuMemoryManager)
125 m_context->setMemoryAllocationChangedCallbackCHROMIUM(this);
126
[email protected]515e8d232012-09-10 19:15:27127 m_capabilities.usingDiscardFramebuffer = extensions.count("GL_CHROMIUM_discard_framebuffer");
[email protected]94f206c12012-08-25 00:09:14128
[email protected]515e8d232012-09-10 19:15:27129 m_capabilities.usingEglImage = extensions.count("GL_OES_EGL_image_external");
[email protected]94f206c12012-08-25 00:09:14130
131 GLC(m_context, m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_capabilities.maxTextureSize));
[email protected]515e8d232012-09-10 19:15:27132 m_capabilities.bestTextureFormat = PlatformColor::bestTextureFormat(m_context, extensions.count("GL_EXT_texture_format_BGRA8888"));
[email protected]94f206c12012-08-25 00:09:14133
[email protected]515e8d232012-09-10 19:15:27134 m_isUsingBindUniform = extensions.count("GL_CHROMIUM_bind_uniform_location");
[email protected]94f206c12012-08-25 00:09:14135
136 if (!initializeSharedObjects())
137 return false;
138
139 // Make sure the viewport and context gets initialized, even if it is to zero.
140 viewportChanged();
141 return true;
142}
143
144CCRendererGL::~CCRendererGL()
145{
146 ASSERT(CCProxy::isImplThread());
147 m_context->setSwapBuffersCompleteCallbackCHROMIUM(0);
148 m_context->setMemoryAllocationChangedCallbackCHROMIUM(0);
149 m_context->setContextLostCallback(0);
150 cleanupSharedObjects();
151}
152
153WebGraphicsContext3D* CCRendererGL::context()
154{
155 return m_context;
156}
157
158void CCRendererGL::debugGLCall(WebGraphicsContext3D* context, const char* command, const char* file, int line)
159{
160 unsigned long error = context->getError();
161 if (error != GraphicsContext3D::NO_ERROR)
162 LOG_ERROR("GL command failed: File: %s\n\tLine %d\n\tcommand: %s, error %x\n", file, line, command, static_cast<int>(error));
163}
164
165void CCRendererGL::setVisible(bool visible)
166{
167 if (m_visible == visible)
168 return;
169 m_visible = visible;
170
171 // TODO: Replace setVisibilityCHROMIUM with an extension to explicitly manage front/backbuffers
172 // crbug.com/116049
173 if (m_capabilities.usingSetVisibility)
174 m_context->setVisibilityCHROMIUM(visible);
175}
176
177void CCRendererGL::releaseRenderPassTextures()
178{
179 m_renderPassTextures.clear();
180}
181
182void CCRendererGL::viewportChanged()
183{
184 m_isViewportChanged = true;
185}
186
187void CCRendererGL::clearFramebuffer(DrawingFrame& frame)
188{
189 // On DEBUG builds, opaque render passes are cleared to blue to easily see regions that were not drawn on the screen.
190 if (frame.currentRenderPass->hasTransparentBackground())
191 GLC(m_context, m_context->clearColor(0, 0, 0, 0));
192 else
193 GLC(m_context, m_context->clearColor(0, 0, 1, 1));
194
195#if defined(NDEBUG)
196 if (frame.currentRenderPass->hasTransparentBackground())
197#endif
198 m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
199}
200
201void CCRendererGL::beginDrawingFrame(DrawingFrame& frame)
202{
203 // FIXME: Remove this once framebuffer is automatically recreated on first use
204 ensureFramebuffer();
205
206 if (viewportSize().isEmpty())
207 return;
208
209 TRACE_EVENT0("cc", "CCRendererGL::drawLayers");
210 if (m_isViewportChanged) {
211 // Only reshape when we know we are going to draw. Otherwise, the reshape
212 // can leave the window at the wrong size if we never draw and the proper
213 // viewport size is never set.
214 m_isViewportChanged = false;
215 m_context->reshape(viewportWidth(), viewportHeight());
216 }
217
218 makeContextCurrent();
219 // Bind the common vertex attributes used for drawing all the layers.
220 m_sharedGeometry->prepareForDraw();
221
222 GLC(m_context, m_context->disable(GraphicsContext3D::DEPTH_TEST));
223 GLC(m_context, m_context->disable(GraphicsContext3D::CULL_FACE));
224 GLC(m_context, m_context->colorMask(true, true, true, true));
225 GLC(m_context, m_context->enable(GraphicsContext3D::BLEND));
226 GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
227}
228
229void CCRendererGL::doNoOp()
230{
231 GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
232 GLC(m_context, m_context->flush());
233}
234
235void CCRendererGL::drawQuad(DrawingFrame& frame, const CCDrawQuad* quad)
236{
237 if (quad->needsBlending())
238 GLC(m_context, m_context->enable(GraphicsContext3D::BLEND));
239 else
240 GLC(m_context, m_context->disable(GraphicsContext3D::BLEND));
241
242 switch (quad->material()) {
243 case CCDrawQuad::Invalid:
244 ASSERT_NOT_REACHED();
245 break;
246 case CCDrawQuad::Checkerboard:
247 drawCheckerboardQuad(frame, CCCheckerboardDrawQuad::materialCast(quad));
248 break;
249 case CCDrawQuad::DebugBorder:
250 drawDebugBorderQuad(frame, CCDebugBorderDrawQuad::materialCast(quad));
251 break;
252 case CCDrawQuad::IOSurfaceContent:
253 drawIOSurfaceQuad(frame, CCIOSurfaceDrawQuad::materialCast(quad));
254 break;
255 case CCDrawQuad::RenderPass:
256 drawRenderPassQuad(frame, CCRenderPassDrawQuad::materialCast(quad));
257 break;
258 case CCDrawQuad::SolidColor:
259 drawSolidColorQuad(frame, CCSolidColorDrawQuad::materialCast(quad));
260 break;
261 case CCDrawQuad::StreamVideoContent:
262 drawStreamVideoQuad(frame, CCStreamVideoDrawQuad::materialCast(quad));
263 break;
264 case CCDrawQuad::TextureContent:
265 drawTextureQuad(frame, CCTextureDrawQuad::materialCast(quad));
266 break;
267 case CCDrawQuad::TiledContent:
268 drawTileQuad(frame, CCTileDrawQuad::materialCast(quad));
269 break;
270 case CCDrawQuad::YUVVideoContent:
271 drawYUVVideoQuad(frame, CCYUVVideoDrawQuad::materialCast(quad));
272 break;
273 }
274}
275
276void CCRendererGL::drawCheckerboardQuad(const DrawingFrame& frame, const CCCheckerboardDrawQuad* quad)
277{
278 const TileCheckerboardProgram* program = tileCheckerboardProgram();
279 ASSERT(program && program->initialized());
280 GLC(context(), context()->useProgram(program->program()));
281
282 IntRect tileRect = quad->quadRect();
283 float texOffsetX = tileRect.x();
284 float texOffsetY = tileRect.y();
285 float texScaleX = tileRect.width();
286 float texScaleY = tileRect.height();
287 GLC(context(), context()->uniform4f(program->fragmentShader().texTransformLocation(), texOffsetX, texOffsetY, texScaleX, texScaleY));
288
289 const int checkerboardWidth = 16;
290 float frequency = 1.0 / checkerboardWidth;
291
292 GLC(context(), context()->uniform1f(program->fragmentShader().frequencyLocation(), frequency));
293
294 setShaderOpacity(quad->opacity(), program->fragmentShader().alphaLocation());
295 drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->vertexShader().matrixLocation());
296}
297
298void CCRendererGL::drawDebugBorderQuad(const DrawingFrame& frame, const CCDebugBorderDrawQuad* quad)
299{
300 static float glMatrix[16];
301 const SolidColorProgram* program = solidColorProgram();
302 ASSERT(program && program->initialized());
303 GLC(context(), context()->useProgram(program->program()));
304
305 // Use the full quadRect for debug quads to not move the edges based on partial swaps.
306 const IntRect& layerRect = quad->quadRect();
307 WebTransformationMatrix renderMatrix = quad->quadTransform();
308 renderMatrix.translate(0.5 * layerRect.width() + layerRect.x(), 0.5 * layerRect.height() + layerRect.y());
309 renderMatrix.scaleNonUniform(layerRect.width(), layerRect.height());
310 CCRendererGL::toGLMatrix(&glMatrix[0], frame.projectionMatrix * renderMatrix);
311 GLC(context(), context()->uniformMatrix4fv(program->vertexShader().matrixLocation(), 1, false, &glMatrix[0]));
312
313 SkColor color = quad->color();
314 float alpha = SkColorGetA(color) / 255.0;
315
316 GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), (SkColorGetR(color) / 255.0) * alpha, (SkColorGetG(color) / 255.0) * alpha, (SkColorGetB(color) / 255.0) * alpha, alpha));
317
318 GLC(context(), context()->lineWidth(quad->width()));
319
320 // The indices for the line are stored in the same array as the triangle indices.
321 GLC(context(), context()->drawElements(GraphicsContext3D::LINE_LOOP, 4, GraphicsContext3D::UNSIGNED_SHORT, 6 * sizeof(unsigned short)));
322}
323
324static inline SkBitmap applyFilters(CCRendererGL* renderer, const WebKit::WebFilterOperations& filters, CCScopedTexture* sourceTexture)
325{
326 if (filters.isEmpty())
327 return SkBitmap();
328
329 WebGraphicsContext3D* filterContext = CCProxy::hasImplThread() ? WebSharedGraphicsContext3D::compositorThreadContext() : WebSharedGraphicsContext3D::mainThreadContext();
330 GrContext* filterGrContext = CCProxy::hasImplThread() ? WebSharedGraphicsContext3D::compositorThreadGrContext() : WebSharedGraphicsContext3D::mainThreadGrContext();
331
332 if (!filterContext || !filterGrContext)
333 return SkBitmap();
334
335 renderer->context()->flush();
336
337 CCResourceProvider::ScopedWriteLockGL lock(renderer->resourceProvider(), sourceTexture->id());
338 SkBitmap source = CCRenderSurfaceFilters::apply(filters, lock.textureId(), sourceTexture->size(), filterContext, filterGrContext);
339 return source;
340}
341
342PassOwnPtr<CCScopedTexture> CCRendererGL::drawBackgroundFilters(DrawingFrame& frame, const CCRenderPassDrawQuad* quad, const WebKit::WebFilterOperations& filters, const WebTransformationMatrix& contentsDeviceTransform)
343{
344 // This method draws a background filter, which applies a filter to any pixels behind the quad and seen through its background.
345 // The algorithm works as follows:
346 // 1. Compute a bounding box around the pixels that will be visible through the quad.
347 // 2. Read the pixels in the bounding box into a buffer R.
348 // 3. Apply the background filter to R, so that it is applied in the pixels' coordinate space.
349 // 4. Apply the quad's inverse transform to map the pixels in R into the quad's content space. This implicitly
350 // clips R by the content bounds of the quad since the destination texture has bounds matching the quad's content.
351 // 5. Draw the background texture for the contents using the same transform as used to draw the contents itself. This is done
352 // without blending to replace the current background pixels with the new filtered background.
353 // 6. Draw the contents of the quad over drop of the new background with blending, as per usual. The filtered background
354 // pixels will show through any non-opaque pixels in this draws.
355 //
356 // Pixel copies in this algorithm occur at steps 2, 3, 4, and 5.
357
358 // FIXME: When this algorithm changes, update CCLayerTreeHost::prioritizeTextures() accordingly.
359
360 if (filters.isEmpty())
361 return nullptr;
362
363 // FIXME: We only allow background filters on an opaque render surface because other surfaces may contain
364 // translucent pixels, and the contents behind those translucent pixels wouldn't have the filter applied.
365 if (frame.currentRenderPass->hasTransparentBackground())
366 return nullptr;
367 ASSERT(!frame.currentTexture);
368
369 // FIXME: Do a single readback for both the surface and replica and cache the filtered results (once filter textures are not reused).
370 IntRect deviceRect = enclosingIntRect(CCMathUtil::mapClippedRect(contentsDeviceTransform, sharedGeometryQuad().boundingBox()));
371
372 int top, right, bottom, left;
373 filters.getOutsets(top, right, bottom, left);
374 deviceRect.move(-left, -top);
375 deviceRect.expand(left + right, top + bottom);
376
377 deviceRect.intersect(frame.currentRenderPass->outputRect());
378
379 OwnPtr<CCScopedTexture> deviceBackgroundTexture = CCScopedTexture::create(m_resourceProvider);
380 if (!getFramebufferTexture(deviceBackgroundTexture.get(), deviceRect))
381 return nullptr;
382
383 SkBitmap filteredDeviceBackground = applyFilters(this, filters, deviceBackgroundTexture.get());
384 if (!filteredDeviceBackground.getTexture())
385 return nullptr;
386
387 GrTexture* texture = reinterpret_cast<GrTexture*>(filteredDeviceBackground.getTexture());
388 int filteredDeviceBackgroundTextureId = texture->getTextureHandle();
389
390 OwnPtr<CCScopedTexture> backgroundTexture = CCScopedTexture::create(m_resourceProvider);
391 if (!backgroundTexture->allocate(CCRenderer::ImplPool, quad->quadRect().size(), GraphicsContext3D::RGBA, CCResourceProvider::TextureUsageFramebuffer))
392 return nullptr;
393
394 const CCRenderPass* targetRenderPass = frame.currentRenderPass;
395 bool usingBackgroundTexture = useScopedTexture(frame, backgroundTexture.get(), quad->quadRect());
396
397 if (usingBackgroundTexture) {
398 // Copy the readback pixels from device to the background texture for the surface.
399 WebTransformationMatrix deviceToFramebufferTransform;
400 deviceToFramebufferTransform.translate(quad->quadRect().width() / 2.0, quad->quadRect().height() / 2.0);
401 deviceToFramebufferTransform.scale3d(quad->quadRect().width(), quad->quadRect().height(), 1);
402 deviceToFramebufferTransform.multiply(contentsDeviceTransform.inverse());
403 copyTextureToFramebuffer(frame, filteredDeviceBackgroundTextureId, deviceRect, deviceToFramebufferTransform);
404 }
405
406 useRenderPass(frame, targetRenderPass);
407
408 if (!usingBackgroundTexture)
409 return nullptr;
410 return backgroundTexture.release();
411}
412
413void CCRendererGL::drawRenderPassQuad(DrawingFrame& frame, const CCRenderPassDrawQuad* quad)
414{
415 CachedTexture* contentsTexture = m_renderPassTextures.get(quad->renderPassId());
416 if (!contentsTexture || !contentsTexture->id())
417 return;
418
419 const CCRenderPass* renderPass = frame.renderPassesById->get(quad->renderPassId());
420 ASSERT(renderPass);
421 if (!renderPass)
422 return;
423
424 WebTransformationMatrix renderMatrix = quad->quadTransform();
425 renderMatrix.translate(0.5 * quad->quadRect().width() + quad->quadRect().x(), 0.5 * quad->quadRect().height() + quad->quadRect().y());
426 WebTransformationMatrix deviceMatrix = renderMatrix;
427 deviceMatrix.scaleNonUniform(quad->quadRect().width(), quad->quadRect().height());
428 WebTransformationMatrix contentsDeviceTransform = WebTransformationMatrix(frame.windowMatrix * frame.projectionMatrix * deviceMatrix).to2dTransform();
429
430 // Can only draw surface if device matrix is invertible.
431 if (!contentsDeviceTransform.isInvertible())
432 return;
433
434 OwnPtr<CCScopedTexture> backgroundTexture = drawBackgroundFilters(frame, quad, renderPass->backgroundFilters(), contentsDeviceTransform);
435
436 // FIXME: Cache this value so that we don't have to do it for both the surface and its replica.
437 // Apply filters to the contents texture.
438 SkBitmap filterBitmap = applyFilters(this, renderPass->filters(), contentsTexture);
439 OwnPtr<CCResourceProvider::ScopedReadLockGL> contentsResourceLock;
440 unsigned contentsTextureId = 0;
441 if (filterBitmap.getTexture()) {
442 GrTexture* texture = reinterpret_cast<GrTexture*>(filterBitmap.getTexture());
443 contentsTextureId = texture->getTextureHandle();
444 } else {
445 contentsResourceLock = adoptPtr(new CCResourceProvider::ScopedReadLockGL(m_resourceProvider, contentsTexture->id()));
446 contentsTextureId = contentsResourceLock->textureId();
447 }
448
449 // Draw the background texture if there is one.
450 if (backgroundTexture) {
451 ASSERT(backgroundTexture->size() == quad->quadRect().size());
452 CCResourceProvider::ScopedReadLockGL lock(m_resourceProvider, backgroundTexture->id());
453 copyTextureToFramebuffer(frame, lock.textureId(), quad->quadRect(), quad->quadTransform());
454 }
455
456 bool clipped = false;
457 FloatQuad deviceQuad = CCMathUtil::mapQuad(contentsDeviceTransform, sharedGeometryQuad(), clipped);
458 ASSERT(!clipped);
459 CCLayerQuad deviceLayerBounds = CCLayerQuad(FloatQuad(deviceQuad.boundingBox()));
460 CCLayerQuad deviceLayerEdges = CCLayerQuad(deviceQuad);
461
462 // Use anti-aliasing programs only when necessary.
463 bool useAA = (!deviceQuad.isRectilinear() || !deviceQuad.boundingBox().isExpressibleAsIntRect());
464 if (useAA) {
465 deviceLayerBounds.inflateAntiAliasingDistance();
466 deviceLayerEdges.inflateAntiAliasingDistance();
467 }
468
469 OwnPtr<CCResourceProvider::ScopedReadLockGL> maskResourceLock;
470 unsigned maskTextureId = 0;
471 if (quad->maskResourceId()) {
472 maskResourceLock = adoptPtr(new CCResourceProvider::ScopedReadLockGL(m_resourceProvider, quad->maskResourceId()));
473 maskTextureId = maskResourceLock->textureId();
474 }
475
476 // FIXME: use the backgroundTexture and blend the background in with this draw instead of having a separate copy of the background texture.
477
478 GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
479 context()->bindTexture(GraphicsContext3D::TEXTURE_2D, contentsTextureId);
480
481 int shaderQuadLocation = -1;
482 int shaderEdgeLocation = -1;
483 int shaderMaskSamplerLocation = -1;
484 int shaderMaskTexCoordScaleLocation = -1;
485 int shaderMaskTexCoordOffsetLocation = -1;
486 int shaderMatrixLocation = -1;
487 int shaderAlphaLocation = -1;
488 if (useAA && maskTextureId) {
489 const RenderPassMaskProgramAA* program = renderPassMaskProgramAA();
490 GLC(context(), context()->useProgram(program->program()));
491 GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
492
493 shaderQuadLocation = program->vertexShader().pointLocation();
494 shaderEdgeLocation = program->fragmentShader().edgeLocation();
495 shaderMaskSamplerLocation = program->fragmentShader().maskSamplerLocation();
496 shaderMaskTexCoordScaleLocation = program->fragmentShader().maskTexCoordScaleLocation();
497 shaderMaskTexCoordOffsetLocation = program->fragmentShader().maskTexCoordOffsetLocation();
498 shaderMatrixLocation = program->vertexShader().matrixLocation();
499 shaderAlphaLocation = program->fragmentShader().alphaLocation();
500 } else if (!useAA && maskTextureId) {
501 const RenderPassMaskProgram* program = renderPassMaskProgram();
502 GLC(context(), context()->useProgram(program->program()));
503 GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
504
505 shaderMaskSamplerLocation = program->fragmentShader().maskSamplerLocation();
506 shaderMaskTexCoordScaleLocation = program->fragmentShader().maskTexCoordScaleLocation();
507 shaderMaskTexCoordOffsetLocation = program->fragmentShader().maskTexCoordOffsetLocation();
508 shaderMatrixLocation = program->vertexShader().matrixLocation();
509 shaderAlphaLocation = program->fragmentShader().alphaLocation();
510 } else if (useAA && !maskTextureId) {
511 const RenderPassProgramAA* program = renderPassProgramAA();
512 GLC(context(), context()->useProgram(program->program()));
513 GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
514
515 shaderQuadLocation = program->vertexShader().pointLocation();
516 shaderEdgeLocation = program->fragmentShader().edgeLocation();
517 shaderMatrixLocation = program->vertexShader().matrixLocation();
518 shaderAlphaLocation = program->fragmentShader().alphaLocation();
519 } else {
520 const RenderPassProgram* program = renderPassProgram();
521 GLC(context(), context()->useProgram(program->program()));
522 GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
523
524 shaderMatrixLocation = program->vertexShader().matrixLocation();
525 shaderAlphaLocation = program->fragmentShader().alphaLocation();
526 }
527
528 if (shaderMaskSamplerLocation != -1) {
529 ASSERT(shaderMaskTexCoordScaleLocation != 1);
530 ASSERT(shaderMaskTexCoordOffsetLocation != 1);
531 GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE1));
532 GLC(context(), context()->uniform1i(shaderMaskSamplerLocation, 1));
533 GLC(context(), context()->uniform2f(shaderMaskTexCoordScaleLocation, quad->maskTexCoordScaleX(), quad->maskTexCoordScaleY()));
534 GLC(context(), context()->uniform2f(shaderMaskTexCoordOffsetLocation, quad->maskTexCoordOffsetX(), quad->maskTexCoordOffsetY()));
535 context()->bindTexture(GraphicsContext3D::TEXTURE_2D, maskTextureId);
536 GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
537 }
538
539 if (shaderEdgeLocation != -1) {
540 float edge[24];
541 deviceLayerEdges.toFloatArray(edge);
542 deviceLayerBounds.toFloatArray(&edge[12]);
543 GLC(context(), context()->uniform3fv(shaderEdgeLocation, 8, edge));
544 }
545
546 // Map device space quad to surface space. contentsDeviceTransform has no 3d component since it was generated with to2dTransform() so we don't need to project.
547 FloatQuad surfaceQuad = CCMathUtil::mapQuad(contentsDeviceTransform.inverse(), deviceLayerEdges.floatQuad(), clipped);
548 ASSERT(!clipped);
549
550 setShaderOpacity(quad->opacity(), shaderAlphaLocation);
551 setShaderFloatQuad(surfaceQuad, shaderQuadLocation);
552 drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), shaderMatrixLocation);
553}
554
555void CCRendererGL::drawSolidColorQuad(const DrawingFrame& frame, const CCSolidColorDrawQuad* quad)
556{
557 const SolidColorProgram* program = solidColorProgram();
558 GLC(context(), context()->useProgram(program->program()));
559
560 SkColor color = quad->color();
561 float opacity = quad->opacity();
562 float alpha = (SkColorGetA(color) / 255.0) * opacity;
563
564 GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), (SkColorGetR(color) / 255.0) * alpha, (SkColorGetG(color) / 255.0) * alpha, (SkColorGetB(color) / 255.0) * alpha, alpha));
565
566 drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->vertexShader().matrixLocation());
567}
568
569struct TileProgramUniforms {
570 unsigned program;
571 unsigned samplerLocation;
572 unsigned vertexTexTransformLocation;
573 unsigned fragmentTexTransformLocation;
574 unsigned edgeLocation;
575 unsigned matrixLocation;
576 unsigned alphaLocation;
577 unsigned pointLocation;
578};
579
580template<class T>
581static void tileUniformLocation(T program, TileProgramUniforms& uniforms)
582{
583 uniforms.program = program->program();
584 uniforms.vertexTexTransformLocation = program->vertexShader().vertexTexTransformLocation();
585 uniforms.matrixLocation = program->vertexShader().matrixLocation();
586 uniforms.pointLocation = program->vertexShader().pointLocation();
587
588 uniforms.samplerLocation = program->fragmentShader().samplerLocation();
589 uniforms.alphaLocation = program->fragmentShader().alphaLocation();
590 uniforms.fragmentTexTransformLocation = program->fragmentShader().fragmentTexTransformLocation();
591 uniforms.edgeLocation = program->fragmentShader().edgeLocation();
592}
593
594void CCRendererGL::drawTileQuad(const DrawingFrame& frame, const CCTileDrawQuad* quad)
595{
596 IntRect tileRect = quad->quadVisibleRect();
597
598 FloatRect clampRect(tileRect);
599 // Clamp texture coordinates to avoid sampling outside the layer
600 // by deflating the tile region half a texel or half a texel
601 // minus epsilon for one pixel layers. The resulting clamp region
602 // is mapped to the unit square by the vertex shader and mapped
603 // back to normalized texture coordinates by the fragment shader
604 // after being clamped to 0-1 range.
605 const float epsilon = 1 / 1024.0f;
606 float clampX = min(0.5, clampRect.width() / 2.0 - epsilon);
607 float clampY = min(0.5, clampRect.height() / 2.0 - epsilon);
608 clampRect.inflateX(-clampX);
609 clampRect.inflateY(-clampY);
610 FloatSize clampOffset = clampRect.minXMinYCorner() - FloatRect(tileRect).minXMinYCorner();
611
612 FloatPoint textureOffset = quad->textureOffset() + clampOffset +
613 IntPoint(tileRect.location() - quad->quadRect().location());
614
615 // Map clamping rectangle to unit square.
616 float vertexTexTranslateX = -clampRect.x() / clampRect.width();
617 float vertexTexTranslateY = -clampRect.y() / clampRect.height();
618 float vertexTexScaleX = tileRect.width() / clampRect.width();
619 float vertexTexScaleY = tileRect.height() / clampRect.height();
620
621 // Map to normalized texture coordinates.
622 const IntSize& textureSize = quad->textureSize();
623 float fragmentTexTranslateX = textureOffset.x() / textureSize.width();
624 float fragmentTexTranslateY = textureOffset.y() / textureSize.height();
625 float fragmentTexScaleX = clampRect.width() / textureSize.width();
626 float fragmentTexScaleY = clampRect.height() / textureSize.height();
627
628
629 FloatQuad localQuad;
630 WebTransformationMatrix deviceTransform = WebTransformationMatrix(frame.windowMatrix * frame.projectionMatrix * quad->quadTransform()).to2dTransform();
631 if (!deviceTransform.isInvertible())
632 return;
633
634 bool clipped = false;
635 FloatQuad deviceLayerQuad = CCMathUtil::mapQuad(deviceTransform, FloatQuad(quad->visibleContentRect()), clipped);
636 ASSERT(!clipped);
637
638 TileProgramUniforms uniforms;
639 // For now, we simply skip anti-aliasing with the quad is clipped. This only happens
640 // on perspective transformed layers that go partially behind the camera.
641 if (quad->isAntialiased() && !clipped) {
642 if (quad->swizzleContents())
643 tileUniformLocation(tileProgramSwizzleAA(), uniforms);
644 else
645 tileUniformLocation(tileProgramAA(), uniforms);
646 } else {
647 if (quad->needsBlending()) {
648 if (quad->swizzleContents())
649 tileUniformLocation(tileProgramSwizzle(), uniforms);
650 else
651 tileUniformLocation(tileProgram(), uniforms);
652 } else {
653 if (quad->swizzleContents())
654 tileUniformLocation(tileProgramSwizzleOpaque(), uniforms);
655 else
656 tileUniformLocation(tileProgramOpaque(), uniforms);
657 }
658 }
659
660 GLC(context(), context()->useProgram(uniforms.program));
661 GLC(context(), context()->uniform1i(uniforms.samplerLocation, 0));
662 GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
663 CCResourceProvider::ScopedReadLockGL quadResourceLock(m_resourceProvider, quad->resourceId());
664 GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quadResourceLock.textureId()));
665 GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, quad->textureFilter()));
666 GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, quad->textureFilter()));
667
668 bool useAA = !clipped && quad->isAntialiased();
669 if (useAA) {
670 CCLayerQuad deviceLayerBounds = CCLayerQuad(FloatQuad(deviceLayerQuad.boundingBox()));
671 deviceLayerBounds.inflateAntiAliasingDistance();
672
673 CCLayerQuad deviceLayerEdges = CCLayerQuad(deviceLayerQuad);
674 deviceLayerEdges.inflateAntiAliasingDistance();
675
676 float edge[24];
677 deviceLayerEdges.toFloatArray(edge);
678 deviceLayerBounds.toFloatArray(&edge[12]);
679 GLC(context(), context()->uniform3fv(uniforms.edgeLocation, 8, edge));
680
681 GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY));
682 GLC(context(), context()->uniform4f(uniforms.fragmentTexTransformLocation, fragmentTexTranslateX, fragmentTexTranslateY, fragmentTexScaleX, fragmentTexScaleY));
683
684 FloatPoint bottomRight(tileRect.maxX(), tileRect.maxY());
685 FloatPoint bottomLeft(tileRect.x(), tileRect.maxY());
686 FloatPoint topLeft(tileRect.x(), tileRect.y());
687 FloatPoint topRight(tileRect.maxX(), tileRect.y());
688
689 // Map points to device space.
690 bottomRight = CCMathUtil::mapPoint(deviceTransform, bottomRight, clipped);
691 ASSERT(!clipped);
692 bottomLeft = CCMathUtil::mapPoint(deviceTransform, bottomLeft, clipped);
693 ASSERT(!clipped);
694 topLeft = CCMathUtil::mapPoint(deviceTransform, topLeft, clipped);
695 ASSERT(!clipped);
696 topRight = CCMathUtil::mapPoint(deviceTransform, topRight, clipped);
697 ASSERT(!clipped);
698
699 CCLayerQuad::Edge bottomEdge(bottomRight, bottomLeft);
700 CCLayerQuad::Edge leftEdge(bottomLeft, topLeft);
701 CCLayerQuad::Edge topEdge(topLeft, topRight);
702 CCLayerQuad::Edge rightEdge(topRight, bottomRight);
703
704 // Only apply anti-aliasing to edges not clipped by culling or scissoring.
705 if (quad->topEdgeAA() && tileRect.y() == quad->quadRect().y())
706 topEdge = deviceLayerEdges.top();
707 if (quad->leftEdgeAA() && tileRect.x() == quad->quadRect().x())
708 leftEdge = deviceLayerEdges.left();
709 if (quad->rightEdgeAA() && tileRect.maxX() == quad->quadRect().maxX())
710 rightEdge = deviceLayerEdges.right();
711 if (quad->bottomEdgeAA() && tileRect.maxY() == quad->quadRect().maxY())
712 bottomEdge = deviceLayerEdges.bottom();
713
714 float sign = FloatQuad(tileRect).isCounterclockwise() ? -1 : 1;
715 bottomEdge.scale(sign);
716 leftEdge.scale(sign);
717 topEdge.scale(sign);
718 rightEdge.scale(sign);
719
720 // Create device space quad.
721 CCLayerQuad deviceQuad(leftEdge, topEdge, rightEdge, bottomEdge);
722
723 // Map device space quad to local space. contentsDeviceTransform has no 3d component since it was generated with to2dTransform() so we don't need to project.
724 WebTransformationMatrix inverseDeviceTransform = deviceTransform.inverse();
725 localQuad = CCMathUtil::mapQuad(inverseDeviceTransform, deviceQuad.floatQuad(), clipped);
726
727 // We should not ASSERT(!clipped) here, because anti-aliasing inflation may cause deviceQuad to become
728 // clipped. To our knowledge this scenario does not need to be handled differently than the unclipped case.
729 } else {
730 // Move fragment shader transform to vertex shader. We can do this while
731 // still producing correct results as fragmentTexTransformLocation
732 // should always be non-negative when tiles are transformed in a way
733 // that could result in sampling outside the layer.
734 vertexTexScaleX *= fragmentTexScaleX;
735 vertexTexScaleY *= fragmentTexScaleY;
736 vertexTexTranslateX *= fragmentTexScaleX;
737 vertexTexTranslateY *= fragmentTexScaleY;
738 vertexTexTranslateX += fragmentTexTranslateX;
739 vertexTexTranslateY += fragmentTexTranslateY;
740
741 GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY));
742
743 localQuad = FloatRect(tileRect);
744 }
745
746 // Normalize to tileRect.
747 localQuad.scale(1.0f / tileRect.width(), 1.0f / tileRect.height());
748
749 setShaderOpacity(quad->opacity(), uniforms.alphaLocation);
750 setShaderFloatQuad(localQuad, uniforms.pointLocation);
751
752 // The tile quad shader behaves differently compared to all other shaders.
753 // The transform and vertex data are used to figure out the extents that the
754 // un-antialiased quad should have and which vertex this is and the float
755 // quad passed in via uniform is the actual geometry that gets used to draw
756 // it. This is why this centered rect is used and not the original quadRect.
757 FloatRect centeredRect(FloatPoint(-0.5 * tileRect.width(), -0.5 * tileRect.height()), tileRect.size());
758 drawQuadGeometry(frame, quad->quadTransform(), centeredRect, uniforms.matrixLocation);
759}
760
761void CCRendererGL::drawYUVVideoQuad(const DrawingFrame& frame, const CCYUVVideoDrawQuad* quad)
762{
763 const VideoYUVProgram* program = videoYUVProgram();
764 ASSERT(program && program->initialized());
765
766 const CCVideoLayerImpl::FramePlane& yPlane = quad->yPlane();
767 const CCVideoLayerImpl::FramePlane& uPlane = quad->uPlane();
768 const CCVideoLayerImpl::FramePlane& vPlane = quad->vPlane();
769
770 CCResourceProvider::ScopedReadLockGL yPlaneLock(m_resourceProvider, yPlane.resourceId);
771 CCResourceProvider::ScopedReadLockGL uPlaneLock(m_resourceProvider, uPlane.resourceId);
772 CCResourceProvider::ScopedReadLockGL vPlaneLock(m_resourceProvider, vPlane.resourceId);
773 GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE1));
774 GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, yPlaneLock.textureId()));
775 GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE2));
776 GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, uPlaneLock.textureId()));
777 GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE3));
778 GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, vPlaneLock.textureId()));
779
780 GLC(context(), context()->useProgram(program->program()));
781
782 float yWidthScaleFactor = static_cast<float>(yPlane.visibleSize.width()) / yPlane.size.width();
783 // Arbitrarily take the u sizes because u and v dimensions are identical.
784 float uvWidthScaleFactor = static_cast<float>(uPlane.visibleSize.width()) / uPlane.size.width();
785 GLC(context(), context()->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor));
786 GLC(context(), context()->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor));
787
788 GLC(context(), context()->uniform1i(program->fragmentShader().yTextureLocation(), 1));
789 GLC(context(), context()->uniform1i(program->fragmentShader().uTextureLocation(), 2));
790 GLC(context(), context()->uniform1i(program->fragmentShader().vTextureLocation(), 3));
791
792 // These values are magic numbers that are used in the transformation from YUV to RGB color values.
793 // They are taken from the following webpage: http://www.fourcc.org/fccyvrgb.php
794 float yuv2RGB[9] = {
795 1.164f, 1.164f, 1.164f,
796 0.f, -.391f, 2.018f,
797 1.596f, -.813f, 0.f,
798 };
799 GLC(context(), context()->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 1, 0, yuv2RGB));
800
801 // These values map to 16, 128, and 128 respectively, and are computed
802 // as a fraction over 256 (e.g. 16 / 256 = 0.0625).
803 // They are used in the YUV to RGBA conversion formula:
804 // Y - 16 : Gives 16 values of head and footroom for overshooting
805 // U - 128 : Turns unsigned U into signed U [-128,127]
806 // V - 128 : Turns unsigned V into signed V [-128,127]
807 float yuvAdjust[3] = {
808 -0.0625f,
809 -0.5f,
810 -0.5f,
811 };
812 GLC(context(), context()->uniform3fv(program->fragmentShader().yuvAdjLocation(), 1, yuvAdjust));
813
814 setShaderOpacity(quad->opacity(), program->fragmentShader().alphaLocation());
815 drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->vertexShader().matrixLocation());
816
817 // Reset active texture back to texture 0.
818 GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
819}
820
821void CCRendererGL::drawStreamVideoQuad(const DrawingFrame& frame, const CCStreamVideoDrawQuad* quad)
822{
823 static float glMatrix[16];
824
825 ASSERT(m_capabilities.usingEglImage);
826
827 const VideoStreamTextureProgram* program = videoStreamTextureProgram();
828 GLC(context(), context()->useProgram(program->program()));
829
830 toGLMatrix(&glMatrix[0], quad->matrix());
831 GLC(context(), context()->uniformMatrix4fv(program->vertexShader().texMatrixLocation(), 1, false, glMatrix));
832
833 GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
834 GLC(context(), context()->bindTexture(Extensions3DChromium::GL_TEXTURE_EXTERNAL_OES, quad->textureId()));
835
836 GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
837
838 setShaderOpacity(quad->opacity(), program->fragmentShader().alphaLocation());
839 drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), program->vertexShader().matrixLocation());
840}
841
842struct TextureProgramBinding {
843 template<class Program> void set(Program* program)
844 {
845 ASSERT(program && program->initialized());
846 programId = program->program();
847 samplerLocation = program->fragmentShader().samplerLocation();
848 matrixLocation = program->vertexShader().matrixLocation();
849 alphaLocation = program->fragmentShader().alphaLocation();
850 }
851 int programId;
852 int samplerLocation;
853 int matrixLocation;
854 int alphaLocation;
855};
856
857struct TexTransformTextureProgramBinding : TextureProgramBinding {
858 template<class Program> void set(Program* program)
859 {
860 TextureProgramBinding::set(program);
861 texTransformLocation = program->vertexShader().texTransformLocation();
862 }
863 int texTransformLocation;
864};
865
866void CCRendererGL::drawTextureQuad(const DrawingFrame& frame, const CCTextureDrawQuad* quad)
867{
868 ASSERT(CCProxy::isImplThread());
869
870 TexTransformTextureProgramBinding binding;
871 if (quad->flipped())
872 binding.set(textureProgramFlip());
873 else
874 binding.set(textureProgram());
875 GLC(context(), context()->useProgram(binding.programId));
876 GLC(context(), context()->uniform1i(binding.samplerLocation, 0));
877 const FloatRect& uvRect = quad->uvRect();
878 GLC(context(), context()->uniform4f(binding.texTransformLocation, uvRect.x(), uvRect.y(), uvRect.width(), uvRect.height()));
879
880 GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
881 CCResourceProvider::ScopedReadLockGL quadResourceLock(m_resourceProvider, quad->resourceId());
882 GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quadResourceLock.textureId()));
883
884 // FIXME: setting the texture parameters every time is redundant. Move this code somewhere
885 // where it will only happen once per texture.
886 GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
887 GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
888 GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
889 GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
890
891 if (!quad->premultipliedAlpha()) {
892 // As it turns out, the premultiplied alpha blending function (ONE, ONE_MINUS_SRC_ALPHA)
893 // will never cause the alpha channel to be set to anything less than 1.0 if it is
894 // initialized to that value! Therefore, premultipliedAlpha being false is the first
895 // situation we can generally see an alpha channel less than 1.0 coming out of the
896 // compositor. This is causing platform differences in some layout tests (see
897 // https://bugs.webkit.org/show_bug.cgi?id=82412), so in this situation, use a separate
898 // blend function for the alpha channel to avoid modifying it. Don't use colorMask for this
899 // as it has performance implications on some platforms.
900 GLC(context(), context()->blendFuncSeparate(GraphicsContext3D::SRC_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA, GraphicsContext3D::ZERO, GraphicsContext3D::ONE));
901 }
902
903 setShaderOpacity(quad->opacity(), binding.alphaLocation);
904 drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), binding.matrixLocation);
905
906 if (!quad->premultipliedAlpha())
907 GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
908}
909
910void CCRendererGL::drawIOSurfaceQuad(const DrawingFrame& frame, const CCIOSurfaceDrawQuad* quad)
911{
912 ASSERT(CCProxy::isImplThread());
913 TexTransformTextureProgramBinding binding;
914 binding.set(textureIOSurfaceProgram());
915
916 GLC(context(), context()->useProgram(binding.programId));
917 GLC(context(), context()->uniform1i(binding.samplerLocation, 0));
918 if (quad->orientation() == CCIOSurfaceDrawQuad::Flipped)
919 GLC(context(), context()->uniform4f(binding.texTransformLocation, 0, quad->ioSurfaceSize().height(), quad->ioSurfaceSize().width(), quad->ioSurfaceSize().height() * -1.0));
920 else
921 GLC(context(), context()->uniform4f(binding.texTransformLocation, 0, 0, quad->ioSurfaceSize().width(), quad->ioSurfaceSize().height()));
922
923 GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
924 GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, quad->ioSurfaceTextureId()));
925
926 setShaderOpacity(quad->opacity(), binding.alphaLocation);
927 drawQuadGeometry(frame, quad->quadTransform(), quad->quadRect(), binding.matrixLocation);
928
929 GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, 0));
930}
931
932void CCRendererGL::finishDrawingFrame(DrawingFrame& frame)
933{
934 m_currentFramebufferLock.clear();
935 m_swapBufferRect.unite(enclosingIntRect(frame.rootDamageRect));
936
937 GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
938 GLC(m_context, m_context->disable(GraphicsContext3D::BLEND));
939}
940
941void CCRendererGL::toGLMatrix(float* flattened, const WebTransformationMatrix& m)
942{
943 flattened[0] = m.m11();
944 flattened[1] = m.m12();
945 flattened[2] = m.m13();
946 flattened[3] = m.m14();
947 flattened[4] = m.m21();
948 flattened[5] = m.m22();
949 flattened[6] = m.m23();
950 flattened[7] = m.m24();
951 flattened[8] = m.m31();
952 flattened[9] = m.m32();
953 flattened[10] = m.m33();
954 flattened[11] = m.m34();
955 flattened[12] = m.m41();
956 flattened[13] = m.m42();
957 flattened[14] = m.m43();
958 flattened[15] = m.m44();
959}
960
961void CCRendererGL::setShaderFloatQuad(const FloatQuad& quad, int quadLocation)
962{
963 if (quadLocation == -1)
964 return;
965
966 float point[8];
967 point[0] = quad.p1().x();
968 point[1] = quad.p1().y();
969 point[2] = quad.p2().x();
970 point[3] = quad.p2().y();
971 point[4] = quad.p3().x();
972 point[5] = quad.p3().y();
973 point[6] = quad.p4().x();
974 point[7] = quad.p4().y();
975 GLC(m_context, m_context->uniform2fv(quadLocation, 4, point));
976}
977
978void CCRendererGL::setShaderOpacity(float opacity, int alphaLocation)
979{
980 if (alphaLocation != -1)
981 GLC(m_context, m_context->uniform1f(alphaLocation, opacity));
982}
983
984void CCRendererGL::drawQuadGeometry(const DrawingFrame& frame, const WebKit::WebTransformationMatrix& drawTransform, const FloatRect& quadRect, int matrixLocation)
985{
986 WebTransformationMatrix quadRectMatrix;
987 quadRectTransform(&quadRectMatrix, drawTransform, quadRect);
988 static float glMatrix[16];
989 toGLMatrix(&glMatrix[0], frame.projectionMatrix * quadRectMatrix);
990 GLC(m_context, m_context->uniformMatrix4fv(matrixLocation, 1, false, &glMatrix[0]));
991
992 GLC(m_context, m_context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0));
993}
994
995void CCRendererGL::copyTextureToFramebuffer(const DrawingFrame& frame, int textureId, const IntRect& rect, const WebTransformationMatrix& drawMatrix)
996{
997 const RenderPassProgram* program = renderPassProgram();
998
999 GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
1000 GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
1001 GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
1002 GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
1003 GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
1004 GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
1005
1006 GLC(context(), context()->useProgram(program->program()));
1007 GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
1008 setShaderOpacity(1, program->fragmentShader().alphaLocation());
1009 drawQuadGeometry(frame, drawMatrix, rect, program->vertexShader().matrixLocation());
1010}
1011
1012void CCRendererGL::finish()
1013{
1014 TRACE_EVENT0("cc", "CCRendererGL::finish");
1015 m_context->finish();
1016}
1017
1018bool CCRendererGL::swapBuffers()
1019{
1020 ASSERT(m_visible);
1021 ASSERT(!m_isFramebufferDiscarded);
1022
1023 TRACE_EVENT0("cc", "CCRendererGL::swapBuffers");
1024 // We're done! Time to swapbuffers!
1025
1026 if (m_capabilities.usingPartialSwap) {
1027 // If supported, we can save significant bandwidth by only swapping the damaged/scissored region (clamped to the viewport)
1028 m_swapBufferRect.intersect(IntRect(IntPoint(), viewportSize()));
1029 int flippedYPosOfRectBottom = viewportHeight() - m_swapBufferRect.y() - m_swapBufferRect.height();
1030 m_context->postSubBufferCHROMIUM(m_swapBufferRect.x(), flippedYPosOfRectBottom, m_swapBufferRect.width(), m_swapBufferRect.height());
1031 } else {
1032 // Note that currently this has the same effect as swapBuffers; we should
1033 // consider exposing a different entry point on WebGraphicsContext3D.
1034 m_context->prepareTexture();
1035 }
1036
1037 m_swapBufferRect = IntRect();
1038
1039 return true;
1040}
1041
1042void CCRendererGL::onSwapBuffersComplete()
1043{
1044 m_client->onSwapBuffersComplete();
1045}
1046
1047void CCRendererGL::onMemoryAllocationChanged(WebGraphicsMemoryAllocation allocation)
1048{
1049 // FIXME: This is called on the main thread in single threaded mode, but we expect it on the impl thread.
1050 if (!CCProxy::hasImplThread()) {
1051 ASSERT(CCProxy::isMainThread());
1052 DebugScopedSetImplThread impl;
1053 onMemoryAllocationChangedOnImplThread(allocation);
1054 } else {
1055 ASSERT(CCProxy::isImplThread());
1056 onMemoryAllocationChangedOnImplThread(allocation);
1057 }
1058}
1059
1060void CCRendererGL::onMemoryAllocationChangedOnImplThread(WebKit::WebGraphicsMemoryAllocation allocation)
1061{
1062 if (m_visible && !allocation.gpuResourceSizeInBytes)
1063 return;
1064
1065 if (!allocation.suggestHaveBackbuffer && !m_visible)
1066 discardFramebuffer();
1067
1068 if (!allocation.gpuResourceSizeInBytes) {
1069 releaseRenderPassTextures();
1070 m_client->releaseContentsTextures();
1071 GLC(m_context, m_context->flush());
1072 } else
1073 m_client->setMemoryAllocationLimitBytes(allocation.gpuResourceSizeInBytes);
1074}
1075
1076void CCRendererGL::discardFramebuffer()
1077{
1078 if (m_isFramebufferDiscarded)
1079 return;
1080
1081 if (!m_capabilities.usingDiscardFramebuffer)
1082 return;
1083
1084 // FIXME: Update attachments argument to appropriate values once they are no longer ignored.
1085 m_context->discardFramebufferEXT(GraphicsContext3D::TEXTURE_2D, 0, 0);
1086 m_isFramebufferDiscarded = true;
1087
1088 // Damage tracker needs a full reset every time framebuffer is discarded.
1089 m_client->setFullRootLayerDamage();
1090}
1091
1092void CCRendererGL::ensureFramebuffer()
1093{
1094 if (!m_isFramebufferDiscarded)
1095 return;
1096
1097 if (!m_capabilities.usingDiscardFramebuffer)
1098 return;
1099
1100 m_context->ensureFramebufferCHROMIUM();
1101 m_isFramebufferDiscarded = false;
1102}
1103
1104void CCRendererGL::onContextLost()
1105{
1106 m_client->didLoseContext();
1107}
1108
1109
1110void CCRendererGL::getFramebufferPixels(void *pixels, const IntRect& rect)
1111{
1112 ASSERT(rect.maxX() <= viewportWidth() && rect.maxY() <= viewportHeight());
1113
1114 if (!pixels)
1115 return;
1116
1117 makeContextCurrent();
1118
1119 bool doWorkaround = needsIOSurfaceReadbackWorkaround();
1120
1121 Platform3DObject temporaryTexture = 0;
1122 Platform3DObject temporaryFBO = 0;
1123
1124 if (doWorkaround) {
1125 // On Mac OS X, calling glReadPixels against an FBO whose color attachment is an
1126 // IOSurface-backed texture causes corruption of future glReadPixels calls, even those on
1127 // different OpenGL contexts. It is believed that this is the root cause of top crasher
1128 // http://crbug.com/99393. <rdar://problem/10949687>
1129
1130 temporaryTexture = m_context->createTexture();
1131 GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, temporaryTexture));
1132 GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
1133 GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
1134 GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
1135 GLC(m_context, m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
1136 // Copy the contents of the current (IOSurface-backed) framebuffer into a temporary texture.
[email protected]387e5432012-09-12 07:40:591137 GLC(m_context, m_context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 0, 0, viewportSize().width(), viewportSize().height(), 0));
[email protected]94f206c12012-08-25 00:09:141138 temporaryFBO = m_context->createFramebuffer();
1139 // Attach this texture to an FBO, and perform the readback from that FBO.
1140 GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, temporaryFBO));
1141 GLC(m_context, m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, temporaryTexture, 0));
1142
1143 ASSERT(m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) == GraphicsContext3D::FRAMEBUFFER_COMPLETE);
1144 }
1145
[email protected]702f703272012-09-15 02:57:291146 OwnArrayPtr<uint8_t> srcPixels = adoptArrayPtr(new uint8_t[rect.width() * rect.height() * 4]);
[email protected]387e5432012-09-12 07:40:591147 GLC(m_context, m_context->readPixels(rect.x(), viewportSize().height() - rect.maxY(), rect.width(), rect.height(),
1148 GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, srcPixels.get()));
1149
1150 uint8_t* destPixels = static_cast<uint8_t*>(pixels);
1151 size_t rowBytes = rect.width() * 4;
1152 int numRows = rect.height();
1153 size_t totalBytes = numRows * rowBytes;
1154 for (size_t destY = 0; destY < totalBytes; destY += rowBytes) {
1155 // Flip Y axis.
1156 size_t srcY = totalBytes - destY - rowBytes;
1157 // Swizzle BGRA -> RGBA.
1158 for (size_t x = 0; x < rowBytes; x += 4) {
1159 destPixels[destY + (x+0)] = srcPixels.get()[srcY + (x+2)];
1160 destPixels[destY + (x+1)] = srcPixels.get()[srcY + (x+1)];
1161 destPixels[destY + (x+2)] = srcPixels.get()[srcY + (x+0)];
1162 destPixels[destY + (x+3)] = srcPixels.get()[srcY + (x+3)];
1163 }
1164 }
[email protected]94f206c12012-08-25 00:09:141165
1166 if (doWorkaround) {
1167 // Clean up.
1168 GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
1169 GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0));
1170 GLC(m_context, m_context->deleteFramebuffer(temporaryFBO));
1171 GLC(m_context, m_context->deleteTexture(temporaryTexture));
1172 }
1173
1174 if (!m_visible) {
1175 TRACE_EVENT0("cc", "CCRendererGL::getFramebufferPixels dropping resources after readback");
1176 discardFramebuffer();
1177 releaseRenderPassTextures();
1178 m_client->releaseContentsTextures();
1179 GLC(m_context, m_context->flush());
1180 }
1181}
1182
1183bool CCRendererGL::getFramebufferTexture(CCScopedTexture* texture, const IntRect& deviceRect)
1184{
1185 ASSERT(!texture->id() || (texture->size() == deviceRect.size() && texture->format() == GraphicsContext3D::RGB));
1186
1187 if (!texture->id() && !texture->allocate(CCRenderer::ImplPool, deviceRect.size(), GraphicsContext3D::RGB, CCResourceProvider::TextureUsageAny))
1188 return false;
1189
1190 CCResourceProvider::ScopedWriteLockGL lock(m_resourceProvider, texture->id());
1191 GLC(m_context, m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, lock.textureId()));
1192 GLC(m_context, m_context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, texture->format(),
1193 deviceRect.x(), deviceRect.y(), deviceRect.width(), deviceRect.height(), 0));
1194 return true;
1195}
1196
1197bool CCRendererGL::useScopedTexture(DrawingFrame& frame, const CCScopedTexture* texture, const IntRect& viewportRect)
1198{
1199 ASSERT(texture->id());
1200 frame.currentRenderPass = 0;
1201 frame.currentTexture = texture;
1202
1203 return bindFramebufferToTexture(frame, texture, viewportRect);
1204}
1205
1206void CCRendererGL::bindFramebufferToOutputSurface(DrawingFrame& frame)
1207{
1208 m_currentFramebufferLock.clear();
1209 GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
1210}
1211
1212bool CCRendererGL::bindFramebufferToTexture(DrawingFrame& frame, const CCScopedTexture* texture, const IntRect& framebufferRect)
1213{
1214 ASSERT(texture->id());
1215
1216 GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId));
1217 m_currentFramebufferLock = adoptPtr(new CCResourceProvider::ScopedWriteLockGL(m_resourceProvider, texture->id()));
1218 unsigned textureId = m_currentFramebufferLock->textureId();
1219 GLC(m_context, m_context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, textureId, 0));
1220
1221#if !defined ( NDEBUG )
1222 if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
1223 ASSERT_NOT_REACHED();
1224 return false;
1225 }
1226#endif
1227
1228 initializeMatrices(frame, framebufferRect, false);
1229 setDrawViewportSize(framebufferRect.size());
1230
1231 return true;
1232}
1233
1234void CCRendererGL::enableScissorTestRect(const IntRect& scissorRect)
1235{
1236 GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST));
1237 GLC(m_context, m_context->scissor(scissorRect.x(), scissorRect.y(), scissorRect.width(), scissorRect.height()));
1238}
1239
1240void CCRendererGL::disableScissorTest()
1241{
1242 GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
1243}
1244
1245void CCRendererGL::setDrawViewportSize(const IntSize& viewportSize)
1246{
1247 GLC(m_context, m_context->viewport(0, 0, viewportSize.width(), viewportSize.height()));
1248}
1249
1250bool CCRendererGL::makeContextCurrent()
1251{
1252 return m_context->makeContextCurrent();
1253}
1254
1255bool CCRendererGL::initializeSharedObjects()
1256{
1257 TRACE_EVENT0("cc", "CCRendererGL::initializeSharedObjects");
1258 makeContextCurrent();
1259
1260 // Create an FBO for doing offscreen rendering.
1261 GLC(m_context, m_offscreenFramebufferId = m_context->createFramebuffer());
1262
1263 // We will always need these programs to render, so create the programs eagerly so that the shader compilation can
1264 // start while we do other work. Other programs are created lazily on first access.
1265 m_sharedGeometry = adoptPtr(new GeometryBinding(m_context, quadVertexRect()));
1266 m_renderPassProgram = adoptPtr(new RenderPassProgram(m_context));
1267 m_tileProgram = adoptPtr(new TileProgram(m_context));
1268 m_tileProgramOpaque = adoptPtr(new TileProgramOpaque(m_context));
1269
1270 GLC(m_context, m_context->flush());
1271
[email protected]94f206c12012-08-25 00:09:141272 return true;
1273}
1274
1275const CCRendererGL::TileCheckerboardProgram* CCRendererGL::tileCheckerboardProgram()
1276{
1277 if (!m_tileCheckerboardProgram)
1278 m_tileCheckerboardProgram = adoptPtr(new TileCheckerboardProgram(m_context));
1279 if (!m_tileCheckerboardProgram->initialized()) {
1280 TRACE_EVENT0("cc", "CCRendererGL::checkerboardProgram::initalize");
1281 m_tileCheckerboardProgram->initialize(m_context, m_isUsingBindUniform);
1282 }
1283 return m_tileCheckerboardProgram.get();
1284}
1285
1286const CCRendererGL::SolidColorProgram* CCRendererGL::solidColorProgram()
1287{
1288 if (!m_solidColorProgram)
1289 m_solidColorProgram = adoptPtr(new SolidColorProgram(m_context));
1290 if (!m_solidColorProgram->initialized()) {
1291 TRACE_EVENT0("cc", "CCRendererGL::solidColorProgram::initialize");
1292 m_solidColorProgram->initialize(m_context, m_isUsingBindUniform);
1293 }
1294 return m_solidColorProgram.get();
1295}
1296
1297const CCRendererGL::RenderPassProgram* CCRendererGL::renderPassProgram()
1298{
1299 ASSERT(m_renderPassProgram);
1300 if (!m_renderPassProgram->initialized()) {
1301 TRACE_EVENT0("cc", "CCRendererGL::renderPassProgram::initialize");
1302 m_renderPassProgram->initialize(m_context, m_isUsingBindUniform);
1303 }
1304 return m_renderPassProgram.get();
1305}
1306
1307const CCRendererGL::RenderPassProgramAA* CCRendererGL::renderPassProgramAA()
1308{
1309 if (!m_renderPassProgramAA)
1310 m_renderPassProgramAA = adoptPtr(new RenderPassProgramAA(m_context));
1311 if (!m_renderPassProgramAA->initialized()) {
1312 TRACE_EVENT0("cc", "CCRendererGL::renderPassProgramAA::initialize");
1313 m_renderPassProgramAA->initialize(m_context, m_isUsingBindUniform);
1314 }
1315 return m_renderPassProgramAA.get();
1316}
1317
1318const CCRendererGL::RenderPassMaskProgram* CCRendererGL::renderPassMaskProgram()
1319{
1320 if (!m_renderPassMaskProgram)
1321 m_renderPassMaskProgram = adoptPtr(new RenderPassMaskProgram(m_context));
1322 if (!m_renderPassMaskProgram->initialized()) {
1323 TRACE_EVENT0("cc", "CCRendererGL::renderPassMaskProgram::initialize");
1324 m_renderPassMaskProgram->initialize(m_context, m_isUsingBindUniform);
1325 }
1326 return m_renderPassMaskProgram.get();
1327}
1328
1329const CCRendererGL::RenderPassMaskProgramAA* CCRendererGL::renderPassMaskProgramAA()
1330{
1331 if (!m_renderPassMaskProgramAA)
1332 m_renderPassMaskProgramAA = adoptPtr(new RenderPassMaskProgramAA(m_context));
1333 if (!m_renderPassMaskProgramAA->initialized()) {
1334 TRACE_EVENT0("cc", "CCRendererGL::renderPassMaskProgramAA::initialize");
1335 m_renderPassMaskProgramAA->initialize(m_context, m_isUsingBindUniform);
1336 }
1337 return m_renderPassMaskProgramAA.get();
1338}
1339
1340const CCRendererGL::TileProgram* CCRendererGL::tileProgram()
1341{
1342 ASSERT(m_tileProgram);
1343 if (!m_tileProgram->initialized()) {
1344 TRACE_EVENT0("cc", "CCRendererGL::tileProgram::initialize");
1345 m_tileProgram->initialize(m_context, m_isUsingBindUniform);
1346 }
1347 return m_tileProgram.get();
1348}
1349
1350const CCRendererGL::TileProgramOpaque* CCRendererGL::tileProgramOpaque()
1351{
1352 ASSERT(m_tileProgramOpaque);
1353 if (!m_tileProgramOpaque->initialized()) {
1354 TRACE_EVENT0("cc", "CCRendererGL::tileProgramOpaque::initialize");
1355 m_tileProgramOpaque->initialize(m_context, m_isUsingBindUniform);
1356 }
1357 return m_tileProgramOpaque.get();
1358}
1359
1360const CCRendererGL::TileProgramAA* CCRendererGL::tileProgramAA()
1361{
1362 if (!m_tileProgramAA)
1363 m_tileProgramAA = adoptPtr(new TileProgramAA(m_context));
1364 if (!m_tileProgramAA->initialized()) {
1365 TRACE_EVENT0("cc", "CCRendererGL::tileProgramAA::initialize");
1366 m_tileProgramAA->initialize(m_context, m_isUsingBindUniform);
1367 }
1368 return m_tileProgramAA.get();
1369}
1370
1371const CCRendererGL::TileProgramSwizzle* CCRendererGL::tileProgramSwizzle()
1372{
1373 if (!m_tileProgramSwizzle)
1374 m_tileProgramSwizzle = adoptPtr(new TileProgramSwizzle(m_context));
1375 if (!m_tileProgramSwizzle->initialized()) {
1376 TRACE_EVENT0("cc", "CCRendererGL::tileProgramSwizzle::initialize");
1377 m_tileProgramSwizzle->initialize(m_context, m_isUsingBindUniform);
1378 }
1379 return m_tileProgramSwizzle.get();
1380}
1381
1382const CCRendererGL::TileProgramSwizzleOpaque* CCRendererGL::tileProgramSwizzleOpaque()
1383{
1384 if (!m_tileProgramSwizzleOpaque)
1385 m_tileProgramSwizzleOpaque = adoptPtr(new TileProgramSwizzleOpaque(m_context));
1386 if (!m_tileProgramSwizzleOpaque->initialized()) {
1387 TRACE_EVENT0("cc", "CCRendererGL::tileProgramSwizzleOpaque::initialize");
1388 m_tileProgramSwizzleOpaque->initialize(m_context, m_isUsingBindUniform);
1389 }
1390 return m_tileProgramSwizzleOpaque.get();
1391}
1392
1393const CCRendererGL::TileProgramSwizzleAA* CCRendererGL::tileProgramSwizzleAA()
1394{
1395 if (!m_tileProgramSwizzleAA)
1396 m_tileProgramSwizzleAA = adoptPtr(new TileProgramSwizzleAA(m_context));
1397 if (!m_tileProgramSwizzleAA->initialized()) {
1398 TRACE_EVENT0("cc", "CCRendererGL::tileProgramSwizzleAA::initialize");
1399 m_tileProgramSwizzleAA->initialize(m_context, m_isUsingBindUniform);
1400 }
1401 return m_tileProgramSwizzleAA.get();
1402}
1403
1404const CCRendererGL::TextureProgram* CCRendererGL::textureProgram()
1405{
1406 if (!m_textureProgram)
1407 m_textureProgram = adoptPtr(new TextureProgram(m_context));
1408 if (!m_textureProgram->initialized()) {
1409 TRACE_EVENT0("cc", "CCRendererGL::textureProgram::initialize");
1410 m_textureProgram->initialize(m_context, m_isUsingBindUniform);
1411 }
1412 return m_textureProgram.get();
1413}
1414
1415const CCRendererGL::TextureProgramFlip* CCRendererGL::textureProgramFlip()
1416{
1417 if (!m_textureProgramFlip)
1418 m_textureProgramFlip = adoptPtr(new TextureProgramFlip(m_context));
1419 if (!m_textureProgramFlip->initialized()) {
1420 TRACE_EVENT0("cc", "CCRendererGL::textureProgramFlip::initialize");
1421 m_textureProgramFlip->initialize(m_context, m_isUsingBindUniform);
1422 }
1423 return m_textureProgramFlip.get();
1424}
1425
1426const CCRendererGL::TextureIOSurfaceProgram* CCRendererGL::textureIOSurfaceProgram()
1427{
1428 if (!m_textureIOSurfaceProgram)
1429 m_textureIOSurfaceProgram = adoptPtr(new TextureIOSurfaceProgram(m_context));
1430 if (!m_textureIOSurfaceProgram->initialized()) {
1431 TRACE_EVENT0("cc", "CCRendererGL::textureIOSurfaceProgram::initialize");
1432 m_textureIOSurfaceProgram->initialize(m_context, m_isUsingBindUniform);
1433 }
1434 return m_textureIOSurfaceProgram.get();
1435}
1436
1437const CCRendererGL::VideoYUVProgram* CCRendererGL::videoYUVProgram()
1438{
1439 if (!m_videoYUVProgram)
1440 m_videoYUVProgram = adoptPtr(new VideoYUVProgram(m_context));
1441 if (!m_videoYUVProgram->initialized()) {
1442 TRACE_EVENT0("cc", "CCRendererGL::videoYUVProgram::initialize");
1443 m_videoYUVProgram->initialize(m_context, m_isUsingBindUniform);
1444 }
1445 return m_videoYUVProgram.get();
1446}
1447
1448const CCRendererGL::VideoStreamTextureProgram* CCRendererGL::videoStreamTextureProgram()
1449{
1450 if (!m_videoStreamTextureProgram)
1451 m_videoStreamTextureProgram = adoptPtr(new VideoStreamTextureProgram(m_context));
1452 if (!m_videoStreamTextureProgram->initialized()) {
1453 TRACE_EVENT0("cc", "CCRendererGL::streamTextureProgram::initialize");
1454 m_videoStreamTextureProgram->initialize(m_context, m_isUsingBindUniform);
1455 }
1456 return m_videoStreamTextureProgram.get();
1457}
1458
1459void CCRendererGL::cleanupSharedObjects()
1460{
1461 makeContextCurrent();
1462
1463 m_sharedGeometry.clear();
1464
1465 if (m_tileProgram)
1466 m_tileProgram->cleanup(m_context);
1467 if (m_tileProgramOpaque)
1468 m_tileProgramOpaque->cleanup(m_context);
1469 if (m_tileProgramSwizzle)
1470 m_tileProgramSwizzle->cleanup(m_context);
1471 if (m_tileProgramSwizzleOpaque)
1472 m_tileProgramSwizzleOpaque->cleanup(m_context);
1473 if (m_tileProgramAA)
1474 m_tileProgramAA->cleanup(m_context);
1475 if (m_tileProgramSwizzleAA)
1476 m_tileProgramSwizzleAA->cleanup(m_context);
1477 if (m_tileCheckerboardProgram)
1478 m_tileCheckerboardProgram->cleanup(m_context);
1479
1480 if (m_renderPassMaskProgram)
1481 m_renderPassMaskProgram->cleanup(m_context);
1482 if (m_renderPassProgram)
1483 m_renderPassProgram->cleanup(m_context);
1484 if (m_renderPassMaskProgramAA)
1485 m_renderPassMaskProgramAA->cleanup(m_context);
1486 if (m_renderPassProgramAA)
1487 m_renderPassProgramAA->cleanup(m_context);
1488
1489 if (m_textureProgram)
1490 m_textureProgram->cleanup(m_context);
1491 if (m_textureProgramFlip)
1492 m_textureProgramFlip->cleanup(m_context);
1493 if (m_textureIOSurfaceProgram)
1494 m_textureIOSurfaceProgram->cleanup(m_context);
1495
1496 if (m_videoYUVProgram)
1497 m_videoYUVProgram->cleanup(m_context);
1498 if (m_videoStreamTextureProgram)
1499 m_videoStreamTextureProgram->cleanup(m_context);
1500
1501 if (m_solidColorProgram)
1502 m_solidColorProgram->cleanup(m_context);
1503
1504 if (m_offscreenFramebufferId)
1505 GLC(m_context, m_context->deleteFramebuffer(m_offscreenFramebufferId));
1506
[email protected]94f206c12012-08-25 00:09:141507 releaseRenderPassTextures();
1508}
1509
1510bool CCRendererGL::isContextLost()
1511{
1512 return (m_context->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR);
1513}
1514
[email protected]9c88e562012-09-14 22:21:301515} // namespace cc
[email protected]94f206c12012-08-25 00:09:141516
1517#endif // USE(ACCELERATED_COMPOSITING)