Log Message
Source/WebCore: [chromium] Allow modification of size of partially occluded quads during culling to reduce pixel overdraw. https://bugs.webkit.org/show_bug.cgi?id=76349
Reviewed by James Robinson. Prior to this patch, draw culling either rejects a DrawQuad because it is completely occluded, or draws the entire quad (even if it is largely occluded). This patch attempts to reduce the number of pixels drawn by determining if a partially occluded DrawQuad can be resized to a smaller quad, based on what portion of the DrawQuad is actually visible, and performing that resizing where possible. Added cases to existing unit tests. * platform/graphics/chromium/LayerRendererChromium.cpp: (WebCore::LayerRendererChromium::drawTileQuad): * platform/graphics/chromium/cc/CCDrawQuad.cpp: (WebCore::CCDrawQuad::CCDrawQuad): * platform/graphics/chromium/cc/CCDrawQuad.h: (WebCore::CCDrawQuad::setQuadVisibleRect): (WebCore::CCDrawQuad::quadVisibleRect): * platform/graphics/chromium/cc/CCQuadCuller.cpp: (WebCore::rectSubtractRegion): (WebCore::CCQuadCuller::cullOccludedQuads): Source/WebKit/chromium: [chromium] Allow modification of size of partially occluded quads. https://bugs.webkit.org/show_bug.cgi?id=76349 Reviewed by James Robinson. * tests/CCQuadCullerTest.cpp: (WebCore::makeTileQuads) (WebCore::setQuads): (WebCore::TEST):
Modified Paths
- trunk/Source/WebCore/ChangeLog
- trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
- trunk/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.cpp
- trunk/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.h
- trunk/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp
- trunk/Source/WebKit/chromium/ChangeLog
- trunk/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp
Diff
Modified: trunk/Source/WebCore/ChangeLog (106075 => 106076)
--- trunk/Source/WebCore/ChangeLog 2012-01-27 02:10:52 UTC (rev 106075)
+++ trunk/Source/WebCore/ChangeLog 2012-01-27 02:11:55 UTC (rev 106076)
@@ -1,3 +1,29 @@
+2012-01-26 W. James MacLean <[email protected]>
+
+ [chromium] Allow modification of size of partially occluded quads during culling to reduce pixel overdraw.
+ https://bugs.webkit.org/show_bug.cgi?id=76349
+
+ Reviewed by James Robinson.
+
+ Prior to this patch, draw culling either rejects a DrawQuad because it is completely
+ occluded, or draws the entire quad (even if it is largely occluded). This patch
+ attempts to reduce the number of pixels drawn by determining if a partially
+ occluded DrawQuad can be resized to a smaller quad, based on what portion of the
+ DrawQuad is actually visible, and performing that resizing where possible.
+
+ Added cases to existing unit tests.
+
+ * platform/graphics/chromium/LayerRendererChromium.cpp:
+ (WebCore::LayerRendererChromium::drawTileQuad):
+ * platform/graphics/chromium/cc/CCDrawQuad.cpp:
+ (WebCore::CCDrawQuad::CCDrawQuad):
+ * platform/graphics/chromium/cc/CCDrawQuad.h:
+ (WebCore::CCDrawQuad::setQuadVisibleRect):
+ (WebCore::CCDrawQuad::quadVisibleRect):
+ * platform/graphics/chromium/cc/CCQuadCuller.cpp:
+ (WebCore::rectSubtractRegion):
+ (WebCore::CCQuadCuller::cullOccludedQuads):
+
2012-01-26 Anders Carlsson <[email protected]>
Scrollbars disappear when switching from legacy to overlay scrollbars
Modified: trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp (106075 => 106076)
--- trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp 2012-01-27 02:10:52 UTC (rev 106075)
+++ trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp 2012-01-27 02:11:55 UTC (rev 106076)
@@ -544,7 +544,7 @@
void LayerRendererChromium::drawTileQuad(const CCTileDrawQuad* quad)
{
- const IntRect& tileRect = quad->quadRect();
+ const IntRect& tileRect = quad->quadVisibleRect();
FloatRect clampRect(tileRect);
// Clamp texture coordinates to avoid sampling outside the layer
@@ -560,7 +560,8 @@
clampRect.inflateY(-clampY);
FloatSize clampOffset = clampRect.minXMinYCorner() - FloatRect(tileRect).minXMinYCorner();
- FloatPoint textureOffset = quad->textureOffset() + clampOffset;
+ FloatPoint textureOffset = quad->textureOffset() + clampOffset +
+ IntPoint(quad->quadVisibleRect().location() - quad->quadRect().location());
// Map clamping rectangle to unit square.
float vertexTexTranslateX = -clampRect.x() / clampRect.width();
@@ -623,13 +624,14 @@
CCLayerQuad::Edge topEdge(topLeft, topRight);
CCLayerQuad::Edge rightEdge(topRight, bottomRight);
- if (quad->topEdgeAA())
+ // Only apply anti-aliasing to edges not clipped during culling.
+ if (quad->topEdgeAA() && quad->quadVisibleRect().y() == quad->quadRect().y())
topEdge = deviceLayerEdges.top();
- if (quad->leftEdgeAA())
+ if (quad->leftEdgeAA() && quad->quadVisibleRect().x() == quad->quadRect().x())
leftEdge = deviceLayerEdges.left();
- if (quad->rightEdgeAA())
+ if (quad->rightEdgeAA() && quad->quadVisibleRect().maxX() == quad->quadRect().maxX())
rightEdge = deviceLayerEdges.right();
- if (quad->bottomEdgeAA())
+ if (quad->bottomEdgeAA() && quad->quadVisibleRect().maxY() == quad->quadRect().maxY())
bottomEdge = deviceLayerEdges.bottom();
float sign = FloatQuad(tileRect).isCounterclockwise() ? -1 : 1;
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.cpp (106075 => 106076)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.cpp 2012-01-27 02:10:52 UTC (rev 106075)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.cpp 2012-01-27 02:11:55 UTC (rev 106076)
@@ -42,6 +42,7 @@
: m_sharedQuadState(sharedQuadState)
, m_material(material)
, m_quadRect(quadRect)
+ , m_quadVisibleRect(quadRect)
, m_quadOpaque(true)
, m_needsBlending(false)
{
@@ -49,6 +50,12 @@
ASSERT(m_material != Invalid);
}
+void CCDrawQuad::setQuadVisibleRect(const IntRect& quadVisibleRect)
+{
+ m_quadVisibleRect = quadVisibleRect;
+ m_quadVisibleRect.intersect(m_quadRect);
+}
+
const CCDebugBorderDrawQuad* CCDrawQuad::toDebugBorderDrawQuad() const
{
ASSERT(m_material == DebugBorder);
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.h (106075 => 106076)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.h 2012-01-27 02:10:52 UTC (rev 106075)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCDrawQuad.h 2012-01-27 02:11:55 UTC (rev 106076)
@@ -56,6 +56,11 @@
bool needsBlending() const { return !m_sharedQuadState->isOpaque() || m_needsBlending || opacity() != 1; }
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().
+ void setQuadVisibleRect(const IntRect&);
+ const IntRect& quadVisibleRect() const { return m_quadVisibleRect; }
+
enum Material {
Invalid,
DebugBorder,
@@ -84,6 +89,7 @@
Material m_material;
IntRect m_quadRect;
+ IntRect m_quadVisibleRect;
// By default, the shared quad state determines whether or not this quad is
// opaque or needs blending. Derived classes can override with these
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp (106075 => 106076)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp 2012-01-27 02:10:52 UTC (rev 106075)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCQuadCuller.cpp 2012-01-27 02:11:55 UTC (rev 106076)
@@ -50,16 +50,29 @@
namespace WebCore {
-static bool regionContainsRect(const Region& region, const IntRect& rect)
+// Determines what portion of rect, if any, is visible (not occluded by region). If
+// the resulting visible region is not rectangular, we just return the original rect.
+static IntRect rectSubtractRegion(const Region& region, const IntRect& rect)
{
Region rectRegion(rect);
Region intersectRegion(intersect(region, rectRegion));
if (intersectRegion.isEmpty())
- return false;
+ return rect;
+ // Test if intersectRegion = rectRegion, if so return empty rect.
rectRegion.subtract(intersectRegion);
- return rectRegion.isEmpty();
+ IntRect boundsRect = rectRegion.bounds();
+ if (boundsRect.isEmpty())
+ return boundsRect;
+
+ // Test if rectRegion is still a rectangle. If it is, it will be identical to its bounds.
+ Region boundsRegion(boundsRect);
+ boundsRegion.subtract(rectRegion);
+ if (boundsRegion.isEmpty())
+ return boundsRect;
+
+ return rect;
}
static IntRect enclosedIntRect(const FloatRect& rect)
@@ -87,15 +100,22 @@
for (int i = quadList.size() - 1; i >= 0; --i) {
CCDrawQuad* drawQuad = quadList[i].get();
- IntRect quadRect(drawQuad->quadTransform().mapRect(drawQuad->quadRect()));
+ FloatRect floatTransformedRect = drawQuad->quadTransform().mapRect(FloatRect(drawQuad->quadRect()));
+ // Inflate rect to be tested to stay conservative.
+ IntRect transformedQuadRect(enclosingIntRect(floatTransformedRect));
- bool keepQuad = !regionContainsRect(opaqueCoverageThusFar, quadRect);
+ IntRect transformedVisibleQuadRect = rectSubtractRegion(opaqueCoverageThusFar, transformedQuadRect);
+ bool keepQuad = !transformedVisibleQuadRect.isEmpty();
- if (keepQuad && drawQuad->drawsOpaque() && drawQuad->isLayerAxisAlignedIntRect()) {
- IntRect opaqueRect = enclosedIntRect(drawQuad->quadTransform().mapRect(FloatRect(drawQuad->quadRect())));
- opaqueCoverageThusFar.unite(opaqueRect);
- }
+ // See if we can reduce the number of pixels to draw by reducing the size of the draw
+ // quad - we do this by changing its visible rect.
+ if (keepQuad && transformedVisibleQuadRect != transformedQuadRect && drawQuad->isLayerAxisAlignedIntRect())
+ drawQuad->setQuadVisibleRect(drawQuad->quadTransform().inverse().mapRect(transformedVisibleQuadRect));
+ // When adding rect to opaque region, deflate it to stay conservative.
+ if (keepQuad && drawQuad->drawsOpaque() && drawQuad->isLayerAxisAlignedIntRect())
+ opaqueCoverageThusFar.unite(Region(enclosedIntRect(floatTransformedRect)));
+
if (keepQuad)
culledList.append(quadList[i].release());
}
Modified: trunk/Source/WebKit/chromium/ChangeLog (106075 => 106076)
--- trunk/Source/WebKit/chromium/ChangeLog 2012-01-27 02:10:52 UTC (rev 106075)
+++ trunk/Source/WebKit/chromium/ChangeLog 2012-01-27 02:11:55 UTC (rev 106076)
@@ -1,3 +1,15 @@
+2012-01-26 W. James MacLean <[email protected]>
+
+ [chromium] Allow modification of size of partially occluded quads.
+ https://bugs.webkit.org/show_bug.cgi?id=76349
+
+ Reviewed by James Robinson.
+
+ * tests/CCQuadCullerTest.cpp:
+ (WebCore::makeTileQuads)
+ (WebCore::setQuads):
+ (WebCore::TEST):
+
2012-01-26 Michal Mocny <[email protected]>
[chromium] Revert changes which added setResourceUsageCHROMIUM gl extension since feature changed directions
Modified: trunk/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp (106075 => 106076)
--- trunk/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp 2012-01-27 02:10:52 UTC (rev 106075)
+++ trunk/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp 2012-01-27 02:11:55 UTC (rev 106076)
@@ -26,6 +26,7 @@
#include "cc/CCQuadCuller.h"
+#include "cc/CCTileDrawQuad.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -36,37 +37,29 @@
class CCQuadCullerTest : public testing::Test {
};
-class TestDrawQuad : public CCDrawQuad {
-public:
- TestDrawQuad(const CCSharedQuadState* state, Material m, const IntRect& rect)
- : CCDrawQuad(state, m, rect)
- {
- }
+static PassOwnPtr<CCDrawQuad> MakeTileQuad(CCSharedQuadState* state, const IntRect& rect)
+{
+ return CCTileDrawQuad::create(state, rect, 1, IntPoint(1, 1), IntSize(100, 100), 0, false, false, false, false, false);
+}
- static PassOwnPtr<TestDrawQuad> create(const CCSharedQuadState* state, Material m, const IntRect& rect)
- {
- return adoptPtr(new TestDrawQuad(state, m, rect));
- }
-};
-
void setQuads(CCSharedQuadState* rootState, CCSharedQuadState* childState, CCQuadList& quadList)
{
quadList.clear();
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(100, 0), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(200, 0), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(0, 100), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(100, 100), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(200, 100), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(0, 200), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(100, 200), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(rootState, CCDrawQuad::TiledContent, IntRect(IntPoint(200, 200), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(100, 0), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(200, 0), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(0, 100), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(100, 100), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(200, 100), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(0, 200), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(100, 200), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(rootState, IntRect(IntPoint(200, 200), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(childState, CCDrawQuad::TiledContent, IntRect(IntPoint(), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(childState, CCDrawQuad::TiledContent, IntRect(IntPoint(100, 0), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(childState, CCDrawQuad::TiledContent, IntRect(IntPoint(0, 100), IntSize(100, 100))));
- quadList.append(TestDrawQuad::create(childState, CCDrawQuad::TiledContent, IntRect(IntPoint(100, 100), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(childState, IntRect(IntPoint(), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(childState, IntRect(IntPoint(100, 0), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(childState, IntRect(IntPoint(0, 100), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(childState, IntRect(IntPoint(100, 100), IntSize(100, 100))));
}
#define DECLARE_AND_INITIALIZE_TEST_QUADS \
@@ -129,8 +122,69 @@
EXPECT_EQ(quadList.size(), 13u);
CCQuadCuller::cullOccludedQuads(quadList);
EXPECT_EQ(quadList.size(), 12u);
+
+ IntRect quadVisibleRect1 = quadList[1].get()->quadVisibleRect();
+ EXPECT_EQ(quadVisibleRect1.height(), 50);
+
+ IntRect quadVisibleRect3 = quadList[3].get()->quadVisibleRect();
+ EXPECT_EQ(quadVisibleRect3.width(), 50);
+
+ // Next index is 4, not 5, since centre quad culled.
+ IntRect quadVisibleRect4 = quadList[4].get()->quadVisibleRect();
+ EXPECT_EQ(quadVisibleRect4.width(), 50);
+ EXPECT_EQ(quadVisibleRect4.x(), 250);
+
+ IntRect quadVisibleRect6 = quadList[6].get()->quadVisibleRect();
+ EXPECT_EQ(quadVisibleRect6.height(), 50);
+ EXPECT_EQ(quadVisibleRect6.y(), 250);
}
+TEST(CCQuadCullerTest, verifyCullCenterTileNonIntegralSize1)
+{
+ DECLARE_AND_INITIALIZE_TEST_QUADS
+
+ childTransform.translate(100, 100);
+
+ // Create root layer tile with extent (99.1, 99.1) -> (200.9, 200.9) to make
+ // sure it doesn't get culled due to transform rounding.
+ TransformationMatrix rootTransform;
+ rootTransform.translate(99.1, 99.1);
+ rootTransform.scale(1.018);
+
+ OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(rootTransform, TransformationMatrix(), rootRect, IntRect(), 1.0, true);
+ OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true);
+
+ quadList.append(MakeTileQuad(rootState.get(), IntRect(IntPoint(), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(childState.get(), IntRect(IntPoint(), IntSize(100, 100))));
+
+ EXPECT_EQ(quadList.size(), 2u);
+ CCQuadCuller::cullOccludedQuads(quadList);
+ EXPECT_EQ(quadList.size(), 2u);
+}
+
+TEST(CCQuadCullerTest, verifyCullCenterTileNonIntegralSize2)
+{
+ DECLARE_AND_INITIALIZE_TEST_QUADS
+
+ // Make the child quad slightly smaller than, and centred over, the root layer tile.
+ // Verify the child does not cause the quad below to be culled due to rounding.
+ childTransform.translate(100.1, 100.1);
+ childTransform.scale(0.982);
+
+ TransformationMatrix rootTransform;
+ rootTransform.translate(100, 100);
+
+ OwnPtr<CCSharedQuadState> rootState = CCSharedQuadState::create(rootTransform, TransformationMatrix(), rootRect, IntRect(), 1.0, true);
+ OwnPtr<CCSharedQuadState> childState = CCSharedQuadState::create(childTransform, TransformationMatrix(), childRect, IntRect(), 1.0, true);
+
+ quadList.append(MakeTileQuad(rootState.get(), IntRect(IntPoint(), IntSize(100, 100))));
+ quadList.append(MakeTileQuad(childState.get(), IntRect(IntPoint(), IntSize(100, 100))));
+
+ EXPECT_EQ(quadList.size(), 2u);
+ CCQuadCuller::cullOccludedQuads(quadList);
+ EXPECT_EQ(quadList.size(), 2u);
+}
+
TEST(CCQuadCullerTest, verifyCullChildLinesUpBottomRight)
{
DECLARE_AND_INITIALIZE_TEST_QUADS
_______________________________________________ webkit-changes mailing list [email protected] http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes
