[chromium] Do partial-swap scissoring on quads during draw instead of on layers
authordanakj@chromium.org <danakj@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Aug 2012 20:15:03 +0000 (20:15 +0000)
committerdanakj@chromium.org <danakj@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 9 Aug 2012 20:15:03 +0000 (20:15 +0000)
https://bugs.webkit.org/show_bug.cgi?id=91800

Reviewed by Adrienne Walker.

Source/WebCore:

Computing the scissor rect for each render pass is now done in
LayerRendererChromium::drawRenderPass() instead of being done for each
layer and then copied into the quads. This allows us to always push a
full frame of quads (and include damage rects) from a child compositor,
and do partial-swap scissoring in the host compositor.

This also make partial-swap functionality completely contained within
LayerRendererChromium!

The scissorRect is removed from all layers, and the concept of
scissorRect is now misplaced in CCOcclusionTracker, so the variables
and methods in the tracker should be renamed to more appropriate
things.

Covered by existing tests, as well as: CCLayerTreeHostImplTest.textureCachingWithScissor

* platform/graphics/chromium/LayerChromium.h:
(LayerChromium):
* platform/graphics/chromium/LayerRendererChromium.cpp:
(WebCore::LayerRendererChromium::clearFramebuffer):
(WebCore::LayerRendererChromium::renderPassTextureSize):
(WebCore::LayerRendererChromium::drawFrame):
(WebCore::LayerRendererChromium::drawRenderPass):
(WebCore::LayerRendererChromium::drawQuad):
(WebCore::LayerRendererChromium::drawDebugBorderQuad):
(WebCore::LayerRendererChromium::drawBackgroundFilters):
(WebCore::LayerRendererChromium::drawTileQuad):
(WebCore::LayerRendererChromium::swapBuffers):
(WebCore::LayerRendererChromium::useRenderPass):
(WebCore::LayerRendererChromium::setScissorToRect):
* platform/graphics/chromium/LayerRendererChromium.h:
(LayerRendererChromium):
(DrawingFrame):
* platform/graphics/chromium/RenderSurfaceChromium.cpp:
* platform/graphics/chromium/RenderSurfaceChromium.h:
(RenderSurfaceChromium):
* platform/graphics/chromium/cc/CCDrawQuad.h:
(WebCore::CCDrawQuad::clippedRectInTarget):
* platform/graphics/chromium/cc/CCLayerImpl.cpp:
(WebCore::CCLayerImpl::createSharedQuadState):
* platform/graphics/chromium/cc/CCLayerImpl.h:
(CCLayerImpl):
* platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
(WebCore::CCLayerTreeHost::updateLayers):
(WebCore::CCLayerTreeHost::paintLayerContents):
* platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp:
(WebCore::calculateVisibleRectsInternal):
(WebCore::CCLayerTreeHostCommon::calculateVisibleRects):
* platform/graphics/chromium/cc/CCLayerTreeHostCommon.h:
(CCLayerTreeHostCommon):
* platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:
(WebCore::CCLayerTreeHostImpl::calculateRenderSurfaceLayerList):
(WebCore::CCLayerTreeHostImpl::calculateRenderPasses):
(WebCore::CCLayerTreeHostImpl::drawLayers):
(WebCore::CCLayerTreeHostImpl::swapBuffers):
* platform/graphics/chromium/cc/CCLayerTreeHostImpl.h:
(CCLayerTreeHostImpl):
* platform/graphics/chromium/cc/CCOcclusionTracker.cpp:
(WebCore::::layerScissorRectInTargetSurface):
* platform/graphics/chromium/cc/CCRenderPass.cpp:
(WebCore::CCRenderPass::CCRenderPass):
(WebCore::CCRenderPass::appendQuadsToFillScreen):
* platform/graphics/chromium/cc/CCRenderPass.h:
(CCRenderPass):
(WebCore::CCRenderPass::transformToRootTarget):
(WebCore::CCRenderPass::outputRect):
(WebCore::CCRenderPass::damageRect):
(WebCore::CCRenderPass::setDamageRect):
* platform/graphics/chromium/cc/CCRenderSurface.cpp:
(WebCore::computeClippedRectInTarget):
(WebCore):
(WebCore::CCRenderSurface::createSharedQuadState):
(WebCore::CCRenderSurface::createReplicaSharedQuadState):
* platform/graphics/chromium/cc/CCRenderSurface.h:
(CCRenderSurface):
* platform/graphics/chromium/cc/CCRenderer.h:
(CCRenderer):
* platform/graphics/chromium/cc/CCSharedQuadState.cpp:
(WebCore::CCSharedQuadState::create):
(WebCore::CCSharedQuadState::CCSharedQuadState):
* platform/graphics/chromium/cc/CCSharedQuadState.h:
(CCSharedQuadState):
* platform/graphics/chromium/cc/CCTiledLayerImpl.cpp:
(WebCore::CCTiledLayerImpl::appendQuads):

Source/WebKit/chromium:

* tests/CCDamageTrackerTest.cpp:
(WebKitTests::executeCalculateDrawTransformsAndVisibility):
* tests/CCLayerIteratorTest.cpp:
* tests/CCLayerTreeHostCommonTest.cpp:
Removed tests of the scissor rect here, as they are no longer
computed within CCLayerTreeHostCommon. Verify that the scissor
does not affect texture caching in CCLayerTreeHostImplTest now.
Previous scissor would affect the texture cache decisions, but
this was incorrect, as damaged areas are always inside the
scissor rect, and anything outside the scissor rect should
be considered as valid and complete (assuming no external
occlusion, which is computed outside the scissor rect now also).

* tests/CCLayerTreeHostImplTest.cpp:
Removed didDrawNotCalledOnScissoredLayer test, as this no longer
applies. didDraw will be called on layers that are outside the
partial swap rect, regardless.

Removed partialSwapNoUpdate test, and merged its functionality into
the partialSwap test while updating its expectations.

Added textureCachingWithScissor, which is loosely based on the
CCLayerTreeHostCommonTest.scissorRectWithClip test.

* tests/CCOcclusionTrackerTest.cpp:
(WebKitTests::CCOcclusionTrackerTest::calcDrawEtc):
(WebKitTests::CCOcclusionTrackerTestChildInRotatedChild::runMyTest):
(WebKitTests::CCOcclusionTrackerTestVisitTargetTwoTimes::runMyTest):
* tests/CCQuadCullerTest.cpp:
* tests/CCRenderSurfaceTest.cpp:
* tests/CCSolidColorLayerImplTest.cpp:
(CCLayerTestCommon::TEST):
* tests/CCTiledLayerImplTest.cpp:
(CCLayerTestCommon::createLayer):
* tests/LayerRendererChromiumTest.cpp:
(LayerRendererChromiumTest::swapBuffers):
(TEST_F):
(TEST):
* tests/TiledLayerChromiumTest.cpp:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@125196 268f45cc-cd09-0410-ab3c-d52691b4dbfc

35 files changed:
Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/chromium/LayerChromium.h
Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h
Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.cpp
Source/WebCore/platform/graphics/chromium/RenderSurfaceChromium.h
Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.h
Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.cpp
Source/WebCore/platform/graphics/chromium/cc/CCLayerImpl.h
Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.cpp
Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp
Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostCommon.h
Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp
Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h
Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp
Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.cpp
Source/WebCore/platform/graphics/chromium/cc/CCRenderPass.h
Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.cpp
Source/WebCore/platform/graphics/chromium/cc/CCRenderSurface.h
Source/WebCore/platform/graphics/chromium/cc/CCRenderer.h
Source/WebCore/platform/graphics/chromium/cc/CCSharedQuadState.cpp
Source/WebCore/platform/graphics/chromium/cc/CCSharedQuadState.h
Source/WebCore/platform/graphics/chromium/cc/CCTiledLayerImpl.cpp
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/tests/CCDamageTrackerTest.cpp
Source/WebKit/chromium/tests/CCLayerIteratorTest.cpp
Source/WebKit/chromium/tests/CCLayerTreeHostCommonTest.cpp
Source/WebKit/chromium/tests/CCLayerTreeHostImplTest.cpp
Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp
Source/WebKit/chromium/tests/CCQuadCullerTest.cpp
Source/WebKit/chromium/tests/CCRenderSurfaceTest.cpp
Source/WebKit/chromium/tests/CCSolidColorLayerImplTest.cpp
Source/WebKit/chromium/tests/CCTiledLayerImplTest.cpp
Source/WebKit/chromium/tests/LayerRendererChromiumTest.cpp
Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp

index f0897a9..ffc927f 100644 (file)
@@ -1,3 +1,95 @@
+2012-08-09  Dana Jansens  <danakj@chromium.org>
+
+        [chromium] Do partial-swap scissoring on quads during draw instead of on layers
+        https://bugs.webkit.org/show_bug.cgi?id=91800
+
+        Reviewed by Adrienne Walker.
+
+        Computing the scissor rect for each render pass is now done in
+        LayerRendererChromium::drawRenderPass() instead of being done for each
+        layer and then copied into the quads. This allows us to always push a
+        full frame of quads (and include damage rects) from a child compositor,
+        and do partial-swap scissoring in the host compositor.
+
+        This also make partial-swap functionality completely contained within
+        LayerRendererChromium!
+
+        The scissorRect is removed from all layers, and the concept of
+        scissorRect is now misplaced in CCOcclusionTracker, so the variables
+        and methods in the tracker should be renamed to more appropriate
+        things.
+
+        Covered by existing tests, as well as: CCLayerTreeHostImplTest.textureCachingWithScissor
+
+        * platform/graphics/chromium/LayerChromium.h:
+        (LayerChromium):
+        * platform/graphics/chromium/LayerRendererChromium.cpp:
+        (WebCore::LayerRendererChromium::clearFramebuffer):
+        (WebCore::LayerRendererChromium::renderPassTextureSize):
+        (WebCore::LayerRendererChromium::drawFrame):
+        (WebCore::LayerRendererChromium::drawRenderPass):
+        (WebCore::LayerRendererChromium::drawQuad):
+        (WebCore::LayerRendererChromium::drawDebugBorderQuad):
+        (WebCore::LayerRendererChromium::drawBackgroundFilters):
+        (WebCore::LayerRendererChromium::drawTileQuad):
+        (WebCore::LayerRendererChromium::swapBuffers):
+        (WebCore::LayerRendererChromium::useRenderPass):
+        (WebCore::LayerRendererChromium::setScissorToRect):
+        * platform/graphics/chromium/LayerRendererChromium.h:
+        (LayerRendererChromium):
+        (DrawingFrame):
+        * platform/graphics/chromium/RenderSurfaceChromium.cpp:
+        * platform/graphics/chromium/RenderSurfaceChromium.h:
+        (RenderSurfaceChromium):
+        * platform/graphics/chromium/cc/CCDrawQuad.h:
+        (WebCore::CCDrawQuad::clippedRectInTarget):
+        * platform/graphics/chromium/cc/CCLayerImpl.cpp:
+        (WebCore::CCLayerImpl::createSharedQuadState):
+        * platform/graphics/chromium/cc/CCLayerImpl.h:
+        (CCLayerImpl):
+        * platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
+        (WebCore::CCLayerTreeHost::updateLayers):
+        (WebCore::CCLayerTreeHost::paintLayerContents):
+        * platform/graphics/chromium/cc/CCLayerTreeHostCommon.cpp:
+        (WebCore::calculateVisibleRectsInternal):
+        (WebCore::CCLayerTreeHostCommon::calculateVisibleRects):
+        * platform/graphics/chromium/cc/CCLayerTreeHostCommon.h:
+        (CCLayerTreeHostCommon):
+        * platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:
+        (WebCore::CCLayerTreeHostImpl::calculateRenderSurfaceLayerList):
+        (WebCore::CCLayerTreeHostImpl::calculateRenderPasses):
+        (WebCore::CCLayerTreeHostImpl::drawLayers):
+        (WebCore::CCLayerTreeHostImpl::swapBuffers):
+        * platform/graphics/chromium/cc/CCLayerTreeHostImpl.h:
+        (CCLayerTreeHostImpl):
+        * platform/graphics/chromium/cc/CCOcclusionTracker.cpp:
+        (WebCore::::layerScissorRectInTargetSurface):
+        * platform/graphics/chromium/cc/CCRenderPass.cpp:
+        (WebCore::CCRenderPass::CCRenderPass):
+        (WebCore::CCRenderPass::appendQuadsToFillScreen):
+        * platform/graphics/chromium/cc/CCRenderPass.h:
+        (CCRenderPass):
+        (WebCore::CCRenderPass::transformToRootTarget):
+        (WebCore::CCRenderPass::outputRect):
+        (WebCore::CCRenderPass::damageRect):
+        (WebCore::CCRenderPass::setDamageRect):
+        * platform/graphics/chromium/cc/CCRenderSurface.cpp:
+        (WebCore::computeClippedRectInTarget):
+        (WebCore):
+        (WebCore::CCRenderSurface::createSharedQuadState):
+        (WebCore::CCRenderSurface::createReplicaSharedQuadState):
+        * platform/graphics/chromium/cc/CCRenderSurface.h:
+        (CCRenderSurface):
+        * platform/graphics/chromium/cc/CCRenderer.h:
+        (CCRenderer):
+        * platform/graphics/chromium/cc/CCSharedQuadState.cpp:
+        (WebCore::CCSharedQuadState::create):
+        (WebCore::CCSharedQuadState::CCSharedQuadState):
+        * platform/graphics/chromium/cc/CCSharedQuadState.h:
+        (CCSharedQuadState):
+        * platform/graphics/chromium/cc/CCTiledLayerImpl.cpp:
+        (WebCore::CCTiledLayerImpl::appendQuads):
+
 2012-08-09  Mike West  <mkwst@chromium.org>
 
         Content Security Policy directives that begin with an invalid character should log a console warning.
index cfe6c78..29e387e 100644 (file)
@@ -162,9 +162,6 @@ public:
     const IntRect& visibleContentRect() const { return m_visibleContentRect; }
     void setVisibleContentRect(const IntRect& visibleContentRect) { m_visibleContentRect = visibleContentRect; }
 
-    const IntRect& scissorRect() const { return m_scissorRect; }
-    void setScissorRect(const IntRect& scissorRect) { m_scissorRect = scissorRect; }
-
     void setScrollPosition(const IntPoint&);
     const IntPoint& scrollPosition() const { return m_scrollPosition; }
 
@@ -350,10 +347,6 @@ private:
     // Uses layer's content space.
     IntRect m_visibleContentRect;
 
-    // During drawing, identifies the region outside of which nothing should be drawn.
-    // This is the intersection of the layer's drawableContentRect and damage (if damage tracking is enabled).
-    // Uses target surface's space.
-    IntRect m_scissorRect;
     IntPoint m_scrollPosition;
     IntSize m_maxScrollPosition;
     bool m_scrollable;
index d2c6ce5..7f9471a 100644 (file)
@@ -284,35 +284,24 @@ void LayerRendererChromium::viewportChanged()
     m_isViewportChanged = true;
 }
 
-void LayerRendererChromium::clearFramebuffer(DrawingFrame& frame, const FloatRect& framebufferDamageRect)
+void LayerRendererChromium::clearFramebuffer(DrawingFrame& frame)
 {
-    // On DEBUG builds, opaque render passes are cleared to blue to easily see regions that were not drawn on the screen. If we
-    // are using partial swap / scissor optimization, then the surface should only
-    // clear the damaged region, so that we don't accidentally clear un-changed portions
-    // of the screen.
-
+    // On DEBUG builds, opaque render passes are cleared to blue to easily see regions that were not drawn on the screen.
     if (frame.currentRenderPass->hasTransparentBackground())
         GLC(m_context, m_context->clearColor(0, 0, 0, 0));
     else
         GLC(m_context, m_context->clearColor(0, 0, 1, 1));
 
-    if (m_capabilities.usingPartialSwap)
-        setScissorToRect(frame, enclosingIntRect(framebufferDamageRect));
-    else
-        GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
-
 #if defined(NDEBUG)
     if (frame.currentRenderPass->hasTransparentBackground())
 #endif
         m_context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
-
-    GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST));
 }
 
 // static
 IntSize LayerRendererChromium::renderPassTextureSize(const CCRenderPass* pass)
 {
-    return pass->framebufferOutputRect().size();
+    return pass->outputRect().size();
 }
 
 // static
@@ -363,7 +352,7 @@ bool LayerRendererChromium::haveCachedResourcesForRenderPassId(int id) const
     return texture && texture->id() && texture->isComplete();
 }
 
-void LayerRendererChromium::drawFrame(const CCRenderPassList& renderPassesInDrawOrder, const CCRenderPassIdHashMap& renderPassesById, const FloatRect& rootScissorRect)
+void LayerRendererChromium::drawFrame(const CCRenderPassList& renderPassesInDrawOrder, const CCRenderPassIdHashMap& renderPassesById)
 {
     const CCRenderPass* rootRenderPass = renderPassesInDrawOrder.last();
     ASSERT(rootRenderPass);
@@ -372,16 +361,17 @@ void LayerRendererChromium::drawFrame(const CCRenderPassList& renderPassesInDraw
     frame.renderPassesById = &renderPassesById;
     frame.rootRenderPass = rootRenderPass;
 
-    beginDrawingFrame();
+    frame.rootDamageRect = m_capabilities.usingPartialSwap ? frame.rootRenderPass->damageRect() : frame.rootRenderPass->outputRect();
+    frame.rootDamageRect.intersect(IntRect(IntPoint::zero(), viewportSize()));
 
-    for (size_t i = 0; i < renderPassesInDrawOrder.size(); ++i) {
-        const CCRenderPass* renderPass = renderPassesInDrawOrder[i];
+    beginDrawingFrame();
 
-        FloatRect rootScissorRectInCurrentSurface = renderPass->targetSurface()->computeRootScissorRectInCurrentSurface(rootScissorRect);
-        drawRenderPass(frame, renderPass, rootScissorRectInCurrentSurface);
-    }
+    for (size_t i = 0; i < renderPassesInDrawOrder.size(); ++i)
+        drawRenderPass(frame, renderPassesInDrawOrder[i]);
 
     finishDrawingFrame();
+
+    m_swapBufferRect.unite(enclosingIntRect(frame.rootDamageRect));
 }
 
 void LayerRendererChromium::beginDrawingFrame()
@@ -418,28 +408,39 @@ void LayerRendererChromium::doNoOp()
     GLC(m_context, m_context->flush());
 }
 
