[chromium] Separate IOSurface layer type from texture layers
[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 "Extensions3D.h"
38 #include "Extensions3DChromium.h"
39 #include "FloatQuad.h"
40 #include "GeometryBinding.h"
41 #include "GrTexture.h"
42 #include "GraphicsContext3D.h"
43 #include "ManagedTexture.h"
44 #include "NativeImageSkia.h"
45 #include "NotImplemented.h"
46 #include "PlatformColor.h"
47 #include "PlatformContextSkia.h"
48 #include "RenderSurfaceChromium.h"
49 #include "TextureCopier.h"
50 #include "TextureManager.h"
51 #include "TraceEvent.h"
52 #include "TrackingTextureAllocator.h"
53 #include "cc/CCCheckerboardDrawQuad.h"
54 #include "cc/CCDamageTracker.h"
55 #include "cc/CCDebugBorderDrawQuad.h"
56 #include "cc/CCIOSurfaceDrawQuad.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 <public/WebVideoFrame.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_currentManagedTexture(0)
209     , m_offscreenFramebufferId(0)
210     , m_context(context)
211     , m_defaultRenderSurface(0)
212     , m_sharedGeometryQuad(FloatRect(-0.5f, -0.5f, 1.0f, 1.0f))
213     , m_isViewportChanged(false)
214     , m_isFramebufferDiscarded(false)
215 {
216 }
217
218 class ContextLostCallbackAdapter : public GraphicsContext3D::ContextLostCallback {
219 public:
220     static PassOwnPtr<ContextLostCallbackAdapter> create(LayerRendererChromiumClient* client)
221     {
222         return adoptPtr(new ContextLostCallbackAdapter(client));
223     }
224
225     virtual void onContextLost()
226     {
227         m_client->didLoseContext();
228     }
229
230 private:
231     explicit ContextLostCallbackAdapter(LayerRendererChromiumClient* client)
232         : m_client(client) { }
233
234     LayerRendererChromiumClient* m_client;
235 };
236
237 bool LayerRendererChromium::initialize()
238 {
239     if (!m_context->makeContextCurrent())
240         return false;
241
242     m_context->setContextLostCallback(ContextLostCallbackAdapter::create(m_client));
243
244     if (settings().acceleratePainting && contextSupportsAcceleratedPainting(m_context.get()))
245         m_capabilities.usingAcceleratedPainting = true;
246
247     WebCore::Extensions3D* extensions = m_context->getExtensions();
248     m_capabilities.contextHasCachedFrontBuffer = extensions->supports("GL_CHROMIUM_front_buffer_cached");
249     if (m_capabilities.contextHasCachedFrontBuffer)
250         extensions->ensureEnabled("GL_CHROMIUM_front_buffer_cached");
251
252     m_capabilities.usingPartialSwap = settings().partialSwapEnabled && extensions->supports("GL_CHROMIUM_post_sub_buffer");
253     if (m_capabilities.usingPartialSwap)
254         extensions->ensureEnabled("GL_CHROMIUM_post_sub_buffer");
255
256     m_capabilities.usingMapSub = extensions->supports("GL_CHROMIUM_map_sub");
257     if (m_capabilities.usingMapSub)
258         extensions->ensureEnabled("GL_CHROMIUM_map_sub");
259
260     // Use the swapBuffers callback only with the threaded proxy.
261     if (CCProxy::hasImplThread())
262         m_capabilities.usingSwapCompleteCallback = extensions->supports("GL_CHROMIUM_swapbuffers_complete_callback");
263     if (m_capabilities.usingSwapCompleteCallback) {
264         extensions->ensureEnabled("GL_CHROMIUM_swapbuffers_complete_callback");
265         Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
266         extensions3DChromium->setSwapBuffersCompleteCallbackCHROMIUM(LayerRendererSwapBuffersCompleteCallbackAdapter::create(this));
267     }
268
269     if (extensions->supports("GL_EXT_texture_format_BGRA8888"))
270         extensions->ensureEnabled("GL_EXT_texture_format_BGRA8888");
271
272     m_capabilities.usingSetVisibility = extensions->supports("GL_CHROMIUM_set_visibility");
273     if (m_capabilities.usingSetVisibility)
274         extensions->ensureEnabled("GL_CHROMIUM_set_visibility");
275
276     if (extensions->supports("GL_CHROMIUM_iosurface")) {
277         ASSERT(extensions->supports("GL_ARB_texture_rectangle"));
278         extensions->ensureEnabled("GL_ARB_texture_rectangle");
279         extensions->ensureEnabled("GL_CHROMIUM_iosurface");
280     }
281
282     m_capabilities.usingTextureUsageHint = extensions->supports("GL_ANGLE_texture_usage");
283     if (m_capabilities.usingTextureUsageHint)
284         extensions->ensureEnabled("GL_ANGLE_texture_usage");
285
286     m_capabilities.usingTextureStorageExtension = extensions->supports("GL_EXT_texture_storage");
287     if (m_capabilities.usingTextureStorageExtension)
288         extensions->ensureEnabled("GL_EXT_texture_storage");
289
290     m_capabilities.usingGpuMemoryManager = extensions->supports("GL_CHROMIUM_gpu_memory_manager");
291     if (m_capabilities.usingGpuMemoryManager) {
292         extensions->ensureEnabled("GL_CHROMIUM_gpu_memory_manager");
293         Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
294         extensions3DChromium->setGpuMemoryAllocationChangedCallbackCHROMIUM(LayerRendererGpuMemoryAllocationChangedCallbackAdapter::create(this));
295     }
296
297     m_capabilities.usingDiscardFramebuffer = extensions->supports("GL_CHROMIUM_discard_framebuffer");
298     if (m_capabilities.usingDiscardFramebuffer)
299         extensions->ensureEnabled("GL_CHROMIUM_discard_framebuffer");
300
301     GLC(m_context, m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_capabilities.maxTextureSize));
302     m_capabilities.bestTextureFormat = PlatformColor::bestTextureFormat(m_context.get());
303
304     if (!initializeSharedObjects())
305         return false;
306
307     // Make sure the viewport and context gets initialized, even if it is to zero.
308     viewportChanged();
309     return true;
310 }
311
312 LayerRendererChromium::~LayerRendererChromium()
313 {
314     ASSERT(CCProxy::isImplThread());
315     Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(m_context->getExtensions());
316     extensions3DChromium->setSwapBuffersCompleteCallbackCHROMIUM(nullptr);
317     extensions3DChromium->setGpuMemoryAllocationChangedCallbackCHROMIUM(nullptr);
318     cleanupSharedObjects();
319 }
320
321 GraphicsContext3D* LayerRendererChromium::context()
322 {
323     return m_context.get();
324 }
325
326 void LayerRendererChromium::debugGLCall(GraphicsContext3D* context, const char* command, const char* file, int line)
327 {
328     unsigned long error = context->getError();
329     if (error != GraphicsContext3D::NO_ERROR)
330         LOG_ERROR("GL command failed: File: %s\n\tLine %d\n\tcommand: %s, error %x\n", file, line, command, static_cast<int>(error));
331 }
332
333 void LayerRendererChromium::setVisible(bool visible)
334 {
335     if (!visible)
336         releaseRenderSurfaceTextures();
337
338     // TODO: Replace setVisibilityCHROMIUM with an extension to explicitly manage front/backbuffers
339     // crbug.com/116049
340     if (m_capabilities.usingSetVisibility) {
341         Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(m_context->getExtensions());
342         extensions3DChromium->setVisibilityCHROMIUM(visible);
343     }
344 }
345
346 void LayerRendererChromium::releaseRenderSurfaceTextures()
347 {
348     if (m_renderSurfaceTextureManager)
349         m_renderSurfaceTextureManager->evictAndDeleteAllTextures(m_renderSurfaceTextureAllocator.get());
350 }
351
352 void LayerRendererChromium::viewportChanged()
353 {
354     m_isViewportChanged = true;
355
356     // Reset the current render surface to force an update of the viewport and
357     // projection matrix next time useRenderSurface is called.
358     m_currentRenderSurface = 0;
359 }
360
361 void LayerRendererChromium::clearRenderSurface(CCRenderSurface* renderSurface, CCRenderSurface* rootRenderSurface, const FloatRect& surfaceDamageRect)
362 {
363     // Non-root layers should clear their entire contents to transparent. On DEBUG builds, the root layer
364     // is cleared to blue to easily see regions that were not drawn on the screen. If we
365     // are using partial swap / scissor optimization, then the surface should only
366     // clear the damaged region, so that we don't accidentally clear un-changed portions
367     // of the screen.
368
369     if (renderSurface != rootRenderSurface)
370         GLC(m_context, m_context->clearColor(0, 0, 0, 0));
371     else
372         GLC(m_context, m_context->clearColor(0, 0, 1, 1));
373
374     if (m_capabilities.usingPartialSwap)
375         setScissorToRect(enclosingIntRect(surfaceDamageRect));
376     else
377         GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
378
379 #if defined(NDEBUG)
380     if (renderSurface != rootRenderSurface)
381 #endif
382         m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
383
384     GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST));
385 }
386
387 void LayerRendererChromium::beginDrawingFrame(CCRenderSurface* defaultRenderSurface)
388 {
389     // FIXME: Remove this once framebuffer is automatically recreated on first use
390     ensureFramebuffer();
391
392     m_defaultRenderSurface = defaultRenderSurface;
393     ASSERT(m_defaultRenderSurface);
394
395     size_t contentsMemoryUseBytes = m_contentsTextureAllocator->currentMemoryUseBytes();
396     size_t maxLimit = TextureManager::highLimitBytes(viewportSize());
397     m_renderSurfaceTextureManager->setMaxMemoryLimitBytes(maxLimit - contentsMemoryUseBytes);
398
399     if (viewportSize().isEmpty())
400         return;
401
402     TRACE_EVENT("LayerRendererChromium::drawLayers", this, 0);
403     if (m_isViewportChanged) {
404         // Only reshape when we know we are going to draw. Otherwise, the reshape
405         // can leave the window at the wrong size if we never draw and the proper
406         // viewport size is never set.
407         m_isViewportChanged = false;
408         m_context->reshape(viewportWidth(), viewportHeight());
409     }
410
411     makeContextCurrent();
412     // Bind the common vertex attributes used for drawing all the layers.
413     m_sharedGeometry->prepareForDraw();
414
415     GLC(m_context, m_context->disable(GraphicsContext3D::DEPTH_TEST));
416     GLC(m_context, m_context->disable(GraphicsContext3D::CULL_FACE));
417     GLC(m_context, m_context->colorMask(true, true, true, true));
418     GLC(m_context, m_context->enable(GraphicsContext3D::BLEND));
419     GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
420 }
421
422 void LayerRendererChromium::doNoOp()
423 {
424     GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
425     GLC(m_context, m_context->flush());
426 }
427
428 void LayerRendererChromium::drawRenderPass(const CCRenderPass* renderPass)
429 {
430     CCRenderSurface* renderSurface = renderPass->targetSurface();
431     if (!useRenderSurface(renderSurface))
432         return;
433
434     clearRenderSurface(renderSurface, m_defaultRenderSurface, renderPass->surfaceDamageRect());
435
436     const CCQuadList& quadList = renderPass->quadList();
437     for (CCQuadList::constBackToFrontIterator it = quadList.backToFrontBegin(); it != quadList.backToFrontEnd(); ++it)
438         drawQuad(it->get(), renderPass->surfaceDamageRect());
439 }
440
441 void LayerRendererChromium::drawQuad(const CCDrawQuad* quad, const FloatRect& surfaceDamageRect)
442 {
443     IntRect scissorRect;
444     if (m_capabilities.usingPartialSwap) {
445         FloatRect clipAndDamageRect = surfaceDamageRect;
446         if (!quad->clipRect().isEmpty())
447             clipAndDamageRect.intersect(quad->clipRect());
448         scissorRect = enclosingIntRect(clipAndDamageRect);
449         if (scissorRect.isEmpty())
450             return;
451     } else
452         scissorRect = quad->clipRect();
453
454     if (scissorRect.isEmpty())
455         GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
456     else
457         setScissorToRect(scissorRect);
458
459     if (quad->needsBlending())
460         GLC(m_context, m_context->enable(GraphicsContext3D::BLEND));
461     else
462         GLC(m_context, m_context->disable(GraphicsContext3D::BLEND));
463
464     switch (quad->material()) {
465     case CCDrawQuad::Invalid:
466         ASSERT_NOT_REACHED();
467         break;
468     case CCDrawQuad::Checkerboard:
469         drawCheckerboardQuad(quad->toCheckerboardDrawQuad());
470         break;
471     case CCDrawQuad::DebugBorder:
472         drawDebugBorderQuad(quad->toDebugBorderDrawQuad());
473         break;
474     case CCDrawQuad::IOSurfaceContent:
475         drawIOSurfaceQuad(quad->toIOSurfaceDrawQuad());
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 TileCheckerboardProgram* program = tileCheckerboardProgram();
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 SolidColorProgram* program = solidColorProgram();
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 SolidColorProgram* program = solidColorProgram();
621     GLC(context(), context()->useProgram(program->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(program->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                      program->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 void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad)
666 {
667     const IntRect& tileRect = quad->quadVisibleRect();
668
669     FloatRect clampRect(tileRect);
670     // Clamp texture coordinates to avoid sampling outside the layer
671     // by deflating the tile region half a texel or half a texel
672     // minus epsilon for one pixel layers. The resulting clamp region
673     // is mapped to the unit square by the vertex shader and mapped
674     // back to normalized texture coordinates by the fragment shader
675     // after being clamped to 0-1 range.
676     const float epsilon = 1 / 1024.0f;
677     float clampX = min(0.5, clampRect.width() / 2.0 - epsilon);
678     float clampY = min(0.5, clampRect.height() / 2.0 - epsilon);
679     clampRect.inflateX(-clampX);
680     clampRect.inflateY(-clampY);
681     FloatSize clampOffset = clampRect.minXMinYCorner() - FloatRect(tileRect).minXMinYCorner();
682
683     FloatPoint textureOffset = quad->textureOffset() + clampOffset +
684                                IntPoint(quad->quadVisibleRect().location() - quad->quadRect().location());
685
686     // Map clamping rectangle to unit square.
687     float vertexTexTranslateX = -clampRect.x() / clampRect.width();
688     float vertexTexTranslateY = -clampRect.y() / clampRect.height();
689     float vertexTexScaleX = tileRect.width() / clampRect.width();
690     float vertexTexScaleY = tileRect.height() / clampRect.height();
691
692     // Map to normalized texture coordinates.
693     const IntSize& textureSize = quad->textureSize();
694     float fragmentTexTranslateX = textureOffset.x() / textureSize.width();
695     float fragmentTexTranslateY = textureOffset.y() / textureSize.height();
696     float fragmentTexScaleX = clampRect.width() / textureSize.width();
697     float fragmentTexScaleY = clampRect.height() / textureSize.height();
698
699
700     FloatQuad localQuad;
701     TransformationMatrix deviceTransform = TransformationMatrix(windowMatrix() * projectionMatrix() * quad->quadTransform()).to2dTransform();
702     if (!deviceTransform.isInvertible())
703         return;
704
705     bool clipped = false;
706     FloatQuad deviceLayerQuad = CCMathUtil::mapQuad(deviceTransform, FloatQuad(quad->layerRect()), clipped);
707
708     TileProgramUniforms uniforms;
709     // For now, we simply skip anti-aliasing with the quad is clipped. This only happens
710     // on perspective transformed layers that go partially behind the camera.
711     if (quad->isAntialiased() && !clipped) {
712         if (quad->swizzleContents())
713             tileUniformLocation(tileProgramSwizzleAA(), uniforms);
714         else
715             tileUniformLocation(tileProgramAA(), uniforms);
716     } else {
717         if (quad->needsBlending()) {
718             if (quad->swizzleContents())
719                 tileUniformLocation(tileProgramSwizzle(), uniforms);
720             else
721                 tileUniformLocation(tileProgram(), uniforms);
722         } else {
723             if (quad->swizzleContents())
724                 tileUniformLocation(tileProgramSwizzleOpaque(), uniforms);
725             else
726                 tileUniformLocation(tileProgramOpaque(), uniforms);
727         }
728     }
729
730     GLC(context(), context()->useProgram(uniforms.program));
731     GLC(context(), context()->uniform1i(uniforms.samplerLocation, 0));
732     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
733     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quad->textureId()));
734     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, quad->textureFilter()));
735     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, quad->textureFilter()));
736
737
738     if (!clipped && quad->isAntialiased()) {
739
740         CCLayerQuad deviceLayerBounds = CCLayerQuad(FloatQuad(deviceLayerQuad.boundingBox()));
741         deviceLayerBounds.inflateAntiAliasingDistance();
742
743         CCLayerQuad deviceLayerEdges = CCLayerQuad(deviceLayerQuad);
744         deviceLayerEdges.inflateAntiAliasingDistance();
745
746         float edge[24];
747         deviceLayerEdges.toFloatArray(edge);
748         deviceLayerBounds.toFloatArray(&edge[12]);
749         GLC(context(), context()->uniform3fv(uniforms.edgeLocation, 8, edge));
750
751         GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY));
752         GLC(context(), context()->uniform4f(uniforms.fragmentTexTransformLocation, fragmentTexTranslateX, fragmentTexTranslateY, fragmentTexScaleX, fragmentTexScaleY));
753
754         FloatPoint bottomRight(tileRect.maxX(), tileRect.maxY());
755         FloatPoint bottomLeft(tileRect.x(), tileRect.maxY());
756         FloatPoint topLeft(tileRect.x(), tileRect.y());
757         FloatPoint topRight(tileRect.maxX(), tileRect.y());
758
759         // Map points to device space.
760         bottomRight = deviceTransform.mapPoint(bottomRight);
761         bottomLeft = deviceTransform.mapPoint(bottomLeft);
762         topLeft = deviceTransform.mapPoint(topLeft);
763         topRight = deviceTransform.mapPoint(topRight);
764
765         CCLayerQuad::Edge bottomEdge(bottomRight, bottomLeft);
766         CCLayerQuad::Edge leftEdge(bottomLeft, topLeft);
767         CCLayerQuad::Edge topEdge(topLeft, topRight);
768         CCLayerQuad::Edge rightEdge(topRight, bottomRight);
769
770         // Only apply anti-aliasing to edges not clipped during culling.
771         if (quad->topEdgeAA() && tileRect.y() == quad->quadRect().y())
772             topEdge = deviceLayerEdges.top();
773         if (quad->leftEdgeAA() && tileRect.x() == quad->quadRect().x())
774             leftEdge = deviceLayerEdges.left();
775         if (quad->rightEdgeAA() && tileRect.maxX() == quad->quadRect().maxX())
776             rightEdge = deviceLayerEdges.right();
777         if (quad->bottomEdgeAA() && tileRect.maxY() == quad->quadRect().maxY())
778             bottomEdge = deviceLayerEdges.bottom();
779
780         float sign = FloatQuad(tileRect).isCounterclockwise() ? -1 : 1;
781         bottomEdge.scale(sign);
782         leftEdge.scale(sign);
783         topEdge.scale(sign);
784         rightEdge.scale(sign);
785
786         // Create device space quad.
787         CCLayerQuad deviceQuad(leftEdge, topEdge, rightEdge, bottomEdge);
788
789         // Map quad to layer space.
790         TransformationMatrix inverseDeviceTransform = deviceTransform.inverse();
791         localQuad = inverseDeviceTransform.mapQuad(deviceQuad.floatQuad());
792     } else {
793         // Move fragment shader transform to vertex shader. We can do this while
794         // still producing correct results as fragmentTexTransformLocation
795         // should always be non-negative when tiles are transformed in a way
796         // that could result in sampling outside the layer.
797         vertexTexScaleX *= fragmentTexScaleX;
798         vertexTexScaleY *= fragmentTexScaleY;
799         vertexTexTranslateX *= fragmentTexScaleX;
800         vertexTexTranslateY *= fragmentTexScaleY;
801         vertexTexTranslateX += fragmentTexTranslateX;
802         vertexTexTranslateY += fragmentTexTranslateY;
803
804         GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY));
805
806         localQuad = FloatRect(tileRect);
807     }
808
809     // Normalize to tileRect.
810     localQuad.scale(1.0f / tileRect.width(), 1.0f / tileRect.height());
811
812     drawTexturedQuad(quad->quadTransform(), tileRect.width(), tileRect.height(), quad->opacity(), localQuad, uniforms.matrixLocation, uniforms.alphaLocation, uniforms.pointLocation);
813 }
814
815 void LayerRendererChromium::drawYUV(const CCVideoDrawQuad* quad)
816 {
817     const VideoYUVProgram* program = videoYUVProgram();
818     ASSERT(program && program->initialized());
819
820     const CCVideoLayerImpl::Texture& yTexture = quad->textures()[WebKit::WebVideoFrame::yPlane];
821     const CCVideoLayerImpl::Texture& uTexture = quad->textures()[WebKit::WebVideoFrame::uPlane];
822     const CCVideoLayerImpl::Texture& vTexture = quad->textures()[WebKit::WebVideoFrame::vPlane];
823
824     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE1));
825     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, yTexture.m_texture->textureId()));
826     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE2));
827     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, uTexture.m_texture->textureId()));
828     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE3));
829     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, vTexture.m_texture->textureId()));
830
831     GLC(context(), context()->useProgram(program->program()));
832
833     float yWidthScaleFactor = static_cast<float>(yTexture.m_visibleSize.width()) / yTexture.m_texture->size().width();
834     // Arbitrarily take the u sizes because u and v dimensions are identical.
835     float uvWidthScaleFactor = static_cast<float>(uTexture.m_visibleSize.width()) / uTexture.m_texture->size().width();
836     GLC(context(), context()->uniform1f(program->vertexShader().yWidthScaleFactorLocation(), yWidthScaleFactor));
837     GLC(context(), context()->uniform1f(program->vertexShader().uvWidthScaleFactorLocation(), uvWidthScaleFactor));
838
839     GLC(context(), context()->uniform1i(program->fragmentShader().yTextureLocation(), 1));
840     GLC(context(), context()->uniform1i(program->fragmentShader().uTextureLocation(), 2));
841     GLC(context(), context()->uniform1i(program->fragmentShader().vTextureLocation(), 3));
842
843     GLC(context(), context()->uniformMatrix3fv(program->fragmentShader().ccMatrixLocation(), 1, 0, const_cast<float*>(CCVideoLayerImpl::yuv2RGB)));
844     GLC(context(), context()->uniform3fv(program->fragmentShader().yuvAdjLocation(), 1, const_cast<float*>(CCVideoLayerImpl::yuvAdjust)));
845
846     const IntSize& bounds = quad->quadRect().size();
847     drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), FloatQuad(),
848                                     program->vertexShader().matrixLocation(),
849                                     program->fragmentShader().alphaLocation(),
850                                     -1);
851
852     // Reset active texture back to texture 0.
853     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
854 }
855
856 template<class Program>
857 void LayerRendererChromium::drawSingleTextureVideoQuad(const CCVideoDrawQuad* quad, Program* program, float widthScaleFactor, Platform3DObject textureId, GC3Denum target)
858 {
859     ASSERT(program && program->initialized());
860
861     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
862     GLC(context(), context()->bindTexture(target, textureId));
863
864     GLC(context(), context()->useProgram(program->program()));
865     GLC(context(), context()->uniform4f(program->vertexShader().texTransformLocation(), 0, 0, widthScaleFactor, 1));
866     GLC(context(), context()->uniform1i(program->fragmentShader().samplerLocation(), 0));
867
868     const IntSize& bounds = quad->quadRect().size();
869     drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), sharedGeometryQuad(),
870                                     program->vertexShader().matrixLocation(),
871                                     program->fragmentShader().alphaLocation(),
872                                     -1);
873 }
874
875 void LayerRendererChromium::drawRGBA(const CCVideoDrawQuad* quad)
876 {
877     const TextureProgram* program = textureProgram();
878     const CCVideoLayerImpl::Texture& texture = quad->textures()[WebKit::WebVideoFrame::rgbPlane];
879     float widthScaleFactor = static_cast<float>(texture.m_visibleSize.width()) / texture.m_texture->size().width();
880     drawSingleTextureVideoQuad(quad, program, widthScaleFactor, texture.m_texture->textureId(), GraphicsContext3D::TEXTURE_2D);
881 }
882
883 void LayerRendererChromium::drawNativeTexture2D(const CCVideoDrawQuad* quad)
884 {
885     drawSingleTextureVideoQuad(quad, textureProgram(), 1, quad->frame()->textureId(), GraphicsContext3D::TEXTURE_2D);
886 }
887
888 void LayerRendererChromium::drawStreamTexture(const CCVideoDrawQuad* quad)
889 {
890     ASSERT(context()->getExtensions()->supports("GL_OES_EGL_image_external") && context()->getExtensions()->isEnabled("GL_OES_EGL_image_external"));
891
892     const VideoStreamTextureProgram* program = videoStreamTextureProgram();
893     GLC(context(), context()->useProgram(program->program()));
894     ASSERT(quad->matrix());
895     GLC(context(), context()->uniformMatrix4fv(program->vertexShader().texMatrixLocation(), 1, false, const_cast<float*>(quad->matrix())));
896
897     drawSingleTextureVideoQuad(quad, program, 1, quad->frame()->textureId(), Extensions3DChromium::GL_TEXTURE_EXTERNAL_OES);
898 }
899
900 bool LayerRendererChromium::copyFrameToTextures(const CCVideoDrawQuad* quad)
901 {
902     const WebKit::WebVideoFrame* frame = quad->frame();
903
904     for (unsigned plane = 0; plane < frame->planes(); ++plane)
905         copyPlaneToTexture(quad, frame->data(plane), plane);
906
907     for (unsigned plane = frame->planes(); plane < CCVideoLayerImpl::MaxPlanes; ++plane) {
908         CCVideoLayerImpl::Texture* texture = &quad->textures()[plane];
909         texture->m_texture.clear();
910         texture->m_visibleSize = IntSize();
911     }
912     return true;
913 }
914
915 void LayerRendererChromium::copyPlaneToTexture(const CCVideoDrawQuad* quad, const void* plane, int index)
916 {
917     CCVideoLayerImpl::Texture& texture = quad->textures()[index];
918     TextureAllocator* allocator = renderSurfaceTextureAllocator();
919     texture.m_texture->bindTexture(context(), allocator);
920     GC3Denum format = texture.m_texture->format();
921     IntSize dimensions = texture.m_texture->size();
922
923     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);
924     if (mem) {
925         memcpy(mem, plane, dimensions.width() * dimensions.height());
926         GLC(context(), static_cast<Extensions3DChromium*>(context()->getExtensions())->unmapTexSubImage2DCHROMIUM(mem));
927     } else {
928         // If mapTexSubImage2DCHROMIUM fails, then do the slower texSubImage2D
929         // upload. This does twice the copies as mapTexSubImage2DCHROMIUM, one
930         // in the command buffer and another to the texture.
931         GLC(context(), context()->texSubImage2D(GraphicsContext3D::TEXTURE_2D, 0, 0, 0, dimensions.width(), dimensions.height(), format, GraphicsContext3D::UNSIGNED_BYTE, plane));
932     }
933 }
934
935 void LayerRendererChromium::drawVideoQuad(const CCVideoDrawQuad* quad)
936 {
937     ASSERT(CCProxy::isImplThread());
938
939     if (!quad->frame())
940         return;
941
942     if (!copyFrameToTextures(quad))
943         return;
944
945     switch (quad->format()) {
946     case GraphicsContext3D::LUMINANCE:
947         drawYUV(quad);
948         break;
949     case GraphicsContext3D::RGBA:
950         drawRGBA(quad);
951         break;
952     case GraphicsContext3D::TEXTURE_2D:
953         drawNativeTexture2D(quad);
954         break;
955     case Extensions3DChromium::GL_TEXTURE_EXTERNAL_OES:
956         drawStreamTexture(quad);
957         break;
958     default:
959         CRASH(); // Someone updated convertVFCFormatToGC3DFormat above but update this!
960     }
961 }
962
963 struct TextureProgramBinding {
964     template<class Program> void set(Program* program)
965     {
966         ASSERT(program && program->initialized());
967         programId = program->program();
968         samplerLocation = program->fragmentShader().samplerLocation();
969         matrixLocation = program->vertexShader().matrixLocation();
970         alphaLocation = program->fragmentShader().alphaLocation();
971     }
972     int programId;
973     int samplerLocation;
974     int matrixLocation;
975     int alphaLocation;
976 };
977
978 struct TexTransformTextureProgramBinding : TextureProgramBinding {
979     template<class Program> void set(Program* program)
980     {
981         TextureProgramBinding::set(program);
982         texTransformLocation = program->vertexShader().texTransformLocation();
983     }
984     int texTransformLocation;
985 };
986
987 void LayerRendererChromium::drawTextureQuad(const CCTextureDrawQuad* quad)
988 {
989     ASSERT(CCProxy::isImplThread());
990
991     TexTransformTextureProgramBinding binding;
992     if (quad->flipped())
993         binding.set(textureProgramFlip());
994     else
995         binding.set(textureProgram());
996     GLC(context(), context()->useProgram(binding.programId));
997     GLC(context(), context()->uniform1i(binding.samplerLocation, 0));
998     const FloatRect& uvRect = quad->uvRect();
999     GLC(context(), context()->uniform4f(binding.texTransformLocation, uvRect.x(), uvRect.y(), uvRect.width(), uvRect.height()));
1000
1001     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
1002     GLC(context(), context()->bindTexture(GraphicsContext3D::TEXTURE_2D, quad->textureId()));
1003
1004     // FIXME: setting the texture parameters every time is redundant. Move this code somewhere
1005     // where it will only happen once per texture.
1006     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
1007     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
1008     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
1009     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
1010
1011     if (!quad->premultipliedAlpha())
1012         GLC(context(), context()->blendFunc(GraphicsContext3D::SRC_ALPHA, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
1013
1014     const IntSize& bounds = quad->quadRect().size();
1015
1016     drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), sharedGeometryQuad(), binding.matrixLocation, binding.alphaLocation, -1);
1017
1018     if (!quad->premultipliedAlpha())
1019         GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
1020 }
1021
1022 void LayerRendererChromium::drawIOSurfaceQuad(const CCIOSurfaceDrawQuad* quad)
1023 {
1024     ASSERT(CCProxy::isImplThread());
1025     TexTransformTextureProgramBinding binding;
1026     binding.set(textureIOSurfaceProgram());
1027
1028     GLC(context(), context()->useProgram(binding.programId));
1029     GLC(context(), context()->uniform1i(binding.samplerLocation, 0));
1030     GLC(context(), context()->uniform4f(binding.texTransformLocation, 0, 0, quad->ioSurfaceSize().width(), quad->ioSurfaceSize().height()));
1031
1032     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
1033     GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, quad->ioSurfaceTextureId()));
1034
1035     // FIXME: setting the texture parameters every time is redundant. Move this code somewhere
1036     // where it will only happen once per texture.
1037     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
1038     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
1039     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
1040     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
1041
1042     const IntSize& bounds = quad->quadRect().size();
1043
1044     drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), sharedGeometryQuad(), binding.matrixLocation, binding.alphaLocation, -1);
1045
1046     GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, 0));
1047 }
1048
1049 void LayerRendererChromium::drawHeadsUpDisplay(ManagedTexture* hudTexture, const IntSize& hudSize)
1050 {
1051     GLC(m_context, m_context->enable(GraphicsContext3D::BLEND));
1052     GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
1053     GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
1054     useRenderSurface(m_defaultRenderSurface);
1055
1056     const HeadsUpDisplayProgram* program = headsUpDisplayProgram();
1057     ASSERT(program && program->initialized());
1058     GLC(m_context, m_context->activeTexture(GraphicsContext3D::TEXTURE0));
1059     hudTexture->bindTexture(m_context.get(), renderSurfaceTextureAllocator());
1060     GLC(m_context, m_context->useProgram(program->program()));
1061     GLC(m_context, m_context->uniform1i(program->fragmentShader().samplerLocation(), 0));
1062
1063     TransformationMatrix matrix;
1064     matrix.translate3d(hudSize.width() * 0.5, hudSize.height() * 0.5, 0);
1065     drawTexturedQuad(matrix, hudSize.width(), hudSize.height(),
1066                      1, sharedGeometryQuad(), program->vertexShader().matrixLocation(),
1067                      program->fragmentShader().alphaLocation(),
1068                      -1);
1069 }
1070
1071 void LayerRendererChromium::finishDrawingFrame()
1072 {
1073     GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
1074     GLC(m_context, m_context->disable(GraphicsContext3D::BLEND));
1075
1076     size_t contentsMemoryUseBytes = m_contentsTextureAllocator->currentMemoryUseBytes();
1077     size_t reclaimLimit = TextureManager::reclaimLimitBytes(viewportSize());
1078     size_t preferredLimit = reclaimLimit > contentsMemoryUseBytes ? reclaimLimit - contentsMemoryUseBytes : 0;
1079     m_renderSurfaceTextureManager->setPreferredMemoryLimitBytes(preferredLimit);
1080     m_renderSurfaceTextureManager->reduceMemoryToLimit(preferredLimit);
1081     m_renderSurfaceTextureManager->deleteEvictedTextures(m_renderSurfaceTextureAllocator.get());
1082 }
1083
1084 void LayerRendererChromium::toGLMatrix(float* flattened, const TransformationMatrix& m)
1085 {
1086     flattened[0] = m.m11();
1087     flattened[1] = m.m12();
1088     flattened[2] = m.m13();
1089     flattened[3] = m.m14();
1090     flattened[4] = m.m21();
1091     flattened[5] = m.m22();
1092     flattened[6] = m.m23();
1093     flattened[7] = m.m24();
1094     flattened[8] = m.m31();
1095     flattened[9] = m.m32();
1096     flattened[10] = m.m33();
1097     flattened[11] = m.m34();
1098     flattened[12] = m.m41();
1099     flattened[13] = m.m42();
1100     flattened[14] = m.m43();
1101     flattened[15] = m.m44();
1102 }
1103
1104 void LayerRendererChromium::drawTexturedQuad(const TransformationMatrix& drawMatrix,
1105                                              float width, float height, float opacity, const FloatQuad& quad,
1106                                              int matrixLocation, int alphaLocation, int quadLocation)
1107 {
1108     static float glMatrix[16];
1109
1110     TransformationMatrix renderMatrix = drawMatrix;
1111
1112     // Apply a scaling factor to size the quad from 1x1 to its intended size.
1113     renderMatrix.scale3d(width, height, 1);
1114
1115     // Apply the projection matrix before sending the transform over to the shader.
1116     toGLMatrix(&glMatrix[0], m_projectionMatrix * renderMatrix);
1117
1118     GLC(m_context, m_context->uniformMatrix4fv(matrixLocation, 1, false, &glMatrix[0]));
1119
1120     if (quadLocation != -1) {
1121         float point[8];
1122         point[0] = quad.p1().x();
1123         point[1] = quad.p1().y();
1124         point[2] = quad.p2().x();
1125         point[3] = quad.p2().y();
1126         point[4] = quad.p3().x();
1127         point[5] = quad.p3().y();
1128         point[6] = quad.p4().x();
1129         point[7] = quad.p4().y();
1130         GLC(m_context, m_context->uniform2fv(quadLocation, 4, point));
1131     }
1132
1133     if (alphaLocation != -1)
1134         GLC(m_context, m_context->uniform1f(alphaLocation, opacity));
1135
1136     GLC(m_context, m_context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0));
1137 }
1138
1139 void LayerRendererChromium::finish()
1140 {
1141     TRACE_EVENT("LayerRendererChromium::finish", this, 0);
1142     m_context->finish();
1143 }
1144
1145 bool LayerRendererChromium::swapBuffers(const IntRect& subBuffer)
1146 {
1147     // FIXME: Remove this once gpu process supports ignoring swap buffers command while framebuffer is discarded.
1148     //        Alternatively (preferably?), protect all cc code so as not to attempt a swap after a framebuffer discard.
1149     if (m_isFramebufferDiscarded) {
1150         m_client->setFullRootLayerDamage();
1151         return false;
1152     }
1153
1154     TRACE_EVENT("LayerRendererChromium::swapBuffers", this, 0);
1155     // We're done! Time to swapbuffers!
1156
1157     if (m_capabilities.usingPartialSwap) {
1158         // If supported, we can save significant bandwidth by only swapping the damaged/scissored region (clamped to the viewport)
1159         IntRect clippedSubBuffer = subBuffer;
1160         clippedSubBuffer.intersect(IntRect(IntPoint::zero(), viewportSize()));
1161         Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(m_context->getExtensions());
1162         int flippedYPosOfRectBottom = viewportHeight() - clippedSubBuffer.y() - clippedSubBuffer.height();
1163         extensions3DChromium->postSubBufferCHROMIUM(clippedSubBuffer.x(), flippedYPosOfRectBottom, clippedSubBuffer.width(), clippedSubBuffer.height());
1164     } else
1165         // Note that currently this has the same effect as swapBuffers; we should
1166         // consider exposing a different entry point on GraphicsContext3D.
1167         m_context->prepareTexture();
1168
1169     return true;
1170 }
1171
1172 void LayerRendererChromium::onSwapBuffersComplete()
1173 {
1174     m_client->onSwapBuffersComplete();
1175 }
1176
1177 void LayerRendererChromium::discardFramebuffer()
1178 {
1179     if (m_isFramebufferDiscarded)
1180         return;
1181
1182     if (!m_capabilities.usingDiscardFramebuffer)
1183         return;
1184
1185     Extensions3D* extensions = m_context->getExtensions();
1186     Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
1187     // FIXME: Update attachments argument to appropriate values once they are no longer ignored.
1188     extensions3DChromium->discardFramebufferEXT(GraphicsContext3D::TEXTURE_2D, 0, 0);
1189     m_isFramebufferDiscarded = true;
1190
1191     // Damage tracker needs a full reset every time framebuffer is discarded.
1192     m_client->setFullRootLayerDamage();
1193 }
1194
1195 void LayerRendererChromium::ensureFramebuffer()
1196 {
1197     if (!m_isFramebufferDiscarded)
1198         return;
1199
1200     if (!m_capabilities.usingDiscardFramebuffer)
1201         return;
1202
1203     Extensions3D* extensions = m_context->getExtensions();
1204     Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
1205     extensions3DChromium->ensureFramebufferCHROMIUM();
1206     m_isFramebufferDiscarded = false;
1207 }
1208
1209 void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect)
1210 {
1211     ASSERT(rect.maxX() <= viewportWidth() && rect.maxY() <= viewportHeight());
1212
1213     if (!pixels)
1214         return;
1215
1216     makeContextCurrent();
1217
1218     bool doWorkaround = needsLionIOSurfaceReadbackWorkaround();
1219
1220     Platform3DObject temporaryTexture = NullPlatform3DObject;
1221     Platform3DObject temporaryFBO = NullPlatform3DObject;
1222     GraphicsContext3D* context = m_context.get();
1223
1224     if (doWorkaround) {
1225         // On Mac OS X 10.7, calling glReadPixels against an FBO whose color attachment is an
1226         // IOSurface-backed texture causes corruption of future glReadPixels calls, even those on
1227         // different OpenGL contexts. It is believed that this is the root cause of top crasher
1228         // http://crbug.com/99393. <rdar://problem/10949687>
1229
1230         temporaryTexture = context->createTexture();
1231         GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, temporaryTexture));
1232         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
1233         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
1234         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
1235         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
1236         // Copy the contents of the current (IOSurface-backed) framebuffer into a temporary texture.
1237         GLC(context, context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 0, 0, rect.maxX(), rect.maxY(), 0));
1238         temporaryFBO = context->createFramebuffer();
1239         // Attach this texture to an FBO, and perform the readback from that FBO.
1240         GLC(context, context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, temporaryFBO));
1241         GLC(context, context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, temporaryTexture, 0));
1242
1243         ASSERT(context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) == GraphicsContext3D::FRAMEBUFFER_COMPLETE);
1244     }
1245
1246     GLC(context, context->readPixels(rect.x(), rect.y(), rect.width(), rect.height(),
1247                                      GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
1248
1249     if (doWorkaround) {
1250         // Clean up.
1251         GLC(context, context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
1252         GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0));
1253         GLC(context, context->deleteFramebuffer(temporaryFBO));
1254         GLC(context, context->deleteTexture(temporaryTexture));
1255     }
1256 }
1257
1258 bool LayerRendererChromium::getFramebufferTexture(ManagedTexture* texture, const IntRect& deviceRect)
1259 {
1260     if (!texture->reserve(deviceRect.size(), GraphicsContext3D::RGB))
1261         return false;
1262
1263     texture->bindTexture(m_context.get(), m_renderSurfaceTextureAllocator.get());
1264     GLC(m_context, m_context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, texture->format(),
1265                                              deviceRect.x(), deviceRect.y(), deviceRect.width(), deviceRect.height(), 0));
1266     return true;
1267 }
1268
1269 bool LayerRendererChromium::isCurrentRenderSurface(CCRenderSurface* renderSurface)
1270 {
1271     // If renderSurface is 0, we can't tell if we are already using it, since m_currentRenderSurface is
1272     // initialized to 0.
1273     return m_currentRenderSurface == renderSurface && !m_currentManagedTexture;
1274 }
1275
1276 bool LayerRendererChromium::useRenderSurface(CCRenderSurface* renderSurface)
1277 {
1278     m_currentRenderSurface = renderSurface;
1279     m_currentManagedTexture = 0;
1280
1281     if (renderSurface == m_defaultRenderSurface) {
1282         GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
1283         setDrawViewportRect(renderSurface->contentRect(), true);
1284         return true;
1285     }
1286
1287     if (!renderSurface->prepareContentsTexture(this))
1288         return false;
1289
1290     return bindFramebufferToTexture(renderSurface->contentsTexture(), renderSurface->contentRect());
1291 }
1292
1293 bool LayerRendererChromium::useManagedTexture(ManagedTexture* texture, const IntRect& viewportRect)
1294 {
1295     m_currentRenderSurface = 0;
1296     m_currentManagedTexture = texture;
1297
1298     return bindFramebufferToTexture(texture, viewportRect);
1299 }
1300
1301 bool LayerRendererChromium::bindFramebufferToTexture(ManagedTexture* texture, const IntRect& viewportRect)
1302 {
1303     GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId));
1304
1305     texture->framebufferTexture2D(m_context.get(), m_renderSurfaceTextureAllocator.get());
1306
1307 #if !defined ( NDEBUG )
1308     if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
1309         ASSERT_NOT_REACHED();
1310         return false;
1311     }
1312 #endif
1313
1314     setDrawViewportRect(viewportRect, false);
1315
1316     return true;
1317 }
1318
1319 // Sets the scissor region to the given rectangle. The coordinate system for the
1320 // scissorRect has its origin at the top left corner of the current visible rect.
1321 void LayerRendererChromium::setScissorToRect(const IntRect& scissorRect)
1322 {
1323     IntRect contentRect = (m_currentRenderSurface ? m_currentRenderSurface->contentRect() : m_defaultRenderSurface->contentRect());
1324
1325     GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST));
1326
1327     // The scissor coordinates must be supplied in viewport space so we need to offset
1328     // by the relative position of the top left corner of the current render surface.
1329     int scissorX = scissorRect.x() - contentRect.x();
1330     // When rendering to the default render surface we're rendering upside down so the top
1331     // of the GL scissor is the bottom of our layer.
1332     // But, if rendering to offscreen texture, we reverse our sense of 'upside down'.
1333     int scissorY;
1334     if (isCurrentRenderSurface(m_defaultRenderSurface))
1335         scissorY = m_currentRenderSurface->contentRect().height() - (scissorRect.maxY() - m_currentRenderSurface->contentRect().y());
1336     else
1337         scissorY = scissorRect.y() - contentRect.y();
1338     GLC(m_context, m_context->scissor(scissorX, scissorY, scissorRect.width(), scissorRect.height()));
1339 }
1340
1341 bool LayerRendererChromium::makeContextCurrent()
1342 {
1343     return m_context->makeContextCurrent();
1344 }
1345
1346 // Sets the coordinate range of content that ends being drawn onto the target render surface.
1347 // The target render surface is assumed to have an origin at 0, 0 and the width and height of
1348 // of the drawRect.
1349 void LayerRendererChromium::setDrawViewportRect(const IntRect& drawRect, bool flipY)
1350 {
1351     if (flipY)
1352         m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.maxY(), drawRect.y());
1353     else
1354         m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.y(), drawRect.maxY());
1355     GLC(m_context, m_context->viewport(0, 0, drawRect.width(), drawRect.height()));
1356     m_windowMatrix = screenMatrix(0, 0, drawRect.width(), drawRect.height());
1357 }
1358
1359
1360 bool LayerRendererChromium::initializeSharedObjects()
1361 {
1362     TRACE_EVENT("LayerRendererChromium::initializeSharedObjects", this, 0);
1363     makeContextCurrent();
1364
1365     // Create an FBO for doing offscreen rendering.
1366     GLC(m_context, m_offscreenFramebufferId = m_context->createFramebuffer());
1367
1368     // We will always need these programs to render, so create the programs eagerly so that the shader compilation can
1369     // start while we do other work. Other programs are created lazily on first access.
1370     m_sharedGeometry = adoptPtr(new GeometryBinding(m_context.get()));
1371     m_renderSurfaceProgram = adoptPtr(new RenderSurfaceProgram(m_context.get()));
1372     m_tileProgram = adoptPtr(new TileProgram(m_context.get()));
1373     m_tileProgramOpaque = adoptPtr(new TileProgramOpaque(m_context.get()));
1374
1375     GLC(m_context, m_context->flush());
1376
1377     m_renderSurfaceTextureManager = TextureManager::create(TextureManager::highLimitBytes(viewportSize()),
1378                                                            TextureManager::reclaimLimitBytes(viewportSize()),
1379                                                            m_capabilities.maxTextureSize);
1380     m_textureCopier = AcceleratedTextureCopier::create(m_context.get());
1381     m_textureUploader = AcceleratedTextureUploader::create(m_context.get());
1382     m_contentsTextureAllocator = TrackingTextureAllocator::create(m_context.get());
1383     m_renderSurfaceTextureAllocator = TrackingTextureAllocator::create(m_context.get());
1384     if (m_capabilities.usingTextureUsageHint)
1385         m_renderSurfaceTextureAllocator->setTextureUsageHint(TrackingTextureAllocator::FramebufferAttachment);
1386     if (m_capabilities.usingTextureStorageExtension) {
1387         m_contentsTextureAllocator->setUseTextureStorageExt(true);
1388         m_renderSurfaceTextureAllocator->setUseTextureStorageExt(true);
1389     }
1390
1391     return true;
1392 }
1393
1394 const LayerRendererChromium::TileCheckerboardProgram* LayerRendererChromium::tileCheckerboardProgram()
1395 {
1396     if (!m_tileCheckerboardProgram)
1397         m_tileCheckerboardProgram = adoptPtr(new TileCheckerboardProgram(m_context.get()));
1398     if (!m_tileCheckerboardProgram->initialized()) {
1399         TRACE_EVENT("LayerRendererChromium::checkerboardProgram::initalize", this, 0);
1400         m_tileCheckerboardProgram->initialize(m_context.get());
1401     }
1402     return m_tileCheckerboardProgram.get();
1403 }
1404
1405 const LayerRendererChromium::SolidColorProgram* LayerRendererChromium::solidColorProgram()
1406 {
1407     if (!m_solidColorProgram)
1408         m_solidColorProgram = adoptPtr(new SolidColorProgram(m_context.get()));
1409     if (!m_solidColorProgram->initialized()) {
1410         TRACE_EVENT("LayerRendererChromium::solidColorProgram::initialize", this, 0);
1411         m_solidColorProgram->initialize(m_context.get());
1412     }
1413     return m_solidColorProgram.get();
1414 }
1415
1416 const LayerRendererChromium::HeadsUpDisplayProgram* LayerRendererChromium::headsUpDisplayProgram()
1417 {
1418     if (!m_headsUpDisplayProgram)
1419         m_headsUpDisplayProgram = adoptPtr(new HeadsUpDisplayProgram(m_context.get()));
1420     if (!m_headsUpDisplayProgram->initialized()) {
1421         TRACE_EVENT("LayerRendererChromium::headsUpDisplayProgram::initialize", this, 0);
1422         m_headsUpDisplayProgram->initialize(m_context.get());
1423     }
1424     return m_headsUpDisplayProgram.get();
1425 }
1426
1427 const LayerRendererChromium::RenderSurfaceProgram* LayerRendererChromium::renderSurfaceProgram()
1428 {
1429     ASSERT(m_renderSurfaceProgram);
1430     if (!m_renderSurfaceProgram->initialized()) {
1431         TRACE_EVENT("LayerRendererChromium::renderSurfaceProgram::initialize", this, 0);
1432         m_renderSurfaceProgram->initialize(m_context.get());
1433     }
1434     return m_renderSurfaceProgram.get();
1435 }
1436
1437 const LayerRendererChromium::RenderSurfaceProgramAA* LayerRendererChromium::renderSurfaceProgramAA()
1438 {
1439     if (!m_renderSurfaceProgramAA)
1440         m_renderSurfaceProgramAA = adoptPtr(new RenderSurfaceProgramAA(m_context.get()));
1441     if (!m_renderSurfaceProgramAA->initialized()) {
1442         TRACE_EVENT("LayerRendererChromium::renderSurfaceProgramAA::initialize", this, 0);
1443         m_renderSurfaceProgramAA->initialize(m_context.get());
1444     }
1445     return m_renderSurfaceProgramAA.get();
1446 }
1447
1448 const LayerRendererChromium::RenderSurfaceMaskProgram* LayerRendererChromium::renderSurfaceMaskProgram()
1449 {
1450     if (!m_renderSurfaceMaskProgram)
1451         m_renderSurfaceMaskProgram = adoptPtr(new RenderSurfaceMaskProgram(m_context.get()));
1452     if (!m_renderSurfaceMaskProgram->initialized()) {
1453         TRACE_EVENT("LayerRendererChromium::renderSurfaceMaskProgram::initialize", this, 0);
1454         m_renderSurfaceMaskProgram->initialize(m_context.get());
1455     }
1456     return m_renderSurfaceMaskProgram.get();
1457 }
1458
1459 const LayerRendererChromium::RenderSurfaceMaskProgramAA* LayerRendererChromium::renderSurfaceMaskProgramAA()
1460 {
1461     if (!m_renderSurfaceMaskProgramAA)
1462         m_renderSurfaceMaskProgramAA = adoptPtr(new RenderSurfaceMaskProgramAA(m_context.get()));
1463     if (!m_renderSurfaceMaskProgramAA->initialized()) {
1464         TRACE_EVENT("LayerRendererChromium::renderSurfaceMaskProgramAA::initialize", this, 0);
1465         m_renderSurfaceMaskProgramAA->initialize(m_context.get());
1466     }
1467     return m_renderSurfaceMaskProgramAA.get();
1468 }
1469
1470 const LayerRendererChromium::TileProgram* LayerRendererChromium::tileProgram()
1471 {
1472     ASSERT(m_tileProgram);
1473     if (!m_tileProgram->initialized()) {
1474         TRACE_EVENT("LayerRendererChromium::tileProgram::initialize", this, 0);
1475         m_tileProgram->initialize(m_context.get());
1476     }
1477     return m_tileProgram.get();
1478 }
1479
1480 const LayerRendererChromium::TileProgramOpaque* LayerRendererChromium::tileProgramOpaque()
1481 {
1482     ASSERT(m_tileProgramOpaque);
1483     if (!m_tileProgramOpaque->initialized()) {
1484         TRACE_EVENT("LayerRendererChromium::tileProgramOpaque::initialize", this, 0);
1485         m_tileProgramOpaque->initialize(m_context.get());
1486     }
1487     return m_tileProgramOpaque.get();
1488 }
1489
1490 const LayerRendererChromium::TileProgramAA* LayerRendererChromium::tileProgramAA()
1491 {
1492     if (!m_tileProgramAA)
1493         m_tileProgramAA = adoptPtr(new TileProgramAA(m_context.get()));
1494     if (!m_tileProgramAA->initialized()) {
1495         TRACE_EVENT("LayerRendererChromium::tileProgramAA::initialize", this, 0);
1496         m_tileProgramAA->initialize(m_context.get());
1497     }
1498     return m_tileProgramAA.get();
1499 }
1500
1501 const LayerRendererChromium::TileProgramSwizzle* LayerRendererChromium::tileProgramSwizzle()
1502 {
1503     if (!m_tileProgramSwizzle)
1504         m_tileProgramSwizzle = adoptPtr(new TileProgramSwizzle(m_context.get()));
1505     if (!m_tileProgramSwizzle->initialized()) {
1506         TRACE_EVENT("LayerRendererChromium::tileProgramSwizzle::initialize", this, 0);
1507         m_tileProgramSwizzle->initialize(m_context.get());
1508     }
1509     return m_tileProgramSwizzle.get();
1510 }
1511
1512 const LayerRendererChromium::TileProgramSwizzleOpaque* LayerRendererChromium::tileProgramSwizzleOpaque()
1513 {
1514     if (!m_tileProgramSwizzleOpaque)
1515         m_tileProgramSwizzleOpaque = adoptPtr(new TileProgramSwizzleOpaque(m_context.get()));
1516     if (!m_tileProgramSwizzleOpaque->initialized()) {
1517         TRACE_EVENT("LayerRendererChromium::tileProgramSwizzleOpaque::initialize", this, 0);
1518         m_tileProgramSwizzleOpaque->initialize(m_context.get());
1519     }
1520     return m_tileProgramSwizzleOpaque.get();
1521 }
1522
1523 const LayerRendererChromium::TileProgramSwizzleAA* LayerRendererChromium::tileProgramSwizzleAA()
1524 {
1525     if (!m_tileProgramSwizzleAA)
1526         m_tileProgramSwizzleAA = adoptPtr(new TileProgramSwizzleAA(m_context.get()));
1527     if (!m_tileProgramSwizzleAA->initialized()) {
1528         TRACE_EVENT("LayerRendererChromium::tileProgramSwizzleAA::initialize", this, 0);
1529         m_tileProgramSwizzleAA->initialize(m_context.get());
1530     }
1531     return m_tileProgramSwizzleAA.get();
1532 }
1533
1534 const LayerRendererChromium::TextureProgram* LayerRendererChromium::textureProgram()
1535 {
1536     if (!m_textureProgram)
1537         m_textureProgram = adoptPtr(new TextureProgram(m_context.get()));
1538     if (!m_textureProgram->initialized()) {
1539         TRACE_EVENT("LayerRendererChromium::textureProgram::initialize", this, 0);
1540         m_textureProgram->initialize(m_context.get());
1541     }
1542     return m_textureProgram.get();
1543 }
1544
1545 const LayerRendererChromium::TextureProgramFlip* LayerRendererChromium::textureProgramFlip()
1546 {
1547     if (!m_textureProgramFlip)
1548         m_textureProgramFlip = adoptPtr(new TextureProgramFlip(m_context.get()));
1549     if (!m_textureProgramFlip->initialized()) {
1550         TRACE_EVENT("LayerRendererChromium::textureProgramFlip::initialize", this, 0);
1551         m_textureProgramFlip->initialize(m_context.get());
1552     }
1553     return m_textureProgramFlip.get();
1554 }
1555
1556 const LayerRendererChromium::TextureIOSurfaceProgram* LayerRendererChromium::textureIOSurfaceProgram()
1557 {
1558     if (!m_textureIOSurfaceProgram)
1559         m_textureIOSurfaceProgram = adoptPtr(new TextureIOSurfaceProgram(m_context.get()));
1560     if (!m_textureIOSurfaceProgram->initialized()) {
1561         TRACE_EVENT("LayerRendererChromium::textureIOSurfaceProgram::initialize", this, 0);
1562         m_textureIOSurfaceProgram->initialize(m_context.get());
1563     }
1564     return m_textureIOSurfaceProgram.get();
1565 }
1566
1567 const LayerRendererChromium::VideoYUVProgram* LayerRendererChromium::videoYUVProgram()
1568 {
1569     if (!m_videoYUVProgram)
1570         m_videoYUVProgram = adoptPtr(new VideoYUVProgram(m_context.get()));
1571     if (!m_videoYUVProgram->initialized()) {
1572         TRACE_EVENT("LayerRendererChromium::videoYUVProgram::initialize", this, 0);
1573         m_videoYUVProgram->initialize(m_context.get());
1574     }
1575     return m_videoYUVProgram.get();
1576 }
1577
1578 const LayerRendererChromium::VideoStreamTextureProgram* LayerRendererChromium::videoStreamTextureProgram()
1579 {
1580     if (!m_videoStreamTextureProgram)
1581         m_videoStreamTextureProgram = adoptPtr(new VideoStreamTextureProgram(m_context.get()));
1582     if (!m_videoStreamTextureProgram->initialized()) {
1583         TRACE_EVENT("LayerRendererChromium::streamTextureProgram::initialize", this, 0);
1584         m_videoStreamTextureProgram->initialize(m_context.get());
1585     }
1586     return m_videoStreamTextureProgram.get();
1587 }
1588
1589 void LayerRendererChromium::cleanupSharedObjects()
1590 {
1591     makeContextCurrent();
1592
1593     m_sharedGeometry.clear();
1594
1595     if (m_tileProgram)
1596         m_tileProgram->cleanup(m_context.get());
1597     if (m_tileProgramOpaque)
1598         m_tileProgramOpaque->cleanup(m_context.get());
1599     if (m_tileProgramSwizzle)
1600         m_tileProgramSwizzle->cleanup(m_context.get());
1601     if (m_tileProgramSwizzleOpaque)
1602         m_tileProgramSwizzleOpaque->cleanup(m_context.get());
1603     if (m_tileProgramAA)
1604         m_tileProgramAA->cleanup(m_context.get());
1605     if (m_tileProgramSwizzleAA)
1606         m_tileProgramSwizzleAA->cleanup(m_context.get());
1607     if (m_tileCheckerboardProgram)
1608         m_tileCheckerboardProgram->cleanup(m_context.get());
1609
1610     if (m_renderSurfaceMaskProgram)
1611         m_renderSurfaceMaskProgram->cleanup(m_context.get());
1612     if (m_renderSurfaceProgram)
1613         m_renderSurfaceProgram->cleanup(m_context.get());
1614     if (m_renderSurfaceMaskProgramAA)
1615         m_renderSurfaceMaskProgramAA->cleanup(m_context.get());
1616     if (m_renderSurfaceProgramAA)
1617         m_renderSurfaceProgramAA->cleanup(m_context.get());
1618
1619     if (m_textureProgram)
1620         m_textureProgram->cleanup(m_context.get());
1621     if (m_textureProgramFlip)
1622         m_textureProgramFlip->cleanup(m_context.get());
1623     if (m_textureIOSurfaceProgram)
1624         m_textureIOSurfaceProgram->cleanup(m_context.get());
1625
1626     if (m_videoYUVProgram)
1627         m_videoYUVProgram->cleanup(m_context.get());
1628     if (m_videoStreamTextureProgram)
1629         m_videoStreamTextureProgram->cleanup(m_context.get());
1630
1631     if (m_solidColorProgram)
1632         m_solidColorProgram->cleanup(m_context.get());
1633
1634     if (m_headsUpDisplayProgram)
1635         m_headsUpDisplayProgram->cleanup(m_context.get());
1636
1637     if (m_offscreenFramebufferId)
1638         GLC(m_context, m_context->deleteFramebuffer(m_offscreenFramebufferId));
1639
1640     m_textureCopier.clear();
1641     m_textureUploader.clear();
1642
1643     releaseRenderSurfaceTextures();
1644 }
1645
1646 bool LayerRendererChromium::isContextLost()
1647 {
1648     return (m_context.get()->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR);
1649 }
1650
1651 } // namespace WebCore
1652
1653 #endif // USE(ACCELERATED_COMPOSITING)