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