[chromium] Painting a layer clears opaque rect in untouched tiles
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 22 Feb 2012 02:45:19 +0000 (02:45 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 22 Feb 2012 02:45:19 +0000 (02:45 +0000)
https://bugs.webkit.org/show_bug.cgi?id=79157

Patch by Dana Jansens <danakj@chromium.org> on 2012-02-21
Reviewed by James Robinson.

Source/WebCore:

When painting a tiled layer, we would throw away the saved opaque rect
for any tiles that were not part of the paint. So now we check
if we are able to save the existing saved opaque rect in a more
proper way:
1. If any pixels of the saved rect are painted non-opaque, we replace
the saved rect.
2. If an opaque rect is drawn outside of the saved rect, we replace
the saved rect.

Unit test: TiledLayerChromiumTest.cpp

* platform/graphics/chromium/TiledLayerChromium.cpp:
(WebCore::TiledLayerChromium::prepareToUpdateTiles):
(WebCore::TiledLayerChromium::addSelfToOccludedScreenSpace):

Source/WebKit/chromium:

* tests/TiledLayerChromiumTest.cpp:
(WTF::TEST):

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

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/chromium/TiledLayerChromium.cpp
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/tests/TiledLayerChromiumTest.cpp

index 370f780..e877f52 100644 (file)
@@ -1,3 +1,25 @@
+2012-02-21  Dana Jansens  <danakj@chromium.org>
+
+        [chromium] Painting a layer clears opaque rect in untouched tiles
+        https://bugs.webkit.org/show_bug.cgi?id=79157
+
+        Reviewed by James Robinson.
+
+        When painting a tiled layer, we would throw away the saved opaque rect
+        for any tiles that were not part of the paint. So now we check
+        if we are able to save the existing saved opaque rect in a more
+        proper way:
+        1. If any pixels of the saved rect are painted non-opaque, we replace
+        the saved rect.
+        2. If an opaque rect is drawn outside of the saved rect, we replace
+        the saved rect.
+
+        Unit test: TiledLayerChromiumTest.cpp
+
+        * platform/graphics/chromium/TiledLayerChromium.cpp:
+        (WebCore::TiledLayerChromium::prepareToUpdateTiles):
+        (WebCore::TiledLayerChromium::addSelfToOccludedScreenSpace):
+
 2012-02-21  Raymond Toy  <rtoy@google.com>
 
         Small typo in AudioPannerNode.cpp
index a7ebb14..a9cf7d6 100644 (file)
@@ -474,12 +474,18 @@ void TiledLayerChromium::prepareToUpdateTiles(bool idle, int left, int top, int
 
             IntRect tileRect = m_tiler->tileBounds(i, j);
 
-            // Save what was painted opaque in the tile. If everything painted in the tile was opaque, and the area is a subset of an
-            // already opaque area, keep the old area.
+            // Save what was painted opaque in the tile. Keep the old area if the paint didn't touch it, and didn't paint some
+            // other part of the tile opaque.
             IntRect tilePaintedRect = intersection(tileRect, m_paintRect);
             IntRect tilePaintedOpaqueRect = intersection(tileRect, paintedOpaqueRect);
-            if (tilePaintedOpaqueRect != tilePaintedRect || !tile->m_opaqueRect.contains(tilePaintedOpaqueRect))
-                tile->m_opaqueRect = tilePaintedOpaqueRect;
+            if (!tilePaintedRect.isEmpty()) {
+                IntRect paintInsideTileOpaqueRect = intersection(tile->m_opaqueRect, tilePaintedRect);
+                bool paintInsideTileOpaqueRectIsNonOpaque = !tilePaintedOpaqueRect.contains(paintInsideTileOpaqueRect);
+                bool opaquePaintNotInsideTileOpaqueRect = !tilePaintedOpaqueRect.isEmpty() && !tile->m_opaqueRect.contains(tilePaintedOpaqueRect);
+
+                if (paintInsideTileOpaqueRectIsNonOpaque || opaquePaintNotInsideTileOpaqueRect)
+                    tile->m_opaqueRect = tilePaintedOpaqueRect;
+            }
 
             // Use m_updateRect as copyAndClearDirty above moved the existing dirty rect to m_updateRect.
             const IntRect& dirtyRect = tile->m_updateRect;
@@ -552,7 +558,9 @@ void TiledLayerChromium::addSelfToOccludedScreenSpace(Region& occludedScreenSpac
             if (tile) {
                 IntRect visibleTileOpaqueRect = intersection(visibleRect, tile->m_opaqueRect);
                 FloatRect screenRect = contentTransform.mapRect(FloatRect(visibleTileOpaqueRect));
-                occludedScreenSpace.unite(enclosedIntRect(screenRect));
+                IntRect screenIntRect = enclosedIntRect(screenRect);
+                if (!screenIntRect.isEmpty())
+                    occludedScreenSpace.unite(screenIntRect);
             }
         }
     }
index 6435dd7..78af4f6 100644 (file)
@@ -1,3 +1,13 @@
+2012-02-21  Dana Jansens  <danakj@chromium.org>
+
+        [chromium] Painting a layer clears opaque rect in untouched tiles
+        https://bugs.webkit.org/show_bug.cgi?id=79157
+
+        Reviewed by James Robinson.
+
+        * tests/TiledLayerChromiumTest.cpp:
+        (WTF::TEST):
+
 2012-02-21  James Robinson  <jamesr@chromium.org>
 
         Enable ScrollingCoordinator in chromium whenever compositing is enabled
index d530400..e035590 100644 (file)
@@ -584,7 +584,7 @@ TEST(TiledLayerChromiumTest, layerAddsSelfToOccludedRegion)
     occluded = Region();
     layer->addSelfToOccludedScreenSpace(occluded);
     EXPECT_EQ_RECT(IntRect(), occluded.bounds());
-    EXPECT_EQ(1u, occluded.rects().size());
+    EXPECT_EQ(0u, occluded.rects().size());
 
     // If the layer paints opaque content, then the occluded region should match the visible opaque content.
     IntRect opaquePaintRect = IntRect(10, 10, 90, 190);
@@ -606,6 +606,28 @@ TEST(TiledLayerChromiumTest, layerAddsSelfToOccludedRegion)
     EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), occluded.bounds());
     EXPECT_EQ(1u, occluded.rects().size());
 
