Diff
Modified: trunk/Source/WebCore/ChangeLog (113560 => 113561)
--- trunk/Source/WebCore/ChangeLog 2012-04-09 08:49:02 UTC (rev 113560)
+++ trunk/Source/WebCore/ChangeLog 2012-04-09 09:05:50 UTC (rev 113561)
@@ -1,3 +1,34 @@
+2012-04-09 Dana Jansens <[email protected]>
+
+ [chromium] Make culling work with clipped rects
+ https://bugs.webkit.org/show_bug.cgi?id=83217
+
+ Reviewed by Adrienne Walker.
+
+ Use new CCMathUtil transformation methods to deal with rects that clip
+ the camera plane. This fixes three things:
+
+ 1. A layer completely behind the camera is not visible and should not
+ occlude.
+ 2. A layer that is clipped by the camera is treated like a
+ non-axis-aligned transform, as the result of a mapClippedRect() is a
+ bounding box and may contain pixels not in the original rect. This guards
+ our use of mapRect() when transforming occluded regions.
+ 3. A layer's occlusion must be clipped by its scissor rect. This scissor
+ rect exists in its target space, so occlusion in screen space is only
+ possible if its target also is axis aligned in the screen, such that
+ the layer's scissor rect remains a rect in screen space.
+
+ Unit tests: CCOcclusionTrackerTestLayerBehindCameraDoesNotOcclude
+ CCOcclusionTrackerTestLargePixelsOccludeInsideClipRect
+
+ * platform/graphics/chromium/cc/CCOcclusionTracker.cpp:
+ (WebCore::transformSurfaceOpaqueRegion):
+ (WebCore::computeOcclusionBehindLayer):
+ (WebCore::::markOccludedBehindLayer):
+ (WebCore::testContentRectOccluded):
+ (WebCore::computeUnoccludedContentRect):
+
2012-04-09 Zan Dobersek <[email protected]>
[Gtk] Web Inspector noinst_DATA images are copied into innacurately named directory
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp (113560 => 113561)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp 2012-04-09 08:49:02 UTC (rev 113560)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCOcclusionTracker.cpp 2012-04-09 09:05:50 UTC (rev 113561)
@@ -115,13 +115,16 @@
// Verify that rects within the |surface| will remain rects in its target surface after applying |transform|. If this is true, then
// apply |transform| to each rect within |region| in order to transform the entire Region.
- FloatQuad transformedBoundsQuad = transform.mapQuad(FloatQuad(region.bounds()));
- if (!transformedBoundsQuad.isRectilinear())
+ bool clipped;
+ FloatQuad transformedBoundsQuad = CCMathUtil::mapQuad(transform, FloatQuad(region.bounds()), clipped);
+ // FIXME: Find a rect interior to each transformed quad.
+ if (clipped || !transformedBoundsQuad.isRectilinear())
return Region();
Region transformedRegion;
Vector<IntRect> rects = region.rects();
+ // Clipping has been verified above, so mapRect will give correct results.
for (size_t i = 0; i < rects.size(); ++i)
transformedRegion.unite(enclosedIntRect(transform.mapRect(FloatRect(rects[i]))));
return transformedRegion;
@@ -195,13 +198,15 @@
// FIXME: Remove usePaintTracking when paint tracking is on for paint culling.
template<typename LayerType>
-static inline Region computeOcclusionBehindLayer(const LayerType* layer, const TransformationMatrix& transform, bool usePaintTracking)
+static inline Region computeOcclusionBehindLayer(const LayerType* layer, const TransformationMatrix& transform, const IntRect& scissorRect, bool usePaintTracking)
{
Region opaqueRegion;
- FloatQuad unoccludedQuad = transform.mapQuad(FloatQuad(layer->visibleLayerRect()));
+ bool clipped;
+ FloatQuad unoccludedQuad = CCMathUtil::mapQuad(transform, FloatQuad(layer->visibleLayerRect()), clipped);
bool isPaintedAxisAligned = unoccludedQuad.isRectilinear();
- if (!isPaintedAxisAligned)
+ // FIXME: Find a rect interior to each transformed quad.
+ if (clipped || !isPaintedAxisAligned)
return opaqueRegion;
if (layer->opaque())
@@ -211,9 +216,11 @@
else if (usePaintTracking) {
Region contentRegion = layer->visibleContentOpaqueRegion();
Vector<IntRect> contentRects = contentRegion.rects();
+ // We verify that the possible bounds of this region are not clipped above, so we can use mapRect() safely here.
for (size_t i = 0; i < contentRects.size(); ++i)
opaqueRegion.unite(enclosedIntRect(transform.mapRect(FloatRect(contentRects[i]))));
}
+ opaqueRegion.intersect(scissorRect);
return opaqueRegion;
}
@@ -228,16 +235,26 @@
if (!layerOpacityKnown(layer) || layer->drawOpacity() < 1)
return;
- // FIXME: Remove m_usePaintTracking when paint tracking is on for paint culling.
- if (layerTransformsToScreenKnown(layer))
- m_stack.last().occlusionInScreen.unite(computeOcclusionBehindLayer<LayerType>(layer, contentToScreenSpaceTransform<LayerType>(layer), m_usePaintTracking));
+ IntRect scissorInTarget = layerScissorRectInTargetSurface(layer);
if (layerTransformsToTargetKnown(layer))
- m_stack.last().occlusionInTarget.unite(computeOcclusionBehindLayer<LayerType>(layer, contentToTargetSurfaceTransform<LayerType>(layer), m_usePaintTracking));
+ m_stack.last().occlusionInTarget.unite(computeOcclusionBehindLayer<LayerType>(layer, contentToTargetSurfaceTransform<LayerType>(layer), scissorInTarget, m_usePaintTracking));
+
+ // We must clip the occlusion within the layer's scissorInTarget within screen space as well. If the scissor rect can't be moved to screen space and
+ // remain rectilinear, then we don't add any occlusion in screen space.
+
+ if (layerTransformsToScreenKnown(layer)) {
+ TransformationMatrix targetToScreenTransform = m_stack.last().surface->screenSpaceTransform();
+ FloatQuad scissorInScreenQuad = targetToScreenTransform.mapQuad(FloatQuad(FloatRect(scissorInTarget)));
+ if (!scissorInScreenQuad.isRectilinear())
+ return;
+ IntRect scissorInScreenRect = intersection(m_scissorRectInScreenSpace, enclosedIntRect(CCMathUtil::mapClippedRect(targetToScreenTransform, FloatRect(scissorInTarget))));
+ m_stack.last().occlusionInScreen.unite(computeOcclusionBehindLayer<LayerType>(layer, contentToScreenSpaceTransform<LayerType>(layer), scissorInScreenRect, m_usePaintTracking));
+ }
}
static inline bool testContentRectOccluded(const IntRect& contentRect, const TransformationMatrix& contentSpaceTransform, const IntRect& scissorRect, const Region& occlusion)
{
- FloatRect transformedRect = contentSpaceTransform.mapRect(FloatRect(contentRect));
+ FloatRect transformedRect = CCMathUtil::mapClippedRect(contentSpaceTransform, FloatRect(contentRect));
// Take the enclosingIntRect, as we want to include partial pixels in the test.
IntRect targetRect = intersection(enclosingIntRect(transformedRect), scissorRect);
return targetRect.isEmpty() || occlusion.contains(targetRect);
@@ -281,13 +298,10 @@
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.
+ FloatRect transformedRect = CCMathUtil::mapClippedRect(contentSpaceTransform, FloatRect(contentRect));
IntRect shrunkRect = rectSubtractRegion(intersection(enclosingIntRect(transformedRect), scissorRect), occlusion);
- bool clipped; // FIXME: We should be able to use projectClippedQuad instead of forcing everything to be unoccluded. https://bugs.webkit.org/show_bug.cgi?id=83217.
- IntRect unoccludedRect = enclosingIntRect(CCMathUtil::projectQuad(contentSpaceTransform.inverse(), FloatQuad(FloatRect(shrunkRect)), clipped).boundingBox());
- if (clipped)
- return contentRect;
+ IntRect unoccludedRect = enclosingIntRect(CCMathUtil::projectClippedRect(contentSpaceTransform.inverse(), FloatRect(shrunkRect)));
// 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/ChangeLog (113560 => 113561)
--- trunk/Source/WebKit/chromium/ChangeLog 2012-04-09 08:49:02 UTC (rev 113560)
+++ trunk/Source/WebKit/chromium/ChangeLog 2012-04-09 09:05:50 UTC (rev 113561)
@@ -1,3 +1,19 @@
+2012-04-09 Dana Jansens <[email protected]>
+
+ [chromium] Make culling work with clipped rects
+ https://bugs.webkit.org/show_bug.cgi?id=83217
+
+ Reviewed by Adrienne Walker.
+
+ * tests/CCOcclusionTrackerTest.cpp:
+ (CCOcclusionTrackerTestLayerBehindCameraDoesNotOcclude):
+ (WebKitTests::CCOcclusionTrackerTestLayerBehindCameraDoesNotOcclude::runMyTest):
+ (WebKitTests):
+ (CCOcclusionTrackerTestLargePixelsOccludeInsideClipRect):
+ (WebKitTests::CCOcclusionTrackerTestLargePixelsOccludeInsideClipRect::runMyTest):
+ * tests/CCQuadCullerTest.cpp:
+ (WebCore::TestCCOcclusionTrackerImpl::TestCCOcclusionTrackerImpl):
+
2012-04-06 Ami Fischman <[email protected]>
Roll Chromium DEPS
Modified: trunk/Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp (113560 => 113561)
--- trunk/Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp 2012-04-09 08:49:02 UTC (rev 113560)
+++ trunk/Source/WebKit/chromium/tests/CCOcclusionTrackerTest.cpp 2012-04-09 09:05:50 UTC (rev 113561)
@@ -1674,6 +1674,65 @@
MAIN_THREAD_TEST(CCOcclusionTrackerTestPerspectiveTransformBehindCamera);
template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestLayerBehindCameraDoesNotOcclude : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix transform;
+ transform.translate(50, 50);
+ transform.applyPerspective(100);
+ transform.translate3d(0, 0, 110);
+ transform.translate(-50, -50);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, transform, FloatPoint(0, 0), IntSize(100, 100), true);
+ parent->setPreserves3D(true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.enterTargetRenderSurface(parent->renderSurface());
+
+ // This layer is entirely behind the camera and should not occlude.
+ occlusion.markOccludedBehindLayer(layer);
+ EXPECT_EQ(0u, occlusion.occlusionInTargetSurface().rects().size());
+ EXPECT_EQ(0u, occlusion.occlusionInScreenSpace().rects().size());
+ }
+};
+
+MAIN_THREAD_TEST(CCOcclusionTrackerTestLayerBehindCameraDoesNotOcclude);
+
+template<class Types, bool opaqueLayers>
+class CCOcclusionTrackerTestLargePixelsOccludeInsideClipRect : public CCOcclusionTrackerTest<Types, opaqueLayers> {
+protected:
+ void runMyTest()
+ {
+ TransformationMatrix transform;
+ transform.translate(50, 50);
+ transform.applyPerspective(100);
+ transform.translate3d(0, 0, 99);
+ transform.translate(-50, -50);
+
+ typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, FloatPoint(0, 0), IntSize(100, 100));
+ typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, transform, FloatPoint(0, 0), IntSize(100, 100), true);
+ parent->setPreserves3D(true);
+ this->calcDrawEtc(parent);
+
+ TestCCOcclusionTrackerWithScissor<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(IntRect(0, 0, 1000, 1000));
+ occlusion.enterTargetRenderSurface(parent->renderSurface());
+
+ // This is very close to the camera, so pixels in its visibleLayerRect will actually go outside of the layer's clipRect.
+ // Ensure that those pixels don't occlude things outside the clipRect.
+ occlusion.markOccludedBehindLayer(layer);
+ EXPECT_EQ(IntRect(0, 0, 100, 100), occlusion.occlusionInTargetSurface().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInTargetSurface().rects().size());
+ EXPECT_EQ(IntRect(0, 0, 100, 100), occlusion.occlusionInScreenSpace().bounds());
+ EXPECT_EQ(1u, occlusion.occlusionInScreenSpace().rects().size());
+ }
+};
+
+MAIN_THREAD_TEST(CCOcclusionTrackerTestLargePixelsOccludeInsideClipRect);
+
+template<class Types, bool opaqueLayers>
class CCOcclusionTrackerTestAnimationOpacity1OnMainThread : public CCOcclusionTrackerTest<Types, opaqueLayers> {
protected:
void runMyTest()
Modified: trunk/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp (113560 => 113561)
--- trunk/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp 2012-04-09 08:49:02 UTC (rev 113560)
+++ trunk/Source/WebKit/chromium/tests/CCQuadCullerTest.cpp 2012-04-09 09:05:50 UTC (rev 113561)
@@ -44,8 +44,9 @@
: CCOcclusionTrackerImpl(scissorRectInScreen, recordMetricsForFrame)
, m_scissorRectInScreen(scissorRectInScreen)
{
- // Pretend we have visited a render surface.
+ // Pretend we have visited the root render surface.
m_stack.append(StackObject());
+ m_stack.last().surface = new CCRenderSurface(0);
}
protected: