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