0afcae82b80d3af7e8453b133e16b222a70bb294
[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     if (quad->flipped())
1027         binding.set(textureIOSurfaceProgramFlip());
1028     else
1029         binding.set(textureIOSurfaceProgram());
1030
1031     GLC(context(), context()->useProgram(binding.programId));
1032     GLC(context(), context()->uniform1i(binding.samplerLocation, 0));
1033     GLC(context(), context()->uniform4f(binding.texTransformLocation, 0, 0, quad->ioSurfaceSize().width(), quad->ioSurfaceSize().height()));
1034
1035     GLC(context(), context()->activeTexture(GraphicsContext3D::TEXTURE0));
1036     GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, quad->ioSurfaceTextureId()));
1037
1038     // FIXME: setting the texture parameters every time is redundant. Move this code somewhere
1039     // where it will only happen once per texture.
1040     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
1041     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
1042     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
1043     GLC(context(), context()->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
1044
1045     const IntSize& bounds = quad->quadRect().size();
1046
1047     drawTexturedQuad(quad->layerTransform(), bounds.width(), bounds.height(), quad->opacity(), sharedGeometryQuad(), binding.matrixLocation, binding.alphaLocation, -1);
1048
1049     GLC(context(), context()->bindTexture(Extensions3D::TEXTURE_RECTANGLE_ARB, 0));
1050 }
1051
1052 void LayerRendererChromium::drawHeadsUpDisplay(ManagedTexture* hudTexture, const IntSize& hudSize)
1053 {
1054     GLC(m_context, m_context->enable(GraphicsContext3D::BLEND));
1055     GLC(m_context, m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
1056     GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
1057     useRenderSurface(m_defaultRenderSurface);
1058
1059     const HeadsUpDisplayProgram* program = headsUpDisplayProgram();
1060     ASSERT(program && program->initialized());
1061     GLC(m_context, m_context->activeTexture(GraphicsContext3D::TEXTURE0));
1062     hudTexture->bindTexture(m_context.get(), renderSurfaceTextureAllocator());
1063     GLC(m_context, m_context->useProgram(program->program()));
1064     GLC(m_context, m_context->uniform1i(program->fragmentShader().samplerLocation(), 0));
1065
1066     TransformationMatrix matrix;
1067     matrix.translate3d(hudSize.width() * 0.5, hudSize.height() * 0.5, 0);
1068     drawTexturedQuad(matrix, hudSize.width(), hudSize.height(),
1069                      1, sharedGeometryQuad(), program->vertexShader().matrixLocation(),
1070                      program->fragmentShader().alphaLocation(),
1071                      -1);
1072 }
1073
1074 void LayerRendererChromium::finishDrawingFrame()
1075 {
1076     GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
1077     GLC(m_context, m_context->disable(GraphicsContext3D::BLEND));
1078
1079     size_t contentsMemoryUseBytes = m_contentsTextureAllocator->currentMemoryUseBytes();
1080     size_t reclaimLimit = TextureManager::reclaimLimitBytes(viewportSize());
1081     size_t preferredLimit = reclaimLimit > contentsMemoryUseBytes ? reclaimLimit - contentsMemoryUseBytes : 0;
1082     m_renderSurfaceTextureManager->setPreferredMemoryLimitBytes(preferredLimit);
1083     m_renderSurfaceTextureManager->reduceMemoryToLimit(preferredLimit);
1084     m_renderSurfaceTextureManager->deleteEvictedTextures(m_renderSurfaceTextureAllocator.get());
1085 }
1086
1087 void LayerRendererChromium::toGLMatrix(float* flattened, const TransformationMatrix& m)
1088 {
1089     flattened[0] = m.m11();
1090     flattened[1] = m.m12();
1091     flattened[2] = m.m13();
1092     flattened[3] = m.m14();
1093     flattened[4] = m.m21();
1094     flattened[5] = m.m22();
1095     flattened[6] = m.m23();
1096     flattened[7] = m.m24();
1097     flattened[8] = m.m31();
1098     flattened[9] = m.m32();
1099     flattened[10] = m.m33();
1100     flattened[11] = m.m34();
1101     flattened[12] = m.m41();
1102     flattened[13] = m.m42();
1103     flattened[14] = m.m43();
1104     flattened[15] = m.m44();
1105 }
1106
1107 void LayerRendererChromium::drawTexturedQuad(const TransformationMatrix& drawMatrix,
1108                                              float width, float height, float opacity, const FloatQuad& quad,
1109                                              int matrixLocation, int alphaLocation, int quadLocation)
1110 {
1111     static float glMatrix[16];
1112
1113     TransformationMatrix renderMatrix = drawMatrix;
1114
1115     // Apply a scaling factor to size the quad from 1x1 to its intended size.
1116     renderMatrix.scale3d(width, height, 1);
1117
1118     // Apply the projection matrix before sending the transform over to the shader.
1119     toGLMatrix(&glMatrix[0], m_projectionMatrix * renderMatrix);
1120
1121     GLC(m_context, m_context->uniformMatrix4fv(matrixLocation, 1, false, &glMatrix[0]));
1122
1123     if (quadLocation != -1) {
1124         float point[8];
1125         point[0] = quad.p1().x();
1126         point[1] = quad.p1().y();
1127         point[2] = quad.p2().x();
1128         point[3] = quad.p2().y();
1129         point[4] = quad.p3().x();
1130         point[5] = quad.p3().y();
1131         point[6] = quad.p4().x();
1132         point[7] = quad.p4().y();
1133         GLC(m_context, m_context->uniform2fv(quadLocation, 4, point));
1134     }
1135
1136     if (alphaLocation != -1)
1137         GLC(m_context, m_context->uniform1f(alphaLocation, opacity));
1138
1139     GLC(m_context, m_context->drawElements(GraphicsContext3D::TRIANGLES, 6, GraphicsContext3D::UNSIGNED_SHORT, 0));
1140 }
1141
1142 void LayerRendererChromium::finish()
1143 {
1144     TRACE_EVENT("LayerRendererChromium::finish", this, 0);
1145     m_context->finish();
1146 }
1147
1148 bool LayerRendererChromium::swapBuffers(const IntRect& subBuffer)
1149 {
1150     // FIXME: Remove this once gpu process supports ignoring swap buffers command while framebuffer is discarded.
1151     //        Alternatively (preferably?), protect all cc code so as not to attempt a swap after a framebuffer discard.
1152     if (m_isFramebufferDiscarded) {
1153         m_client->setFullRootLayerDamage();
1154         return false;
1155     }
1156
1157     TRACE_EVENT("LayerRendererChromium::swapBuffers", this, 0);
1158     // We're done! Time to swapbuffers!
1159
1160     if (m_capabilities.usingPartialSwap) {
1161         // If supported, we can save significant bandwidth by only swapping the damaged/scissored region (clamped to the viewport)
1162         IntRect clippedSubBuffer = subBuffer;
1163         clippedSubBuffer.intersect(IntRect(IntPoint::zero(), viewportSize()));
1164         Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(m_context->getExtensions());
1165         int flippedYPosOfRectBottom = viewportHeight() - clippedSubBuffer.y() - clippedSubBuffer.height();
1166         extensions3DChromium->postSubBufferCHROMIUM(clippedSubBuffer.x(), flippedYPosOfRectBottom, clippedSubBuffer.width(), clippedSubBuffer.height());
1167     } else
1168         // Note that currently this has the same effect as swapBuffers; we should
1169         // consider exposing a different entry point on GraphicsContext3D.
1170         m_context->prepareTexture();
1171
1172     return true;
1173 }
1174
1175 void LayerRendererChromium::onSwapBuffersComplete()
1176 {
1177     m_client->onSwapBuffersComplete();
1178 }
1179
1180 void LayerRendererChromium::discardFramebuffer()
1181 {
1182     if (m_isFramebufferDiscarded)
1183         return;
1184
1185     if (!m_capabilities.usingDiscardFramebuffer)
1186         return;
1187
1188     Extensions3D* extensions = m_context->getExtensions();
1189     Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
1190     // FIXME: Update attachments argument to appropriate values once they are no longer ignored.
1191     extensions3DChromium->discardFramebufferEXT(GraphicsContext3D::TEXTURE_2D, 0, 0);
1192     m_isFramebufferDiscarded = true;
1193
1194     // Damage tracker needs a full reset every time framebuffer is discarded.
1195     m_client->setFullRootLayerDamage();
1196 }
1197
1198 void LayerRendererChromium::ensureFramebuffer()
1199 {
1200     if (!m_isFramebufferDiscarded)
1201         return;
1202
1203     if (!m_capabilities.usingDiscardFramebuffer)
1204         return;
1205
1206     Extensions3D* extensions = m_context->getExtensions();
1207     Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
1208     extensions3DChromium->ensureFramebufferCHROMIUM();
1209     m_isFramebufferDiscarded = false;
1210 }
1211
1212 void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect)
1213 {
1214     ASSERT(rect.maxX() <= viewportWidth() && rect.maxY() <= viewportHeight());
1215
1216     if (!pixels)
1217         return;
1218
1219     makeContextCurrent();
1220
1221     bool doWorkaround = needsLionIOSurfaceReadbackWorkaround();
1222
1223     Platform3DObject temporaryTexture = NullPlatform3DObject;
1224     Platform3DObject temporaryFBO = NullPlatform3DObject;
1225     GraphicsContext3D* context = m_context.get();
1226
1227     if (doWorkaround) {
1228         // On Mac OS X 10.7, calling glReadPixels against an FBO whose color attachment is an
1229         // IOSurface-backed texture causes corruption of future glReadPixels calls, even those on
1230         // different OpenGL contexts. It is believed that this is the root cause of top crasher
1231         // http://crbug.com/99393. <rdar://problem/10949687>
1232
1233         temporaryTexture = context->createTexture();
1234         GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, temporaryTexture));
1235         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
1236         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
1237         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
1238         GLC(context, context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
1239         // Copy the contents of the current (IOSurface-backed) framebuffer into a temporary texture.
1240         GLC(context, context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 0, 0, rect.maxX(), rect.maxY(), 0));
1241         temporaryFBO = context->createFramebuffer();
1242         // Attach this texture to an FBO, and perform the readback from that FBO.
1243         GLC(context, context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, temporaryFBO));
1244         GLC(context, context->framebufferTexture2D(GraphicsContext3D::FRAMEBUFFER, GraphicsContext3D::COLOR_ATTACHMENT0, GraphicsContext3D::TEXTURE_2D, temporaryTexture, 0));
1245
1246         ASSERT(context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) == GraphicsContext3D::FRAMEBUFFER_COMPLETE);
1247     }
1248
1249     GLC(context, context->readPixels(rect.x(), rect.y(), rect.width(), rect.height(),
1250                                      GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
1251
1252     if (doWorkaround) {
1253         // Clean up.
1254         GLC(context, context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
1255         GLC(context, context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0));
1256         GLC(context, context->deleteFramebuffer(temporaryFBO));
1257         GLC(context, context->deleteTexture(temporaryTexture));
1258     }
1259 }
1260
1261 bool LayerRendererChromium::getFramebufferTexture(ManagedTexture* texture, const IntRect& deviceRect)
1262 {
1263     if (!texture->reserve(deviceRect.size(), GraphicsContext3D::RGB))
1264         return false;
1265
1266     texture->bindTexture(m_context.get(), m_renderSurfaceTextureAllocator.get());
1267     GLC(m_context, m_context->copyTexImage2D(GraphicsContext3D::TEXTURE_2D, 0, texture->format(),
1268                                              deviceRect.x(), deviceRect.y(), deviceRect.width(), deviceRect.height(), 0));
1269     return true;
1270 }
1271
1272 bool LayerRendererChromium::isCurrentRenderSurface(CCRenderSurface* renderSurface)
1273 {
1274     // If renderSurface is 0, we can't tell if we are already using it, since m_currentRenderSurface is
1275     // initialized to 0.
1276     return m_currentRenderSurface == renderSurface && !m_currentManagedTexture;
1277 }
1278
1279 bool LayerRendererChromium::useRenderSurface(CCRenderSurface* renderSurface)
1280 {
1281     m_currentRenderSurface = renderSurface;
1282     m_currentManagedTexture = 0;
1283
1284     if (renderSurface == m_defaultRenderSurface) {
1285         GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
1286         setDrawViewportRect(renderSurface->contentRect(), true);
1287         return true;
1288     }
1289
1290     if (!renderSurface->prepareContentsTexture(this))
1291         return false;
1292
1293     return bindFramebufferToTexture(renderSurface->contentsTexture(), renderSurface->contentRect());
1294 }
1295
1296 bool LayerRendererChromium::useManagedTexture(ManagedTexture* texture, const IntRect& viewportRect)
1297 {
1298     m_currentRenderSurface = 0;
1299     m_currentManagedTexture = texture;
1300
1301     return bindFramebufferToTexture(texture, viewportRect);
1302 }
1303
1304 bool LayerRendererChromium::bindFramebufferToTexture(ManagedTexture* texture, const IntRect& viewportRect)
1305 {
1306     GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId));
1307
1308     texture->framebufferTexture2D(m_context.get(), m_renderSurfaceTextureAllocator.get());
1309
1310 #if !defined ( NDEBUG )
1311     if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
1312         ASSERT_NOT_REACHED();
1313         return false;
1314     }
1315 #endif
1316
1317     setDrawViewportRect(viewportRect, false);
1318
1319     return true;
1320 }
1321
1322 // Sets the scissor region to the given rectangle. The coordinate system for the
1323 // scissorRect has its origin at the top left corner of the current visible rect.
1324 void LayerRendererChromium::setScissorToRect(const IntRect& scissorRect)
1325 {
1326     IntRect contentRect = (m_currentRenderSurface ? m_currentRenderSurface->contentRect() : m_defaultRenderSurface->contentRect());
1327
1328     GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST));
1329
1330     // The scissor coordinates must be supplied in viewport space so we need to offset
1331     // by the relative position of the top left corner of the current render surface.
1332     int scissorX = scissorRect.x() - contentRect.x();
1333     // When rendering to the default render surface we're rendering upside down so the top
1334     // of the GL scissor is the bottom of our layer.
1335     // But, if rendering to offscreen texture, we reverse our sense of 'upside down'.
1336     int scissorY;
1337     if (isCurrentRenderSurface(m_defaultRenderSurface))
1338         scissorY = m_currentRenderSurface->contentRect().height() - (scissorRect.maxY() - m_currentRenderSurface->contentRect().y());
1339     else
1340         scissorY = scissorRect.y() - contentRect.y();
1341     GLC(m_context, m_context->scissor(scissorX, scissorY, scissorRect.width(), scissorRect.height()));
1342 }
1343
1344 bool LayerRendererChromium::makeContextCurrent()
1345 {
1346     return m_context->makeContextCurrent();
1347 }
1348
1349 // Sets the coordinate range of content that ends being drawn onto the target render surface.
1350 // The target render surface is assumed to have an origin at 0, 0 and the width and height of
1351 // of the drawRect.
1352 void LayerRendererChromium::setDrawViewportRect(const IntRect& drawRect, bool flipY)
1353 {
1354     if (flipY)
1355         m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.maxY(), drawRect.y());
1356     else
1357         m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.y(), drawRect.maxY());
1358     GLC(m_context, m_context->viewport(0, 0, drawRect.width(), drawRect.height()));
1359     m_windowMatrix = screenMatrix(0, 0, drawRect.width(), drawRect.height());
1360 }
1361
1362
1363 bool LayerRendererChromium::initializeSharedObjects()
1364 {
1365     TRACE_EVENT("LayerRendererChromium::initializeSharedObjects", this, 0);
1366     makeContextCurrent();
1367
1368     // Create an FBO for doing offscreen rendering.
1369     GLC(m_context, m_offscreenFramebufferId = m_context->createFramebuffer());
1370
1371     // We will always need these programs to render, so create the programs eagerly so that the shader compilation can
1372     // start while we do other work. Other programs are created lazily on first access.
1373     m_sharedGeometry = adoptPtr(new GeometryBinding(m_context.get()));
1374     m_renderSurfaceProgram = adoptPtr(new RenderSurfaceProgram(m_context.get()));
1375     m_tileProgram = adoptPtr(new TileProgram(m_context.get()));
1376     m_tileProgramOpaque = adoptPtr(new TileProgramOpaque(m_context.get()));
1377
1378     GLC(m_context, m_context->flush());
1379
1380     m_renderSurfaceTextureManager = TextureManager::create(TextureManager::highLimitBytes(viewportSize()),
1381                                                            TextureManager::reclaimLimitBytes(viewportSize()),
1382                                                            m_capabilities.maxTextureSize);
1383     m_textureCopier = AcceleratedTextureCopier::create(m_context.get());
1384     m_textureUploader = AcceleratedTextureUploader::create(m_context.get());
1385     m_contentsTextureAllocator = TrackingTextureAllocator::create(m_context.get());
1386     m_renderSurfaceTextureAllocator = TrackingTextureAllocator::create(m_context.get());
1387     if (m_capabilities.usingTextureUsageHint)
1388         m_renderSurfaceTextureAllocator->setTextureUsageHint(TrackingTextureAllocator::FramebufferAttachment);
1389     if (m_capabilities.usingTextureStorageExtension) {
1390         m_contentsTextureAllocator->setUseTextureStorageExt(true);
1391         m_renderSurfaceTextureAllocator->setUseTextureStorageExt(true);
1392     }
1393
1394     return true;
1395 }
1396
1397 const LayerRendererChromium::TileCheckerboardProgram* LayerRendererChromium::tileCheckerboardProgram()
1398 {
1399     if (!m_tileCheckerboardProgram)
1400         m_tileCheckerboardProgram = adoptPtr(new TileCheckerboardProgram(m_context.get()));
1401     if (!m_tileCheckerboardProgram->initialized()) {
1402         TRACE_EVENT("LayerRendererChromium::checkerboardProgram::initalize", this, 0);
1403         m_tileCheckerboardProgram->initialize(m_context.get());
1404     }
1405     return m_tileCheckerboardProgram.get();
1406 }
1407
1408 const LayerRendererChromium::SolidColorProgram* LayerRendererChromium::solidColorProgram()
1409 {
1410     if (!m_solidColorProgram)
1411         m_solidColorProgram = adoptPtr(new SolidColorProgram(m_context.get()));
1412     if (!m_solidColorProgram->initialized()) {
1413         TRACE_EVENT("LayerRendererChromium::solidColorProgram::initialize", this, 0);
1414         m_solidColorProgram->initialize(m_context.get());
1415     }
1416     return m_solidColorProgram.get();
1417 }
1418
1419 const LayerRendererChromium::HeadsUpDisplayProgram* LayerRendererChromium::headsUpDisplayProgram()
1420 {
1421     if (!m_headsUpDisplayProgram)
1422         m_headsUpDisplayProgram = adoptPtr(new HeadsUpDisplayProgram(m_context.get()));
1423     if (!m_headsUpDisplayProgram->initialized()) {
1424         TRACE_EVENT("LayerRendererChromium::headsUpDisplayProgram::initialize", this, 0);
1425         m_headsUpDisplayProgram->initialize(m_context.get());
1426     }
1427     return m_headsUpDisplayProgram.get();
1428 }
1429
1430 const LayerRendererChromium::RenderSurfaceProgram* LayerRendererChromium::renderSurfaceProgram()
1431 {
1432     ASSERT(m_renderSurfaceProgram);
1433     if (!m_renderSurfaceProgram->initialized()) {
1434         TRACE_EVENT("LayerRendererChromium::renderSurfaceProgram::initialize", this, 0);
1435         m_renderSurfaceProgram->initialize(m_context.get());
1436     }
1437     return m_renderSurfaceProgram.get();
1438 }
1439
1440 const LayerRendererChromium::RenderSurfaceProgramAA* LayerRendererChromium::renderSurfaceProgramAA()
1441 {
1442     if (!m_renderSurfaceProgramAA)
1443         m_renderSurfaceProgramAA = adoptPtr(new RenderSurfaceProgramAA(m_context.get()));
1444     if (!m_renderSurfaceProgramAA->initialized()) {
1445         TRACE_EVENT("LayerRendererChromium::renderSurfaceProgramAA::initialize", this, 0);
1446         m_renderSurfaceProgramAA->initialize(m_context.get());
1447     }
1448     return m_renderSurfaceProgramAA.get();
1449 }
1450
1451 const LayerRendererChromium::RenderSurfaceMaskProgram* LayerRendererChromium::renderSurfaceMaskProgram()
1452 {
1453     if (!m_renderSurfaceMaskProgram)
1454         m_renderSurfaceMaskProgram = adoptPtr(new RenderSurfaceMaskProgram(m_context.get()));
1455     if (!m_renderSurfaceMaskProgram->initialized()) {
1456         TRACE_EVENT("LayerRendererChromium::renderSurfaceMaskProgram::initialize", this, 0);
1457         m_renderSurfaceMaskProgram->initialize(m_context.get());
1458     }
1459     return m_renderSurfaceMaskProgram.get();
1460 }
1461
1462 const LayerRendererChromium::RenderSurfaceMaskProgramAA* LayerRendererChromium::renderSurfaceMaskProgramAA()
1463 {
1464     if (!m_renderSurfaceMaskProgramAA)
1465         m_renderSurfaceMaskProgramAA = adoptPtr(new RenderSurfaceMaskProgramAA(m_context.get()));
1466     if (!m_renderSurfaceMaskProgramAA->initialized()) {
1467         TRACE_EVENT("LayerRendererChromium::renderSurfaceMaskProgramAA::initialize", this, 0);
1468         m_renderSurfaceMaskProgramAA->initialize(m_context.get());
1469     }
1470     return m_renderSurfaceMaskProgramAA.get();
1471 }
1472
1473 const LayerRendererChromium::TileProgram* LayerRendererChromium::tileProgram()
1474 {
1475     ASSERT(m_tileProgram);
1476     if (!m_tileProgram->initialized()) {
1477         TRACE_EVENT("LayerRendererChromium::tileProgram::initialize", this, 0);
1478         m_tileProgram->initialize(m_context.get());
1479     }
1480     return m_tileProgram.get();
1481 }
1482
1483 const LayerRendererChromium::TileProgramOpaque* LayerRendererChromium::tileProgramOpaque()
1484 {
1485     ASSERT(m_tileProgramOpaque);
1486     if (!m_tileProgramOpaque->initialized()) {
1487         TRACE_EVENT("LayerRendererChromium::tileProgramOpaque::initialize", this, 0);
1488         m_tileProgramOpaque->initialize(m_context.get());
1489     }
1490     return m_tileProgramOpaque.get();
1491 }
1492
1493 const LayerRendererChromium::TileProgramAA* LayerRendererChromium::tileProgramAA()
1494 {
1495     if (!m_tileProgramAA)
1496         m_tileProgramAA = adoptPtr(new TileProgramAA(m_context.get()));
1497     if (!m_tileProgramAA->initialized()) {
1498         TRACE_EVENT("LayerRendererChromium::tileProgramAA::initialize", this, 0);
1499         m_tileProgramAA->initialize(m_context.get());
1500     }
1501     return m_tileProgramAA.get();
1502 }
1503
1504 const LayerRendererChromium::TileProgramSwizzle* LayerRendererChromium::tileProgramSwizzle()
1505 {
1506     if (!m_tileProgramSwizzle)
1507         m_tileProgramSwizzle = adoptPtr(new TileProgramSwizzle(m_context.get()));
1508     if (!m_tileProgramSwizzle->initialized()) {
1509         TRACE_EVENT("LayerRendererChromium::tileProgramSwizzle::initialize", this, 0);
1510         m_tileProgramSwizzle->initialize(m_context.get());
1511     }
1512     return m_tileProgramSwizzle.get();
1513 }
1514
1515 const LayerRendererChromium::TileProgramSwizzleOpaque* LayerRendererChromium::tileProgramSwizzleOpaque()
1516 {
1517     if (!m_tileProgramSwizzleOpaque)
1518         m_tileProgramSwizzleOpaque = adoptPtr(new TileProgramSwizzleOpaque(m_context.get()));
1519     if (!m_tileProgramSwizzleOpaque->initialized()) {
1520         TRACE_EVENT("LayerRendererChromium::tileProgramSwizzleOpaque::initialize", this, 0);
1521         m_tileProgramSwizzleOpaque->initialize(m_context.get());
1522     }
1523     return m_tileProgramSwizzleOpaque.get();
1524 }
1525
1526 const LayerRendererChromium::TileProgramSwizzleAA* LayerRendererChromium::tileProgramSwizzleAA()
1527 {
1528     if (!m_tileProgramSwizzleAA)
1529         m_tileProgramSwizzleAA = adoptPtr(new TileProgramSwizzleAA(m_context.get()));
1530     if (!m_tileProgramSwizzleAA->initialized()) {
1531         TRACE_EVENT("LayerRendererChromium::tileProgramSwizzleAA::initialize", this, 0);
1532         m_tileProgramSwizzleAA->initialize(m_context.get());
1533     }
1534     return m_tileProgramSwizzleAA.get();
1535 }
1536
1537 const LayerRendererChromium::TextureProgram* LayerRendererChromium::textureProgram()
1538 {
1539     if (!m_textureProgram)
1540         m_textureProgram = adoptPtr(new TextureProgram(m_context.get()));
1541     if (!m_textureProgram->initialized()) {
1542         TRACE_EVENT("LayerRendererChromium::textureProgram::initialize", this, 0);
1543         m_textureProgram->initialize(m_context.get());
1544     }
1545     return m_textureProgram.get();
1546 }
1547
1548 const LayerRendererChromium::TextureProgramFlip* LayerRendererChromium::textureProgramFlip()
1549 {
1550     if (!m_textureProgramFlip)
1551         m_textureProgramFlip = adoptPtr(new TextureProgramFlip(m_context.get()));
1552     if (!m_textureProgramFlip->initialized()) {
1553         TRACE_EVENT("LayerRendererChromium::textureProgramFlip::initialize", this, 0);
1554         m_textureProgramFlip->initialize(m_context.get());
1555     }
1556     return m_textureProgramFlip.get();
1557 }
1558
1559 const LayerRendererChromium::TextureIOSurfaceProgram* LayerRendererChromium::textureIOSurfaceProgram()
1560 {
1561     if (!m_textureIOSurfaceProgram)
1562         m_textureIOSurfaceProgram = adoptPtr(new TextureIOSurfaceProgram(m_context.get()));
1563     if (!m_textureIOSurfaceProgram->initialized()) {
1564         TRACE_EVENT("LayerRendererChromium::textureIOSurfaceProgram::initialize", this, 0);
1565         m_textureIOSurfaceProgram->initialize(m_context.get());
1566     }
1567     return m_textureIOSurfaceProgram.get();
1568 }
1569
1570 const LayerRendererChromium::TextureIOSurfaceProgramFlip* LayerRendererChromium::textureIOSurfaceProgramFlip()
1571 {
1572     if (!m_textureIOSurfaceProgramFlip)
1573         m_textureIOSurfaceProgramFlip = adoptPtr(new TextureIOSurfaceProgramFlip(m_context.get()));
1574     if (!m_textureIOSurfaceProgramFlip->initialized()) {
1575         TRACE_EVENT("LayerRendererChromium::textureIOSurfaceProgramFlip::initialize", this, 0);
1576         m_textureIOSurfaceProgramFlip->initialize(m_context.get());
1577     }
1578     return m_textureIOSurfaceProgramFlip.get();
1579 }
1580
1581 const LayerRendererChromium::VideoYUVProgram* LayerRendererChromium::videoYUVProgram()
1582 {
1583     if (!m_videoYUVProgram)
1584         m_videoYUVProgram = adoptPtr(new VideoYUVProgram(m_context.get()));
1585     if (!m_videoYUVProgram->initialized()) {
1586         TRACE_EVENT("LayerRendererChromium::videoYUVProgram::initialize", this, 0);
1587         m_videoYUVProgram->initialize(m_context.get());
1588     }
1589     return m_videoYUVProgram.get();
1590 }
1591
1592 const LayerRendererChromium::VideoStreamTextureProgram* LayerRendererChromium::videoStreamTextureProgram()
1593 {
1594     if (!m_videoStreamTextureProgram)
1595         m_videoStreamTextureProgram = adoptPtr(new VideoStreamTextureProgram(m_context.get()));
1596     if (!m_videoStreamTextureProgram->initialized()) {
1597         TRACE_EVENT("LayerRendererChromium::streamTextureProgram::initialize", this, 0);
1598         m_videoStreamTextureProgram->initialize(m_context.get());
1599     }
1600     return m_videoStreamTextureProgram.get();
1601 }
1602
1603 void LayerRendererChromium::cleanupSharedObjects()
1604 {
1605     makeContextCurrent();
1606
1607     m_sharedGeometry.clear();
1608
1609     if (m_tileProgram)
1610         m_tileProgram->cleanup(m_context.get());
1611     if (m_tileProgramOpaque)
1612         m_tileProgramOpaque->cleanup(m_context.get());
1613     if (m_tileProgramSwizzle)
1614         m_tileProgramSwizzle->cleanup(m_context.get());
1615     if (m_tileProgramSwizzleOpaque)
1616         m_tileProgramSwizzleOpaque->cleanup(m_context.get());
1617     if (m_tileProgramAA)
1618         m_tileProgramAA->cleanup(m_context.get());
1619     if (m_tileProgramSwizzleAA)
1620         m_tileProgramSwizzleAA->cleanup(m_context.get());
1621     if (m_tileCheckerboardProgram)
1622         m_tileCheckerboardProgram->cleanup(m_context.get());
1623
1624     if (m_renderSurfaceMaskProgram)
1625         m_renderSurfaceMaskProgram->cleanup(m_context.get());
1626     if (m_renderSurfaceProgram)
1627         m_renderSurfaceProgram->cleanup(m_context.get());
1628     if (m_renderSurfaceMaskProgramAA)
1629         m_renderSurfaceMaskProgramAA->cleanup(m_context.get());
1630     if (m_renderSurfaceProgramAA)
1631         m_renderSurfaceProgramAA->cleanup(m_context.get());
1632
1633     if (m_textureProgram)
1634         m_textureProgram->cleanup(m_context.get());
1635     if (m_textureProgramFlip)
1636         m_textureProgramFlip->cleanup(m_context.get());
1637     if (m_textureIOSurfaceProgram)
1638         m_textureIOSurfaceProgram->cleanup(m_context.get());
1639     if (m_textureIOSurfaceProgramFlip)
1640         m_textureIOSurfaceProgramFlip->cleanup(m_context.get());
1641
1642     if (m_videoYUVProgram)
1643         m_videoYUVProgram->cleanup(m_context.get());
1644     if (m_videoStreamTextureProgram)
1645         m_videoStreamTextureProgram->cleanup(m_context.get());
1646
1647     if (m_solidColorProgram)
1648         m_solidColorProgram->cleanup(m_context.get());
1649
1650     if (m_headsUpDisplayProgram)
1651         m_headsUpDisplayProgram->cleanup(m_context.get());
1652
1653     if (m_offscreenFramebufferId)
1654         GLC(m_context, m_context->deleteFramebuffer(m_offscreenFramebufferId));
1655
1656     m_textureCopier.clear();
1657     m_textureUploader.clear();
1658
1659     releaseRenderSurfaceTextures();
1660 }
1661
1662 bool LayerRendererChromium::isContextLost()
1663 {
1664     return (m_context.get()->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR);
1665 }
1666
1667 } // namespace WebCore
1668
1669 #endif // USE(ACCELERATED_COMPOSITING)