• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
57 namespace WebCore {
58 
59 // FIXME: Make this limit adjustable and give it a useful value.
60 static size_t textureMemoryLimitBytes = 64 * 1024 * 1024;
61 
orthoMatrix(float left,float right,float bottom,float top)62 static 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.
isScaleOrTranslation(const TransformationMatrix & m)82 static 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 
compareLayerZ(const RefPtr<CCLayerImpl> & a,const RefPtr<CCLayerImpl> & b)91 bool LayerRendererChromium::compareLayerZ(const RefPtr<CCLayerImpl>& a, const RefPtr<CCLayerImpl>& b)
92 {
93     return a->drawDepth() < b->drawDepth();
94 }
95 
create(PassRefPtr<GraphicsContext3D> context,PassOwnPtr<TilePaintInterface> contentPaint)96 PassRefPtr<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 
LayerRendererChromium(PassRefPtr<GraphicsContext3D> context,PassOwnPtr<TilePaintInterface> contentPaint)108 LayerRendererChromium::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 
~LayerRendererChromium()130 LayerRendererChromium::~LayerRendererChromium()
131 {
132     m_headsUpDisplay.clear(); // Explicitly destroy the HUD before the TextureManager dies.
133     cleanupSharedObjects();
134 }
135 
context()136 GraphicsContext3D* LayerRendererChromium::context()
137 {
138     return m_context.get();
139 }
140 
debugGLCall(GraphicsContext3D * context,const char * command,const char * file,int line)141 void 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 
useShader(unsigned programId)148 void 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 
invalidateRootLayerRect(const IntRect & dirtyRect)156 void LayerRendererChromium::invalidateRootLayerRect(const IntRect& dirtyRect)
157 {
158     m_rootLayerContentTiler->invalidateRect(dirtyRect);
159 }
160 
updateRootLayerContents()161 void LayerRendererChromium::updateRootLayerContents()
162 {
163     TRACE_EVENT("LayerRendererChromium::updateRootLayerContents", this, 0);
164     m_rootLayerContentTiler->update(*m_rootLayerContentPaint, m_viewportVisibleRect);
165 }
166 
drawRootLayer()167 void 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 
setViewport(const IntRect & visibleRect,const IntRect & contentRect,const IntPoint & scrollPosition)176 void 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 
updateAndDrawLayers()192 void 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 
updateLayers(LayerList & renderSurfaceLayerList)257 void 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 
paintLayerContents(const LayerList & renderSurfaceLayerList)332 void 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 
drawLayers(const LayerList & renderSurfaceLayerList)372 void 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 
finish()449 void LayerRendererChromium::finish()
450 {
451     TRACE_EVENT("LayerRendererChromium::finish", this, 0);
452     m_context->finish();
453 }
454 
present()455 void 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 
setRootLayer(PassRefPtr<LayerChromium> layer)467 void 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 
getFramebufferPixels(void * pixels,const IntRect & rect)475 void 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.
createLayerTexture()489 unsigned 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 
deleteLayerTexture(unsigned textureId)503 void 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
isLayerVisible(LayerChromium * layer,const TransformationMatrix & matrix,const IntRect & visibleRect)512 bool 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.
updatePropertiesAndRenderSurfaces(LayerChromium * layer,const TransformationMatrix & parentMatrix,LayerList & renderSurfaceLayerList,LayerList & layerList)530 void 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 
updateCompositorResourcesRecursive(LayerChromium * layer)805 void 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 
setCompositeOffscreen(bool compositeOffscreen)828 void 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 
getOffscreenLayerTexture()839 LayerTexture* LayerRendererChromium::getOffscreenLayerTexture()
840 {
841     return m_compositeOffscreen ? m_rootLayer->ccLayerImpl()->renderSurface()->m_contentsTexture.get() : 0;
842 }
843 
copyOffscreenTextureToDisplay()844 void 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 
useRenderSurface(RenderSurfaceChromium * renderSurface)858 bool 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 
drawLayer(CCLayerImpl * layer,RenderSurfaceChromium * targetSurface)892 void 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.
setScissorToRect(const IntRect & scissorRect)943 void 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 
makeContextCurrent()961 bool 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.
checkTextureSize(const IntSize & textureSize)968 bool 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.
setDrawViewportRect(const IntRect & drawRect,bool flipY)978 void 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 
resizeOnscreenContent(const IntSize & size)989 void LayerRendererChromium::resizeOnscreenContent(const IntSize& size)
990 {
991     if (m_context)
992         m_context->reshape(size.width(), size.height());
993 }
994 
initializeSharedObjects()995 bool 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 
cleanupSharedObjects()1032 void 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 
layerTreeAsText() const1055 String 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 
addChildContext(GraphicsContext3D * ctx)1066 void 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 
removeChildContext(GraphicsContext3D * ctx)1091 void 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 
dumpRenderSurfaces(TextStream & ts,int indent,LayerChromium * layer) const1108 void 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