From 64fe79505a1687f0f8bc2213465afdd9197bf7ec Mon Sep 17 00:00:00 2001 From: Joe Drew Date: Thu, 30 May 2013 09:50:50 -0400 Subject: [PATCH] Bug 867770 - Layerize all animated images. r=mattwoodrow --- layout/base/nsCSSRendering.cpp | 12 +++++++++ layout/base/nsCSSRendering.h | 1 + layout/base/nsDisplayList.cpp | 42 ++++++++++++++++------------- layout/base/nsDisplayList.h | 2 ++ layout/generic/nsImageFrame.cpp | 47 +++++++++++++++++++-------------- 5 files changed, 66 insertions(+), 38 deletions(-) diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index a83bea7219ab..7a54a5de0483 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -4688,6 +4688,18 @@ nsImageRenderer::IsRasterImage() return mImageContainer->GetType() == imgIContainer::TYPE_RASTER; } +bool +nsImageRenderer::IsAnimatedImage() +{ + if (mType != eStyleImageType_Image || !mImageContainer) + return false; + bool animated = false; + if (NS_SUCCEEDED(mImageContainer->GetAnimated(&animated)) && animated) + return true; + + return false; +} + already_AddRefed nsImageRenderer::GetContainer(LayerManager* aManager) { diff --git a/layout/base/nsCSSRendering.h b/layout/base/nsCSSRendering.h index fc3e97276b48..6e4435baf1ad 100644 --- a/layout/base/nsCSSRendering.h +++ b/layout/base/nsCSSRendering.h @@ -63,6 +63,7 @@ public: const nsRect& aDirty); bool IsRasterImage(); + bool IsAnimatedImage(); already_AddRefed GetContainer(LayerManager* aManager); private: diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 417c3e4a2501..97b5ac15979d 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1559,6 +1559,7 @@ nsDisplayBackgroundImage::nsDisplayBackgroundImage(nsDisplayListBuilder* aBuilde , mLayer(aLayer) , mIsThemed(aIsThemed) , mIsBottommostLayer(true) + , mIsAnimated(false) { MOZ_COUNT_CTOR(nsDisplayBackgroundImage); @@ -1820,6 +1821,7 @@ nsDisplayBackgroundImage::TryOptimizeToImageLayer(LayerManager* aManager, int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel(); mDestRect = nsLayoutUtils::RectToGfxRect(state.mDestArea, appUnitsPerDevPixel); mImageContainer = imageContainer; + mIsAnimated = imageRenderer->IsAnimatedImage(); // Ok, we can turn this into a layer if needed. return true; @@ -1843,31 +1845,35 @@ nsDisplayBackgroundImage::GetLayerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager, const FrameLayerBuilder::ContainerParameters& aParameters) { - if (!aManager->IsCompositingCheap() || - !nsLayoutUtils::GPUImageScalingEnabled() || - !TryOptimizeToImageLayer(aManager, aBuilder)) { - return LAYER_NONE; + if (!TryOptimizeToImageLayer(aManager, aBuilder) || + !mIsAnimated) { + if (!aManager->IsCompositingCheap() || + !nsLayoutUtils::GPUImageScalingEnabled()) { + return LAYER_NONE; + } } - gfxSize imageSize = mImageContainer->GetCurrentSize(); - NS_ASSERTION(imageSize.width != 0 && imageSize.height != 0, "Invalid image size!"); + if (!mIsAnimated) { + gfxSize imageSize = mImageContainer->GetCurrentSize(); + NS_ASSERTION(imageSize.width != 0 && imageSize.height != 0, "Invalid image size!"); - gfxRect destRect = mDestRect; + gfxRect destRect = mDestRect; - destRect.width *= aParameters.mXScale; - destRect.height *= aParameters.mYScale; + destRect.width *= aParameters.mXScale; + destRect.height *= aParameters.mYScale; - // Calculate the scaling factor for the frame. - gfxSize scale = gfxSize(destRect.width / imageSize.width, destRect.height / imageSize.height); + // Calculate the scaling factor for the frame. + gfxSize scale = gfxSize(destRect.width / imageSize.width, destRect.height / imageSize.height); - // If we are not scaling at all, no point in separating this into a layer. - if (scale.width == 1.0f && scale.height == 1.0f) { - return LAYER_NONE; - } + // If we are not scaling at all, no point in separating this into a layer. + if (scale.width == 1.0f && scale.height == 1.0f) { + return LAYER_NONE; + } - // If the target size is pretty small, no point in using a layer. - if (destRect.width * destRect.height < 64 * 64) { - return LAYER_NONE; + // If the target size is pretty small, no point in using a layer. + if (destRect.width * destRect.height < 64 * 64) { + return LAYER_NONE; + } } return LAYER_ACTIVE; diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 1eca3b8fd340..ecda275723c9 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -2030,6 +2030,8 @@ protected: bool mIsThemed; /* true if this item represents the bottom-most background layer */ bool mIsBottommostLayer; + /* true if this image is known to be animated */ + bool mIsAnimated; }; class nsDisplayBackgroundColor : public nsDisplayItem diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index f0944c95da7e..3652fee1fc36 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -1258,35 +1258,42 @@ nsDisplayImage::GetLayerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager, const FrameLayerBuilder::ContainerParameters& aParameters) { + bool animated = false; if (mImage->GetType() != imgIContainer::TYPE_RASTER || - !aManager->IsCompositingCheap() || - !nsLayoutUtils::GPUImageScalingEnabled()) { - return LAYER_NONE; + NS_FAILED(mImage->GetAnimated(&animated)) || + !animated) { + if (!aManager->IsCompositingCheap() || + !nsLayoutUtils::GPUImageScalingEnabled()) { + return LAYER_NONE; + } } - int32_t imageWidth; - int32_t imageHeight; - mImage->GetWidth(&imageWidth); - mImage->GetHeight(&imageHeight); + if (!animated) { + int32_t imageWidth; + int32_t imageHeight; + mImage->GetWidth(&imageWidth); + mImage->GetHeight(&imageHeight); - NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!"); + NS_ASSERTION(imageWidth != 0 && imageHeight != 0, "Invalid image size!"); - gfxRect destRect = GetDestRect(); + gfxRect destRect = GetDestRect(); - destRect.width *= aParameters.mXScale; - destRect.height *= aParameters.mYScale; + destRect.width *= aParameters.mXScale; + destRect.height *= aParameters.mYScale; - // Calculate the scaling factor for the frame. - gfxSize scale = gfxSize(destRect.width / imageWidth, destRect.height / imageHeight); + // Calculate the scaling factor for the frame. + gfxSize scale = gfxSize(destRect.width / imageWidth, + destRect.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) { - return LAYER_NONE; - } + // If we are not scaling at all, no point in separating this into a layer. + if (scale.width == 1.0f && scale.height == 1.0f) { + return LAYER_NONE; + } - // If the target size is pretty small, no point in using a layer. - if (destRect.width * destRect.height < 64 * 64) { - return LAYER_NONE; + // If the target size is pretty small, no point in using a layer. + if (destRect.width * destRect.height < 64 * 64) { + return LAYER_NONE; + } } nsRefPtr container;