-void LayerRendererChromium::drawRenderPass(DrawingFrame& frame, const CCRenderPass* renderPass, const FloatRect& framebufferDamageRect)
+void LayerRendererChromium::drawRenderPass(DrawingFrame& frame, const CCRenderPass* renderPass)
 {
     if (!useRenderPass(frame, renderPass))
         return;
 
-    clearFramebuffer(frame, framebufferDamageRect);
+    FloatRect scissorRect = renderPass->outputRect();
+    if (frame.rootDamageRect != frame.rootRenderPass->outputRect()) {
+        WebTransformationMatrix inverseTransformToRoot = renderPass->transformToRootTarget().inverse();
+        scissorRect.intersect(CCMathUtil::projectClippedRect(inverseTransformToRoot, frame.rootDamageRect));
+    }
+
+    if (scissorRect != renderPass->outputRect())
+        setScissorToRect(frame, enclosingIntRect(scissorRect));
+    else
+        GLC(m_context, m_context->disable(GraphicsContext3D::SCISSOR_TEST));
+
+    clearFramebuffer(frame);
 
     const CCQuadList& quadList = renderPass->quadList();
     for (CCQuadList::constBackToFrontIterator it = quadList.backToFrontBegin(); it != quadList.backToFrontEnd(); ++it)
-        drawQuad(frame, it->get());
+        drawQuad(frame, it->get(), scissorRect);
+
+    CachedTexture* texture = m_renderPassTextures.get(renderPass->id());
+    if (texture)
+        texture->setIsComplete(!renderPass->hasOcclusionFromOutsideTargetSurface());
 }
 