+    // If we repaint a non-opaque part of the tile, then it shouldn't lose its opaque-ness. And other tiles should
+    // not be affected.
+    layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
+    layer->invalidateRect(IntRect(0, 0, 1, 1));
+    layer->prepareToUpdate(contentBounds);
+
+    occluded = Region();
+    layer->addSelfToOccludedScreenSpace(occluded);
+    EXPECT_EQ_RECT(intersection(opaquePaintRect, visibleBounds), occluded.bounds());
+    EXPECT_EQ(1u, occluded.rects().size());
+
+    // If we repaint an opaque part of the tile, then it should lose its opaque-ness. But other tiles should still
+    // not be affected.
+    layer->fakeLayerTextureUpdater()->setOpaquePaintRect(IntRect());
+    layer->invalidateRect(IntRect(10, 10, 1, 1));
+    layer->prepareToUpdate(contentBounds);
+
+    occluded = Region();
+    layer->addSelfToOccludedScreenSpace(occluded);
+    EXPECT_EQ_RECT(intersection(IntRect(10, 100, 90, 100), visibleBounds), occluded.bounds());
+    EXPECT_EQ(1u, occluded.rects().size());
+
     // If the layer is transformed then the resulting occluded area needs to be transformed to its target space.
     TransformationMatrix transform;
     transform.translate(contentBounds.width() / 2.0, contentBounds.height() / 2.0);
@@ -616,6 +638,8 @@ TEST(TiledLayerChromiumTest, layerAddsSelfToOccludedRegion)
     screenSpaceTransform *= transform;
     screenSpaceTransform.translate(-contentBounds.width() / 2.0, -contentBounds.height() / 2.0);
     layer->setScreenSpaceTransform(screenSpaceTransform);
+    layer->fakeLayerTextureUpdater()->setOpaquePaintRect(opaquePaintRect);
+    layer->invalidateRect(opaquePaintRect);
     layer->prepareToUpdate(contentBounds);
 
     occluded = Region();