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 "Canvas2DLayerChromium.h"
38#include "Extensions3DChromium.h"
39#include "FloatQuad.h"
40#include "GeometryBinding.h"
41#include "GraphicsContext3D.h"
42#include "LayerChromium.h"
43#include "LayerTexture.h"
44#include "NotImplemented.h"
45#include "TextStream.h"
46#include "TextureManager.h"
47#include "TraceEvent.h"
48#include "WebGLLayerChromium.h"
49#include "cc/CCLayerImpl.h"
50#if USE(SKIA)
51#include "NativeImageSkia.h"
52#include "PlatformContextSkia.h"
53#elif USE(CG)
54#include <CoreGraphics/CGBitmapContext.h>
55#endif
56
57namespace WebCore {
58
59// FIXME: Make this limit adjustable and give it a useful value.
60static size_t textureMemoryLimitBytes = 64 * 1024 * 1024;
61
62static TransformationMatrix orthoMatrix(float left, float right, float bottom, float top)
63{
64    float deltaX = right - left;
65    float deltaY = top - bottom;
66    TransformationMatrix ortho;
67    if (!deltaX || !deltaY)
68        return ortho;
69    ortho.setM11(2.0f / deltaX);
70    ortho.setM41(-(right + left) / deltaX);
71    ortho.setM22(2.0f / deltaY);
72    ortho.setM42(-(top + bottom) / deltaY);
73
74    // Z component of vertices is always set to zero as we don't use the depth buffer
75    // while drawing.
76    ortho.setM33(0);
77
78    return ortho;
79}
80
81// Returns true if the matrix has no rotation, skew or perspective components to it.
82static bool isScaleOrTranslation(const TransformationMatrix& m)
83{
84    return !m.m12() && !m.m13() && !m.m14()
85           && !m.m21() && !m.m23() && !m.m24()
86           && !m.m31() && !m.m32() && !m.m43()
87           && m.m44();
88
89}
90
91bool LayerRendererChromium::compareLayerZ(const RefPtr<CCLayerImpl>& a, const RefPtr<CCLayerImpl>& b)
92{
93    return a->drawDepth() < b->drawDepth();
94}
95
96PassRefPtr<LayerRendererChromium> LayerRendererChromium::create(PassRefPtr<GraphicsContext3D> context, PassOwnPtr<TilePaintInterface> contentPaint)
97{
98    if (!context)
99        return 0;
100
101    RefPtr<LayerRendererChromium> layerRenderer(adoptRef(new LayerRendererChromium(context, contentPaint)));
102    if (!layerRenderer->hardwareCompositing())
103        return 0;
104
105    return layerRenderer.release();
106}
107
108LayerRendererChromium::LayerRendererChromium(PassRefPtr<GraphicsContext3D> context,
109                                             PassOwnPtr<TilePaintInterface> contentPaint)
110    : m_viewportScrollPosition(IntPoint(-1, -1))
111    , m_rootLayer(0)
112    , m_rootLayerContentPaint(contentPaint)
113    , m_currentShader(0)
114    , m_currentRenderSurface(0)
115    , m_offscreenFramebufferId(0)
116    , m_compositeOffscreen(false)
117    , m_context(context)
118    , m_childContextsWereCopied(false)
119    , m_contextSupportsLatch(false)
120    , m_defaultRenderSurface(0)
121{
122    m_contextSupportsLatch = m_context->getExtensions()->supports("GL_CHROMIUM_latch");
123    m_hardwareCompositing = initializeSharedObjects();
124    m_rootLayerContentTiler = LayerTilerChromium::create(this, IntSize(256, 256), LayerTilerChromium::NoBorderTexels);
125    ASSERT(m_rootLayerContentTiler);
126
127    m_headsUpDisplay = CCHeadsUpDisplay::create(this);
128}
129
130LayerRendererChromium::~LayerRendererChromium()
131{
132    m_headsUpDisplay.clear(); // Explicitly destroy the HUD before the TextureManager dies.
133    cleanupSharedObjects();
134}
135
136GraphicsContext3D* LayerRendererChromium::context()
137{
138    return m_context.get();
139}
140
141void LayerRendererChromium::debugGLCall(GraphicsContext3D* context, const char* command, const char* file, int line)
142{
143    unsigned long error = context->getError();
144    if (error != GraphicsContext3D::NO_ERROR)
145        LOG_ERROR("GL command failed: File: %s\n\tLine %d\n\tcommand: %s, error %x\n", file, line, command, static_cast<int>(error));
146}
147
148void LayerRendererChromium::useShader(unsigned programId)
149{
150    if (programId != m_currentShader) {
151        GLC(m_context.get(), m_context->useProgram(programId));
152        m_currentShader = programId;
153    }
154}
155
156void LayerRendererChromium::invalidateRootLayerRect(const IntRect& dirtyRect)
157{
158    m_rootLayerContentTiler->invalidateRect(dirtyRect);
159}
160
161void LayerRendererChromium::updateRootLayerContents()
162{
163    TRACE_EVENT("LayerRendererChromium::updateRootLayerContents", this, 0);
164    m_rootLayerContentTiler->update(*m_rootLayerContentPaint, m_viewportVisibleRect);
165}
166
167void LayerRendererChromium::drawRootLayer()
168{
169    TransformationMatrix scroll;
170    scroll.translate(-m_viewportVisibleRect.x(), -m_viewportVisibleRect.y());
171
172    m_rootLayerContentTiler->uploadCanvas();
173    m_rootLayerContentTiler->draw(m_viewportVisibleRect, scroll, 1.0f);
174}
175
176void LayerRendererChromium::setViewport(const IntRect& visibleRect, const IntRect& contentRect, const IntPoint& scrollPosition)
177{
178    bool visibleRectChanged = m_viewportVisibleRect.size() != visibleRect.size();
179
180    m_viewportVisibleRect = visibleRect;
181    m_viewportContentRect = contentRect;
182    m_viewportScrollPosition = scrollPosition;
183
184    if (visibleRectChanged) {
185        // Reset the current render surface to force an update of the viewport and
186        // projection matrix next time useRenderSurface is called.
187        m_currentRenderSurface = 0;
188        m_rootLayerContentTiler->invalidateEntireLayer();
189    }
190}
191
192void LayerRendererChromium::updateAndDrawLayers()
193{
194    ASSERT(m_hardwareCompositing);
195
196    if (!m_rootLayer)
197        return;
198
199    updateRootLayerContents();
200
201    // Recheck that we still have a root layer. This may become null if
202    // compositing gets turned off during a paint operation.
203    if (!m_rootLayer)
204        return;
205
206    LayerList renderSurfaceLayerList;
207
208    updateLayers(renderSurfaceLayerList);
209
210    // Before drawLayers:
211    if (hardwareCompositing() && m_contextSupportsLatch) {
212        // FIXME: The multithreaded compositor case will not work as long as
213        // copyTexImage2D resolves to the parent texture, because the main
214        // thread can execute WebGL calls on the child context at any time,
215        // potentially clobbering the parent texture that is being renderered
216        // by the compositor thread.
217        if (m_childContextsWereCopied) {
218            Extensions3DChromium* parentExt = static_cast<Extensions3DChromium*>(m_context->getExtensions());
219            // For each child context:
220            //   glWaitLatch(Offscreen->Compositor);
221            ChildContextMap::iterator i = m_childContexts.begin();
222            for (; i != m_childContexts.end(); ++i) {
223                Extensions3DChromium* childExt = static_cast<Extensions3DChromium*>(i->first->getExtensions());
224                GC3Duint latchId;
225                childExt->getChildToParentLatchCHROMIUM(&latchId);
226                parentExt->waitLatchCHROMIUM(latchId);
227            }
228        }
229        // Reset to false to indicate that we have consumed the dirty child
230        // contexts' parent textures. (This is only useful when the compositor
231        // is multithreaded.)
232        m_childContextsWereCopied = false;
233    }
234
235    drawLayers(renderSurfaceLayerList);
236
237    m_textureManager->unprotectAllTextures();
238
239    // After drawLayers:
240    if (hardwareCompositing() && m_contextSupportsLatch) {
241        Extensions3DChromium* parentExt = static_cast<Extensions3DChromium*>(m_context->getExtensions());
242        // For each child context:
243        //   glSetLatch(Compositor->Offscreen);
244        ChildContextMap::iterator i = m_childContexts.begin();
245        for (; i != m_childContexts.end(); ++i) {
246            Extensions3DChromium* childExt = static_cast<Extensions3DChromium*>(i->first->getExtensions());
247            GC3Duint latchId;
248            childExt->getParentToChildLatchCHROMIUM(&latchId);
249            parentExt->setLatchCHROMIUM(latchId);
250        }
251    }
252
253    if (isCompositingOffscreen())
254        copyOffscreenTextureToDisplay();
255}
256
257void LayerRendererChromium::updateLayers(LayerList& renderSurfaceLayerList)
258{
259    TRACE_EVENT("LayerRendererChromium::updateLayers", this, 0);
260    m_rootLayer->createCCLayerImplIfNeeded();
261    CCLayerImpl* rootDrawLayer = m_rootLayer->ccLayerImpl();
262
263    if (!rootDrawLayer->renderSurface())
264        rootDrawLayer->createRenderSurface();
265    ASSERT(rootDrawLayer->renderSurface());
266
267    rootDrawLayer->renderSurface()->m_contentRect = IntRect(IntPoint(0, 0), m_viewportVisibleRect.size());
268
269    IntRect rootScissorRect(m_viewportVisibleRect);
270    // The scissorRect should not include the scroll offset.
271    rootScissorRect.move(-m_viewportScrollPosition.x(), -m_viewportScrollPosition.y());
272    rootDrawLayer->setScissorRect(rootScissorRect);
273
274    m_defaultRenderSurface = rootDrawLayer->renderSurface();
275
276    renderSurfaceLayerList.append(rootDrawLayer);
277
278    TransformationMatrix identityMatrix;
279    m_defaultRenderSurface->m_layerList.clear();
280    // Unfortunately, updatePropertiesAndRenderSurfaces() currently both updates the layers and updates the draw state
281    // (transforms, etc). It'd be nicer if operations on the presentation layers happened later, but the draw
282    // transforms are needed by large layers to determine visibility. Tiling will fix this by eliminating the
283    // concept of a large content layer.
284    updatePropertiesAndRenderSurfaces(m_rootLayer.get(), identityMatrix, renderSurfaceLayerList, m_defaultRenderSurface->m_layerList);
285
286    paintLayerContents(renderSurfaceLayerList);
287
288    // FIXME: Before updateCompositorResourcesRecursive, when the compositor runs in
289    // its own thread, and when the copyTexImage2D bug is fixed, insert
290    // a glWaitLatch(Compositor->Offscreen) on all child contexts here instead
291    // of after updateCompositorResourcesRecursive.
292    // Also uncomment the glSetLatch(Compositor->Offscreen) code in addChildContext.
293//  if (hardwareCompositing() && m_contextSupportsLatch) {
294//      // For each child context:
295//      //   glWaitLatch(Compositor->Offscreen);
296//      ChildContextMap::iterator i = m_childContexts.begin();
297//      for (; i != m_childContexts.end(); ++i) {
298//          Extensions3DChromium* ext = static_cast<Extensions3DChromium*>(i->first->getExtensions());
299//          GC3Duint childToParentLatchId, parentToChildLatchId;
300//          ext->getParentToChildLatchCHROMIUM(&parentToChildLatchId);
301//          ext->waitLatchCHROMIUM(parentToChildLatchId);
302//      }
303//  }
304
305    updateCompositorResourcesRecursive(m_rootLayer.get());
306
307    // After updateCompositorResourcesRecursive, set/wait latches for all child
308    // contexts. This will prevent the compositor from using any of the child
309    // parent textures while WebGL commands are executing from javascript *and*
310    // while the final parent texture is being blit'd. copyTexImage2D
311    // uses the parent texture as a temporary resolve buffer, so that's why the
312    // waitLatch is below, to block the compositor from using the parent texture
313    // until the next WebGL SwapBuffers (or copyTextureToParentTexture for
314    // Canvas2D).
315    if (hardwareCompositing() && m_contextSupportsLatch) {
316        m_childContextsWereCopied = true;
317        // For each child context:
318        //   glSetLatch(Offscreen->Compositor);
319        //   glWaitLatch(Compositor->Offscreen);
320        ChildContextMap::iterator i = m_childContexts.begin();
321        for (; i != m_childContexts.end(); ++i) {
322            Extensions3DChromium* ext = static_cast<Extensions3DChromium*>(i->first->getExtensions());
323            GC3Duint childToParentLatchId, parentToChildLatchId;
324            ext->getParentToChildLatchCHROMIUM(&parentToChildLatchId);
325            ext->getChildToParentLatchCHROMIUM(&childToParentLatchId);
326            ext->setLatchCHROMIUM(childToParentLatchId);
327            ext->waitLatchCHROMIUM(parentToChildLatchId);
328        }
329    }
330}
331
332void LayerRendererChromium::paintLayerContents(const LayerList& renderSurfaceLayerList)
333{
334    for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
335        CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex].get();
336        RenderSurfaceChromium* renderSurface = renderSurfaceLayer->renderSurface();
337        ASSERT(renderSurface);
338
339        // Render surfaces whose drawable area has zero width or height
340        // will have no layers associated with them and should be skipped.
341        if (!renderSurface->m_layerList.size())
342            continue;
343
344        LayerList& layerList = renderSurface->m_layerList;
345        ASSERT(layerList.size());
346        for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex) {
347            CCLayerImpl* ccLayerImpl = layerList[layerIndex].get();
348
349            // Layers that start a new render surface will be painted when the render
350            // surface's list is processed.
351            if (ccLayerImpl->renderSurface() && ccLayerImpl->renderSurface() != renderSurface)
352                continue;
353
354            LayerChromium* layer = ccLayerImpl->owner();
355            if (layer->bounds().isEmpty())
356                continue;
357
358            const IntRect targetSurfaceRect = layer->ccLayerImpl()->scissorRect();
359
360            if (layer->drawsContent())
361                layer->paintContentsIfDirty(targetSurfaceRect);
362            if (layer->maskLayer() && layer->maskLayer()->drawsContent())
363                layer->maskLayer()->paintContentsIfDirty(targetSurfaceRect);
364            if (layer->replicaLayer() && layer->replicaLayer()->drawsContent())
365                layer->replicaLayer()->paintContentsIfDirty(targetSurfaceRect);
366            if (layer->replicaLayer() && layer->replicaLayer()->maskLayer() && layer->replicaLayer()->maskLayer()->drawsContent())
367                layer->replicaLayer()->maskLayer()->paintContentsIfDirty(targetSurfaceRect);
368        }
369    }
370}
371
372void LayerRendererChromium::drawLayers(const LayerList& renderSurfaceLayerList)
373{
374    TRACE_EVENT("LayerRendererChromium::drawLayers", this, 0);
375    CCLayerImpl* rootDrawLayer = m_rootLayer->ccLayerImpl();
376    makeContextCurrent();
377
378    // The GL viewport covers the entire visible area, including the scrollbars.
379    GLC(m_context.get(), m_context->viewport(0, 0, m_viewportVisibleRect.width(), m_viewportVisibleRect.height()));
380
381    // Bind the common vertex attributes used for drawing all the layers.
382    m_sharedGeometry->prepareForDraw();
383
384    // FIXME: These calls can be made once, when the compositor context is initialized.
385    GLC(m_context.get(), m_context->disable(GraphicsContext3D::DEPTH_TEST));
386    GLC(m_context.get(), m_context->disable(GraphicsContext3D::CULL_FACE));
387
388    // Blending disabled by default. Root layer alpha channel on Windows is incorrect when Skia uses ClearType.
389    GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND));
390
391    useRenderSurface(m_defaultRenderSurface);
392
393    // Clear to blue to make it easier to spot unrendered regions.
394    m_context->clearColor(0, 0, 1, 1);
395    m_context->colorMask(true, true, true, true);
396    m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
397    // Mask out writes to alpha channel: subpixel antialiasing via Skia results in invalid
398    // zero alpha values on text glyphs. The root layer is always opaque.
399    m_context->colorMask(true, true, true, false);
400
401    drawRootLayer();
402
403    // Re-enable color writes to layers, which may be partially transparent.
404    m_context->colorMask(true, true, true, true);
405
406    GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND));
407    GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
408    GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
409
410    // Update the contents of the render surfaces. We traverse the array from
411    // back to front to guarantee that nested render surfaces get rendered in the
412    // correct order.
413    for (int surfaceIndex = renderSurfaceLayerList.size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
414        CCLayerImpl* renderSurfaceLayer = renderSurfaceLayerList[surfaceIndex].get();
415        ASSERT(renderSurfaceLayer->renderSurface());
416
417        // Render surfaces whose drawable area has zero width or height
418        // will have no layers associated with them and should be skipped.
419        if (!renderSurfaceLayer->renderSurface()->m_layerList.size())
420            continue;
421
422        if (useRenderSurface(renderSurfaceLayer->renderSurface())) {
423            if (renderSurfaceLayer != rootDrawLayer) {
424                GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
425                GLC(m_context.get(), m_context->clearColor(0, 0, 0, 0));
426                GLC(m_context.get(), m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT));
427                GLC(m_context.get(), m_context->enable(GraphicsContext3D::SCISSOR_TEST));
428            }
429
430            LayerList& layerList = renderSurfaceLayer->renderSurface()->m_layerList;
431            ASSERT(layerList.size());
432            for (unsigned layerIndex = 0; layerIndex < layerList.size(); ++layerIndex)
433                drawLayer(layerList[layerIndex].get(), renderSurfaceLayer->renderSurface());
434        }
435    }
436
437    if (m_headsUpDisplay->enabled()) {
438        GLC(m_context.get(), m_context->enable(GraphicsContext3D::BLEND));
439        GLC(m_context.get(), m_context->blendFunc(GraphicsContext3D::ONE, GraphicsContext3D::ONE_MINUS_SRC_ALPHA));
440        GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
441        useRenderSurface(m_defaultRenderSurface);
442        m_headsUpDisplay->draw();
443    }
444
445    GLC(m_context.get(), m_context->disable(GraphicsContext3D::SCISSOR_TEST));
446    GLC(m_context.get(), m_context->disable(GraphicsContext3D::BLEND));
447}
448
449void LayerRendererChromium::finish()
450{
451    TRACE_EVENT("LayerRendererChromium::finish", this, 0);
452    m_context->finish();
453}
454
455void LayerRendererChromium::present()
456{
457    TRACE_EVENT("LayerRendererChromium::present", this, 0);
458    // We're done! Time to swapbuffers!
459
460    // Note that currently this has the same effect as swapBuffers; we should
461    // consider exposing a different entry point on GraphicsContext3D.
462    m_context->prepareTexture();
463
464    m_headsUpDisplay->onPresent();
465}
466
467void LayerRendererChromium::setRootLayer(PassRefPtr<LayerChromium> layer)
468{
469    m_rootLayer = layer;
470    if (m_rootLayer)
471        m_rootLayer->setLayerRenderer(this);
472    m_rootLayerContentTiler->invalidateEntireLayer();
473}
474
475void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect)
476{
477    ASSERT(rect.maxX() <= m_viewportVisibleRect.width() && rect.maxY() <= m_viewportVisibleRect.height());
478
479    if (!pixels)
480        return;
481
482    makeContextCurrent();
483
484    GLC(m_context.get(), m_context->readPixels(rect.x(), rect.y(), rect.width(), rect.height(),
485                                         GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, pixels));
486}
487
488// FIXME: This method should eventually be replaced by a proper texture manager.
489unsigned LayerRendererChromium::createLayerTexture()
490{
491    unsigned textureId = 0;
492    GLC(m_context.get(), textureId = m_context->createTexture());
493    GLC(m_context.get(), m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, textureId));
494    // Do basic linear filtering on resize.
495    GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::LINEAR));
496    GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_MAG_FILTER, GraphicsContext3D::LINEAR));
497    // NPOT textures in GL ES only work when the wrap mode is set to GraphicsContext3D::CLAMP_TO_EDGE.
498    GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_S, GraphicsContext3D::CLAMP_TO_EDGE));
499    GLC(m_context.get(), m_context->texParameteri(GraphicsContext3D::TEXTURE_2D, GraphicsContext3D::TEXTURE_WRAP_T, GraphicsContext3D::CLAMP_TO_EDGE));
500    return textureId;
501}
502
503void LayerRendererChromium::deleteLayerTexture(unsigned textureId)
504{
505    if (!textureId)
506        return;
507
508    GLC(m_context.get(), m_context->deleteTexture(textureId));
509}
510
511// Returns true if any part of the layer falls within the visibleRect
512bool LayerRendererChromium::isLayerVisible(LayerChromium* layer, const TransformationMatrix& matrix, const IntRect& visibleRect)
513{
514    // Form the matrix used by the shader to map the corners of the layer's
515    // bounds into clip space.
516    TransformationMatrix renderMatrix = matrix;
517    renderMatrix.scale3d(layer->bounds().width(), layer->bounds().height(), 1);
518    renderMatrix = m_projectionMatrix * renderMatrix;
519
520    FloatRect layerRect(-0.5, -0.5, 1, 1);
521    FloatRect mappedRect = renderMatrix.mapRect(layerRect);
522
523    // The layer is visible if it intersects any part of a rectangle whose origin
524    // is at (-1, -1) and size is 2x2.
525    return mappedRect.intersects(FloatRect(-1, -1, 2, 2));
526}
527
528// Recursively walks the layer tree starting at the given node and computes all the
529// necessary transformations, scissor rectangles, render surfaces, etc.
530void LayerRendererChromium::updatePropertiesAndRenderSurfaces(LayerChromium* layer, const TransformationMatrix& parentMatrix, LayerList& renderSurfaceLayerList, LayerList& layerList)
531{
532    // Make sure we have CCLayerImpls for this subtree.
533    layer->createCCLayerImplIfNeeded();
534    layer->setLayerRenderer(this);
535    if (layer->maskLayer()) {
536        layer->maskLayer()->createCCLayerImplIfNeeded();
537        layer->maskLayer()->setLayerRenderer(this);
538    }
539    if (layer->replicaLayer()) {
540        layer->replicaLayer()->createCCLayerImplIfNeeded();
541        layer->replicaLayer()->setLayerRenderer(this);
542    }
543    if (layer->replicaLayer() && layer->replicaLayer()->maskLayer()) {
544        layer->replicaLayer()->maskLayer()->createCCLayerImplIfNeeded();
545        layer->replicaLayer()->maskLayer()->setLayerRenderer(this);
546    }
547
548    CCLayerImpl* drawLayer = layer->ccLayerImpl();
549    // Currently we're calling pushPropertiesTo() twice - once here and once in updateCompositorResourcesRecursive().
550    // We should only call pushPropertiesTo() in commit, but because we rely on the draw layer state to update
551    // RenderSurfaces and we rely on RenderSurfaces being up to date in order to paint contents we have
552    // to update the draw layers twice.
553    // FIXME: Remove this call once layer updates no longer depend on render surfaces.
554    layer->pushPropertiesTo(drawLayer);
555
556    // Compute the new matrix transformation that will be applied to this layer and
557    // all its sublayers. It's important to remember that the layer's position
558    // is the position of the layer's anchor point. Also, the coordinate system used
559    // assumes that the origin is at the lower left even though the coordinates the browser
560    // gives us for the layers are for the upper left corner. The Y flip happens via
561    // the orthographic projection applied at render time.
562    // The transformation chain for the layer is (using the Matrix x Vector order):
563    // M = M[p] * Tr[l] * M[l] * Tr[c]
564    // Where M[p] is the parent matrix passed down to the function
565    //       Tr[l] is the translation matrix locating the layer's anchor point
566    //       Tr[c] is the translation offset between the anchor point and the center of the layer
567    //       M[l] is the layer's matrix (applied at the anchor point)
568    // This transform creates a coordinate system whose origin is the center of the layer.
569    // Note that the final matrix used by the shader for the layer is P * M * S . This final product
570    // is computed in drawTexturedQuad().
571    // Where: P is the projection matrix
572    //        M is the layer's matrix computed above
573    //        S is the scale adjustment (to scale up to the layer size)
574    IntSize bounds = drawLayer->bounds();
575    FloatPoint anchorPoint = drawLayer->anchorPoint();
576    FloatPoint position = drawLayer->position();
577
578    // Offset between anchor point and the center of the quad.
579    float centerOffsetX = (0.5 - anchorPoint.x()) * bounds.width();
580    float centerOffsetY = (0.5 - anchorPoint.y()) * bounds.height();
581
582    TransformationMatrix layerLocalTransform;
583    // LT = Tr[l]
584    layerLocalTransform.translate3d(position.x(), position.y(), drawLayer->anchorPointZ());
585    // LT = Tr[l] * M[l]
586    layerLocalTransform.multiply(drawLayer->transform());
587    // LT = Tr[l] * M[l] * Tr[c]
588    layerLocalTransform.translate3d(centerOffsetX, centerOffsetY, -drawLayer->anchorPointZ());
589
590    TransformationMatrix combinedTransform = parentMatrix;
591    combinedTransform = combinedTransform.multiply(layerLocalTransform);
592
593    FloatRect layerRect(-0.5 * drawLayer->bounds().width(), -0.5 * drawLayer->bounds().height(), drawLayer->bounds().width(), drawLayer->bounds().height());
594    IntRect transformedLayerRect;
595
596    // The layer and its descendants render on a new RenderSurface if any of
597    // these conditions hold:
598    // 1. The layer clips its descendants and its transform is not a simple translation.
599    // 2. If the layer has opacity != 1 and does not have a preserves-3d transform style.
600    // 3. The layer uses a mask
601    // 4. The layer has a replica (used for reflections)
602    // If a layer preserves-3d then we don't create a RenderSurface for it to avoid flattening
603    // out its children. The opacity value of the children layers is multiplied by the opacity
604    // of their parent.
605    bool useSurfaceForClipping = drawLayer->masksToBounds() && !isScaleOrTranslation(combinedTransform);
606    bool useSurfaceForOpacity = drawLayer->opacity() != 1 && !drawLayer->preserves3D();
607    bool useSurfaceForMasking = drawLayer->maskLayer();
608    bool useSurfaceForReflection = drawLayer->replicaLayer();
609    if (useSurfaceForMasking || useSurfaceForReflection || ((useSurfaceForClipping || useSurfaceForOpacity) && drawLayer->descendantsDrawsContent())) {
610        RenderSurfaceChromium* renderSurface = drawLayer->renderSurface();
611        if (!renderSurface)
612            renderSurface = drawLayer->createRenderSurface();
613
614        // The origin of the new surface is the upper left corner of the layer.
615        TransformationMatrix drawTransform;
616        drawTransform.translate3d(0.5 * bounds.width(), 0.5 * bounds.height(), 0);
617        drawLayer->setDrawTransform(drawTransform);
618
619        transformedLayerRect = IntRect(0, 0, bounds.width(), bounds.height());
620
621        // Layer's opacity will be applied when drawing the render surface.
622        renderSurface->m_drawOpacity = drawLayer->opacity();
623        if (drawLayer->superlayer() && drawLayer->superlayer()->preserves3D())
624            renderSurface->m_drawOpacity *= drawLayer->superlayer()->drawOpacity();
625        drawLayer->setDrawOpacity(1);
626
627        TransformationMatrix layerOriginTransform = combinedTransform;
628        layerOriginTransform.translate3d(-0.5 * bounds.width(), -0.5 * bounds.height(), 0);
629        renderSurface->m_originTransform = layerOriginTransform;
630        if (layerOriginTransform.isInvertible() && drawLayer->superlayer()) {
631            TransformationMatrix parentToLayer = layerOriginTransform.inverse();
632
633            drawLayer->setScissorRect(parentToLayer.mapRect(drawLayer->superlayer()->scissorRect()));
634        } else
635            drawLayer->setScissorRect(IntRect());
636
637        // The render surface scissor rect is the scissor rect that needs to
638        // be applied before drawing the render surface onto its containing
639        // surface and is therefore expressed in the superlayer's coordinate system.
640        renderSurface->m_scissorRect = drawLayer->superlayer() ? drawLayer->superlayer()->scissorRect() : drawLayer->scissorRect();
641
642        renderSurface->m_layerList.clear();
643
644        if (drawLayer->maskLayer()) {
645            renderSurface->m_maskLayer = drawLayer->maskLayer();
646            drawLayer->maskLayer()->setTargetRenderSurface(renderSurface);
647        } else
648            renderSurface->m_maskLayer = 0;
649
650        if (drawLayer->replicaLayer() && drawLayer->replicaLayer()->maskLayer())
651            drawLayer->replicaLayer()->maskLayer()->setTargetRenderSurface(renderSurface);
652
653        renderSurfaceLayerList.append(drawLayer);
654    } else {
655        // DT = M[p] * LT
656        drawLayer->setDrawTransform(combinedTransform);
657        transformedLayerRect = enclosingIntRect(drawLayer->drawTransform().mapRect(layerRect));
658
659        drawLayer->setDrawOpacity(drawLayer->opacity());
660
661        if (drawLayer->superlayer()) {
662            if (drawLayer->superlayer()->preserves3D())
663               drawLayer->setDrawOpacity(drawLayer->drawOpacity() * drawLayer->superlayer()->drawOpacity());
664
665            // Layers inherit the scissor rect from their superlayer.
666            drawLayer->setScissorRect(drawLayer->superlayer()->scissorRect());
667
668            drawLayer->setTargetRenderSurface(drawLayer->superlayer()->targetRenderSurface());
669        }
670
671        if (layer != m_rootLayer)
672            drawLayer->clearRenderSurface();
673
674        if (drawLayer->masksToBounds()) {
675            IntRect scissor = drawLayer->scissorRect();
676            scissor.intersect(transformedLayerRect);
677            drawLayer->setScissorRect(scissor);
678        }
679    }
680
681    if (drawLayer->renderSurface())
682        drawLayer->setTargetRenderSurface(drawLayer->renderSurface());
683    else {
684        ASSERT(drawLayer->superlayer());
685        drawLayer->setTargetRenderSurface(drawLayer->superlayer()->targetRenderSurface());
686    }
687
688    // drawableContentRect() is always stored in the coordinate system of the
689    // RenderSurface the layer draws into.
690    if (drawLayer->drawsContent())
691        drawLayer->setDrawableContentRect(transformedLayerRect);
692    else
693        drawLayer->setDrawableContentRect(IntRect());
694
695    TransformationMatrix sublayerMatrix = drawLayer->drawTransform();
696
697    // Flatten to 2D if the layer doesn't preserve 3D.
698    if (!drawLayer->preserves3D()) {
699        sublayerMatrix.setM13(0);
700        sublayerMatrix.setM23(0);
701        sublayerMatrix.setM31(0);
702        sublayerMatrix.setM32(0);
703        sublayerMatrix.setM33(1);
704        sublayerMatrix.setM34(0);
705        sublayerMatrix.setM43(0);
706    }
707
708    // Apply the sublayer transform at the center of the layer.
709    sublayerMatrix.multiply(drawLayer->sublayerTransform());
710
711    // The origin of the sublayers is the top left corner of the layer, not the
712    // center. The matrix passed down to the sublayers is therefore:
713    // M[s] = M * Tr[-center]
714    sublayerMatrix.translate3d(-bounds.width() * 0.5, -bounds.height() * 0.5, 0);
715
716    // Compute the depth value of the center of the layer which will be used when
717    // sorting the layers for the preserves-3d property.
718    const TransformationMatrix& layerDrawMatrix = drawLayer->renderSurface() ? drawLayer->renderSurface()->m_drawTransform : drawLayer->drawTransform();
719    if (drawLayer->superlayer()) {
720        if (!drawLayer->superlayer()->preserves3D())
721            drawLayer->setDrawDepth(drawLayer->superlayer()->drawDepth());
722        else
723            drawLayer->setDrawDepth(layerDrawMatrix.m43());
724    } else
725        drawLayer->setDrawDepth(0);
726
727    LayerList& descendants = (drawLayer->renderSurface() ? drawLayer->renderSurface()->m_layerList : layerList);
728    descendants.append(drawLayer);
729    unsigned thisLayerIndex = descendants.size() - 1;
730
731    const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers();
732    for (size_t i = 0; i < sublayers.size(); ++i) {
733        sublayers[i]->createCCLayerImplIfNeeded();
734        CCLayerImpl* sublayer = sublayers[i]->ccLayerImpl();
735        updatePropertiesAndRenderSurfaces(sublayers[i].get(), sublayerMatrix, renderSurfaceLayerList, descendants);
736
737        if (sublayer->renderSurface()) {
738            RenderSurfaceChromium* sublayerRenderSurface = sublayer->renderSurface();
739            IntRect drawableContentRect = drawLayer->drawableContentRect();
740            drawableContentRect.unite(enclosingIntRect(sublayerRenderSurface->drawableContentRect()));
741            drawLayer->setDrawableContentRect(drawableContentRect);
742            descendants.append(sublayer);
743        } else {
744            IntRect drawableContentRect = drawLayer->drawableContentRect();
745            drawableContentRect.unite(sublayer->drawableContentRect());
746            drawLayer->setDrawableContentRect(drawableContentRect);
747        }
748    }
749
750    if (drawLayer->masksToBounds() || useSurfaceForMasking) {
751        IntRect drawableContentRect = drawLayer->drawableContentRect();
752        drawableContentRect.intersect(transformedLayerRect);
753        drawLayer->setDrawableContentRect(drawableContentRect);
754    }
755
756    if (drawLayer->renderSurface() && layer != m_rootLayer) {
757        RenderSurfaceChromium* renderSurface = drawLayer->renderSurface();
758        renderSurface->m_contentRect = drawLayer->drawableContentRect();
759        FloatPoint surfaceCenter = renderSurface->contentRectCenter();
760
761        // Restrict the RenderSurface size to the portion that's visible.
762        FloatSize centerOffsetDueToClipping;
763
764        // Don't clip if the layer is reflected as the reflection shouldn't be
765        // clipped.
766        if (!drawLayer->replicaLayer()) {
767            renderSurface->m_contentRect.intersect(drawLayer->scissorRect());
768            FloatPoint clippedSurfaceCenter = renderSurface->contentRectCenter();
769            centerOffsetDueToClipping = clippedSurfaceCenter - surfaceCenter;
770        }
771
772        // The RenderSurface backing texture cannot exceed the maximum supported
773        // texture size.
774        renderSurface->m_contentRect.setWidth(std::min(renderSurface->m_contentRect.width(), m_maxTextureSize));
775        renderSurface->m_contentRect.setHeight(std::min(renderSurface->m_contentRect.height(), m_maxTextureSize));
776
777        if (renderSurface->m_contentRect.isEmpty())
778            renderSurface->m_layerList.clear();
779
780        // Since the layer starts a new render surface we need to adjust its
781        // scissor rect to be expressed in the new surface's coordinate system.
782        drawLayer->setScissorRect(drawLayer->drawableContentRect());
783
784        // Adjust the origin of the transform to be the center of the render surface.
785        renderSurface->m_drawTransform = renderSurface->m_originTransform;
786        renderSurface->m_drawTransform.translate3d(surfaceCenter.x() + centerOffsetDueToClipping.width(), surfaceCenter.y() + centerOffsetDueToClipping.height(), 0);
787
788        // Compute the transformation matrix used to draw the replica of the render
789        // surface.
790        if (drawLayer->replicaLayer()) {
791            renderSurface->m_replicaDrawTransform = renderSurface->m_originTransform;
792            renderSurface->m_replicaDrawTransform.translate3d(drawLayer->replicaLayer()->position().x(), drawLayer->replicaLayer()->position().y(), 0);
793            renderSurface->m_replicaDrawTransform.multiply(drawLayer->replicaLayer()->transform());
794            renderSurface->m_replicaDrawTransform.translate3d(surfaceCenter.x() - anchorPoint.x() * bounds.width(), surfaceCenter.y() - anchorPoint.y() * bounds.height(), 0);
795        }
796    }
797
798    // If preserves-3d then sort all the descendants by the Z coordinate of their
799    // center. If the preserves-3d property is also set on the superlayer then
800    // skip the sorting as the superlayer will sort all the descendants anyway.
801    if (drawLayer->preserves3D() && (!drawLayer->superlayer() || !drawLayer->superlayer()->preserves3D()))
802        std::stable_sort(&descendants.at(thisLayerIndex), descendants.end(), compareLayerZ);
803}
804
805void LayerRendererChromium::updateCompositorResourcesRecursive(LayerChromium* layer)
806{
807    const Vector<RefPtr<LayerChromium> >& sublayers = layer->getSublayers();
808    for (size_t i = 0; i < sublayers.size(); ++i)
809        updateCompositorResourcesRecursive(sublayers[i].get());
810
811    if (layer->bounds().isEmpty())
812        return;
813
814    CCLayerImpl* drawLayer = layer->ccLayerImpl();
815
816    if (drawLayer->drawsContent())
817        drawLayer->updateCompositorResources();
818    if (drawLayer->maskLayer() && drawLayer->maskLayer()->drawsContent())
819        drawLayer->maskLayer()->updateCompositorResources();
820    if (drawLayer->replicaLayer() && drawLayer->replicaLayer()->drawsContent())
821        drawLayer->replicaLayer()->updateCompositorResources();
822    if (drawLayer->replicaLayer() && drawLayer->replicaLayer()->maskLayer() && drawLayer->replicaLayer()->maskLayer()->drawsContent())
823        drawLayer->replicaLayer()->maskLayer()->updateCompositorResources();
824
825    layer->pushPropertiesTo(drawLayer);
826}
827
828void LayerRendererChromium::setCompositeOffscreen(bool compositeOffscreen)
829{
830    if (m_compositeOffscreen == compositeOffscreen)
831       return;
832
833    m_compositeOffscreen = compositeOffscreen;
834
835    if (!m_compositeOffscreen && m_rootLayer)
836        m_rootLayer->ccLayerImpl()->clearRenderSurface();
837}
838
839LayerTexture* LayerRendererChromium::getOffscreenLayerTexture()
840{
841    return m_compositeOffscreen ? m_rootLayer->ccLayerImpl()->renderSurface()->m_contentsTexture.get() : 0;
842}
843
844void LayerRendererChromium::copyOffscreenTextureToDisplay()
845{
846    if (m_compositeOffscreen) {
847        makeContextCurrent();
848
849        useRenderSurface(0);
850        m_defaultRenderSurface->m_drawTransform.makeIdentity();
851        m_defaultRenderSurface->m_drawTransform.translate3d(0.5 * m_defaultRenderSurface->m_contentRect.width(),
852                                                            0.5 * m_defaultRenderSurface->m_contentRect.height(), 0);
853        m_defaultRenderSurface->m_drawOpacity = 1;
854        m_defaultRenderSurface->draw(m_defaultRenderSurface->m_contentRect);
855    }
856}
857
858bool LayerRendererChromium::useRenderSurface(RenderSurfaceChromium* renderSurface)
859{
860    if (m_currentRenderSurface == renderSurface)
861        return true;
862
863    m_currentRenderSurface = renderSurface;
864
865    if ((renderSurface == m_defaultRenderSurface && !m_compositeOffscreen) || (!renderSurface && m_compositeOffscreen)) {
866        GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
867        if (renderSurface)
868            setDrawViewportRect(renderSurface->m_contentRect, true);
869        else
870            setDrawViewportRect(m_defaultRenderSurface->m_contentRect, true);
871        return true;
872    }
873
874    GLC(m_context.get(), m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, m_offscreenFramebufferId));
875
876    if (!renderSurface->prepareContentsTexture())
877        return false;
878
879    renderSurface->m_contentsTexture->framebufferTexture2D();
880
881#if !defined ( NDEBUG )
882    if (m_context->checkFramebufferStatus(GraphicsContext3D::FRAMEBUFFER) != GraphicsContext3D::FRAMEBUFFER_COMPLETE) {
883        ASSERT_NOT_REACHED();
884        return false;
885    }
886#endif
887
888    setDrawViewportRect(renderSurface->m_contentRect, false);
889    return true;
890}
891
892void LayerRendererChromium::drawLayer(CCLayerImpl* layer, RenderSurfaceChromium* targetSurface)
893{
894    if (layer->renderSurface() && layer->renderSurface() != targetSurface) {
895        layer->renderSurface()->draw(layer->getDrawRect());
896        return;
897    }
898
899    if (!layer->drawsContent())
900        return;
901
902    if (layer->bounds().isEmpty()) {
903        layer->unreserveContentsTexture();
904        return;
905    }
906
907    setScissorToRect(layer->scissorRect());
908
909    // Check if the layer falls within the visible bounds of the page.
910    IntRect layerRect = layer->getDrawRect();
911    bool isLayerVisible = layer->scissorRect().intersects(layerRect);
912    if (!isLayerVisible) {
913        layer->unreserveContentsTexture();
914        return;
915    }
916
917    // FIXME: Need to take into account the commulative render surface transforms all the way from
918    //        the default render surface in order to determine visibility.
919    TransformationMatrix combinedDrawMatrix = (layer->targetRenderSurface() ? layer->targetRenderSurface()->drawTransform().multiply(layer->drawTransform()) : layer->drawTransform());
920
921    if (!layer->doubleSided()) {
922        FloatRect layerRect(FloatPoint(0, 0), FloatSize(layer->bounds()));
923        FloatQuad mappedLayer = combinedDrawMatrix.mapQuad(FloatQuad(layerRect));
924        FloatSize horizontalDir = mappedLayer.p2() - mappedLayer.p1();
925        FloatSize verticalDir = mappedLayer.p4() - mappedLayer.p1();
926        FloatPoint3D xAxis(horizontalDir.width(), horizontalDir.height(), 0);
927        FloatPoint3D yAxis(verticalDir.width(), verticalDir.height(), 0);
928        FloatPoint3D zAxis = xAxis.cross(yAxis);
929        if (zAxis.z() < 0) {
930            layer->unreserveContentsTexture();
931            return;
932        }
933    }
934
935    layer->draw(layer->scissorRect());
936
937    // Draw the debug border if there is one.
938    layer->drawDebugBorder();
939}
940
941// Sets the scissor region to the given rectangle. The coordinate system for the
942// scissorRect has its origin at the top left corner of the current visible rect.
943void LayerRendererChromium::setScissorToRect(const IntRect& scissorRect)
944{
945    IntRect contentRect = (m_currentRenderSurface ? m_currentRenderSurface->m_contentRect : m_defaultRenderSurface->m_contentRect);
946
947    // The scissor coordinates must be supplied in viewport space so we need to offset
948    // by the relative position of the top left corner of the current render surface.
949    int scissorX = scissorRect.x() - contentRect.x();
950    // When rendering to the default render surface we're rendering upside down so the top
951    // of the GL scissor is the bottom of our layer.
952    // But, if rendering to offscreen texture, we reverse our sense of 'upside down'.
953    int scissorY;
954    if (m_currentRenderSurface == m_defaultRenderSurface && !m_compositeOffscreen)
955        scissorY = m_currentRenderSurface->m_contentRect.height() - (scissorRect.maxY() - m_currentRenderSurface->m_contentRect.y());
956    else
957        scissorY = scissorRect.y() - contentRect.y();
958    GLC(m_context.get(), m_context->scissor(scissorX, scissorY, scissorRect.width(), scissorRect.height()));
959}
960
961bool LayerRendererChromium::makeContextCurrent()
962{
963    m_context->makeContextCurrent();
964    return true;
965}
966
967// Checks whether a given size is within the maximum allowed texture size range.
968bool LayerRendererChromium::checkTextureSize(const IntSize& textureSize)
969{
970    if (textureSize.width() > m_maxTextureSize || textureSize.height() > m_maxTextureSize)
971        return false;
972    return true;
973}
974
975// Sets the coordinate range of content that ends being drawn onto the target render surface.
976// The target render surface is assumed to have an origin at 0, 0 and the width and height of
977// of the drawRect.
978void LayerRendererChromium::setDrawViewportRect(const IntRect& drawRect, bool flipY)
979{
980    if (flipY)
981        m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.maxY(), drawRect.y());
982    else
983        m_projectionMatrix = orthoMatrix(drawRect.x(), drawRect.maxX(), drawRect.y(), drawRect.maxY());
984    GLC(m_context.get(), m_context->viewport(0, 0, drawRect.width(), drawRect.height()));
985}
986
987
988
989void LayerRendererChromium::resizeOnscreenContent(const IntSize& size)
990{
991    if (m_context)
992        m_context->reshape(size.width(), size.height());
993}
994
995bool LayerRendererChromium::initializeSharedObjects()
996{
997    makeContextCurrent();
998
999    // Get the max texture size supported by the system.
1000    m_maxTextureSize = 0;
1001    GLC(m_context.get(), m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize));
1002
1003    // Create an FBO for doing offscreen rendering.
1004    GLC(m_context.get(), m_offscreenFramebufferId = m_context->createFramebuffer());
1005
1006    m_sharedGeometry = adoptPtr(new GeometryBinding(m_context.get()));
1007    m_borderProgram = adoptPtr(new LayerChromium::BorderProgram(m_context.get()));
1008    m_headsUpDisplayProgram = adoptPtr(new CCHeadsUpDisplay::Program(m_context.get()));
1009    m_canvasLayerProgram = adoptPtr(new CCCanvasLayerImpl::Program(m_context.get()));
1010    m_videoLayerRGBAProgram = adoptPtr(new CCVideoLayerImpl::RGBAProgram(m_context.get()));
1011    m_videoLayerYUVProgram = adoptPtr(new CCVideoLayerImpl::YUVProgram(m_context.get()));
1012    m_pluginLayerProgram = adoptPtr(new CCPluginLayerImpl::Program(m_context.get()));
1013    m_renderSurfaceProgram = adoptPtr(new RenderSurfaceChromium::Program(m_context.get()));
1014    m_renderSurfaceMaskProgram = adoptPtr(new RenderSurfaceChromium::MaskProgram(m_context.get()));
1015    m_tilerProgram = adoptPtr(new LayerTilerChromium::Program(m_context.get()));
1016
1017    if (!m_sharedGeometry->initialized() || !m_borderProgram->initialized()
1018        || !m_canvasLayerProgram->initialized()
1019        || !m_headsUpDisplayProgram->initialized()
1020        || !m_videoLayerRGBAProgram->initialized() || !m_videoLayerYUVProgram->initialized()
1021        || !m_pluginLayerProgram->initialized() || !m_renderSurfaceProgram->initialized()
1022        || !m_renderSurfaceMaskProgram->initialized() || !m_tilerProgram->initialized()) {
1023        LOG_ERROR("Compositor failed to initialize shaders. Falling back to software.");
1024        cleanupSharedObjects();
1025        return false;
1026    }
1027
1028    m_textureManager = TextureManager::create(m_context.get(), textureMemoryLimitBytes, m_maxTextureSize);
1029    return true;
1030}
1031
1032void LayerRendererChromium::cleanupSharedObjects()
1033{
1034    makeContextCurrent();
1035
1036    m_sharedGeometry.clear();
1037    m_borderProgram.clear();
1038    m_canvasLayerProgram.clear();
1039    m_headsUpDisplayProgram.clear();
1040    m_videoLayerRGBAProgram.clear();
1041    m_videoLayerYUVProgram.clear();
1042    m_pluginLayerProgram.clear();
1043    m_renderSurfaceProgram.clear();
1044    m_renderSurfaceMaskProgram.clear();
1045    m_tilerProgram.clear();
1046    if (m_offscreenFramebufferId)
1047        GLC(m_context.get(), m_context->deleteFramebuffer(m_offscreenFramebufferId));
1048
1049    // Clear tilers before the texture manager, as they have references to textures.
1050    m_rootLayerContentTiler.clear();
1051
1052    m_textureManager.clear();
1053}
1054
1055String LayerRendererChromium::layerTreeAsText() const
1056{
1057    TextStream ts;
1058    if (m_rootLayer.get()) {
1059        ts << m_rootLayer->layerTreeAsText();
1060        ts << "RenderSurfaces:\n";
1061        dumpRenderSurfaces(ts, 1, m_rootLayer.get());
1062    }
1063    return ts.release();
1064}
1065
1066void LayerRendererChromium::addChildContext(GraphicsContext3D* ctx)
1067{
1068    if (!ctx->getExtensions()->supports("GL_CHROMIUM_latch"))
1069        return;
1070
1071    // This is a ref-counting map, because some contexts are shared by multiple
1072    // layers (specifically, Canvas2DLayerChromium).
1073
1074    // Insert the ctx with a count of 1, or return the existing iterator.
1075    std::pair<ChildContextMap::iterator, bool> insert_result = m_childContexts.add(ctx, 1);
1076    if (!insert_result.second) {
1077        // Already present in map, so increment.
1078        ++insert_result.first->second;
1079    } else {
1080// FIXME(jbates): when compositor is multithreaded and copyTexImage2D bug is fixed,
1081// uncomment this block:
1082//      // This is a new child context - set the parentToChild latch so that it
1083//      // can continue past its first wait latch.
1084//      Extensions3DChromium* ext = static_cast<Extensions3DChromium*>(ctx->getExtensions());
1085//      GC3Duint latchId;
1086//      ext->getParentToChildLatchCHROMIUM(&latchId);
1087//      ext->setLatchCHROMIUM(0, latchId);
1088    }
1089}
1090
1091void LayerRendererChromium::removeChildContext(GraphicsContext3D* ctx)
1092{
1093    if (!ctx->getExtensions()->supports("GL_CHROMIUM_latch"))
1094        return;
1095
1096    ChildContextMap::iterator i = m_childContexts.find(ctx);
1097    if (i != m_childContexts.end()) {
1098        if (--i->second <= 0) {
1099            // Count reached zero, so remove from map.
1100            m_childContexts.remove(i);
1101        }
1102    } else {
1103        // error
1104        ASSERT(0 && "m_childContexts map has mismatched add/remove calls");
1105    }
1106}
1107
1108void LayerRendererChromium::dumpRenderSurfaces(TextStream& ts, int indent, LayerChromium* layer) const
1109{
1110    if (layer->ccLayerImpl()->renderSurface())
1111        layer->ccLayerImpl()->renderSurface()->dumpSurface(ts, indent);
1112
1113    for (size_t i = 0; i < layer->getSublayers().size(); ++i)
1114        dumpRenderSurfaces(ts, indent, layer->getSublayers()[i].get());
1115}
1116
1117} // namespace WebCore
1118
1119#endif // USE(ACCELERATED_COMPOSITING)
1120