-void LayerRendererChromium::drawQuad(DrawingFrame& frame, const CCDrawQuad* quad)
+void LayerRendererChromium::drawQuad(DrawingFrame& frame, const CCDrawQuad* quad, FloatRect scissorRect)
 {
-    IntRect scissorRect = quad->scissorRect();
-
-    ASSERT(!scissorRect.isEmpty());
+    scissorRect.intersect(quad->clippedRectInTarget());
     if (scissorRect.isEmpty())
         return;
 
-    setScissorToRect(frame, scissorRect);
-
     if (quad->needsBlending())
         GLC(m_context, m_context->enable(GraphicsContext3D::BLEND));
     else
@@ -508,6 +509,7 @@ void LayerRendererChromium::drawDebugBorderQuad(DrawingFrame& frame, const CCDeb
     ASSERT(program && program->initialized());
     GLC(context(), context()->useProgram(program->program()));
 
+    // Use the full quadRect for debug quads to not move the edges based on partial swaps.
     const IntRect& layerRect = quad->quadRect();
     WebTransformationMatrix renderMatrix = quad->quadTransform();
     renderMatrix.translate(0.5 * layerRect.width() + layerRect.x(), 0.5 * layerRect.height() + layerRect.y());
@@ -579,7 +581,7 @@ PassOwnPtr<CCScopedTexture> LayerRendererChromium::drawBackgroundFilters(Drawing
     deviceRect.move(-left, -top);
     deviceRect.expand(left + right, top + bottom);
 
-    deviceRect.intersect(frame.currentRenderPass->framebufferOutputRect());
+    deviceRect.intersect(frame.currentRenderPass->outputRect());
 
     OwnPtr<CCScopedTexture> deviceBackgroundTexture = CCScopedTexture::create(m_resourceProvider);
     if (!getFramebufferTexture(deviceBackgroundTexture.get(), deviceRect))
@@ -798,7 +800,7 @@ static void tileUniformLocation(T program, TileProgramUniforms& uniforms)
 
 void LayerRendererChromium::drawTileQuad(DrawingFrame& frame, const CCTileDrawQuad* quad)
 {
-    const IntRect& tileRect = quad->quadVisibleRect();
+    IntRect tileRect = quad->quadVisibleRect();
 
     FloatRect clampRect(tileRect);
     // Clamp texture coordinates to avoid sampling outside the layer
@@ -815,7 +817,7 @@ void LayerRendererChromium::drawTileQuad(DrawingFrame& frame, const CCTileDrawQu
     FloatSize clampOffset = clampRect.minXMinYCorner() - FloatRect(tileRect).minXMinYCorner();
 
     FloatPoint textureOffset = quad->textureOffset() + clampOffset +
-                               IntPoint(quad->quadVisibleRect().location() - quad->quadRect().location());
+                               IntPoint(tileRect.location() - quad->quadRect().location());
 
     // Map clamping rectangle to unit square.
     float vertexTexTranslateX = -clampRect.x() / clampRect.width();
@@ -906,7 +908,7 @@ void LayerRendererChromium::drawTileQuad(DrawingFrame& frame, const CCTileDrawQu
         CCLayerQuad::Edge topEdge(topLeft, topRight);
         CCLayerQuad::Edge rightEdge(topRight, bottomRight);
 
-        // Only apply anti-aliasing to edges not clipped during culling.
+        // Only apply anti-aliasing to edges not clipped by culling or scissoring.
         if (quad->topEdgeAA() && tileRect.y() == quad->quadRect().y())
             topEdge = deviceLayerEdges.top();
         if (quad->leftEdgeAA() && tileRect.x() == quad->quadRect().x())
@@ -1219,7 +1221,7 @@ void LayerRendererChromium::finish()
     m_context->finish();
 }
 
-bool LayerRendererChromium::swapBuffers(const IntRect& subBuffer)
+bool LayerRendererChromium::swapBuffers()
 {
     ASSERT(m_visible);
     ASSERT(!m_isFramebufferDiscarded);
@@ -1229,14 +1231,16 @@ bool LayerRendererChromium::swapBuffers(const IntRect& subBuffer)
 
     if (m_capabilities.usingPartialSwap) {
         // If supported, we can save significant bandwidth by only swapping the damaged/scissored region (clamped to the viewport)
-        IntRect clippedSubBuffer = subBuffer;
-        clippedSubBuffer.intersect(IntRect(IntPoint::zero(), viewportSize()));
-        int flippedYPosOfRectBottom = viewportHeight() - clippedSubBuffer.y() - clippedSubBuffer.height();
-        m_context->postSubBufferCHROMIUM(clippedSubBuffer.x(), flippedYPosOfRectBottom, clippedSubBuffer.width(), clippedSubBuffer.height());
-    } else
+        m_swapBufferRect.intersect(IntRect(IntPoint(), viewportSize()));
+        int flippedYPosOfRectBottom = viewportHeight() - m_swapBufferRect.y() - m_swapBufferRect.height();
+        m_context->postSubBufferCHROMIUM(m_swapBufferRect.x(), flippedYPosOfRectBottom, m_swapBufferRect.width(), m_swapBufferRect.height());
+    } else {
         // Note that currently this has the same effect as swapBuffers; we should
         // consider exposing a different entry point on WebGraphicsContext3D.
         m_context->prepareTexture();
+    }
+
+    m_swapBufferRect = IntRect();
 
     return true;
 }
@@ -1392,19 +1396,16 @@ bool LayerRendererChromium::useRenderPass(DrawingFrame& frame, const CCRenderPas
     if (renderPass == frame.rootRenderPass) {
         frame.currentFramebufferLock.clear();
         GLC(m_context, m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0));
-        setDrawFramebufferRect(frame, renderPass->framebufferOutputRect(), true);
+        setDrawFramebufferRect(frame, renderPass->outputRect(), true);
         return true;
     }
 
     CachedTexture* texture = m_renderPassTextures.get(renderPass->id());
     ASSERT(texture);
-
-    texture->setIsComplete(!renderPass->hasOcclusionFromOutsideTargetSurface());
-
     if (!texture->id() && !texture->allocate(CCRenderer::ImplPool, renderPassTextureSize(renderPass), renderPassTextureFormat(renderPass), CCResourceProvider::TextureUsageFramebuffer))
         return false;
 
-    return bindFramebufferToTexture(frame, texture, renderPass->framebufferOutputRect());
+    return bindFramebufferToTexture(frame, texture, renderPass->outputRect());
 }
 
 bool LayerRendererChromium::useScopedTexture(DrawingFrame& frame, const CCScopedTexture* texture, const IntRect& viewportRect)
@@ -1441,7 +1442,7 @@ bool LayerRendererChromium::bindFramebufferToTexture(DrawingFrame& frame, const
 // scissorRect has its origin at the top left corner of the current visible rect.
 void LayerRendererChromium::setScissorToRect(DrawingFrame& frame, const IntRect& scissorRect)
 {
-    IntRect framebufferOutputRect = frame.currentRenderPass->framebufferOutputRect();
+    IntRect framebufferOutputRect = frame.currentRenderPass->outputRect();
 
     GLC(m_context, m_context->enable(GraphicsContext3D::SCISSOR_TEST));
 
index 6842f0c..1791033 100644 (file)
@@ -80,14 +80,14 @@ public:
     virtual void decideRenderPassAllocationsForFrame(const CCRenderPassList&) OVERRIDE;
     virtual bool haveCachedResourcesForRenderPassId(int id) const OVERRIDE;
 
-    virtual void drawFrame(const CCRenderPassList&, const CCRenderPassIdHashMap&, const FloatRect& rootScissorRect) OVERRIDE;
+    virtual void drawFrame(const CCRenderPassList&, const CCRenderPassIdHashMap&) OVERRIDE;
 
     // waits for rendering to finish
     virtual void finish() OVERRIDE;
 
     virtual void doNoOp() OVERRIDE;
     // puts backbuffer onscreen
-    virtual bool swapBuffers(const IntRect& subBuffer) OVERRIDE;
+    virtual bool swapBuffers() OVERRIDE;
 
     static void debugGLCall(WebKit::WebGraphicsContext3D*, const char* command, const char* file, int line);
 
@@ -122,6 +122,8 @@ private:
         const CCScopedTexture* currentTexture;
         OwnPtr<CCScopedLockResourceForWrite> currentFramebufferLock;
 
+        FloatRect rootDamageRect;
+
         WebKit::WebTransformationMatrix projectionMatrix;
         WebKit::WebTransformationMatrix windowMatrix;
 
@@ -135,10 +137,10 @@ private:
     static void toGLMatrix(float*, const WebKit::WebTransformationMatrix&);
 
     void beginDrawingFrame();
-    void drawRenderPass(DrawingFrame&, const CCRenderPass*, const FloatRect& framebufferDamageRect);
+    void drawRenderPass(DrawingFrame&, const CCRenderPass*);
     void finishDrawingFrame();
 
-    void drawQuad(DrawingFrame&, const CCDrawQuad*);
+    void drawQuad(DrawingFrame&, const CCDrawQuad*, FloatRect scissorRect);
     void drawCheckerboardQuad(DrawingFrame&, const CCCheckerboardDrawQuad*);
     void drawDebugBorderQuad(DrawingFrame&, const CCDebugBorderDrawQuad*);
     PassOwnPtr<CCScopedTexture> drawBackgroundFilters(DrawingFrame&, const CCRenderPassDrawQuad*, const WebKit::WebFilterOperations&, const WebKit::WebTransformationMatrix& deviceTransform);
@@ -167,7 +169,7 @@ private:
 
     bool bindFramebufferToTexture(DrawingFrame&, const CCScopedTexture*, const IntRect& viewportRect);
 
-    void clearFramebuffer(DrawingFrame&, const FloatRect& framebufferDamageRect);
+    void clearFramebuffer(DrawingFrame&);
 
     bool makeContextCurrent();
 
@@ -279,6 +281,7 @@ private:
 
     WebKit::WebGraphicsContext3D* m_context;
 
+    IntRect m_swapBufferRect;
     bool m_isViewportChanged;
     bool m_isFramebufferDiscarded;
     bool m_isUsingBindUniform;
index 7c280a0..ee9be67 100644 (file)
@@ -60,11 +60,5 @@ FloatRect RenderSurfaceChromium::drawableContentRect() const
     return drawableContentRect;
 }
 
-FloatRect RenderSurfaceChromium::computeRootScissorRectInCurrentSurface(const FloatRect& rootScissorRect) const
-{
-    WebTransformationMatrix inverseScreenSpaceTransform = m_screenSpaceTransform.inverse();
-    return CCMathUtil::projectClippedRect(inverseScreenSpaceTransform, rootScissorRect);
-}
-
 }
 #endif // USE(ACCELERATED_COMPOSITING)
index 034be58..7b11f6a 100644 (file)
@@ -79,16 +79,12 @@ public:
     const IntRect& clipRect() const { return m_clipRect; }
     void setClipRect(const IntRect& clipRect) { m_clipRect = clipRect; }
 
-    const IntRect& scissorRect() const { return m_scissorRect; }
-    void setScissorRect(const IntRect& scissorRect) { m_scissorRect = scissorRect; }
-
     void clearLayerList() { m_layerList.clear(); }
     Vector<RefPtr<LayerChromium> >& layerList() { return m_layerList; }
 
     void setNearestAncestorThatMovesPixels(RenderSurfaceChromium* surface) { m_nearestAncestorThatMovesPixels = surface; }
     const RenderSurfaceChromium* nearestAncestorThatMovesPixels() const { return m_nearestAncestorThatMovesPixels; }
 
-    FloatRect computeRootScissorRectInCurrentSurface(const FloatRect& rootScissorRect) const;
 private:
     LayerChromium* m_owningLayer;
 
@@ -107,10 +103,6 @@ private:
     // Uses the space of the surface's target surface.
     IntRect m_clipRect;
 
-    // During drawing, identifies the region outside of which nothing should be drawn.
-    // Uses the space of the surface's target surface.
-    IntRect m_scissorRect;
-
     Vector<RefPtr<LayerChromium> > m_layerList;
 
     // The nearest ancestor target surface that will contain the contents of this surface, and that is going
index faf6b4f..bcda345 100644 (file)
@@ -62,12 +62,11 @@ public:
     IntRect quadRect() const { return m_quadRect; }
     const WebKit::WebTransformationMatrix& quadTransform() const { return m_sharedQuadState->quadTransform; }
     IntRect visibleContentRect() const { return m_sharedQuadState->visibleContentRect; }
-    IntRect scissorRect() const { return m_sharedQuadState->scissorRect; }
+    IntRect clippedRectInTarget() const { return m_sharedQuadState->clippedRectInTarget; }
     float opacity() const { return m_sharedQuadState->opacity; }
     // For the purposes of blending, what part of the contents of this quad are opaque?
     IntRect opaqueRect() const;
     bool needsBlending() const { return m_needsBlending || !opaqueRect().contains(m_quadVisibleRect); }
-    bool isLayerAxisAlignedIntRect() const { return m_sharedQuadState->isLayerAxisAlignedIntRect(); }
 
     // Allows changing the rect that gets drawn to make it smaller. Parameter passed
     // in will be clipped to quadRect().
index 288aa88..a11dcd2 100644 (file)
@@ -146,7 +146,7 @@ bool CCLayerImpl::descendantDrawsContent()
 
 PassOwnPtr<CCSharedQuadState> CCLayerImpl::createSharedQuadState(int id) const
 {
-    return CCSharedQuadState::create(id, m_drawTransform, m_visibleContentRect, m_scissorRect, m_drawOpacity, m_opaque);
+    return CCSharedQuadState::create(id, m_drawTransform, m_visibleContentRect, m_drawableContentRect, m_drawOpacity, m_opaque);
 }
 
 void CCLayerImpl::willDraw(CCResourceProvider*)
index 9261758..ff089b5 100644 (file)
@@ -177,9 +177,6 @@ public:
     bool drawOpacityIsAnimating() const { return m_drawOpacityIsAnimating; }
     void setDrawOpacityIsAnimating(bool drawOpacityIsAnimating) { m_drawOpacityIsAnimating = drawOpacityIsAnimating; }
 
-    const IntRect& scissorRect() const { return m_scissorRect; }
-    void setScissorRect(const IntRect& rect) { m_scissorRect = rect; }
-
     CCLayerImpl* renderTarget() const { ASSERT(!m_renderTarget || m_renderTarget->renderSurface()); return m_renderTarget; }
     void setRenderTarget(CCLayerImpl* target) { m_renderTarget = target; }
 
@@ -386,10 +383,6 @@ private:
     bool m_betweenWillDrawAndDidDraw;
 #endif
 
-    // During drawing, identifies the region outside of which nothing should be drawn.
-    // Uses target surface's space.
-    IntRect m_scissorRect;
-
     // Render surface associated with this layer. The layer and its descendants
     // will render to this surface.
     OwnPtr<CCRenderSurface> m_renderSurface;
index f7dbfba..0f563bd 100644 (file)
@@ -481,9 +481,7 @@ void CCLayerTreeHost::updateLayers(LayerChromium* rootLayer, CCTextureUpdateQueu
     {
         TRACE_EVENT0("cc", "CCLayerTreeHost::updateLayers::calcDrawEtc");
         CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer, deviceViewportSize(), m_deviceScaleFactor, layerRendererCapabilities().maxTextureSize, updateList);
-
-        FloatRect rootScissorRect(FloatPoint(0, 0), deviceViewportSize());
-        CCLayerTreeHostCommon::calculateVisibleAndScissorRects(updateList, rootScissorRect);
+        CCLayerTreeHostCommon::calculateVisibleRects(updateList);
     }
 
     // Reset partial texture update requests.
@@ -593,7 +591,7 @@ bool CCLayerTreeHost::paintLayerContents(const LayerList& renderSurfaceLayerList
 
     bool needMoreUpdates = false;
     bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off.
-    CCOcclusionTracker occlusionTracker(IntRect(IntPoint(), deviceViewportSize()), recordMetricsForFrame);
+    CCOcclusionTracker occlusionTracker(m_rootLayer->renderSurface()->contentRect(), recordMetricsForFrame);
     occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingSize);
 
     prioritizeTextures(renderSurfaceLayerList, occlusionTracker.overdrawMetrics());
index 2a79aea..9f4a035 100644 (file)
@@ -65,50 +65,6 @@ IntRect CCLayerTreeHostCommon::calculateVisibleRect(const IntRect& targetSurface
     return layerRect;
 }
 
-template<typename LayerType, typename RenderSurfaceType>
-static IntRect calculateLayerScissorRect(LayerType* layer, const FloatRect& rootScissorRect)
-{
-    LayerType* renderTarget = layer->renderTarget();
-    RenderSurfaceType* targetSurface = renderTarget->renderSurface();
-
-    FloatRect rootScissorRectInTargetSurface = targetSurface->computeRootScissorRectInCurrentSurface(rootScissorRect);
-    FloatRect clipAndDamage = intersection(rootScissorRectInTargetSurface, layer->drawableContentRect());
-
-    return enclosingIntRect(clipAndDamage);
-}
-
-template<typename LayerType, typename RenderSurfaceType>
-static IntRect calculateSurfaceScissorRect(LayerType* layer, const FloatRect& rootScissorRect)
-{
-    LayerType* parentLayer = layer->parent();
-    LayerType* renderTarget = parentLayer->renderTarget();
-
-    RenderSurfaceType* targetSurface = renderTarget->renderSurface();
-    ASSERT(targetSurface);
-
-    RenderSurfaceType* currentSurface = layer->renderSurface();
-    ASSERT(currentSurface);
-
-    FloatRect clipRect = currentSurface->clipRect();
-
-    // For surfaces, empty clipRect means that the surface does not clip anything.
-    if (clipRect.isEmpty())
-        clipRect = intersection(targetSurface->contentRect(), currentSurface->drawableContentRect());
-    else
-        clipRect.intersect(currentSurface->drawableContentRect());
-
-    FloatRect rootScissorRectInTargetSurface = targetSurface->computeRootScissorRectInCurrentSurface(rootScissorRect);
-
-    FloatRect clipAndDamage = intersection(rootScissorRectInTargetSurface, clipRect);
-
-    // If the layer has background filters that move pixels, we cannot scissor as tightly.
-    // FIXME: this should be able to be a tighter scissor, perhaps expanded by the filter outsets?
-    if (layer->backgroundFilters().hasFilterThatMovesPixels())
-        clipAndDamage = rootScissorRectInTargetSurface;
-
-    return enclosingIntRect(clipAndDamage);
-}
-
 template<typename LayerType>
 static inline bool layerIsInExisting3DRenderingContext(LayerType* layer)
 {
@@ -819,7 +775,7 @@ static void calculateDrawTransformsInternal(LayerType* layer, LayerType* rootLay
 // tree pass, revise calculateVisibleContentRect() so that this can be done in a single
 // pass inside calculateDrawTransformsInternal<>().
 template<typename LayerType, typename LayerList, typename RenderSurfaceType>
-static void calculateVisibleAndScissorRectsInternal(const LayerList& renderSurfaceLayerList, const FloatRect& rootScissorRect)
+static void calculateVisibleRectsInternal(const LayerList& renderSurfaceLayerList)
 {
     // Use BackToFront since it's cheap and this isn't order-dependent.
     typedef CCLayerIterator<LayerType, LayerList, RenderSurfaceType, CCLayerIteratorActions::BackToFront> CCLayerIteratorType;
@@ -836,12 +792,6 @@ static void calculateVisibleAndScissorRectsInternal(const LayerList& renderSurfa
         } else if (it.representsItself()) {
             IntRect visibleContentRect = calculateVisibleContentRect(*it);
             it->setVisibleContentRect(visibleContentRect);
-
-            IntRect scissorRect = calculateLayerScissorRect<LayerType, RenderSurfaceType>(*it, rootScissorRect);
-            it->setScissorRect(scissorRect);
-        } else if (it.representsContributingRenderSurface()) {
-            IntRect scissorRect = calculateSurfaceScissorRect<LayerType, RenderSurfaceType>(*it, rootScissorRect);
-            it->renderSurface()->setScissorRect(scissorRect);
         }
     }
 }
@@ -874,14 +824,14 @@ void CCLayerTreeHostCommon::calculateDrawTransforms(CCLayerImpl* rootLayer, cons
                                                                                                                 rootLayer->renderSurface()->layerList(), layerSorter, maxTextureSize, deviceScaleFactor, totalDrawableContentRect);
 }
 
-void CCLayerTreeHostCommon::calculateVisibleAndScissorRects(Vector<RefPtr<LayerChromium> >& renderSurfaceLayerList, const FloatRect& rootScissorRect)
+void CCLayerTreeHostCommon::calculateVisibleRects(Vector<RefPtr<LayerChromium> >& renderSurfaceLayerList)
 {
-    calculateVisibleAndScissorRectsInternal<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium>(renderSurfaceLayerList, rootScissorRect);
+    calculateVisibleRectsInternal<LayerChromium, Vector<RefPtr<LayerChromium> >, RenderSurfaceChromium>(renderSurfaceLayerList);
 }
 
-void CCLayerTreeHostCommon::calculateVisibleAndScissorRects(Vector<CCLayerImpl*>& renderSurfaceLayerList, const FloatRect& rootScissorRect)
+void CCLayerTreeHostCommon::calculateVisibleRects(Vector<CCLayerImpl*>& renderSurfaceLayerList)
 {
-    calculateVisibleAndScissorRectsInternal<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface>(renderSurfaceLayerList, rootScissorRect);
+    calculateVisibleRectsInternal<CCLayerImpl, Vector<CCLayerImpl*>, CCRenderSurface>(renderSurfaceLayerList);
 }
 
 static bool pointHitsRect(const IntPoint& viewportPoint, const WebTransformationMatrix& localSpaceToScreenSpaceTransform, FloatRect localSpaceRect)
index b6e2a07..4e96904 100644 (file)
@@ -44,8 +44,8 @@ public:
     static void calculateDrawTransforms(LayerChromium* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, int maxTextureSize, Vector<RefPtr<LayerChromium> >& renderSurfaceLayerList);
     static void calculateDrawTransforms(CCLayerImpl* rootLayer, const IntSize& deviceViewportSize, float deviceScaleFactor, CCLayerSorter*, int maxTextureSize, Vector<CCLayerImpl*>& renderSurfaceLayerList);
 
-    static void calculateVisibleAndScissorRects(Vector<CCLayerImpl*>& renderSurfaceLayerList, const FloatRect& rootScissorRect);
-    static void calculateVisibleAndScissorRects(Vector<RefPtr<LayerChromium> >& renderSurfaceLayerList, const FloatRect& rootScissorRect);
+    static void calculateVisibleRects(Vector<CCLayerImpl*>& renderSurfaceLayerList);
+    static void calculateVisibleRects(Vector<RefPtr<LayerChromium> >& renderSurfaceLayerList);
 
     // Performs hit testing for a given renderSurfaceLayerList.
     static CCLayerImpl* findLayerThatIsHitByPoint(const IntPoint& viewportPoint, Vector<CCLayerImpl*>& renderSurfaceLayerList);
index 5ac1931..9f5ff3f 100644 (file)
@@ -256,15 +256,9 @@ void CCLayerTreeHostImpl::calculateRenderSurfaceLayerList(CCLayerList& renderSur
     {
         TRACE_EVENT0("cc", "CCLayerTreeHostImpl::calcDrawEtc");
         CCLayerTreeHostCommon::calculateDrawTransforms(m_rootLayerImpl.get(), deviceViewportSize(), m_deviceScaleFactor, &m_layerSorter, layerRendererCapabilities().maxTextureSize, renderSurfaceLayerList);
+        CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
         trackDamageForAllSurfaces(m_rootLayerImpl.get(), renderSurfaceLayerList);
-
-        if (layerRendererCapabilities().usingPartialSwap)
-            m_rootScissorRect = m_rootLayerImpl->renderSurface()->damageTracker()->currentDamageRect();
-        else
-            m_rootScissorRect = FloatRect(FloatPoint(0, 0), deviceViewportSize());
-
-        CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, m_rootScissorRect);
     }
 }
 
@@ -276,8 +270,6 @@ bool CCLayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
 
     TRACE_EVENT1("cc", "CCLayerTreeHostImpl::calculateRenderPasses", "renderSurfaceLayerList.size()", static_cast<long long unsigned>(frame.renderSurfaceLayerList->size()));
 
-    m_rootLayerImpl->setScissorRect(enclosingIntRect(m_rootScissorRect));
-
     // Create the render passes in dependency order.
     HashMap<CCRenderSurface*, CCRenderPass*> surfacePassMap;
     for (int surfaceIndex = frame.renderSurfaceLayerList->size() - 1; surfaceIndex >= 0 ; --surfaceIndex) {
@@ -286,6 +278,7 @@ bool CCLayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
 
         int renderPassId = renderSurfaceLayer->id();
         OwnPtr<CCRenderPass> pass = CCRenderPass::create(renderSurface, renderPassId);
+        pass->setDamageRect(renderSurface->damageTracker()->currentDamageRect());
         pass->setFilters(renderSurfaceLayer->filters());
         pass->setBackgroundFilters(renderSurfaceLayer->backgroundFilters());
 
@@ -295,7 +288,7 @@ bool CCLayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
     }
 
     bool recordMetricsForFrame = true; // FIXME: In the future, disable this when about:tracing is off.
-    CCOcclusionTrackerImpl occlusionTracker(enclosingIntRect(m_rootScissorRect), recordMetricsForFrame);
+    CCOcclusionTrackerImpl occlusionTracker(m_rootLayerImpl->renderSurface()->contentRect(), recordMetricsForFrame);
     occlusionTracker.setMinimumTrackingSize(m_settings.minimumOcclusionTrackingSize);
 
     if (settings().showOccludingRects)
@@ -317,10 +310,10 @@ bool CCLayerTreeHostImpl::calculateRenderPasses(FrameData& frame)
 
         occlusionTracker.enterLayer(it);
 
-        if (it.representsContributingRenderSurface() && !it->renderSurface()->scissorRect().isEmpty()) {
+        if (it.representsContributingRenderSurface()) {
             CCRenderPass* contributingRenderPass = surfacePassMap.get(it->renderSurface());
             pass->appendQuadsForRenderSurfaceLayer(*it, contributingRenderPass, &occlusionTracker);
-        } else if (it.representsItself() && !it->visibleContentRect().isEmpty() && !it->scissorRect().isEmpty()) {
+        } else if (it.representsItself() && !it->visibleContentRect().isEmpty()) {
             bool hasOcclusionFromOutsideTargetSurface;
             if (occlusionTracker.occluded(*it, it->visibleContentRect(), &hasOcclusionFromOutsideTargetSurface)) {
                 if (hasOcclusionFromOutsideTargetSurface)
@@ -545,11 +538,16 @@ void CCLayerTreeHostImpl::drawLayers(const FrameData& frame)
     // RenderWidget.
     m_fpsCounter->markBeginningOfFrame(currentTime());
 
-    m_layerRenderer->drawFrame(frame.renderPasses, frame.renderPassesById, m_rootScissorRect);
+    m_layerRenderer->drawFrame(frame.renderPasses, frame.renderPassesById);
 
-    for (unsigned int i = 0; i < frame.renderPasses.size(); i++)
+    for (unsigned int i = 0; i < frame.renderPasses.size(); i++) {
         frame.renderPasses[i]->targetSurface()->damageTracker()->didDrawDamagedArea();
 
+        // Once a RenderPass has been drawn, its damage should be cleared in
+        // case the RenderPass will be reused next frame.
+        frame.renderPasses[i]->setDamageRect(FloatRect());
+    }
+
     if (m_settings.showDebugRects())
         m_debugRectHistory->saveDebugRectsForCurrentFrame(m_rootLayerImpl.get(), *frame.renderSurfaceLayerList, frame.occludingScreenSpaceRects, settings());
 
@@ -584,7 +582,7 @@ bool CCLayerTreeHostImpl::swapBuffers()
     ASSERT(m_layerRenderer);
 
     m_fpsCounter->markEndOfFrame();
-    return m_layerRenderer->swapBuffers(enclosingIntRect(m_rootScissorRect));
+    return m_layerRenderer->swapBuffers();
 }
 
 void CCLayerTreeHostImpl::didLoseContext()
index c14dd20..dce984f 100644 (file)
@@ -289,8 +289,6 @@ private:
 
     CCLayerSorter m_layerSorter;
 
-    FloatRect m_rootScissorRect;
-
     // List of visible layers for the most recently prepared frame. Used for
     // rendering and input event hit testing.
     CCLayerList m_renderSurfaceLayerList;
index 1b5d397..a9a97cc 100644 (file)
@@ -471,7 +471,7 @@ IntRect CCOcclusionTrackerBase<LayerType, RenderSurfaceType>::layerScissorRectIn
 {
     // FIXME: we could remove this helper function, but unit tests currently override this
     //        function, and they need to be verified/adjusted before this can be removed.
-    return layer->scissorRect();
+    return layer->drawableContentRect();
 }
 
 // Declare the possible functions here for the linker.
index c1af9d1..e438463 100644 (file)
@@ -46,7 +46,8 @@ PassOwnPtr<CCRenderPass> CCRenderPass::create(CCRenderSurface* targetSurface, in
 CCRenderPass::CCRenderPass(CCRenderSurface* targetSurface, int id)
     : m_id(id)
     , m_targetSurface(targetSurface)
-    , m_framebufferOutputRect(targetSurface->contentRect())
+    , m_transformToRootTarget(targetSurface->screenSpaceTransform())
+    , m_outputRect(targetSurface->contentRect())
     , m_hasTransparentBackground(true)
     , m_hasOcclusionFromOutsideTargetSurface(false)
 {
@@ -106,7 +107,11 @@ void CCRenderPass::appendQuadsToFillScreen(CCLayerImpl* rootLayer, SkColor scree
 
     // Manually create the quad state for the gutter quads, as the root layer
     // doesn't have any bounds and so can't generate this itself.
-    OwnPtr<CCSharedQuadState> sharedQuadState = rootLayer->createSharedQuadState(m_sharedQuadStateList.size());
+    // FIXME: Make the gutter quads generated by the solid color layer (make it smarter about generating quads to fill unoccluded areas).
+    IntRect rootTargetRect = rootLayer->renderSurface()->contentRect();
+    float opacity = 1;
+    bool opaque = true;
+    OwnPtr<CCSharedQuadState> sharedQuadState = CCSharedQuadState::create(0, rootLayer->drawTransform(), rootTargetRect, rootTargetRect, opacity, opaque);
     ASSERT(rootLayer->screenSpaceTransform().isInvertible());
     WebTransformationMatrix transformToLayerSpace = rootLayer->screenSpaceTransform().inverse();
     Vector<IntRect> fillRects = fillRegion.rects();
index 7158212..f12311b 100644 (file)
@@ -31,6 +31,7 @@
 #include "cc/CCOcclusionTracker.h"
 #include "cc/CCSharedQuadState.h"
 #include <public/WebFilterOperations.h>
+#include <public/WebTransformationMatrix.h>
 #include <wtf/HashMap.h>
 #include <wtf/PassOwnPtr.h>
 #include <wtf/Vector.h>
@@ -66,8 +67,15 @@ public:
     int id() const { return m_id; }
     CCRenderSurface* targetSurface() const { return m_targetSurface; }
 
+    // FIXME: Modify this transform when merging the RenderPass into a parent compositor.
+    // Transforms from quad's original content space to the root target's content space.
+    const WebKit::WebTransformationMatrix& transformToRootTarget() const { return m_transformToRootTarget; }
+
     // This denotes the bounds in physical pixels of the output generated by this RenderPass.
-    const IntRect& framebufferOutputRect() const { return m_framebufferOutputRect; }
+    const IntRect& outputRect() const { return m_outputRect; }
+
+    FloatRect damageRect() const { return m_damageRect; }
+    void setDamageRect(FloatRect rect) { m_damageRect = rect; }
 
     const WebKit::WebFilterOperations& filters() const { return m_filters; }
     void setFilters(const WebKit::WebFilterOperations& filters) { m_filters = filters; }
@@ -86,7 +94,9 @@ protected:
     int m_id;
     CCRenderSurface* m_targetSurface;
     CCQuadList m_quadList;
-    IntRect m_framebufferOutputRect;
+    WebKit::WebTransformationMatrix m_transformToRootTarget;
+    IntRect m_outputRect;
+    FloatRect m_damageRect;
     Vector<OwnPtr<CCSharedQuadState> > m_sharedQuadStateList;
     bool m_hasTransparentBackground;
     bool m_hasOcclusionFromOutsideTargetSurface;
index 4b271e1..ed9675e 100644 (file)
@@ -161,22 +161,38 @@ bool CCRenderSurface::surfacePropertyChangedOnlyFromDescendant() const
     return m_surfacePropertyChanged && !m_owningLayer->layerPropertyChanged();
 }
 
-PassOwnPtr<CCSharedQuadState> CCRenderSurface::createSharedQuadState(int id) const
+static inline IntRect computeClippedRectInTarget(const CCLayerImpl* owningLayer)
 {
-    bool isOpaque = false;
-    return CCSharedQuadState::create(id, m_drawTransform, m_contentRect, m_scissorRect, m_drawOpacity, isOpaque);
+    ASSERT(owningLayer->parent());
+
+    const CCLayerImpl* renderTarget = owningLayer->parent()->renderTarget();
+    const CCRenderSurface* self = owningLayer->renderSurface();
+
+    IntRect clippedRectInTarget = self->clipRect();
+    if (owningLayer->backgroundFilters().hasFilterThatMovesPixels()) {
+        // If the layer has background filters that move pixels, we cannot scissor as tightly.
+        // FIXME: this should be able to be a tighter scissor, perhaps expanded by the filter outsets?
+        clippedRectInTarget = renderTarget->renderSurface()->contentRect();
+    } else if (clippedRectInTarget.isEmpty()) {
+        // For surfaces, empty clipRect means that the surface does not clip anything.
+        clippedRectInTarget = enclosingIntRect(intersection(renderTarget->renderSurface()->contentRect(), self->drawableContentRect()));
+    } else
+        clippedRectInTarget.intersect(enclosingIntRect(self->drawableContentRect()));
+    return clippedRectInTarget;
 }
 
-PassOwnPtr<CCSharedQuadState> CCRenderSurface::createReplicaSharedQuadState(int id) const
+PassOwnPtr<CCSharedQuadState> CCRenderSurface::createSharedQuadState(int id) const
 {
+    IntRect clippedRectInTarget = computeClippedRectInTarget(m_owningLayer);
     bool isOpaque = false;
-    return CCSharedQuadState::create(id, m_replicaDrawTransform, m_contentRect, m_scissorRect, m_drawOpacity, isOpaque);
+    return CCSharedQuadState::create(id, m_drawTransform, m_contentRect, clippedRectInTarget, m_drawOpacity, isOpaque);
 }
 
-FloatRect CCRenderSurface::computeRootScissorRectInCurrentSurface(const FloatRect& rootScissorRect) const
+PassOwnPtr<CCSharedQuadState> CCRenderSurface::createReplicaSharedQuadState(int id) const
 {
-    WebTransformationMatrix inverseScreenSpaceTransform = m_screenSpaceTransform.inverse();
-    return CCMathUtil::projectClippedRect(inverseScreenSpaceTransform, rootScissorRect);
+    IntRect clippedRectInTarget = computeClippedRectInTarget(m_owningLayer);
+    bool isOpaque = false;
+    return CCSharedQuadState::create(id, m_replicaDrawTransform, m_contentRect, clippedRectInTarget, m_drawOpacity, isOpaque);
 }
 
 void CCRenderSurface::appendQuads(CCQuadSink& quadList, CCSharedQuadState* sharedQuadState, bool forReplica, int renderPassId)
index 283cbfa..eb53af2 100644 (file)
@@ -88,9 +88,6 @@ public:
     void setClipRect(const IntRect&);
     const IntRect& clipRect() const { return m_clipRect; }
 
-    void setScissorRect(const IntRect& scissorRect) { m_scissorRect = scissorRect; }
-    const IntRect& scissorRect() const { return m_scissorRect; }
-
     bool contentsChanged() const;
 
     void setContentRect(const IntRect&);
@@ -112,8 +109,6 @@ public:
 
     void appendQuads(CCQuadSink&, CCSharedQuadState*, bool forReplica, int renderPassId);
 
-    FloatRect computeRootScissorRectInCurrentSurface(const FloatRect& rootScissorRect) const;
-
 private:
     CCLayerImpl* m_owningLayer;
 
@@ -133,10 +128,6 @@ private:
     // Uses the space of the surface's target surface.
     IntRect m_clipRect;
 
-    // During drawing, identifies the region outside of which nothing should be drawn.
-    // Uses the space of the surface's target surface.
-    IntRect m_scissorRect;
-
     Vector<CCLayerImpl*> m_layerList;
 
     // The nearest ancestor target surface that will contain the contents of this surface, and that is going
index 9080564..fc31bc8 100644 (file)
@@ -77,14 +77,14 @@ public:
     virtual void decideRenderPassAllocationsForFrame(const CCRenderPassList&) { }
     virtual bool haveCachedResourcesForRenderPassId(int) const { return false; }
 
-    virtual void drawFrame(const CCRenderPassList&, const CCRenderPassIdHashMap&, const FloatRect& rootScissorRect) = 0;
+    virtual void drawFrame(const CCRenderPassList&, const CCRenderPassIdHashMap&) = 0;
 
     // waits for rendering to finish
     virtual void finish() = 0;
 
     virtual void doNoOp() { }
     // puts backbuffer onscreen
-    virtual bool swapBuffers(const IntRect& subBuffer) = 0;
+    virtual bool swapBuffers() = 0;
 
     virtual void getFramebufferPixels(void *pixels, const IntRect&) = 0;
 
index 55fee9a..e64f72f 100644 (file)
 #include "cc/CCSharedQuadState.h"
 
 #include "FloatQuad.h"
-#include "cc/CCMathUtil.h"
 
 namespace WebCore {
 
-PassOwnPtr<CCSharedQuadState> CCSharedQuadState::create(int id, const WebKit::WebTransformationMatrix& quadTransform, const IntRect& visibleContentRect, const IntRect& scissorRect, float opacity, bool opaque)
+PassOwnPtr<CCSharedQuadState> CCSharedQuadState::create(int id, const WebKit::WebTransformationMatrix& quadTransform, const IntRect& visibleContentRect, const IntRect& clippedRectInTarget, float opacity, bool opaque)
 {
-    return adoptPtr(new CCSharedQuadState(id, quadTransform, visibleContentRect, scissorRect, opacity, opaque));
+    return adoptPtr(new CCSharedQuadState(id, quadTransform, visibleContentRect, clippedRectInTarget, opacity, opaque));
 }
 
-CCSharedQuadState::CCSharedQuadState(int id, const WebKit::WebTransformationMatrix& quadTransform, const IntRect& visibleContentRect, const IntRect& scissorRect, float opacity, bool opaque)
+CCSharedQuadState::CCSharedQuadState(int id, const WebKit::WebTransformationMatrix& quadTransform, const IntRect& visibleContentRect, const IntRect& clippedRectInTarget, float opacity, bool opaque)
     : id(id)
     , quadTransform(quadTransform)
     , visibleContentRect(visibleContentRect)
-    , scissorRect(scissorRect)
+    , clippedRectInTarget(clippedRectInTarget)
     , opacity(opacity)
     , opaque(opaque)
 {
 }
 
-bool CCSharedQuadState::isLayerAxisAlignedIntRect() const
-{
-    // Note: this doesn't consider window or projection matrices.
-    // Assume that they're orthonormal and have integer scales and translations.
-    bool clipped = false;
-    FloatQuad quad = CCMathUtil::mapQuad(quadTransform, FloatQuad(IntRect(visibleContentRect)), clipped);
-    return !clipped && quad.isRectilinear() && quad.boundingBox().isExpressibleAsIntRect();
-}
-
 }
index 6dd4aa5..af12bec 100644 (file)
@@ -39,13 +39,12 @@ struct CCSharedQuadState {
     WebKit::WebTransformationMatrix quadTransform;
     // This rect lives in the content space for the quad's originating layer.
     IntRect visibleContentRect;
-    // This rect lives in the quad's target content space.
-    IntRect scissorRect;
+    IntRect clippedRectInTarget;
     float opacity;
     bool opaque;
 
-    static PassOwnPtr<CCSharedQuadState> create(int id, const WebKit::WebTransformationMatrix& quadTransform, const IntRect& visibleContentRect, const IntRect& scissorRect, float opacity, bool opaque);
-    CCSharedQuadState(int id, const WebKit::WebTransformationMatrix& quadTransform, const IntRect& visibleContentRect, const IntRect& scissorRect, float opacity, bool opaque);
+    static PassOwnPtr<CCSharedQuadState> create(int id, const WebKit::WebTransformationMatrix& quadTransform, const IntRect& visibleContentRect, const IntRect& clippedRectInTarget, float opacity, bool opaque);
+    CCSharedQuadState(int id, const WebKit::WebTransformationMatrix& quadTransform, const IntRect& visibleContentRect, const IntRect& clippedRectInTarget, float opacity, bool opaque);
     bool isLayerAxisAlignedIntRect() const;
 };
 
index ee49651..74eb2dc 100644 (file)
@@ -35,6 +35,7 @@
 #include "cc/CCCheckerboardDrawQuad.h"
 #include "cc/CCDebugBorderDrawQuad.h"
 #include "cc/CCLayerTilingData.h"
+#include "cc/CCMathUtil.h"
 #include "cc/CCQuadSink.h"
 #include "cc/CCSolidColorDrawQuad.h"
 #include "cc/CCTileDrawQuad.h"
@@ -182,7 +183,10 @@ void CCTiledLayerImpl::appendQuads(CCQuadSink& quadList, const CCSharedQuadState
             float tileHeight = static_cast<float>(m_tiler->tileSize().height());
             IntSize textureSize(tileWidth, tileHeight);
 
-            bool useAA = m_tiler->hasBorderTexels() && !sharedQuadState->isLayerAxisAlignedIntRect();
+            bool clipped = false;
+            FloatQuad visibleContentInTargetQuad = CCMathUtil::mapQuad(drawTransform(), FloatQuad(visibleContentRect()), clipped);
+            bool isAxisAlignedInTarget = !clipped && visibleContentInTargetQuad.isRectilinear();
+            bool useAA = m_tiler->hasBorderTexels() && !isAxisAlignedInTarget;
 
             bool leftEdgeAA = !i && useAA;
             bool topEdgeAA = !j && useAA;
index 82d7a85..34af389 100644 (file)
@@ -1,3 +1,50 @@
+2012-08-09  Dana Jansens  <danakj@chromium.org>
+
+        [chromium] Do partial-swap scissoring on quads during draw instead of on layers
+        https://bugs.webkit.org/show_bug.cgi?id=91800
+
+        Reviewed by Adrienne Walker.
+
+        * tests/CCDamageTrackerTest.cpp:
+        (WebKitTests::executeCalculateDrawTransformsAndVisibility):
+        * tests/CCLayerIteratorTest.cpp:
+        * tests/CCLayerTreeHostCommonTest.cpp:
+        Removed tests of the scissor rect here, as they are no longer
+        computed within CCLayerTreeHostCommon. Verify that the scissor
+        does not affect texture caching in CCLayerTreeHostImplTest now.
+        Previous scissor would affect the texture cache decisions, but
+        this was incorrect, as damaged areas are always inside the
+        scissor rect, and anything outside the scissor rect should
+        be considered as valid and complete (assuming no external
+        occlusion, which is computed outside the scissor rect now also).
+
+        * tests/CCLayerTreeHostImplTest.cpp:
+        Removed didDrawNotCalledOnScissoredLayer test, as this no longer
+        applies. didDraw will be called on layers that are outside the
+        partial swap rect, regardless.
+
+        Removed partialSwapNoUpdate test, and merged its functionality into
+        the partialSwap test while updating its expectations.
+
+        Added textureCachingWithScissor, which is loosely based on the
+        CCLayerTreeHostCommonTest.scissorRectWithClip test.
+
+        * tests/CCOcclusionTrackerTest.cpp:
+        (WebKitTests::CCOcclusionTrackerTest::calcDrawEtc):
+        (WebKitTests::CCOcclusionTrackerTestChildInRotatedChild::runMyTest):
+        (WebKitTests::CCOcclusionTrackerTestVisitTargetTwoTimes::runMyTest):
+        * tests/CCQuadCullerTest.cpp:
+        * tests/CCRenderSurfaceTest.cpp:
+        * tests/CCSolidColorLayerImplTest.cpp:
+        (CCLayerTestCommon::TEST):
+        * tests/CCTiledLayerImplTest.cpp:
+        (CCLayerTestCommon::createLayer):
+        * tests/LayerRendererChromiumTest.cpp:
+        (LayerRendererChromiumTest::swapBuffers):
+        (TEST_F):
+        (TEST):
+        * tests/TiledLayerChromiumTest.cpp:
+
 2012-08-09  Shawn Singh  <shawnsingh@chromium.org>
 
         [chromium] Pass mask scale and offset to shaders for correct masking
index 8294ca6..8f813b9 100644 (file)
@@ -55,7 +55,7 @@ void executeCalculateDrawTransformsAndVisibility(CCLayerImpl* root, Vector<CCLay
     ASSERT_FALSE(renderSurfaceLayerList.size());
 
     CCLayerTreeHostCommon::calculateDrawTransforms(root, root->bounds(), 1, &layerSorter, dummyMaxTextureSize, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, root->renderSurface()->contentRect());
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 }
 
 void clearDamageForAllSurfaces(CCLayerImpl* layer)
index 73fda4c..b5e2269 100644 (file)
@@ -148,7 +148,7 @@ TEST(CCLayerIteratorTest, simpleTree)
 
     Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
     CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer.get(), rootLayer->bounds(), 1, 256, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, rootLayer->renderSurface()->contentRect());
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     iterateBackToFront(&renderSurfaceLayerList);
     EXPECT_COUNT(rootLayer, 0, -1, 1);
@@ -191,7 +191,7 @@ TEST(CCLayerIteratorTest, complexTree)
 
     Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
     CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer.get(), rootLayer->bounds(), 1, 256, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, rootLayer->renderSurface()->contentRect());
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     iterateBackToFront(&renderSurfaceLayerList);
     EXPECT_COUNT(rootLayer, 0, -1, 1);
@@ -247,7 +247,7 @@ TEST(CCLayerIteratorTest, complexTreeMultiSurface)
 
     Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
     CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer.get(), rootLayer->bounds(), 1, 256, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, rootLayer->renderSurface()->contentRect());
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     iterateBackToFront(&renderSurfaceLayerList);
     EXPECT_COUNT(rootLayer, 0, -1, 1);
index 3285830..9fd2268 100644 (file)
@@ -79,7 +79,7 @@ void executeCalculateDrawTransformsAndVisibility(LayerChromium* rootLayer)
     // We are probably not testing what is intended if the rootLayer bounds are empty.
     ASSERT(!rootLayer->bounds().isEmpty());
     CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer, rootLayer->bounds(), 1, dummyMaxTextureSize, dummyRenderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(dummyRenderSurfaceLayerList, rootLayer->renderSurface()->contentRect());
+    CCLayerTreeHostCommon::calculateVisibleRects(dummyRenderSurfaceLayerList);
 }
 
 void executeCalculateDrawTransformsAndVisibility(CCLayerImpl* rootLayer)
@@ -93,7 +93,7 @@ void executeCalculateDrawTransformsAndVisibility(CCLayerImpl* rootLayer)
     // We are probably not testing what is intended if the rootLayer bounds are empty.
     ASSERT(!rootLayer->bounds().isEmpty());
     CCLayerTreeHostCommon::calculateDrawTransforms(rootLayer, rootLayer->bounds(), 1, 0, dummyMaxTextureSize, dummyRenderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(dummyRenderSurfaceLayerList, rootLayer->renderSurface()->contentRect());
+    CCLayerTreeHostCommon::calculateVisibleRects(dummyRenderSurfaceLayerList);
 }
 
 WebTransformationMatrix remove3DComponentOfMatrix(const WebTransformationMatrix& mat)
@@ -358,344 +358,6 @@ TEST(CCLayerTreeHostCommonTest, verifyTransformsForSingleRenderSurface)
     EXPECT_TRANSFORMATION_MATRIX_EQ(parentCompositeTransform, child->renderTarget()->renderSurface()->screenSpaceTransform());
 }
 
-TEST(CCLayerTreeHostCommonTest, scissorRectWithClip)
-{
-    DebugScopedSetImplThread thisScopeIsOnImplThread;
-
-    /*
-      Layers are created as follows:
-
-         +--------------------+
-         |                  1 |
-         |  +-----------+     |
-         |  |         2 |     |
-         |  | +-------------------+
-         |  | |   3               |
-         |  | +-------------------+
-         |  |           |     |
-         |  +-----------+     |
-         |                    |
-         |                    |
-         +--------------------+
-
-         Layers 1, 2 have render surfaces
-     */
-    OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
-    OwnPtr<CCLayerImpl> child = CCLayerImpl::create(2);
-    OwnPtr<CCLayerImpl> grandChild = CCLayerImpl::create(3);
-
-    IntRect rootRect(0, 0, 100, 100);
-    IntRect childRect(10, 10, 50, 50);
-    IntRect grandChildRect(5, 5, 150, 150);
-
-    root->setAnchorPoint(FloatPoint(0, 0));
-    root->setPosition(FloatPoint(rootRect.x(), rootRect.y()));
-    root->setBounds(IntSize(rootRect.width(), rootRect.height()));
-    root->setContentBounds(root->bounds());
-    root->setDrawsContent(true);
-
-    child->setAnchorPoint(FloatPoint(0, 0));
-    child->setPosition(FloatPoint(childRect.x(), childRect.y()));
-    child->setOpacity(0.5);
-    child->setBounds(IntSize(childRect.width(), childRect.height()));
-    child->setContentBounds(child->bounds());
-    child->setDrawsContent(true);
-
-    grandChild->setAnchorPoint(FloatPoint(0, 0));
-    grandChild->setPosition(IntPoint(grandChildRect.x(), grandChildRect.y()));
-    grandChild->setBounds(IntSize(grandChildRect.width(), grandChildRect.height()));
-    grandChild->setContentBounds(grandChild->bounds());
-    grandChild->setDrawsContent(true);
-
-    CCLayerImpl* childPtr = child.get();
-    CCLayerImpl* grandChildPtr = grandChild.get();
-
-    child->addChild(grandChild.release());
-    root->addChild(child.release());
-
-    root->setMasksToBounds(true);
-
-    Vector<CCLayerImpl*> renderSurfaceLayerList;
-    {
-        int dummyMaxTextureSize = 512;
-        CCLayerSorter layerSorter;
-        CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, &layerSorter, dummyMaxTextureSize, renderSurfaceLayerList);
-
-        FloatRect dummyDamageRect;
-        CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, dummyDamageRect);
-    }
-    
-    ASSERT_TRUE(childPtr->renderSurface());
-    ASSERT_TRUE(root->renderSurface());
-    ASSERT_FALSE(grandChildPtr->renderSurface());
-    
-    EXPECT_EQ(renderSurfaceLayerList.size(), 2U);
-    
-    ASSERT_EQ(root->renderSurface()->clipRect(), rootRect);
-    // Child surface's clipping rect is now set to root's
-    ASSERT_EQ(childPtr->renderSurface()->clipRect(), rootRect);
-    
-    // Damage the entire screen
-    IntRect rootDamage(rootRect);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, rootDamage);
-    
-    EXPECT_EQ(root->renderTarget()->renderSurface()->scissorRect(), IntRect(0, 0, 0, 0));
-    // Child's renderSurface would have expanded to include the 150x150 grandChild located at (5, 5), and then have been clipped by the parent.
-    IntRect expectedChildRenderSurfaceScissor = intersection(rootRect, IntRect(10, 10, 155, 155));
-    EXPECT_EQ(childPtr->renderTarget()->renderSurface()->scissorRect(), expectedChildRenderSurfaceScissor);
-    
-    EXPECT_EQ(root->scissorRect(), IntRect(rootRect));
-
-    // The child layer is not clipped by anything (that clip is already represented by the rootSurface clipping the child's surface)
-    // So here, the expected scissor is just the child layer's rect expressed in targetSurface (child surface) space.
-    EXPECT_EQ(childPtr->scissorRect(), IntRect(0, 0, childRect.width(), childRect.height()));
-
-    // Grand child is (indirectly) clipped by the root surface. But the scissor is expressed in the targetSurface (child surface) space.
-    EXPECT_INT_RECT_EQ(grandChildPtr->scissorRect(), IntRect(5, 5, 85, 85));
-    
-    // Empty damage
-    rootDamage = IntRect(0, 0, 0, 0);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, rootDamage);
-    
-    // Empty damage == empty scissor
-    EXPECT_EQ(root->renderTarget()->renderSurface()->scissorRect(), IntRect(0, 0, 0, 0));
-    EXPECT_EQ(childPtr->renderTarget()->renderSurface()->scissorRect(), IntRect(0, 0, 0, 0));
-    
-    EXPECT_EQ(root->scissorRect(), IntRect(0, 0, 0, 0));
-    EXPECT_EQ(childPtr->scissorRect(), IntRect(0, 0, 0, 0));
-    EXPECT_EQ(grandChildPtr->scissorRect(), IntRect(0, 0, 0, 0));
-    
-    // Partial damage within child
-    rootDamage = IntRect(10, 10, 20, 20);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, rootDamage);
-    
-    // Scissors are not computed for root
-    EXPECT_EQ(root->renderTarget()->renderSurface()->scissorRect(), IntRect(0, 0, 0, 0));
-
-    // Entire damage rect is within the root surface
-    EXPECT_EQ(childPtr->renderTarget()->renderSurface()->scissorRect(), rootDamage);
-    
-    // Entire damage rect is within the layer
-    EXPECT_EQ(root->scissorRect(), rootDamage);
-
-    // Entire damage rect is within the layer, but with different offset
-    EXPECT_EQ(childPtr->scissorRect(), IntRect(rootDamage.x() - childRect.x(), rootDamage.y() - childRect.y(), rootDamage.width(), rootDamage.height()));
-
-    // Grand child scissor is the damage intersected with the clipped grandChild layer rect (expressed in targetSurface space).
-    EXPECT_EQ(grandChildPtr->scissorRect(), IntRect(5, 5, 15, 15));
-
-    // Partial damage beyond child
-    rootDamage = IntRect(10, 10, 80, 80);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, rootDamage);
-    
-    // Scissors are not computed for root
-    EXPECT_EQ(root->renderTarget()->renderSurface()->scissorRect(), IntRect(0, 0, 0, 0));
-
-    // Entire damage rect is within the root surface
-    EXPECT_EQ(childPtr->renderTarget()->renderSurface()->scissorRect(), rootDamage);
-    
-    // Entire damage rect is within the layer
-    EXPECT_EQ(root->scissorRect(), rootDamage);
-
-    // Child layer overlaps a portion of the damage rect.
-    EXPECT_INT_RECT_EQ(childPtr->scissorRect(), IntRect(rootDamage.x() - childRect.x(), rootDamage.y() - childRect.y(), childRect.width(), childRect.height()));
-
-    // Grand child scissor is the intersection of damage and grandChild rect, expressed in child surface.
-    // The damage fits entirely within the grandChild.
-    EXPECT_INT_RECT_EQ(grandChildPtr->scissorRect(), IntRect(5, 5, 75, 75));
-
-    // Partial damage beyond root
-    rootDamage = IntRect(10, 10, 110, 110);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, rootDamage);
-    
-    // Scissors are not computed for root
-    EXPECT_EQ(root->renderTarget()->renderSurface()->scissorRect(), IntRect(0, 0, 0, 0));
-
-    // Root damage rect is clipped at root layer boundary.
-    EXPECT_EQ(childPtr->renderTarget()->renderSurface()->scissorRect(), IntRect(rootDamage.x(), rootDamage.y(), rootRect.width() - rootDamage.x(), rootRect.height() - rootDamage.y()));
-    EXPECT_EQ(root->scissorRect(), IntRect(rootDamage.x(), rootDamage.y(), rootRect.width() - rootDamage.x(), rootRect.height() - rootDamage.y()));
-
-    // Now the scissor rects are clipped by surfaces contentRect
-    EXPECT_INT_RECT_EQ(childPtr->scissorRect(), IntRect(rootDamage.x() - childRect.x(), rootDamage.y() - childRect.y(), childRect.width(), childRect.height()));
-    EXPECT_INT_RECT_EQ(grandChildPtr->scissorRect(), IntRect(5, 5, 105, 105));
-}
-
-TEST(CCLayerTreeHostCommonTest, scissorRectWithClipAndSpaceTransform)
-{
-    DebugScopedSetImplThread thisScopeIsOnImplThread;
-
-    /*
-      Layers are created as follows:
-
-         +--------------------+
-         |                  1 |
-         |  +-----------+     |
-         |  |         2 |     |
-         |  | +-------------------+
-         |  | |   3,4             |
-         |  | +-------------------+
-         |  |           |     |
-         |  +-----------+     |
-         |                    |
-         |                    |
-         +--------------------+
-
-         Layers 1, 2 and 3 have render surfaces
-     */
-    OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
-    OwnPtr<CCLayerImpl> child = CCLayerImpl::create(2);
-    OwnPtr<CCLayerImpl> grandChild = CCLayerImpl::create(3);
-    OwnPtr<CCLayerImpl> grandChild2 = CCLayerImpl::create(4);
-
-    IntRect rootRect(0, 0, 100, 100);
-    IntRect childRect(10, 10, 50, 50);
-    IntRect grandChildRect(5, 5, 150, 150);
-
-    root->setAnchorPoint(FloatPoint(0, 0));
-    root->setPosition(FloatPoint(rootRect.x(), rootRect.y()));
-    root->setBounds(IntSize(rootRect.width(), rootRect.height()));
-    root->setContentBounds(root->bounds());
-    root->setDrawsContent(true);
-
-    child->setAnchorPoint(FloatPoint(0, 0));
-    child->setPosition(FloatPoint(childRect.x(), childRect.y()));
-    child->setOpacity(0.5);
-    child->setBounds(IntSize(childRect.width(), childRect.height()));
-    child->setContentBounds(child->bounds());
-    child->setDrawsContent(true);
-
-    grandChild->setAnchorPoint(FloatPoint(0, 0));
-    grandChild->setPosition(IntPoint(grandChildRect.x(), grandChildRect.y()));
-    grandChild->setOpacity(0.5);
-    grandChild->setBounds(IntSize(grandChildRect.width(), grandChildRect.height()));
-    grandChild->setContentBounds(grandChild->bounds());
-    grandChild->setDrawsContent(true);
-
-    grandChild2->setAnchorPoint(FloatPoint(0, 0));
-    grandChild2->setPosition(IntPoint(grandChildRect.x(), grandChildRect.y()));
-    grandChild2->setOpacity(0.5);
-    grandChild2->setBounds(IntSize(grandChildRect.width(), grandChildRect.height()));
-    grandChild2->setContentBounds(grandChild2->bounds());
-    grandChild2->setDrawsContent(true);
-
-    CCLayerImpl* childPtr = child.get();
-    CCLayerImpl* grandChildPtr = grandChild.get();
-
-    grandChild->addChild(grandChild2.release());
-    child->addChild(grandChild.release());
-    root->addChild(child.release());
-
-    root->setMasksToBounds(true);
-
-    Vector<CCLayerImpl*> renderSurfaceLayerList;
-    {
-        int dummyMaxTextureSize = 512;
-        CCLayerSorter layerSorter;
-        CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, &layerSorter, dummyMaxTextureSize, renderSurfaceLayerList);
-
-        FloatRect dummyDamageRect;
-        CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, dummyDamageRect);
-    }
-    
-    ASSERT_TRUE(childPtr->renderSurface());
-    ASSERT_TRUE(root->renderSurface());
-    ASSERT_TRUE(grandChildPtr->renderSurface());
-    
-    EXPECT_EQ(renderSurfaceLayerList.size(), 3U);
-    
-    EXPECT_INT_RECT_EQ(root->renderSurface()->clipRect(), rootRect);
-    // Child surface's clipping rect is now set to root's
-    EXPECT_INT_RECT_EQ(childPtr->renderSurface()->clipRect(), rootRect);
-    
-    // Damage the entire screen
-    IntRect rootDamage(rootRect);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, rootDamage);
-    
-    ASSERT_EQ(root->renderTarget()->renderSurface()->scissorRect(), IntRect(0, 0, 0, 0));
-    // Child's renderSurface would have expanded to include the grandChild1 and grandChild2, and then have been clipped by the parent.
-    IntRect expectedChildRenderSurfaceScissor = intersection(rootRect, IntRect(10, 10, 160, 160));
-    ASSERT_EQ(childPtr->renderTarget()->renderSurface()->scissorRect(), expectedChildRenderSurfaceScissor);
-    
-    EXPECT_EQ(root->scissorRect(), IntRect(rootRect));
-
-    // The child layer is not clipped by anything (that clip is already represented by the rootSurface clipping the child's surface)
-    // So here, the expected scissor is just the child layer's rect expressed in targetSurface (child surface) space.
-    EXPECT_EQ(childPtr->scissorRect(), IntRect(0, 0, childRect.width(), childRect.height()));
-
-    // Grand child now draws to its own render surface, so the scissorRect is in that surface's space.
-    EXPECT_EQ(grandChildPtr->scissorRect(), IntRect(0, 0, rootRect.width() - childRect.x() - grandChildRect.x(), rootRect.height() - childRect.y() - grandChildRect.y()));
-    
-    // Empty damage
-    rootDamage = IntRect(0, 0, 0, 0);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, rootDamage);
-    
-    // Empty damage == empty scissor
-    EXPECT_EQ(root->renderTarget()->renderSurface()->scissorRect(), IntRect(0, 0, 0, 0));
-    EXPECT_EQ(childPtr->renderTarget()->renderSurface()->scissorRect(), IntRect(0, 0, 0, 0));
-    
-    EXPECT_EQ(root->scissorRect(), IntRect(0, 0, 0, 0));
-    EXPECT_EQ(childPtr->scissorRect(), IntRect(0, 0, 0, 0));
-    EXPECT_EQ(grandChildPtr->scissorRect(), IntRect(0, 0, 0, 0));
-    
-    // Partial damage within child
-    rootDamage = IntRect(10, 10, 20, 20);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, rootDamage);
-    
-    // Scissors are not computed for root
-    EXPECT_EQ(root->renderTarget()->renderSurface()->scissorRect(), IntRect(0, 0, 0, 0));
-
-    // Entire damage rect is within the root surface
-    EXPECT_EQ(childPtr->renderTarget()->renderSurface()->scissorRect(), rootDamage);
-    
-    // Entire damage rect is within the layer
-    EXPECT_EQ(root->scissorRect(), rootDamage);
-
-    // Entire damage rect is within the layer, but with different offset
-    EXPECT_EQ(childPtr->scissorRect(), IntRect(rootDamage.x() - childRect.x(), rootDamage.y() - childRect.y(), rootDamage.width(), rootDamage.height()));
-
-    // Grand child now gets scissored by its target surface as well as root
-    EXPECT_EQ(grandChildPtr->scissorRect(), IntRect(rootDamage.x() - childRect.x(), rootDamage.y() - childRect.y(), rootDamage.width() - grandChildRect.x(), rootDamage.height() - grandChildRect.y()));
-
-    // Partial damage beyond child
-    rootDamage = IntRect(10, 10, 80, 80);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, rootDamage);
-    
-    // Scissors are not computed for root
-    EXPECT_EQ(root->renderTarget()->renderSurface()->scissorRect(), IntRect(0, 0, 0, 0));
-
-    // Entire damage rect is within the root surface
-    EXPECT_EQ(childPtr->renderTarget()->renderSurface()->scissorRect(), rootDamage);
-    
-    // Entire damage rect is within the layer
-    EXPECT_EQ(root->scissorRect(), rootDamage);
-
-    // Entire damage rect is within the layer, but it is still clipped with respect to the root.
-    EXPECT_INT_RECT_EQ(childPtr->scissorRect(), IntRect(rootDamage.x() - childRect.x(), rootDamage.y() - childRect.y(), childRect.width(), childRect.height()));
-
-    // Grand child now gets scissored by its target surface as well as root
-    EXPECT_EQ(grandChildPtr->scissorRect(), IntRect(rootDamage.x() - childRect.x(), rootDamage.y() - childRect.y(), rootDamage.width() - grandChildRect.x(), rootDamage.height() - grandChildRect.y()));
-
-    // Partial damage beyond root
-    rootDamage = IntRect(10, 10, 110, 110);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, rootDamage);
-    
-    // Scissors are not computed for root
-    EXPECT_EQ(root->renderTarget()->renderSurface()->scissorRect(), IntRect(0, 0, 0, 0));
-
-    // Root surface does not have a clipRect, so its contentRect will be used to intersect with damage.
-    // Result is that root damage rect is clipped at root layer boundary
-    EXPECT_EQ(childPtr->renderTarget()->renderSurface()->scissorRect(), IntRect(rootDamage.x(), rootDamage.y(), rootRect.width() - rootDamage.x(), rootRect.height() - rootDamage.y()));
-    
-    // Root does not use layer clipping, so its content rect will be used to intersect with damage
-    // Result is that root damage rect is clipped at root layer boundary
-    EXPECT_EQ(root->scissorRect(), IntRect(rootDamage.x(), rootDamage.y(), rootRect.width() - rootDamage.x(), rootRect.height() - rootDamage.y()));
-
-    EXPECT_INT_RECT_EQ(childPtr->scissorRect(), IntRect(rootDamage.x() - childRect.x(), rootDamage.y() - childRect.y(), childRect.width(), childRect.height()));
-
-    // Grandchild's scissor rect is clipped by its target surface
-    EXPECT_EQ(grandChildPtr->scissorRect(), IntRect(rootDamage.x() - childRect.x(), rootDamage.y() - childRect.y(), rootDamage.width() - grandChildRect.x(), rootDamage.height() - grandChildRect.y()));
-}
-
 TEST(CCLayerTreeHostCommonTest, verifyTransformsForReplica)
 {
     RefPtr<LayerChromium> parent = LayerChromium::create();
@@ -965,7 +627,7 @@ TEST(CCLayerTreeHostCommonTest, verifyRenderSurfaceListForRenderSurfaceWithClipp
     Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
     int dummyMaxTextureSize = 512;
     CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, parent->renderSurface()->contentRect());
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     // The child layer's content is entirely outside the parent's clip rect, so the intermediate
     // render surface should not be listed here, even if it was forced to be created. Render surfaces without children or visible
@@ -993,7 +655,7 @@ TEST(CCLayerTreeHostCommonTest, verifyRenderSurfaceListForTransparentChild)
     Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
     int dummyMaxTextureSize = 512;
     CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, parent->renderSurface()->contentRect());
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     // Since the layer is transparent, renderSurface1->renderSurface() should not have gotten added anywhere.
     // Also, the drawable content rect should not have been extended by the children.
