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