Bug 1163878 (Part 2) - Use IsImageContainerAvailable() when making layerization decisions and only call GetImageContainer() if we layerize. r=tn

This commit is contained in:
Seth Fowler 2015-05-13 00:23:46 -07:00
parent 23ee589538
commit f8b4b72216
9 changed files with 261 additions and 91 deletions

View File

@ -350,11 +350,17 @@ public:
}
/**
* If this represents only a nsDisplayImage, and the image type
* supports being optimized to an ImageLayer (TYPE_RASTER only) returns
* an ImageContainer for the image.
* If this represents only a nsDisplayImage, and the image type supports being
* optimized to an ImageLayer, returns true.
*/
already_AddRefed<ImageContainer> CanOptimizeImageLayer(nsDisplayListBuilder* aBuilder);
bool CanOptimizeToImageLayer(nsDisplayListBuilder* aBuilder);
/**
* If this represents only a nsDisplayImage, and the image type supports being
* optimized to an ImageLayer, returns an ImageContainer for the underlying
* image if one is available.
*/
already_AddRefed<ImageContainer> GetContainerForImageLayer(nsDisplayListBuilder* aBuilder);
bool VisibleAboveRegionIntersects(const nsIntRect& aRect) const
{ return mVisibleAboveRegion.Intersects(aRect); }
@ -1051,6 +1057,19 @@ protected:
const nsIFrame* aReferenceFrame,
const nsPoint& aTopLeft,
bool aDidResetScrollPositionForLayerPixelAlignment);
/**
* Attempt to prepare an ImageLayer based upon the provided PaintedLayerData.
* Returns nullptr on failure.
*/
already_AddRefed<Layer> PrepareImageLayer(PaintedLayerData* aData);
/**
* Attempt to prepare a ColorLayer based upon the provided PaintedLayerData.
* Returns nullptr on failure.
*/
already_AddRefed<Layer> PrepareColorLayer(PaintedLayerData* aData);
/**
* Grab the next recyclable ColorLayer, or create one if there are no
* more recyclable ColorLayers.
@ -2352,8 +2371,18 @@ PaintedLayerData::UpdateCommonClipCount(
}
}
bool
PaintedLayerData::CanOptimizeToImageLayer(nsDisplayListBuilder* aBuilder)
{
if (!mImage) {
return nullptr;
}
return mImage->CanOptimizeToImageLayer(mLayer->Manager(), aBuilder);
}
already_AddRefed<ImageContainer>
PaintedLayerData::CanOptimizeImageLayer(nsDisplayListBuilder* aBuilder)
PaintedLayerData::GetContainerForImageLayer(nsDisplayListBuilder* aBuilder)
{
if (!mImage) {
return nullptr;
@ -2786,6 +2815,58 @@ static int32_t FindIndexOfLayerIn(nsTArray<NewLayerEntry>& aArray,
}
#endif
already_AddRefed<Layer>
ContainerState::PrepareImageLayer(PaintedLayerData* aData)
{
nsRefPtr<ImageContainer> imageContainer =
aData->GetContainerForImageLayer(mBuilder);
if (!imageContainer) {
return nullptr;
}
nsRefPtr<ImageLayer> imageLayer = CreateOrRecycleImageLayer(aData->mLayer);
imageLayer->SetContainer(imageContainer);
aData->mImage->ConfigureLayer(imageLayer, mParameters);
imageLayer->SetPostScale(mParameters.mXScale,
mParameters.mYScale);
if (aData->mItemClip.HasClip()) {
ParentLayerIntRect clip =
ViewAs<ParentLayerPixel>(ScaleToNearestPixels(aData->mItemClip.GetClipRect()));
clip.MoveBy(ViewAs<ParentLayerPixel>(mParameters.mOffset));
imageLayer->SetClipRect(Some(clip));
} else {
imageLayer->SetClipRect(Nothing());
}
mLayerBuilder->StoreOptimizedLayerForFrame(aData->mImage, imageLayer);
FLB_LOG_PAINTED_LAYER_DECISION(aData,
" Selected image layer=%p\n", imageLayer.get());
return imageLayer.forget();
}
already_AddRefed<Layer>
ContainerState::PrepareColorLayer(PaintedLayerData* aData)
{
nsRefPtr<ColorLayer> colorLayer = CreateOrRecycleColorLayer(aData->mLayer);
colorLayer->SetColor(aData->mSolidColor);
// Copy transform
colorLayer->SetBaseTransform(aData->mLayer->GetBaseTransform());
colorLayer->SetPostScale(aData->mLayer->GetPostXScale(),
aData->mLayer->GetPostYScale());
nsIntRect visibleRect = aData->mVisibleRegion.GetBounds();
visibleRect.MoveBy(-GetTranslationForPaintedLayer(aData->mLayer));
colorLayer->SetBounds(visibleRect);
colorLayer->SetClipRect(Nothing());
FLB_LOG_PAINTED_LAYER_DECISION(aData,
" Selected color layer=%p\n", colorLayer.get());
return colorLayer.forget();
}
template<typename FindOpaqueBackgroundColorCallbackType>
void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueBackgroundColorCallbackType aFindOpaqueBackgroundColor)
@ -2814,72 +2895,46 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB
NewLayerEntry* newLayerEntry = &mNewChildLayers[data->mNewChildLayersIndex];
nsRefPtr<Layer> layer;
nsRefPtr<ImageContainer> imageContainer = data->CanOptimizeImageLayer(mBuilder);
bool canOptimizeToImageLayer = data->CanOptimizeToImageLayer(mBuilder);
FLB_LOG_PAINTED_LAYER_DECISION(data, "Selecting layer for pld=%p\n", data);
FLB_LOG_PAINTED_LAYER_DECISION(data, " Solid=%i, hasImage=%i, canOptimizeAwayPaintedLayer=%i\n",
data->mIsSolidColorInVisibleRegion, !!imageContainer,
FLB_LOG_PAINTED_LAYER_DECISION(data, " Solid=%i, hasImage=%c, canOptimizeAwayPaintedLayer=%i\n",
data->mIsSolidColorInVisibleRegion, canOptimizeToImageLayer ? 'y' : 'n',
CanOptimizeAwayPaintedLayer(data, mLayerBuilder));
if ((data->mIsSolidColorInVisibleRegion || imageContainer) &&
if ((data->mIsSolidColorInVisibleRegion || canOptimizeToImageLayer) &&
CanOptimizeAwayPaintedLayer(data, mLayerBuilder)) {
NS_ASSERTION(!(data->mIsSolidColorInVisibleRegion && imageContainer),
NS_ASSERTION(!(data->mIsSolidColorInVisibleRegion && canOptimizeToImageLayer),
"Can't be a solid color as well as an image!");
if (imageContainer) {
nsRefPtr<ImageLayer> imageLayer = CreateOrRecycleImageLayer(data->mLayer);
imageLayer->SetContainer(imageContainer);
data->mImage->ConfigureLayer(imageLayer, mParameters);
imageLayer->SetPostScale(mParameters.mXScale,
mParameters.mYScale);
if (data->mItemClip.HasClip()) {
ParentLayerIntRect clip = ViewAs<ParentLayerPixel>(ScaleToNearestPixels(data->mItemClip.GetClipRect()));
clip.MoveBy(ViewAs<ParentLayerPixel>(mParameters.mOffset));
imageLayer->SetClipRect(Some(clip));
} else {
imageLayer->SetClipRect(Nothing());
}
layer = imageLayer;
mLayerBuilder->StoreOptimizedLayerForFrame(data->mImage,
imageLayer);
FLB_LOG_PAINTED_LAYER_DECISION(data, " Selected image layer=%p\n", layer.get());
} else {
nsRefPtr<ColorLayer> colorLayer = CreateOrRecycleColorLayer(data->mLayer);
colorLayer->SetColor(data->mSolidColor);
// Copy transform
colorLayer->SetBaseTransform(data->mLayer->GetBaseTransform());
colorLayer->SetPostScale(data->mLayer->GetPostXScale(), data->mLayer->GetPostYScale());
layer = canOptimizeToImageLayer ? PrepareImageLayer(data)
: PrepareColorLayer(data);
nsIntRect visibleRect = data->mVisibleRegion.GetBounds();
visibleRect.MoveBy(-GetTranslationForPaintedLayer(data->mLayer));
colorLayer->SetBounds(visibleRect);
colorLayer->SetClipRect(Nothing());
if (layer) {
NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, layer) < 0,
"Layer already in list???");
NS_ASSERTION(newLayerEntry->mLayer == data->mLayer,
"Painted layer at wrong index");
// Store optimized layer in reserved slot
newLayerEntry = &mNewChildLayers[data->mNewChildLayersIndex + 1];
NS_ASSERTION(!newLayerEntry->mLayer, "Slot already occupied?");
newLayerEntry->mLayer = layer;
newLayerEntry->mAnimatedGeometryRoot = data->mAnimatedGeometryRoot;
newLayerEntry->mFixedPosFrameForLayerData = data->mFixedPosFrameForLayerData;
layer = colorLayer;
FLB_LOG_PAINTED_LAYER_DECISION(data, " Selected color layer=%p\n", layer.get());
// Hide the PaintedLayer. We leave it in the layer tree so that we
// can find and recycle it later.
ParentLayerIntRect emptyRect;
data->mLayer->SetClipRect(Some(emptyRect));
data->mLayer->SetVisibleRegion(nsIntRegion());
data->mLayer->InvalidateRegion(data->mLayer->GetValidRegion().GetBounds());
data->mLayer->SetEventRegions(EventRegions());
}
NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, layer) < 0,
"Layer already in list???");
NS_ASSERTION(newLayerEntry->mLayer == data->mLayer,
"Painted layer at wrong index");
// Store optimized layer in reserved slot
newLayerEntry = &mNewChildLayers[data->mNewChildLayersIndex + 1];
NS_ASSERTION(!newLayerEntry->mLayer, "Slot already occupied?");
newLayerEntry->mLayer = layer;
newLayerEntry->mAnimatedGeometryRoot = data->mAnimatedGeometryRoot;
newLayerEntry->mFixedPosFrameForLayerData = data->mFixedPosFrameForLayerData;
// Hide the PaintedLayer. We leave it in the layer tree so that we
// can find and recycle it later.
ParentLayerIntRect emptyRect;
data->mLayer->SetClipRect(Some(emptyRect));
data->mLayer->SetVisibleRegion(nsIntRegion());
data->mLayer->InvalidateRegion(data->mLayer->GetValidRegion().GetBounds());
data->mLayer->SetEventRegions(EventRegions());
} else {
}
if (!layer) {
// We couldn't optimize to an image layer or a color layer above.
layer = data->mLayer;
imageContainer = nullptr;
layer->SetClipRect(Nothing());
FLB_LOG_PAINTED_LAYER_DECISION(data, " Selected painted layer=%p\n", layer.get());
}

View File

@ -5193,14 +5193,30 @@ nsImageRenderer::IsAnimatedImage()
return false;
}
already_AddRefed<mozilla::layers::ImageContainer>
nsImageRenderer::GetContainer(LayerManager* aManager)
bool
nsImageRenderer::IsContainerAvailable(LayerManager* aManager,
nsDisplayListBuilder* aBuilder)
{
if (mType != eStyleImageType_Image || !mImageContainer) {
return false;
}
uint32_t flags = aBuilder->ShouldSyncDecodeImages()
? imgIContainer::FLAG_SYNC_DECODE
: imgIContainer::FLAG_NONE;
return mImageContainer->IsImageContainerAvailable(aManager, flags);
}
already_AddRefed<imgIContainer>
nsImageRenderer::GetImage()
{
if (mType != eStyleImageType_Image || !mImageContainer) {
return nullptr;
}
return mImageContainer->GetImageContainer(aManager, imgIContainer::FLAG_NONE);
nsCOMPtr<imgIContainer> image = mImageContainer;
return image.forget();
}
#define MAX_BLUR_RADIUS 300

View File

@ -237,7 +237,19 @@ public:
bool IsRasterImage();
bool IsAnimatedImage();
already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager);
/**
* @return true if this nsImageRenderer wraps an image which has an
* ImageContainer available.
*
* If IsContainerAvailable() returns true, GetImage() will return a non-null
* imgIContainer which callers can use to retrieve the ImageContainer.
*/
bool IsContainerAvailable(LayerManager* aManager,
nsDisplayListBuilder* aBuilder);
/// Retrieves the image associated with this nsImageRenderer, if there is one.
already_AddRefed<imgIContainer> GetImage();
bool IsReady() { return mIsReady; }