@@ -1649,7 +1311,7 @@ TEST(CCLayerTreeHostCommonTest, verifyClipRectCullsRenderSurfaces)
     Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
     int dummyMaxTextureSize = 512;
     CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, parent->renderSurface()->contentRect());
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
 
     ASSERT_EQ(2U, renderSurfaceLayerList.size());
@@ -1762,9 +1424,7 @@ TEST(CCLayerTreeHostCommonTest, verifyDrawableContentRectForLayers)
     Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
     int dummyMaxTextureSize = 512;
     CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
-
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, parent->renderSurface()->contentRect());
-
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     EXPECT_INT_RECT_EQ(IntRect(IntPoint(5, 5), IntSize(10, 10)), grandChild1->drawableContentRect());
     EXPECT_INT_RECT_EQ(IntRect(IntPoint(15, 15), IntSize(5, 5)), grandChild3->drawableContentRect());
@@ -1830,8 +1490,7 @@ TEST(CCLayerTreeHostCommonTest, verifyClipRectIsPropagatedCorrectlyToSurfaces)
     Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
     int dummyMaxTextureSize = 512;
     CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
-
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, parent->renderSurface()->contentRect());
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     ASSERT_TRUE(grandChild1->renderSurface());
     ASSERT_TRUE(grandChild2->renderSurface());
