зеркало из https://github.com/mozilla/gecko-dev.git
Bug 983208 - Fix progressive tile update calculations. r=botond
A lot of this code used incorrect coordinate spaces or calculations that only worked because things were setup in a certain way. Now that the input data is more consistently correct and things have changed slightly, this code no longer worked. This patch reworks things to use what I think are the correct coordinate spaces and calculations, and should hopefully be less prone to breakage.
This commit is contained in:
Родитель
ee76ef609a
Коммит
d83c7c160e
|
@ -29,7 +29,7 @@ ClientTiledThebesLayer::ClientTiledThebesLayer(ClientLayerManager* const aManage
|
|||
, mContentClient()
|
||||
{
|
||||
MOZ_COUNT_CTOR(ClientTiledThebesLayer);
|
||||
mPaintData.mLastScrollOffset = ScreenPoint(0, 0);
|
||||
mPaintData.mLastScrollOffset = ParentLayerPoint(0, 0);
|
||||
mPaintData.mFirstPaint = true;
|
||||
}
|
||||
|
||||
|
@ -67,73 +67,106 @@ ClientTiledThebesLayer::BeginPaint()
|
|||
|
||||
mPaintData.mLowPrecisionPaintCount = 0;
|
||||
mPaintData.mPaintFinished = false;
|
||||
mPaintData.mCompositionBounds.SetEmpty();
|
||||
mPaintData.mCriticalDisplayPort.SetEmpty();
|
||||
|
||||
// Get the metrics of the nearest scroll container.
|
||||
if (!GetBaseTransform().Is2DIntegerTranslation()) {
|
||||
// Give up if the layer is transformed. The code below assumes that there
|
||||
// is no transform set, and not making that assumption would cause huge
|
||||
// complication to handle a quite rare case.
|
||||
//
|
||||
// FIXME The intention is to bail out of this function when there's a CSS
|
||||
// transform set on the layer, but unfortunately there's no way to
|
||||
// distinguish transforms due to scrolling from transforms due to
|
||||
// CSS transforms.
|
||||
//
|
||||
// Because of this, there may be unintended behaviour when setting
|
||||
// 2d CSS translations on the children of scrollable displayport
|
||||
// layers.
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the metrics of the nearest scrollable layer and the nearest layer
|
||||
// with a displayport.
|
||||
ContainerLayer* displayPortParent = nullptr;
|
||||
ContainerLayer* scrollParent = nullptr;
|
||||
for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
|
||||
const FrameMetrics& metrics = parent->GetFrameMetrics();
|
||||
if (metrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID) {
|
||||
if (!scrollParent && metrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID) {
|
||||
scrollParent = parent;
|
||||
}
|
||||
if (!metrics.mDisplayPort.IsEmpty()) {
|
||||
displayPortParent = parent;
|
||||
// Any layer that has a displayport must be scrollable, so we can break
|
||||
// here.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!scrollParent) {
|
||||
// XXX I don't think this can happen, but if it does, warn and set the
|
||||
// composition bounds to empty so that progressive updates are disabled.
|
||||
if (!displayPortParent || !scrollParent) {
|
||||
// No displayport or scroll parent, so we can't do progressive rendering.
|
||||
// Just set the composition bounds to empty and return.
|
||||
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_B2G)
|
||||
// Both Android and b2g are guaranteed to have a displayport set, so this
|
||||
// should never happen.
|
||||
NS_WARNING("Tiled Thebes layer with no scrollable container parent");
|
||||
mPaintData.mCompositionBounds.SetEmpty();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
const FrameMetrics& metrics = scrollParent->GetFrameMetrics();
|
||||
// Note, not handling transformed layers lets us assume that LayoutDevice
|
||||
// space of the scroll parent layer is the same as LayoutDevice space of
|
||||
// this layer.
|
||||
const FrameMetrics& scrollMetrics = scrollParent->GetFrameMetrics();
|
||||
const FrameMetrics& displayportMetrics = displayPortParent->GetFrameMetrics();
|
||||
|
||||
// Calculate the transform required to convert parent layer space into
|
||||
// transformed layout device space.
|
||||
gfx::Matrix4x4 effectiveTransform = GetEffectiveTransform();
|
||||
for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
|
||||
if (parent->UseIntermediateSurface()) {
|
||||
effectiveTransform = effectiveTransform * parent->GetEffectiveTransform();
|
||||
}
|
||||
// Calculate the transform required to convert ParentLayer space of our
|
||||
// display port parent to LayoutDevice space of this layer.
|
||||
gfx::Matrix4x4 transform = scrollParent->GetTransform();
|
||||
ContainerLayer* displayPortParentParent = displayPortParent->GetParent() ?
|
||||
displayPortParent->GetParent()->GetParent() : nullptr;
|
||||
for (ContainerLayer* parent = scrollParent->GetParent();
|
||||
parent != displayPortParentParent;
|
||||
parent = parent->GetParent()) {
|
||||
transform = transform * parent->GetTransform();
|
||||
}
|
||||
gfx3DMatrix layoutToParentLayer;
|
||||
gfx::To3DMatrix(effectiveTransform, layoutToParentLayer);
|
||||
layoutToParentLayer.ScalePost(metrics.GetParentResolution().scale,
|
||||
metrics.GetParentResolution().scale,
|
||||
1.f);
|
||||
gfx3DMatrix layoutDeviceToScrollParentLayer;
|
||||
gfx::To3DMatrix(transform, layoutDeviceToScrollParentLayer);
|
||||
layoutDeviceToScrollParentLayer.ScalePost(scrollMetrics.mCumulativeResolution.scale,
|
||||
scrollMetrics.mCumulativeResolution.scale,
|
||||
1.f);
|
||||
|
||||
mPaintData.mTransformParentLayerToLayout = layoutToParentLayer.Inverse();
|
||||
mPaintData.mTransformParentLayerToLayoutDevice = layoutDeviceToScrollParentLayer.Inverse();
|
||||
|
||||
// Compute the critical display port in layer space.
|
||||
mPaintData.mLayoutCriticalDisplayPort.SetEmpty();
|
||||
if (!metrics.mCriticalDisplayPort.IsEmpty()) {
|
||||
// Convert the display port to screen space first so that we can transform
|
||||
// it into layout device space.
|
||||
const ParentLayerRect& criticalDisplayPort = metrics.mCriticalDisplayPort
|
||||
* metrics.mDevPixelsPerCSSPixel
|
||||
* metrics.GetParentResolution();
|
||||
LayoutDeviceRect transformedCriticalDisplayPort =
|
||||
ApplyParentLayerToLayoutTransform(mPaintData.mTransformParentLayerToLayout, criticalDisplayPort);
|
||||
mPaintData.mLayoutCriticalDisplayPort =
|
||||
LayoutDeviceIntRect::ToUntyped(RoundedOut(transformedCriticalDisplayPort));
|
||||
}
|
||||
// Compute the critical display port of the display port layer in
|
||||
// LayoutDevice space of this layer.
|
||||
ParentLayerRect criticalDisplayPort =
|
||||
(displayportMetrics.mCriticalDisplayPort + displayportMetrics.GetScrollOffset()) *
|
||||
displayportMetrics.GetZoomToParent();
|
||||
mPaintData.mCriticalDisplayPort = LayoutDeviceIntRect::ToUntyped(RoundedOut(
|
||||
ApplyParentLayerToLayoutTransform(mPaintData.mTransformParentLayerToLayoutDevice,
|
||||
criticalDisplayPort)));
|
||||
|
||||
// Calculate the frame resolution. Because this is Gecko-side, before any
|
||||
// async transforms have occurred, we can use mZoom for this.
|
||||
mPaintData.mResolution = metrics.GetZoom();
|
||||
// Compute the viewport of the display port layer in LayoutDevice space of
|
||||
// this layer.
|
||||
ParentLayerRect viewport =
|
||||
(displayportMetrics.mViewport + displayportMetrics.GetScrollOffset()) *
|
||||
displayportMetrics.GetZoomToParent();
|
||||
mPaintData.mViewport = ApplyParentLayerToLayoutTransform(
|
||||
mPaintData.mTransformParentLayerToLayoutDevice, viewport);
|
||||
|
||||
// Calculate the scroll offset since the last transaction, and the
|
||||
// composition bounds.
|
||||
mPaintData.mCompositionBounds.SetEmpty();
|
||||
mPaintData.mScrollOffset.MoveTo(0, 0);
|
||||
Layer* primaryScrollable = ClientManager()->GetPrimaryScrollableLayer();
|
||||
if (primaryScrollable) {
|
||||
const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
|
||||
mPaintData.mScrollOffset = metrics.GetScrollOffset() * metrics.GetZoom();
|
||||
mPaintData.mCompositionBounds =
|
||||
ApplyParentLayerToLayoutTransform(mPaintData.mTransformParentLayerToLayout,
|
||||
ParentLayerRect(metrics.mCompositionBounds));
|
||||
}
|
||||
// Store the scroll parent resolution. Because this is Gecko-side, before any
|
||||
// async transforms have occurred, we can use the zoom for this.
|
||||
mPaintData.mResolution = displayportMetrics.GetZoomToParent();
|
||||
|
||||
// Store the parent composition bounds in LayoutDevice units.
|
||||
// This is actually in LayoutDevice units of the scrollParent's parent layer,
|
||||
// but because there is no transform, we can assume that these are the same.
|
||||
mPaintData.mCompositionBounds =
|
||||
scrollMetrics.mCompositionBounds / scrollMetrics.GetParentResolution();
|
||||
|
||||
// Calculate the scroll offset since the last transaction
|
||||
mPaintData.mScrollOffset = displayportMetrics.GetScrollOffset() * displayportMetrics.GetZoomToParent();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -213,15 +246,15 @@ ClientTiledThebesLayer::RenderLayer()
|
|||
// discarded on the first update.
|
||||
if (!ClientManager()->IsRepeatTransaction()) {
|
||||
mValidRegion.And(mValidRegion, mVisibleRegion);
|
||||
if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
|
||||
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
|
||||
// Make sure that tiles that fall outside of the critical displayport are
|
||||
// discarded on the first update.
|
||||
mValidRegion.And(mValidRegion, mPaintData.mLayoutCriticalDisplayPort);
|
||||
mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort);
|
||||
}
|
||||
}
|
||||
|
||||
nsIntRegion lowPrecisionInvalidRegion;
|
||||
if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
|
||||
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
|
||||
if (gfxPrefs::UseLowPrecisionBuffer()) {
|
||||
// Calculate the invalid region for the low precision buffer
|
||||
lowPrecisionInvalidRegion.Sub(mVisibleRegion, mLowPrecisionValidRegion);
|
||||
|
@ -232,7 +265,7 @@ ClientTiledThebesLayer::RenderLayer()
|
|||
}
|
||||
|
||||
// Clip the invalid region to the critical display-port
|
||||
invalidRegion.And(invalidRegion, mPaintData.mLayoutCriticalDisplayPort);
|
||||
invalidRegion.And(invalidRegion, mPaintData.mCriticalDisplayPort);
|
||||
if (invalidRegion.IsEmpty() && lowPrecisionInvalidRegion.IsEmpty()) {
|
||||
EndPaint(true);
|
||||
return;
|
||||
|
@ -250,8 +283,8 @@ ClientTiledThebesLayer::RenderLayer()
|
|||
// used to decide stale content (currently valid and previously visible)
|
||||
nsIntRegion oldValidRegion = mContentClient->mTiledBuffer.GetValidRegion();
|
||||
oldValidRegion.And(oldValidRegion, mVisibleRegion);
|
||||
if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
|
||||
oldValidRegion.And(oldValidRegion, mPaintData.mLayoutCriticalDisplayPort);
|
||||
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
|
||||
oldValidRegion.And(oldValidRegion, mPaintData.mCriticalDisplayPort);
|
||||
}
|
||||
|
||||
updatedBuffer =
|
||||
|
@ -261,8 +294,8 @@ ClientTiledThebesLayer::RenderLayer()
|
|||
} else {
|
||||
updatedBuffer = true;
|
||||
mValidRegion = mVisibleRegion;
|
||||
if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
|
||||
mValidRegion.And(mValidRegion, mPaintData.mLayoutCriticalDisplayPort);
|
||||
if (!mPaintData.mCriticalDisplayPort.IsEmpty()) {
|
||||
mValidRegion.And(mValidRegion, mPaintData.mCriticalDisplayPort);
|
||||
}
|
||||
mContentClient->mTiledBuffer.SetFrameResolution(mPaintData.mResolution);
|
||||
mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
|
||||
|
@ -292,7 +325,7 @@ ClientTiledThebesLayer::RenderLayer()
|
|||
// visible region is larger than the critical display port.
|
||||
bool updatedLowPrecision = false;
|
||||
if (!lowPrecisionInvalidRegion.IsEmpty() &&
|
||||
!nsIntRegion(mPaintData.mLayoutCriticalDisplayPort).Contains(mVisibleRegion)) {
|
||||
!nsIntRegion(mPaintData.mCriticalDisplayPort).Contains(mVisibleRegion)) {
|
||||
nsIntRegion oldValidRegion =
|
||||
mContentClient->mLowPrecisionTiledBuffer.GetValidRegion();
|
||||
oldValidRegion.And(oldValidRegion, mVisibleRegion);
|
||||
|
|
|
@ -248,9 +248,6 @@ SimpleClientTiledThebesLayer::SimpleClientTiledThebesLayer(ClientLayerManager* a
|
|||
, mContentClient()
|
||||
{
|
||||
MOZ_COUNT_CTOR(SimpleClientTiledThebesLayer);
|
||||
|
||||
mPaintData.mLastScrollOffset = ScreenPoint(0, 0);
|
||||
mPaintData.mFirstPaint = true;
|
||||
}
|
||||
|
||||
SimpleClientTiledThebesLayer::~SimpleClientTiledThebesLayer()
|
||||
|
@ -264,102 +261,6 @@ SimpleClientTiledThebesLayer::FillSpecificAttributes(SpecificLayerAttributes& aA
|
|||
aAttrs = ThebesLayerAttributes(GetValidRegion());
|
||||
}
|
||||
|
||||
static LayoutDeviceRect
|
||||
ApplyParentLayerToLayoutTransform(const gfx3DMatrix& aTransform, const ParentLayerRect& aParentLayerRect)
|
||||
{
|
||||
return TransformTo<LayoutDevicePixel>(aTransform, aParentLayerRect);
|
||||
}
|
||||
|
||||
void
|
||||
SimpleClientTiledThebesLayer::BeginPaint()
|
||||
{
|
||||
if (ClientManager()->IsRepeatTransaction()) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPaintData.mLowPrecisionPaintCount = 0;
|
||||
mPaintData.mPaintFinished = false;
|
||||
|
||||
// Get the metrics of the nearest scroll container.
|
||||
ContainerLayer* scrollParent = nullptr;
|
||||
for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
|
||||
const FrameMetrics& metrics = parent->GetFrameMetrics();
|
||||
if (metrics.GetScrollId() != FrameMetrics::NULL_SCROLL_ID) {
|
||||
scrollParent = parent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!scrollParent) {
|
||||
// XXX I don't think this can happen, but if it does, warn and set the
|
||||
// composition bounds to empty so that progressive updates are disabled.
|
||||
NS_WARNING("Tiled Thebes layer with no scrollable container parent");
|
||||
mPaintData.mCompositionBounds.SetEmpty();
|
||||
return;
|
||||
}
|
||||
|
||||
const FrameMetrics& metrics = scrollParent->GetFrameMetrics();
|
||||
|
||||
// Calculate the transform required to convert screen space into transformed
|
||||
// layout device space.
|
||||
gfx::Matrix4x4 effectiveTransform = GetEffectiveTransform();
|
||||
for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) {
|
||||
if (parent->UseIntermediateSurface()) {
|
||||
effectiveTransform = effectiveTransform * parent->GetEffectiveTransform();
|
||||
}
|
||||
}
|
||||
gfx3DMatrix layoutToParentLayer;
|
||||
gfx::To3DMatrix(effectiveTransform, layoutToParentLayer);
|
||||
layoutToParentLayer.ScalePost(metrics.GetParentResolution().scale,
|
||||
metrics.GetParentResolution().scale,
|
||||
1.f);
|
||||
|
||||
mPaintData.mTransformParentLayerToLayout = layoutToParentLayer.Inverse();
|
||||
|
||||
// Compute the critical display port in layer space.
|
||||
mPaintData.mLayoutCriticalDisplayPort.SetEmpty();
|
||||
if (!metrics.mCriticalDisplayPort.IsEmpty()) {
|
||||
// Convert the display port to screen space first so that we can transform
|
||||
// it into layout device space.
|
||||
const ParentLayerRect& criticalDisplayPort = metrics.mCriticalDisplayPort
|
||||
* metrics.mDevPixelsPerCSSPixel
|
||||
* metrics.GetParentResolution();
|
||||
LayoutDeviceRect transformedCriticalDisplayPort =
|
||||
ApplyParentLayerToLayoutTransform(mPaintData.mTransformParentLayerToLayout, criticalDisplayPort);
|
||||
mPaintData.mLayoutCriticalDisplayPort =
|
||||
LayoutDeviceIntRect::ToUntyped(RoundedOut(transformedCriticalDisplayPort));
|
||||
}
|
||||
|
||||
// Calculate the frame resolution. Because this is Gecko-side, before any
|
||||
// async transforms have occurred, we can use mZoom for this.
|
||||
mPaintData.mResolution = metrics.GetZoom();
|
||||
|
||||
// Calculate the scroll offset since the last transaction, and the
|
||||
// composition bounds.
|
||||
mPaintData.mCompositionBounds.SetEmpty();
|
||||
mPaintData.mScrollOffset.MoveTo(0, 0);
|
||||
Layer* primaryScrollable = ClientManager()->GetPrimaryScrollableLayer();
|
||||
if (primaryScrollable) {
|
||||
const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics();
|
||||
mPaintData.mScrollOffset = metrics.GetScrollOffset() * metrics.GetZoom();
|
||||
mPaintData.mCompositionBounds =
|
||||
ApplyParentLayerToLayoutTransform(mPaintData.mTransformParentLayerToLayout,
|
||||
ParentLayerRect(metrics.mCompositionBounds));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SimpleClientTiledThebesLayer::EndPaint(bool aFinish)
|
||||
{
|
||||
if (!aFinish && !mPaintData.mPaintFinished) {
|
||||
return;
|
||||
}
|
||||
|
||||
mPaintData.mLastScrollOffset = mPaintData.mScrollOffset;
|
||||
mPaintData.mPaintFinished = true;
|
||||
mPaintData.mFirstPaint = false;
|
||||
}
|
||||
|
||||
void
|
||||
SimpleClientTiledThebesLayer::RenderLayer()
|
||||
{
|
||||
|
@ -388,83 +289,29 @@ SimpleClientTiledThebesLayer::RenderLayer()
|
|||
nsIntRegion invalidRegion = mVisibleRegion;
|
||||
invalidRegion.Sub(invalidRegion, mValidRegion);
|
||||
if (invalidRegion.IsEmpty()) {
|
||||
EndPaint(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const FrameMetrics& parentMetrics = GetParent()->GetFrameMetrics();
|
||||
|
||||
nsIntRegion wantToPaintRegion = mVisibleRegion;
|
||||
|
||||
// Only paint the mask layer on the first transaction.
|
||||
if (GetMaskLayer() && !ClientManager()->IsRepeatTransaction()) {
|
||||
ToClientLayer(GetMaskLayer())->RenderLayer();
|
||||
}
|
||||
|
||||
// Fast path for no progressive updates, no low-precision updates and no
|
||||
// critical display-port set, or no display-port set.
|
||||
if (parentMetrics.mCriticalDisplayPort.IsEmpty() ||
|
||||
parentMetrics.mDisplayPort.IsEmpty())
|
||||
{
|
||||
mValidRegion = wantToPaintRegion;
|
||||
// SimpleTiledContentClient doesn't support progressive updates or the low
|
||||
// precision buffer yet.
|
||||
MOZ_ASSERT(!gfxPrefs::UseProgressiveTilePainting() &&
|
||||
!gfxPrefs::UseLowPrecisionBuffer());
|
||||
|
||||
NS_ASSERTION(!ClientManager()->IsRepeatTransaction(), "Didn't paint our mask layer");
|
||||
mValidRegion = mVisibleRegion;
|
||||
|
||||
mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
|
||||
callback, data);
|
||||
NS_ASSERTION(!ClientManager()->IsRepeatTransaction(), "Didn't paint our mask layer");
|
||||
|
||||
ClientManager()->Hold(this);
|
||||
mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
|
||||
callback, data);
|
||||
|
||||
mContentClient->UseTiledLayerBuffer();
|
||||
ClientManager()->Hold(this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate everything we need to perform the paint.
|
||||
BeginPaint();
|
||||
|
||||
if (mPaintData.mPaintFinished) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure that tiles that fall outside of the visible region are
|
||||
// discarded on the first update.
|
||||
if (!ClientManager()->IsRepeatTransaction()) {
|
||||
mValidRegion.And(mValidRegion, wantToPaintRegion);
|
||||
if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
|
||||
// Make sure that tiles that fall outside of the critical displayport are
|
||||
// discarded on the first update.
|
||||
mValidRegion.And(mValidRegion, mPaintData.mLayoutCriticalDisplayPort);
|
||||
}
|
||||
}
|
||||
|
||||
nsIntRegion lowPrecisionInvalidRegion;
|
||||
if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
|
||||
// Clip the invalid region to the critical display-port
|
||||
invalidRegion.And(invalidRegion, mPaintData.mLayoutCriticalDisplayPort);
|
||||
if (invalidRegion.IsEmpty() && lowPrecisionInvalidRegion.IsEmpty()) {
|
||||
EndPaint(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!invalidRegion.IsEmpty()) {
|
||||
mValidRegion = wantToPaintRegion;
|
||||
if (!mPaintData.mLayoutCriticalDisplayPort.IsEmpty()) {
|
||||
mValidRegion.And(mValidRegion, mPaintData.mLayoutCriticalDisplayPort);
|
||||
}
|
||||
mContentClient->mTiledBuffer.SetFrameResolution(mPaintData.mResolution);
|
||||
mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
|
||||
callback, data);
|
||||
|
||||
ClientManager()->Hold(this);
|
||||
mContentClient->UseTiledLayerBuffer();
|
||||
|
||||
EndPaint(false);
|
||||
return;
|
||||
}
|
||||
|
||||
EndPaint(false);
|
||||
mContentClient->UseTiledLayerBuffer();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -106,8 +106,8 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
const CSSToScreenScale& GetFrameResolution() const { return mFrameResolution; }
|
||||
void SetFrameResolution(const CSSToScreenScale& aResolution) { mFrameResolution = aResolution; }
|
||||
const CSSToParentLayerScale& GetFrameResolution() const { return mFrameResolution; }
|
||||
void SetFrameResolution(const CSSToParentLayerScale& aResolution) { mFrameResolution = aResolution; }
|
||||
|
||||
bool HasFormatChanged() const;
|
||||
private:
|
||||
|
@ -116,7 +116,7 @@ private:
|
|||
ClientLayerManager* mManager;
|
||||
LayerManager::DrawThebesLayerCallback mCallback;
|
||||
void* mCallbackData;
|
||||
CSSToScreenScale mFrameResolution;
|
||||
CSSToParentLayerScale mFrameResolution;
|
||||
bool mLastPaintOpaque;
|
||||
|
||||
gfxContentType GetContentType() const;
|
||||
|
@ -180,11 +180,7 @@ public:
|
|||
protected:
|
||||
ClientLayerManager* ClientManager() { return static_cast<ClientLayerManager*>(mManager); }
|
||||
|
||||
void BeginPaint();
|
||||
void EndPaint(bool aFinish);
|
||||
|
||||
RefPtr<SimpleTiledContentClient> mContentClient;
|
||||
BasicTiledLayerPaintData mPaintData;
|
||||
};
|
||||
|
||||
} // mozilla
|
||||
|
|
|
@ -861,18 +861,18 @@ ClientTiledLayerBuffer::ValidateTile(TileClient aTile,
|
|||
static LayoutDeviceRect
|
||||
TransformCompositionBounds(const ParentLayerRect& aCompositionBounds,
|
||||
const CSSToParentLayerScale& aZoom,
|
||||
const ScreenPoint& aScrollOffset,
|
||||
const CSSToScreenScale& aResolution,
|
||||
const gfx3DMatrix& aTransformScreenToLayout)
|
||||
const ParentLayerPoint& aScrollOffset,
|
||||
const CSSToParentLayerScale& aResolution,
|
||||
const gfx3DMatrix& aTransformParentLayerToLayoutDevice)
|
||||
{
|
||||
// Transform the current composition bounds into transformed layout device
|
||||
// space by compensating for the difference in resolution and subtracting the
|
||||
// Transform the current composition bounds into ParentLayer coordinates
|
||||
// by compensating for the difference in resolution and subtracting the
|
||||
// old composition bounds origin.
|
||||
ScreenRect offsetViewportRect = (aCompositionBounds / aZoom) * aResolution;
|
||||
ParentLayerRect offsetViewportRect = (aCompositionBounds / aZoom) * aResolution;
|
||||
offsetViewportRect.MoveBy(-aScrollOffset);
|
||||
|
||||
gfxRect transformedViewport =
|
||||
aTransformScreenToLayout.TransformBounds(
|
||||
aTransformParentLayerToLayoutDevice.TransformBounds(
|
||||
gfxRect(offsetViewportRect.x, offsetViewportRect.y,
|
||||
offsetViewportRect.width, offsetViewportRect.height));
|
||||
|
||||
|
@ -884,10 +884,10 @@ TransformCompositionBounds(const ParentLayerRect& aCompositionBounds,
|
|||
|
||||
bool
|
||||
ClientTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvalidRegion,
|
||||
const nsIntRegion& aOldValidRegion,
|
||||
nsIntRegion& aRegionToPaint,
|
||||
BasicTiledLayerPaintData* aPaintData,
|
||||
bool aIsRepeated)
|
||||
const nsIntRegion& aOldValidRegion,
|
||||
nsIntRegion& aRegionToPaint,
|
||||
BasicTiledLayerPaintData* aPaintData,
|
||||
bool aIsRepeated)
|
||||
{
|
||||
aRegionToPaint = aInvalidRegion;
|
||||
|
||||
|
@ -942,20 +942,27 @@ ClientTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInval
|
|||
}
|
||||
}
|
||||
|
||||
// Transform the screen coordinates into transformed layout device coordinates.
|
||||
// Transform the composition bounds, which is in the ParentLayer coordinates
|
||||
// of the nearest ContainerLayer with a valid displayport to LayoutDevice
|
||||
// coordinates relative to this layer.
|
||||
LayoutDeviceRect transformedCompositionBounds =
|
||||
TransformCompositionBounds(compositionBounds, zoom, aPaintData->mScrollOffset,
|
||||
aPaintData->mResolution, aPaintData->mTransformParentLayerToLayout);
|
||||
aPaintData->mResolution, aPaintData->mTransformParentLayerToLayoutDevice);
|
||||
|
||||
// Paint tiles that have stale content or that intersected with the screen
|
||||
// at the time of issuing the draw command in a single transaction first.
|
||||
// This is to avoid rendering glitches on animated page content, and when
|
||||
// layers change size/shape.
|
||||
LayoutDeviceRect coherentUpdateRect =
|
||||
LayoutDeviceRect typedCoherentUpdateRect =
|
||||
transformedCompositionBounds.Intersect(aPaintData->mCompositionBounds);
|
||||
|
||||
// Offset by the viewport origin, as the composition bounds are stored in
|
||||
// Layer space and not LayoutDevice space.
|
||||
typedCoherentUpdateRect.MoveBy(aPaintData->mViewport.TopLeft());
|
||||
|
||||
// Convert to untyped to intersect with the invalid region.
|
||||
nsIntRect roundedCoherentUpdateRect =
|
||||
LayoutDeviceIntRect::ToUntyped(RoundedOut(coherentUpdateRect));
|
||||
LayoutDeviceIntRect::ToUntyped(RoundedOut(typedCoherentUpdateRect));
|
||||
|
||||
aRegionToPaint.And(aInvalidRegion, roundedCoherentUpdateRect);
|
||||
aRegionToPaint.Or(aRegionToPaint, staleRegion);
|
||||
|
|
|
@ -244,41 +244,46 @@ struct BasicTiledLayerPaintData {
|
|||
* The scroll offset of the content from the nearest ancestor layer that
|
||||
* represents scrollable content with a display port set.
|
||||
*/
|
||||
ScreenPoint mScrollOffset;
|
||||
ParentLayerPoint mScrollOffset;
|
||||
|
||||
/*
|
||||
* The scroll offset of the content from the nearest ancestor layer that
|
||||
* represents scrollable content with a display port set, for the last
|
||||
* layer update transaction.
|
||||
*/
|
||||
ScreenPoint mLastScrollOffset;
|
||||
ParentLayerPoint mLastScrollOffset;
|
||||
|
||||
/*
|
||||
* The transform matrix to go from ParentLayer units to transformed
|
||||
* LayoutDevice units.
|
||||
* The transform matrix to go from Screen units to ParentLayer units.
|
||||
*/
|
||||
gfx3DMatrix mTransformParentLayerToLayout;
|
||||
gfx3DMatrix mTransformParentLayerToLayoutDevice;
|
||||
|
||||
/*
|
||||
* The critical displayport of the content from the nearest ancestor layer
|
||||
* that represents scrollable content with a display port set. Empty if a
|
||||
* critical displayport is not set.
|
||||
*
|
||||
* This is in transformed LayoutDevice coordinates, but is stored as an
|
||||
* nsIntRect for convenience when intersecting with the layer's mValidRegion.
|
||||
* This is in LayoutDevice coordinates, but is stored as an nsIntRect for
|
||||
* convenience when intersecting with the layer's mValidRegion.
|
||||
*/
|
||||
nsIntRect mLayoutCriticalDisplayPort;
|
||||
nsIntRect mCriticalDisplayPort;
|
||||
|
||||
/*
|
||||
* The viewport of the content from the nearest ancestor layer that
|
||||
* represents scrollable content with a display port set.
|
||||
*/
|
||||
LayoutDeviceRect mViewport;
|
||||
|
||||
/*
|
||||
* The render resolution of the document that the content this layer
|
||||
* represents is in.
|
||||
*/
|
||||
CSSToScreenScale mResolution;
|
||||
CSSToParentLayerScale mResolution;
|
||||
|
||||
/*
|
||||
* The composition bounds of the primary scrollable layer, in transformed
|
||||
* layout device coordinates. This is used to make sure that tiled updates to
|
||||
* regions that are visible to the user are grouped coherently.
|
||||
* The composition bounds of the layer, in LayoutDevice coordinates. This is
|
||||
* used to make sure that tiled updates to regions that are visible to the
|
||||
* user are grouped coherently.
|
||||
*/
|
||||
LayoutDeviceRect mCompositionBounds;
|
||||
|
||||
|
@ -381,9 +386,9 @@ public:
|
|||
|
||||
void DiscardBackBuffers();
|
||||
|
||||
const CSSToScreenScale& GetFrameResolution() { return mFrameResolution; }
|
||||
const CSSToParentLayerScale& GetFrameResolution() { return mFrameResolution; }
|
||||
|
||||
void SetFrameResolution(const CSSToScreenScale& aResolution) { mFrameResolution = aResolution; }
|
||||
void SetFrameResolution(const CSSToParentLayerScale& aResolution) { mFrameResolution = aResolution; }
|
||||
|
||||
bool HasFormatChanged() const;
|
||||
|
||||
|
@ -424,7 +429,7 @@ private:
|
|||
ClientLayerManager* mManager;
|
||||
LayerManager::DrawThebesLayerCallback mCallback;
|
||||
void* mCallbackData;
|
||||
CSSToScreenScale mFrameResolution;
|
||||
CSSToParentLayerScale mFrameResolution;
|
||||
bool mLastPaintOpaque;
|
||||
|
||||
// The DrawTarget we use when UseSinglePaintBuffer() above is true.
|
||||
|
|
|
@ -42,7 +42,7 @@ TiledLayerBufferComposite::TiledLayerBufferComposite(ISurfaceAllocator* aAllocat
|
|||
mRetainedWidth = aDescriptor.retainedWidth();
|
||||
mRetainedHeight = aDescriptor.retainedHeight();
|
||||
mResolution = aDescriptor.resolution();
|
||||
mFrameResolution = CSSToScreenScale(aDescriptor.frameResolution());
|
||||
mFrameResolution = CSSToParentLayerScale(aDescriptor.frameResolution());
|
||||
|
||||
// Combine any valid content that wasn't already uploaded
|
||||
nsIntRegion oldPaintedRegion(aOldPaintedRegion);
|
||||
|
@ -379,8 +379,8 @@ TiledContentHost::RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer,
|
|||
// We assume that the current frame resolution is the one used in our primary
|
||||
// layer buffer. Compensate for a changing frame resolution.
|
||||
if (aLayerBuffer.GetFrameResolution() != mTiledBuffer.GetFrameResolution()) {
|
||||
const CSSToScreenScale& layerResolution = aLayerBuffer.GetFrameResolution();
|
||||
const CSSToScreenScale& localResolution = mTiledBuffer.GetFrameResolution();
|
||||
const CSSToParentLayerScale& layerResolution = aLayerBuffer.GetFrameResolution();
|
||||
const CSSToParentLayerScale& localResolution = mTiledBuffer.GetFrameResolution();
|
||||
layerScale.width = layerScale.height = layerResolution.scale / localResolution.scale;
|
||||
aVisibleRect.ScaleRoundOut(layerScale.width, layerScale.height);
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ public:
|
|||
|
||||
// Stores the absolute resolution of the containing frame, calculated
|
||||
// by the sum of the resolutions of all parent layers' FrameMetrics.
|
||||
const CSSToScreenScale& GetFrameResolution() { return mFrameResolution; }
|
||||
const CSSToParentLayerScale& GetFrameResolution() { return mFrameResolution; }
|
||||
|
||||
void ReadUnlock();
|
||||
|
||||
|
@ -144,7 +144,7 @@ protected:
|
|||
void SwapTiles(TileHost& aTileA, TileHost& aTileB) { std::swap(aTileA, aTileB); }
|
||||
|
||||
private:
|
||||
CSSToScreenScale mFrameResolution;
|
||||
CSSToParentLayerScale mFrameResolution;
|
||||
bool mHasDoubleBufferedTiles;
|
||||
bool mUninitialized;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче