diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index caee4a819e1..f81919c79ab 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -79,11 +79,31 @@ CompositorParent::RecvStop() return true; } + void CompositorParent::ScheduleComposition() { CancelableTask *composeTask = NewRunnableMethod(this, &CompositorParent::Composite); MessageLoop::current()->PostTask(FROM_HERE, composeTask); + +// Test code for async scrolling. +#ifdef OMTC_TEST_ASYNC_SCROLLING + static bool scrollScheduled = false; + if (!scrollScheduled) { + CancelableTask *composeTask2 = NewRunnableMethod(this, + &CompositorParent::TestScroll); + MessageLoop::current()->PostDelayedTask(FROM_HERE, composeTask2, 500); + scrollScheduled = true; + } +#endif +} + +void +CompositorParent::SetTransformation(float aScale, nsIntPoint aScrollOffset) +{ + mXScale = aScale; + mYScale = aScale; + mScrollOffset = aScrollOffset; } void @@ -113,6 +133,113 @@ SetShadowProperties(Layer* aLayer) } } +static double GetXScale(const gfx3DMatrix& aTransform) +{ + return aTransform._11; +} + +static double GetYScale(const gfx3DMatrix& aTransform) +{ + return aTransform._22; +} + +static void ReverseTranslate(gfx3DMatrix& aTransform, ViewTransform& aViewTransform) +{ + aTransform._41 -= aViewTransform.mTranslation.x / aViewTransform.mXScale; + aTransform._42 -= aViewTransform.mTranslation.y / aViewTransform.mYScale; +} + +void +CompositorParent::TransformShadowTree(Layer* aLayer, const ViewTransform& aTransform, + float aTempScaleDiffX, float aTempScaleDiffY) +{ + ShadowLayer* shadow = aLayer->AsShadowLayer(); + + gfx3DMatrix shadowTransform = aLayer->GetTransform(); + ViewTransform layerTransform = aTransform; + + ContainerLayer* container = aLayer->AsContainerLayer(); + + if (container && container->GetFrameMetrics().IsScrollable()) { + const FrameMetrics* metrics = &container->GetFrameMetrics(); + const gfx3DMatrix& currentTransform = aLayer->GetTransform(); + + aTempScaleDiffX *= GetXScale(shadowTransform); + aTempScaleDiffY *= GetYScale(shadowTransform); + + nsIntPoint metricsScrollOffset = metrics->mViewportScrollOffset; + + nsIntPoint scrollCompensation( + (mScrollOffset.x / aTempScaleDiffX - metricsScrollOffset.x) * mXScale, + (mScrollOffset.y / aTempScaleDiffY - metricsScrollOffset.y) * mYScale); + ViewTransform treeTransform(-scrollCompensation, mXScale, + mYScale); + shadowTransform = gfx3DMatrix(treeTransform) * currentTransform; + layerTransform = treeTransform; + } + + // Uncomment to deal with position:fixed. + /* + if (aLayer->GetIsFixedPosition() && + !aLayer->GetParent()->GetIsFixedPosition()) { + printf_stderr("Correcting for position fixed\n"); + ReverseTranslate(shadowTransform, layerTransform); + const nsIntRect* clipRect = shadow->GetShadowClipRect(); + if (clipRect) { + nsIntRect transformedClipRect(*clipRect); + transformedClipRect.MoveBy(shadowTransform._41, shadowTransform._42); + shadow->SetShadowClipRect(&transformedClipRect); + } + }*/ + + shadow->SetShadowTransform(shadowTransform); + + // Uncomment the following when we want to deal with position:fixed. + // Note that we need to modify other code to ensure that position:fixed + // things get their own layer. See Bug 607417. + /* + for (Layer* child = aLayer->GetFirstChild(); child; + child = child->GetNextSibling()) { + TransformShadowTree(child, layerTransform, aTempScaleDiffX, + aTempScaleDiffY); + }*/ + +} + +void +CompositorParent::AsyncRender() +{ + if (mStopped || !mLayerManager) { + return; + } + + Layer* root = mLayerManager->GetRoot(); + ContainerLayer* container = root->AsContainerLayer(); + if (!container) + return; + + FrameMetrics metrics = container->GetFrameMetrics(); +/* + printf("FrameMetrics: mViewPort: X: %d, Y: %d, Width: %d, Height: %d ", + metrics.mViewport.X(), metrics.mViewport.Y(), metrics.mViewport.Width(), + metrics.mViewport.Height()); + printf("mDisplayPort: X: %d, Y: %d, Width: %d, Height: %d ", + metrics.mDisplayPort.X(), metrics.mDisplayPort.Y(), metrics.mDisplayPort.Width(), + metrics.mDisplayPort.Height()); + printf("mContentSize: width: %d, height: %d ", metrics.mContentSize.width, + metrics. mContentSize.height); + printf("mViewPortScrollOffset: x: %d, y: %d\n", + metrics.mViewportScrollOffset.x, + metrics.mViewportScrollOffset.y); +*/ + // Modify framemetrics here, just as a test. + metrics.mScrollId = FrameMetrics::ROOT_SCROLL_ID; + container->SetFrameMetrics(metrics); + ViewTransform transform; + TransformShadowTree(root, transform); + Composite(); +} + void CompositorParent::ShadowLayersUpdated() { @@ -127,6 +254,36 @@ CompositorParent::ShadowLayersUpdated() ScheduleComposition(); } +// Test code for async scrolling. +#ifdef OMTC_TEST_ASYNC_SCROLLING +void +CompositorParent::TestScroll() +{ + static int scrollFactor = 0; + static bool fakeScrollDownwards = true; + if (fakeScrollDownwards) { + scrollFactor++; + if (scrollFactor > 10) { + scrollFactor = 10; + fakeScrollDownwards = false; + } + } else { + scrollFactor--; + if (scrollFactor < 0) { + scrollFactor = 0; + fakeScrollDownwards = true; + } + } + SetTransformation(1.0+2.0*scrollFactor/10, nsIntPoint(-25*scrollFactor, + -25*scrollFactor)); + printf_stderr("AsyncRender scroll factor:%d\n", scrollFactor); + AsyncRender(); + + CancelableTask *composeTask = NewRunnableMethod(this, &CompositorParent::TestScroll); + MessageLoop::current()->PostDelayedTask(FROM_HERE, composeTask, 1000/65); +} +#endif + PLayersParent* CompositorParent::AllocPLayers(const LayersBackend &backendType) { diff --git a/gfx/layers/ipc/CompositorParent.h b/gfx/layers/ipc/CompositorParent.h index 7a8b4d49a8f..511907c38d5 100644 --- a/gfx/layers/ipc/CompositorParent.h +++ b/gfx/layers/ipc/CompositorParent.h @@ -52,6 +52,26 @@ namespace layers { class LayerManager; +// Represents (affine) transforms that are calculated from a content view. +struct ViewTransform { + ViewTransform(nsIntPoint aTranslation = nsIntPoint(0, 0), float aXScale = 1, float aYScale = 1) + : mTranslation(aTranslation) + , mXScale(aXScale) + , mYScale(aYScale) + {} + + operator gfx3DMatrix() const + { + return + gfx3DMatrix::ScalingMatrix(mXScale, mYScale, 1) * + gfx3DMatrix::Translation(mTranslation.x, mTranslation.y, 0); + } + + nsIntPoint mTranslation; + float mXScale; + float mYScale; +}; + class CompositorParent : public PCompositorParent, public ShadowLayersManager { @@ -67,6 +87,9 @@ public: LayerManager* GetLayerManager() { return mLayerManager; } + void SetTransformation(float aScale, nsIntPoint aScrollOffset); + void AsyncRender(); + protected: virtual PLayersParent* AllocPLayers(const LayersBackend &backendType); virtual bool DeallocPLayers(PLayersParent* aLayers); @@ -74,6 +97,12 @@ protected: private: void ScheduleComposition(); void Composite(); +#ifdef OMTC_TEST_ASYNC_SCROLLING + void TestScroll(); +#endif + void TransformShadowTree(Layer* aLayer, const ViewTransform& aTransform, + float aTempScaleDiffX = 1.0, + float aTempScaleDiffY = 1.0); // Platform specific functions #ifdef MOZ_WIDGET_ANDROID @@ -88,6 +117,9 @@ private: nsRefPtr mLayerManager; bool mStopped; nsIWidget* mWidget; + float mXScale; + float mYScale; + nsIntPoint mScrollOffset; DISALLOW_EVIL_CONSTRUCTORS(CompositorParent); };