@@ -2482,8 +2141,7 @@ TEST(CCLayerTreeHostCommonTest, verifyBackFaceCullingWithAnimatingTransforms)
     Vector<RefPtr<LayerChromium> > renderSurfaceLayerList;
     int dummyMaxTextureSize = 512;
     CCLayerTreeHostCommon::calculateDrawTransforms(parent.get(), parent->bounds(), 1, dummyMaxTextureSize, renderSurfaceLayerList);
-
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, parent->renderSurface()->contentRect());
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     EXPECT_FALSE(child->renderSurface());
     EXPECT_TRUE(animatingSurface->renderSurface());
@@ -2604,7 +2262,7 @@ TEST(CCLayerTreeHostCommonTest, verifyHitTestingForSingleLayer)
     Vector<CCLayerImpl*> renderSurfaceLayerList;
     int dummyMaxTextureSize = 512;
     CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, FloatRect()); // empty scissorRect will help ensure we're hit testing the correct rect.
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     // Sanity check the scenario we just created.
     ASSERT_EQ(1u, renderSurfaceLayerList.size());
@@ -2654,7 +2312,7 @@ TEST(CCLayerTreeHostCommonTest, verifyHitTestingForUninvertibleTransform)
     Vector<CCLayerImpl*> renderSurfaceLayerList;
     int dummyMaxTextureSize = 512;
     CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, FloatRect()); // empty scissorRect will help ensure we're hit testing the correct rect.
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     // Sanity check the scenario we just created.
     ASSERT_EQ(1u, renderSurfaceLayerList.size());
@@ -2709,7 +2367,7 @@ TEST(CCLayerTreeHostCommonTest, verifyHitTestingForSinglePositionedLayer)
     Vector<CCLayerImpl*> renderSurfaceLayerList;
     int dummyMaxTextureSize = 512;
     CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, FloatRect()); // empty scissorRect will help ensure we're hit testing the correct rect.
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     // Sanity check the scenario we just created.
     ASSERT_EQ(1u, renderSurfaceLayerList.size());
@@ -2757,7 +2415,7 @@ TEST(CCLayerTreeHostCommonTest, verifyHitTestingForSingleRotatedLayer)
     Vector<CCLayerImpl*> renderSurfaceLayerList;
     int dummyMaxTextureSize = 512;
     CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, FloatRect()); // empty scissorRect will help ensure we're hit testing the correct rect.
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     // Sanity check the scenario we just created.
     ASSERT_EQ(1u, renderSurfaceLayerList.size());
@@ -2814,7 +2472,7 @@ TEST(CCLayerTreeHostCommonTest, verifyHitTestingForSinglePerspectiveLayer)
     Vector<CCLayerImpl*> renderSurfaceLayerList;
     int dummyMaxTextureSize = 512;
     CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, FloatRect()); // empty scissorRect will help ensure we're hit testing the correct rect.
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     // Sanity check the scenario we just created.
     ASSERT_EQ(1u, renderSurfaceLayerList.size());
@@ -2879,7 +2537,7 @@ TEST(CCLayerTreeHostCommonTest, verifyHitTestingForSingleLayerWithScaledContents
     Vector<CCLayerImpl*> renderSurfaceLayerList;
     int dummyMaxTextureSize = 512;
     CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, FloatRect()); // empty scissorRect will help ensure we're hit testing the correct rect.
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     // Sanity check the scenario we just created.
     // The visibleContentRect for testLayer is actually 100x100, even though its layout size is 50x50, positioned at 25x25.
@@ -2944,7 +2602,7 @@ TEST(CCLayerTreeHostCommonTest, verifyHitTestingForSimpleClippedLayer)
     Vector<CCLayerImpl*> renderSurfaceLayerList;
     int dummyMaxTextureSize = 512;
     CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, FloatRect()); // empty scissorRect will help ensure we're hit testing the correct rect.
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     // Sanity check the scenario we just created.
     ASSERT_EQ(1u, renderSurfaceLayerList.size());
@@ -3035,7 +2693,7 @@ TEST(CCLayerTreeHostCommonTest, verifyHitTestingForMultiClippedRotatedLayer)
     Vector<CCLayerImpl*> renderSurfaceLayerList;
     int dummyMaxTextureSize = 512;
     CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, FloatRect()); // empty scissorRect will help ensure we're hit testing the correct rect.
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     // Sanity check the scenario we just created.
     // The grandChild is expected to create a renderSurface because it masksToBounds and is not axis aligned.
@@ -3118,7 +2776,7 @@ TEST(CCLayerTreeHostCommonTest, verifyHitTestingForNonClippingIntermediateLayer)
     Vector<CCLayerImpl*> renderSurfaceLayerList;
     int dummyMaxTextureSize = 512;
     CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, FloatRect()); // empty scissorRect will help ensure we're hit testing the correct rect.
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     // Sanity check the scenario we just created.
     ASSERT_EQ(1u, renderSurfaceLayerList.size());
@@ -3199,7 +2857,7 @@ TEST(CCLayerTreeHostCommonTest, verifyHitTestingForMultipleLayers)
     Vector<CCLayerImpl*> renderSurfaceLayerList;
     int dummyMaxTextureSize = 512;
     CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, FloatRect()); // empty scissorRect will help ensure we're hit testing the correct rect.
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     // Sanity check the scenario we just created.
     ASSERT_TRUE(child1);
@@ -3308,7 +2966,7 @@ TEST(CCLayerTreeHostCommonTest, verifyHitTestingForMultipleLayerLists)
     Vector<CCLayerImpl*> renderSurfaceLayerList;
     int dummyMaxTextureSize = 512;
     CCLayerTreeHostCommon::calculateDrawTransforms(root.get(), root->bounds(), 1, 0, dummyMaxTextureSize, renderSurfaceLayerList);
-    CCLayerTreeHostCommon::calculateVisibleAndScissorRects(renderSurfaceLayerList, FloatRect()); // empty scissorRect will help ensure we're hit testing the correct rect.
+    CCLayerTreeHostCommon::calculateVisibleRects(renderSurfaceLayerList);
 
     // Sanity check the scenario we just created.
     ASSERT_TRUE(child1);
index 752abc1..24e45b6 100644 (file)
@@ -1750,6 +1750,7 @@ public:
     MOCK_METHOD1(getString, WebString(WGC3Denum name));
     MOCK_METHOD0(getRequestableExtensionsCHROMIUM, WebString());
     MOCK_METHOD1(enable, void(WGC3Denum cap));
+    MOCK_METHOD1(disable, void(WGC3Denum cap));
     MOCK_METHOD4(scissor, void(WGC3Dint x, WGC3Dint y, WGC3Dsizei width, WGC3Dsizei height));
 };
 
@@ -1788,6 +1789,10 @@ public:
         // Any un-sanctioned calls to enable() are OK
         EXPECT_CALL(*m_context, enable(_))
             .WillRepeatedly(Return());
+
+        // Any un-sanctioned calls to disable() are OK
+        EXPECT_CALL(*m_context, disable(_))
+            .WillRepeatedly(Return());
     }
 
     void mustDrawSolidQuad()
@@ -1813,6 +1818,17 @@ public:
             .WillRepeatedly(Return());
     }
 
+    void mustSetNoScissor()
+    {
+        EXPECT_CALL(*m_context, disable(GraphicsContext3D::SCISSOR_TEST))
+            .WillRepeatedly(Return());
+
+        EXPECT_CALL(*m_context, enable(GraphicsContext3D::SCISSOR_TEST))
+            .Times(0);
+
+        EXPECT_CALL(*m_context, scissor(_, _, _, _))
+            .Times(0);
+    }
 };
 
 TEST_F(CCLayerTreeHostImplTest, noPartialSwap)
@@ -1822,7 +1838,7 @@ TEST_F(CCLayerTreeHostImplTest, noPartialSwap)
     MockContextHarness harness(mockContext);
 
     harness.mustDrawSolidQuad();
-    harness.mustSetScissor(0, 0, 10, 10);
+    harness.mustSetNoScissor();
 
     // Run test case
     OwnPtr<CCLayerTreeHostImpl> myHostImpl = createLayerTreeHost(false, context.release(), FakeLayerWithQuads::create(1));
@@ -1840,46 +1856,31 @@ TEST_F(CCLayerTreeHostImplTest, partialSwap)
     MockContext* mockContext = static_cast<MockContext*>(context->context3D());
     MockContextHarness harness(mockContext);
 
-    harness.mustDrawSolidQuad();
-    harness.mustSetScissor(0, 0, 10, 10);
-
     OwnPtr<CCLayerTreeHostImpl> myHostImpl = createLayerTreeHost(true, context.release(), FakeLayerWithQuads::create(1));
 
-    CCLayerTreeHostImpl::FrameData frame;
-    EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
-    myHostImpl->drawLayers(frame);
-    myHostImpl->didDrawAllLayers(frame);
+    // The first frame is not a partially-swapped one.
+    harness.mustSetNoScissor();
+    harness.mustDrawSolidQuad();
+    {
+        CCLayerTreeHostImpl::FrameData frame;
+        EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
+        myHostImpl->drawLayers(frame);
+        myHostImpl->didDrawAllLayers(frame);
+    }
     Mock::VerifyAndClearExpectations(&mockContext);
-}
 
-TEST_F(CCLayerTreeHostImplTest, partialSwapNoUpdate)
-{
-    OwnPtr<CCGraphicsContext> context = CCGraphicsContext::create3D(adoptPtr(new MockContext));
-    MockContext* mockContext = static_cast<MockContext*>(context->context3D());
-    MockContextHarness harness(mockContext);
+    // Damage a portion of the frame.
+    myHostImpl->rootLayer()->setUpdateRect(IntRect(0, 0, 2, 3));
 
+    // The second frame will be partially-swapped (the y coordinates are flipped).
+    harness.mustSetScissor(0, 7, 2, 3);
     harness.mustDrawSolidQuad();
-    harness.mustSetScissor(0, 8, 2, 2);
-    harness.mustDrawSolidQuad();
-    harness.mustSetScissor(0, 0, 10, 10);
-
-    OwnPtr<CCLayerTreeHostImpl> myHostImpl = createLayerTreeHost(true, context.release(), FakeLayerWithQuads::create(1));
-
-    // Draw once to make sure layer is not new
-    CCLayerTreeHostImpl::FrameData frame;
-    EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
-    myHostImpl->drawLayers(frame);
-    myHostImpl->didDrawAllLayers(frame);
-
-    // Generate update in layer
-    CCLayerImpl* root = myHostImpl->rootLayer();
-    root->setUpdateRect(FloatRect(0, 0, 2, 2));
-
-    // This draw should generate no new udpates
-    EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
-    myHostImpl->drawLayers(frame);
-    myHostImpl->didDrawAllLayers(frame);
-
+    {
+        CCLayerTreeHostImpl::FrameData frame;
+        EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
+        myHostImpl->drawLayers(frame);
+        myHostImpl->didDrawAllLayers(frame);
+    }
     Mock::VerifyAndClearExpectations(&mockContext);
 }
 
@@ -2015,59 +2016,6 @@ TEST_F(CCLayerTreeHostImplTest, contributingLayerEmptyScissorNoPartialSwap)
     }
 }
 
-TEST_F(CCLayerTreeHostImplTest, didDrawNotCalledOnScissoredLayer)
-{
-    CCLayerTreeSettings settings;
-    CCSettings::setPartialSwapEnabled(true);
-
-    OwnPtr<CCGraphicsContext> context = CCGraphicsContext::create3D(adoptPtr(new PartialSwapContext));
-    OwnPtr<CCLayerTreeHostImpl> myHostImpl = CCLayerTreeHostImpl::create(settings, this);
-    myHostImpl->initializeLayerRenderer(context.release(), UnthrottledUploader);
-    myHostImpl->setViewportSize(IntSize(10, 10), IntSize(10, 10));
-
-    myHostImpl->setRootLayer(DidDrawCheckLayer::create(1));
-    DidDrawCheckLayer* root = static_cast<DidDrawCheckLayer*>(myHostImpl->rootLayer());
-    root->setMasksToBounds(true);
-
-    root->addChild(DidDrawCheckLayer::create(2));
-    DidDrawCheckLayer* layer = static_cast<DidDrawCheckLayer*>(root->children()[0].get());
-
-    CCLayerTreeHostImpl::FrameData frame;
-
-    EXPECT_FALSE(root->willDrawCalled());
-    EXPECT_FALSE(root->didDrawCalled());
-    EXPECT_FALSE(layer->willDrawCalled());
-    EXPECT_FALSE(layer->didDrawCalled());
-
-    // We should draw everything the first frame.
-    EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
-    myHostImpl->drawLayers(frame);
-    myHostImpl->didDrawAllLayers(frame);
-
-    EXPECT_TRUE(root->willDrawCalled());
-    EXPECT_TRUE(root->didDrawCalled());
-    EXPECT_TRUE(layer->willDrawCalled());
-    EXPECT_TRUE(layer->didDrawCalled());
-
-    root->clearDidDrawCheck();
-    layer->clearDidDrawCheck();
-
-    EXPECT_FALSE(root->willDrawCalled());
-    EXPECT_FALSE(root->didDrawCalled());
-    EXPECT_FALSE(layer->willDrawCalled());
-    EXPECT_FALSE(layer->didDrawCalled());
-
-    // Drawing again, we should scissor out everything since there is no damage.
-    EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
-    myHostImpl->drawLayers(frame);
-    myHostImpl->didDrawAllLayers(frame);
-
-    EXPECT_FALSE(root->willDrawCalled());
-    EXPECT_FALSE(root->didDrawCalled());
-    EXPECT_FALSE(layer->willDrawCalled());
-    EXPECT_FALSE(layer->didDrawCalled());
-}
-
 // Make sure that context lost notifications are propagated through the tree.
 class ContextLostNotificationCheckLayer : public CCLayerImpl {
 public:
@@ -2626,7 +2574,7 @@ static void setupLayersForTextureCaching(CCLayerTreeHostImpl* layerTreeHostImpl,
     surfaceLayerPtr->setOpacity(0.5f); // This will cause it to have a surface
 
     // Child of the surface layer will produce some quads
-    addDrawingLayerTo(surfaceLayerPtr, 4, IntRect(5, 5, rootSize.width(), rootSize.height()), &childPtr);
+    addDrawingLayerTo(surfaceLayerPtr, 4, IntRect(5, 5, rootSize.width() - 25, rootSize.height() - 25), &childPtr);
 }
 
 class LayerRendererChromiumWithReleaseTextures : public LayerRendererChromium {
@@ -2690,15 +2638,15 @@ TEST_F(CCLayerTreeHostImplTest, textureCachingWithClipping)
         EXPECT_EQ(2U, frame.renderPasses[0]->quadList().size());
         ASSERT_EQ(1U, frame.renderPasses[1]->quadList().size());
 
-        // Verify that the child layers have been drawn entirely.
+        // Verify that the child layers are being clipped.
         IntRect quadVisibleRect = frame.renderPasses[0]->quadList()[0]->quadVisibleRect();
-        EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 3), quadVisibleRect);
+        EXPECT_LT(quadVisibleRect.width(), 100);
 
         quadVisibleRect = frame.renderPasses[0]->quadList()[1]->quadVisibleRect();
-        EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 3), quadVisibleRect);
+        EXPECT_LT(quadVisibleRect.width(), 100);
 
         // Verify that the render surface texture is *not* clipped.
-        EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 100), frame.renderPasses[0]->framebufferOutputRect());
+        EXPECT_INT_RECT_EQ(IntRect(0, 0, 100, 100), frame.renderPasses[0]->outputRect());
 
         EXPECT_EQ(CCDrawQuad::RenderPass, frame.renderPasses[1]->quadList()[0]->material());
         CCRenderPassDrawQuad* quad = static_cast<CCRenderPassDrawQuad*>(frame.renderPasses[1]->quadList()[0].get());
@@ -2715,15 +2663,16 @@ TEST_F(CCLayerTreeHostImplTest, textureCachingWithClipping)
     surfaceLayerPtr->setTransform(transform);
 
     // The surface is now aligned again, and the clipped parts are exposed.
-    // That should be OK, as we've already verified that the quads are drawn in full.
-    // Verify that the render pass is removed.
+    // Since the layers were clipped, even though the render surface size
+    // was not changed, the texture should not be saved.
     {
         CCLayerTreeHostImpl::FrameData frame;
         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
 
-        // Must receive a single render pass using a cached texture.
-        ASSERT_EQ(1U, frame.renderPasses.size());
-        EXPECT_EQ(1U, frame.renderPasses[0]->quadList().size());
+        // Must receive two render passes, each with one quad
+        ASSERT_EQ(2U, frame.renderPasses.size());
+        EXPECT_EQ(2U, frame.renderPasses[0]->quadList().size());
+        ASSERT_EQ(1U, frame.renderPasses[1]->quadList().size());
 
         myHostImpl->drawLayers(frame);
         myHostImpl->didDrawAllLayers(frame);
@@ -2967,6 +2916,7 @@ TEST_F(CCLayerTreeHostImplTest, textureCachingWithOcclusionExternalOverInternal)
     CCSettings::setPartialSwapEnabled(false);
 
     CCLayerTreeSettings settings;
+    settings.minimumOcclusionTrackingSize = IntSize();
     OwnPtr<CCLayerTreeHostImpl> myHostImpl = CCLayerTreeHostImpl::create(settings, this);
 
     // Layers are structured as follows:
@@ -3207,12 +3157,12 @@ TEST_F(CCLayerTreeHostImplTest, textureCachingWithOcclusionPartialSwap)
         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
 
         // Must receive 2 render passes.
-        // For Root, there are 2 quads
-        // For S1, the number of quads depends on what got unoccluded, so not asserted beyond being positive.
+        // For Root, there are 2 quads.
+        // For S1, there are 2 quads.
         // For S2, there is no render pass
         ASSERT_EQ(2U, frame.renderPasses.size());
 
-        EXPECT_GT(frame.renderPasses[0]->quadList().size(), 0U);
+        EXPECT_EQ(2U, frame.renderPasses[0]->quadList().size());
         EXPECT_EQ(2U, frame.renderPasses[1]->quadList().size());
 
         myHostImpl->drawLayers(frame);
@@ -3222,9 +3172,6 @@ TEST_F(CCLayerTreeHostImplTest, textureCachingWithOcclusionPartialSwap)
     // "Re-occlude" surface S1 and repeat draw.
     // Must remove S1's render pass since it is now available in full.
     // S2 has no change so must also be removed.
-    // FIXME: Due to partial swap, the scissor rect will cause OcclusionTracker
-    // to think there is an external occlusion in the previous step. Therefore,
-    // S1's render pass will not be removed.
     transform = layerS2Ptr->transform();
     transform.translate(-15, -15);
     layerS2Ptr->setTransform(transform);
@@ -3232,18 +3179,118 @@ TEST_F(CCLayerTreeHostImplTest, textureCachingWithOcclusionPartialSwap)
         CCLayerTreeHostImpl::FrameData frame;
         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
 
-        // 2 Render passes - Root and S1.
-        ASSERT_EQ(2U, frame.renderPasses.size());
+        // Root render pass only.
+        ASSERT_EQ(1U, frame.renderPasses.size());
 
-        // Render pass for S1 contains no quads as the scissor rect is now occluded.
-        EXPECT_EQ(0U, frame.renderPasses[0]->quadList().size());
+        myHostImpl->drawLayers(frame);
+        myHostImpl->didDrawAllLayers(frame);
+    }
+}
 
