[chromium] Add TextureCopier for copying texture contents
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / LayerRendererChromium.cpp
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31
32 #include "config.h"
33
34 #if USE(ACCELERATED_COMPOSITING)
35 #include "LayerRendererChromium.h"
36
37 #include "Extensions3DChromium.h"
38 #include "FloatQuad.h"
39 #include "GeometryBinding.h"
40 #include "GraphicsContext3D.h"
41 #include "LayerChromium.h"
42 #include "LayerPainterChromium.h"
43 #include "ManagedTexture.h"
44 #include "NotImplemented.h"
45 #include "PlatformColor.h"
46 #include "RenderSurfaceChromium.h"
47 #include "TextStream.h"
48 #include "TextureCopier.h"
49 #include "TextureManager.h"
50 #include "TraceEvent.h"
51 #include "TrackingTextureAllocator.h"
52 #include "TreeSynchronizer.h"
53 #include "WebGLLayerChromium.h"
54 #include "cc/CCDamageTracker.h"
55 #include "cc/CCDebugBorderDrawQuad.h"
56 #include "cc/CCLayerImpl.h"
57 #include "cc/CCLayerTreeHostCommon.h"
58 #include "cc/CCProxy.h"
59 #include "cc/CCRenderPass.h"
60 #include "cc/CCRenderSurfaceDrawQuad.h"
61 #include "cc/CCSolidColorDrawQuad.h"
62 #include "cc/CCTextureDrawQuad.h"
63 #include "cc/CCTileDrawQuad.h"
64 #include "cc/CCVideoDrawQuad.h"
65 #include "Extensions3D.h"
66 #include "NativeImageSkia.h"
67 #include "PlatformContextSkia.h"
68 #include <wtf/CurrentTime.h>
69 #include <wtf/MainThread.h>
70
71 using namespace std;
72
73 namespace WebCore {
74
75 namespace {
76
77 static TransformationMatrix orthoMatrix(float left, float right, float bottom, float top)
78 {
79     float deltaX = right - left;
80     float deltaY = top - bottom;
81     TransformationMatrix ortho;
82     if (!deltaX || !deltaY)
83         return ortho;
84     ortho.setM11(2.0f / deltaX);
85     ortho.setM41(-(right + left) / deltaX);
86     ortho.setM22(2.0f / deltaY);
87     ortho.setM42(-(top + bottom) / deltaY);
88
89     // Z component of vertices is always set to zero as we don't use the depth buffer
90     // while drawing.
91     ortho.setM33(0);
92
93     return ortho;
94 }
95
96 static TransformationMatrix screenMatrix(int x, int y, int width, int height)
97 {
98     TransformationMatrix screen;
99
100     // Map to viewport.
101     screen.translate3d(x, y, 0);
102     screen.scale3d(width, height, 0);
103
104     // Map x, y and z to unit square.
105     screen.translate3d(0.5, 0.5, 0.5);
106     screen.scale3d(0.5, 0.5, 0.5);
107
108     return screen;
109 }
110
111 bool contextSupportsAcceleratedPainting(GraphicsContext3D* context)
112 {
113     WebCore::Extensions3D* extensions = context->getExtensions();
114     if (extensions->supports("GL_EXT_texture_format_BGRA8888"))
115         extensions->ensureEnabled("GL_EXT_texture_format_BGRA8888");
116     else
117         return false;
118
119     if (extensions->supports("GL_EXT_read_format_bgra"))
120         extensions->ensureEnabled("GL_EXT_read_format_bgra");
121     else
122         return false;
123
124     if (!context->grContext())
125         return false;
126
127     return true;
128 }
129
130 bool needsLionIOSurfaceReadbackWorkaround()
131 {
132 #if OS(DARWIN)
133     static SInt32 systemVersion = 0;
134     if (!systemVersion) {
135         if (Gestalt(gestaltSystemVersion, &systemVersion) != noErr)
136             return false;
137     }
138
139     return systemVersion >= 0x1070;
140 #else
141     return false;
142 #endif
143 }
144
145 } // anonymous namespace
146
147 class LayerRendererSwapBuffersCompleteCallbackAdapter : public Extensions3DChromium::SwapBuffersCompleteCallbackCHROMIUM {
148 public:
149     static PassOwnPtr<LayerRendererSwapBuffersCompleteCallbackAdapter> create(LayerRendererChromium* layerRenderer)
150     {
151         return adoptPtr(new LayerRendererSwapBuffersCompleteCallbackAdapter(layerRenderer));
152     }
153     virtual ~LayerRendererSwapBuffersCompleteCallbackAdapter() { }
154
155     virtual void onSwapBuffersComplete()
156     {
157         m_layerRenderer->onSwapBuffersComplete();
158     }
159
160 private:
161     explicit LayerRendererSwapBuffersCompleteCallbackAdapter(LayerRendererChromium* layerRenderer)
162     {
163         m_layerRenderer = layerRenderer;
164     }
165
166     LayerRendererChromium* m_layerRenderer;
167 };
168
169 class LayerRendererGpuMemoryAllocationChangedCallbackAdapter : public Extensions3DChromium::GpuMemoryAllocationChangedCallbackCHROMIUM {
170 public:
171     static PassOwnPtr<LayerRendererGpuMemoryAllocationChangedCallbackAdapter> create(LayerRendererChromium* layerRenderer)
172     {
173         return adoptPtr(new LayerRendererGpuMemoryAllocationChangedCallbackAdapter(layerRenderer));
174     }
175     virtual ~LayerRendererGpuMemoryAllocationChangedCallbackAdapter() { }
176
177     virtual void onGpuMemoryAllocationChanged(Extensions3DChromium::GpuMemoryAllocationCHROMIUM allocation)
178     {
179         if (!allocation.suggestHaveBackbuffer)
180             m_layerRenderer->discardFramebuffer();
181         else
182             m_layerRenderer->ensureFramebuffer();
183     }
184
185 private:
186     explicit LayerRendererGpuMemoryAllocationChangedCallbackAdapter(LayerRendererChromium* layerRenderer)
187         : m_layerRenderer(layerRenderer)
188     {
189     }
190
191     LayerRendererChromium* m_layerRenderer;
192 };
193
194
195 PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create(LayerRendererChromiumClient* client, PassRefPtr<GraphicsContext3D> context)
196 {
197     OwnPtr<LayerRendererChromium> layerRenderer(adoptPtr(new LayerRendererChromium(client, context)));
198     if (!layerRenderer->initialize())
199         return nullptr;
200
201     return layerRenderer.release();
202 }
203
204 LayerRendererChromium::LayerRendererChromium(LayerRendererChromiumClient* client,
205                                              PassRefPtr<GraphicsContext3D> context)
206     : m_client(client)
207     , m_currentRenderSurface(0)
208     , m_offscreenFramebufferId(0)
209     , m_context(context)
210     , m_defaultRenderSurface(0)
211     , m_sharedGeometryQuad(FloatRect(-0.5f, -0.5f, 1.0f, 1.0f))
212     , m_isViewportChanged(false)
213     , m_isFramebufferDiscarded(false)
214 {
215 }
216
217 class ContextLostCallbackAdapter : public GraphicsContext3D::ContextLostCallback {
218 public:
219     static PassOwnPtr<ContextLostCallbackAdapter> create(LayerRendererChromiumClient* client)
220     {
221         return adoptPtr(new ContextLostCallbackAdapter(client));
222     }
223
224     virtual void onContextLost()
225     {
226         m_client->didLoseContext();
227     }
228
229 private:
230     explicit ContextLostCallbackAdapter(LayerRendererChromiumClient* client)
231         : m_client(client) { }
232
233     LayerRendererChromiumClient* m_client;
234 };
235
236 bool LayerRendererChromium::initialize()
237 {
238     if (!m_context->makeContextCurrent())
239         return false;
240
241     m_context->setContextLostCallback(ContextLostCallbackAdapter::create(m_client));
242
243     if (settings().acceleratePainting && contextSupportsAcceleratedPainting(m_context.get()))
244         m_capabilities.usingAcceleratedPainting = true;
245
246     WebCore::Extensions3D* extensions = m_context->getExtensions();
247     m_capabilities.contextHasCachedFrontBuffer = extensions->supports("GL_CHROMIUM_front_buffer_cached");
248     if (m_capabilities.contextHasCachedFrontBuffer)
249         extensions->ensureEnabled("GL_CHROMIUM_front_buffer_cached");
250
251     m_capabilities.usingPartialSwap = settings().partialSwapEnabled && extensions->supports("GL_CHROMIUM_post_sub_buffer");
252     if (m_capabilities.usingPartialSwap)
253         extensions->ensureEnabled("GL_CHROMIUM_post_sub_buffer");
254
255     m_capabilities.usingMapSub = extensions->supports("GL_CHROMIUM_map_sub");
256     if (m_capabilities.usingMapSub)
257         extensions->ensureEnabled("GL_CHROMIUM_map_sub");
258
259     // Use the swapBuffers callback only with the threaded proxy.
260     if (CCProxy::hasImplThread())
261         m_capabilities.usingSwapCompleteCallback = extensions->supports("GL_CHROMIUM_swapbuffers_complete_callback");
262     if (m_capabilities.usingSwapCompleteCallback) {
263         extensions->ensureEnabled("GL_CHROMIUM_swapbuffers_complete_callback");
264         Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
265         extensions3DChromium->setSwapBuffersCompleteCallbackCHROMIUM(LayerRendererSwapBuffersCompleteCallbackAdapter::create(this));
266     }
267
268     if (extensions->supports("GL_EXT_texture_format_BGRA8888"))
269         extensions->ensureEnabled("GL_EXT_texture_format_BGRA8888");
270
271     m_capabilities.usingSetVisibility = extensions->supports("GL_CHROMIUM_set_visibility");
272     if (m_capabilities.usingSetVisibility)
273         extensions->ensureEnabled("GL_CHROMIUM_set_visibility");
274
275     if (extensions->supports("GL_CHROMIUM_iosurface")) {
276         ASSERT(extensions->supports("GL_ARB_texture_rectangle"));
277         extensions->ensureEnabled("GL_ARB_texture_rectangle");
278         extensions->ensureEnabled("GL_CHROMIUM_iosurface");
279     }
280
281     m_capabilities.usingTextureUsageHint = extensions->supports("GL_ANGLE_texture_usage");
282     if (m_capabilities.usingTextureUsageHint)
283         extensions->ensureEnabled("GL_ANGLE_texture_usage");
284
285     m_capabilities.usingTextureStorageExtension = extensions->supports("GL_EXT_texture_storage");
286     if (m_capabilities.usingTextureStorageExtension)
287         extensions->ensureEnabled("GL_EXT_texture_storage");
288
289     m_capabilities.usingGpuMemoryManager = extensions->supports("GL_CHROMIUM_gpu_memory_manager");
290     if (m_capabilities.usingGpuMemoryManager) {
291         extensions->ensureEnabled("GL_CHROMIUM_gpu_memory_manager");
292         Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
293         extensions3DChromium->setGpuMemoryAllocationChangedCallbackCHROMIUM(LayerRendererGpuMemoryAllocationChangedCallbackAdapter::create(this));
294     }
295
296     m_capabilities.usingDiscardFramebuffer = extensions->supports("GL_CHROMIUM_discard_framebuffer");
297     if (m_capabilities.usingDiscardFramebuffer)
298         extensions->ensureEnabled("GL_CHROMIUM_discard_framebuffer");
299
300     GLC(m_context.get(), m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_capabilities.maxTextureSize));
301     m_capabilities.bestTextureFormat = PlatformColor::bestTextureFormat(m_context.get());
302
303     if (!initializeSharedObjects())
304         return false;
305
306     m_headsUpDisplay = CCHeadsUpDisplay::create(this);
307
308     // Make sure the viewport and context gets initialized, even if it is to zero.
309     viewportChanged();
310     return true;
311 }
312
313 LayerRendererChromium::~LayerRendererChromium()
314 {
315     ASSERT(CCProxy::isImplThread());
316     Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(m_context->getExtensions());
317     extensions3DChromium->setSwapBuffersCompleteCallbackCHROMIUM(nullptr);
318     extensions3DChromium->setGpuMemoryAllocationChangedCallbackCHROMIUM(nullptr);
319     m_headsUpDisplay.clear(); // Explicitly destroy the HUD before the TextureManager dies.
320     cleanupSharedObjects();
321 }
322
323 void LayerRendererChromium::clearRenderSurfacesOnCCLayerImplRecursive(CCLayerImpl* layer)
324 {
325     for (size_t i = 0; i < layer->children().size(); ++i)
326         clearRenderSurfacesOnCCLayerImplRecursive(layer->children()[i].get());
327     layer->clearRenderSurface();
328 }
329
330 void LayerRendererChromium::close()
331 {
332     if (rootLayer())
333         clearRenderSurfacesOnCCLayerImplRecursive(rootLayer());
334 }
335
336 GraphicsContext3D* LayerRendererChromium::context()
337 {
338     return m_context.get();
339 }
340
341 void LayerRendererChromium::debugGLCall(GraphicsContext3D* context, const char* command, const char* file, int line)
342 {
343     unsigned long error = context->getError();
344     if (error != GraphicsContext3D::NO_ERROR)
345         LOG_ERROR("GL command failed: File: %s\n\tLine %d\n\tcommand: %s, error %x\n", file, line, command, static_cast<int>(error));
346 }
347
348 void LayerRendererChromium::setVisible(bool visible)
349 {
350     if (!visible)
351         releaseRenderSurfaceTextures();
352
353     // FIXME: Remove this once framebuffer is automatically recreated on first use
354     if (visible)
355         ensureFramebuffer();
356
357     // TODO: Replace setVisibilityCHROMIUM with an extension to explicitly manage front/backbuffers
358     // crbug.com/116049
359     if (m_capabilities.usingSetVisibility) {
360         Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(m_context->getExtensions());
361         extensions3DChromium->setVisibilityCHROMIUM(visible);
362     }
363 }
364
365 void LayerRendererChromium::releaseRenderSurfaceTextures()
366 {
367     if (m_renderSurfaceTextureManager)
368         m_renderSurfaceTextureManager->evictAndDeleteAllTextures(m_renderSurfaceTextureAllocator.get());
369 }
370
371 void LayerRendererChromium::viewportChanged()
372 {
373     m_isViewportChanged = true;
374
375     // Reset the current render surface to force an update of the viewport and
376     // projection matrix next time useRenderSurface is called.
377     m_currentRenderSurface = 0;
378 }
379
380 void LayerRendererChromium::clearRenderSurface(CCRenderSurface* renderSurface, CCRenderSurface* rootRenderSurface, const FloatRect& surfaceDamageRect)
381 {
382     // Non-root layers should clear their entire contents to transparent. On DEBUG builds, the root layer
383     // is cleared to blue to easily see regions that were not drawn on the screen. If we
384     // are using partial swap / scissor optimization, then the surface should only
385     // clear the damaged region, so that we don't accidentally clear un-changed portions
386     // of the screen.
387
388     if (renderSurface != rootRenderSurface)
389         GLC(m_context.get(), m_context->clearColor(0, 0, 0, 0));
390     else
391         GLC(m_context.get(), m_context->clearColor(0, 0, 1, 1));
392
393     if (m_capabilities.usingPartialSwap)
394         setScissorToRect(enclosingIntRect(surfaceDamageRect));
395     else
396         GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
397
398 #if defined(NDEBUG)
399     if (renderSurface != rootRenderSurface)
400 #endif
401         m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
402
403     GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
404 }
405
406 void LayerRendererChromium::beginDrawingFrame()
407 {
408     ASSERT(rootLayer());
409     m_defaultRenderSurface = rootLayer()->renderSurface();
410
411     // FIXME: use the frame begin time from the overall compositor scheduler.
412     // This value is currently inaccessible because it is up in Chromium's
413     // RenderWidget.
414     m_headsUpDisplay->onFrameBegin(currentTime());
415
416     size_t contentsMemoryUseBytes = m_contentsTextureAllocator->currentMemoryUseBytes();
417     size_t maxLimit = TextureManager::highLimitBytes(viewportSize());
418     m_renderSurfaceTextureManager->setMaxMemoryLimitBytes(maxLimit - contentsMemoryUseBytes);
419
420     if (viewportSize().isEmpty() || !rootLayer())
421         return;
422
423     TRACE_EVENT("LayerRendererChromium::drawLayers", this, 0);
424     if (m_isViewportChanged) {
425         // Only reshape when we know we are going to draw. Otherwise, the reshape
426         // can leave the window at the wrong size if we never draw and the proper
427         // viewport size is never set.
428         m_isViewportChanged = false;
429         m_context->reshape(viewportWidth(), viewportHeight());
430     }
431
432     makeContextCurrent();
433     // Bind the common vertex attributes used for drawing all the layers.
434     m_sharedGeometry->prepareForDraw();
435
436     GLC(m_context.get(), m_context->disable(GraphicsContext3D::DEPTH_TEST));
437     GLC(m_context.get(), m_context->disable(GraphicsContext3D::CULL_FACE));
438     GLC(m_context.get(), m_context->colorMask(true, true, true, true));
439     GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND));
440     GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
441 }
442
443 void LayerRendererChromium::drawRenderPass(const CCRenderPass* renderPass)
444 {
445     CCRenderSurface* renderSurface = renderPass->targetSurface();
446     if (!useRenderSurface(renderSurface))
447         return;
448
449     clearRenderSurface(renderSurface, m_defaultRenderSurface, renderPass->surfaceDamageRect());
450
451     const CCQuadList& quadList = renderPass->quadList();
452     for (CCQuadList::constBackToFrontIterator it = quadList.backToFrontBegin(); it != quadList.backToFrontEnd(); ++it)
453         drawQuad(it->get(), renderPass->surfaceDamageRect());
454 }
455
456 void LayerRendererChromium::drawQuad(const CCDrawQuad* quad, const FloatRect& surfaceDamageRect)
457 {
458     IntRect scissorRect;
459     if (m_capabilities.usingPartialSwap) {
460         FloatRect clipAndDamageRect = surfaceDamageRect;
461         if (!quad->clipRect().isEmpty())
462             clipAndDamageRect.intersect(quad->clipRect());
463         scissorRect = enclosingIntRect(clipAndDamageRect);
464         if (scissorRect.isEmpty())
465             return;
466     } else
467         scissorRect = quad->clipRect();
468
469     if (scissorRect.isEmpty())
470         GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
471     else
472         setScissorToRect(scissorRect);
473
474     if (quad->needsBlending())
475         GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND));
476     else
477         GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND));
478
479     switch (quad->material()) {
480     case CCDrawQuad::Invalid:
481         ASSERT_NOT_REACHED();
482         break;
483     case CCDrawQuad::DebugBorder:
484         drawDebugBorderQuad(quad->toDebugBorderDrawQuad());
485         break;
486     case CCDrawQuad::RenderSurface:
487         drawRenderSurfaceQuad(quad->toRenderSurfaceDrawQuad());
488         break;
489     case CCDrawQuad::SolidColor:
490         drawSolidColorQuad(quad->toSolidColorDrawQuad());
491         break;
492     case CCDrawQuad::TextureContent:
493         drawTextureQuad(quad->toTextureDrawQuad());
494         break;
495     case CCDrawQuad::TiledContent:
496         drawTileQuad(quad->toTileDrawQuad());
497         break;
498     case CCDrawQuad::VideoContent:
499         drawVideoQuad(quad->toVideoDrawQuad());
500         break;
501     }
502 }
503
504 void LayerRendererChromium::drawDebugBorderQuad(const CCDebugBorderDrawQuad* quad)
505 {
506     static float glMatrix[16];
507     const LayerChromium::BorderProgram* program = borderProgram();
508     ASSERT(program && program->initialized());
509     GLC(context(), context()->useProgram(program->program()));
510
511     const IntRect& layerRect = quad->quadRect();
512     TransformationMatrix renderMatrix = quad->quadTransform();
513     renderMatrix.translate(0.5 * layerRect.width() + layerRect.x(), 0.5 * layerRect.height() + layerRect.y());
514     renderMatrix.scaleNonUniform(layerRect.width(), layerRect.height());
515     LayerRendererChromium::toGLMatrix(&glMatrix[0], projectionMatrix() * renderMatrix);
516     GLC(context(), context()->uniformMatrix4fv(program->vertexShader().matrixLocation(), 1, false, &glMatrix[0]));
517
518     GLC(context(), context()->uniform4f(program->fragmentShader().colorLocation(), quad->color().red() / 255.0, quad->color().green() / 255.0, quad->color().blue() / 255.0, quad->color().alpha() / 255.0));
519
520     GLC(context(), context()->lineWidth(quad->width()));
521
522     // The indices for the line are stored in the same array as the triangle indices.
523     GLC(context(), context()->drawElements(GraphicsContext3D::LINE_LOOP, 4, GraphicsContext3D::UNSIGNED_SHORT, 6 * sizeof(unsigned short)));
524 }
525
526 void LayerRendererChromium::drawRenderSurfaceQuad(const CCRenderSurfaceDrawQuad* quad)
527 {
528     CCLayerImpl* layer = quad->layer();
529     layer->renderSurface()->draw(this, quad->surfaceDamageRect());
530     layer->renderSurface()->releaseContentsTexture();
531 }
532
533 void LayerRendererChromium::drawSolidColorQuad(const CCSolidColorDrawQuad* quad)
534 {
535     const LayerChromium::BorderProgram* solidColorProgram = borderProgram();
536     GLC(context(), context()->useProgram(solidColorProgram->program()));
537
538     IntRect tileRect = quad->quadRect();
539
540     TransformationMatrix tileTransform = quad->quadTransform();
541     tileTransform.translate(tileRect.x() + tileRect.width() / 2.0, tileRect.y() + tileRect.height() / 2.0);
542
543     const Color& color = quad->color();
544
545     GLC(context(), context()->uniform4f(solidColorProgram->fragmentShader().colorLocation(), color.red() / 255.0, color.green() / 255.0, color.blue() / 255.0, color.alpha() / 255.0));
546
547     float opacity = quad->opacity();
548     drawTexturedQuad(tileTransform,
549                      tileRect.width(), tileRect.height(), opacity, FloatQuad(),
550                      solidColorProgram->vertexShader().matrixLocation(),
551                      -1, -1);
552 }
553
554 struct TileProgramUniforms {
555     unsigned program;
556     unsigned samplerLocation;
557     unsigned vertexTexTransformLocation;
558     unsigned fragmentTexTransformLocation;
559     unsigned edgeLocation;
560     unsigned matrixLocation;
561     unsigned alphaLocation;
562     unsigned pointLocation;
563 };
564
565 template<class T>
566 static void tileUniformLocation(T program, TileProgramUniforms& uniforms)
567 {
568     uniforms.program = program->program();
569     uniforms.vertexTexTransformLocation = program->vertexShader().vertexTexTransformLocation();
570     uniforms.matrixLocation = program->vertexShader().matrixLocation();
571     uniforms.pointLocation = program->vertexShader().pointLocation();
572
573     uniforms.samplerLocation = program->fragmentShader().samplerLocation();
574     uniforms.alphaLocation = program->fragmentShader().alphaLocation();
575     uniforms.fragmentTexTransformLocation = program->fragmentShader().fragmentTexTransformLocation();
576     uniforms.edgeLocation = program->fragmentShader().edgeLocation();
577 }
578
579 static void findTileProgramUniforms(LayerRendererChromium* layerRenderer, const CCTileDrawQuad* quad, TileProgramUniforms& uniforms)
580 {
581     if (quad->isAntialiased()) {
582         if (quad->swizzleContents()) {
583             const CCTiledLayerImpl::ProgramSwizzleAA* program = layerRenderer->tilerProgramSwizzleAA();
584             tileUniformLocation(program, uniforms);
585         } else {
586             const CCTiledLayerImpl::ProgramAA* program = layerRenderer->tilerProgramAA();
587             tileUniformLocation(program, uniforms);
588         }
589     } else {
590         if (quad->needsBlending()) {
591             if (quad->swizzleContents()) {
592                 const CCTiledLayerImpl::ProgramSwizzle* program = layerRenderer->tilerProgramSwizzle();
593                 tileUniformLocation(program, uniforms);
594             } else {
595                 const CCTiledLayerImpl::Program* program = layerRenderer->tilerProgram();
596                 tileUniformLocation(program, uniforms);
597             }
598         } else {
599             if (quad->swizzleContents()) {
600                 const CCTiledLayerImpl::ProgramSwizzleOpaque* program = layerRenderer->tilerProgramSwizzleOpaque();
601                 tileUniformLocation(program, uniforms);
602             } else {
603                 const CCTiledLayerImpl::ProgramOpaque* program = layerRenderer->tilerProgramOpaque();
604                 tileUniformLocation(program, uniforms);
605             }
606         }
607     }
608 }
609
610 void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad)
611 {
612     const IntRect& tileRect = quad->quadVisibleRect();
613
614     FloatRect clampRect(tileRect);
615     // Clamp texture coordinates to avoid sampling outside the layer
616     // by deflating the tile region half a texel or half a texel
617     // minus epsilon for one pixel layers. The resulting clamp region
618     // is mapped to the unit square by the vertex shader and mapped
619     // back to normalized texture coordinates by the fragment shader
620     // after being clamped to 0-1 range.
621     const float epsilon = 1 / 1024.0f;
622     float clampX = min(0.5, clampRect.width() / 2.0 - epsilon);
623     float clampY = min(0.5, clampRect.height() / 2.0 - epsilon);
624     clampRect.inflateX(-clampX);
625     clampRect.inflateY(-clampY);
626     FloatSize clampOffset = clampRect.minXMinYCorner() - FloatRect(tileRect).minXMinYCorner();
627
628     FloatPoint textureOffset = quad->textureOffset() + clampOffset +
629                                IntPoint(quad->quadVisibleRect().location() - quad->quadRect().location());
630
631     // Map clamping rectangle to unit square.
632     float vertexTexTranslateX = -clampRect.x() / clampRect.width();
633     float vertexTexTranslateY = -clampRect.y() / clampRect.height();
634     float vertexTexScaleX = tileRect.width() / clampRect.width();
635     float vertexTexScaleY = tileRect.height() / clampRect.height();
636
637     // Map to normalized texture coordinates.
638     const IntSize& textureSize = quad->textureSize();
639     float fragmentTexTranslateX = textureOffset.x() / textureSize.width();
640     float fragmentTexTranslateY = textureOffset.y() / textureSize.height();
641     float fragmentTexScaleX = clampRect.width() / textureSize.width();
642     float fragmentTexScaleY = clampRect.height() / textureSize.height();
643
644     TileProgramUniforms uniforms;
645     findTileProgramUniforms(this, quad, uniforms);
646
647     GLC(context(), context()->useProgram(uniforms.program));
648     GLC(context(), context()->uniform1i(uniforms.samplerLocation, 0));
649     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
650     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quad->textureId()));
651     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, quad->textureFilter()));
652     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, quad->textureFilter()));
653
654     FloatQuad localQuad;
655     if (quad->isAntialiased()) {
656         TransformationMatrix deviceTransform = TransformationMatrix(windowMatrix() * projectionMatrix() * quad->quadTransform()).to2dTransform();
657         if (!deviceTransform.isInvertible())
658             return;
659
660         FloatQuad deviceLayerQuad = deviceTransform.mapQuad(FloatQuad(quad->layerRect()));
661
662         CCLayerQuad deviceLayerBounds = CCLayerQuad(FloatQuad(deviceLayerQuad.boundingBox()));
663         deviceLayerBounds.inflateAntiAliasingDistance();
664
665         CCLayerQuad deviceLayerEdges = CCLayerQuad(deviceLayerQuad);
666         deviceLayerEdges.inflateAntiAliasingDistance();
667
668         float edge[24];
669         deviceLayerEdges.toFloatArray(edge);
670         deviceLayerBounds.toFloatArray(&edge[12]);
671         GLC(context(), context()->uniform3fv(uniforms.edgeLocation, 8, edge));
672
673         GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY));
674         GLC(context(), context()->uniform4f(uniforms.fragmentTexTransformLocation, fragmentTexTranslateX, fragmentTexTranslateY, fragmentTexScaleX, fragmentTexScaleY));
675
676         FloatPoint bottomRight(tileRect.maxX(), tileRect.maxY());
677         FloatPoint bottomLeft(tileRect.x(), tileRect.maxY());
678         FloatPoint topLeft(tileRect.x(), tileRect.y());
679         FloatPoint topRight(tileRect.maxX(), tileRect.y());
680
681         // Map points to device space.
682         bottomRight = deviceTransform.mapPoint(bottomRight);
683         bottomLeft = deviceTransform.mapPoint(bottomLeft);
684         topLeft = deviceTransform.mapPoint(topLeft);
685         topRight = deviceTransform.mapPoint(topRight);
686
687         CCLayerQuad::Edge bottomEdge(bottomRight, bottomLeft);
688         CCLayerQuad::Edge leftEdge(bottomLeft, topLeft);
689         CCLayerQuad::Edge topEdge(topLeft, topRight);
690         CCLayerQuad::Edge rightEdge(topRight, bottomRight);
691
692         // Only apply anti-aliasing to edges not clipped during culling.
693         if (quad->topEdgeAA() && tileRect.y() == quad->quadRect().y())
694             topEdge = deviceLayerEdges.top();
695         if (quad->leftEdgeAA() && tileRect.x() == quad->quadRect().x())
696             leftEdge = deviceLayerEdges.left();
697         if (quad->rightEdgeAA() && tileRect.maxX() == quad->quadRect().maxX())
698             rightEdge = deviceLayerEdges.right();
699         if (quad->bottomEdgeAA() && tileRect.maxY() == quad->quadRect().maxY())
700             bottomEdge = deviceLayerEdges.bottom();
701
702         float sign = FloatQuad(tileRect).isCounterclockwise() ? -1 : 1;
703         bottomEdge.scale(sign);
704         leftEdge.scale(sign);
705         topEdge.scale(sign);
706         rightEdge.scale(sign);
707
708         // Create device space quad.
709         CCLayerQuad deviceQuad(leftEdge, topEdge, rightEdge, bottomEdge);
710
711         // Map quad to layer space.
712         TransformationMatrix inverseDeviceTransform = deviceTransform.inverse();
713         localQuad = inverseDeviceTransform.mapQuad(deviceQuad.floatQuad());
714     } else {
715         // Move fragment shader transform to vertex shader. We can do this while
716         // still producing correct results as fragmentTexTransformLocation
717         // should always be non-negative when tiles are transformed in a way
718         // that could result in sampling outside the layer.
719         vertexTexScaleX *= fragmentTexScaleX;
720         vertexTexScaleY *= fragmentTexScaleY;
721         vertexTexTranslateX *= fragmentTexScaleX;
722         vertexTexTranslateY *= fragmentTexScaleY;
723         vertexTexTranslateX += fragmentTexTranslateX;
724         vertexTexTranslateY += fragmentTexTranslateY;
725
726         GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY));
727
728         localQuad = FloatRect(tileRect);
729     }
730
731     // Normalize to tileRect.
732     localQuad.scale(1.0f / tileRect.width(), 1.0f / tileRect.height());
733
734     drawTexturedQuad(quad->quadTransform(), tileRect.width(), tileRect.height(), quad->opacity(), localQuad, uniforms.matrixLocation, uniforms.alphaLocation, uniforms.pointLocation);
735 }
736
737 void LayerRendererChromium::drawYUV(const CCVideoDrawQuad* quad)
738 {
739     const CCVideoLayerImpl::YUVProgram* program = videoLayerYUVProgram();
740     ASSERT(program && program->initialized());
741
742     const CCVideoLayerImpl::Texture& yTexture = quad->textures()[VideoFrameChromium::yPlane];
743     const CCVideoLayerImpl::Texture& uTexture = quad->textures()[VideoFrameChromium::uPlane];
744     const CCVideoLayerImpl::Texture& vTexture = quad->textures()[VideoFrameChromium::vPlane];
745
746     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE1));
747     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, yTexture.m_texture->textureId()));
748     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE2));
749     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, uTexture.m_texture->textureId()));
750     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE3));
751     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, vTexture.m_texture->textureId()));
752
753     GLC(context(), context()->useProgram(program->program()));
754
755     float yWidthScaleFactor = static_cast<float>(yTexture.m_visibleSize.width()) / yTexture.m_texture->size().width();
756     // Arbitrarily take the u sizes because u and v dimensions are identical.
757     float uvWidthScaleFactor = static_cast<float>(uTexture.m_visibleSize.width()) / uTexture.m_texture->size().width();
758     GLC(context(), context()->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor));
759     GLC(context(), context()->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor));
760
761     GLC(context(), context()->uniform1i(program->fragmentShader().yTextureLocation(), 1));
762     GLC(context(), context()->uniform1i(program->fragmentShader().uTextureLocation(), 2));
763     GLC(context(), context()->uniform1i(program->fragmentShader().vTextureLocation(), 3));
764
765     GLC(context(), context()->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 1, 0, const_cast<float*>(CCVideoLayerImpl::yuv2RGB)));
766     GLC(context(), context()->uniform3fv(program->fragmentShader().yuvAdjLocation(), 1, const_cast<float*>(CCVideoLayerImpl::yuvAdjust)));
767
768     const IntSize& bounds = quad->quadRect().size();
769     drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), FloatQuad(),
770                                     program->vertexShader().matrixLocation(),
771                                     program->fragmentShader().alphaLocation(),
772                                     -1);
773
774     // Reset active texture back to texture 0.
775     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
776 }
777
778 template<class Program>
779 void LayerRendererChromium::drawSingleTextureVideoQuad(const CCVideoDrawQuad* quad, Program* program, float widthScaleFactor, Platform3DObject textureId, GC3Denum target)
780 {
781     ASSERT(program && program->initialized());
782
783     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
784     GLC(context(), context()->bindTexture(target, textureId));
785
786     GLC(context(), context()->useProgram(program->program()));
787     GLC(context(), context()->uniform4f(program->vertexShader().texTransformLocation(), 0, 0, widthScaleFactor, 1));
788     GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
789
790     const IntSize& bounds = quad->quadRect().size();
791     drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), sharedGeometryQuad(),
792                                     program->vertexShader().matrixLocation(),
793                                     program->fragmentShader().alphaLocation(),
794                                     -1);
795 }
796
797 void LayerRendererChromium::drawRGBA(const CCVideoDrawQuad* quad)
798 {
799     const CCVideoLayerImpl::RGBAProgram* program = videoLayerRGBAProgram();
800     const CCVideoLayerImpl::Texture& texture = quad->textures()[VideoFrameChromium::rgbPlane];
801     float widthScaleFactor = static_cast<float>(texture.m_visibleSize.width()) / texture.m_texture->size().width();
802     drawSingleTextureVideoQuad(quad, program, widthScaleFactor, texture.m_texture->textureId(), GraphicsContext3D::TEXTURE_2D);
803 }
804
805 void LayerRendererChromium::drawNativeTexture2D(const CCVideoDrawQuad* quad)
806 {
807     const CCVideoLayerImpl::NativeTextureProgram* program = videoLayerNativeTextureProgram();
808     drawSingleTextureVideoQuad(quad, program, 1, quad->frame()->textureId(), GraphicsContext3D::TEXTURE_2D);
809 }
810
811 void LayerRendererChromium::drawStreamTexture(const CCVideoDrawQuad* quad)
812 {
813     ASSERT(context()->getExtensions()->supports("GL_OES_EGL_image_external") && context()->getExtensions()->isEnabled("GL_OES_EGL_image_external"));
814
815     const CCVideoLayerImpl::StreamTextureProgram* program = streamTextureLayerProgram();
816     GLC(context(), context()->useProgram(program->program()));
817     ASSERT(quad->matrix());
818     GLC(context(), context()->uniformMatrix4fv(program->vertexShader().texMatrixLocation(), 1, false, const_cast<float*>(quad->matrix())));
819
820     drawSingleTextureVideoQuad(quad, program, 1, quad->frame()->textureId(), Extensions3DChromium::GL_TEXTURE_EXTERNAL_OES);
821 }
822
823 bool LayerRendererChromium::copyFrameToTextures(const CCVideoDrawQuad* quad)
824 {
825     const VideoFrameChromium* frame = quad->frame();
826
827     for (unsigned plane = 0; plane < frame->planes(); ++plane) {
828         ASSERT(quad->frame()->requiredTextureSize(plane) == quad->textures()[plane].m_texture->size());
829         copyPlaneToTexture(quad, frame->data(plane), plane);
830     }
831     for (unsigned plane = frame->planes(); plane < CCVideoLayerImpl::MaxPlanes; ++plane) {
832         CCVideoLayerImpl::Texture* texture = &quad->textures()[plane];
833         texture->m_texture.clear();
834         texture->m_visibleSize = IntSize();
835     }
836     return true;
837 }
838
839 void LayerRendererChromium::copyPlaneToTexture(const CCVideoDrawQuad* quad, const void* plane, int index)
840 {
841     CCVideoLayerImpl::Texture& texture = quad->textures()[index];
842     TextureAllocator* allocator = renderSurfaceTextureAllocator();
843     texture.m_texture->bindTexture(context(), allocator);
844     GC3Denum format = texture.m_texture->format();
845     IntSize dimensions = texture.m_texture->size();
846
847     void* mem = static_cast<Extensions3DChromium*>(context()->getExtensions())->mapTexSubImage2DCHROMIUM(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, dimensions.width(), dimensions.height(), format, GraphicsContext3D::UNSIGNED_BYTE, Extensions3DChromium::WRITE_ONLY);
848     if (mem) {
849         memcpy(mem, plane, dimensions.width() * dimensions.height());
850         GLC(context(), static_cast<Extensions3DChromium*>(context()->getExtensions())->unmapTexSubImage2DCHROMIUM(mem));
851     } else {
852         // If mapTexSubImage2DCHROMIUM fails, then do the slower texSubImage2D
853         // upload. This does twice the copies as mapTexSubImage2DCHROMIUM, one
854         // in the command buffer and another to the texture.
855         GLC(context(), context()->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, dimensions.width(), dimensions.height(), format, GraphicsContext3D::UNSIGNED_BYTE, plane));
856     }
857 }
858
859 void LayerRendererChromium::drawVideoQuad(const CCVideoDrawQuad* quad)
860 {
861     ASSERT(CCProxy::isImplThread());
862
863     if (!quad->frame())
864         return;
865
866     if (!copyFrameToTextures(quad))
867         return;
868
869     switch (quad->format()) {
870     case GraphicsContext3D::LUMINANCE:
871         drawYUV(quad);
872         break;
873     case GraphicsContext3D::RGBA:
874         drawRGBA(quad);
875         break;
876     case GraphicsContext3D::TEXTURE_2D:
877         drawNativeTexture2D(quad);
878         break;
879     case Extensions3DChromium::GL_TEXTURE_EXTERNAL_OES:
880         drawStreamTexture(quad);
881         break;
882     default:
883         CRASH(); // Someone updated convertVFCFormatToGC3DFormat above but update this!
884     }
885 }
886
887 struct TextureProgramBinding {
888     template<class Program> void set(Program* program)
889     {
890         ASSERT(program && program->initialized());
891         programId = program->program();
892         samplerLocation = program->fragmentShader().samplerLocation();
893         matrixLocation = program->vertexShader().matrixLocation();
894         alphaLocation = program->fragmentShader().alphaLocation();
895     }
896     int programId;
897     int samplerLocation;
898     int matrixLocation;
899     int alphaLocation;
900 };
901
902 struct TexStretchTextureProgramBinding : TextureProgramBinding {
903     template<class Program> void set(Program* program)
904     {
905         TextureProgramBinding::set(program);
906         offsetLocation = program->vertexShader().offsetLocation();
907         scaleLocation = program->vertexShader().scaleLocation();
908     }
909     int offsetLocation;
910     int scaleLocation;
911 };
912
913 struct TexTransformTextureProgramBinding : TextureProgramBinding {
914     template<class Program> void set(Program* program)
915     {
916         TextureProgramBinding::set(program);
917         texTransformLocation = program->vertexShader().texTransformLocation();
918     }
919     int texTransformLocation;
920 };
921
922 void LayerRendererChromium::drawTextureQuad(const CCTextureDrawQuad* quad)
923 {
924     ASSERT(CCProxy::isImplThread());
925     unsigned matrixLocation = 0;
926     unsigned alphaLocation = 0;
927     if (quad->ioSurfaceTextureId()) {
928         TexTransformTextureProgramBinding binding;
929         if (quad->flipped())
930             binding.set(textureLayerTexRectProgramFlip());
931         else
932             binding.set(textureLayerTexRectProgram());
933
934         GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
935
936         GLC(context(), context()->useProgram(binding.programId));
937         GLC(context(), context()->uniform1i(binding.samplerLocation, 0));
938         GLC(context(), context()->uniform4f(binding.texTransformLocation, 0, 0, quad->ioSurfaceSize().width(), quad->ioSurfaceSize().height()));
939
940         matrixLocation = binding.matrixLocation;
941         alphaLocation = binding.alphaLocation;
942     } else if (quad->flipped() && quad->uvRect() == FloatRect(0, 0, 1, 1)) {
943         // A flipped quad with the default UV mapping is common enough to use a special shader.
944         // Canvas 2d and WebGL layers use this path always and plugin/external texture layers use this by default.
945         const CCTextureLayerImpl::ProgramFlip* program = textureLayerProgramFlip();
946         GLC(context(), context()->useProgram(program->program()));
947         GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
948         matrixLocation = program->vertexShader().matrixLocation();
949         alphaLocation = program->fragmentShader().alphaLocation();
950     } else {
951         TexStretchTextureProgramBinding binding;
952         if (quad->flipped())
953             binding.set(textureLayerProgramStretchFlip());
954         else
955             binding.set(textureLayerProgramStretch());
956         GLC(context, context()->useProgram(binding.programId));
957         GLC(context, context()->uniform1i(binding.samplerLocation, 0));
958         GLC(context, context()->uniform2f(binding.offsetLocation, quad->uvRect().x(), quad->uvRect().y()));
959         GLC(context, context()->uniform2f(binding.scaleLocation, quad->uvRect().width(), quad->uvRect().height()));
960
961         matrixLocation = binding.matrixLocation;
962         alphaLocation = binding.alphaLocation;
963     }
964     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
965
966     if (quad->ioSurfaceTextureId())
967         GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, quad->ioSurfaceTextureId()));
968     else
969         GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quad->textureId()));
970
971     // FIXME: setting the texture parameters every time is redundant. Move this code somewhere
972     // where it will only happen once per texture.
973     GLC(context, context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
974     GLC(context, context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
975     GLC(context, context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
976     GLC(context, context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
977
978     if (quad->hasAlpha() && !quad->premultipliedAlpha())
979         GLC(context(), context()->blendFunc(GraphicsContext3D::SRC_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
980
981     const IntSize& bounds = quad->quadRect().size();
982
983     drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), sharedGeometryQuad(), matrixLocation, alphaLocation, -1);
984
985     GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
986
987     if (quad->ioSurfaceTextureId())
988         GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, 0));
989 }
990
991 void LayerRendererChromium::finishDrawingFrame()
992 {
993     if (m_headsUpDisplay->enabled()) {
994         GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND));
995         GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
996         GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
997         useRenderSurface(m_defaultRenderSurface);
998         m_headsUpDisplay->draw();
999     }
1000
1001     GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
1002     GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND));
1003
1004     size_t contentsMemoryUseBytes = m_contentsTextureAllocator->currentMemoryUseBytes();
1005     size_t reclaimLimit = TextureManager::reclaimLimitBytes(viewportSize());
1006     size_t preferredLimit = reclaimLimit > contentsMemoryUseBytes ? reclaimLimit - contentsMemoryUseBytes : 0;
1007     m_renderSurfaceTextureManager->setPreferredMemoryLimitBytes(preferredLimit);
1008     m_renderSurfaceTextureManager->reduceMemoryToLimit(preferredLimit);
1009     m_renderSurfaceTextureManager->deleteEvictedTextures(m_renderSurfaceTextureAllocator.get());
1010
1011     if (settings().compositeOffscreen)
1012         copyOffscreenTextureToDisplay();
1013 }
1014
1015 void LayerRendererChromium::toGLMatrix(float* flattened, const TransformationMatrix& m)
1016 {
1017     flattened[0] = m.m11();
1018     flattened[1] = m.m12();
1019     flattened[2] = m.m13();
1020     flattened[3] = m.m14();
1021     flattened[4] = m.m21();
1022     flattened[5] = m.m22();
1023     flattened[6] = m.m23();
1024     flattened[7] = m.m24();
1025     flattened[8] = m.m31();
1026     flattened[9] = m.m32();
1027     flattened[10] = m.m33();
1028     flattened[11] = m.m34();
1029     flattened[12] = m.m41();
1030     flattened[13] = m.m42();
1031     flattened[14] = m.m43();
1032     flattened[15] = m.m44();
1033 }
1034
1035 void LayerRendererChromium::drawTexturedQuad(const TransformationMatrix& drawMatrix,
1036                                              float width, float height, float opacity, const FloatQuad& quad,
1037                                              int matrixLocation, int alphaLocation, int quadLocation)
1038 {
1039     static float glMatrix[16];
1040
1041     TransformationMatrix renderMatrix = drawMatrix;
1042
1043     // Apply a scaling factor to size the quad from 1x1 to its intended size.
1044     renderMatrix.scale3d(width, height, 1);
1045
1046     // Apply the projection matrix before sending the transform over to the shader.
1047     toGLMatrix(&glMatrix[0], m_projectionMatrix * renderMatrix);
1048
1049     GLC(m_context, m_context->uniformMatrix4fv(matrixLocation, 1, false, &glMatrix[0]));
1050
1051     if (quadLocation != -1) {
1052         float point[8];
1053         point[0] = quad.p1().x();
1054         point[1] = quad.p1().y();
1055         point[2] = quad.p2().x();
1056         point[3] = quad.p2().y();
1057         point[4] = quad.p3().x();
1058         point[5] = quad.p3().y();
1059         point[6] = quad.p4().x();
1060         point[7] = quad.p4().y();
1061         GLC(m_context, m_context->uniform2fv(quadLocation, 4, point));
1062     }
1063
1064     if (alphaLocation != -1)
1065         GLC(m_context, m_context->uniform1f(alphaLocation, opacity));
1066
1067     GLC(m_context, m_context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0));
1068 }
1069
1070 void LayerRendererChromium::finish()
1071 {
1072     TRACE_EVENT("LayerRendererChromium::finish", this, 0);
1073     m_context->finish();
1074 }
1075
1076 void LayerRendererChromium::swapBuffers(const IntRect& subBuffer)
1077 {
1078     // FIXME: Remove this once gpu process supports ignoring swap buffers command while framebuffer is discarded.
1079     //        Alternatively (preferably?), protect all cc code so as not to attempt a swap after a framebuffer discard.
1080     if (m_isFramebufferDiscarded) {
1081         m_client->setFullRootLayerDamage();
1082         return;
1083     }
1084
1085     TRACE_EVENT("LayerRendererChromium::swapBuffers", this, 0);
1086     // We're done! Time to swapbuffers!
1087
1088     if (m_capabilities.usingPartialSwap) {
1089         // If supported, we can save significant bandwidth by only swapping the damaged/scissored region (clamped to the viewport)
1090         IntRect clippedSubBuffer = subBuffer;
1091         clippedSubBuffer.intersect(IntRect(IntPoint::zero(), viewportSize()));
1092         Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(m_context->getExtensions());
1093         int flippedYPosOfRectBottom = viewportHeight() - clippedSubBuffer.y() - clippedSubBuffer.height();
1094         extensions3DChromium->postSubBufferCHROMIUM(clippedSubBuffer.x(), flippedYPosOfRectBottom, clippedSubBuffer.width(), clippedSubBuffer.height());
1095     } else
1096         // Note that currently this has the same effect as swapBuffers; we should
1097         // consider exposing a different entry point on GraphicsContext3D.
1098         m_context->prepareTexture();
1099
1100     m_headsUpDisplay->onSwapBuffers();
1101 }
1102
1103 void LayerRendererChromium::onSwapBuffersComplete()
1104 {
1105     m_client->onSwapBuffersComplete();
1106 }
1107
1108 void LayerRendererChromium::discardFramebuffer()
1109 {
1110     if (m_isFramebufferDiscarded)
1111         return;
1112
1113     if (!m_capabilities.usingDiscardFramebuffer)
1114         return;
1115
1116     Extensions3D* extensions = m_context->getExtensions();
1117     Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
1118     // FIXME: Update attachments argument to appropriate values once they are no longer ignored.
1119     extensions3DChromium->discardFramebufferEXT(GraphicsContext3D::TEXTURE_2D, 0, 0);
1120     m_isFramebufferDiscarded = true;
1121
1122     // Damage tracker needs a full reset every time framebuffer is discarded.
1123     m_client->setFullRootLayerDamage();
1124 }
1125
1126 void LayerRendererChromium::ensureFramebuffer()
1127 {
1128     if (!m_isFramebufferDiscarded)
1129         return;
1130
1131     if (!m_capabilities.usingDiscardFramebuffer)
1132         return;
1133
1134     Extensions3D* extensions = m_context->getExtensions();
1135     Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
1136     extensions3DChromium->ensureFramebufferCHROMIUM();
1137     m_isFramebufferDiscarded = false;
1138 }
1139
1140 void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect)
1141 {
1142     ASSERT(rect.maxX() <= viewportWidth() && rect.maxY() <= viewportHeight());
1143
1144     if (!pixels)
1145         return;
1146
1147     makeContextCurrent();
1148
1149     bool doWorkaround = needsLionIOSurfaceReadbackWorkaround();
1150
1151     Platform3DObject temporaryTexture = NullPlatform3DObject;
1152     Platform3DObject temporaryFBO = NullPlatform3DObject;
1153     GraphicsContext3D* context = m_context.get();
1154
1155     if (doWorkaround) {
1156         // On Mac OS X 10.7, calling glReadPixels against an FBO whose color attachment is an
1157         // IOSurface-backed texture causes corruption of future glReadPixels calls, even those on
1158         // different OpenGL contexts. It is believed that this is the root cause of top crasher
1159         // http://crbug.com/99393. <rdar://problem/10949687>
1160
1161         temporaryTexture = context->createTexture();
1162         GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, temporaryTexture));
1163         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
1164         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
1165         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
1166         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
1167         // Copy the contents of the current (IOSurface-backed) framebuffer into a temporary texture.
1168         GLC(context, context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 0, 0, rect.maxX(), rect.maxY(), 0));
1169         temporaryFBO = context->createFramebuffer();
1170         // Attach this texture to an FBO, and perform the readback from that FBO.
1171         GLC(context, context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, temporaryFBO));
1172         GLC(context, context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, temporaryTexture, 0));
1173
1174         ASSERT(context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) == GraphicsContext3D::FRAMEBUFFER_COMPLETE);
1175     }
1176
1177     GLC(context, context->readPixels(rect.x(), rect.y(), rect.width(), rect.height(),
1178                                      GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
1179
1180     if (doWorkaround) {
1181         // Clean up.
1182         GLC(context, context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
1183         GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0));
1184         GLC(context, context->deleteFramebuffer(temporaryFBO));
1185         GLC(context, context->deleteTexture(temporaryTexture));
1186     }
1187 }
1188
1189 ManagedTexture* LayerRendererChromium::getOffscreenLayerTexture()
1190 {
1191     return settings().compositeOffscreen && rootLayer() ? rootLayer()->renderSurface()->contentsTexture() : 0;
1192 }
1193
1194 void LayerRendererChromium::copyOffscreenTextureToDisplay()
1195 {
1196     if (settings().compositeOffscreen) {
1197         makeContextCurrent();
1198
1199         useRenderSurface(0);
1200         TransformationMatrix drawTransform;
1201         drawTransform.translate3d(0.5 * m_defaultRenderSurface->contentRect().width(), 0.5 * m_defaultRenderSurface->contentRect().height(), 0);
1202         m_defaultRenderSurface->setDrawTransform(drawTransform);
1203         m_defaultRenderSurface->setDrawOpacity(1);
1204         m_defaultRenderSurface->draw(this, m_defaultRenderSurface->contentRect());
1205     }
1206 }
1207
1208 bool LayerRendererChromium::useRenderSurface(CCRenderSurface* renderSurface)
1209 {
1210     m_currentRenderSurface = renderSurface;
1211
1212     if ((renderSurface == m_defaultRenderSurface && !settings().compositeOffscreen) || (!renderSurface && settings().compositeOffscreen)) {
1213         GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
1214         if (renderSurface)
1215             setDrawViewportRect(renderSurface->contentRect(), true);
1216         else
1217             setDrawViewportRect(m_defaultRenderSurface->contentRect(), true);
1218         return true;
1219     }
1220
1221     GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId));
1222
1223     if (!renderSurface->prepareContentsTexture(this))
1224         return false;
1225
1226     renderSurface->contentsTexture()->framebufferTexture2D(m_context.get(), m_renderSurfaceTextureAllocator.get());
1227
1228 #if !defined ( NDEBUG )
1229     if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
1230         ASSERT_NOT_REACHED();
1231         return false;
1232     }
1233 #endif
1234
1235     setDrawViewportRect(renderSurface->contentRect(), false);
1236
1237     return true;
1238 }
1239
1240 // Sets the scissor region to the given rectangle. The coordinate system for the
1241 // scissorRect has its origin at the top left corner of the current visible rect.
1242 void LayerRendererChromium::setScissorToRect(const IntRect& scissorRect)
1243 {
1244     IntRect contentRect = (m_currentRenderSurface ? m_currentRenderSurface->contentRect() : m_defaultRenderSurface->contentRect());
1245
1246     GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
1247
1248     // The scissor coordinates must be supplied in viewport space so we need to offset
1249     // by the relative position of the top left corner of the current render surface.
1250     int scissorX = scissorRect.x() - contentRect.x();
1251     // When rendering to the default render surface we're rendering upside down so the top
1252     // of the GL scissor is the bottom of our layer.
1253     // But, if rendering to offscreen texture, we reverse our sense of 'upside down'.
1254     int scissorY;
1255     if (m_currentRenderSurface == m_defaultRenderSurface && !settings().compositeOffscreen)
1256         scissorY = m_currentRenderSurface->contentRect().height() - (scissorRect.maxY() - m_currentRenderSurface->contentRect().y());
1257     else
1258         scissorY = scissorRect.y() - contentRect.y();
1259     GLC(m_context.get(), m_context->scissor(scissorX, scissorY, scissorRect.width(), scissorRect.height()));
1260 }
1261
1262 bool LayerRendererChromium::makeContextCurrent()
1263 {
1264     return m_context->makeContextCurrent();
1265 }
1266
1267 // Sets the coordinate range of content that ends being drawn onto the target render surface.
1268 // The target render surface is assumed to have an origin at 0, 0 and the width and height of
1269 // of the drawRect.
1270 void LayerRendererChromium::setDrawViewportRect(const IntRect& drawRect, bool flipY)
1271 {
1272     if (flipY)
1273         m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.maxY(), drawRect.y());
1274     else
1275         m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.y(), drawRect.maxY());
1276     GLC(m_context.get(), m_context->viewport(0, 0, drawRect.width(), drawRect.height()));
1277     m_windowMatrix = screenMatrix(0, 0, drawRect.width(), drawRect.height());
1278 }
1279
1280
1281 bool LayerRendererChromium::initializeSharedObjects()
1282 {
1283     TRACE_EVENT("LayerRendererChromium::initializeSharedObjects", this, 0);
1284     makeContextCurrent();
1285
1286     // Create an FBO for doing offscreen rendering.
1287     GLC(m_context.get(), m_offscreenFramebufferId = m_context->createFramebuffer());
1288
1289     // We will always need these programs to render, so create the programs eagerly so that the shader compilation can
1290     // start while we do other work. Other programs are created lazily on first access.
1291     m_sharedGeometry = adoptPtr(new GeometryBinding(m_context.get()));
1292     m_renderSurfaceProgram = adoptPtr(new CCRenderSurface::Program(m_context.get()));
1293     m_tilerProgram = adoptPtr(new CCTiledLayerImpl::Program(m_context.get()));
1294     m_tilerProgramOpaque = adoptPtr(new CCTiledLayerImpl::ProgramOpaque(m_context.get()));
1295
1296     GLC(m_context.get(), m_context->flush());
1297
1298     m_renderSurfaceTextureManager = TextureManager::create(TextureManager::highLimitBytes(viewportSize()),
1299                                                            TextureManager::reclaimLimitBytes(viewportSize()),
1300                                                            m_capabilities.maxTextureSize);
1301     m_textureCopier = AcceleratedTextureCopier::create(m_context.get());
1302     m_contentsTextureAllocator = TrackingTextureAllocator::create(m_context.get());
1303     m_renderSurfaceTextureAllocator = TrackingTextureAllocator::create(m_context.get());
1304     if (m_capabilities.usingTextureUsageHint)
1305         m_renderSurfaceTextureAllocator->setTextureUsageHint(TrackingTextureAllocator::FramebufferAttachment);
1306     if (m_capabilities.usingTextureStorageExtension) {
1307         m_contentsTextureAllocator->setUseTextureStorageExt(true);
1308         m_renderSurfaceTextureAllocator->setUseTextureStorageExt(true);
1309     }
1310
1311     return true;
1312 }
1313
1314 const LayerChromium::BorderProgram* LayerRendererChromium::borderProgram()
1315 {
1316     if (!m_borderProgram)
1317         m_borderProgram = adoptPtr(new LayerChromium::BorderProgram(m_context.get()));
1318     if (!m_borderProgram->initialized()) {
1319         TRACE_EVENT("LayerRendererChromium::borderProgram::initialize", this, 0);
1320         m_borderProgram->initialize(m_context.get());
1321     }
1322     return m_borderProgram.get();
1323 }
1324
1325 const CCHeadsUpDisplay::Program* LayerRendererChromium::headsUpDisplayProgram()
1326 {
1327     if (!m_headsUpDisplayProgram)
1328         m_headsUpDisplayProgram = adoptPtr(new CCHeadsUpDisplay::Program(m_context.get()));
1329     if (!m_headsUpDisplayProgram->initialized()) {
1330         TRACE_EVENT("LayerRendererChromium::headsUpDisplayProgram::initialize", this, 0);
1331         m_headsUpDisplayProgram->initialize(m_context.get());
1332     }
1333     return m_headsUpDisplayProgram.get();
1334 }
1335
1336 const CCRenderSurface::Program* LayerRendererChromium::renderSurfaceProgram()
1337 {
1338     ASSERT(m_renderSurfaceProgram);
1339     if (!m_renderSurfaceProgram->initialized()) {
1340         TRACE_EVENT("LayerRendererChromium::renderSurfaceProgram::initialize", this, 0);
1341         m_renderSurfaceProgram->initialize(m_context.get());
1342     }
1343     return m_renderSurfaceProgram.get();
1344 }
1345
1346 const CCRenderSurface::ProgramAA* LayerRendererChromium::renderSurfaceProgramAA()
1347 {
1348     if (!m_renderSurfaceProgramAA)
1349         m_renderSurfaceProgramAA = adoptPtr(new CCRenderSurface::ProgramAA(m_context.get()));
1350     if (!m_renderSurfaceProgramAA->initialized()) {
1351         TRACE_EVENT("LayerRendererChromium::renderSurfaceProgramAA::initialize", this, 0);
1352         m_renderSurfaceProgramAA->initialize(m_context.get());
1353     }
1354     return m_renderSurfaceProgramAA.get();
1355 }
1356
1357 const CCRenderSurface::MaskProgram* LayerRendererChromium::renderSurfaceMaskProgram()
1358 {
1359     if (!m_renderSurfaceMaskProgram)
1360         m_renderSurfaceMaskProgram = adoptPtr(new CCRenderSurface::MaskProgram(m_context.get()));
1361     if (!m_renderSurfaceMaskProgram->initialized()) {
1362         TRACE_EVENT("LayerRendererChromium::renderSurfaceMaskProgram::initialize", this, 0);
1363         m_renderSurfaceMaskProgram->initialize(m_context.get());
1364     }
1365     return m_renderSurfaceMaskProgram.get();
1366 }
1367
1368 const CCRenderSurface::MaskProgramAA* LayerRendererChromium::renderSurfaceMaskProgramAA()
1369 {
1370     if (!m_renderSurfaceMaskProgramAA)
1371         m_renderSurfaceMaskProgramAA = adoptPtr(new CCRenderSurface::MaskProgramAA(m_context.get()));
1372     if (!m_renderSurfaceMaskProgramAA->initialized()) {
1373         TRACE_EVENT("LayerRendererChromium::renderSurfaceMaskProgramAA::initialize", this, 0);
1374         m_renderSurfaceMaskProgramAA->initialize(m_context.get());
1375     }
1376     return m_renderSurfaceMaskProgramAA.get();
1377 }
1378
1379 const CCTiledLayerImpl::Program* LayerRendererChromium::tilerProgram()
1380 {
1381     ASSERT(m_tilerProgram);
1382     if (!m_tilerProgram->initialized()) {
1383         TRACE_EVENT("LayerRendererChromium::tilerProgram::initialize", this, 0);
1384         m_tilerProgram->initialize(m_context.get());
1385     }
1386     return m_tilerProgram.get();
1387 }
1388
1389 const CCTiledLayerImpl::ProgramOpaque* LayerRendererChromium::tilerProgramOpaque()
1390 {
1391     ASSERT(m_tilerProgramOpaque);
1392     if (!m_tilerProgramOpaque->initialized()) {
1393         TRACE_EVENT("LayerRendererChromium::tilerProgramOpaque::initialize", this, 0);
1394         m_tilerProgramOpaque->initialize(m_context.get());
1395     }
1396     return m_tilerProgramOpaque.get();
1397 }
1398
1399 const CCTiledLayerImpl::ProgramAA* LayerRendererChromium::tilerProgramAA()
1400 {
1401     if (!m_tilerProgramAA)
1402         m_tilerProgramAA = adoptPtr(new CCTiledLayerImpl::ProgramAA(m_context.get()));
1403     if (!m_tilerProgramAA->initialized()) {
1404         TRACE_EVENT("LayerRendererChromium::tilerProgramAA::initialize", this, 0);
1405         m_tilerProgramAA->initialize(m_context.get());
1406     }
1407     return m_tilerProgramAA.get();
1408 }
1409
1410 const CCTiledLayerImpl::ProgramSwizzle* LayerRendererChromium::tilerProgramSwizzle()
1411 {
1412     if (!m_tilerProgramSwizzle)
1413         m_tilerProgramSwizzle = adoptPtr(new CCTiledLayerImpl::ProgramSwizzle(m_context.get()));
1414     if (!m_tilerProgramSwizzle->initialized()) {
1415         TRACE_EVENT("LayerRendererChromium::tilerProgramSwizzle::initialize", this, 0);
1416         m_tilerProgramSwizzle->initialize(m_context.get());
1417     }
1418     return m_tilerProgramSwizzle.get();
1419 }
1420
1421 const CCTiledLayerImpl::ProgramSwizzleOpaque* LayerRendererChromium::tilerProgramSwizzleOpaque()
1422 {
1423     if (!m_tilerProgramSwizzleOpaque)
1424         m_tilerProgramSwizzleOpaque = adoptPtr(new CCTiledLayerImpl::ProgramSwizzleOpaque(m_context.get()));
1425     if (!m_tilerProgramSwizzleOpaque->initialized()) {
1426         TRACE_EVENT("LayerRendererChromium::tilerProgramSwizzleOpaque::initialize", this, 0);
1427         m_tilerProgramSwizzleOpaque->initialize(m_context.get());
1428     }
1429     return m_tilerProgramSwizzleOpaque.get();
1430 }
1431
1432 const CCTiledLayerImpl::ProgramSwizzleAA* LayerRendererChromium::tilerProgramSwizzleAA()
1433 {
1434     if (!m_tilerProgramSwizzleAA)
1435         m_tilerProgramSwizzleAA = adoptPtr(new CCTiledLayerImpl::ProgramSwizzleAA(m_context.get()));
1436     if (!m_tilerProgramSwizzleAA->initialized()) {
1437         TRACE_EVENT("LayerRendererChromium::tilerProgramSwizzleAA::initialize", this, 0);
1438         m_tilerProgramSwizzleAA->initialize(m_context.get());
1439     }
1440     return m_tilerProgramSwizzleAA.get();
1441 }
1442
1443 const CCTextureLayerImpl::ProgramFlip* LayerRendererChromium::textureLayerProgramFlip()
1444 {
1445     if (!m_textureLayerProgramFlip)
1446         m_textureLayerProgramFlip = adoptPtr(new CCTextureLayerImpl::ProgramFlip(m_context.get()));
1447     if (!m_textureLayerProgramFlip->initialized()) {
1448         TRACE_EVENT("LayerRendererChromium::textureLayerProgram::initialize", this, 0);
1449         m_textureLayerProgramFlip->initialize(m_context.get());
1450     }
1451     return m_textureLayerProgramFlip.get();
1452 }
1453
1454 const CCTextureLayerImpl::ProgramStretch* LayerRendererChromium::textureLayerProgramStretch()
1455 {
1456     if (!m_textureLayerProgramStretch)
1457         m_textureLayerProgramStretch = adoptPtr(new CCTextureLayerImpl::ProgramStretch(m_context.get()));
1458     if (!m_textureLayerProgramStretch->initialized()) {
1459         TRACE_EVENT("LayerRendererChromium::textureLayerProgram::initialize", this, 0);
1460         m_textureLayerProgramStretch->initialize(m_context.get());
1461     }
1462     return m_textureLayerProgramStretch.get();
1463 }
1464
1465 const CCTextureLayerImpl::ProgramStretchFlip* LayerRendererChromium::textureLayerProgramStretchFlip()
1466 {
1467     if (!m_textureLayerProgramStretchFlip)
1468         m_textureLayerProgramStretchFlip = adoptPtr(new CCTextureLayerImpl::ProgramStretchFlip(m_context.get()));
1469     if (!m_textureLayerProgramStretchFlip->initialized()) {
1470         TRACE_EVENT("LayerRendererChromium::textureLayerProgramStretchFlip::initialize", this, 0);
1471         m_textureLayerProgramStretchFlip->initialize(m_context.get());
1472     }
1473     return m_textureLayerProgramStretchFlip.get();
1474 }
1475
1476 const CCTextureLayerImpl::TexRectProgram* LayerRendererChromium::textureLayerTexRectProgram()
1477 {
1478     if (!m_textureLayerTexRectProgram)
1479         m_textureLayerTexRectProgram = adoptPtr(new CCTextureLayerImpl::TexRectProgram(m_context.get()));
1480     if (!m_textureLayerTexRectProgram->initialized()) {
1481         TRACE_EVENT("LayerRendererChromium::textureLayerTexRectProgram::initialize", this, 0);
1482         m_textureLayerTexRectProgram->initialize(m_context.get());
1483     }
1484     return m_textureLayerTexRectProgram.get();
1485 }
1486
1487 const CCTextureLayerImpl::TexRectProgramFlip* LayerRendererChromium::textureLayerTexRectProgramFlip()
1488 {
1489     if (!m_textureLayerTexRectProgramFlip)
1490         m_textureLayerTexRectProgramFlip = adoptPtr(new CCTextureLayerImpl::TexRectProgramFlip(m_context.get()));
1491     if (!m_textureLayerTexRectProgramFlip->initialized()) {
1492         TRACE_EVENT("LayerRendererChromium::textureLayerTexRectProgramFlip::initialize", this, 0);
1493         m_textureLayerTexRectProgramFlip->initialize(m_context.get());
1494     }
1495     return m_textureLayerTexRectProgramFlip.get();
1496 }
1497
1498 const CCVideoLayerImpl::RGBAProgram* LayerRendererChromium::videoLayerRGBAProgram()
1499 {
1500     if (!m_videoLayerRGBAProgram)
1501         m_videoLayerRGBAProgram = adoptPtr(new CCVideoLayerImpl::RGBAProgram(m_context.get()));
1502     if (!m_videoLayerRGBAProgram->initialized()) {
1503         TRACE_EVENT("LayerRendererChromium::videoLayerRGBAProgram::initialize", this, 0);
1504         m_videoLayerRGBAProgram->initialize(m_context.get());
1505     }
1506     return m_videoLayerRGBAProgram.get();
1507 }
1508
1509 const CCVideoLayerImpl::YUVProgram* LayerRendererChromium::videoLayerYUVProgram()
1510 {
1511     if (!m_videoLayerYUVProgram)
1512         m_videoLayerYUVProgram = adoptPtr(new CCVideoLayerImpl::YUVProgram(m_context.get()));
1513     if (!m_videoLayerYUVProgram->initialized()) {
1514         TRACE_EVENT("LayerRendererChromium::videoLayerYUVProgram::initialize", this, 0);
1515         m_videoLayerYUVProgram->initialize(m_context.get());
1516     }
1517     return m_videoLayerYUVProgram.get();
1518 }
1519
1520 const CCVideoLayerImpl::NativeTextureProgram* LayerRendererChromium::videoLayerNativeTextureProgram()
1521 {
1522     if (!m_videoLayerNativeTextureProgram)
1523         m_videoLayerNativeTextureProgram = adoptPtr(new CCVideoLayerImpl::NativeTextureProgram(m_context.get()));
1524     if (!m_videoLayerNativeTextureProgram->initialized()) {
1525         TRACE_EVENT("LayerRendererChromium::videoLayerNativeTextureProgram::initialize", this, 0);
1526         m_videoLayerNativeTextureProgram->initialize(m_context.get());
1527     }
1528     return m_videoLayerNativeTextureProgram.get();
1529 }
1530
1531 const CCVideoLayerImpl::StreamTextureProgram* LayerRendererChromium::streamTextureLayerProgram()
1532 {
1533     if (!m_streamTextureLayerProgram)
1534         m_streamTextureLayerProgram = adoptPtr(new CCVideoLayerImpl::StreamTextureProgram(m_context.get()));
1535     if (!m_streamTextureLayerProgram->initialized()) {
1536         TRACE_EVENT("LayerRendererChromium::streamTextureLayerProgram::initialize", this, 0);
1537         m_streamTextureLayerProgram->initialize(m_context.get());
1538     }
1539     return m_streamTextureLayerProgram.get();
1540 }
1541
1542 void LayerRendererChromium::cleanupSharedObjects()
1543 {
1544     makeContextCurrent();
1545
1546     m_sharedGeometry.clear();
1547
1548     if (m_borderProgram)
1549         m_borderProgram->cleanup(m_context.get());
1550     if (m_headsUpDisplayProgram)
1551         m_headsUpDisplayProgram->cleanup(m_context.get());
1552     if (m_textureLayerProgramFlip)
1553         m_textureLayerProgramFlip->cleanup(m_context.get());
1554     if (m_textureLayerProgramStretch)
1555         m_textureLayerProgramStretch->cleanup(m_context.get());
1556     if (m_textureLayerProgramStretchFlip)
1557         m_textureLayerProgramStretchFlip->cleanup(m_context.get());
1558     if (m_textureLayerTexRectProgram)
1559         m_textureLayerTexRectProgram->cleanup(m_context.get());
1560     if (m_textureLayerTexRectProgramFlip)
1561         m_textureLayerTexRectProgramFlip->cleanup(m_context.get());
1562     if (m_tilerProgram)
1563         m_tilerProgram->cleanup(m_context.get());
1564     if (m_tilerProgramOpaque)
1565         m_tilerProgramOpaque->cleanup(m_context.get());
1566     if (m_tilerProgramSwizzle)
1567         m_tilerProgramSwizzle->cleanup(m_context.get());
1568     if (m_tilerProgramSwizzleOpaque)
1569         m_tilerProgramSwizzleOpaque->cleanup(m_context.get());
1570     if (m_tilerProgramAA)
1571         m_tilerProgramAA->cleanup(m_context.get());
1572     if (m_tilerProgramSwizzleAA)
1573         m_tilerProgramSwizzleAA->cleanup(m_context.get());
1574     if (m_renderSurfaceMaskProgram)
1575         m_renderSurfaceMaskProgram->cleanup(m_context.get());
1576     if (m_renderSurfaceProgram)
1577         m_renderSurfaceProgram->cleanup(m_context.get());
1578     if (m_renderSurfaceMaskProgramAA)
1579         m_renderSurfaceMaskProgramAA->cleanup(m_context.get());
1580     if (m_renderSurfaceProgramAA)
1581         m_renderSurfaceProgramAA->cleanup(m_context.get());
1582     if (m_videoLayerRGBAProgram)
1583         m_videoLayerRGBAProgram->cleanup(m_context.get());
1584     if (m_videoLayerYUVProgram)
1585         m_videoLayerYUVProgram->cleanup(m_context.get());
1586     if (m_videoLayerNativeTextureProgram)
1587         m_videoLayerNativeTextureProgram->cleanup(m_context.get());
1588     if (m_streamTextureLayerProgram)
1589         m_streamTextureLayerProgram->cleanup(m_context.get());
1590
1591     m_borderProgram.clear();
1592     m_headsUpDisplayProgram.clear();
1593     m_textureLayerProgramFlip.clear();
1594     m_textureLayerProgramStretch.clear();
1595     m_textureLayerProgramStretchFlip.clear();
1596     m_textureLayerTexRectProgram.clear();
1597     m_textureLayerTexRectProgramFlip.clear();
1598     m_tilerProgram.clear();
1599     m_tilerProgramOpaque.clear();
1600     m_tilerProgramSwizzle.clear();
1601     m_tilerProgramSwizzleOpaque.clear();
1602     m_tilerProgramAA.clear();
1603     m_tilerProgramSwizzleAA.clear();
1604     m_renderSurfaceMaskProgram.clear();
1605     m_renderSurfaceProgram.clear();
1606     m_renderSurfaceMaskProgramAA.clear();
1607     m_renderSurfaceProgramAA.clear();
1608     m_videoLayerRGBAProgram.clear();
1609     m_videoLayerYUVProgram.clear();
1610     m_videoLayerNativeTextureProgram.clear();
1611     m_streamTextureLayerProgram.clear();
1612     if (m_offscreenFramebufferId)
1613         GLC(m_context.get(), m_context->deleteFramebuffer(m_offscreenFramebufferId));
1614     m_textureCopier.clear();
1615
1616     releaseRenderSurfaceTextures();
1617 }
1618
1619 String LayerRendererChromium::layerTreeAsText() const
1620 {
1621     TextStream ts;
1622     if (rootLayer()) {
1623         ts << rootLayer()->layerTreeAsText();
1624         ts << "RenderSurfaces:\n";
1625         dumpRenderSurfaces(ts, 1, rootLayer());
1626     }
1627     return ts.release();
1628 }
1629
1630 void LayerRendererChromium::dumpRenderSurfaces(TextStream& ts, int indent, const CCLayerImpl* layer) const
1631 {
1632     if (layer->renderSurface())
1633         layer->renderSurface()->dumpSurface(ts, indent);
1634
1635     for (size_t i = 0; i < layer->children().size(); ++i)
1636         dumpRenderSurfaces(ts, indent, layer->children()[i].get());
1637 }
1638
1639 bool LayerRendererChromium::isContextLost()
1640 {
1641     return (m_context.get()->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR);
1642 }
1643
1644 } // namespace WebCore
1645
1646 #endif // USE(ACCELERATED_COMPOSITING)