Bug 695610 - Move ImageContainer caching into imgIContainer. r=joe

This commit is contained in:
Matt Woodrow 2011-11-09 16:14:41 +13:00
parent 874b4c8a33
commit b9a9dba520
6 changed files with 74 additions and 48 deletions

View File

@ -55,6 +55,13 @@ interface imgIDecoderObserver;
#include "nsSize.h"
#include "limits.h"
namespace mozilla {
namespace layers {
class LayerManager;
class ImageContainer;
}
}
class nsIFrame;
%}
@ -68,6 +75,8 @@ native gfxGraphicsFilter(gfxPattern::GraphicsFilter);
[ref] native nsIntRect(nsIntRect);
[ref] native nsIntSize(nsIntSize);
[ptr] native nsIFrame(nsIFrame);
[ptr] native ImageContainer(mozilla::layers::ImageContainer);
[ptr] native LayerManager(mozilla::layers::LayerManager);
/**
* imgIContainer is the interface that represents an image. It allows
@ -170,6 +179,14 @@ interface imgIContainer : nsISupports
[noscript] gfxASurface getFrame(in PRUint32 aWhichFrame,
in PRUint32 aFlags);
/**
* Attempts to create an ImageContainer (and Image) containing the current
* frame. Only valid for RASTER type images.
*
* @param aManager The layer manager to use to create the ImageContainer.
*/
[noscript] ImageContainer getImageContainer(in LayerManager aManager);
/**
* Create and return a new copy of the given frame that you can write to
* and otherwise inspect the pixels of.

View File

@ -58,6 +58,7 @@
#include "ImageLogging.h"
#include "mozilla/TimeStamp.h"
#include "mozilla/Telemetry.h"
#include "ImageLayers.h"
#include "nsPNGDecoder.h"
#include "nsGIFDecoder2.h"
@ -70,6 +71,7 @@
using namespace mozilla;
using namespace mozilla::imagelib;
using namespace mozilla::layers;
// a mask for flags that will affect the decoding
#define DECODE_FLAGS_MASK (imgIContainer::FLAG_DECODE_NO_PREMULTIPLY_ALPHA | imgIContainer::FLAG_DECODE_NO_COLORSPACE_CONVERSION)
@ -747,6 +749,42 @@ RasterImage::GetFrame(PRUint32 aWhichFrame,
return rv;
}
NS_IMETHODIMP
RasterImage::GetImageContainer(LayerManager* aManager,
ImageContainer **_retval)
{
if (mImageContainer &&
(mImageContainer->Manager() == aManager ||
(!mImageContainer->Manager() &&
(mImageContainer->GetBackendType() == aManager->GetBackendType())))) {
*_retval = mImageContainer;
return NS_OK;
}
CairoImage::Data cairoData;
nsRefPtr<gfxASurface> imageSurface;
GetFrame(FRAME_CURRENT, FLAG_SYNC_DECODE, getter_AddRefs(imageSurface));
cairoData.mSurface = imageSurface;
GetWidth(&cairoData.mSize.width);
GetHeight(&cairoData.mSize.height);
mImageContainer = aManager->CreateImageContainer();
NS_ASSERTION(mImageContainer, "Failed to create ImageContainer!");
// Now create a CairoImage to display the surface.
layers::Image::Format cairoFormat = layers::Image::CAIRO_SURFACE;
nsRefPtr<layers::Image> image = mImageContainer->CreateImage(&cairoFormat, 1);
NS_ASSERTION(image, "Failed to create Image");
NS_ASSERTION(image->GetFormat() == cairoFormat, "Wrong format");
static_cast<CairoImage*>(image.get())->SetData(cairoData);
mImageContainer->SetCurrentImage(image);
*_retval = mImageContainer;
return NS_OK;
}
namespace {
PRUint32
@ -1011,6 +1049,8 @@ RasterImage::FrameUpdated(PRUint32 aFrameNum, nsIntRect &aUpdatedRect)
NS_ABORT_IF_FALSE(frame, "Calling FrameUpdated on frame that doesn't exist!");
frame->ImageUpdated(aUpdatedRect);
// The image has changed, so we need to invalidate our cached ImageContainer.
mImageContainer = NULL;
}
nsresult

View File

@ -145,6 +145,10 @@ class nsIInputStream;
*/
namespace mozilla {
namespace layers {
class LayerManager;
class ImageContainer;
}
namespace imagelib {
class imgDecodeWorker;
@ -175,6 +179,7 @@ public:
NS_SCRIPTABLE NS_IMETHOD GetAnimated(bool *aAnimated);
NS_SCRIPTABLE NS_IMETHOD GetCurrentFrameIsOpaque(bool *aCurrentFrameIsOpaque);
NS_IMETHOD GetFrame(PRUint32 aWhichFrame, PRUint32 aFlags, gfxASurface **_retval NS_OUTPARAM);
NS_IMETHOD GetImageContainer(mozilla::layers::LayerManager* aManager, mozilla::layers::ImageContainer **_retval NS_OUTPARAM);
NS_IMETHOD CopyFrame(PRUint32 aWhichFrame, PRUint32 aFlags, gfxImageSurface **_retval NS_OUTPARAM);
NS_IMETHOD ExtractFrame(PRUint32 aWhichFrame, const nsIntRect & aRect, PRUint32 aFlags, imgIContainer **_retval NS_OUTPARAM);
NS_IMETHOD Draw(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter, const gfxMatrix & aUserSpaceToImageSpace, const gfxRect & aFill, const nsIntRect & aSubimage, const nsIntSize & aViewportSize, PRUint32 aFlags);
@ -506,6 +511,9 @@ private: // data
// This is currently only used for statistics
PRInt32 mDecodeCount;
// Cached value for GetImageContainer.
nsRefPtr<mozilla::layers::ImageContainer> mImageContainer;
#ifdef DEBUG
PRUint32 mFramesNotified;
#endif

View File

@ -46,6 +46,10 @@
class imgIDecoderObserver;
namespace mozilla {
namespace layers {
class LayerManager;
class ImageContainer;
}
namespace imagelib {
class SVGDocumentWrapper;
@ -68,6 +72,7 @@ public:
NS_SCRIPTABLE NS_IMETHOD GetAnimated(bool *aAnimated);
NS_SCRIPTABLE NS_IMETHOD GetCurrentFrameIsOpaque(bool *aCurrentFrameIsOpaque);
NS_IMETHOD GetFrame(PRUint32 aWhichFrame, PRUint32 aFlags, gfxASurface **_retval NS_OUTPARAM);
NS_IMETHOD GetImageContainer(mozilla::layers::LayerManager* aManager, mozilla::layers::ImageContainer **_retval NS_OUTPARAM) { *_retval = NULL; return NS_OK; }
NS_IMETHOD CopyFrame(PRUint32 aWhichFrame, PRUint32 aFlags, gfxImageSurface **_retval NS_OUTPARAM);
NS_IMETHOD ExtractFrame(PRUint32 aWhichFrame, const nsIntRect & aRect, PRUint32 aFlags, imgIContainer **_retval NS_OUTPARAM);
NS_IMETHOD Draw(gfxContext *aContext, gfxPattern::GraphicsFilter aFilter, const gfxMatrix & aUserSpaceToImageSpace, const gfxRect & aFill, const nsIntRect & aSubimage, const nsIntSize & aViewportSize, PRUint32 aFlags);

View File

@ -550,7 +550,6 @@ nsImageFrame::OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage)
*/
nsPresContext *presContext = PresContext();
aImage->SetAnimationMode(presContext->ImageAnimationMode());
mImageContainer = nsnull;
if (IsPendingLoad(aRequest)) {
// We don't care
@ -614,7 +613,6 @@ nsImageFrame::OnDataAvailable(imgIRequest *aRequest,
r.x, r.y, r.width, r.height);
#endif
mImageContainer = nsnull;
Invalidate(r);
return NS_OK;
@ -628,7 +626,6 @@ nsImageFrame::OnStopDecode(imgIRequest *aRequest,
nsPresContext *presContext = PresContext();
nsIPresShell *presShell = presContext->GetPresShell();
NS_ASSERTION(presShell, "No PresShell.");
mImageContainer = nsnull;
// Check what request type we're dealing with
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);
@ -695,7 +692,6 @@ nsImageFrame::FrameChanged(imgIContainer *aContainer,
// Update border+content to account for image change
Invalidate(r);
mImageContainer = nsnull;
return NS_OK;
}
@ -1213,7 +1209,10 @@ nsDisplayImage::GetImage()
nsRefPtr<ImageContainer>
nsDisplayImage::GetContainer(LayerManager* aManager)
{
return static_cast<nsImageFrame*>(mFrame)->GetContainer(aManager, mImage);
ImageContainer* container;
nsresult rv = mImage->GetImageContainer(aManager, &container);
NS_ENSURE_SUCCESS(rv, NULL);
return container;
}
void
@ -1242,44 +1241,6 @@ nsDisplayImage::ConfigureLayer(ImageLayer* aLayer)
aLayer->SetVisibleRegion(nsIntRect(0, 0, imageWidth, imageHeight));
}
nsRefPtr<ImageContainer>
nsImageFrame::GetContainer(LayerManager* aManager, imgIContainer* aImage)
{
if (mImageContainer &&
(mImageContainer->Manager() == aManager ||
(!mImageContainer->Manager() &&
(mImageContainer->GetBackendType() == aManager->GetBackendType())))) {
return mImageContainer;
}
if (aImage->GetType() != imgIContainer::TYPE_RASTER) {
return nsnull;
}
CairoImage::Data cairoData;
nsRefPtr<gfxASurface> imageSurface;
aImage->GetFrame(imgIContainer::FRAME_CURRENT,
imgIContainer::FLAG_SYNC_DECODE,
getter_AddRefs(imageSurface));
cairoData.mSurface = imageSurface;
aImage->GetWidth(&cairoData.mSize.width);
aImage->GetHeight(&cairoData.mSize.height);
mImageContainer = aManager->CreateImageContainer();
NS_ASSERTION(mImageContainer, "Failed to create ImageContainer!");
// Now create a CairoImage to display the surface.
Image::Format cairoFormat = Image::CAIRO_SURFACE;
nsRefPtr<Image> image = mImageContainer->CreateImage(&cairoFormat, 1);
NS_ASSERTION(image, "Failed to create Image");
NS_ASSERTION(image->GetFormat() == cairoFormat, "Wrong format");
static_cast<CairoImage*>(image.get())->SetData(cairoData);
mImageContainer->SetCurrentImage(image);
return mImageContainer;
}
void
nsImageFrame::PaintImage(nsRenderingContext& aRenderingContext, nsPoint aPt,
const nsRect& aDirtyRect, imgIContainer* aImage,

View File

@ -187,9 +187,6 @@ public:
virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext,
InlineMinWidthData *aData);
nsRefPtr<ImageContainer> GetContainer(LayerManager* aManager,
imgIContainer* aImage);
void DisconnectMap();
protected:
virtual ~nsImageFrame();
@ -307,8 +304,6 @@ private:
static nsIIOService* sIOService;
nsRefPtr<ImageContainer> mImageContainer;
/* loading / broken image icon support */
// XXXbz this should be handled by the prescontext, I think; that