Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp (110528 => 110529)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp 2012-03-13 02:17:32 UTC (rev 110528)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp 2012-03-13 02:27:21 UTC (rev 110529)
@@ -270,12 +270,34 @@
return boundsRect;
}
+static FloatQuad projectQuad(const TransformationMatrix& transform, const FloatQuad& q, bool& clamped)
+{
+ FloatQuad projectedQuad;
+ bool clampedPoint;
+ projectedQuad.setP1(transform.projectPoint(q.p1(), &clampedPoint));
+ clamped = clampedPoint;
+ projectedQuad.setP2(transform.projectPoint(q.p2(), &clampedPoint));
+ clamped |= clampedPoint;
+ projectedQuad.setP3(transform.projectPoint(q.p3(), &clampedPoint));
+ clamped |= clampedPoint;
+ projectedQuad.setP4(transform.projectPoint(q.p4(), &clampedPoint));
+ clamped |= clampedPoint;
+
+ return projectedQuad;
+}
+
static inline IntRect computeUnoccludedContentRect(const IntRect& contentRect, const TransformationMatrix& contentSpaceTransform, const IntRect& scissorRect, const Region& occlusion)
{
+ if (!contentSpaceTransform.isInvertible())
+ return contentRect;
+
FloatRect transformedRect = contentSpaceTransform.mapRect(FloatRect(contentRect));
// Take the enclosingIntRect at each step, as we want to contain any unoccluded partial pixels in the resulting IntRect.
IntRect shrunkRect = rectSubtractRegion(intersection(enclosingIntRect(transformedRect), scissorRect), occlusion);
- IntRect unoccludedRect = enclosingIntRect(contentSpaceTransform.inverse().mapRect(FloatRect(shrunkRect)));
+ bool clamped; // FIXME: projectQuad returns invalid results when a point gets clamped. To be fixed in bug https://bugs.webkit.org/show_bug.cgi?id=80806.
+ IntRect unoccludedRect = enclosingIntRect(projectQuad(contentSpaceTransform.inverse(), FloatQuad(FloatRect(shrunkRect)), clamped).boundingBox());
+ if (clamped)
+ return contentRect;
// The rect back in content space is a bounding box and may extend outside of the original contentRect, so clamp it to the contentRectBounds.
return intersection(unoccludedRect, contentRect);
}
Modified: trunk/Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp (110528 => 110529)
--- trunk/Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp 2012-03-13 02:17:32 UTC (rev 110528)
+++ trunk/Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp 2012-03-13 02:27:21 UTC (rev 110529)
@@ -314,6 +314,9 @@
RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \
RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName)
+#define MAIN_THREAD_TEST(ClassName) \
+ RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName)
+
#define MAIN_AND_IMPL_THREAD_TEST(ClassName) \
RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \
RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName)
@@ -1712,4 +1715,83 @@
MAIN_AND_IMPL_THREAD_TEST(CCOcclusionTrackerTestOpaqueContentsRegionNonEmpty);
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTest3dTransform : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix transform;
+ transform.rotate3d(0, 30, 0);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::LayerType* container = this->createLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingSurface(container, transform, FloatPoint(100, 100), IntSize(200, 200), true);
+ calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.enterTargetRenderSurface(parent->renderSurface());
+
+ EXPECT_EQ_RECT(IntRect(0, 0, 200, 200), occlusion.unoccludedContentRect(layer, IntRect(0, 0, 200, 200)));
+ }
+};
+
+MAIN_AND_IMPL_THREAD_TEST(CCOcclusionTrackerTest3dTransform);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestPerspectiveTransform : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix transform;
+ transform.translate(150, 150);
+ transform.applyPerspective(400);
+ transform.rotate3d(1, 0, 0, -30);
+ transform.translate(-150, -150);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::LayerType* container = this->createLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(300, 300));
+ typename Types::ContentLayerType* layer = this->createDrawingSurface(container, transform, FloatPoint(100, 100), IntSize(200, 200), true);
+ container->setPreserves3D(true);
+ calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.enterTargetRenderSurface(parent->renderSurface());
+
+ EXPECT_EQ_RECT(IntRect(0, 0, 200, 200), occlusion.unoccludedContentRect(layer, IntRect(0, 0, 200, 200)));
+ }
+};
+
+MAIN_THREAD_TEST(CCOcclusionTrackerTestPerspectiveTransform);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestPerspectiveTransformBehindCamera : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ // This test is based on the platform/chromium/compositing/3d-corners.html layout test.
+ TransformationMatrix transform;
+ transform.translate(250, 50);
+ transform.applyPerspective(10);
+ transform.translate(-250, -50);
+ transform.translate(250, 50);
+ transform.rotate3d(1, 0, 0, -167);
+ transform.translate(-250, -50);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(500, 100));
+ typename Types::LayerType* container = this->createLayer(parent, this->identityMatrix, FloatPoint(0, 0), IntSize(500, 500));
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(container, transform, FloatPoint(0, 0), IntSize(500, 500), true);
+ container->setPreserves3D(true);
+ calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerBase<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.enterTargetRenderSurface(parent->renderSurface());
+
+ // The bottom 11 pixel rows of this layer remain visible inside the container, after translation to the target surface. When translated back,
+ // this will include many more pixels but must include at least the bottom 11 rows.
+ EXPECT_TRUE(occlusion.unoccludedContentRect(layer, IntRect(0, 0, 500, 500)).contains(IntRect(0, 489, 500, 11)));
+ }
+};
+
+MAIN_THREAD_TEST(CCOcclusionTrackerTestPerspectiveTransformBehindCamera);
+
} // namespace