-        // Root contains S2 only, as S1 doesn't have any damage.
-        EXPECT_EQ(1U, frame.renderPasses[1]->quadList().size());
+TEST_F(CCLayerTreeHostImplTest, textureCachingWithScissor)
+{
+    CCSettings::setPartialSwapEnabled(false);
+
+    CCLayerTreeSettings settings;
+    settings.minimumOcclusionTrackingSize = IntSize();
+    OwnPtr<CCLayerTreeHostImpl> myHostImpl = CCLayerTreeHostImpl::create(settings, this);
+
+    /*
+      Layers are created as follows:
+
+         +--------------------+
+         |                  1 |
+         |  +-----------+     |
+         |  |         2 |     |
+         |  | +-------------------+
+         |  | |   3               |
+         |  | +-------------------+
+         |  |           |     |
+         |  +-----------+     |
+         |                    |
+         |                    |
+         +--------------------+
+
+         Layers 1, 2 have render surfaces
+     */
+    OwnPtr<CCLayerImpl> root = CCLayerImpl::create(1);
+    OwnPtr<CCTiledLayerImpl> child = CCTiledLayerImpl::create(2);
+    OwnPtr<CCLayerImpl> grandChild = CCLayerImpl::create(3);
 
+    IntRect rootRect(0, 0, 100, 100);
+    IntRect childRect(10, 10, 50, 50);
+    IntRect grandChildRect(5, 5, 150, 150);
+
+    OwnPtr<CCGraphicsContext> context = CCGraphicsContext::create3D(adoptPtr(new PartialSwapContext));
+    myHostImpl->initializeLayerRenderer(context.release(), UnthrottledUploader);
+
+    root->setAnchorPoint(FloatPoint(0, 0));
+    root->setPosition(FloatPoint(rootRect.x(), rootRect.y()));
+    root->setBounds(IntSize(rootRect.width(), rootRect.height()));
+    root->setContentBounds(root->bounds());
+    root->setDrawsContent(true);
+    root->setMasksToBounds(true);
+
+    child->setAnchorPoint(FloatPoint(0, 0));
+    child->setPosition(FloatPoint(childRect.x(), childRect.y()));
+    child->setOpacity(0.5);
+    child->setBounds(IntSize(childRect.width(), childRect.height()));
+    child->setContentBounds(child->bounds());
+    child->setDrawsContent(true);
+    child->setSkipsDraw(false);
+
+    // child layer has 10x10 tiles.
+    OwnPtr<CCLayerTilingData> tiler = CCLayerTilingData::create(IntSize(10, 10), CCLayerTilingData::HasBorderTexels);
+    tiler->setBounds(child->contentBounds());
+    child->setTilingData(*tiler.get());
+
+    grandChild->setAnchorPoint(FloatPoint(0, 0));
+    grandChild->setPosition(IntPoint(grandChildRect.x(), grandChildRect.y()));
+    grandChild->setBounds(IntSize(grandChildRect.width(), grandChildRect.height()));
+    grandChild->setContentBounds(grandChild->bounds());
+    grandChild->setDrawsContent(true);
+
+    CCTiledLayerImpl* childPtr = child.get();
+
+    child->addChild(grandChild.release());
+    root->addChild(child.release());
+    myHostImpl->setRootLayer(root.release());
+    myHostImpl->setViewportSize(rootRect.size(), rootRect.size());
+
+    EXPECT_FALSE(myHostImpl->layerRenderer()->haveCachedResourcesForRenderPassId(childPtr->id()));
+
+    {
+        CCLayerTreeHostImpl::FrameData frame;
+        EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
         myHostImpl->drawLayers(frame);
         myHostImpl->didDrawAllLayers(frame);
     }
+
+    // We should have cached textures for surface 2.
+    EXPECT_TRUE(myHostImpl->layerRenderer()->haveCachedResourcesForRenderPassId(childPtr->id()));
+
+    {
+        CCLayerTreeHostImpl::FrameData frame;
+        EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
+        myHostImpl->drawLayers(frame);
+        myHostImpl->didDrawAllLayers(frame);
+    }
+
+    // We should still have cached textures for surface 2 after drawing with no damage.
+    EXPECT_TRUE(myHostImpl->layerRenderer()->haveCachedResourcesForRenderPassId(childPtr->id()));
+
+    // Damage a single tile of surface 2.
+    childPtr->setUpdateRect(IntRect(10, 10, 10, 10));
+
+    {
+        CCLayerTreeHostImpl::FrameData frame;
+        EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
+        myHostImpl->drawLayers(frame);
+        myHostImpl->didDrawAllLayers(frame);
+    }
+
+    // We should have a cached texture for surface 2 again even though it was damaged.
+    EXPECT_TRUE(myHostImpl->layerRenderer()->haveCachedResourcesForRenderPassId(childPtr->id()));
 }
 
 TEST_F(CCLayerTreeHostImplTest, surfaceTextureCaching)
@@ -3284,10 +3331,14 @@ TEST_F(CCLayerTreeHostImplTest, surfaceTextureCaching)
         CCLayerTreeHostImpl::FrameData frame;
         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
 
-        // Must receive two EMPTY render passes
-        ASSERT_EQ(2U, frame.renderPasses.size());
-        EXPECT_EQ(0U, frame.renderPasses[0]->quadList().size());
-        EXPECT_EQ(0U, frame.renderPasses[1]->quadList().size());
+        // Must receive one render pass, as the other one should be culled
+        ASSERT_EQ(1U, frame.renderPasses.size());
+
+        EXPECT_EQ(1U, frame.renderPasses[0]->quadList().size());
+        EXPECT_EQ(CCDrawQuad::RenderPass, frame.renderPasses[0]->quadList()[0]->material());
+        CCRenderPassDrawQuad* quad = static_cast<CCRenderPassDrawQuad*>(frame.renderPasses[0]->quadList()[0].get());
+        CCRenderPass* targetPass = frame.renderPassesById.get(quad->renderPassId());
+        EXPECT_FALSE(targetPass->targetSurface()->contentsChanged());
 
         myHostImpl->drawLayers(frame);
         myHostImpl->didDrawAllLayers(frame);
@@ -3368,10 +3419,14 @@ TEST_F(CCLayerTreeHostImplTest, surfaceTextureCaching)
         CCLayerTreeHostImpl::FrameData frame;
         EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
 
-        // Must receive two EMPTY render passes
-        ASSERT_EQ(2U, frame.renderPasses.size());
-        EXPECT_EQ(0U, frame.renderPasses[0]->quadList().size());
-        EXPECT_EQ(0U, frame.renderPasses[1]->quadList().size());
+        // Must receive one render pass, as the other one should be culled
+        ASSERT_EQ(1U, frame.renderPasses.size());
+
+        EXPECT_EQ(1U, frame.renderPasses[0]->quadList().size());
+        EXPECT_EQ(CCDrawQuad::RenderPass, frame.renderPasses[0]->quadList()[0]->material());
+        CCRenderPassDrawQuad* quad = static_cast<CCRenderPassDrawQuad*>(frame.renderPasses[0]->quadList()[0].get());
+        CCRenderPass* targetPass = frame.renderPassesById.get(quad->renderPassId());
+        EXPECT_FALSE(targetPass->targetSurface()->contentsChanged());
 
         myHostImpl->drawLayers(frame);
         myHostImpl->didDrawAllLayers(frame);
@@ -3562,82 +3617,6 @@ TEST_F(CCLayerTreeHostImplTest, surfaceTextureCachingNoPartialSwap)
     }
 }
 
-// FIXME: This test is temporary until memory management in render surfaces gets refactored.
-// It depends on implementation of TextureManager and needs to get removed as
-// it will become meaningless with a different implementation.
-TEST_F(CCLayerTreeHostImplTest, surfaceTextureCachingMemoryLimit)
-{
-    CCSettings::setPartialSwapEnabled(true);
-
-    CCLayerTreeSettings settings;
-    OwnPtr<CCLayerTreeHostImpl> myHostImpl = CCLayerTreeHostImpl::create(settings, this);
-
-    CCLayerImpl* rootPtr;
-    CCLayerImpl* intermediateLayerPtr;
-    CCLayerImpl* surfaceLayerPtr;
-    CCLayerImpl* childPtr;
-
-    // FIXME: The number 4200 is the "magic" number which will cause render surface size
-    // to go above 64M. This will bring it above reclaimLimitBytes().
-    // We could compute this number from return value of reclaimLimitBytes(), however
-    // it takes a viewport, so it's no better as it still contains same kind of assumption
-    // (namely that reclaimLimitBytes() ignores viewport size).
-    IntSize largeSurfaceSize(4200, 4200);
-    setupLayersForTextureCaching(myHostImpl.get(), rootPtr, intermediateLayerPtr, surfaceLayerPtr, childPtr, largeSurfaceSize);
-
-    {
-        CCLayerTreeHostImpl::FrameData frame;
-        EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
-
-        // Must receive two render passes, each with one quad
-        ASSERT_EQ(2U, frame.renderPasses.size());
-        EXPECT_EQ(1U, frame.renderPasses[0]->quadList().size());
-        EXPECT_EQ(1U, frame.renderPasses[1]->quadList().size());
-
-        EXPECT_EQ(CCDrawQuad::RenderPass, frame.renderPasses[1]->quadList()[0]->material());
-        CCRenderPassDrawQuad* quad = static_cast<CCRenderPassDrawQuad*>(frame.renderPasses[1]->quadList()[0].get());
-        CCRenderPass* targetPass = frame.renderPassesById.get(quad->renderPassId());
-        EXPECT_TRUE(targetPass->targetSurface()->contentsChanged());
-
-        myHostImpl->drawLayers(frame);
-        myHostImpl->didDrawAllLayers(frame);
-    }
-
-    // Draw without any change
-    {
-        CCLayerTreeHostImpl::FrameData frame;
-        EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
-
-        // Must receive two EMPTY render passes
-        ASSERT_EQ(2U, frame.renderPasses.size());
-        EXPECT_EQ(0U, frame.renderPasses[0]->quadList().size());
-        EXPECT_EQ(0U, frame.renderPasses[1]->quadList().size());
-
-        myHostImpl->drawLayers(frame);
-        myHostImpl->didDrawAllLayers(frame);
-    }
-
-    // Change opacity and draw.
-    // If all goes well, the texture must still be available, even though it's really big.
-    surfaceLayerPtr->setOpacity(0.6f);
-    {
-        CCLayerTreeHostImpl::FrameData frame;
-        EXPECT_TRUE(myHostImpl->prepareToDraw(frame));
-
-        // Must receive one render pass, as the other one should be culled
-        ASSERT_EQ(1U, frame.renderPasses.size());
-
-        EXPECT_EQ(1U, frame.renderPasses[0]->quadList().size());
-        EXPECT_EQ(CCDrawQuad::RenderPass, frame.renderPasses[0]->quadList()[0]->material());
-        CCRenderPassDrawQuad* quad = static_cast<CCRenderPassDrawQuad*>(frame.renderPasses[0]->quadList()[0].get());
-        CCRenderPass* targetPass = frame.renderPassesById.get(quad->renderPassId());
-        EXPECT_FALSE(targetPass->targetSurface()->contentsChanged());
-
-        myHostImpl->drawLayers(frame);
-        myHostImpl->didDrawAllLayers(frame);
-    }
-}
-
 TEST_F(CCLayerTreeHostImplTest, releaseContentsTextureShouldTriggerCommit)
 {
     m_hostImpl->releaseContentsTextures();
index 8ec3989..7443aba 100644 (file)
@@ -261,8 +261,7 @@ protected:
         ASSERT(!root->renderSurface());
 
         CCLayerTreeHostCommon::calculateDrawTransforms(root, root->bounds(), 1, &layerSorter, dummyMaxTextureSize, m_renderSurfaceLayerListImpl);
-
-        CCLayerTreeHostCommon::calculateVisibleAndScissorRects(m_renderSurfaceLayerListImpl, root->renderSurface()->contentRect());
+        CCLayerTreeHostCommon::calculateVisibleRects(m_renderSurfaceLayerListImpl);
 
         m_layerIterator = m_layerIteratorBegin = Types::LayerIterator::begin(&m_renderSurfaceLayerListImpl);
     }
@@ -275,8 +274,7 @@ protected:
         ASSERT(!root->renderSurface());
 
         CCLayerTreeHostCommon::calculateDrawTransforms(root, root->bounds(), 1, dummyMaxTextureSize, m_renderSurfaceLayerListChromium);
-
-        CCLayerTreeHostCommon::calculateVisibleAndScissorRects(m_renderSurfaceLayerListChromium, root->renderSurface()->contentRect());
+        CCLayerTreeHostCommon::calculateVisibleRects(m_renderSurfaceLayerListChromium);
 
         m_layerIterator = m_layerIteratorBegin = Types::LayerIterator::begin(&m_renderSurfaceLayerListChromium);
     }
@@ -624,20 +622,6 @@ protected:
         EXPECT_INT_RECT_EQ(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
         EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
 
-        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 70)));
-        EXPECT_FALSE(occlusion.occluded(child, IntRect(9, 430, 60, 70)));
-        EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 429, 60, 70)));
-        EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 430, 61, 70)));
-        EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 430, 60, 71)));
-
-        occlusion.useDefaultLayerScissorRect();
-        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 70)));
-        EXPECT_TRUE(occlusion.occluded(child, IntRect(9, 430, 60, 70)));
-        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 429, 60, 70)));
-        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 61, 70)));
-        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 71)));
-        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
-
         this->leaveContributingSurface(child, occlusion);
         this->enterLayer(parent, occlusion);
 
@@ -728,45 +712,10 @@ protected:
 
         this->enterContributingSurface(child, occlusion);
 
-        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 70)));
-        EXPECT_FALSE(occlusion.occluded(child, IntRect(9, 430, 60, 70)));
-        EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 429, 60, 70)));
-        EXPECT_FALSE(occlusion.occluded(child, IntRect(11, 430, 60, 70)));
-        EXPECT_FALSE(occlusion.occluded(child, IntRect(10, 431, 60, 70)));
-
-        occlusion.useDefaultLayerScissorRect();
-        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 430, 60, 70)));
-        EXPECT_TRUE(occlusion.occluded(child, IntRect(9, 430, 60, 70)));
-        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 429, 60, 70)));
-        EXPECT_TRUE(occlusion.occluded(child, IntRect(11, 430, 60, 70)));
-        EXPECT_TRUE(occlusion.occluded(child, IntRect(10, 431, 60, 70)));
-        occlusion.setLayerScissorRect(IntRect(-10, -10, 1000, 1000));
-
-        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(10, 430, 60, 70)).isEmpty());
-        // This is the little piece not occluded by child2
-        EXPECT_INT_RECT_EQ(IntRect(9, 430, 1, 10), occlusion.unoccludedContentRect(child, IntRect(9, 430, 60, 70)));
-        // This extends past both sides of child2, so it will be the original rect.
-        EXPECT_INT_RECT_EQ(IntRect(9, 430, 60, 80), occlusion.unoccludedContentRect(child, IntRect(9, 430, 60, 80)));
-        // This extends past two adjacent sides of child2, and should included the unoccluded parts of each side.
-        // This also demonstrates that the rect can be arbitrary and does not get clipped to the layer's visibleContentRect().
-        EXPECT_INT_RECT_EQ(IntRect(-10, 430, 20, 70), occlusion.unoccludedContentRect(child, IntRect(-10, 430, 60, 70)));
-        // This extends past three adjacent sides of child2, so it should contain the unoccluded parts of each side. The left
-        // and bottom edges are completely unoccluded for some row/column so we get back the original query rect.
-        EXPECT_INT_RECT_EQ(IntRect(-10, 430, 60, 80), occlusion.unoccludedContentRect(child, IntRect(-10, 430, 60, 80)));
-        EXPECT_INT_RECT_EQ(IntRect(10, 429, 60, 1), occlusion.unoccludedContentRect(child, IntRect(10, 429, 60, 70)));
-        EXPECT_INT_RECT_EQ(IntRect(70, 430, 1, 70), occlusion.unoccludedContentRect(child, IntRect(11, 430, 60, 70)));
-        EXPECT_INT_RECT_EQ(IntRect(10, 500, 60, 1), occlusion.unoccludedContentRect(child, IntRect(10, 431, 60, 70)));
-
-        occlusion.useDefaultLayerScissorRect();
-        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(10, 430, 60, 70)).isEmpty());
-        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(9, 430, 60, 70)).isEmpty());
-        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(9, 430, 60, 80)).isEmpty());
-        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(-10, 430, 60, 70)).isEmpty());
-        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(-10, 430, 60, 80)).isEmpty());
-        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(10, 429, 60, 70)).isEmpty());
-        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(11, 430, 60, 70)).isEmpty());
-        EXPECT_TRUE(occlusion.unoccludedContentRect(child, IntRect(10, 431, 60, 70)).isEmpty());
-        occlusion.setLayerScissorRect(IntRect(0, 0, 1000, 1000));
+        EXPECT_INT_RECT_EQ(IntRect(30, 30, 70, 70), occlusion.occlusionInScreenSpace().bounds());
+        EXPECT_EQ(2u, occlusion.occlusionInScreenSpace().rects().size());
+        EXPECT_INT_RECT_EQ(IntRect(10, 430, 60, 70), occlusion.occlusionInTargetSurface().bounds());
+        EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
 
         // Occlusion in |child2| should get merged with the |child| surface we are leaving now.
         this->leaveContributingSurface(child, occlusion);
