Bug 1157066. When reading back the OMTA transfrom of a layer don't include transforms from async panning or zooming. r=kats,birtles

Containerless scrolling means that the pan zoom controller applies it's transforms (to compensate for differences between the state of layout the last time we painted and the current state as composited to the screen) to the layers that are scrolled instead of the container layer that contains the layers that scroll.

When running test_animations_omta.html there is a zoom of 1.306122 applied, and the page is scrolled down to 67 screen pixels (before the test starts, not sure why exactly). Gecko scrolls as close to 67 screen pixels as it can: 67/1.306122 = 51.29689 css pixels, which is 3077.813 appunits. Gecko scrolls to 3078 app units. When AsyncCompositionManager::TransformScrollableLayer runs we calculate the scroll position of gecko and the current scroll position that the pan zoom controller is using. Since there are no async pan or zoom operations taking place these should match. However when the gecko scroll position is calculated we get 3078/60*1.306122 = 67.0040586. So it applies a transform of 0.0040586 to the container layer for the transform that test_animations_omta.html is animating off main thread. When test_animations_omta.html reads the transform of this layer it fails because it's expecting 0 and 0.0040586 is outside of it's epsilon for considering it to be close enough.
This commit is contained in:
Timothy Nikkel 2015-04-24 16:41:56 -05:00
parent 2f5b7f8767
commit c773a56c70
4 changed files with 36 additions and 34 deletions

View File

@ -1030,7 +1030,8 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer)
}
bool
AsyncCompositionManager::TransformShadowTree(TimeStamp aCurrentFrame)
AsyncCompositionManager::TransformShadowTree(TimeStamp aCurrentFrame,
TransformsToSkip aSkip)
{
PROFILER_LABEL("AsyncCompositionManager", "TransformShadowTree",
js::ProfileEntry::Category::GRAPHICS);
@ -1045,29 +1046,31 @@ AsyncCompositionManager::TransformShadowTree(TimeStamp aCurrentFrame)
// transforms.
bool wantNextFrame = SampleAnimations(root, aCurrentFrame);
// FIXME/bug 775437: unify this interface with the ~native-fennec
// derived code
//
// Attempt to apply an async content transform to any layer that has
// an async pan zoom controller (which means that it is rendered
// async using Gecko). If this fails, fall back to transforming the
// primary scrollable layer. "Failing" here means that we don't
// find a frame that is async scrollable. Note that the fallback
// code also includes Fennec which is rendered async. Fennec uses
// its own platform-specific async rendering that is done partially
// in Gecko and partially in Java.
wantNextFrame |= SampleAPZAnimations(LayerMetricsWrapper(root), aCurrentFrame);
if (!ApplyAsyncContentTransformToTree(root)) {
nsAutoTArray<Layer*,1> scrollableLayers;
if (!(aSkip & TransformsToSkip::APZ)) {
// FIXME/bug 775437: unify this interface with the ~native-fennec
// derived code
//
// Attempt to apply an async content transform to any layer that has
// an async pan zoom controller (which means that it is rendered
// async using Gecko). If this fails, fall back to transforming the
// primary scrollable layer. "Failing" here means that we don't
// find a frame that is async scrollable. Note that the fallback
// code also includes Fennec which is rendered async. Fennec uses
// its own platform-specific async rendering that is done partially
// in Gecko and partially in Java.
wantNextFrame |= SampleAPZAnimations(LayerMetricsWrapper(root), aCurrentFrame);
if (!ApplyAsyncContentTransformToTree(root)) {
nsAutoTArray<Layer*,1> scrollableLayers;
#ifdef MOZ_WIDGET_ANDROID
mLayerManager->GetRootScrollableLayers(scrollableLayers);
mLayerManager->GetRootScrollableLayers(scrollableLayers);
#else
mLayerManager->GetScrollableLayers(scrollableLayers);
mLayerManager->GetScrollableLayers(scrollableLayers);
#endif
for (uint32_t i = 0; i < scrollableLayers.Length(); i++) {
if (scrollableLayers[i]) {
TransformScrollableLayer(scrollableLayers[i]);
for (uint32_t i = 0; i < scrollableLayers.Length(); i++) {
if (scrollableLayers[i]) {
TransformScrollableLayer(scrollableLayers[i]);
}
}
}
}

View File

@ -95,7 +95,9 @@ public:
// Sample transforms for layer trees. Return true to request
// another animation frame.
bool TransformShadowTree(TimeStamp aCurrentFrame);
enum class TransformsToSkip : uint8_t { None = 0, APZ = 1 };
bool TransformShadowTree(TimeStamp aCurrentFrame,
TransformsToSkip aSkip = TransformsToSkip::None);
// Calculates the correct rotation and applies the transform to
// our layer manager
@ -208,6 +210,8 @@ private:
gfx::Matrix mWorldTransform;
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(AsyncCompositionManager::TransformsToSkip)
class MOZ_STACK_CLASS AutoResolveRefLayers {
public:
explicit AutoResolveRefLayers(AsyncCompositionManager* aManager) : mManager(aManager)

View File

@ -1152,12 +1152,6 @@ CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
if (mPaused) {
DidComposite();
}
// When testing we synchronously update the shadow tree with the animated
// values to avoid race conditions when calling GetAnimationTransform etc.
// (since the above SetShadowProperties will remove animation effects).
if (mIsTesting) {
ApplyAsyncProperties(aLayerTree);
}
}
mLayerManager->NotifyShadowTreeTransaction();
}
@ -1210,16 +1204,15 @@ CompositorParent::ApplyAsyncProperties(LayerTransactionParent* aLayerTree)
// true or when called from test-only methods like
// LayerTransactionParent::RecvGetAnimationTransform.
// Synchronously update the layer tree, but only if a composite was already
// scehduled.
if (aLayerTree->GetRoot() &&
(mCurrentCompositeTask ||
(mCompositorVsyncObserver &&
mCompositorVsyncObserver->NeedsComposite()))) {
// Synchronously update the layer tree
if (aLayerTree->GetRoot()) {
AutoResolveRefLayers resolve(mCompositionManager);
SetShadowProperties(mLayerManager->GetRoot());
TimeStamp time = mIsTesting ? mTestTime : mLastCompose;
bool requestNextFrame =
mCompositionManager->TransformShadowTree(time);
mCompositionManager->TransformShadowTree(time,
AsyncCompositionManager::TransformsToSkip::APZ);
if (!requestNextFrame) {
CancelCurrentCompositeTask();
// Pretend we composited in case someone is waiting for this event.

View File

@ -664,6 +664,8 @@ LayerTransactionParent::RecvGetOpacity(PLayerParent* aParent,
return false;
}
mShadowLayersManager->ApplyAsyncProperties(this);
*aOpacity = layer->GetLocalOpacity();
return true;
}