mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1054079 (Part 3) - Store imgFrame objects, not SourceSurface objects, in the SurfaceCache. r=dholbert
This commit is contained in:
parent
bb0bbb475a
commit
6cbe3de817
@ -12,14 +12,15 @@
|
||||
#include <algorithm>
|
||||
#include "mozilla/Attributes.h" // for MOZ_THIS_IN_INITIALIZER_LIST
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "gfxPattern.h" // Workaround for flaw in bug 921753 part 2.
|
||||
#include "gfxDrawable.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "imgFrame.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsExpirationTracker.h"
|
||||
#include "nsHashKeys.h"
|
||||
@ -117,7 +118,7 @@ class CachedSurface
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(CachedSurface)
|
||||
|
||||
CachedSurface(SourceSurface* aSurface,
|
||||
CachedSurface(imgFrame* aSurface,
|
||||
const IntSize aTargetSize,
|
||||
const Cost aCost,
|
||||
const ImageKey aImageKey,
|
||||
@ -132,11 +133,9 @@ public:
|
||||
MOZ_ASSERT(mImageKey, "Must have a valid image key");
|
||||
}
|
||||
|
||||
already_AddRefed<gfxDrawable> Drawable() const
|
||||
DrawableFrameRef DrawableRef() const
|
||||
{
|
||||
nsRefPtr<gfxDrawable> drawable =
|
||||
new gfxSurfaceDrawable(mSurface, ThebesIntSize(mTargetSize));
|
||||
return drawable.forget();
|
||||
return mSurface->DrawableRef();
|
||||
}
|
||||
|
||||
ImageKey GetImageKey() const { return mImageKey; }
|
||||
@ -145,12 +144,12 @@ public:
|
||||
nsExpirationState* GetExpirationState() { return &mExpirationState; }
|
||||
|
||||
private:
|
||||
nsExpirationState mExpirationState;
|
||||
nsRefPtr<SourceSurface> mSurface;
|
||||
const IntSize mTargetSize;
|
||||
const Cost mCost;
|
||||
const ImageKey mImageKey;
|
||||
const SurfaceKey mSurfaceKey;
|
||||
nsExpirationState mExpirationState;
|
||||
nsRefPtr<imgFrame> mSurface;
|
||||
const IntSize mTargetSize;
|
||||
const Cost mCost;
|
||||
const ImageKey mImageKey;
|
||||
const SurfaceKey mSurfaceKey;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -240,14 +239,14 @@ public:
|
||||
RegisterWeakMemoryReporter(this);
|
||||
}
|
||||
|
||||
void Insert(SourceSurface* aSurface,
|
||||
void Insert(imgFrame* aSurface,
|
||||
IntSize aTargetSize,
|
||||
const Cost aCost,
|
||||
const ImageKey aImageKey,
|
||||
const SurfaceKey& aSurfaceKey)
|
||||
{
|
||||
MOZ_ASSERT(!Lookup(aImageKey, aSurfaceKey).take(),
|
||||
"Inserting a duplicate drawable into the SurfaceCache");
|
||||
MOZ_ASSERT(!Lookup(aImageKey, aSurfaceKey),
|
||||
"Inserting a duplicate surface into the SurfaceCache");
|
||||
|
||||
// If this is bigger than the maximum cache size, refuse to cache it.
|
||||
if (!CanHold(aCost))
|
||||
@ -317,19 +316,27 @@ public:
|
||||
MOZ_ASSERT(mAvailableCost <= mMaxCost, "More available cost than we started with");
|
||||
}
|
||||
|
||||
already_AddRefed<gfxDrawable> Lookup(const ImageKey aImageKey,
|
||||
const SurfaceKey& aSurfaceKey)
|
||||
DrawableFrameRef Lookup(const ImageKey aImageKey,
|
||||
const SurfaceKey& aSurfaceKey)
|
||||
{
|
||||
nsRefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
|
||||
if (!cache)
|
||||
return nullptr; // No cached surfaces for this image.
|
||||
|
||||
return DrawableFrameRef(); // No cached surfaces for this image.
|
||||
|
||||
nsRefPtr<CachedSurface> surface = cache->Lookup(aSurfaceKey);
|
||||
if (!surface)
|
||||
return nullptr; // Lookup in the per-image cache missed.
|
||||
|
||||
return DrawableFrameRef(); // Lookup in the per-image cache missed.
|
||||
|
||||
DrawableFrameRef ref = surface->DrawableRef();
|
||||
if (!ref) {
|
||||
// The surface was released by the operating system. Remove the cache
|
||||
// entry as well.
|
||||
Remove(surface);
|
||||
return DrawableFrameRef();
|
||||
}
|
||||
|
||||
mExpirationTracker.MarkUsed(surface);
|
||||
return surface->Drawable();
|
||||
return ref;
|
||||
}
|
||||
|
||||
bool CanHold(const Cost aCost) const
|
||||
@ -497,7 +504,7 @@ SurfaceCache::Shutdown()
|
||||
sInstance = nullptr;
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<gfxDrawable>
|
||||
/* static */ DrawableFrameRef
|
||||
SurfaceCache::Lookup(const ImageKey aImageKey,
|
||||
const SurfaceKey& aSurfaceKey)
|
||||
{
|
||||
@ -508,7 +515,7 @@ SurfaceCache::Lookup(const ImageKey aImageKey,
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
SurfaceCache::Insert(SourceSurface* aSurface,
|
||||
SurfaceCache::Insert(imgFrame* aSurface,
|
||||
const ImageKey aImageKey,
|
||||
const SurfaceKey& aSurfaceKey)
|
||||
{
|
||||
|
@ -4,7 +4,8 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/**
|
||||
* SurfaceCache is a service for caching temporary surfaces in imagelib.
|
||||
* SurfaceCache is a service for caching temporary surfaces and decoded image
|
||||
* data in imagelib.
|
||||
*/
|
||||
|
||||
#ifndef MOZILLA_IMAGELIB_SURFACECACHE_H_
|
||||
@ -15,19 +16,15 @@
|
||||
#include "gfxPoint.h" // for gfxSize
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "mozilla/gfx/Point.h" // for mozilla::gfx::IntSize
|
||||
#include "mozilla/gfx/2D.h" // for SourceSurface
|
||||
#include "SVGImageContext.h" // for SVGImageContext
|
||||
|
||||
class gfxDrawable;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace gfx {
|
||||
class DrawTarget;
|
||||
} // namespace gfx
|
||||
|
||||
namespace image {
|
||||
|
||||
class DrawableFrameRef;
|
||||
class Image;
|
||||
class imgFrame;
|
||||
|
||||
/*
|
||||
* ImageKey contains the information we need to look up all cached surfaces for
|
||||
@ -90,6 +87,11 @@ private:
|
||||
* surfaces. Surfaces expire from the cache automatically if they go too long
|
||||
* without being accessed.
|
||||
*
|
||||
* SurfaceCache does not hold surfaces directly; instead, it holds imgFrame
|
||||
* objects, which hold surfaces but also layer on additional features specific
|
||||
* to imagelib's needs like animation, padding support, and transparent support
|
||||
* for volatile buffers.
|
||||
*
|
||||
* SurfaceCache is not thread-safe; it should only be accessed from the main
|
||||
* thread.
|
||||
*/
|
||||
@ -108,27 +110,33 @@ struct SurfaceCache
|
||||
static void Shutdown();
|
||||
|
||||
/*
|
||||
* Look up a surface in the cache.
|
||||
* Look up the imgFrame containing a surface in the cache and returns a
|
||||
* drawable reference to that imgFrame.
|
||||
*
|
||||
* If the imgFrame was found in the cache, but had stored its surface in a
|
||||
* volatile buffer which was discarded by the OS, then it is automatically
|
||||
* removed from the cache and an empty DrawableFrameRef is returned.
|
||||
*
|
||||
* @param aImageKey Key data identifying which image the surface belongs to.
|
||||
* @param aSurfaceKey Key data which uniquely identifies the requested surface.
|
||||
*
|
||||
* @return the requested surface, or nullptr if not found.
|
||||
* @return a DrawableFrameRef to the imgFrame wrapping the requested surface,
|
||||
* or an empty DrawableFrameRef if not found.
|
||||
*/
|
||||
static already_AddRefed<gfxDrawable> Lookup(const ImageKey aImageKey,
|
||||
const SurfaceKey& aSurfaceKey);
|
||||
static DrawableFrameRef Lookup(const ImageKey aImageKey,
|
||||
const SurfaceKey& aSurfaceKey);
|
||||
|
||||
/*
|
||||
* Insert a surface into the cache. It is an error to call this function
|
||||
* without first calling Lookup to verify that the surface is not already in
|
||||
* the cache.
|
||||
*
|
||||
* @param aTarget The new surface (in the form of a DrawTarget) to insert
|
||||
* into the cache.
|
||||
* @param aTarget The new surface (wrapped in an imgFrame) to insert into
|
||||
* the cache.
|
||||
* @param aImageKey Key data identifying which image the surface belongs to.
|
||||
* @param aSurfaceKey Key data which uniquely identifies the requested surface.
|
||||
*/
|
||||
static void Insert(gfx::SourceSurface* aSurface,
|
||||
static void Insert(imgFrame* aSurface,
|
||||
const ImageKey aImageKey,
|
||||
const SurfaceKey& aSurfaceKey);
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "imgDecoderObserver.h"
|
||||
#include "imgFrame.h"
|
||||
#include "mozilla/AutoRestore.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/dom/SVGSVGElement.h"
|
||||
@ -842,27 +843,30 @@ VectorImage::Draw(gfxContext* aContext,
|
||||
aSVGContext, animTime, aFlags);
|
||||
|
||||
if (aFlags & FLAG_BYPASS_SURFACE_CACHE) {
|
||||
CreateDrawableAndShow(params);
|
||||
CreateSurfaceAndShow(params);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxDrawable> drawable =
|
||||
DrawableFrameRef frameRef =
|
||||
SurfaceCache::Lookup(ImageKey(this),
|
||||
SurfaceKey(params.size, aSVGContext,
|
||||
animTime, aFlags));
|
||||
|
||||
// Draw.
|
||||
if (drawable) {
|
||||
Show(drawable, params);
|
||||
if (frameRef) {
|
||||
RefPtr<SourceSurface> surface = frameRef->GetSurface();
|
||||
nsRefPtr<gfxDrawable> svgDrawable =
|
||||
new gfxSurfaceDrawable(surface, ThebesIntSize(frameRef->GetSize()));
|
||||
Show(svgDrawable, params);
|
||||
} else {
|
||||
CreateDrawableAndShow(params);
|
||||
CreateSurfaceAndShow(params);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
VectorImage::CreateDrawableAndShow(const SVGDrawingParameters& aParams)
|
||||
VectorImage::CreateSurfaceAndShow(const SVGDrawingParameters& aParams)
|
||||
{
|
||||
mSVGDocumentWrapper->UpdateViewportBounds(aParams.viewportSize);
|
||||
mSVGDocumentWrapper->FlushImageTransformInvalidation();
|
||||
@ -885,38 +889,32 @@ VectorImage::CreateDrawableAndShow(const SVGDrawingParameters& aParams)
|
||||
if (bypassCache)
|
||||
return Show(svgDrawable, aParams);
|
||||
|
||||
// Try to create an offscreen surface.
|
||||
RefPtr<gfx::DrawTarget> target =
|
||||
gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenContentDrawTarget(aParams.size,
|
||||
gfx::SurfaceFormat::B8G8R8A8);
|
||||
// Try to create an imgFrame, initializing the surface it contains by drawing
|
||||
// our gfxDrawable into it. (We use FILTER_NEAREST since we never scale here.)
|
||||
nsRefPtr<imgFrame> frame = new imgFrame;
|
||||
nsresult rv =
|
||||
frame->InitWithDrawable(svgDrawable, ThebesIntSize(aParams.size),
|
||||
SurfaceFormat::B8G8R8A8,
|
||||
GraphicsFilter::FILTER_NEAREST, aParams.flags);
|
||||
|
||||
// If we couldn't create the draw target, it was probably because it would end
|
||||
// If we couldn't create the frame, it was probably because it would end
|
||||
// up way too big. Generally it also wouldn't fit in the cache, but the prefs
|
||||
// could be set such that the cache isn't the limiting factor.
|
||||
if (!target)
|
||||
if (NS_FAILED(rv))
|
||||
return Show(svgDrawable, aParams);
|
||||
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(target);
|
||||
// Take a strong reference to the frame's surface and make sure it hasn't
|
||||
// already been purged by the operating system.
|
||||
RefPtr<SourceSurface> surface = frame->GetSurface();
|
||||
if (!surface)
|
||||
return Show(svgDrawable, aParams);
|
||||
|
||||
// Actually draw. (We use FILTER_NEAREST since we never scale here.)
|
||||
nsIntRect imageRect(ThebesIntRect(aParams.imageRect));
|
||||
gfxUtils::DrawPixelSnapped(ctx, svgDrawable,
|
||||
ThebesIntSize(aParams.size),
|
||||
ImageRegion::Create(imageRect),
|
||||
SurfaceFormat::B8G8R8A8,
|
||||
GraphicsFilter::FILTER_NEAREST, aParams.flags);
|
||||
|
||||
RefPtr<SourceSurface> surface = target->Snapshot();
|
||||
|
||||
// Attempt to cache the resulting surface.
|
||||
SurfaceCache::Insert(surface, ImageKey(this),
|
||||
// Attempt to cache the frame.
|
||||
SurfaceCache::Insert(frame, ImageKey(this),
|
||||
SurfaceKey(aParams.size, aParams.svgContext,
|
||||
aParams.animationTime, aParams.flags));
|
||||
|
||||
// Draw. Note that if SurfaceCache::Insert failed for whatever reason,
|
||||
// then |target| is all that is keeping the pixel data alive, so we have
|
||||
// to draw before returning from this function.
|
||||
// Draw.
|
||||
nsRefPtr<gfxDrawable> drawable =
|
||||
new gfxSurfaceDrawable(surface, ThebesIntSize(aParams.size));
|
||||
Show(drawable, aParams);
|
||||
|
@ -86,7 +86,7 @@ protected:
|
||||
virtual nsresult StopAnimation();
|
||||
virtual bool ShouldAnimate();
|
||||
|
||||
void CreateDrawableAndShow(const SVGDrawingParameters& aParams);
|
||||
void CreateSurfaceAndShow(const SVGDrawingParameters& aParams);
|
||||
void Show(gfxDrawable* aDrawable, const SVGDrawingParameters& aParams);
|
||||
|
||||
private:
|
||||
|
Loading…
Reference in New Issue
Block a user