index 9eff157..8279a3a 100644 (file)
@@ -27,6 +27,7 @@
 #include "cc/CCQuadCuller.h"
 
 #include "cc/CCLayerTilingData.h"
+#include "cc/CCMathUtil.h"
 #include "cc/CCOcclusionTracker.h"
 #include "cc/CCOverdrawMetrics.h"
 #include "cc/CCSingleThreadProxy.h"
@@ -80,6 +81,7 @@ static PassOwnPtr<CCTiledLayerImpl> makeLayer(CCTiledLayerImpl* parent, const We
             layer->pushTileProperties(i, j, resourceId++, tileOpaqueRect);
         }
 
+    IntRect rectInTarget = CCMathUtil::mapClippedRect(layer->drawTransform(), layer->visibleContentRect());
     if (!parent) {
         layer->createRenderSurface();
         surfaceLayerList.append(layer.get());
@@ -87,7 +89,9 @@ static PassOwnPtr<CCTiledLayerImpl> makeLayer(CCTiledLayerImpl* parent, const We
     } else {
         layer->setRenderTarget(parent->renderTarget());
         parent->renderSurface()->layerList().append(layer.get());
+        rectInTarget.unite(CCMathUtil::mapClippedRect(parent->drawTransform(), parent->visibleContentRect()));
     }
+    layer->setDrawableContentRect(rectInTarget);
 
     return layer.release();
 }
index c95d71e..ad8df25 100644 (file)
@@ -94,11 +94,16 @@ TEST(CCRenderSurfaceTest, sanityCheckSurfaceCreatesCorrectSharedQuadState)
     // This will fake that we are on the correct thread for testing purposes.
     DebugScopedSetImplThread setImplThread;
 
-    OwnPtr<CCLayerImpl> owningLayer = CCLayerImpl::create(1);
+    OwnPtr<CCLayerImpl> rootLayer = CCLayerImpl::create(1);
+
+    OwnPtr<CCLayerImpl> owningLayer = CCLayerImpl::create(2);
     owningLayer->createRenderSurface();
     ASSERT_TRUE(owningLayer->renderSurface());
+    owningLayer->setRenderTarget(owningLayer.get());
     CCRenderSurface* renderSurface = owningLayer->renderSurface();
 
+    rootLayer->addChild(owningLayer.release());
+
     IntRect contentRect = IntRect(IntPoint::zero(), IntSize(50, 50));
     IntRect clipRect = IntRect(IntPoint(5, 5), IntSize(40, 40));
     WebTransformationMatrix origin;
@@ -108,7 +113,6 @@ TEST(CCRenderSurfaceTest, sanityCheckSurfaceCreatesCorrectSharedQuadState)
     renderSurface->setDrawTransform(origin);
     renderSurface->setContentRect(contentRect);
     renderSurface->setClipRect(clipRect);
-    renderSurface->setScissorRect(clipRect);
     renderSurface->setDrawOpacity(1);
 
     OwnPtr<CCSharedQuadState> sharedQuadState = renderSurface->createSharedQuadState(0);
@@ -116,7 +120,6 @@ TEST(CCRenderSurfaceTest, sanityCheckSurfaceCreatesCorrectSharedQuadState)
     EXPECT_EQ(30, sharedQuadState->quadTransform.m41());
     EXPECT_EQ(40, sharedQuadState->quadTransform.m42());
     EXPECT_EQ(contentRect, IntRect(sharedQuadState->visibleContentRect));
-    EXPECT_EQ(clipRect, IntRect(sharedQuadState->scissorRect));
     EXPECT_EQ(1, sharedQuadState->opacity);
     EXPECT_FALSE(sharedQuadState->opaque);
 }
index 1754a5b..141a963 100644 (file)
@@ -51,6 +51,8 @@ TEST(CCSolidColorLayerImplTest, verifyTilingCompleteAndNoOverlap)
     layer->setVisibleContentRect(visibleContentRect);
     layer->setBounds(layerSize);
     layer->setContentBounds(layerSize);
+    layer->createRenderSurface();
+    layer->setRenderTarget(layer.get());
 
     OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState(0);
     bool hadMissingTiles = false;
@@ -74,6 +76,8 @@ TEST(CCSolidColorLayerImplTest, verifyCorrectBackgroundColorInQuad)
     layer->setBounds(layerSize);
     layer->setContentBounds(layerSize);
     layer->setBackgroundColor(testColor);
+    layer->createRenderSurface();
+    layer->setRenderTarget(layer.get());
 
     OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState(0);
     bool hadMissingTiles = false;
@@ -98,6 +102,8 @@ TEST(CCSolidColorLayerImplTest, verifyCorrectOpacityInQuad)
     layer->setBounds(layerSize);
     layer->setContentBounds(layerSize);
     layer->setDrawOpacity(opacity);
+    layer->createRenderSurface();
+    layer->setRenderTarget(layer.get());
 
     OwnPtr<CCSharedQuadState> sharedQuadState = layer->createSharedQuadState(0);
     bool hadMissingTiles = false;
index a0850b2..8d3ca42 100644 (file)
@@ -52,6 +52,8 @@ static PassOwnPtr<CCTiledLayerImpl> createLayer(const IntSize& tileSize, const I
     layer->setDrawOpacity(1);
     layer->setBounds(layerSize);
     layer->setContentBounds(layerSize);
+    layer->createRenderSurface();
+    layer->setRenderTarget(layer.get());
 
     CCResourceProvider::ResourceId resourceId = 1;
     for (int i = 0; i < tiler->numTilesX(); ++i)
index 53d1337..fbdffe7 100644 (file)
@@ -147,7 +147,7 @@ protected:
 
     void swapBuffers()
     {
-        m_layerRendererChromium.swapBuffers(IntRect());
+        m_layerRendererChromium.swapBuffers();
     }
 
     FrameCountingMemoryAllocationSettingContext* context() { return static_cast<FrameCountingMemoryAllocationSettingContext*>(m_context->context3D()); }
@@ -224,7 +224,7 @@ TEST_F(LayerRendererChromiumTest, DiscardedBackbufferIsRecreatedForScopeDuration
     EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
 
     m_layerRendererChromium.setVisible(true);
-    m_layerRendererChromium.drawFrame(m_mockClient.renderPassesInDrawOrder(), m_mockClient.renderPasses(), FloatRect());
+    m_layerRendererChromium.drawFrame(m_mockClient.renderPassesInDrawOrder(), m_mockClient.renderPasses());
     EXPECT_FALSE(m_layerRendererChromium.isFramebufferDiscarded());
 
     swapBuffers();
@@ -239,7 +239,7 @@ TEST_F(LayerRendererChromiumTest, FramebufferDiscardedAfterReadbackWhenNotVisibl
     EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
 
     char pixels[4];
-    m_layerRendererChromium.drawFrame(m_mockClient.renderPassesInDrawOrder(), m_mockClient.renderPasses(), FloatRect());
+    m_layerRendererChromium.drawFrame(m_mockClient.renderPassesInDrawOrder(), m_mockClient.renderPasses());
     EXPECT_FALSE(m_layerRendererChromium.isFramebufferDiscarded());
 
     m_layerRendererChromium.getFramebufferPixels(pixels, IntRect(0, 0, 1, 1));
@@ -420,7 +420,7 @@ TEST(LayerRendererChromiumTest2, opaqueBackground)
 
     EXPECT_TRUE(layerRendererChromium.initialize());
 
-    layerRendererChromium.drawFrame(mockClient.renderPassesInDrawOrder(), mockClient.renderPasses(), FloatRect());
+    layerRendererChromium.drawFrame(mockClient.renderPassesInDrawOrder(), mockClient.renderPasses());
 
     // On DEBUG builds, render passes with opaque background clear to blue to
     // easily see regions that were not drawn on the screen.
@@ -443,7 +443,7 @@ TEST(LayerRendererChromiumTest2, transparentBackground)
 
     EXPECT_TRUE(layerRendererChromium.initialize());
 
-    layerRendererChromium.drawFrame(mockClient.renderPassesInDrawOrder(), mockClient.renderPasses(), FloatRect());
+    layerRendererChromium.drawFrame(mockClient.renderPassesInDrawOrder(), mockClient.renderPasses());
 
     EXPECT_EQ(1, context->clearCount());
 }
index f6ecebc..3ad66b1 100644 (file)
@@ -150,6 +150,7 @@ TEST_F(TiledLayerChromiumTest, pushOccludedDirtyTiles)
 
     // The tile size is 100x100, so this invalidates and then paints two tiles.
     layer->setBounds(IntSize(100, 200));
+    layer->setDrawableContentRect(IntRect(0, 0, 100, 200));
     layer->setVisibleContentRect(IntRect(0, 0, 100, 200));
     layer->invalidateContentRect(IntRect(0, 0, 100, 200));
 
@@ -1043,6 +1044,7 @@ TEST_F(TiledLayerChromiumTest, tilesPaintedWithoutOcclusion)
 
     // The tile size is 100x100, so this invalidates and then paints two tiles.
     layer->setBounds(IntSize(100, 200));
+    layer->setDrawableContentRect(IntRect(0, 0, 100, 200));
     layer->setVisibleContentRect(IntRect(0, 0, 100, 200));
     layer->invalidateContentRect(IntRect(0, 0, 100, 200));
 
@@ -1063,6 +1065,7 @@ TEST_F(TiledLayerChromiumTest, tilesPaintedWithOcclusion)
     layer->setBounds(IntSize(600, 600));
 
     occluded.setOcclusion(IntRect(200, 200, 300, 100));
+    layer->setDrawableContentRect(IntRect(IntPoint(), layer->contentBounds()));
     layer->setVisibleContentRect(IntRect(IntPoint(), layer->contentBounds()));
     layer->invalidateContentRect(IntRect(0, 0, 600, 600));
 
@@ -1114,6 +1117,7 @@ TEST_F(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndVisiblityConstraints)
 
     // The partially occluded tiles (by the 150 occlusion height) are visible beyond the occlusion, so not culled.
     occluded.setOcclusion(IntRect(200, 200, 300, 150));
+    layer->setDrawableContentRect(IntRect(0, 0, 600, 360));
     layer->setVisibleContentRect(IntRect(0, 0, 600, 360));
     layer->invalidateContentRect(IntRect(0, 0, 600, 600));
 
@@ -1130,6 +1134,7 @@ TEST_F(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndVisiblityConstraints)
 
     // Now the visible region stops at the edge of the occlusion so the partly visible tiles become fully occluded.
     occluded.setOcclusion(IntRect(200, 200, 300, 150));
+    layer->setDrawableContentRect(IntRect(0, 0, 600, 350));
     layer->setVisibleContentRect(IntRect(0, 0, 600, 350));
     layer->invalidateContentRect(IntRect(0, 0, 600, 600));
     layer->setTexturePriorities(m_priorityCalculator);
@@ -1145,6 +1150,7 @@ TEST_F(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndVisiblityConstraints)
 
     // Now the visible region is even smaller than the occlusion, it should have the same result.
     occluded.setOcclusion(IntRect(200, 200, 300, 150));
+    layer->setDrawableContentRect(IntRect(0, 0, 600, 340));
     layer->setVisibleContentRect(IntRect(0, 0, 600, 340));
     layer->invalidateContentRect(IntRect(0, 0, 600, 600));
     layer->setTexturePriorities(m_priorityCalculator);
@@ -1169,6 +1175,7 @@ TEST_F(TiledLayerChromiumTest, tilesNotPaintedWithoutInvalidation)
     layer->setBounds(IntSize(600, 600));
 
     occluded.setOcclusion(IntRect(200, 200, 300, 100));
+    layer->setDrawableContentRect(IntRect(0, 0, 600, 600));
     layer->setVisibleContentRect(IntRect(0, 0, 600, 600));
     layer->invalidateContentRect(IntRect(0, 0, 600, 600));
     layer->setTexturePriorities(m_priorityCalculator);
@@ -1214,6 +1221,7 @@ TEST_F(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndTransforms)
     layer->setDrawTransform(screenTransform);
 
     occluded.setOcclusion(IntRect(100, 100, 150, 50));
+    layer->setDrawableContentRect(IntRect(IntPoint(), layer->contentBounds()));
     layer->setVisibleContentRect(IntRect(IntPoint(), layer->contentBounds()));
     layer->invalidateContentRect(IntRect(0, 0, 600, 600));
     layer->setTexturePriorities(m_priorityCalculator);
@@ -1245,6 +1253,7 @@ TEST_F(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndScaling)
     layer->setScreenSpaceTransform(drawTransform);
 
     occluded.setOcclusion(IntRect(200, 200, 300, 100));
+    layer->setDrawableContentRect(IntRect(IntPoint(), layer->contentBounds()));
     layer->setVisibleContentRect(IntRect(IntPoint(), layer->contentBounds()));
     layer->invalidateContentRect(IntRect(0, 0, 600, 600));
     layer->setTexturePriorities(m_priorityCalculator);
@@ -1265,6 +1274,7 @@ TEST_F(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndScaling)
     // a different layer space. In this case the occluded region catches the
     // blown up tiles.
     occluded.setOcclusion(IntRect(200, 200, 300, 200));
+    layer->setDrawableContentRect(IntRect(IntPoint(), layer->contentBounds()));
     layer->setVisibleContentRect(IntRect(IntPoint(), layer->contentBounds()));
     layer->invalidateContentRect(IntRect(0, 0, 600, 600));
     layer->setTexturePriorities(m_priorityCalculator);
@@ -1285,6 +1295,7 @@ TEST_F(TiledLayerChromiumTest, tilesPaintedWithOcclusionAndScaling)
     layer->setDrawTransform(screenTransform);
 
     occluded.setOcclusion(IntRect(100, 100, 150, 100));
+    layer->setDrawableContentRect(IntRect(IntPoint(), layer->contentBounds()));
     layer->setVisibleContentRect(IntRect(IntPoint(), layer->contentBounds()));
     layer->invalidateContentRect(IntRect(0, 0, 600, 600));
     layer->setTexturePriorities(m_priorityCalculator);
@@ -1313,6 +1324,7 @@ TEST_F(TiledLayerChromiumTest, visibleContentOpaqueRegion)
     IntRect visibleBounds = IntRect(0, 0, 100, 150);
 
     layer->setBounds(contentBounds.size());
+    layer->setDrawableContentRect(visibleBounds);
     layer->setVisibleContentRect(visibleBounds);
     layer->setDrawOpacity(1);
 
@@ -1406,6 +1418,7 @@ TEST_F(TiledLayerChromiumTest, pixelsPaintedMetrics)
     IntRect visibleBounds = IntRect(0, 0, 100, 300);
 
     layer->setBounds(contentBounds.size());
+    layer->setDrawableContentRect(visibleBounds);
     layer->setVisibleContentRect(visibleBounds);
     layer->setDrawOpacity(1);
 
@@ -1465,6 +1478,7 @@ TEST_F(TiledLayerChromiumTest, dontAllocateContentsWhenTargetSurfaceCantBeAlloca
 
     root->setBounds(rootRect.size());
     root->setAnchorPoint(FloatPoint());
+    root->setDrawableContentRect(rootRect);
     root->setVisibleContentRect(rootRect);
     root->addChild(surface);
 
@@ -1478,11 +1492,13 @@ TEST_F(TiledLayerChromiumTest, dontAllocateContentsWhenTargetSurfaceCantBeAlloca
     child->setAnchorPoint(FloatPoint());
     child->setPosition(childRect.location());
     child->setVisibleContentRect(childRect);
+    child->setDrawableContentRect(rootRect);
 
     child2->setBounds(child2Rect.size());
     child2->setAnchorPoint(FloatPoint());
     child2->setPosition(child2Rect.location());
     child2->setVisibleContentRect(child2Rect);
+    child2->setDrawableContentRect(rootRect);
 
     ccLayerTreeHost->setRootLayer(root);
     ccLayerTreeHost->setViewportSize(rootRect.size(), rootRect.size());
@@ -1653,6 +1669,7 @@ TEST_F(TiledLayerChromiumTest, nonIntegerContentsScaleIsNotDistortedDuringPaint)
     IntRect contentRect(0, 0, 45, 47);
     EXPECT_EQ(contentRect.size(), layer->contentBounds());
     layer->setVisibleContentRect(contentRect);
+    layer->setDrawableContentRect(contentRect);
 
     layer->setTexturePriorities(m_priorityCalculator);
     textureManager->prioritizeTextures();
@@ -1688,6 +1705,7 @@ TEST_F(TiledLayerChromiumTest, nonIntegerContentsScaleIsNotDistortedDuringInvali
 
     IntRect contentRect(IntPoint(), layer->contentBounds());
     layer->setVisibleContentRect(contentRect);
+    layer->setDrawableContentRect(contentRect);
 
     layer->setTexturePriorities(m_priorityCalculator);
     textureManager->prioritizeTextures();