View File

@ -2296,11 +2296,12 @@ nsDisplayBackgroundImage::ShouldFixToViewport(LayerManager* aManager)
}
bool
nsDisplayBackgroundImage::TryOptimizeToImageLayer(LayerManager* aManager,
nsDisplayBackgroundImage::CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder)
{
if (!mBackgroundStyle)
if (!mBackgroundStyle) {
return false;
}
nsPresContext* presContext = mFrame->PresContext();
uint32_t flags = aBuilder->GetBackgroundPaintFlags();
@ -2320,13 +2321,14 @@ nsDisplayBackgroundImage::TryOptimizeToImageLayer(LayerManager* aManager,
borderArea, borderArea, layer);
nsImageRenderer* imageRenderer = &state.mImageRenderer;
// We only care about images here, not gradients.
if (!imageRenderer->IsRasterImage())
if (!imageRenderer->IsRasterImage()) {
return false;
}
nsRefPtr<ImageContainer> imageContainer = imageRenderer->GetContainer(aManager);
// Image is not ready to be made into a layer yet
if (!imageContainer)
if (!imageRenderer->IsContainerAvailable(aManager, aBuilder)) {
// The image is not ready to be made into a layer yet.
return false;
}
// We currently can't handle tiled or partial backgrounds.
if (!state.mDestArea.IsEqualEdges(state.mFillArea)) {
@ -2339,9 +2341,11 @@ nsDisplayBackgroundImage::TryOptimizeToImageLayer(LayerManager* aManager,
int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
mDestRect =
LayoutDeviceRect::FromAppUnits(state.mDestArea, appUnitsPerDevPixel);
mImageContainer = imageContainer;
// Ok, we can turn this into a layer if needed.
mImage = imageRenderer->GetImage();
MOZ_ASSERT(mImage);
return true;
}
@ -2349,12 +2353,23 @@ already_AddRefed<ImageContainer>
nsDisplayBackgroundImage::GetContainer(LayerManager* aManager,
nsDisplayListBuilder *aBuilder)
{
if (!TryOptimizeToImageLayer(aManager, aBuilder)) {
if (!mImage) {
MOZ_ASSERT_UNREACHABLE("Must call CanOptimizeToImage() and get true "
"before calling GetContainer()");
return nullptr;
}
nsRefPtr<ImageContainer> container = mImageContainer;
if (!mImageContainer) {
// We don't have an ImageContainer yet; get it from mImage.
uint32_t flags = aBuilder->ShouldSyncDecodeImages()
? imgIContainer::FLAG_SYNC_DECODE
: imgIContainer::FLAG_NONE;
mImageContainer = mImage->GetImageContainer(aManager, flags);
}
nsRefPtr<ImageContainer> container = mImageContainer;
return container.forget();
}
@ -2386,19 +2401,24 @@ nsDisplayBackgroundImage::GetLayerState(nsDisplayListBuilder* aBuilder,
}
}
if (!TryOptimizeToImageLayer(aManager, aBuilder)) {
if (!CanOptimizeToImageLayer(aManager, aBuilder)) {
return LAYER_NONE;
}
MOZ_ASSERT(mImage);
if (!animated) {
mozilla::gfx::IntSize imageSize = mImageContainer->GetCurrentSize();
NS_ASSERTION(imageSize.width != 0 && imageSize.height != 0, "Invalid image size!");
int32_t imageWidth;
int32_t imageHeight;
mImage->GetWidth(&imageWidth);
mImage->GetHeight(&imageHeight);
NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!");
const LayerRect destLayerRect = mDestRect * aParameters.Scale();
// Calculate the scaling factor for the frame.
const gfxSize scale = gfxSize(destLayerRect.width / imageSize.width,
destLayerRect.height / imageSize.height);
const gfxSize scale = gfxSize(destLayerRect.width / imageWidth,
destLayerRect.height / imageHeight);
// If we are not scaling at all, no point in separating this into a layer.
if (scale.width == 1.0f && scale.height == 1.0f) {
@ -2426,7 +2446,8 @@ nsDisplayBackgroundImage::BuildLayer(nsDisplayListBuilder* aBuilder,
if (!layer)
return nullptr;
}
layer->SetContainer(mImageContainer);
nsRefPtr<ImageContainer> imageContainer = GetContainer(aManager, aBuilder);
layer->SetContainer(imageContainer);
ConfigureLayer(layer, aParameters);
return layer.forget();
}
@ -2437,9 +2458,14 @@ nsDisplayBackgroundImage::ConfigureLayer(ImageLayer* aLayer,
{
aLayer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(mFrame));
mozilla::gfx::IntSize imageSize = mImageContainer->GetCurrentSize();
NS_ASSERTION(imageSize.width != 0 && imageSize.height != 0, "Invalid image size!");
if (imageSize.width > 0 && imageSize.height > 0) {
MOZ_ASSERT(mImage);
int32_t imageWidth;
int32_t imageHeight;
mImage->GetWidth(&imageWidth);
mImage->GetHeight(&imageHeight);
NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!");
if (imageWidth > 0 && imageHeight > 0) {
// We're actually using the ImageContainer. Let our frame know that it
// should consider itself to have painted successfully.
nsDisplayBackgroundGeometry::UpdateDrawResult(this, DrawResult::SUCCESS);
@ -2453,8 +2479,8 @@ nsDisplayBackgroundImage::ConfigureLayer(ImageLayer* aLayer,
const LayoutDevicePoint p = mDestRect.TopLeft();
Matrix transform = Matrix::Translation(p.x, p.y);
transform.PreScale(mDestRect.width / imageSize.width,
mDestRect.height / imageSize.height);
transform.PreScale(mDestRect.width / imageWidth,
mDestRect.height / imageHeight);
aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
}

View File

@ -1988,6 +1988,14 @@ public:
: nsDisplayItem(aBuilder, aFrame)
{}
/**
* @return true if this display item can be optimized into an image layer.
* It is an error to call GetContainer() unless you've called
* CanOptimizeToImageLayer() first and it returned true.
*/
virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) = 0;
virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) = 0;
virtual void ConfigureLayer(ImageLayer* aLayer,
@ -2336,6 +2344,8 @@ public:
const nsDisplayItemGeometry* aGeometry,
nsRegion* aInvalidRegion) override;
virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) override;
virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
nsDisplayListBuilder *aBuilder) override;
virtual void ConfigureLayer(ImageLayer* aLayer,
@ -2362,7 +2372,7 @@ protected:
// Cache the result of nsCSSRendering::FindBackground. Always null if
// mIsThemed is true or if FindBackground returned false.
const nsStyleBackground* mBackgroundStyle;
/* If this background can be a simple image layer, we store the format here. */
nsCOMPtr<imgIContainer> mImage;
nsRefPtr<ImageContainer> mImageContainer;
LayoutDeviceRect mDestRect;
/* Bounds of this display item */

View File

@ -1415,6 +1415,17 @@ nsDisplayImage::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
nsDisplayImageContainer::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
}
bool
nsDisplayImage::CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder)
{
uint32_t flags = aBuilder->ShouldSyncDecodeImages()
? imgIContainer::FLAG_SYNC_DECODE
: imgIContainer::FLAG_NONE;
return mImage->IsImageContainerAvailable(aManager, flags);
}
already_AddRefed<ImageContainer>
nsDisplayImage::GetContainer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder)
@ -1503,9 +1514,7 @@ nsDisplayImage::GetLayerState(nsDisplayListBuilder* aBuilder,
? imgIContainer::FLAG_SYNC_DECODE
: imgIContainer::FLAG_NONE;
nsRefPtr<ImageContainer> container =
mImage->GetImageContainer(aManager, flags);
if (!container) {
if (!mImage->IsImageContainerAvailable(aManager, flags)) {
return LAYER_NONE;
}

View File

@ -394,6 +394,9 @@ public:
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) override;
virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) override;
/**
* Returns an ImageContainer for this image if the image type
* supports it (TYPE_RASTER only).

View File

@ -437,6 +437,36 @@ nsDisplayXULImage::ConfigureLayer(ImageLayer* aLayer,
aLayer->SetBaseTransform(gfx::Matrix4x4::From2D(transform));
}
bool
nsDisplayXULImage::CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder)
{
uint32_t flags = aBuilder->ShouldSyncDecodeImages()
? imgIContainer::FLAG_SYNC_DECODE
: imgIContainer::FLAG_NONE;
return static_cast<nsImageBoxFrame*>(mFrame)
->IsImageContainerAvailable(aManager, flags);
}
bool
nsImageBoxFrame::IsImageContainerAvailable(LayerManager* aManager,
uint32_t aFlags)
{
bool hasSubRect = !mUseSrcAttr && (mSubRect.width > 0 || mSubRect.height > 0);
if (hasSubRect || !mImageRequest) {
return false;
}
nsCOMPtr<imgIContainer> imgCon;
mImageRequest->GetImage(getter_AddRefs(imgCon));
if (!imgCon) {
return false;
}
return imgCon->IsImageContainerAvailable(aManager, aFlags);
}
already_AddRefed<ImageContainer>
nsDisplayXULImage::GetContainer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder)
@ -451,17 +481,23 @@ nsDisplayXULImage::GetContainer(LayerManager* aManager,
already_AddRefed<ImageContainer>
nsImageBoxFrame::GetContainer(LayerManager* aManager, uint32_t aFlags)
{
bool hasSubRect = !mUseSrcAttr && (mSubRect.width > 0 || mSubRect.height > 0);
if (hasSubRect || !mImageRequest) {
MOZ_ASSERT(IsImageContainerAvailable(aManager, aFlags),
"Should call IsImageContainerAvailable and get true before "
"calling GetContainer");
if (!mImageRequest) {
MOZ_ASSERT_UNREACHABLE("mImageRequest should be available if "
"IsImageContainerAvailable returned true");
return nullptr;
}
nsCOMPtr<imgIContainer> imgCon;
mImageRequest->GetImage(getter_AddRefs(imgCon));
if (!imgCon) {
MOZ_ASSERT_UNREACHABLE("An imgIContainer should be available if "
"IsImageContainerAvailable returned true");
return nullptr;
}
return imgCon->GetImageContainer(aManager, aFlags);
}

View File

@ -96,6 +96,7 @@ public:
const nsRect& aDirtyRect,
nsPoint aPt, uint32_t aFlags);
bool IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags);
already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
uint32_t aFlags);
@ -142,6 +143,8 @@ public:
}
#endif
virtual bool CanOptimizeToImageLayer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) override;
virtual already_AddRefed<ImageContainer> GetContainer(LayerManager* aManager,
nsDisplayListBuilder* aBuilder) override;
virtual void ConfigureLayer(ImageLayer* aLayer,