зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1006084 - Allow ThebesLayers to be recreated when the creation hint changes. r=mattwoodrow
This commit is contained in:
Родитель
0bfb7d3b01
Коммит
ffcda6a27d
|
@ -357,6 +357,13 @@ public:
|
|||
NONE, SCROLLABLE
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns true if aLayer is optimized for the given ThebesLayerCreationHint.
|
||||
*/
|
||||
virtual bool IsOptimizedFor(ThebesLayer* aLayer,
|
||||
ThebesLayerCreationHint aCreationHint)
|
||||
{ return true; }
|
||||
|
||||
/**
|
||||
* CONSTRUCTION PHASE ONLY
|
||||
* Create a ThebesLayer for this manager's layer tree.
|
||||
|
@ -1549,6 +1556,8 @@ public:
|
|||
ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
|
||||
}
|
||||
|
||||
LayerManager::ThebesLayerCreationHint GetCreationHint() const { return mCreationHint; }
|
||||
|
||||
bool UsedForReadback() { return mUsedForReadback; }
|
||||
void SetUsedForReadback(bool aUsed) { mUsedForReadback = aUsed; }
|
||||
/**
|
||||
|
@ -1562,9 +1571,11 @@ public:
|
|||
gfxPoint GetResidualTranslation() const { return mResidualTranslation; }
|
||||
|
||||
protected:
|
||||
ThebesLayer(LayerManager* aManager, void* aImplData)
|
||||
ThebesLayer(LayerManager* aManager, void* aImplData,
|
||||
LayerManager::ThebesLayerCreationHint aCreationHint = LayerManager::NONE)
|
||||
: Layer(aManager, aImplData)
|
||||
, mValidRegion()
|
||||
, mCreationHint(aCreationHint)
|
||||
, mUsedForReadback(false)
|
||||
, mAllowResidualTranslation(false)
|
||||
{
|
||||
|
@ -1580,6 +1591,10 @@ protected:
|
|||
*/
|
||||
gfxPoint mResidualTranslation;
|
||||
nsIntRegion mValidRegion;
|
||||
/**
|
||||
* The creation hint that was used when constructing this layer.
|
||||
*/
|
||||
const LayerManager::ThebesLayerCreationHint mCreationHint;
|
||||
/**
|
||||
* Set when this ThebesLayer is participating in readback, i.e. some
|
||||
* ReadbackLayer (may) be getting its background from this layer.
|
||||
|
|
|
@ -73,6 +73,8 @@ public:
|
|||
|
||||
virtual void Mutated(Layer* aLayer);
|
||||
|
||||
virtual bool IsOptimizedFor(ThebesLayer* aLayer, ThebesLayerCreationHint aHint);
|
||||
|
||||
virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
|
||||
virtual already_AddRefed<ThebesLayer> CreateThebesLayerWithHint(ThebesLayerCreationHint aHint);
|
||||
virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
|
||||
|
|
|
@ -127,6 +127,22 @@ ClientThebesLayer::RenderLayer()
|
|||
mContentClient->EndPaint();
|
||||
}
|
||||
|
||||
bool
|
||||
ClientLayerManager::IsOptimizedFor(ThebesLayer* aLayer, ThebesLayerCreationHint aHint)
|
||||
{
|
||||
#ifdef MOZ_B2G
|
||||
// The only creation hint is whether the layer is scrollable or not, and this
|
||||
// is only respected on B2G, where it's used to determine whether to use
|
||||
// tiled layers or not.
|
||||
// There are pretty nasty performance consequences for not using tiles on
|
||||
// large, scrollable layers, so we want the layer to be recreated in this
|
||||
// situation.
|
||||
return aHint == aLayer->GetCreationHint();
|
||||
#else
|
||||
return LayerManager::IsOptimizedFor(aLayer, aHint);
|
||||
#endif
|
||||
}
|
||||
|
||||
already_AddRefed<ThebesLayer>
|
||||
ClientLayerManager::CreateThebesLayer()
|
||||
{
|
||||
|
@ -150,19 +166,19 @@ ClientLayerManager::CreateThebesLayerWithHint(ThebesLayerCreationHint aHint)
|
|||
}
|
||||
if (gfxPrefs::LayersUseSimpleTiles()) {
|
||||
nsRefPtr<SimpleClientTiledThebesLayer> layer =
|
||||
new SimpleClientTiledThebesLayer(this);
|
||||
new SimpleClientTiledThebesLayer(this, aHint);
|
||||
CREATE_SHADOW(Thebes);
|
||||
return layer.forget();
|
||||
} else {
|
||||
nsRefPtr<ClientTiledThebesLayer> layer =
|
||||
new ClientTiledThebesLayer(this);
|
||||
new ClientTiledThebesLayer(this, aHint);
|
||||
CREATE_SHADOW(Thebes);
|
||||
return layer.forget();
|
||||
}
|
||||
} else
|
||||
{
|
||||
nsRefPtr<ClientThebesLayer> layer =
|
||||
new ClientThebesLayer(this);
|
||||
new ClientThebesLayer(this, aHint);
|
||||
CREATE_SHADOW(Thebes);
|
||||
return layer.forget();
|
||||
}
|
||||
|
|
|
@ -27,15 +27,17 @@ class CompositableClient;
|
|||
class ShadowableLayer;
|
||||
class SpecificLayerAttributes;
|
||||
|
||||
class ClientThebesLayer : public ThebesLayer,
|
||||
class ClientThebesLayer : public ThebesLayer,
|
||||
public ClientLayer {
|
||||
public:
|
||||
typedef RotatedContentBuffer::PaintState PaintState;
|
||||
typedef RotatedContentBuffer::ContentType ContentType;
|
||||
|
||||
ClientThebesLayer(ClientLayerManager* aLayerManager) :
|
||||
ClientThebesLayer(ClientLayerManager* aLayerManager,
|
||||
LayerManager::ThebesLayerCreationHint aCreationHint = LayerManager::NONE) :
|
||||
ThebesLayer(aLayerManager,
|
||||
static_cast<ClientLayer*>(MOZ_THIS_IN_INITIALIZER_LIST())),
|
||||
static_cast<ClientLayer*>(MOZ_THIS_IN_INITIALIZER_LIST()),
|
||||
aCreationHint),
|
||||
mContentClient(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ClientThebesLayer);
|
||||
|
|
|
@ -29,9 +29,11 @@ namespace mozilla {
|
|||
namespace layers {
|
||||
|
||||
|
||||
ClientTiledThebesLayer::ClientTiledThebesLayer(ClientLayerManager* const aManager)
|
||||
ClientTiledThebesLayer::ClientTiledThebesLayer(ClientLayerManager* const aManager,
|
||||
ClientLayerManager::ThebesLayerCreationHint aCreationHint)
|
||||
: ThebesLayer(aManager,
|
||||
static_cast<ClientLayer*>(MOZ_THIS_IN_INITIALIZER_LIST()))
|
||||
static_cast<ClientLayer*>(MOZ_THIS_IN_INITIALIZER_LIST()),
|
||||
aCreationHint)
|
||||
, mContentClient()
|
||||
{
|
||||
MOZ_COUNT_CTOR(ClientTiledThebesLayer);
|
||||
|
|
|
@ -41,7 +41,8 @@ class ClientTiledThebesLayer : public ThebesLayer,
|
|||
typedef ThebesLayer Base;
|
||||
|
||||
public:
|
||||
ClientTiledThebesLayer(ClientLayerManager* const aManager);
|
||||
ClientTiledThebesLayer(ClientLayerManager* const aManager,
|
||||
ClientLayerManager::ThebesLayerCreationHint aCreationHint = LayerManager::NONE);
|
||||
~ClientTiledThebesLayer();
|
||||
|
||||
// Override name to distinguish it from ClientThebesLayer in layer dumps
|
||||
|
|
|
@ -247,9 +247,11 @@ SimpleTiledContentClient::UseTiledLayerBuffer()
|
|||
mTiledBuffer.ClearPaintedRegion();
|
||||
}
|
||||
|
||||
SimpleClientTiledThebesLayer::SimpleClientTiledThebesLayer(ClientLayerManager* aManager)
|
||||
SimpleClientTiledThebesLayer::SimpleClientTiledThebesLayer(ClientLayerManager* aManager,
|
||||
ClientLayerManager::ThebesLayerCreationHint aCreationHint)
|
||||
: ThebesLayer(aManager,
|
||||
static_cast<ClientLayer*>(MOZ_THIS_IN_INITIALIZER_LIST()))
|
||||
static_cast<ClientLayer*>(MOZ_THIS_IN_INITIALIZER_LIST()),
|
||||
aCreationHint)
|
||||
, mContentClient()
|
||||
{
|
||||
MOZ_COUNT_CTOR(SimpleClientTiledThebesLayer);
|
||||
|
|
|
@ -159,7 +159,8 @@ class SimpleClientTiledThebesLayer : public ThebesLayer,
|
|||
typedef ThebesLayer Base;
|
||||
|
||||
public:
|
||||
SimpleClientTiledThebesLayer(ClientLayerManager* const aManager);
|
||||
SimpleClientTiledThebesLayer(ClientLayerManager* const aManager,
|
||||
ClientLayerManager::ThebesLayerCreationHint aCreationHint = LayerManager::NONE);
|
||||
~SimpleClientTiledThebesLayer();
|
||||
|
||||
// Thebes Layer
|
||||
|
|
|
@ -1446,74 +1446,85 @@ ContainerState::CreateOrRecycleThebesLayer(const nsIFrame* aAnimatedGeometryRoot
|
|||
// We need a new thebes layer
|
||||
nsRefPtr<ThebesLayer> layer;
|
||||
ThebesDisplayItemLayerUserData* data;
|
||||
bool layerRecycled = false;
|
||||
#ifndef MOZ_ANDROID_OMTC
|
||||
bool didResetScrollPositionForLayerPixelAlignment = false;
|
||||
#endif
|
||||
|
||||
// Check whether the layer will be scrollable. This is used as a hint to
|
||||
// influence whether tiled layers are used or not.
|
||||
LayerManager::ThebesLayerCreationHint creationHint = LayerManager::NONE;
|
||||
nsIFrame* animatedGeometryRootParent = aAnimatedGeometryRoot->GetParent();
|
||||
if (animatedGeometryRootParent &&
|
||||
animatedGeometryRootParent->GetType() == nsGkAtoms::scrollFrame) {
|
||||
creationHint = LayerManager::SCROLLABLE;
|
||||
}
|
||||
|
||||
if (mNextFreeRecycledThebesLayer < mRecycledThebesLayers.Length()) {
|
||||
// Recycle a layer
|
||||
// Try to recycle a layer
|
||||
layer = mRecycledThebesLayers[mNextFreeRecycledThebesLayer];
|
||||
++mNextFreeRecycledThebesLayer;
|
||||
// Clear clip rect and mask layer so we don't accidentally stay clipped.
|
||||
// We will reapply any necessary clipping.
|
||||
layer->SetMaskLayer(nullptr);
|
||||
|
||||
data = static_cast<ThebesDisplayItemLayerUserData*>
|
||||
(layer->GetUserData(&gThebesDisplayItemLayerUserData));
|
||||
NS_ASSERTION(data, "Recycled ThebesLayers must have user data");
|
||||
// Check if the layer hint has changed and whether or not the layer should
|
||||
// be recreated because of it.
|
||||
if (mManager->IsOptimizedFor(layer->AsThebesLayer(), creationHint)) {
|
||||
layerRecycled = true;
|
||||
|
||||
// This gets called on recycled ThebesLayers that are going to be in the
|
||||
// final layer tree, so it's a convenient time to invalidate the
|
||||
// content that changed where we don't know what ThebesLayer it belonged
|
||||
// to, or if we need to invalidate the entire layer, we can do that.
|
||||
// This needs to be done before we update the ThebesLayer to its new
|
||||
// transform. See nsGfxScrollFrame::InvalidateInternal, where
|
||||
// we ensure that mInvalidThebesContent is updated according to the
|
||||
// scroll position as of the most recent paint.
|
||||
if (!FuzzyEqual(data->mXScale, mParameters.mXScale, 0.00001f) ||
|
||||
!FuzzyEqual(data->mYScale, mParameters.mYScale, 0.00001f) ||
|
||||
data->mAppUnitsPerDevPixel != mAppUnitsPerDevPixel) {
|
||||
// Clear clip rect and mask layer so we don't accidentally stay clipped.
|
||||
// We will reapply any necessary clipping.
|
||||
layer->SetMaskLayer(nullptr);
|
||||
|
||||
data = static_cast<ThebesDisplayItemLayerUserData*>
|
||||
(layer->GetUserData(&gThebesDisplayItemLayerUserData));
|
||||
NS_ASSERTION(data, "Recycled ThebesLayers must have user data");
|
||||
|
||||
// This gets called on recycled ThebesLayers that are going to be in the
|
||||
// final layer tree, so it's a convenient time to invalidate the
|
||||
// content that changed where we don't know what ThebesLayer it belonged
|
||||
// to, or if we need to invalidate the entire layer, we can do that.
|
||||
// This needs to be done before we update the ThebesLayer to its new
|
||||
// transform. See nsGfxScrollFrame::InvalidateInternal, where
|
||||
// we ensure that mInvalidThebesContent is updated according to the
|
||||
// scroll position as of the most recent paint.
|
||||
if (!FuzzyEqual(data->mXScale, mParameters.mXScale, 0.00001f) ||
|
||||
!FuzzyEqual(data->mYScale, mParameters.mYScale, 0.00001f) ||
|
||||
data->mAppUnitsPerDevPixel != mAppUnitsPerDevPixel) {
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
|
||||
printf_stderr("Recycled layer %p changed scale\n", layer.get());
|
||||
}
|
||||
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
|
||||
printf_stderr("Recycled layer %p changed scale\n", layer.get());
|
||||
}
|
||||
#endif
|
||||
InvalidateEntireThebesLayer(layer, aAnimatedGeometryRoot);
|
||||
InvalidateEntireThebesLayer(layer, aAnimatedGeometryRoot);
|
||||
#ifndef MOZ_ANDROID_OMTC
|
||||
didResetScrollPositionForLayerPixelAlignment = true;
|
||||
didResetScrollPositionForLayerPixelAlignment = true;
|
||||
#endif
|
||||
}
|
||||
if (!data->mRegionToInvalidate.IsEmpty()) {
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
|
||||
printf_stderr("Invalidating deleted frame content from layer %p\n", layer.get());
|
||||
}
|
||||
#endif
|
||||
layer->InvalidateRegion(data->mRegionToInvalidate);
|
||||
if (!data->mRegionToInvalidate.IsEmpty()) {
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
|
||||
nsAutoCString str;
|
||||
AppendToString(str, data->mRegionToInvalidate);
|
||||
printf_stderr("Invalidating layer %p: %s\n", layer.get(), str.get());
|
||||
}
|
||||
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
|
||||
printf_stderr("Invalidating deleted frame content from layer %p\n", layer.get());
|
||||
}
|
||||
#endif
|
||||
data->mRegionToInvalidate.SetEmpty();
|
||||
}
|
||||
layer->InvalidateRegion(data->mRegionToInvalidate);
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
|
||||
nsAutoCString str;
|
||||
AppendToString(str, data->mRegionToInvalidate);
|
||||
printf_stderr("Invalidating layer %p: %s\n", layer.get(), str.get());
|
||||
}
|
||||
#endif
|
||||
data->mRegionToInvalidate.SetEmpty();
|
||||
}
|
||||
|
||||
// We do not need to Invalidate these areas in the widget because we
|
||||
// assume the caller of InvalidateThebesLayerContents has ensured
|
||||
// the area is invalidated in the widget.
|
||||
} else {
|
||||
// Check whether the layer will be scrollable. This is used as a hint to
|
||||
// influence whether tiled layers are used or not.
|
||||
bool canScroll = false;
|
||||
nsIFrame* animatedGeometryRootParent = aAnimatedGeometryRoot->GetParent();
|
||||
if (animatedGeometryRootParent &&
|
||||
animatedGeometryRootParent->GetType() == nsGkAtoms::scrollFrame) {
|
||||
canScroll = true;
|
||||
// We do not need to Invalidate these areas in the widget because we
|
||||
// assume the caller of InvalidateThebesLayerContents has ensured
|
||||
// the area is invalidated in the widget.
|
||||
}
|
||||
}
|
||||
|
||||
if (!layerRecycled) {
|
||||
// Create a new thebes layer
|
||||
layer = mManager->CreateThebesLayerWithHint(canScroll ? LayerManager::SCROLLABLE :
|
||||
LayerManager::NONE);
|
||||
layer = mManager->CreateThebesLayerWithHint(creationHint);
|
||||
if (!layer)
|
||||
return nullptr;
|
||||
// Mark this layer as being used for Thebes-painting display items
|
||||
|
|
Загрузка…
Ссылка в новой задаче