mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 775459 - Implement hit testing on layer tree + tests. r=kats
--HG-- extra : rebase_source : c596cc4c4dd9810319830ec8105a5e251e9b0ddb
This commit is contained in:
parent
78226b8419
commit
38f8cfba6c
@ -73,7 +73,7 @@ public:
|
||||
}
|
||||
|
||||
/* Retrives the userData for the associated key */
|
||||
void *Get(UserDataKey *key)
|
||||
void *Get(UserDataKey *key) const
|
||||
{
|
||||
for (int i=0; i<count; i++) {
|
||||
if (key == entries[i].key) {
|
||||
|
@ -414,7 +414,7 @@ ContainerLayer::SetAsyncPanZoomController(AsyncPanZoomController *controller)
|
||||
}
|
||||
|
||||
AsyncPanZoomController*
|
||||
ContainerLayer::GetAsyncPanZoomController()
|
||||
ContainerLayer::GetAsyncPanZoomController() const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (mAPZC) {
|
||||
@ -618,10 +618,10 @@ Layer::CalculateScissorRect(const nsIntRect& aCurrentScissorRect,
|
||||
}
|
||||
|
||||
const gfx3DMatrix
|
||||
Layer::GetTransform()
|
||||
Layer::GetTransform() const
|
||||
{
|
||||
gfx3DMatrix transform = mTransform;
|
||||
if (ContainerLayer* c = AsContainerLayer()) {
|
||||
if (const ContainerLayer* c = AsContainerLayer()) {
|
||||
transform.Scale(c->GetPreXScale(), c->GetPreYScale(), 1.0f);
|
||||
}
|
||||
transform.ScalePost(mPostXScale, mPostYScale, 1.0f);
|
||||
|
@ -438,7 +438,7 @@ public:
|
||||
* This getter can be used anytime. Ownership is retained by the layer
|
||||
* manager.
|
||||
*/
|
||||
LayerUserData* GetUserData(void* aKey)
|
||||
LayerUserData* GetUserData(void* aKey) const
|
||||
{
|
||||
return static_cast<LayerUserData*>(mUserData.Get(static_cast<gfx::UserDataKey*>(aKey)));
|
||||
}
|
||||
@ -895,17 +895,19 @@ public:
|
||||
const nsIntRegion& GetVisibleRegion() { return mVisibleRegion; }
|
||||
ContainerLayer* GetParent() { return mParent; }
|
||||
Layer* GetNextSibling() { return mNextSibling; }
|
||||
const Layer* GetNextSibling() const { return mNextSibling; }
|
||||
Layer* GetPrevSibling() { return mPrevSibling; }
|
||||
virtual Layer* GetFirstChild() { return nullptr; }
|
||||
virtual Layer* GetLastChild() { return nullptr; }
|
||||
const gfx3DMatrix GetTransform();
|
||||
const gfx3DMatrix& GetBaseTransform() { return mTransform; }
|
||||
float GetPostXScale() { return mPostXScale; }
|
||||
float GetPostYScale() { return mPostYScale; }
|
||||
const Layer* GetPrevSibling() const { return mPrevSibling; }
|
||||
virtual Layer* GetFirstChild() const { return nullptr; }
|
||||
virtual Layer* GetLastChild() const { return nullptr; }
|
||||
const gfx3DMatrix GetTransform() const;
|
||||
const gfx3DMatrix& GetBaseTransform() const { return mTransform; }
|
||||
float GetPostXScale() const { return mPostXScale; }
|
||||
float GetPostYScale() const { return mPostYScale; }
|
||||
bool GetIsFixedPosition() { return mIsFixedPosition; }
|
||||
gfxPoint GetFixedPositionAnchor() { return mAnchor; }
|
||||
const gfx::Margin& GetFixedPositionMargins() { return mMargins; }
|
||||
Layer* GetMaskLayer() { return mMaskLayer; }
|
||||
Layer* GetMaskLayer() const { return mMaskLayer; }
|
||||
|
||||
// Note that all lengths in animation data are either in CSS pixels or app
|
||||
// units and must be converted to device pixels by the compositor.
|
||||
@ -991,7 +993,7 @@ public:
|
||||
* This getter can be used anytime. Ownership is retained by the layer
|
||||
* manager.
|
||||
*/
|
||||
LayerUserData* GetUserData(void* aKey)
|
||||
LayerUserData* GetUserData(void* aKey) const
|
||||
{
|
||||
return static_cast<LayerUserData*>(mUserData.Get(static_cast<gfx::UserDataKey*>(aKey)));
|
||||
}
|
||||
@ -1018,6 +1020,7 @@ public:
|
||||
* a ContainerLayer.
|
||||
*/
|
||||
virtual ContainerLayer* AsContainerLayer() { return nullptr; }
|
||||
virtual const ContainerLayer* AsContainerLayer() const { return nullptr; }
|
||||
|
||||
/**
|
||||
* Dynamic cast to a RefLayer. Returns null if this is not a
|
||||
@ -1420,7 +1423,7 @@ public:
|
||||
// and can be used anytime.
|
||||
// A container layer has an APZC only-if GetFrameMetrics().IsScrollable()
|
||||
void SetAsyncPanZoomController(AsyncPanZoomController *controller);
|
||||
AsyncPanZoomController* GetAsyncPanZoomController();
|
||||
AsyncPanZoomController* GetAsyncPanZoomController() const;
|
||||
|
||||
void SetPreScale(float aXScale, float aYScale)
|
||||
{
|
||||
@ -1453,14 +1456,15 @@ public:
|
||||
// These getters can be used anytime.
|
||||
|
||||
virtual ContainerLayer* AsContainerLayer() { return this; }
|
||||
virtual const ContainerLayer* AsContainerLayer() const { return this; }
|
||||
|
||||
virtual Layer* GetFirstChild() { return mFirstChild; }
|
||||
virtual Layer* GetLastChild() { return mLastChild; }
|
||||
const FrameMetrics& GetFrameMetrics() { return mFrameMetrics; }
|
||||
float GetPreXScale() { return mPreXScale; }
|
||||
float GetPreYScale() { return mPreYScale; }
|
||||
float GetInheritedXScale() { return mInheritedXScale; }
|
||||
float GetInheritedYScale() { return mInheritedYScale; }
|
||||
virtual Layer* GetFirstChild() const { return mFirstChild; }
|
||||
virtual Layer* GetLastChild() const { return mLastChild; }
|
||||
const FrameMetrics& GetFrameMetrics() const { return mFrameMetrics; }
|
||||
float GetPreXScale() const { return mPreXScale; }
|
||||
float GetPreYScale() const { return mPreYScale; }
|
||||
float GetInheritedXScale() const { return mInheritedXScale; }
|
||||
float GetInheritedYScale() const { return mInheritedYScale; }
|
||||
|
||||
MOZ_LAYER_DECL_NAME("ContainerLayer", TYPE_CONTAINER)
|
||||
|
||||
|
@ -185,6 +185,7 @@ AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoCon
|
||||
mDelayPanning(false)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_COUNT_CTOR(AsyncPanZoomController);
|
||||
|
||||
InitAZPCPrefs();
|
||||
|
||||
@ -206,7 +207,7 @@ AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoCon
|
||||
}
|
||||
|
||||
AsyncPanZoomController::~AsyncPanZoomController() {
|
||||
|
||||
MOZ_COUNT_DTOR(AsyncPanZoomController);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1458,5 +1459,53 @@ void AsyncPanZoomController::SendAsyncScrollEvent() {
|
||||
|
||||
mGeckoContentController->SendAsyncScrollDOMEvent(contentRect, scrollableSize);
|
||||
}
|
||||
|
||||
static void GetAPZCAtPointOnSubtree(const ContainerLayer& aLayerIn,
|
||||
const gfxPoint& aPoint,
|
||||
AsyncPanZoomController** aApzcOut,
|
||||
LayerIntPoint* aRelativePointOut)
|
||||
{
|
||||
// Making layers const correct is very slow because it requires
|
||||
// a near clobber of the tree. Once const correct is further along
|
||||
// remove this cast.
|
||||
ContainerLayer& aLayer = const_cast<ContainerLayer&>(aLayerIn);
|
||||
gfx3DMatrix transform = aLayer.GetLocalTransform().Inverse();
|
||||
gfxPoint layerPoint = transform.Transform(aPoint);
|
||||
|
||||
// iterate over the children first. They are better match then the parent
|
||||
Layer* currLayer = aLayer.GetLastChild();
|
||||
while (currLayer) {
|
||||
if (currLayer->AsContainerLayer()) {
|
||||
GetAPZCAtPointOnSubtree(*currLayer->AsContainerLayer(), layerPoint, aApzcOut, aRelativePointOut);
|
||||
}
|
||||
if (*aApzcOut) {
|
||||
return;
|
||||
}
|
||||
currLayer = currLayer->GetPrevSibling();
|
||||
}
|
||||
|
||||
bool intersect = aLayer.GetVisibleRegion().Contains(nsIntRect(layerPoint.x, layerPoint.y, 1, 1));
|
||||
|
||||
if (intersect) {
|
||||
if (aLayer.GetFrameMetrics().IsScrollable()) {
|
||||
*aApzcOut = aLayer.GetAsyncPanZoomController();
|
||||
*aRelativePointOut = LayerIntPoint(NS_lround(layerPoint.x), NS_lround(layerPoint.y));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::GetAPZCAtPoint(const ContainerLayer& aLayerTree,
|
||||
const ScreenIntPoint& aPoint,
|
||||
AsyncPanZoomController** aApzcOut,
|
||||
LayerIntPoint* aRelativePointOut)
|
||||
{
|
||||
*aApzcOut = nullptr;
|
||||
|
||||
gfxPoint point(aPoint.x, aPoint.y);
|
||||
|
||||
GetAPZCAtPointOnSubtree(aLayerTree, point, aApzcOut, aRelativePointOut);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -242,6 +242,17 @@ public:
|
||||
*/
|
||||
static void SetFrameTime(const TimeStamp& aMilliseconds);
|
||||
|
||||
/**
|
||||
* Transform and intersect aPoint with the layer tree returning the appropriate
|
||||
* AsyncPanZoomController for this point.
|
||||
* aRelativePointOut Return the point transformed into the layer coordinates
|
||||
* relative to the scroll origin for this layer.
|
||||
*/
|
||||
static void GetAPZCAtPoint(const ContainerLayer& aLayerTree,
|
||||
const ScreenIntPoint& aPoint,
|
||||
AsyncPanZoomController** aApzcOut,
|
||||
LayerIntPoint* aRelativePointOut);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Helper method for touches beginning. Sets everything up for panning and any
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "mozilla/layers/LayerManagerComposite.h"
|
||||
#include "mozilla/layers/GeckoContentController.h"
|
||||
#include "Layers.h"
|
||||
#include "TestLayers.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
@ -27,9 +28,9 @@ public:
|
||||
MOCK_METHOD2(PostDelayedTask, void(Task* aTask, int aDelayMs));
|
||||
};
|
||||
|
||||
class TestContainerLayer : public ContainerLayer {
|
||||
class TestAPZCContainerLayer : public ContainerLayer {
|
||||
public:
|
||||
TestContainerLayer()
|
||||
TestAPZCContainerLayer()
|
||||
: ContainerLayer(nullptr, nullptr)
|
||||
{}
|
||||
void RemoveChild(Layer* aChild) {}
|
||||
@ -100,7 +101,7 @@ TEST(AsyncPanZoomController, SimpleTransform) {
|
||||
nsRefPtr<AsyncPanZoomController> apzc = new AsyncPanZoomController(mcc);
|
||||
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
|
||||
|
||||
TestContainerLayer layer;
|
||||
TestAPZCContainerLayer layer;
|
||||
ScreenPoint pointOut;
|
||||
ViewTransform viewTransformOut;
|
||||
apzc->SampleContentTransformForFrame(testStartTime, &layer, &viewTransformOut, pointOut);
|
||||
@ -123,7 +124,7 @@ TEST(AsyncPanZoomController, Pan) {
|
||||
int time = 0;
|
||||
int touchStart = 50;
|
||||
int touchEnd = 10;
|
||||
TestContainerLayer layer;
|
||||
TestAPZCContainerLayer layer;
|
||||
ScreenPoint pointOut;
|
||||
ViewTransform viewTransformOut;
|
||||
|
||||
@ -154,7 +155,7 @@ TEST(AsyncPanZoomController, Fling) {
|
||||
int time = 0;
|
||||
int touchStart = 50;
|
||||
int touchEnd = 10;
|
||||
TestContainerLayer layer;
|
||||
TestAPZCContainerLayer layer;
|
||||
ScreenPoint pointOut;
|
||||
ViewTransform viewTransformOut;
|
||||
|
||||
@ -163,7 +164,6 @@ TEST(AsyncPanZoomController, Fling) {
|
||||
ScreenPoint lastPoint;
|
||||
for (int i = 1; i < 50; i+=1) {
|
||||
apzc->SampleContentTransformForFrame(testStartTime+TimeDuration::FromMilliseconds(i), &layer, &viewTransformOut, pointOut);
|
||||
printf("Time %f, y position %f\n", (float)i, pointOut.y);
|
||||
EXPECT_GT(pointOut.y, lastPoint.y);
|
||||
lastPoint = pointOut;
|
||||
}
|
||||
@ -184,7 +184,7 @@ TEST(AsyncPanZoomController, OverScrollPanning) {
|
||||
int time = 0;
|
||||
int touchStart = 500;
|
||||
int touchEnd = 10;
|
||||
TestContainerLayer layer;
|
||||
TestAPZCContainerLayer layer;
|
||||
ScreenPoint pointOut;
|
||||
ViewTransform viewTransformOut;
|
||||
|
||||
@ -194,3 +194,157 @@ TEST(AsyncPanZoomController, OverScrollPanning) {
|
||||
EXPECT_EQ(pointOut, ScreenPoint(0, 90));
|
||||
}
|
||||
|
||||
static already_AddRefed<mozilla::layers::Layer>
|
||||
CreateTestLayerTree(nsRefPtr<LayerManager>& aLayerManager, nsTArray<nsRefPtr<Layer> >& aLayers) {
|
||||
const char* layerTreeSyntax = "c(ttccc(c(c)))";
|
||||
// LayerID 0 12345 6 7
|
||||
nsIntRegion layerVisibleRegion[] = {
|
||||
nsIntRegion(nsIntRect(0,0,100,100)),
|
||||
nsIntRegion(nsIntRect(0,0,100,100)),
|
||||
nsIntRegion(nsIntRect(10,10,20,20)),
|
||||
nsIntRegion(nsIntRect(10,10,20,20)),
|
||||
nsIntRegion(nsIntRect(5,5,20,20)),
|
||||
nsIntRegion(nsIntRect(10,10,40,40)),
|
||||
nsIntRegion(nsIntRect(10,10,40,40)),
|
||||
nsIntRegion(nsIntRect(10,10,40,40)),
|
||||
};
|
||||
gfx3DMatrix transforms[] = {
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
};
|
||||
return CreateLayerTree(layerTreeSyntax, layerVisibleRegion, transforms, aLayerManager, aLayers);
|
||||
}
|
||||
|
||||
TEST(AsyncPanZoomController, GetAPZCAtPoint) {
|
||||
nsTArray<nsRefPtr<Layer> > layers;
|
||||
nsRefPtr<LayerManager> lm;
|
||||
nsRefPtr<Layer> root = CreateTestLayerTree(lm, layers);
|
||||
|
||||
TimeStamp testStartTime = TimeStamp::Now();
|
||||
AsyncPanZoomController::SetFrameTime(testStartTime);
|
||||
|
||||
nsRefPtr<MockContentController> mcc = new MockContentController();
|
||||
nsRefPtr<AsyncPanZoomController> apzcMain = new AsyncPanZoomController(mcc);
|
||||
nsRefPtr<AsyncPanZoomController> apzcSub3 = new AsyncPanZoomController(mcc);
|
||||
nsRefPtr<AsyncPanZoomController> apzcSub4 = new AsyncPanZoomController(mcc);
|
||||
nsRefPtr<AsyncPanZoomController> apzcSub7 = new AsyncPanZoomController(mcc);
|
||||
apzcMain->NotifyLayersUpdated(TestFrameMetrics(), true);
|
||||
|
||||
ScreenIntPoint touchPoint(20, 20);
|
||||
AsyncPanZoomController* apzcOut;
|
||||
LayerIntPoint relativePointOut;
|
||||
|
||||
FrameMetrics scrollable;
|
||||
|
||||
// No APZC attached so hit testing will return no APZC at (20,20)
|
||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
||||
&apzcOut, &relativePointOut);
|
||||
|
||||
AsyncPanZoomController* nullAPZC = nullptr;
|
||||
EXPECT_EQ(apzcOut, nullAPZC);
|
||||
|
||||
// Now we have a root APZC that will match the page
|
||||
scrollable.mScrollId = FrameMetrics::ROOT_SCROLL_ID;
|
||||
root->AsContainerLayer()->SetFrameMetrics(scrollable);
|
||||
root->AsContainerLayer()->SetAsyncPanZoomController(apzcMain);
|
||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
||||
&apzcOut, &relativePointOut);
|
||||
EXPECT_EQ(apzcOut, apzcMain.get());
|
||||
EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut);
|
||||
|
||||
// Now we have a sub APZC with a better fit
|
||||
scrollable.mScrollId = FrameMetrics::START_SCROLL_ID;
|
||||
layers[3]->AsContainerLayer()->SetFrameMetrics(scrollable);
|
||||
layers[3]->AsContainerLayer()->SetAsyncPanZoomController(apzcSub3);
|
||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
||||
&apzcOut, &relativePointOut);
|
||||
EXPECT_EQ(apzcOut, apzcSub3.get());
|
||||
EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut);
|
||||
|
||||
// Now test hit testing when we have two scrollable layers
|
||||
touchPoint = ScreenIntPoint(15,15);
|
||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
||||
&apzcOut, &relativePointOut);
|
||||
EXPECT_EQ(apzcOut, apzcSub3.get()); // We haven't bound apzcSub4 yet
|
||||
scrollable.mScrollId++;
|
||||
layers[4]->AsContainerLayer()->SetFrameMetrics(scrollable);
|
||||
layers[4]->AsContainerLayer()->SetAsyncPanZoomController(apzcSub4);
|
||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
||||
&apzcOut, &relativePointOut);
|
||||
EXPECT_EQ(apzcOut, apzcSub4.get());
|
||||
EXPECT_EQ(LayerIntPoint(15, 15), relativePointOut);
|
||||
|
||||
// Hit test ouside the reach of apzc3/4 but inside apzcMain
|
||||
touchPoint = ScreenIntPoint(90,90);
|
||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
||||
&apzcOut, &relativePointOut);
|
||||
EXPECT_EQ(apzcOut, apzcMain.get());
|
||||
EXPECT_EQ(LayerIntPoint(90, 90), relativePointOut);
|
||||
|
||||
// Hit test ouside the reach of any layer
|
||||
touchPoint = ScreenIntPoint(1000,10);
|
||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
||||
&apzcOut, &relativePointOut);
|
||||
EXPECT_EQ(apzcOut, nullAPZC);
|
||||
touchPoint = ScreenIntPoint(-1000,10);
|
||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
||||
&apzcOut, &relativePointOut);
|
||||
EXPECT_EQ(apzcOut, nullAPZC);
|
||||
|
||||
// Test layer transform
|
||||
gfx3DMatrix transform;
|
||||
transform.ScalePost(0.1, 0.1, 1);
|
||||
root->SetBaseTransform(transform);
|
||||
|
||||
touchPoint = ScreenIntPoint(50,50); // This point is now outside the root layer
|
||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
||||
&apzcOut, &relativePointOut);
|
||||
EXPECT_EQ(apzcOut, nullAPZC);
|
||||
|
||||
touchPoint = ScreenIntPoint(2,2);
|
||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
||||
&apzcOut, &relativePointOut);
|
||||
EXPECT_EQ(apzcOut, apzcSub4.get());
|
||||
EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut);
|
||||
|
||||
// Scale layer[4] outside the range
|
||||
layers[4]->SetBaseTransform(transform);
|
||||
// layer 4 effective visible screenrect: (0.05, 0.05, 0.2, 0.2)
|
||||
// Does not contain (2, 2)
|
||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
||||
&apzcOut, &relativePointOut);
|
||||
EXPECT_EQ(apzcOut, apzcSub3.get());
|
||||
EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut);
|
||||
|
||||
// Transformation chain to layer 7
|
||||
scrollable.mScrollId++;
|
||||
layers[7]->AsContainerLayer()->SetFrameMetrics(scrollable);
|
||||
layers[7]->AsContainerLayer()->SetAsyncPanZoomController(apzcSub7);
|
||||
|
||||
gfx3DMatrix translateTransform;
|
||||
translateTransform.Translate(gfxPoint3D(10, 10, 0));
|
||||
layers[5]->SetBaseTransform(translateTransform);
|
||||
|
||||
gfx3DMatrix translateTransform2;
|
||||
translateTransform2.Translate(gfxPoint3D(-20, 0, 0));
|
||||
layers[6]->SetBaseTransform(translateTransform2);
|
||||
|
||||
gfx3DMatrix translateTransform3;
|
||||
translateTransform3.ScalePost(1,15,1);
|
||||
layers[7]->SetBaseTransform(translateTransform3);
|
||||
|
||||
touchPoint = ScreenIntPoint(1,45);
|
||||
// layer 7 effective visible screenrect (0,16,4,60) but clipped by parent layers
|
||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
||||
&apzcOut, &relativePointOut);
|
||||
EXPECT_EQ(apzcOut, apzcSub7.get());
|
||||
EXPECT_EQ(LayerIntPoint(20, 29), relativePointOut);
|
||||
}
|
||||
|
||||
|
||||
|
@ -3,21 +3,44 @@
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
#include "TestLayers.h"
|
||||
#include "gtest/gtest.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "Layers.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::layers;
|
||||
|
||||
class TestLayer: public Layer {
|
||||
class TestLayerManager: public LayerManager {
|
||||
public:
|
||||
TestLayer(LayerManager* aManager)
|
||||
: Layer(aManager, nullptr)
|
||||
TestLayerManager()
|
||||
: LayerManager()
|
||||
{}
|
||||
|
||||
virtual bool EndEmptyTransaction(EndTransactionFlags aFlags = END_DEFAULT) { return false; }
|
||||
virtual already_AddRefed<ContainerLayer> CreateContainerLayer() { return nullptr; }
|
||||
virtual void GetBackendName(nsAString& aName) {}
|
||||
virtual LayersBackend GetBackendType() { return LAYERS_BASIC; }
|
||||
virtual void BeginTransaction() {}
|
||||
virtual already_AddRefed<ImageLayer> CreateImageLayer() { return nullptr; }
|
||||
virtual void SetRoot(Layer* aLayer) {}
|
||||
virtual already_AddRefed<ColorLayer> CreateColorLayer() { return nullptr; }
|
||||
virtual void BeginTransactionWithTarget(gfxContext* aTarget) {}
|
||||
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer() { return nullptr; }
|
||||
virtual void EndTransaction(DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
EndTransactionFlags aFlags = END_DEFAULT) {}
|
||||
virtual int32_t GetMaxTextureSize() const { return 0; }
|
||||
virtual already_AddRefed<ThebesLayer> CreateThebesLayer() { return nullptr; }
|
||||
};
|
||||
|
||||
class TestContainerLayer: public ContainerLayer {
|
||||
public:
|
||||
TestContainerLayer(LayerManager* aManager)
|
||||
: ContainerLayer(aManager, nullptr)
|
||||
{}
|
||||
|
||||
virtual const char* Name() const {
|
||||
return "TestLayer";
|
||||
return "TestContainerLayer";
|
||||
}
|
||||
|
||||
virtual LayerType GetType() const {
|
||||
@ -25,6 +48,55 @@ public:
|
||||
}
|
||||
|
||||
virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) {
|
||||
}
|
||||
|
||||
virtual void RepositionChild(Layer* aChild, Layer* aAfter) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
virtual void InsertAfter(Layer* aChild, Layer* aAfter) {
|
||||
// Bad implementation but it should be fine for testing
|
||||
if (this == aChild) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
if (aAfter != nullptr && aAfter != mLastChild) {
|
||||
// Fix the implementation to support this if you need it
|
||||
MOZ_CRASH();
|
||||
}
|
||||
if (!mFirstChild) {
|
||||
mFirstChild = aChild;
|
||||
}
|
||||
if (mLastChild) {
|
||||
mLastChild->SetNextSibling(aChild);
|
||||
}
|
||||
aChild->SetPrevSibling(mLastChild);
|
||||
mLastChild = aChild;
|
||||
}
|
||||
|
||||
virtual void RemoveChild(Layer* aChild) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
};
|
||||
|
||||
class TestThebesLayer: public ThebesLayer {
|
||||
public:
|
||||
TestThebesLayer(LayerManager* aManager)
|
||||
: ThebesLayer(aManager, nullptr)
|
||||
{}
|
||||
|
||||
virtual const char* Name() const {
|
||||
return "TestThebesLayer";
|
||||
}
|
||||
|
||||
virtual LayerType GetType() const {
|
||||
return TYPE_THEBES;
|
||||
}
|
||||
|
||||
virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
virtual void InvalidateRegion(const nsIntRegion& aRegion) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
};
|
||||
@ -37,11 +109,11 @@ public:
|
||||
|
||||
|
||||
TEST(Layers, LayerConstructor) {
|
||||
TestLayer layer(nullptr);
|
||||
TestContainerLayer layer(nullptr);
|
||||
}
|
||||
|
||||
TEST(Layers, Defaults) {
|
||||
TestLayer layer(nullptr);
|
||||
TestContainerLayer layer(nullptr);
|
||||
ASSERT_EQ(1.0, layer.GetOpacity());
|
||||
ASSERT_EQ(1.0f, layer.GetPostXScale());
|
||||
ASSERT_EQ(1.0f, layer.GetPostYScale());
|
||||
@ -53,7 +125,7 @@ TEST(Layers, Defaults) {
|
||||
}
|
||||
|
||||
TEST(Layers, Transform) {
|
||||
TestLayer layer(nullptr);
|
||||
TestContainerLayer layer(nullptr);
|
||||
|
||||
gfx3DMatrix identity;
|
||||
ASSERT_EQ(true, identity.IsIdentity());
|
||||
@ -62,15 +134,15 @@ TEST(Layers, Transform) {
|
||||
}
|
||||
|
||||
TEST(Layers, Type) {
|
||||
TestLayer layer(nullptr);
|
||||
TestContainerLayer layer(nullptr);
|
||||
ASSERT_EQ(nullptr, layer.AsThebesLayer());
|
||||
ASSERT_EQ(nullptr, layer.AsRefLayer());
|
||||
ASSERT_EQ(nullptr, layer.AsColorLayer());
|
||||
}
|
||||
|
||||
TEST(Layers, UserData) {
|
||||
TestLayer* layerPtr = new TestLayer(nullptr);
|
||||
TestLayer& layer = *layerPtr;
|
||||
TestContainerLayer* layerPtr = new TestContainerLayer(nullptr);
|
||||
TestContainerLayer& layer = *layerPtr;
|
||||
|
||||
void* key1 = (void*)1;
|
||||
void* key2 = (void*)2;
|
||||
@ -105,3 +177,93 @@ TEST(Layers, UserData) {
|
||||
|
||||
}
|
||||
|
||||
static
|
||||
already_AddRefed<Layer> CreateLayer(char aLayerType, LayerManager* aManager) {
|
||||
nsRefPtr<Layer> layer = nullptr;
|
||||
if (aLayerType == 'c') {
|
||||
layer = new TestContainerLayer(aManager);
|
||||
} else if (aLayerType == 't') {
|
||||
layer = new TestThebesLayer(aManager);
|
||||
}
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Layer> CreateLayerTree(
|
||||
const char* aLayerTreeDescription,
|
||||
nsIntRegion* aVisibleRegions,
|
||||
const gfx3DMatrix* aTransforms,
|
||||
nsRefPtr<LayerManager>& manager,
|
||||
nsTArray<nsRefPtr<Layer> >& aLayersOut) {
|
||||
|
||||
aLayersOut.Clear();
|
||||
|
||||
manager = new TestLayerManager();
|
||||
|
||||
nsRefPtr<Layer> rootLayer = nullptr;
|
||||
nsRefPtr<ContainerLayer> parentContainerLayer = nullptr;
|
||||
nsRefPtr<Layer> lastLayer = nullptr;
|
||||
int layerNumber = 0;
|
||||
for (size_t i = 0; i < strlen(aLayerTreeDescription); i++) {
|
||||
if (aLayerTreeDescription[i] == '(') {
|
||||
if (!lastLayer) {
|
||||
printf("Syntax error, likely '(' character isn't preceded by a container.\n");
|
||||
MOZ_CRASH();
|
||||
}
|
||||
parentContainerLayer = lastLayer->AsContainerLayer();
|
||||
if (!parentContainerLayer) {
|
||||
printf("Layer before '(' must be a container.\n");
|
||||
MOZ_CRASH();
|
||||
}
|
||||
} else if (aLayerTreeDescription[i] == ')') {
|
||||
parentContainerLayer = parentContainerLayer->GetParent();
|
||||
lastLayer = nullptr;
|
||||
} else {
|
||||
nsRefPtr<Layer> layer = CreateLayer(aLayerTreeDescription[i], manager.get());
|
||||
layer->SetVisibleRegion(aVisibleRegions[layerNumber]);
|
||||
layer->SetBaseTransform(aTransforms[layerNumber]);
|
||||
aLayersOut.AppendElement(layer);
|
||||
layerNumber++;
|
||||
if (rootLayer && !parentContainerLayer) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
if (!rootLayer) {
|
||||
rootLayer = layer;
|
||||
}
|
||||
if (parentContainerLayer) {
|
||||
parentContainerLayer->InsertAfter(layer, nullptr);
|
||||
layer->SetParent(parentContainerLayer);
|
||||
}
|
||||
lastLayer = layer;
|
||||
}
|
||||
}
|
||||
return rootLayer.forget();
|
||||
}
|
||||
|
||||
TEST(Layers, LayerTree) {
|
||||
const char* layerTreeSyntax = "c(c(tt))";
|
||||
nsIntRegion layerVisibleRegion[] = {
|
||||
nsIntRegion(nsIntRect(0,0,100,100)),
|
||||
nsIntRegion(nsIntRect(0,0,100,100)),
|
||||
nsIntRegion(nsIntRect(0,0,100,100)),
|
||||
nsIntRegion(nsIntRect(10,10,20,20)),
|
||||
};
|
||||
gfx3DMatrix transforms[] = {
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
};
|
||||
nsTArray<nsRefPtr<Layer> > layers;
|
||||
|
||||
nsRefPtr<LayerManager> lm;
|
||||
nsRefPtr<Layer> root = CreateLayerTree(layerTreeSyntax, layerVisibleRegion, transforms, lm, layers);
|
||||
|
||||
// B2G g++ doesn't like ASSERT_NE with nullptr directly. It thinks it's
|
||||
// an int.
|
||||
Layer* nullLayer = nullptr;
|
||||
ASSERT_NE(nullLayer, layers[0]->AsContainerLayer());
|
||||
ASSERT_NE(nullLayer, layers[1]->AsContainerLayer());
|
||||
ASSERT_NE(nullLayer, layers[2]->AsThebesLayer());
|
||||
ASSERT_NE(nullLayer, layers[3]->AsThebesLayer());
|
||||
}
|
||||
|
||||
|
35
gfx/tests/gtest/TestLayers.h
Normal file
35
gfx/tests/gtest/TestLayers.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
#ifndef GFX_TEST_LAYERS_H
|
||||
#define GFX_TEST_LAYERS_H
|
||||
|
||||
#include "Layers.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
// Create layer tree from a simple layer tree description syntax.
|
||||
// Each index is either the first letter of the layer type or
|
||||
// a '(',')' to indicate the start/end of the child layers.
|
||||
// The aim of this function is to remove hard to read
|
||||
// layer tree creation code.
|
||||
//
|
||||
// Example "c(c(c(tt)t))" would yield:
|
||||
// c
|
||||
// |
|
||||
// c
|
||||
// / \
|
||||
// c t
|
||||
// / \
|
||||
// t t
|
||||
already_AddRefed<mozilla::layers::Layer> CreateLayerTree(
|
||||
const char* aLayerTreeDescription,
|
||||
nsIntRegion* aVisibleRegions,
|
||||
const gfx3DMatrix* aTransforms,
|
||||
nsRefPtr<mozilla::layers::LayerManager>& aLayerManager,
|
||||
nsTArray<nsRefPtr<mozilla::layers::Layer> >& aLayersOut);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -43,7 +43,7 @@ public:
|
||||
}
|
||||
virtual void OnTestPartResult(const TestPartResult& aTestPartResult) MOZ_OVERRIDE {
|
||||
printf("TEST-%s | %s.%s | %s @ %s:%i\n",
|
||||
aTestPartResult.failed() ? "PASS" : "UNEXPECTED-FAIL",
|
||||
!aTestPartResult.failed() ? "PASS" : "UNEXPECTED-FAIL",
|
||||
mTestInfo->test_case_name(), mTestInfo->name(),
|
||||
aTestPartResult.summary(),
|
||||
aTestPartResult.file_name(), aTestPartResult.line_number());
|
||||
|
Loading…
Reference in New Issue
Block a user