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