| // Copyright 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "cc/occlusion_tracker.h" |
| |
| #include <public/WebFilterOperation.h> |
| #include <public/WebFilterOperations.h> |
| |
| #include "cc/layer.h" |
| #include "cc/layer_animation_controller.h" |
| #include "cc/layer_impl.h" |
| #include "cc/layer_tree_host_common.h" |
| #include "cc/math_util.h" |
| #include "cc/overdraw_metrics.h" |
| #include "cc/single_thread_proxy.h" |
| #include "cc/test/animation_test_common.h" |
| #include "cc/test/geometry_test_utils.h" |
| #include "cc/test/occlusion_tracker_test_common.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/gfx/transform.h" |
| |
| using namespace WebKit; |
| using namespace WebKitTests; |
| |
| namespace cc { |
| namespace { |
| |
| class TestContentLayer : public Layer { |
| public: |
| TestContentLayer() |
| : Layer() |
| , m_overrideOpaqueContentsRect(false) |
| { |
| } |
| |
| virtual bool drawsContent() const OVERRIDE { return true; } |
| virtual Region visibleContentOpaqueRegion() const OVERRIDE |
| { |
| if (m_overrideOpaqueContentsRect) |
| return gfx::IntersectRects(m_opaqueContentsRect, visibleContentRect()); |
| return Layer::visibleContentOpaqueRegion(); |
| } |
| void setOpaqueContentsRect(const gfx::Rect& opaqueContentsRect) |
| { |
| m_overrideOpaqueContentsRect = true; |
| m_opaqueContentsRect = opaqueContentsRect; |
| } |
| |
| private: |
| virtual ~TestContentLayer() |
| { |
| } |
| |
| bool m_overrideOpaqueContentsRect; |
| gfx::Rect m_opaqueContentsRect; |
| }; |
| |
| class TestContentLayerImpl : public LayerImpl { |
| public: |
| TestContentLayerImpl(int id) |
| : LayerImpl(id) |
| , m_overrideOpaqueContentsRect(false) |
| { |
| setDrawsContent(true); |
| } |
| |
| virtual Region visibleContentOpaqueRegion() const OVERRIDE |
| { |
| if (m_overrideOpaqueContentsRect) |
| return gfx::IntersectRects(m_opaqueContentsRect, visibleContentRect()); |
| return LayerImpl::visibleContentOpaqueRegion(); |
| } |
| void setOpaqueContentsRect(const gfx::Rect& opaqueContentsRect) |
| { |
| m_overrideOpaqueContentsRect = true; |
| m_opaqueContentsRect = opaqueContentsRect; |
| } |
| |
| private: |
| bool m_overrideOpaqueContentsRect; |
| gfx::Rect m_opaqueContentsRect; |
| }; |
| |
| static inline bool layerImplDrawTransformIsUnknown(const Layer* layer) { return layer->drawTransformIsAnimating(); } |
| static inline bool layerImplDrawTransformIsUnknown(const LayerImpl*) { return false; } |
| |
| template<typename LayerType, typename RenderSurfaceType> |
| class TestOcclusionTrackerWithClip : public TestOcclusionTrackerBase<LayerType, RenderSurfaceType> { |
| public: |
| TestOcclusionTrackerWithClip(gfx::Rect viewportRect, bool recordMetricsForFrame = false) |
| : TestOcclusionTrackerBase<LayerType, RenderSurfaceType>(viewportRect, recordMetricsForFrame) |
| , m_overrideLayerClipRect(false) |
| { |
| } |
| |
| void setLayerClipRect(const gfx::Rect& rect) { m_overrideLayerClipRect = true; m_layerClipRect = rect;} |
| void useDefaultLayerClipRect() { m_overrideLayerClipRect = false; } |
| // Returns true if the given rect in content space for the layer is fully occluded in either screen space or the layer's target surface. |
| bool occludedLayer(const LayerType* layer, const gfx::Rect& contentRect, bool* hasOcclusionFromOutsideTargetSurface = 0) const |
| { |
| return this->occluded(layer->renderTarget(), contentRect, layer->drawTransform(), layerImplDrawTransformIsUnknown(layer), layerClipRectInTarget(layer), hasOcclusionFromOutsideTargetSurface); |
| } |
| // Gives an unoccluded sub-rect of |contentRect| in the content space of the layer. Simple wrapper around unoccludedContentRect. |
| gfx::Rect unoccludedLayerContentRect(const LayerType* layer, const gfx::Rect& contentRect, bool* hasOcclusionFromOutsideTargetSurface = 0) const |
| { |
| return this->unoccludedContentRect(layer->renderTarget(), contentRect, layer->drawTransform(), layerImplDrawTransformIsUnknown(layer), layerClipRectInTarget(layer), hasOcclusionFromOutsideTargetSurface); |
| } |
| |
| |
| protected: |
| virtual gfx::Rect layerClipRectInTarget(const LayerType* layer) const { return m_overrideLayerClipRect ? m_layerClipRect : OcclusionTrackerBase<LayerType, RenderSurfaceType>::layerClipRectInTarget(layer); } |
| |
| private: |
| bool m_overrideLayerClipRect; |
| gfx::Rect m_layerClipRect; |
| }; |
| |
| struct OcclusionTrackerTestMainThreadTypes { |
| typedef Layer LayerType; |
| typedef RenderSurface RenderSurfaceType; |
| typedef TestContentLayer ContentLayerType; |
| typedef scoped_refptr<Layer> LayerPtrType; |
| typedef scoped_refptr<ContentLayerType> ContentLayerPtrType; |
| typedef LayerIterator<Layer, std::vector<scoped_refptr<Layer> >, RenderSurface, LayerIteratorActions::FrontToBack> TestLayerIterator; |
| typedef OcclusionTracker OcclusionTrackerType; |
| |
| static LayerPtrType createLayer() |
| { |
| return Layer::create(); |
| } |
| static ContentLayerPtrType createContentLayer() { return make_scoped_refptr(new ContentLayerType()); } |
| |
| static LayerPtrType passLayerPtr(ContentLayerPtrType& layer) |
| { |
| return layer.release(); |
| } |
| |
| static LayerPtrType passLayerPtr(LayerPtrType& layer) |
| { |
| return layer.release(); |
| } |
| |
| static void destroyLayer(LayerPtrType& layer) |
| { |
| layer = NULL; |
| } |
| }; |
| |
| struct OcclusionTrackerTestImplThreadTypes { |
| typedef LayerImpl LayerType; |
| typedef RenderSurfaceImpl RenderSurfaceType; |
| typedef TestContentLayerImpl ContentLayerType; |
| typedef scoped_ptr<LayerImpl> LayerPtrType; |
| typedef scoped_ptr<ContentLayerType> ContentLayerPtrType; |
| typedef LayerIterator<LayerImpl, std::vector<LayerImpl*>, RenderSurfaceImpl, LayerIteratorActions::FrontToBack> TestLayerIterator; |
| typedef OcclusionTrackerImpl OcclusionTrackerType; |
| |
| static LayerPtrType createLayer() { return LayerImpl::create(nextLayerImplId++); } |
| static ContentLayerPtrType createContentLayer() { return make_scoped_ptr(new ContentLayerType(nextLayerImplId++)); } |
| static int nextLayerImplId; |
| |
| static LayerPtrType passLayerPtr(LayerPtrType& layer) |
| { |
| return layer.Pass(); |
| } |
| |
| static LayerPtrType passLayerPtr(ContentLayerPtrType& layer) |
| { |
| return layer.PassAs<LayerType>(); |
| } |
| |
| static void destroyLayer(LayerPtrType& layer) |
| { |
| layer.reset(); |
| } |
| }; |
| |
| int OcclusionTrackerTestImplThreadTypes::nextLayerImplId = 1; |
| |
| template<typename Types> |
| class OcclusionTrackerTest : public testing::Test { |
| protected: |
| OcclusionTrackerTest(bool opaqueLayers) |
| : m_opaqueLayers(opaqueLayers) |
| { } |
| |
| virtual void runMyTest() = 0; |
| |
| virtual void TearDown() |
| { |
| Types::destroyLayer(m_root); |
| m_renderSurfaceLayerList.clear(); |
| m_renderSurfaceLayerListImpl.clear(); |
| m_replicaLayers.clear(); |
| m_maskLayers.clear(); |
| LayerTreeHost::setNeedsFilterContext(false); |
| } |
| |
| typename Types::ContentLayerType* createRoot(const gfx::Transform& transform, const gfx::PointF& position, const gfx::Size& bounds) |
| { |
| typename Types::ContentLayerPtrType layer(Types::createContentLayer()); |
| typename Types::ContentLayerType* layerPtr = layer.get(); |
| setProperties(layerPtr, transform, position, bounds); |
| |
| DCHECK(!m_root); |
| m_root = Types::passLayerPtr(layer); |
| return layerPtr; |
| } |
| |
| typename Types::LayerType* createLayer(typename Types::LayerType* parent, const gfx::Transform& transform, const gfx::PointF& position, const gfx::Size& bounds) |
| { |
| typename Types::LayerPtrType layer(Types::createLayer()); |
| typename Types::LayerType* layerPtr = layer.get(); |
| setProperties(layerPtr, transform, position, bounds); |
| parent->addChild(Types::passLayerPtr(layer)); |
| return layerPtr; |
| } |
| |
| typename Types::LayerType* createSurface(typename Types::LayerType* parent, const gfx::Transform& transform, const gfx::PointF& position, const gfx::Size& bounds) |
| { |
| typename Types::LayerType* layer = createLayer(parent, transform, position, bounds); |
| WebFilterOperations filters; |
| filters.append(WebFilterOperation::createGrayscaleFilter(0.5)); |
| layer->setFilters(filters); |
| return layer; |
| } |
| |
| typename Types::ContentLayerType* createDrawingLayer(typename Types::LayerType* parent, const gfx::Transform& transform, const gfx::PointF& position, const gfx::Size& bounds, bool opaque) |
| { |
| typename Types::ContentLayerPtrType layer(Types::createContentLayer()); |
| typename Types::ContentLayerType* layerPtr = layer.get(); |
| setProperties(layerPtr, transform, position, bounds); |
| |
| if (m_opaqueLayers) |
| layerPtr->setContentsOpaque(opaque); |
| else { |
| layerPtr->setContentsOpaque(false); |
| if (opaque) |
| layerPtr->setOpaqueContentsRect(gfx::Rect(gfx::Point(), bounds)); |
| else |
| layerPtr->setOpaqueContentsRect(gfx::Rect()); |
| } |
| |
| parent->addChild(Types::passLayerPtr(layer)); |
| return layerPtr; |
| } |
| |
| typename Types::LayerType* createReplicaLayer(typename Types::LayerType* owningLayer, const gfx::Transform& transform, const gfx::PointF& position, const gfx::Size& bounds) |
| { |
| typename Types::ContentLayerPtrType layer(Types::createContentLayer()); |
| typename Types::ContentLayerType* layerPtr = layer.get(); |
| setProperties(layerPtr, transform, position, bounds); |
| setReplica(owningLayer, Types::passLayerPtr(layer)); |
| return layerPtr; |
| } |
| |
| typename Types::LayerType* createMaskLayer(typename Types::LayerType* owningLayer, const gfx::Size& bounds) |
| { |
| typename Types::ContentLayerPtrType layer(Types::createContentLayer()); |
| typename Types::ContentLayerType* layerPtr = layer.get(); |
| setProperties(layerPtr, identityMatrix, gfx::PointF(), bounds); |
| setMask(owningLayer, Types::passLayerPtr(layer)); |
| return layerPtr; |
| } |
| |
| typename Types::ContentLayerType* createDrawingSurface(typename Types::LayerType* parent, const gfx::Transform& transform, const gfx::PointF& position, const gfx::Size& bounds, bool opaque) |
| { |
| typename Types::ContentLayerType* layer = createDrawingLayer(parent, transform, position, bounds, opaque); |
| WebFilterOperations filters; |
| filters.append(WebFilterOperation::createGrayscaleFilter(0.5)); |
| layer->setFilters(filters); |
| return layer; |
| } |
| |
| void calcDrawEtc(TestContentLayerImpl* root) |
| { |
| DCHECK(root == m_root.get()); |
| int dummyMaxTextureSize = 512; |
| LayerSorter layerSorter; |
| |
| DCHECK(!root->renderSurface()); |
| |
| LayerTreeHostCommon::calculateDrawTransforms(root, root->bounds(), 1, 1, &layerSorter, dummyMaxTextureSize, m_renderSurfaceLayerListImpl); |
| |
| m_layerIterator = m_layerIteratorBegin = Types::TestLayerIterator::begin(&m_renderSurfaceLayerListImpl); |
| } |
| |
| void calcDrawEtc(TestContentLayer* root) |
| { |
| DCHECK(root == m_root.get()); |
| int dummyMaxTextureSize = 512; |
| |
| DCHECK(!root->renderSurface()); |
| |
| LayerTreeHostCommon::calculateDrawTransforms(root, root->bounds(), 1, 1, dummyMaxTextureSize, m_renderSurfaceLayerList); |
| |
| m_layerIterator = m_layerIteratorBegin = Types::TestLayerIterator::begin(&m_renderSurfaceLayerList); |
| } |
| |
| void enterLayer(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion) |
| { |
| ASSERT_EQ(layer, *m_layerIterator); |
| ASSERT_TRUE(m_layerIterator.representsItself()); |
| occlusion.enterLayer(m_layerIterator); |
| } |
| |
| void leaveLayer(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion) |
| { |
| ASSERT_EQ(layer, *m_layerIterator); |
| ASSERT_TRUE(m_layerIterator.representsItself()); |
| occlusion.leaveLayer(m_layerIterator); |
| ++m_layerIterator; |
| } |
| |
| void visitLayer(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion) |
| { |
| enterLayer(layer, occlusion); |
| leaveLayer(layer, occlusion); |
| } |
| |
| void enterContributingSurface(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion) |
| { |
| ASSERT_EQ(layer, *m_layerIterator); |
| ASSERT_TRUE(m_layerIterator.representsTargetRenderSurface()); |
| occlusion.enterLayer(m_layerIterator); |
| occlusion.leaveLayer(m_layerIterator); |
| ++m_layerIterator; |
| ASSERT_TRUE(m_layerIterator.representsContributingRenderSurface()); |
| occlusion.enterLayer(m_layerIterator); |
| } |
| |
| void leaveContributingSurface(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion) |
| { |
| ASSERT_EQ(layer, *m_layerIterator); |
| ASSERT_TRUE(m_layerIterator.representsContributingRenderSurface()); |
| occlusion.leaveLayer(m_layerIterator); |
| ++m_layerIterator; |
| } |
| |
| void visitContributingSurface(typename Types::LayerType* layer, typename Types::OcclusionTrackerType& occlusion) |
| { |
| enterContributingSurface(layer, occlusion); |
| leaveContributingSurface(layer, occlusion); |
| } |
| |
| void resetLayerIterator() |
| { |
| m_layerIterator = m_layerIteratorBegin; |
| } |
| |
| const gfx::Transform identityMatrix; |
| |
| private: |
| void setBaseProperties(typename Types::LayerType* layer, const gfx::Transform& transform, const gfx::PointF& position, const gfx::Size& bounds) |
| { |
| layer->setTransform(transform); |
| layer->setSublayerTransform(gfx::Transform()); |
| layer->setAnchorPoint(gfx::PointF(0, 0)); |
| layer->setPosition(position); |
| layer->setBounds(bounds); |
| } |
| |
| void setProperties(Layer* layer, const gfx::Transform& transform, const gfx::PointF& position, const gfx::Size& bounds) |
| { |
| setBaseProperties(layer, transform, position, bounds); |
| } |
| |
| void setProperties(LayerImpl* layer, const gfx::Transform& transform, const gfx::PointF& position, const gfx::Size& bounds) |
| { |
| setBaseProperties(layer, transform, position, bounds); |
| |
| layer->setContentBounds(layer->bounds()); |
| } |
| |
| void setReplica(Layer* owningLayer, scoped_refptr<Layer> layer) |
| { |
| owningLayer->setReplicaLayer(layer.get()); |
| m_replicaLayers.push_back(layer); |
| } |
| |
| void setReplica(LayerImpl* owningLayer, scoped_ptr<LayerImpl> layer) |
| { |
| owningLayer->setReplicaLayer(layer.Pass()); |
| } |
| |
| void setMask(Layer* owningLayer, scoped_refptr<Layer> layer) |
| { |
| owningLayer->setMaskLayer(layer.get()); |
| m_maskLayers.push_back(layer); |
| } |
| |
| void setMask(LayerImpl* owningLayer, scoped_ptr<LayerImpl> layer) |
| { |
| owningLayer->setMaskLayer(layer.Pass()); |
| } |
| |
| bool m_opaqueLayers; |
| // These hold ownership of the layers for the duration of the test. |
| typename Types::LayerPtrType m_root; |
| std::vector<scoped_refptr<Layer> > m_renderSurfaceLayerList; |
| std::vector<LayerImpl*> m_renderSurfaceLayerListImpl; |
| typename Types::TestLayerIterator m_layerIteratorBegin; |
| typename Types::TestLayerIterator m_layerIterator; |
| typename Types::LayerType* m_lastLayerVisited; |
| std::vector<scoped_refptr<Layer> > m_replicaLayers; |
| std::vector<scoped_refptr<Layer> > m_maskLayers; |
| }; |
| |
| #define RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \ |
| class ClassName##MainThreadOpaqueLayers : public ClassName<OcclusionTrackerTestMainThreadTypes> { \ |
| public: \ |
| ClassName##MainThreadOpaqueLayers() : ClassName<OcclusionTrackerTestMainThreadTypes>(true) { } \ |
| }; \ |
| TEST_F(ClassName##MainThreadOpaqueLayers, runTest) { runMyTest(); } |
| #define RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \ |
| class ClassName##MainThreadOpaquePaints : public ClassName<OcclusionTrackerTestMainThreadTypes> { \ |
| public: \ |
| ClassName##MainThreadOpaquePaints() : ClassName<OcclusionTrackerTestMainThreadTypes>(false) { } \ |
| }; \ |
| TEST_F(ClassName##MainThreadOpaquePaints, runTest) { runMyTest(); } |
| |
| #define RUN_TEST_IMPL_THREAD_OPAQUE_LAYERS(ClassName) \ |
| class ClassName##ImplThreadOpaqueLayers : public ClassName<OcclusionTrackerTestImplThreadTypes> { \ |
| public: \ |
| ClassName##ImplThreadOpaqueLayers() : ClassName<OcclusionTrackerTestImplThreadTypes>(true) { } \ |
| }; \ |
| TEST_F(ClassName##ImplThreadOpaqueLayers, runTest) { runMyTest(); } |
| #define RUN_TEST_IMPL_THREAD_OPAQUE_PAINTS(ClassName) \ |
| class ClassName##ImplThreadOpaquePaints : public ClassName<OcclusionTrackerTestImplThreadTypes> { \ |
| public: \ |
| ClassName##ImplThreadOpaquePaints() : ClassName<OcclusionTrackerTestImplThreadTypes>(false) { } \ |
| }; \ |
| TEST_F(ClassName##ImplThreadOpaquePaints, runTest) { runMyTest(); } |
| |
| #define ALL_OCCLUSIONTRACKER_TEST(ClassName) \ |
| RUN_TEST_MAIN_THREAD_OPAQUE_LAYERS(ClassName) \ |
| RUN_TEST_MAIN_THREAD_OPAQUE_PAINTS(ClassName) \ |
| 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 IMPL_THREAD_TEST(ClassName) \ |
| RUN_TEST_IMPL_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) |
| |
| template<class Types> |
| class OcclusionTrackerTestIdentityTransforms : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestIdentityTransforms(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100)); |
| typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(30, 30), gfx::Size(500, 500), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(30, 30, 70, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(29, 30, 70, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(30, 29, 70, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(31, 30, 70, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(30, 31, 70, 70))); |
| |
| occlusion.useDefaultLayerClipRect(); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(30, 30, 70, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(29, 30, 70, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(30, 29, 70, 70))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(31, 30, 70, 70))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(30, 31, 70, 70))); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(30, 30, 70, 70)).IsEmpty()); |
| EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 70), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(29, 30, 70, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(29, 29, 70, 70), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(29, 29, 70, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 1), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(30, 29, 70, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(31, 29, 70, 70), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(31, 29, 70, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(100, 30, 1, 70), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(31, 30, 70, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(31, 31, 70, 70), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(31, 31, 70, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(30, 100, 70, 1), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(30, 31, 70, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(29, 31, 70, 70), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(29, 31, 70, 70))); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestIdentityTransforms); |
| |
| template<class Types> |
| class OcclusionTrackerTestQuadsMismatchLayer : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestQuadsMismatchLayer(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform layerTransform; |
| layerTransform.Translate(10, 10); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::Point(0, 0), gfx::Size(100, 100)); |
| typename Types::ContentLayerType* layer1 = this->createDrawingLayer(parent, layerTransform, gfx::PointF(0, 0), gfx::Size(90, 90), true); |
| typename Types::ContentLayerType* layer2 = this->createDrawingLayer(layer1, layerTransform, gfx::PointF(0, 0), gfx::Size(50, 50), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(layer2, occlusion); |
| this->enterLayer(layer1, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(20, 20, 50, 50).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(20, 20, 50, 50).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| // This checks cases where the quads don't match their "containing" |
| // layers, e.g. in terms of transforms or clip rect. This is typical for |
| // DelegatedRendererLayer. |
| |
| gfx::Transform quadTransform; |
| quadTransform.Translate(30, 30); |
| gfx::Rect clipRectInTarget(0, 0, 100, 100); |
| |
| EXPECT_TRUE(occlusion.unoccludedContentRect(parent, gfx::Rect(0, 0, 10, 10), quadTransform, false, clipRectInTarget).IsEmpty()); |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 10, 10), occlusion.unoccludedContentRect(parent, gfx::Rect(0, 0, 10, 10), quadTransform, true, clipRectInTarget)); |
| EXPECT_RECT_EQ(gfx::Rect(40, 40, 10, 10), occlusion.unoccludedContentRect(parent, gfx::Rect(40, 40, 10, 10), quadTransform, false, clipRectInTarget)); |
| EXPECT_RECT_EQ(gfx::Rect(40, 30, 5, 10), occlusion.unoccludedContentRect(parent, gfx::Rect(35, 30, 10, 10), quadTransform, false, clipRectInTarget)); |
| EXPECT_RECT_EQ(gfx::Rect(40, 40, 5, 5), occlusion.unoccludedContentRect(parent, gfx::Rect(40, 40, 10, 10), quadTransform, false, gfx::Rect(0, 0, 75, 75))); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestQuadsMismatchLayer); |
| |
| template<class Types> |
| class OcclusionTrackerTestRotatedChild : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestRotatedChild(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform layerTransform; |
| layerTransform.Translate(250, 250); |
| layerTransform.Rotate(90); |
| layerTransform.Translate(-250, -250); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100)); |
| typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, layerTransform, gfx::PointF(30, 30), gfx::Size(500, 500), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(30, 30, 70, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(29, 30, 70, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(30, 29, 70, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(31, 30, 70, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(30, 31, 70, 70))); |
| |
| occlusion.useDefaultLayerClipRect(); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(30, 30, 70, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(29, 30, 70, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(30, 29, 70, 70))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(31, 30, 70, 70))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(30, 31, 70, 70))); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(30, 30, 70, 70)).IsEmpty()); |
| EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 70), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(29, 30, 70, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(29, 29, 70, 70), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(29, 29, 70, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 1), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(30, 29, 70, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(31, 29, 70, 70), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(31, 29, 70, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(100, 30, 1, 70), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(31, 30, 70, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(31, 31, 70, 70), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(31, 31, 70, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(30, 100, 70, 1), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(30, 31, 70, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(29, 31, 70, 70), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(29, 31, 70, 70))); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestRotatedChild); |
| |
| template<class Types> |
| class OcclusionTrackerTestTranslatedChild : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestTranslatedChild(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform layerTransform; |
| layerTransform.Translate(20, 20); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100)); |
| typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, layerTransform, gfx::PointF(30, 30), gfx::Size(500, 500), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(50, 50, 50, 50).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(50, 50, 50, 50).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(50, 50, 50, 50))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(49, 50, 50, 50))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(50, 49, 50, 50))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(51, 50, 50, 50))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(50, 51, 50, 50))); |
| |
| occlusion.useDefaultLayerClipRect(); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(50, 50, 50, 50))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(49, 50, 50, 50))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(50, 49, 50, 50))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(51, 50, 50, 50))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(50, 51, 50, 50))); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(50, 50, 50, 50)).IsEmpty()); |
| EXPECT_RECT_EQ(gfx::Rect(49, 50, 1, 50), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(49, 50, 50, 50))); |
| EXPECT_RECT_EQ(gfx::Rect(49, 49, 50, 50), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(49, 49, 50, 50))); |
| EXPECT_RECT_EQ(gfx::Rect(50, 49, 50, 1), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(50, 49, 50, 50))); |
| EXPECT_RECT_EQ(gfx::Rect(51, 49, 50, 50), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(51, 49, 50, 50))); |
| EXPECT_RECT_EQ(gfx::Rect(100, 50, 1, 50), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(51, 50, 50, 50))); |
| EXPECT_RECT_EQ(gfx::Rect(51, 51, 50, 50), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(51, 51, 50, 50))); |
| EXPECT_RECT_EQ(gfx::Rect(50, 100, 50, 1), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(50, 51, 50, 50))); |
| EXPECT_RECT_EQ(gfx::Rect(49, 51, 50, 50), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(49, 51, 50, 50))); |
| |
| occlusion.useDefaultLayerClipRect(); |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(50, 50, 50, 50)).IsEmpty()); |
| EXPECT_RECT_EQ(gfx::Rect(49, 50, 1, 50), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(49, 50, 50, 50))); |
| EXPECT_RECT_EQ(gfx::Rect(49, 49, 50, 50), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(49, 49, 50, 50))); |
| EXPECT_RECT_EQ(gfx::Rect(50, 49, 50, 1), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(50, 49, 50, 50))); |
| EXPECT_RECT_EQ(gfx::Rect(51, 49, 49, 1), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(51, 49, 50, 50))); |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(51, 50, 50, 50)).IsEmpty()); |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(51, 51, 50, 50)).IsEmpty()); |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(50, 51, 50, 50)).IsEmpty()); |
| EXPECT_RECT_EQ(gfx::Rect(49, 51, 1, 49), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(49, 51, 50, 50))); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestTranslatedChild); |
| |
| template<class Types> |
| class OcclusionTrackerTestChildInRotatedChild : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestChildInRotatedChild(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform childTransform; |
| childTransform.Translate(250, 250); |
| childTransform.Rotate(90); |
| childTransform.Translate(-250, -250); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100)); |
| parent->setMasksToBounds(true); |
| typename Types::LayerType* child = this->createLayer(parent, childTransform, gfx::PointF(30, 30), gfx::Size(500, 500)); |
| child->setMasksToBounds(true); |
| typename Types::ContentLayerType* layer = this->createDrawingLayer(child, this->identityMatrix, gfx::PointF(10, 10), gfx::Size(500, 500), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(layer, occlusion); |
| this->enterContributingSurface(child, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| this->leaveContributingSurface(child, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(30, 40, 70, 60))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(29, 40, 70, 60))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(30, 39, 70, 60))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(31, 40, 70, 60))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(30, 41, 70, 60))); |
| |
| occlusion.useDefaultLayerClipRect(); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(30, 40, 70, 60))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(29, 40, 70, 60))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(30, 39, 70, 60))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(31, 40, 70, 60))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(30, 41, 70, 60))); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| |
| /* Justification for the above occlusion from |layer|: |
| 100 |
| +---------------------+ +---------------------+ |
| | | | |30 Visible region of |layer|: ///// |
| | 30 | rotate(90) | | |
| | 30 + ---------------------------------+ | +---------------------------------+ |
| 100 | | 10 | | ==> | | |10 | |
| | |10+---------------------------------+ | +---------------------------------+ | |
| | | | | | | | | |///////////////| 420 | | |
| | | | | | | | | |///////////////|60 | | |
| | | | | | | | | |///////////////| | | |
| +----|--|-------------+ | | +--|--|---------------+ | | |
| | | | | 20|10| 70 | | |
| | | | | | | | | |
| | | | |500 | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | |10| |
| +--|-------------------------------+ | | +------------------------------|--+ |
| | | | 490 | |
| +---------------------------------+ +---------------------------------+ |
| 500 500 |
| */ |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestChildInRotatedChild); |
| |
| template<class Types> |
| class OcclusionTrackerTestScaledRenderSurface : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestScaledRenderSurface(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(200, 200)); |
| |
| gfx::Transform layer1Matrix; |
| layer1Matrix.Scale(2, 2); |
| typename Types::ContentLayerType* layer1 = this->createDrawingLayer(parent, layer1Matrix, gfx::PointF(0, 0), gfx::Size(100, 100), true); |
| layer1->setForceRenderSurface(true); |
| |
| gfx::Transform layer2Matrix; |
| layer2Matrix.Translate(25, 25); |
| typename Types::ContentLayerType* layer2 = this->createDrawingLayer(layer1, layer2Matrix, gfx::PointF(0, 0), gfx::Size(50, 50), true); |
| typename Types::ContentLayerType* occluder = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(100, 100), gfx::Size(500, 500), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(occluder, occlusion); |
| this->enterLayer(layer2, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(100, 100, 100, 100).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect().ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 25, 25), occlusion.unoccludedLayerContentRect(layer2, gfx::Rect(0, 0, 25, 25))); |
| EXPECT_RECT_EQ(gfx::Rect(10, 25, 15, 25), occlusion.unoccludedLayerContentRect(layer2, gfx::Rect(10, 25, 25, 25))); |
| EXPECT_RECT_EQ(gfx::Rect(25, 10, 25, 15), occlusion.unoccludedLayerContentRect(layer2, gfx::Rect(25, 10, 25, 25))); |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(layer2, gfx::Rect(25, 25, 25, 25)).IsEmpty()); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestScaledRenderSurface); |
| |
| template<class Types> |
| class OcclusionTrackerTestVisitTargetTwoTimes : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestVisitTargetTwoTimes(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform childTransform; |
| childTransform.Translate(250, 250); |
| childTransform.Rotate(90); |
| childTransform.Translate(-250, -250); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100)); |
| parent->setMasksToBounds(true); |
| typename Types::LayerType* child = this->createLayer(parent, childTransform, gfx::PointF(30, 30), gfx::Size(500, 500)); |
| child->setMasksToBounds(true); |
| typename Types::ContentLayerType* layer = this->createDrawingLayer(child, this->identityMatrix, gfx::PointF(10, 10), gfx::Size(500, 500), true); |
| // |child2| makes |parent|'s surface get considered by OcclusionTracker first, instead of |child|'s. This exercises different code in |
| // leaveToTargetRenderSurface, as the target surface has already been seen. |
| typename Types::ContentLayerType* child2 = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(30, 30), gfx::Size(60, 20), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(-10, -10, 1000, 1000)); |
| |
| this->visitLayer(child2, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(30, 30, 60, 20).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(30, 30, 60, 20).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| this->visitLayer(layer, occlusion); |
| |
| EXPECT_EQ(UnionRegions(gfx::Rect(30, 30, 60, 10), gfx::Rect(30, 40, 70, 60)).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| this->enterContributingSurface(child, occlusion); |
| |
| EXPECT_EQ(UnionRegions(gfx::Rect(30, 30, 60, 10), gfx::Rect(30, 40, 70, 60)).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| // Occlusion in |child2| should get merged with the |child| surface we are leaving now. |
| this->leaveContributingSurface(child, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_EQ(UnionRegions(gfx::Rect(30, 30, 60, 10), gfx::Rect(30, 40, 70, 60)).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(UnionRegions(gfx::Rect(30, 30, 60, 10), gfx::Rect(30, 40, 70, 60)).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(30, 30, 70, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(90, 30, 10, 10), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(30, 30, 70, 70))); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(30, 30, 60, 10))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(29, 30, 60, 10))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(30, 29, 60, 10))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(31, 30, 60, 10))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(30, 31, 60, 10))); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(30, 40, 70, 60))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(29, 40, 70, 60))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(30, 39, 70, 60))); |
| |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(30, 30, 60, 10)).IsEmpty()); |
| EXPECT_RECT_EQ(gfx::Rect(29, 30, 1, 10), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(29, 30, 60, 10))); |
| EXPECT_RECT_EQ(gfx::Rect(30, 29, 60, 1), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(30, 29, 60, 10))); |
| EXPECT_RECT_EQ(gfx::Rect(90, 30, 1, 10), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(31, 30, 60, 10))); |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(30, 31, 60, 10)).IsEmpty()); |
| |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(30, 40, 70, 60)).IsEmpty()); |
| EXPECT_RECT_EQ(gfx::Rect(29, 40, 1, 60), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(29, 40, 70, 60))); |
| // This rect is mostly occluded by |child2|. |
| EXPECT_RECT_EQ(gfx::Rect(90, 39, 10, 1), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(30, 39, 70, 60))); |
| // This rect extends past top/right ends of |child2|. |
| EXPECT_RECT_EQ(gfx::Rect(30, 29, 70, 11), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(30, 29, 70, 70))); |
| // This rect extends past left/right ends of |child2|. |
| EXPECT_RECT_EQ(gfx::Rect(20, 39, 80, 60), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(20, 39, 80, 60))); |
| EXPECT_RECT_EQ(gfx::Rect(100, 40, 1, 60), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(31, 40, 70, 60))); |
| EXPECT_RECT_EQ(gfx::Rect(30, 100, 70, 1), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(30, 41, 70, 60))); |
| |
| /* Justification for the above occlusion from |layer|: |
| 100 |
| +---------------------+ +---------------------+ |
| | | | |30 Visible region of |layer|: ///// |
| | 30 | rotate(90) | 30 60 | |child2|: \\\\\ |
| | 30 + ------------+--------------------+ | 30 +------------+--------------------+ |
| 100 | | 10 | | | ==> | |\\\\\\\\\\\\| |10 | |
| | |10+----------|----------------------+ | +--|\\\\\\\\\\\\|-----------------+ | |
| | + ------------+ | | | | | +------------+//| 420 | | |
| | | | | | | | | |///////////////|60 | | |
| | | | | | | | | |///////////////| | | |
| +----|--|-------------+ | | +--|--|---------------+ | | |
| | | | | 20|10| 70 | | |
| | | | | | | | | |
| | | | |500 | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | | | |
| | | | | | | |10| |
| +--|-------------------------------+ | | +------------------------------|--+ |
| | | | 490 | |
| +---------------------------------+ +---------------------------------+ |
| 500 500 |
| */ |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestVisitTargetTwoTimes); |
| |
| template<class Types> |
| class OcclusionTrackerTestSurfaceRotatedOffAxis : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestSurfaceRotatedOffAxis(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform childTransform; |
| childTransform.Translate(250, 250); |
| childTransform.Rotate(95); |
| childTransform.Translate(-250, -250); |
| |
| gfx::Transform layerTransform; |
| layerTransform.Translate(10, 10); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100)); |
| typename Types::LayerType* child = this->createLayer(parent, childTransform, gfx::PointF(30, 30), gfx::Size(500, 500)); |
| child->setMasksToBounds(true); |
| typename Types::ContentLayerType* layer = this->createDrawingLayer(child, layerTransform, gfx::PointF(0, 0), gfx::Size(500, 500), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| gfx::Rect clippedLayerInChild = MathUtil::mapClippedRect(layerTransform, layer->visibleContentRect()); |
| |
| this->visitLayer(layer, occlusion); |
| this->enterContributingSurface(child, occlusion); |
| |
| EXPECT_EQ(gfx::Rect().ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(clippedLayerInChild.ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(child, clippedLayerInChild)); |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(child, clippedLayerInChild).IsEmpty()); |
| clippedLayerInChild += gfx::Vector2d(-1, 0); |
| EXPECT_FALSE(occlusion.occludedLayer(child, clippedLayerInChild)); |
| EXPECT_FALSE(occlusion.unoccludedLayerContentRect(child, clippedLayerInChild).IsEmpty()); |
| clippedLayerInChild += gfx::Vector2d(1, 0); |
| clippedLayerInChild += gfx::Vector2d(1, 0); |
| EXPECT_FALSE(occlusion.occludedLayer(child, clippedLayerInChild)); |
| EXPECT_FALSE(occlusion.unoccludedLayerContentRect(child, clippedLayerInChild).IsEmpty()); |
| clippedLayerInChild += gfx::Vector2d(-1, 0); |
| clippedLayerInChild += gfx::Vector2d(0, -1); |
| EXPECT_FALSE(occlusion.occludedLayer(child, clippedLayerInChild)); |
| EXPECT_FALSE(occlusion.unoccludedLayerContentRect(child, clippedLayerInChild).IsEmpty()); |
| clippedLayerInChild += gfx::Vector2d(0, 1); |
| clippedLayerInChild += gfx::Vector2d(0, 1); |
| EXPECT_FALSE(occlusion.occludedLayer(child, clippedLayerInChild)); |
| EXPECT_FALSE(occlusion.unoccludedLayerContentRect(child, clippedLayerInChild).IsEmpty()); |
| clippedLayerInChild += gfx::Vector2d(0, -1); |
| |
| this->leaveContributingSurface(child, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_EQ(gfx::Rect().ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect().ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(75, 55, 1, 1))); |
| EXPECT_RECT_EQ(gfx::Rect(75, 55, 1, 1), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(75, 55, 1, 1))); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceRotatedOffAxis); |
| |
| template<class Types> |
| class OcclusionTrackerTestSurfaceWithTwoOpaqueChildren : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestSurfaceWithTwoOpaqueChildren(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform childTransform; |
| childTransform.Translate(250, 250); |
| childTransform.Rotate(90); |
| childTransform.Translate(-250, -250); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100)); |
| parent->setMasksToBounds(true); |
| typename Types::LayerType* child = this->createLayer(parent, childTransform, gfx::PointF(30, 30), gfx::Size(500, 500)); |
| child->setMasksToBounds(true); |
| typename Types::ContentLayerType* layer1 = this->createDrawingLayer(child, this->identityMatrix, gfx::PointF(10, 10), gfx::Size(500, 500), true); |
| typename Types::ContentLayerType* layer2 = this->createDrawingLayer(child, this->identityMatrix, gfx::PointF(10, 450), gfx::Size(500, 60), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(layer2, occlusion); |
| this->visitLayer(layer1, occlusion); |
| this->enterContributingSurface(child, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(10, 430, 60, 70).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(child, gfx::Rect(10, 430, 60, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(child, gfx::Rect(9, 430, 60, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(child, gfx::Rect(10, 429, 60, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(child, gfx::Rect(11, 430, 60, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(child, gfx::Rect(10, 431, 60, 70))); |
| |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(child, gfx::Rect(10, 430, 60, 70)).IsEmpty()); |
| EXPECT_RECT_EQ(gfx::Rect(9, 430, 1, 70), occlusion.unoccludedLayerContentRect(child, gfx::Rect(9, 430, 60, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(10, 429, 60, 1), occlusion.unoccludedLayerContentRect(child, gfx::Rect(10, 429, 60, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(70, 430, 1, 70), occlusion.unoccludedLayerContentRect(child, gfx::Rect(11, 430, 60, 70))); |
| EXPECT_RECT_EQ(gfx::Rect(10, 500, 60, 1), occlusion.unoccludedLayerContentRect(child, gfx::Rect(10, 431, 60, 70))); |
| |
| this->leaveContributingSurface(child, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(30, 40, 70, 60).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(30, 40, 70, 60))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(29, 40, 70, 60))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(30, 39, 70, 60))); |
| |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(30, 40, 70, 60)).IsEmpty()); |
| EXPECT_RECT_EQ(gfx::Rect(29, 40, 1, 60), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(29, 40, 70, 60))); |
| EXPECT_RECT_EQ(gfx::Rect(30, 39, 70, 1), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(30, 39, 70, 60))); |
| EXPECT_RECT_EQ(gfx::Rect(100, 40, 1, 60), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(31, 40, 70, 60))); |
| EXPECT_RECT_EQ(gfx::Rect(30, 100, 70, 1), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(30, 41, 70, 60))); |
| |
| /* Justification for the above occlusion from |layer1| and |layer2|: |
| |
| +---------------------+ |
| | |30 Visible region of |layer1|: ///// |
| | | Visible region of |layer2|: \\\\\ |
| | +---------------------------------+ |
| | | |10 | |
| | +---------------+-----------------+ | |
| | | |\\\\\\\\\\\\|//| 420 | | |
| | | |\\\\\\\\\\\\|//|60 | | |
| | | |\\\\\\\\\\\\|//| | | |
| +--|--|------------|--+ | | |
| 20|10| 70 | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | | | |
| | | | |10| |
| | +------------|-----------------|--+ |
| | | 490 | |
| +---------------+-----------------+ |
| 60 440 |
| */ |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceWithTwoOpaqueChildren); |
| |
| template<class Types> |
| class OcclusionTrackerTestOverlappingSurfaceSiblings : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestOverlappingSurfaceSiblings(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform childTransform; |
| childTransform.Translate(250, 250); |
| childTransform.Rotate(90); |
| childTransform.Translate(-250, -250); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100)); |
| parent->setMasksToBounds(true); |
| typename Types::LayerType* child1 = this->createSurface(parent, childTransform, gfx::PointF(30, 30), gfx::Size(10, 10)); |
| typename Types::LayerType* child2 = this->createSurface(parent, childTransform, gfx::PointF(20, 40), gfx::Size(10, 10)); |
| typename Types::ContentLayerType* layer1 = this->createDrawingLayer(child1, this->identityMatrix, gfx::PointF(-10, -10), gfx::Size(510, 510), true); |
| typename Types::ContentLayerType* layer2 = this->createDrawingLayer(child2, this->identityMatrix, gfx::PointF(-10, -10), gfx::Size(510, 510), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(-20, -20, 1000, 1000)); |
| |
| this->visitLayer(layer2, occlusion); |
| this->enterContributingSurface(child2, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(20, 30, 80, 70).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(-10, 420, 70, 80).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(child2, gfx::Rect(-10, 420, 70, 80))); |
| EXPECT_FALSE(occlusion.occludedLayer(child2, gfx::Rect(-11, 420, 70, 80))); |
| EXPECT_FALSE(occlusion.occludedLayer(child2, gfx::Rect(-10, 419, 70, 80))); |
| EXPECT_FALSE(occlusion.occludedLayer(child2, gfx::Rect(-10, 420, 71, 80))); |
| EXPECT_FALSE(occlusion.occludedLayer(child2, gfx::Rect(-10, 420, 70, 81))); |
| |
| occlusion.useDefaultLayerClipRect(); |
| EXPECT_TRUE(occlusion.occludedLayer(child2, gfx::Rect(-10, 420, 70, 80))); |
| EXPECT_TRUE(occlusion.occludedLayer(child2, gfx::Rect(-11, 420, 70, 80))); |
| EXPECT_TRUE(occlusion.occludedLayer(child2, gfx::Rect(-10, 419, 70, 80))); |
| EXPECT_TRUE(occlusion.occludedLayer(child2, gfx::Rect(-10, 420, 71, 80))); |
| EXPECT_TRUE(occlusion.occludedLayer(child2, gfx::Rect(-10, 420, 70, 81))); |
| occlusion.setLayerClipRect(gfx::Rect(-20, -20, 1000, 1000)); |
| |
| // There is nothing above child2's surface in the z-order. |
| EXPECT_RECT_EQ(gfx::Rect(-10, 420, 70, 80), occlusion.unoccludedContributingSurfaceContentRect(child2, false, gfx::Rect(-10, 420, 70, 80))); |
| |
| this->leaveContributingSurface(child2, occlusion); |
| this->visitLayer(layer1, occlusion); |
| this->enterContributingSurface(child1, occlusion); |
| |
| EXPECT_EQ(UnionRegions(gfx::Rect(30, 20, 70, 10), gfx::Rect(20, 30, 80, 70)).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(-10, 430, 80, 70).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(child1, gfx::Rect(-10, 430, 80, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(child1, gfx::Rect(-11, 430, 80, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(child1, gfx::Rect(-10, 429, 80, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(child1, gfx::Rect(-10, 430, 81, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(child1, gfx::Rect(-10, 430, 80, 71))); |
| |
| // child2's contents will occlude child1 below it. |
| EXPECT_RECT_EQ(gfx::Rect(-10, 430, 10, 70), occlusion.unoccludedContributingSurfaceContentRect(child1, false, gfx::Rect(-10, 430, 80, 70))); |
| |
| this->leaveContributingSurface(child1, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_EQ(UnionRegions(gfx::Rect(30, 20, 70, 10), gfx::Rect(20, 30, 80, 70)).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(UnionRegions(gfx::Rect(30, 20, 70, 10), gfx::Rect(20, 30, 80, 70)).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(20, 20, 80, 80))); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(30, 20, 70, 80))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(29, 20, 70, 80))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(30, 19, 70, 80))); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(20, 30, 80, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(19, 30, 80, 70))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(20, 29, 80, 70))); |
| |
| /* Justification for the above occlusion: |
| 100 |
| +---------------------+ |
| | 20 | layer1 |
| | 30+ ---------------------------------+ |
| 100 | 30| | layer2 | |
| |20+----------------------------------+ | |
| | | | | | | |
| | | | | | | |
| | | | | | | |
| +--|-|----------------+ | | |
| | | | | 510 |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | +--------------------------------|-+ |
| | | |
| +----------------------------------+ |
| 510 |
| */ |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestOverlappingSurfaceSiblings); |
| |
| template<class Types> |
| class OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform child1Transform; |
| child1Transform.Translate(250, 250); |
| child1Transform.Rotate(-90); |
| child1Transform.Translate(-250, -250); |
| |
| gfx::Transform child2Transform; |
| child2Transform.Translate(250, 250); |
| child2Transform.Rotate(90); |
| child2Transform.Translate(-250, -250); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100)); |
| parent->setMasksToBounds(true); |
| typename Types::LayerType* child1 = this->createSurface(parent, child1Transform, gfx::PointF(30, 20), gfx::Size(10, 10)); |
| typename Types::LayerType* child2 = this->createDrawingSurface(parent, child2Transform, gfx::PointF(20, 40), gfx::Size(10, 10), false); |
| typename Types::ContentLayerType* layer1 = this->createDrawingLayer(child1, this->identityMatrix, gfx::PointF(-10, -20), gfx::Size(510, 510), true); |
| typename Types::ContentLayerType* layer2 = this->createDrawingLayer(child2, this->identityMatrix, gfx::PointF(-10, -10), gfx::Size(510, 510), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(-30, -30, 1000, 1000)); |
| |
| this->visitLayer(layer2, occlusion); |
| this->enterLayer(child2, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(20, 30, 80, 70).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(-10, 420, 70, 80).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(child2, gfx::Rect(-10, 420, 70, 80))); |
| EXPECT_FALSE(occlusion.occludedLayer(child2, gfx::Rect(-11, 420, 70, 80))); |
| EXPECT_FALSE(occlusion.occludedLayer(child2, gfx::Rect(-10, 419, 70, 80))); |
| EXPECT_FALSE(occlusion.occludedLayer(child2, gfx::Rect(-10, 420, 71, 80))); |
| EXPECT_FALSE(occlusion.occludedLayer(child2, gfx::Rect(-10, 420, 70, 81))); |
| |
| this->leaveLayer(child2, occlusion); |
| this->enterContributingSurface(child2, occlusion); |
| |
| // There is nothing above child2's surface in the z-order. |
| EXPECT_RECT_EQ(gfx::Rect(-10, 420, 70, 80), occlusion.unoccludedContributingSurfaceContentRect(child2, false, gfx::Rect(-10, 420, 70, 80))); |
| |
| this->leaveContributingSurface(child2, occlusion); |
| this->visitLayer(layer1, occlusion); |
| this->enterContributingSurface(child1, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(10, 20, 90, 80).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(420, -20, 80, 90).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(child1, gfx::Rect(420, -20, 80, 90))); |
| EXPECT_FALSE(occlusion.occludedLayer(child1, gfx::Rect(419, -20, 80, 90))); |
| EXPECT_FALSE(occlusion.occludedLayer(child1, gfx::Rect(420, -21, 80, 90))); |
| EXPECT_FALSE(occlusion.occludedLayer(child1, gfx::Rect(420, -19, 80, 90))); |
| EXPECT_FALSE(occlusion.occludedLayer(child1, gfx::Rect(421, -20, 80, 90))); |
| |
| // child2's contents will occlude child1 below it. |
| EXPECT_RECT_EQ(gfx::Rect(420, -20, 80, 90), occlusion.unoccludedContributingSurfaceContentRect(child1, false, gfx::Rect(420, -20, 80, 90))); |
| EXPECT_RECT_EQ(gfx::Rect(490, -10, 10, 80), occlusion.unoccludedContributingSurfaceContentRect(child1, false, gfx::Rect(420, -10, 80, 90))); |
| EXPECT_RECT_EQ(gfx::Rect(420, -20, 70, 10), occlusion.unoccludedContributingSurfaceContentRect(child1, false, gfx::Rect(420, -20, 70, 90))); |
| |
| this->leaveContributingSurface(child1, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(10, 20, 90, 80).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(10, 20, 90, 80).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(10, 20, 90, 80))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(9, 20, 90, 80))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(10, 19, 90, 80))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(11, 20, 90, 80))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(10, 21, 90, 80))); |
| |
| /* Justification for the above occlusion: |
| 100 |
| +---------------------+ |
| |20 | layer1 |
| 10+----------------------------------+ |
| 100 || 30 | layer2 | |
| |20+----------------------------------+ |
| || | | | | |
| || | | | | |
| || | | | | |
| +|-|------------------+ | | |
| | | | | 510 |
| | | 510 | | |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
| | | 520 | | |
| +----------------------------------+ | |
| | | |
| +----------------------------------+ |
| 510 |
| */ |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestOverlappingSurfaceSiblingsWithTwoTransforms); |
| |
| template<class Types> |
| class OcclusionTrackerTestFilters : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestFilters(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform layerTransform; |
| layerTransform.Translate(250, 250); |
| layerTransform.Rotate(90); |
| layerTransform.Translate(-250, -250); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100)); |
| parent->setMasksToBounds(true); |
| typename Types::ContentLayerType* blurLayer = this->createDrawingLayer(parent, layerTransform, gfx::PointF(30, 30), gfx::Size(500, 500), true); |
| typename Types::ContentLayerType* opaqueLayer = this->createDrawingLayer(parent, layerTransform, gfx::PointF(30, 30), gfx::Size(500, 500), true); |
| typename Types::ContentLayerType* opacityLayer = this->createDrawingLayer(parent, layerTransform, gfx::PointF(30, 30), gfx::Size(500, 500), true); |
| |
| WebFilterOperations filters; |
| filters.append(WebFilterOperation::createBlurFilter(10)); |
| blurLayer->setFilters(filters); |
| |
| filters.clear(); |
| filters.append(WebFilterOperation::createGrayscaleFilter(0.5)); |
| opaqueLayer->setFilters(filters); |
| |
| filters.clear(); |
| filters.append(WebFilterOperation::createOpacityFilter(0.5)); |
| opacityLayer->setFilters(filters); |
| |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| // Opacity layer won't contribute to occlusion. |
| this->visitLayer(opacityLayer, occlusion); |
| this->enterContributingSurface(opacityLayer, occlusion); |
| |
| EXPECT_TRUE(occlusion.occlusionInScreenSpace().IsEmpty()); |
| EXPECT_TRUE(occlusion.occlusionInTargetSurface().IsEmpty()); |
| |
| // And has nothing to contribute to its parent surface. |
| this->leaveContributingSurface(opacityLayer, occlusion); |
| EXPECT_TRUE(occlusion.occlusionInScreenSpace().IsEmpty()); |
| EXPECT_TRUE(occlusion.occlusionInTargetSurface().IsEmpty()); |
| |
| // Opaque layer will contribute to occlusion. |
| this->visitLayer(opaqueLayer, occlusion); |
| this->enterContributingSurface(opaqueLayer, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 430, 70, 70).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| // And it gets translated to the parent surface. |
| this->leaveContributingSurface(opaqueLayer, occlusion); |
| EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| // The blur layer needs to throw away any occlusion from outside its subtree. |
| this->enterLayer(blurLayer, occlusion); |
| EXPECT_TRUE(occlusion.occlusionInScreenSpace().IsEmpty()); |
| EXPECT_TRUE(occlusion.occlusionInTargetSurface().IsEmpty()); |
| |
| // And it won't contribute to occlusion. |
| this->leaveLayer(blurLayer, occlusion); |
| this->enterContributingSurface(blurLayer, occlusion); |
| EXPECT_TRUE(occlusion.occlusionInScreenSpace().IsEmpty()); |
| EXPECT_TRUE(occlusion.occlusionInTargetSurface().IsEmpty()); |
| |
| // But the opaque layer's occlusion is preserved on the parent. |
| this->leaveContributingSurface(blurLayer, occlusion); |
| this->enterLayer(parent, occlusion); |
| EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(30, 30, 70, 70).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestFilters); |
| |
| template<class Types> |
| class OcclusionTrackerTestReplicaDoesOcclude : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestReplicaDoesOcclude(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 200)); |
| typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 100), gfx::Size(50, 50), true); |
| this->createReplicaLayer(surface, this->identityMatrix, gfx::PointF(50, 50), gfx::Size()); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(surface, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(0, 100, 50, 50).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| this->visitContributingSurface(surface, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| // The surface and replica should both be occluding the parent. |
| EXPECT_EQ(UnionRegions(gfx::Rect(0, 100, 50, 50), gfx::Rect(50, 150, 50, 50)).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaDoesOcclude); |
| |
| template<class Types> |
| class OcclusionTrackerTestReplicaWithClipping : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestReplicaWithClipping(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 170)); |
| parent->setMasksToBounds(true); |
| typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 100), gfx::Size(50, 50), true); |
| this->createReplicaLayer(surface, this->identityMatrix, gfx::PointF(50, 50), gfx::Size()); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(surface, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(0, 100, 50, 50).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| this->visitContributingSurface(surface, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| // The surface and replica should both be occluding the parent. |
| EXPECT_EQ(UnionRegions(gfx::Rect(0, 100, 50, 50), gfx::Rect(50, 150, 50, 20)).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaWithClipping); |
| |
| template<class Types> |
| class OcclusionTrackerTestReplicaWithMask : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestReplicaWithMask(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 200)); |
| typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 100), gfx::Size(50, 50), true); |
| typename Types::LayerType* replica = this->createReplicaLayer(surface, this->identityMatrix, gfx::PointF(50, 50), gfx::Size()); |
| this->createMaskLayer(replica, gfx::Size(10, 10)); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(surface, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(0, 100, 50, 50).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| this->visitContributingSurface(surface, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| // The replica should not be occluding the parent, since it has a mask applied to it. |
| EXPECT_EQ(gfx::Rect(0, 100, 50, 50).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaWithMask); |
| |
| template<class Types> |
| class OcclusionTrackerTestLayerClipRectOutsideChild : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestLayerClipRectOutsideChild(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(200, 200), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(200, 100, 100, 100)); |
| |
| this->enterLayer(layer, occlusion); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(100, 100, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(200, 100, 100, 100))); |
| |
| occlusion.useDefaultLayerClipRect(); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(200, 100, 100, 100))); |
| occlusion.setLayerClipRect(gfx::Rect(200, 100, 100, 100)); |
| |
| this->leaveLayer(layer, occlusion); |
| this->visitContributingSurface(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(200, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(200, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 200, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 200, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(200, 200, 100, 100))); |
| |
| EXPECT_RECT_EQ(gfx::Rect(200, 100, 100, 100), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 0, 300, 300))); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestLayerClipRectOutsideChild); |
| |
| template<class Types> |
| class OcclusionTrackerTestViewportRectOutsideChild : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestViewportRectOutsideChild(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(200, 200), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(200, 100, 100, 100)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->enterLayer(layer, occlusion); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(100, 100, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(200, 100, 100, 100))); |
| |
| occlusion.useDefaultLayerClipRect(); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(200, 100, 100, 100))); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->leaveLayer(layer, occlusion); |
| this->visitContributingSurface(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(200, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(200, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 200, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 200, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(200, 200, 100, 100))); |
| |
| EXPECT_RECT_EQ(gfx::Rect(200, 100, 100, 100), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 0, 300, 300))); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestViewportRectOutsideChild); |
| |
| template<class Types> |
| class OcclusionTrackerTestLayerClipRectOverChild : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestLayerClipRectOverChild(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(200, 200), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(100, 100, 100, 100)); |
| |
| this->enterLayer(layer, occlusion); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(100, 100, 100, 100))); |
| |
| this->leaveLayer(layer, occlusion); |
| this->visitContributingSurface(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(200, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(200, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 200, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 200, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(200, 200, 100, 100))); |
| |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 0, 300, 300)).IsEmpty()); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestLayerClipRectOverChild); |
| |
| template<class Types> |
| class OcclusionTrackerTestViewportRectOverChild : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestViewportRectOverChild(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(200, 200), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(100, 100, 100, 100)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->enterLayer(layer, occlusion); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(100, 100, 100, 100))); |
| |
| this->leaveLayer(layer, occlusion); |
| this->visitContributingSurface(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(200, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(200, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 200, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 200, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(200, 200, 100, 100))); |
| |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 0, 300, 300)).IsEmpty()); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestViewportRectOverChild); |
| |
| template<class Types> |
| class OcclusionTrackerTestLayerClipRectPartlyOverChild : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestLayerClipRectPartlyOverChild(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(200, 200), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(50, 50, 200, 200)); |
| |
| this->enterLayer(layer, occlusion); |
| |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(100, 100, 100, 100))); |
| |
| this->leaveLayer(layer, occlusion); |
| this->visitContributingSurface(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 100, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(200, 100, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(200, 0, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(0, 200, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(100, 200, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(200, 200, 100, 100))); |
| |
| EXPECT_RECT_EQ(gfx::Rect(50, 50, 200, 200), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 0, 300, 300))); |
| EXPECT_RECT_EQ(gfx::Rect(200, 50, 50, 50), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 0, 300, 100))); |
| EXPECT_RECT_EQ(gfx::Rect(200, 100, 50, 100), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 100, 300, 100))); |
| EXPECT_RECT_EQ(gfx::Rect(200, 100, 50, 100), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(200, 100, 100, 100))); |
| EXPECT_RECT_EQ(gfx::Rect(100, 200, 100, 50), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(100, 200, 100, 100))); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestLayerClipRectPartlyOverChild); |
| |
| template<class Types> |
| class OcclusionTrackerTestViewportRectPartlyOverChild : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestViewportRectPartlyOverChild(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(200, 200), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(50, 50, 200, 200)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->enterLayer(layer, occlusion); |
| |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(100, 100, 100, 100))); |
| |
| this->leaveLayer(layer, occlusion); |
| this->visitContributingSurface(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 100, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(200, 100, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(200, 0, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(0, 200, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(100, 200, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(200, 200, 100, 100))); |
| |
| EXPECT_RECT_EQ(gfx::Rect(50, 50, 200, 200), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 0, 300, 300))); |
| EXPECT_RECT_EQ(gfx::Rect(200, 50, 50, 50), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 0, 300, 100))); |
| EXPECT_RECT_EQ(gfx::Rect(200, 100, 50, 100), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 100, 300, 100))); |
| EXPECT_RECT_EQ(gfx::Rect(200, 100, 50, 100), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(200, 100, 100, 100))); |
| EXPECT_RECT_EQ(gfx::Rect(100, 200, 100, 50), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(100, 200, 100, 100))); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestViewportRectPartlyOverChild); |
| |
| template<class Types> |
| class OcclusionTrackerTestLayerClipRectOverNothing : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestLayerClipRectOverNothing(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(200, 200), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(500, 500, 100, 100)); |
| |
| this->enterLayer(layer, occlusion); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(100, 100, 100, 100))); |
| |
| this->leaveLayer(layer, occlusion); |
| this->visitContributingSurface(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(200, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(200, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 200, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 200, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(200, 200, 100, 100))); |
| |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 0, 300, 300)).IsEmpty()); |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 0, 300, 100)).IsEmpty()); |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 100, 300, 100)).IsEmpty()); |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(200, 100, 100, 100)).IsEmpty()); |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(100, 200, 100, 100)).IsEmpty()); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestLayerClipRectOverNothing); |
| |
| template<class Types> |
| class OcclusionTrackerTestViewportRectOverNothing : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestViewportRectOverNothing(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(200, 200), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(500, 500, 100, 100)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->enterLayer(layer, occlusion); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(100, 100, 100, 100))); |
| |
| this->leaveLayer(layer, occlusion); |
| this->visitContributingSurface(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(200, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(200, 0, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(0, 200, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 200, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(200, 200, 100, 100))); |
| |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 0, 300, 300)).IsEmpty()); |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 0, 300, 100)).IsEmpty()); |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 100, 300, 100)).IsEmpty()); |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(200, 100, 100, 100)).IsEmpty()); |
| EXPECT_TRUE(occlusion.unoccludedLayerContentRect(parent, gfx::Rect(100, 200, 100, 100)).IsEmpty()); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestViewportRectOverNothing); |
| |
| template<class Types> |
| class OcclusionTrackerTestLayerClipRectForLayerOffOrigin : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestLayerClipRectForLayerOffOrigin(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(200, 200), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| this->enterLayer(layer, occlusion); |
| |
| // This layer is translated when drawn into its target. So if the clip rect given from the target surface |
| // is not in that target space, then after translating these query rects into the target, they will fall outside |
| // the clip and be considered occluded. |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(100, 100, 100, 100))); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestLayerClipRectForLayerOffOrigin); |
| |
| template<class Types> |
| class OcclusionTrackerTestOpaqueContentsRegionEmpty : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestOpaqueContentsRegionEmpty(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::ContentLayerType* layer = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(200, 200), false); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| this->enterLayer(layer, occlusion); |
| |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(100, 0, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(100, 100, 100, 100))); |
| |
| // Occluded since its outside the surface bounds. |
| EXPECT_TRUE(occlusion.occludedLayer(layer, gfx::Rect(200, 100, 100, 100))); |
| |
| // Test without any clip rect. |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| EXPECT_FALSE(occlusion.occludedLayer(layer, gfx::Rect(200, 100, 100, 100))); |
| occlusion.useDefaultLayerClipRect(); |
| |
| this->leaveLayer(layer, occlusion); |
| this->visitContributingSurface(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_TRUE(occlusion.occlusionInScreenSpace().IsEmpty()); |
| } |
| }; |
| |
| MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTestOpaqueContentsRegionEmpty); |
| |
| template<class Types> |
| class OcclusionTrackerTestOpaqueContentsRegionNonEmpty : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestOpaqueContentsRegionNonEmpty(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(100, 100), gfx::Size(200, 200), false); |
| this->calcDrawEtc(parent); |
| |
| { |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| layer->setOpaqueContentsRect(gfx::Rect(0, 0, 100, 100)); |
| |
| this->resetLayerIterator(); |
| this->visitLayer(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(100, 100, 100, 100).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(100, 100, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(200, 200, 100, 100))); |
| } |
| |
| { |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| layer->setOpaqueContentsRect(gfx::Rect(20, 20, 180, 180)); |
| |
| this->resetLayerIterator(); |
| this->visitLayer(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(120, 120, 180, 180).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(100, 100, 100, 100))); |
| EXPECT_TRUE(occlusion.occludedLayer(parent, gfx::Rect(200, 200, 100, 100))); |
| } |
| |
| { |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| layer->setOpaqueContentsRect(gfx::Rect(150, 150, 100, 100)); |
| |
| this->resetLayerIterator(); |
| this->visitLayer(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(250, 250, 50, 50).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(0, 100, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(100, 100, 100, 100))); |
| EXPECT_FALSE(occlusion.occludedLayer(parent, gfx::Rect(200, 200, 100, 100))); |
| } |
| } |
| }; |
| |
| MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTestOpaqueContentsRegionNonEmpty); |
| |
| template<class Types> |
| class OcclusionTrackerTest3dTransform : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTest3dTransform(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform transform; |
| MathUtil::rotateEulerAngles(&transform, 0, 30, 0); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::LayerType* container = this->createLayer(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::ContentLayerType* layer = this->createDrawingLayer(container, transform, gfx::PointF(100, 100), gfx::Size(200, 200), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| this->enterLayer(layer, occlusion); |
| |
| // The layer is rotated in 3d but without preserving 3d, so it only gets resized. |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 200, 200), occlusion.unoccludedLayerContentRect(layer, gfx::Rect(0, 0, 200, 200))); |
| } |
| }; |
| |
| MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTest3dTransform); |
| |
| template<class Types> |
| class OcclusionTrackerTestUnsorted3dLayers : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestUnsorted3dLayers(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| // Currently, the main thread layer iterator does not iterate over 3d items in |
| // sorted order, because layer sorting is not performed on the main thread. |
| // Because of this, the occlusion tracker cannot assume that a 3d layer occludes |
| // other layers that have not yet been iterated over. For now, the expected |
| // behavior is that a 3d layer simply does not add any occlusion to the occlusion |
| // tracker. |
| |
| gfx::Transform translationToFront; |
| translationToFront.Translate3d(0, 0, -10); |
| gfx::Transform translationToBack; |
| translationToFront.Translate3d(0, 0, -100); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::ContentLayerType* child1 = this->createDrawingLayer(parent, translationToBack, gfx::PointF(0, 0), gfx::Size(100, 100), true); |
| typename Types::ContentLayerType* child2 = this->createDrawingLayer(parent, translationToFront, gfx::PointF(50, 50), gfx::Size(100, 100), true); |
| parent->setPreserves3D(true); |
| |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| this->visitLayer(child2, occlusion); |
| EXPECT_TRUE(occlusion.occlusionInScreenSpace().IsEmpty()); |
| EXPECT_TRUE(occlusion.occlusionInTargetSurface().IsEmpty()); |
| |
| this->visitLayer(child1, occlusion); |
| EXPECT_TRUE(occlusion.occlusionInScreenSpace().IsEmpty()); |
| EXPECT_TRUE(occlusion.occlusionInTargetSurface().IsEmpty()); |
| } |
| }; |
| |
| // This test will have different layer ordering on the impl thread; the test will only work on the main thread. |
| MAIN_THREAD_TEST(OcclusionTrackerTestUnsorted3dLayers); |
| |
| template<class Types> |
| class OcclusionTrackerTestPerspectiveTransform : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestPerspectiveTransform(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform transform; |
| transform.Translate(150, 150); |
| transform.ApplyPerspectiveDepth(400); |
| transform.RotateAboutXAxis(-30); |
| transform.Translate(-150, -150); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::LayerType* container = this->createLayer(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::ContentLayerType* layer = this->createDrawingLayer(container, transform, gfx::PointF(100, 100), gfx::Size(200, 200), true); |
| container->setPreserves3D(true); |
| layer->setPreserves3D(true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| this->enterLayer(layer, occlusion); |
| |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 200, 200), occlusion.unoccludedLayerContentRect(layer, gfx::Rect(0, 0, 200, 200))); |
| } |
| }; |
| |
| // This test requires accumulating occlusion of 3d layers, which are skipped by the occlusion tracker on the main thread. So this test should run on the impl thread. |
| IMPL_THREAD_TEST(OcclusionTrackerTestPerspectiveTransform); |
| |
| template<class Types> |
| class OcclusionTrackerTestPerspectiveTransformBehindCamera : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestPerspectiveTransformBehindCamera(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| // This test is based on the platform/chromium/compositing/3d-corners.html layout test. |
| gfx::Transform transform; |
| transform.Translate(250, 50); |
| transform.ApplyPerspectiveDepth(10); |
| transform.Translate(-250, -50); |
| transform.Translate(250, 50); |
| transform.RotateAboutXAxis(-167); |
| transform.Translate(-250, -50); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(500, 100)); |
| typename Types::LayerType* container = this->createLayer(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(500, 500)); |
| typename Types::ContentLayerType* layer = this->createDrawingLayer(container, transform, gfx::PointF(0, 0), gfx::Size(500, 500), true); |
| container->setPreserves3D(true); |
| layer->setPreserves3D(true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| this->enterLayer(layer, occlusion); |
| |
| // 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.unoccludedLayerContentRect(layer, gfx::Rect(0, 0, 500, 500)).Contains(gfx::Rect(0, 489, 500, 11))); |
| } |
| }; |
| |
| // This test requires accumulating occlusion of 3d layers, which are skipped by the occlusion tracker on the main thread. So this test should run on the impl thread. |
| IMPL_THREAD_TEST(OcclusionTrackerTestPerspectiveTransformBehindCamera); |
| |
| template<class Types> |
| class OcclusionTrackerTestLayerBehindCameraDoesNotOcclude : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestLayerBehindCameraDoesNotOcclude(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform transform; |
| transform.Translate(50, 50); |
| transform.ApplyPerspectiveDepth(100); |
| transform.Translate3d(0, 0, 110); |
| transform.Translate(-50, -50); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100)); |
| typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, transform, gfx::PointF(0, 0), gfx::Size(100, 100), true); |
| parent->setPreserves3D(true); |
| layer->setPreserves3D(true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| |
| // The |layer| is entirely behind the camera and should not occlude. |
| this->visitLayer(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| EXPECT_TRUE(occlusion.occlusionInTargetSurface().IsEmpty()); |
| EXPECT_TRUE(occlusion.occlusionInScreenSpace().IsEmpty()); |
| } |
| }; |
| |
| // This test requires accumulating occlusion of 3d layers, which are skipped by the occlusion tracker on the main thread. So this test should run on the impl thread. |
| IMPL_THREAD_TEST(OcclusionTrackerTestLayerBehindCameraDoesNotOcclude); |
| |
| template<class Types> |
| class OcclusionTrackerTestLargePixelsOccludeInsideClipRect : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestLargePixelsOccludeInsideClipRect(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform transform; |
| transform.Translate(50, 50); |
| transform.ApplyPerspectiveDepth(100); |
| transform.Translate3d(0, 0, 99); |
| transform.Translate(-50, -50); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100)); |
| parent->setMasksToBounds(true); |
| typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, transform, gfx::PointF(0, 0), gfx::Size(100, 100), true); |
| parent->setPreserves3D(true); |
| layer->setPreserves3D(true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| |
| // This is very close to the camera, so pixels in its visibleContentRect will actually go outside of the layer's clipRect. |
| // Ensure that those pixels don't occlude things outside the clipRect. |
| this->visitLayer(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| } |
| }; |
| |
| // This test requires accumulating occlusion of 3d layers, which are skipped by the occlusion tracker on the main thread. So this test should run on the impl thread. |
| IMPL_THREAD_TEST(OcclusionTrackerTestLargePixelsOccludeInsideClipRect); |
| |
| template<class Types> |
| class OcclusionTrackerTestAnimationOpacity1OnMainThread : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestAnimationOpacity1OnMainThread(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300), true); |
| typename Types::ContentLayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300), true); |
| typename Types::ContentLayerType* surfaceChild = this->createDrawingLayer(surface, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(200, 300), true); |
| typename Types::ContentLayerType* surfaceChild2 = this->createDrawingLayer(surface, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 300), true); |
| typename Types::ContentLayerType* parent2 = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300), false); |
| typename Types::ContentLayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(250, 0), gfx::Size(50, 300), true); |
| |
| addOpacityTransitionToController(*layer->layerAnimationController(), 10, 0, 1, false); |
| addOpacityTransitionToController(*surface->layerAnimationController(), 10, 0, 1, false); |
| this->calcDrawEtc(parent); |
| |
| EXPECT_TRUE(layer->drawOpacityIsAnimating()); |
| EXPECT_FALSE(surface->drawOpacityIsAnimating()); |
| EXPECT_TRUE(surface->renderSurface()->drawOpacityIsAnimating()); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(topmost, occlusion); |
| this->enterLayer(parent2, occlusion); |
| // This occlusion will affect all surfaces. |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300), occlusion.unoccludedLayerContentRect(parent2, gfx::Rect(0, 0, 300, 300))); |
| this->leaveLayer(parent2, occlusion); |
| |
| this->visitLayer(surfaceChild2, occlusion); |
| this->enterLayer(surfaceChild, occlusion); |
| EXPECT_RECT_EQ(gfx::Rect(100, 0, 100, 300), occlusion.unoccludedLayerContentRect(surfaceChild, gfx::Rect(0, 0, 300, 300))); |
| this->leaveLayer(surfaceChild, occlusion); |
| this->enterLayer(surface, occlusion); |
| EXPECT_RECT_EQ(gfx::Rect(200, 0, 50, 300), occlusion.unoccludedLayerContentRect(surface, gfx::Rect(0, 0, 300, 300))); |
| this->leaveLayer(surface, occlusion); |
| |
| this->enterContributingSurface(surface, occlusion); |
| // Occlusion within the surface is lost when leaving the animating surface. |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300), occlusion.unoccludedContributingSurfaceContentRect(surface, false, gfx::Rect(0, 0, 300, 300))); |
| this->leaveContributingSurface(surface, occlusion); |
| |
| this->visitLayer(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| // Occlusion is not added for the animating |layer|. |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 0, 300, 300))); |
| } |
| }; |
| |
| MAIN_THREAD_TEST(OcclusionTrackerTestAnimationOpacity1OnMainThread); |
| |
| template<class Types> |
| class OcclusionTrackerTestAnimationOpacity0OnMainThread : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestAnimationOpacity0OnMainThread(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300), true); |
| typename Types::ContentLayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300), true); |
| typename Types::ContentLayerType* surfaceChild = this->createDrawingLayer(surface, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(200, 300), true); |
| typename Types::ContentLayerType* surfaceChild2 = this->createDrawingLayer(surface, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 300), true); |
| typename Types::ContentLayerType* parent2 = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300), false); |
| typename Types::ContentLayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(250, 0), gfx::Size(50, 300), true); |
| |
| addOpacityTransitionToController(*layer->layerAnimationController(), 10, 1, 0, false); |
| addOpacityTransitionToController(*surface->layerAnimationController(), 10, 1, 0, false); |
| this->calcDrawEtc(parent); |
| |
| EXPECT_TRUE(layer->drawOpacityIsAnimating()); |
| EXPECT_FALSE(surface->drawOpacityIsAnimating()); |
| EXPECT_TRUE(surface->renderSurface()->drawOpacityIsAnimating()); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(topmost, occlusion); |
| this->enterLayer(parent2, occlusion); |
| // This occlusion will affect all surfaces. |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 0, 300, 300))); |
| this->leaveLayer(parent2, occlusion); |
| |
| this->visitLayer(surfaceChild2, occlusion); |
| this->enterLayer(surfaceChild, occlusion); |
| EXPECT_RECT_EQ(gfx::Rect(100, 0, 100, 300), occlusion.unoccludedLayerContentRect(surfaceChild, gfx::Rect(0, 0, 300, 300))); |
| this->leaveLayer(surfaceChild, occlusion); |
| this->enterLayer(surface, occlusion); |
| EXPECT_RECT_EQ(gfx::Rect(200, 0, 50, 300), occlusion.unoccludedLayerContentRect(surface, gfx::Rect(0, 0, 300, 300))); |
| this->leaveLayer(surface, occlusion); |
| |
| this->enterContributingSurface(surface, occlusion); |
| // Occlusion within the surface is lost when leaving the animating surface. |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300), occlusion.unoccludedContributingSurfaceContentRect(surface, false, gfx::Rect(0, 0, 300, 300))); |
| this->leaveContributingSurface(surface, occlusion); |
| |
| this->visitLayer(layer, occlusion); |
| this->enterLayer(parent, occlusion); |
| |
| // Occlusion is not added for the animating |layer|. |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 250, 300), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 0, 300, 300))); |
| } |
| }; |
| |
| MAIN_THREAD_TEST(OcclusionTrackerTestAnimationOpacity0OnMainThread); |
| |
| template<class Types> |
| class OcclusionTrackerTestAnimationTranslateOnMainThread : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestAnimationTranslateOnMainThread(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| typename Types::ContentLayerType* layer = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300), true); |
| typename Types::ContentLayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300), true); |
| typename Types::ContentLayerType* surfaceChild = this->createDrawingLayer(surface, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(200, 300), true); |
| typename Types::ContentLayerType* surfaceChild2 = this->createDrawingLayer(surface, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 300), true); |
| typename Types::ContentLayerType* surface2 = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(50, 300), true); |
| |
| addAnimatedTransformToController(*layer->layerAnimationController(), 10, 30, 0); |
| addAnimatedTransformToController(*surface->layerAnimationController(), 10, 30, 0); |
| addAnimatedTransformToController(*surfaceChild->layerAnimationController(), 10, 30, 0); |
| this->calcDrawEtc(parent); |
| |
| EXPECT_TRUE(layer->drawTransformIsAnimating()); |
| EXPECT_TRUE(layer->screenSpaceTransformIsAnimating()); |
| EXPECT_TRUE(surface->renderSurface()->targetSurfaceTransformsAreAnimating()); |
| EXPECT_TRUE(surface->renderSurface()->screenSpaceTransformsAreAnimating()); |
| // The surface owning layer doesn't animate against its own surface. |
| EXPECT_FALSE(surface->drawTransformIsAnimating()); |
| EXPECT_TRUE(surface->screenSpaceTransformIsAnimating()); |
| EXPECT_TRUE(surfaceChild->drawTransformIsAnimating()); |
| EXPECT_TRUE(surfaceChild->screenSpaceTransformIsAnimating()); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(surface2, occlusion); |
| this->enterContributingSurface(surface2, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| |
| this->leaveContributingSurface(surface2, occlusion); |
| this->enterLayer(surfaceChild2, occlusion); |
| |
| // surfaceChild2 is moving in screen space but not relative to its target, so occlusion should happen in its target space only. |
| // It also means that things occluding in screen space (e.g. surface2) cannot occlude this layer. |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 300), occlusion.unoccludedLayerContentRect(surfaceChild2, gfx::Rect(0, 0, 100, 300))); |
| EXPECT_FALSE(occlusion.occludedLayer(surfaceChild, gfx::Rect(0, 0, 50, 300))); |
| |
| this->leaveLayer(surfaceChild2, occlusion); |
| this->enterLayer(surfaceChild, occlusion); |
| EXPECT_FALSE(occlusion.occludedLayer(surfaceChild, gfx::Rect(0, 0, 100, 300))); |
| EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| EXPECT_RECT_EQ(gfx::Rect(100, 0, 200, 300), occlusion.unoccludedLayerContentRect(surface, gfx::Rect(0, 0, 300, 300))); |
| |
| // The surfaceChild is occluded by the surfaceChild2, but is moving relative its target and the screen, so it |
| // can't be occluded. |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 200, 300), occlusion.unoccludedLayerContentRect(surfaceChild, gfx::Rect(0, 0, 200, 300))); |
| EXPECT_FALSE(occlusion.occludedLayer(surfaceChild, gfx::Rect(0, 0, 50, 300))); |
| |
| this->leaveLayer(surfaceChild, occlusion); |
| this->enterLayer(surface, occlusion); |
| // The surfaceChild is moving in screen space but not relative to its target, so occlusion should happen in its target space only. |
| EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 100, 300).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| EXPECT_RECT_EQ(gfx::Rect(100, 0, 200, 300), occlusion.unoccludedLayerContentRect(surface, gfx::Rect(0, 0, 300, 300))); |
| |
| this->leaveLayer(surface, occlusion); |
| // The surface's owning layer is moving in screen space but not relative to its target, so occlusion should happen in its target space only. |
| EXPECT_EQ(gfx::Rect(0, 0, 50, 300).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 300, 300).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 0, 0), occlusion.unoccludedLayerContentRect(surface, gfx::Rect(0, 0, 300, 300))); |
| |
| this->enterContributingSurface(surface, occlusion); |
| // The contributing |surface| is animating so it can't be occluded. |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 300, 300), occlusion.unoccludedContributingSurfaceContentRect(surface, false, gfx::Rect(0, 0, 300, 300))); |
| this->leaveContributingSurface(surface, occlusion); |
| |
| this->enterLayer(layer, occlusion); |
| // The |surface| is moving in the screen and in its target, so all occlusion within the surface is lost when leaving it. |
| EXPECT_RECT_EQ(gfx::Rect(50, 0, 250, 300), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 0, 300, 300))); |
| this->leaveLayer(layer, occlusion); |
| |
| this->enterLayer(parent, occlusion); |
| // The |layer| is animating in the screen and in its target, so no occlusion is added. |
| EXPECT_RECT_EQ(gfx::Rect(50, 0, 250, 300), occlusion.unoccludedLayerContentRect(parent, gfx::Rect(0, 0, 300, 300))); |
| } |
| }; |
| |
| MAIN_THREAD_TEST(OcclusionTrackerTestAnimationTranslateOnMainThread); |
| |
| template<class Types> |
| class OcclusionTrackerTestSurfaceOcclusionTranslatesToParent : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestSurfaceOcclusionTranslatesToParent(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform surfaceTransform; |
| surfaceTransform.Translate(300, 300); |
| surfaceTransform.Scale(2, 2); |
| surfaceTransform.Translate(-150, -150); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(500, 500)); |
| typename Types::ContentLayerType* surface = this->createDrawingSurface(parent, surfaceTransform, gfx::PointF(0, 0), gfx::Size(300, 300), false); |
| typename Types::ContentLayerType* surface2 = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(50, 50), gfx::Size(300, 300), false); |
| surface->setOpaqueContentsRect(gfx::Rect(0, 0, 200, 200)); |
| surface2->setOpaqueContentsRect(gfx::Rect(0, 0, 200, 200)); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(surface2, occlusion); |
| this->visitContributingSurface(surface2, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(50, 50, 200, 200).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(50, 50, 200, 200).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| // Clear any stored occlusion. |
| occlusion.setOcclusionInScreenSpace(Region()); |
| occlusion.setOcclusionInTargetSurface(Region()); |
| |
| this->visitLayer(surface, occlusion); |
| this->visitContributingSurface(surface, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(0, 0, 400, 400).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 400, 400).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| } |
| }; |
| |
| MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTestSurfaceOcclusionTranslatesToParent); |
| |
| template<class Types> |
| class OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 300)); |
| parent->setMasksToBounds(true); |
| typename Types::ContentLayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(500, 300), false); |
| surface->setOpaqueContentsRect(gfx::Rect(0, 0, 400, 200)); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(surface, occlusion); |
| this->visitContributingSurface(surface, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(0, 0, 300, 200).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 300, 200).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| } |
| }; |
| |
| MAIN_AND_IMPL_THREAD_TEST(OcclusionTrackerTestSurfaceOcclusionTranslatesWithClipping); |
| |
| template<class Types> |
| class OcclusionTrackerTestReplicaOccluded : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestReplicaOccluded(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 200)); |
| typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100), true); |
| this->createReplicaLayer(surface, this->identityMatrix, gfx::PointF(0, 100), gfx::Size(100, 100)); |
| typename Types::LayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 100), gfx::Size(100, 100), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| // |topmost| occludes the replica, but not the surface itself. |
| this->visitLayer(topmost, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(0, 100, 100, 100).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 100, 100, 100).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| this->visitLayer(surface, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(0, 0, 100, 200).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| this->enterContributingSurface(surface, occlusion); |
| |
| // Surface is not occluded so it shouldn't think it is. |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100), occlusion.unoccludedContributingSurfaceContentRect(surface, false, gfx::Rect(0, 0, 100, 100))); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReplicaOccluded); |
| |
| template<class Types> |
| class OcclusionTrackerTestSurfaceWithReplicaUnoccluded : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestSurfaceWithReplicaUnoccluded(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 200)); |
| typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100), true); |
| this->createReplicaLayer(surface, this->identityMatrix, gfx::PointF(0, 100), gfx::Size(100, 100)); |
| typename Types::LayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 110), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| // |topmost| occludes the surface, but not the entire surface's replica. |
| this->visitLayer(topmost, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(0, 0, 100, 110).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 100, 110).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| this->visitLayer(surface, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(0, 0, 100, 110).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| this->enterContributingSurface(surface, occlusion); |
| |
| // Surface is occluded, but only the top 10px of the replica. |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 0, 0), occlusion.unoccludedContributingSurfaceContentRect(surface, false, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_RECT_EQ(gfx::Rect(0, 10, 100, 90), occlusion.unoccludedContributingSurfaceContentRect(surface, true, gfx::Rect(0, 0, 100, 100))); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceWithReplicaUnoccluded); |
| |
| template<class Types> |
| class OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 200)); |
| typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100), true); |
| this->createReplicaLayer(surface, this->identityMatrix, gfx::PointF(0, 100), gfx::Size(100, 100)); |
| typename Types::LayerType* overSurface = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(40, 100), true); |
| typename Types::LayerType* overReplica = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 100), gfx::Size(50, 100), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| // These occlude the surface and replica differently, so we can test each one. |
| this->visitLayer(overReplica, occlusion); |
| this->visitLayer(overSurface, occlusion); |
| |
| EXPECT_EQ(UnionRegions(gfx::Rect(0, 0, 40, 100), gfx::Rect(0, 100, 50, 100)).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(UnionRegions(gfx::Rect(0, 0, 40, 100), gfx::Rect(0, 100, 50, 100)).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| this->visitLayer(surface, occlusion); |
| |
| EXPECT_EQ(UnionRegions(gfx::Rect(0, 0, 100, 100), gfx::Rect(0, 100, 50, 100)).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| this->enterContributingSurface(surface, occlusion); |
| |
| // Surface and replica are occluded different amounts. |
| EXPECT_RECT_EQ(gfx::Rect(40, 0, 60, 100), occlusion.unoccludedContributingSurfaceContentRect(surface, false, gfx::Rect(0, 0, 100, 100))); |
| EXPECT_RECT_EQ(gfx::Rect(50, 0, 50, 100), occlusion.unoccludedContributingSurfaceContentRect(surface, true, gfx::Rect(0, 0, 100, 100))); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceAndReplicaOccludedDifferently); |
| |
| template<class Types> |
| class OcclusionTrackerTestSurfaceChildOfSurface : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestSurfaceChildOfSurface(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| // This test verifies that the surface cliprect does not end up empty and clip away the entire unoccluded rect. |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 200)); |
| typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100), true); |
| typename Types::LayerType* surfaceChild = this->createDrawingSurface(surface, this->identityMatrix, gfx::PointF(0, 10), gfx::Size(100, 50), true); |
| typename Types::LayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 50), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(-100, -100, 1000, 1000)); |
| |
| // |topmost| occludes everything partially so we know occlusion is happening at all. |
| this->visitLayer(topmost, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| this->visitLayer(surfaceChild, occlusion); |
| |
| // surfaceChild increases the occlusion in the screen by a narrow sliver. |
| EXPECT_EQ(gfx::Rect(0, 0, 100, 60).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| // In its own surface, surfaceChild is at 0,0 as is its occlusion. |
| EXPECT_EQ(gfx::Rect(0, 0, 100, 50).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| // The root layer always has a clipRect. So the parent of |surface| has a clipRect. However, the owning layer for |surface| does not |
| // mask to bounds, so it doesn't have a clipRect of its own. Thus the parent of |surfaceChild| exercises different code paths |
| // as its parent does not have a clipRect. |
| |
| this->enterContributingSurface(surfaceChild, occlusion); |
| // The surfaceChild's parent does not have a clipRect as it owns a render surface. Make sure the unoccluded rect |
| // does not get clipped away inappropriately. |
| EXPECT_RECT_EQ(gfx::Rect(0, 40, 100, 10), occlusion.unoccludedContributingSurfaceContentRect(surfaceChild, false, gfx::Rect(0, 0, 100, 50))); |
| this->leaveContributingSurface(surfaceChild, occlusion); |
| |
| // When the surfaceChild's occlusion is transformed up to its parent, make sure it is not clipped away inappropriately also. |
| this->enterLayer(surface, occlusion); |
| EXPECT_EQ(gfx::Rect(0, 0, 100, 60).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 10, 100, 50).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| this->leaveLayer(surface, occlusion); |
| |
| this->enterContributingSurface(surface, occlusion); |
| // The surface's parent does have a clipRect as it is the root layer. |
| EXPECT_RECT_EQ(gfx::Rect(0, 50, 100, 50), occlusion.unoccludedContributingSurfaceContentRect(surface, false, gfx::Rect(0, 0, 100, 100))); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceChildOfSurface); |
| |
| template<class Types> |
| class OcclusionTrackerTestTopmostSurfaceIsClippedToViewport : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestTopmostSurfaceIsClippedToViewport(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| // This test verifies that the top-most surface is considered occluded outside of its target's clipRect and outside the viewport rect. |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 200)); |
| typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 300), true); |
| this->calcDrawEtc(parent); |
| |
| { |
| // Make a viewport rect that is larger than the root layer. |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(surface, occlusion); |
| |
| // The root layer always has a clipRect. So the parent of |surface| has a clipRect giving the surface itself a clipRect. |
| this->enterContributingSurface(surface, occlusion); |
| // Make sure the parent's clipRect clips the unoccluded region of the child surface. |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 200), occlusion.unoccludedContributingSurfaceContentRect(surface, false, gfx::Rect(0, 0, 100, 300))); |
| } |
| this->resetLayerIterator(); |
| { |
| // Make a viewport rect that is smaller than the root layer. |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 100, 100)); |
| |
| this->visitLayer(surface, occlusion); |
| |
| // The root layer always has a clipRect. So the parent of |surface| has a clipRect giving the surface itself a clipRect. |
| this->enterContributingSurface(surface, occlusion); |
| // Make sure the viewport rect clips the unoccluded region of the child surface. |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 100), occlusion.unoccludedContributingSurfaceContentRect(surface, false, gfx::Rect(0, 0, 100, 300))); |
| } |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestTopmostSurfaceIsClippedToViewport); |
| |
| template<class Types> |
| class OcclusionTrackerTestSurfaceChildOfClippingSurface : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestSurfaceChildOfClippingSurface(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| // This test verifies that the surface cliprect does not end up empty and clip away the entire unoccluded rect. |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(80, 200)); |
| parent->setMasksToBounds(true); |
| typename Types::LayerType* surface = this->createDrawingSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100), true); |
| typename Types::LayerType* surfaceChild = this->createDrawingSurface(surface, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 100), false); |
| typename Types::LayerType* topmost = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(100, 50), true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| // |topmost| occludes everything partially so we know occlusion is happening at all. |
| this->visitLayer(topmost, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(0, 0, 80, 50).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 80, 50).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| // surfaceChild is not opaque and does not occlude, so we have a non-empty unoccluded area on surface. |
| this->visitLayer(surfaceChild, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(0, 0, 80, 50).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(0, 0, 0, 0).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| // The root layer always has a clipRect. So the parent of |surface| has a clipRect. However, the owning layer for |surface| does not |
| // mask to bounds, so it doesn't have a clipRect of its own. Thus the parent of |surfaceChild| exercises different code paths |
| // as its parent does not have a clipRect. |
| |
| this->enterContributingSurface(surfaceChild, occlusion); |
| // The surfaceChild's parent does not have a clipRect as it owns a render surface. |
| EXPECT_RECT_EQ(gfx::Rect(0, 50, 80, 50), occlusion.unoccludedContributingSurfaceContentRect(surfaceChild, false, gfx::Rect(0, 0, 100, 100))); |
| this->leaveContributingSurface(surfaceChild, occlusion); |
| |
| this->visitLayer(surface, occlusion); |
| this->enterContributingSurface(surface, occlusion); |
| // The surface's parent does have a clipRect as it is the root layer. |
| EXPECT_RECT_EQ(gfx::Rect(0, 50, 80, 50), occlusion.unoccludedContributingSurfaceContentRect(surface, false, gfx::Rect(0, 0, 100, 100))); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestSurfaceChildOfClippingSurface); |
| |
| template<class Types> |
| class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform scaleByHalf; |
| scaleByHalf.Scale(0.5, 0.5); |
| |
| // Make a surface and its replica, each 50x50, that are completely surrounded by opaque layers which are above them in the z-order. |
| // The surface is scaled to test that the pixel moving is done in the target space, where the background filter is applied, but the surface |
| // appears at 50, 50 and the replica at 200, 50. |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 150)); |
| typename Types::LayerType* filteredSurface = this->createDrawingLayer(parent, scaleByHalf, gfx::PointF(50, 50), gfx::Size(100, 100), false); |
| this->createReplicaLayer(filteredSurface, this->identityMatrix, gfx::PointF(300, 0), gfx::Size()); |
| typename Types::LayerType* occludingLayer1 = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 50), true); |
| typename Types::LayerType* occludingLayer2 = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 100), gfx::Size(300, 50), true); |
| typename Types::LayerType* occludingLayer3 = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 50), gfx::Size(50, 50), true); |
| typename Types::LayerType* occludingLayer4 = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(100, 50), gfx::Size(100, 50), true); |
| typename Types::LayerType* occludingLayer5 = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(250, 50), gfx::Size(50, 50), true); |
| |
| // Filters make the layer own a surface. |
| WebFilterOperations filters; |
| filters.append(WebFilterOperation::createBlurFilter(10)); |
| filteredSurface->setBackgroundFilters(filters); |
| |
| // Save the distance of influence for the blur effect. |
| int outsetTop, outsetRight, outsetBottom, outsetLeft; |
| filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft); |
| |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| // These layers occlude pixels directly beside the filteredSurface. Because filtered surface blends pixels in a radius, it will |
| // need to see some of the pixels (up to radius far) underneath the occludingLayers. |
| this->visitLayer(occludingLayer5, occlusion); |
| this->visitLayer(occludingLayer4, occlusion); |
| this->visitLayer(occludingLayer3, occlusion); |
| this->visitLayer(occludingLayer2, occlusion); |
| this->visitLayer(occludingLayer1, occlusion); |
| |
| Region expectedOcclusion; |
| expectedOcclusion.Union(gfx::Rect(0, 0, 300, 50)); |
| expectedOcclusion.Union(gfx::Rect(0, 50, 50, 50)); |
| expectedOcclusion.Union(gfx::Rect(100, 50, 100, 50)); |
| expectedOcclusion.Union(gfx::Rect(250, 50, 50, 50)); |
| expectedOcclusion.Union(gfx::Rect(0, 100, 300, 50)); |
| |
| EXPECT_EQ(expectedOcclusion.ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(expectedOcclusion.ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| // Everything outside the surface/replica is occluded but the surface/replica itself is not. |
| this->enterLayer(filteredSurface, occlusion); |
| EXPECT_RECT_EQ(gfx::Rect(1, 0, 99, 100), occlusion.unoccludedLayerContentRect(filteredSurface, gfx::Rect(1, 0, 100, 100))); |
| EXPECT_RECT_EQ(gfx::Rect(0, 1, 100, 99), occlusion.unoccludedLayerContentRect(filteredSurface, gfx::Rect(0, 1, 100, 100))); |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 99, 100), occlusion.unoccludedLayerContentRect(filteredSurface, gfx::Rect(-1, 0, 100, 100))); |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 100, 99), occlusion.unoccludedLayerContentRect(filteredSurface, gfx::Rect(0, -1, 100, 100))); |
| |
| EXPECT_RECT_EQ(gfx::Rect(300 + 1, 0, 99, 100), occlusion.unoccludedLayerContentRect(filteredSurface, gfx::Rect(300 + 1, 0, 100, 100))); |
| EXPECT_RECT_EQ(gfx::Rect(300 + 0, 1, 100, 99), occlusion.unoccludedLayerContentRect(filteredSurface, gfx::Rect(300 + 0, 1, 100, 100))); |
| EXPECT_RECT_EQ(gfx::Rect(300 + 0, 0, 99, 100), occlusion.unoccludedLayerContentRect(filteredSurface, gfx::Rect(300 - 1, 0, 100, 100))); |
| EXPECT_RECT_EQ(gfx::Rect(300 + 0, 0, 100, 99), occlusion.unoccludedLayerContentRect(filteredSurface, gfx::Rect(300 + 0, -1, 100, 100))); |
| this->leaveLayer(filteredSurface, occlusion); |
| |
| // The filtered layer/replica does not occlude. |
| EXPECT_EQ(expectedOcclusion.ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect().ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| // The surface has a background blur, so it needs pixels that are currently considered occluded in order to be drawn. So the pixels |
| // it needs should be removed some the occluded area so that when we get to the parent they are drawn. |
| this->visitContributingSurface(filteredSurface, occlusion); |
| |
| this->enterLayer(parent, occlusion); |
| |
| Region expectedBlurredOcclusion; |
| expectedBlurredOcclusion.Union(gfx::Rect(0, 0, 300, 50 - outsetTop)); |
| expectedBlurredOcclusion.Union(gfx::Rect(0, 50 - outsetTop, 50 - outsetLeft, 50 + outsetTop + outsetBottom)); |
| expectedBlurredOcclusion.Union(gfx::Rect(100 + outsetRight, 50 - outsetTop, 100 - outsetRight - outsetLeft, 50 + outsetTop + outsetBottom)); |
| expectedBlurredOcclusion.Union(gfx::Rect(250 + outsetRight, 50 - outsetTop, 50 - outsetRight, 50 + outsetTop + outsetBottom)); |
| expectedBlurredOcclusion.Union(gfx::Rect(0, 100 + outsetBottom, 300, 50 - outsetBottom)); |
| |
| EXPECT_EQ(expectedBlurredOcclusion.ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(expectedBlurredOcclusion.ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| gfx::Rect outsetRect; |
| gfx::Rect testRect; |
| |
| // Nothing in the blur outsets for the filteredSurface is occluded. |
| outsetRect = gfx::Rect(50 - outsetLeft, 50 - outsetTop, 50 + outsetLeft + outsetRight, 50 + outsetTop + outsetBottom); |
| testRect = outsetRect; |
| EXPECT_RECT_EQ(outsetRect, occlusion.unoccludedLayerContentRect(parent, testRect)); |
| |
| // Stuff outside the blur outsets is still occluded though. |
| testRect = outsetRect; |
| testRect.Inset(0, 0, -1, 0); |
| EXPECT_RECT_EQ(outsetRect, occlusion.unoccludedLayerContentRect(parent, testRect)); |
| testRect = outsetRect; |
| testRect.Inset(0, 0, 0, -1); |
| EXPECT_RECT_EQ(outsetRect, occlusion.unoccludedLayerContentRect(parent, testRect)); |
| testRect = outsetRect; |
| testRect.Inset(-1, 0, 0, 0); |
| EXPECT_RECT_EQ(outsetRect, occlusion.unoccludedLayerContentRect(parent, testRect)); |
| testRect = outsetRect; |
| testRect.Inset(0, -1, 0, 0); |
| EXPECT_RECT_EQ(outsetRect, occlusion.unoccludedLayerContentRect(parent, testRect)); |
| |
| // Nothing in the blur outsets for the filteredSurface's replica is occluded. |
| outsetRect = gfx::Rect(200 - outsetLeft, 50 - outsetTop, 50 + outsetLeft + outsetRight, 50 + outsetTop + outsetBottom); |
| testRect = outsetRect; |
| EXPECT_RECT_EQ(outsetRect, occlusion.unoccludedLayerContentRect(parent, testRect)); |
| |
| // Stuff outside the blur outsets is still occluded though. |
| testRect = outsetRect; |
| testRect.Inset(0, 0, -1, 0); |
| EXPECT_RECT_EQ(outsetRect, occlusion.unoccludedLayerContentRect(parent, testRect)); |
| testRect = outsetRect; |
| testRect.Inset(0, 0, 0, -1); |
| EXPECT_RECT_EQ(outsetRect, occlusion.unoccludedLayerContentRect(parent, testRect)); |
| testRect = outsetRect; |
| testRect.Inset(-1, 0, 0, 0); |
| EXPECT_RECT_EQ(outsetRect, occlusion.unoccludedLayerContentRect(parent, testRect)); |
| testRect = outsetRect; |
| testRect.Inset(0, -1, 0, 0); |
| EXPECT_RECT_EQ(outsetRect, occlusion.unoccludedLayerContentRect(parent, testRect)); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilter); |
| |
| template<class Types> |
| class OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform scaleByHalf; |
| scaleByHalf.Scale(0.5, 0.5); |
| |
| // Makes two surfaces that completely cover |parent|. The occlusion both above and below the filters will be reduced by each of them. |
| typename Types::ContentLayerType* root = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(75, 75)); |
| typename Types::LayerType* parent = this->createSurface(root, scaleByHalf, gfx::PointF(0, 0), gfx::Size(150, 150)); |
| parent->setMasksToBounds(true); |
| typename Types::LayerType* filteredSurface1 = this->createDrawingLayer(parent, scaleByHalf, gfx::PointF(0, 0), gfx::Size(300, 300), false); |
| typename Types::LayerType* filteredSurface2 = this->createDrawingLayer(parent, scaleByHalf, gfx::PointF(0, 0), gfx::Size(300, 300), false); |
| typename Types::LayerType* occludingLayerAbove = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(100, 100), gfx::Size(50, 50), true); |
| |
| // Filters make the layers own surfaces. |
| WebFilterOperations filters; |
| filters.append(WebFilterOperation::createBlurFilter(1)); |
| filteredSurface1->setBackgroundFilters(filters); |
| filteredSurface2->setBackgroundFilters(filters); |
| |
| // Save the distance of influence for the blur effect. |
| int outsetTop, outsetRight, outsetBottom, outsetLeft; |
| filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft); |
| |
| this->calcDrawEtc(root); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(occludingLayerAbove, occlusion); |
| EXPECT_EQ(gfx::Rect(100 / 2, 100 / 2, 50 / 2, 50 / 2).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(100 / 2, 100 / 2, 50 / 2, 50 / 2).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| this->visitLayer(filteredSurface2, occlusion); |
| this->visitContributingSurface(filteredSurface2, occlusion); |
| this->visitLayer(filteredSurface1, occlusion); |
| this->visitContributingSurface(filteredSurface1, occlusion); |
| |
| // Test expectations in the target. |
| gfx::Rect expectedOcclusion = gfx::Rect(100 / 2 + outsetRight * 2, 100 / 2 + outsetBottom * 2, 50 / 2 - (outsetLeft + outsetRight) * 2, 50 / 2 - (outsetTop + outsetBottom) * 2); |
| EXPECT_EQ(expectedOcclusion.ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| // Test expectations in the screen are the same as in the target, as the render surface is 1:1 with the screen. |
| EXPECT_EQ(expectedOcclusion.ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestTwoBackgroundFiltersReduceOcclusionTwice); |
| |
| template<class Types> |
| class OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilterWithClip : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilterWithClip(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| // Make a surface and its replica, each 50x50, that are completely surrounded by opaque layers which are above them in the z-order. |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 150)); |
| // We stick the filtered surface inside a clipping surface so that we can make sure the clip is honored when exposing pixels for |
| // the background filter. |
| typename Types::LayerType* clippingSurface = this->createSurface(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 70)); |
| clippingSurface->setMasksToBounds(true); |
| typename Types::LayerType* filteredSurface = this->createDrawingLayer(clippingSurface, this->identityMatrix, gfx::PointF(50, 50), gfx::Size(50, 50), false); |
| this->createReplicaLayer(filteredSurface, this->identityMatrix, gfx::PointF(150, 0), gfx::Size()); |
| typename Types::LayerType* occludingLayer1 = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 50), true); |
| typename Types::LayerType* occludingLayer2 = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 100), gfx::Size(300, 50), true); |
| typename Types::LayerType* occludingLayer3 = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 50), gfx::Size(50, 50), true); |
| typename Types::LayerType* occludingLayer4 = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(100, 50), gfx::Size(100, 50), true); |
| typename Types::LayerType* occludingLayer5 = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(250, 50), gfx::Size(50, 50), true); |
| |
| // Filters make the layer own a surface. This filter is large enough that it goes outside the bottom of the clippingSurface. |
| WebFilterOperations filters; |
| filters.append(WebFilterOperation::createBlurFilter(12)); |
| filteredSurface->setBackgroundFilters(filters); |
| |
| // Save the distance of influence for the blur effect. |
| int outsetTop, outsetRight, outsetBottom, outsetLeft; |
| filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft); |
| |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| // These layers occlude pixels directly beside the filteredSurface. Because filtered surface blends pixels in a radius, it will |
| // need to see some of the pixels (up to radius far) underneath the occludingLayers. |
| this->visitLayer(occludingLayer5, occlusion); |
| this->visitLayer(occludingLayer4, occlusion); |
| this->visitLayer(occludingLayer3, occlusion); |
| this->visitLayer(occludingLayer2, occlusion); |
| this->visitLayer(occludingLayer1, occlusion); |
| |
| Region expectedOcclusion; |
| expectedOcclusion.Union(gfx::Rect(0, 0, 300, 50)); |
| expectedOcclusion.Union(gfx::Rect(0, 50, 50, 50)); |
| expectedOcclusion.Union(gfx::Rect(100, 50, 100, 50)); |
| expectedOcclusion.Union(gfx::Rect(250, 50, 50, 50)); |
| expectedOcclusion.Union(gfx::Rect(0, 100, 300, 50)); |
| |
| EXPECT_EQ(expectedOcclusion.ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(expectedOcclusion.ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| // Everything outside the surface/replica is occluded but the surface/replica itself is not. |
| this->enterLayer(filteredSurface, occlusion); |
| EXPECT_RECT_EQ(gfx::Rect(1, 0, 49, 50), occlusion.unoccludedLayerContentRect(filteredSurface, gfx::Rect(1, 0, 50, 50))); |
| EXPECT_RECT_EQ(gfx::Rect(0, 1, 50, 49), occlusion.unoccludedLayerContentRect(filteredSurface, gfx::Rect(0, 1, 50, 50))); |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 49, 50), occlusion.unoccludedLayerContentRect(filteredSurface, gfx::Rect(-1, 0, 50, 50))); |
| EXPECT_RECT_EQ(gfx::Rect(0, 0, 50, 49), occlusion.unoccludedLayerContentRect(filteredSurface, gfx::Rect(0, -1, 50, 50))); |
| |
| EXPECT_RECT_EQ(gfx::Rect(150 + 1, 0, 49, 50), occlusion.unoccludedLayerContentRect(filteredSurface, gfx::Rect(150 + 1, 0, 50, 50))); |
| EXPECT_RECT_EQ(gfx::Rect(150 + 0, 1, 50, 49), occlusion.unoccludedLayerContentRect(filteredSurface, gfx::Rect(150 + 0, 1, 50, 50))); |
| EXPECT_RECT_EQ(gfx::Rect(150 + 0, 0, 49, 50), occlusion.unoccludedLayerContentRect(filteredSurface, gfx::Rect(150 - 1, 0, 50, 50))); |
| EXPECT_RECT_EQ(gfx::Rect(150 + 0, 0, 50, 49), occlusion.unoccludedLayerContentRect(filteredSurface, gfx::Rect(150 + 0, -1, 50, 50))); |
| this->leaveLayer(filteredSurface, occlusion); |
| |
| // The filtered layer/replica does not occlude. |
| EXPECT_EQ(expectedOcclusion.ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect().ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| // The surface has a background blur, so it needs pixels that are currently considered occluded in order to be drawn. So the pixels |
| // it needs should be removed some the occluded area so that when we get to the parent they are drawn. |
| this->visitContributingSurface(filteredSurface, occlusion); |
| |
| this->enterContributingSurface(clippingSurface, occlusion); |
| |
| Region expectedBlurredOcclusion; |
| expectedBlurredOcclusion.Union(gfx::Rect(0, 0, 300, 50 - outsetTop)); |
| expectedBlurredOcclusion.Union(gfx::Rect(0, 50 - outsetTop, 50 - outsetLeft, 20 + outsetTop + outsetBottom)); |
| expectedBlurredOcclusion.Union(gfx::Rect(100 + outsetRight, 50 - outsetTop, 100 - outsetRight - outsetLeft, 20 + outsetTop + outsetBottom)); |
| expectedBlurredOcclusion.Union(gfx::Rect(250 + outsetRight, 50 - outsetTop, 50 - outsetRight, 20 + outsetTop + outsetBottom)); |
| expectedBlurredOcclusion.Union(gfx::Rect(0, 100 + 5, 300, 50 - 5)); |
| |
| EXPECT_EQ(expectedBlurredOcclusion.ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect().ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| gfx::Rect outsetRect; |
| gfx::Rect clippedOutsetRect; |
| gfx::Rect testRect; |
| |
| // Nothing in the (clipped) blur outsets for the filteredSurface is occluded. |
| outsetRect = gfx::Rect(50 - outsetLeft, 50 - outsetTop, 50 + outsetLeft + outsetRight, 50 + outsetTop + outsetBottom); |
| clippedOutsetRect = gfx::IntersectRects(outsetRect, gfx::Rect(0 - outsetLeft, 0 - outsetTop, 300 + outsetLeft + outsetRight, 70 + outsetTop + outsetBottom)); |
| testRect = outsetRect; |
| EXPECT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedLayerContentRect(clippingSurface, testRect)); |
| |
| // Stuff outside the (clipped) blur outsets is still occluded though. |
| testRect = outsetRect; |
| testRect.Inset(0, 0, -1, 0); |
| EXPECT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedLayerContentRect(clippingSurface, testRect)); |
| testRect = outsetRect; |
| testRect.Inset(0, 0, 0, -1); |
| EXPECT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedLayerContentRect(clippingSurface, testRect)); |
| testRect = outsetRect; |
| testRect.Inset(-1, 0, 0, 0); |
| EXPECT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedLayerContentRect(clippingSurface, testRect)); |
| testRect = outsetRect; |
| testRect.Inset(0, -1, 0, 0); |
| EXPECT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedLayerContentRect(clippingSurface, testRect)); |
| |
| // Nothing in the (clipped) blur outsets for the filteredSurface's replica is occluded. |
| outsetRect = gfx::Rect(200 - outsetLeft, 50 - outsetTop, 50 + outsetLeft + outsetRight, 50 + outsetTop + outsetBottom); |
| clippedOutsetRect = gfx::IntersectRects(outsetRect, gfx::Rect(0 - outsetLeft, 0 - outsetTop, 300 + outsetLeft + outsetRight, 70 + outsetTop + outsetBottom)); |
| testRect = outsetRect; |
| EXPECT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedLayerContentRect(clippingSurface, testRect)); |
| |
| // Stuff outside the (clipped) blur outsets is still occluded though. |
| testRect = outsetRect; |
| testRect.Inset(0, 0, -1, 0); |
| EXPECT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedLayerContentRect(clippingSurface, testRect)); |
| testRect = outsetRect; |
| testRect.Inset(0, 0, 0, -1); |
| EXPECT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedLayerContentRect(clippingSurface, testRect)); |
| testRect = outsetRect; |
| testRect.Inset(-1, 0, 0, 0); |
| EXPECT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedLayerContentRect(clippingSurface, testRect)); |
| testRect = outsetRect; |
| testRect.Inset(0, -1, 0, 0); |
| EXPECT_RECT_EQ(clippedOutsetRect, occlusion.unoccludedLayerContentRect(clippingSurface, testRect)); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestDontOccludePixelsNeededForBackgroundFilterWithClip); |
| |
| template<class Types> |
| class OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform scaleByHalf; |
| scaleByHalf.Scale(0.5, 0.5); |
| |
| // Make a surface and its replica, each 50x50, with a smaller 30x30 layer centered below each. |
| // The surface is scaled to test that the pixel moving is done in the target space, where the background filter is applied, but the surface |
| // appears at 50, 50 and the replica at 200, 50. |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 150)); |
| typename Types::LayerType* behindSurfaceLayer = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(60, 60), gfx::Size(30, 30), true); |
| typename Types::LayerType* behindReplicaLayer = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(210, 60), gfx::Size(30, 30), true); |
| typename Types::LayerType* filteredSurface = this->createDrawingLayer(parent, scaleByHalf, gfx::PointF(50, 50), gfx::Size(100, 100), false); |
| this->createReplicaLayer(filteredSurface, this->identityMatrix, gfx::PointF(300, 0), gfx::Size()); |
| |
| // Filters make the layer own a surface. |
| WebFilterOperations filters; |
| filters.append(WebFilterOperation::createBlurFilter(3)); |
| filteredSurface->setBackgroundFilters(filters); |
| |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| // The surface has a background blur, so it blurs non-opaque pixels below it. |
| this->visitLayer(filteredSurface, occlusion); |
| this->visitContributingSurface(filteredSurface, occlusion); |
| |
| this->visitLayer(behindReplicaLayer, occlusion); |
| this->visitLayer(behindSurfaceLayer, occlusion); |
| |
| // The layers behind the surface are not blurred, and their occlusion does not change, until we leave the surface. |
| // So it should not be modified by the filter here. |
| gfx::Rect occlusionBehindSurface = gfx::Rect(60, 60, 30, 30); |
| gfx::Rect occlusionBehindReplica = gfx::Rect(210, 60, 30, 30); |
| |
| Region expectedOpaqueBounds = UnionRegions(occlusionBehindSurface, occlusionBehindReplica); |
| EXPECT_EQ(expectedOpaqueBounds.ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(expectedOpaqueBounds.ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestDontReduceOcclusionBelowBackgroundFilter); |
| |
| template<class Types> |
| class OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform scaleByHalf; |
| scaleByHalf.Scale(0.5, 0.5); |
| |
| // Make a surface and its replica, each 50x50, that are completely occluded by opaque layers which are above them in the z-order. |
| // The surface is scaled to test that the pixel moving is done in the target space, where the background filter is applied, but the surface |
| // appears at 50, 50 and the replica at 200, 50. |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 150)); |
| typename Types::LayerType* filteredSurface = this->createDrawingLayer(parent, scaleByHalf, gfx::PointF(50, 50), gfx::Size(100, 100), false); |
| this->createReplicaLayer(filteredSurface, this->identityMatrix, gfx::PointF(300, 0), gfx::Size()); |
| typename Types::LayerType* aboveSurfaceLayer = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(50, 50), gfx::Size(50, 50), true); |
| typename Types::LayerType* aboveReplicaLayer = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(200, 50), gfx::Size(50, 50), true); |
| |
| // Filters make the layer own a surface. |
| WebFilterOperations filters; |
| filters.append(WebFilterOperation::createBlurFilter(3)); |
| filteredSurface->setBackgroundFilters(filters); |
| |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(aboveReplicaLayer, occlusion); |
| this->visitLayer(aboveSurfaceLayer, occlusion); |
| |
| // The surface has a background blur, so it blurs non-opaque pixels below it. |
| this->visitLayer(filteredSurface, occlusion); |
| this->visitContributingSurface(filteredSurface, occlusion); |
| |
| // The filter is completely occluded, so it should not blur anything and reduce any occlusion. |
| gfx::Rect occlusionAboveSurface = gfx::Rect(50, 50, 50, 50); |
| gfx::Rect occlusionAboveReplica = gfx::Rect(200, 50, 50, 50); |
| |
| Region expectedOpaqueRegion = UnionRegions(occlusionAboveSurface, occlusionAboveReplica); |
| EXPECT_EQ(expectedOpaqueRegion, occlusion.occlusionInScreenSpace()); |
| EXPECT_EQ(expectedOpaqueRegion, occlusion.occlusionInTargetSurface()); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestDontReduceOcclusionIfBackgroundFilterIsOccluded); |
| |
| template<class Types> |
| class OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Transform scaleByHalf; |
| scaleByHalf.Scale(0.5, 0.5); |
| |
| // Make a surface and its replica, each 50x50, that are partially occluded by opaque layers which are above them in the z-order. |
| // The surface is scaled to test that the pixel moving is done in the target space, where the background filter is applied, but the surface |
| // appears at 50, 50 and the replica at 200, 50. |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(300, 150)); |
| typename Types::LayerType* filteredSurface = this->createDrawingLayer(parent, scaleByHalf, gfx::PointF(50, 50), gfx::Size(100, 100), false); |
| this->createReplicaLayer(filteredSurface, this->identityMatrix, gfx::PointF(300, 0), gfx::Size()); |
| typename Types::LayerType* aboveSurfaceLayer = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(70, 50), gfx::Size(30, 50), true); |
| typename Types::LayerType* aboveReplicaLayer = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(200, 50), gfx::Size(30, 50), true); |
| typename Types::LayerType* besideSurfaceLayer = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(90, 40), gfx::Size(10, 10), true); |
| typename Types::LayerType* besideReplicaLayer = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(200, 40), gfx::Size(10, 10), true); |
| |
| // Filters make the layer own a surface. |
| WebFilterOperations filters; |
| filters.append(WebFilterOperation::createBlurFilter(3)); |
| filteredSurface->setBackgroundFilters(filters); |
| |
| // Save the distance of influence for the blur effect. |
| int outsetTop, outsetRight, outsetBottom, outsetLeft; |
| filters.getOutsets(outsetTop, outsetRight, outsetBottom, outsetLeft); |
| |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| |
| this->visitLayer(besideReplicaLayer, occlusion); |
| this->visitLayer(besideSurfaceLayer, occlusion); |
| this->visitLayer(aboveReplicaLayer, occlusion); |
| this->visitLayer(aboveSurfaceLayer, occlusion); |
| |
| // The surface has a background blur, so it blurs non-opaque pixels below it. |
| this->visitLayer(filteredSurface, occlusion); |
| this->visitContributingSurface(filteredSurface, occlusion); |
| |
| // The filter in the surface and replica are partially unoccluded. Only the unoccluded parts should reduce occlusion. |
| // This means it will push back the occlusion that touches the unoccluded part (occlusionAbove___), but it will not |
| // touch occlusionBeside____ since that is not beside the unoccluded part of the surface, even though it is beside |
| // the occluded part of the surface. |
| gfx::Rect occlusionAboveSurface = gfx::Rect(70 + outsetRight, 50, 30 - outsetRight, 50); |
| gfx::Rect occlusionAboveReplica = gfx::Rect(200, 50, 30 - outsetLeft, 50); |
| gfx::Rect occlusionBesideSurface = gfx::Rect(90, 40, 10, 10); |
| gfx::Rect occlusionBesideReplica = gfx::Rect(200, 40, 10, 10); |
| |
| Region expectedOcclusion; |
| expectedOcclusion.Union(occlusionAboveSurface); |
| expectedOcclusion.Union(occlusionAboveReplica); |
| expectedOcclusion.Union(occlusionBesideSurface); |
| expectedOcclusion.Union(occlusionBesideReplica); |
| |
| ASSERT_EQ(expectedOcclusion, occlusion.occlusionInTargetSurface()); |
| ASSERT_EQ(expectedOcclusion, occlusion.occlusionInScreenSpace()); |
| |
| Region::Iterator expectedRects(expectedOcclusion); |
| Region::Iterator screenSpaceRects(occlusion.occlusionInScreenSpace()); |
| Region::Iterator targetSurfaceRects(occlusion.occlusionInTargetSurface()); |
| for (; expectedRects.has_rect(); expectedRects.next(), screenSpaceRects.next(), targetSurfaceRects.next()) { |
| ASSERT_TRUE(screenSpaceRects.has_rect()); |
| ASSERT_TRUE(targetSurfaceRects.has_rect()); |
| EXPECT_EQ(expectedRects.rect(), screenSpaceRects.rect()); |
| EXPECT_EQ(expectedRects.rect(), targetSurfaceRects.rect()); |
| } |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestReduceOcclusionWhenBackgroundFilterIsPartiallyOccluded); |
| |
| template<class Types> |
| class OcclusionTrackerTestMinimumTrackingSize : public OcclusionTrackerTest<Types> { |
| protected: |
| OcclusionTrackerTestMinimumTrackingSize(bool opaqueLayers) : OcclusionTrackerTest<Types>(opaqueLayers) {} |
| void runMyTest() |
| { |
| gfx::Size trackingSize(100, 100); |
| gfx::Size belowTrackingSize(99, 99); |
| |
| typename Types::ContentLayerType* parent = this->createRoot(this->identityMatrix, gfx::PointF(0, 0), gfx::Size(400, 400)); |
| typename Types::LayerType* large = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 0), trackingSize, true); |
| typename Types::LayerType* small = this->createDrawingLayer(parent, this->identityMatrix, gfx::PointF(0, 0), belowTrackingSize, true); |
| this->calcDrawEtc(parent); |
| |
| TestOcclusionTrackerWithClip<typename Types::LayerType, typename Types::RenderSurfaceType> occlusion(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setLayerClipRect(gfx::Rect(0, 0, 1000, 1000)); |
| occlusion.setMinimumTrackingSize(trackingSize); |
| |
| // The small layer is not tracked because it is too small. |
| this->visitLayer(small, occlusion); |
| |
| EXPECT_EQ(gfx::Rect().ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect().ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| |
| // The large layer is tracked as it is large enough. |
| this->visitLayer(large, occlusion); |
| |
| EXPECT_EQ(gfx::Rect(gfx::Point(), trackingSize).ToString(), occlusion.occlusionInScreenSpace().ToString()); |
| EXPECT_EQ(gfx::Rect(gfx::Point(), trackingSize).ToString(), occlusion.occlusionInTargetSurface().ToString()); |
| } |
| }; |
| |
| ALL_OCCLUSIONTRACKER_TEST(OcclusionTrackerTestMinimumTrackingSize); |
| |
| } // namespace |
| } // namespace cc |