Backed out changeset 37340346a89e (Bug 1289628 - Return ISurfaceProvider objects from SurfaceCache lookup functions. r=dholbert,edwin) for causing bug 1292290.

This commit is contained in:
Timothy Nikkel 2016-08-15 19:58:35 -05:00
Родитель e21abc7248
Коммит d7a0b010ae
7 изменённых файлов: 106 добавлений и 158 удалений

Просмотреть файл

@ -7,7 +7,6 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/Move.h"
#include "mozilla/NotNull.h"
#include "imgIContainer.h"
#include "LookupResult.h"
#include "MainThreadUtils.h"
@ -302,9 +301,7 @@ FrameAnimator::GetCompositedFrame(uint32_t aFrameNum)
// If we have a composited version of this frame, return that.
if (mLastCompositedFrameIndex == int32_t(aFrameNum)) {
RefPtr<ISurfaceProvider> provider =
new SimpleSurfaceProvider(WrapNotNull(mCompositingFrame.get()));
return LookupResult(Move(provider), MatchType::EXACT);
return LookupResult(mCompositingFrame->DrawableRef(), MatchType::EXACT);
}
// Otherwise return the raw frame. DoBlend is required to ensure that we only
@ -314,9 +311,7 @@ FrameAnimator::GetCompositedFrame(uint32_t aFrameNum)
RasterSurfaceKey(mSize,
DefaultSurfaceFlags(),
aFrameNum));
MOZ_ASSERT(!result ||
!result.Provider()->DrawableRef() ||
!result.Provider()->DrawableRef()->GetIsPaletted(),
MOZ_ASSERT(!result || !result.DrawableRef()->GetIsPaletted(),
"About to return a paletted frame");
return result;
}
@ -386,18 +381,8 @@ FrameAnimator::GetRawFrame(uint32_t aFrameNum) const
RasterSurfaceKey(mSize,
DefaultSurfaceFlags(),
aFrameNum));
if (!result) {
return RawAccessFrameRef();
}
DrawableFrameRef drawableRef = result.Provider()->DrawableRef();
if (!drawableRef) {
MOZ_ASSERT_UNREACHABLE("Animated image frames should be locked and "
"in-memory; how did we lose one?");
return RawAccessFrameRef();
}
return drawableRef->RawAccessRef();
return result ? result.DrawableRef()->RawAccessRef()
: RawAccessFrameRef();
}
//******************************************************************************

Просмотреть файл

@ -13,7 +13,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/Move.h"
#include "ISurfaceProvider.h"
#include "imgFrame.h"
namespace mozilla {
namespace image {
@ -30,7 +30,7 @@ enum class MatchType : uint8_t
/**
* LookupResult is the return type of SurfaceCache's Lookup*() functions. It
* combines an ISurfaceProvider with relevant metadata tracked by SurfaceCache.
* combines a surface with relevant metadata tracked by SurfaceCache.
*/
class MOZ_STACK_CLASS LookupResult
{
@ -44,35 +44,35 @@ public:
}
LookupResult(LookupResult&& aOther)
: mProvider(Move(aOther.mProvider))
: mDrawableRef(Move(aOther.mDrawableRef))
, mMatchType(aOther.mMatchType)
{ }
LookupResult(RefPtr<ISurfaceProvider>&& aProvider, MatchType aMatchType)
: mProvider(Move(aProvider))
LookupResult(DrawableFrameRef&& aDrawableRef, MatchType aMatchType)
: mDrawableRef(Move(aDrawableRef))
, mMatchType(aMatchType)
{
MOZ_ASSERT(!mProvider || !(mMatchType == MatchType::NOT_FOUND ||
mMatchType == MatchType::PENDING),
MOZ_ASSERT(!mDrawableRef || !(mMatchType == MatchType::NOT_FOUND ||
mMatchType == MatchType::PENDING),
"Only NOT_FOUND or PENDING make sense with no surface");
MOZ_ASSERT(mProvider || mMatchType == MatchType::NOT_FOUND ||
mMatchType == MatchType::PENDING,
MOZ_ASSERT(mDrawableRef || mMatchType == MatchType::NOT_FOUND ||
mMatchType == MatchType::PENDING,
"NOT_FOUND or PENDING do not make sense with a surface");
}
LookupResult& operator=(LookupResult&& aOther)
{
MOZ_ASSERT(&aOther != this, "Self-move-assignment is not supported");
mProvider = Move(aOther.mProvider);
mDrawableRef = Move(aOther.mDrawableRef);
mMatchType = aOther.mMatchType;
return *this;
}
ISurfaceProvider* Provider() { return mProvider.get(); }
const ISurfaceProvider* Provider() const { return mProvider.get(); }
DrawableFrameRef& DrawableRef() { return mDrawableRef; }
const DrawableFrameRef& DrawableRef() const { return mDrawableRef; }
/// @return true if this LookupResult contains a surface provider.
explicit operator bool() const { return bool(mProvider); }
/// @return true if this LookupResult contains a surface.
explicit operator bool() const { return bool(mDrawableRef); }
/// @return what kind of match this is (exact, substitute, etc.)
MatchType Type() const { return mMatchType; }
@ -80,7 +80,7 @@ public:
private:
LookupResult(const LookupResult&) = delete;
RefPtr<ISurfaceProvider> mProvider;
DrawableFrameRef mDrawableRef;
MatchType mMatchType;
};

Просмотреть файл

@ -354,29 +354,18 @@ RasterImage::LookupFrame(uint32_t aFrameNum,
return DrawableFrameRef();
}
// OK, we've got an ISurfaceProvider. Ask it to give us a surface containing
// the frame we're looking for. (This could be computationally expensive in
// some cases.)
DrawableFrameRef drawableRef = result.Provider()->DrawableRef();
if (!drawableRef) {
// An ISurfaceProvider will only fail to give us a surface in catastrophic
// cases such as the operating system freeing our volatile buffers. Our best
// bet is to throw everything out and attempt to recover.
RecoverFromInvalidFrames(aSize, aFlags);
if (result.DrawableRef()->GetCompositingFailed()) {
return DrawableFrameRef();
}
if (drawableRef->GetCompositingFailed()) {
return DrawableFrameRef();
}
MOZ_ASSERT(!drawableRef->GetIsPaletted(), "Should not have a paletted frame");
MOZ_ASSERT(!result.DrawableRef()->GetIsPaletted(),
"Should not have a paletted frame");
// Sync decoding guarantees that we got the frame, but if it's owned by an
// async decoder that's currently running, the contents of the frame may not
// be available yet. Make sure we get everything.
if (mHasSourceData && (aFlags & FLAG_SYNC_DECODE)) {
drawableRef->WaitUntilFinished();
result.DrawableRef()->WaitUntilFinished();
}
// If we could have done some decoding in this function we need to check if
@ -384,11 +373,11 @@ RasterImage::LookupFrame(uint32_t aFrameNum,
// to avoid calling IsAborted if we weren't passed any sync decode flag because
// IsAborted acquires the monitor for the imgFrame.
if (aFlags & (FLAG_SYNC_DECODE | FLAG_SYNC_DECODE_IF_FAST) &&
drawableRef->IsAborted()) {
result.DrawableRef()->IsAborted()) {
return DrawableFrameRef();
}
return Move(drawableRef);
return Move(result.DrawableRef());
}
uint32_t

Просмотреть файл

@ -55,7 +55,6 @@ class SurfaceCacheImpl;
// The single surface cache instance.
static StaticRefPtr<SurfaceCacheImpl> sInstance;
///////////////////////////////////////////////////////////////////////////////
// SurfaceCache Implementation
///////////////////////////////////////////////////////////////////////////////
@ -147,17 +146,14 @@ public:
MOZ_ASSERT(mImageKey, "Must have a valid image key");
}
already_AddRefed<ISurfaceProvider> Provider() const
DrawableFrameRef DrawableRef() const
{
if (MOZ_UNLIKELY(IsPlaceholder())) {
MOZ_ASSERT_UNREACHABLE("Shouldn't call Provider() on a placeholder");
return nullptr;
MOZ_ASSERT_UNREACHABLE("Shouldn't call DrawableRef() on a placeholder");
return DrawableFrameRef();
}
MOZ_ASSERT(mProvider);
RefPtr<ISurfaceProvider> provider = mProvider;
return provider.forget();
return mProvider->DrawableRef();
}
void SetLocked(bool aLocked)
@ -202,30 +198,18 @@ public:
SurfaceMemoryCounter counter(aCachedSurface->GetSurfaceKey(),
aCachedSurface->IsLocked());
if (aCachedSurface->IsPlaceholder()) {
mCounters.AppendElement(counter);
return;
}
if (!aCachedSurface->IsPlaceholder()) {
DrawableFrameRef surfaceRef = aCachedSurface->DrawableRef();
if (surfaceRef) {
counter.SubframeSize() = Some(surfaceRef->GetSize());
RefPtr<ISurfaceProvider> provider = aCachedSurface->Provider();
if (!provider) {
MOZ_ASSERT_UNREACHABLE("Not a placeholder, but no ISurfaceProvider?");
mCounters.AppendElement(counter);
return;
size_t heap = 0, nonHeap = 0;
surfaceRef->AddSizeOfExcludingThis(mMallocSizeOf, heap, nonHeap);
counter.Values().SetDecodedHeap(heap);
counter.Values().SetDecodedNonHeap(nonHeap);
}
}
DrawableFrameRef surfaceRef = provider->DrawableRef();
if (!surfaceRef) {
mCounters.AppendElement(counter);
return;
}
counter.SubframeSize() = Some(surfaceRef->GetSize());
size_t heap = 0, nonHeap = 0;
surfaceRef->AddSizeOfExcludingThis(mMallocSizeOf, heap, nonHeap);
counter.Values().SetDecodedHeap(heap);
counter.Values().SetDecodedNonHeap(nonHeap);
mCounters.AppendElement(counter);
}
@ -237,6 +221,7 @@ public:
private:
nsExpirationState mExpirationState;
RefPtr<ISurfaceProvider> mProvider;
DrawableFrameRef mDrawableRef;
const Cost mCost;
const ImageKey mImageKey;
const SurfaceKey mSurfaceKey;
@ -614,9 +599,10 @@ public:
return LookupResult(MatchType::PENDING);
}
RefPtr<ISurfaceProvider> provider = surface->Provider();
if (!provider) {
MOZ_ASSERT_UNREACHABLE("Not a placeholder, but no ISurfaceProvider?");
DrawableFrameRef ref = surface->DrawableRef();
if (!ref) {
// The surface was released by the operating system. Remove the cache
// entry as well.
Remove(surface);
return LookupResult(MatchType::NOT_FOUND);
}
@ -627,7 +613,7 @@ public:
MOZ_ASSERT(surface->GetSurfaceKey() == aSurfaceKey,
"Lookup() not returning an exact match?");
return LookupResult(Move(provider), MatchType::EXACT);
return LookupResult(Move(ref), MatchType::EXACT);
}
LookupResult LookupBestMatch(const ImageKey aImageKey,
@ -639,18 +625,30 @@ public:
return LookupResult(MatchType::NOT_FOUND);
}
RefPtr<CachedSurface> surface;
MatchType matchType = MatchType::NOT_FOUND;
Tie(surface, matchType) = cache->LookupBestMatch(aSurfaceKey);
if (!surface) {
return LookupResult(matchType); // Lookup in the per-image cache missed.
}
// Repeatedly look up the best match, trying again if the resulting surface
// has been freed by the operating system, until we can either lock a
// surface for drawing or there are no matching surfaces left.
// XXX(seth): This is O(N^2), but N is expected to be very small. If we
// encounter a performance problem here we can revisit this.
RefPtr<ISurfaceProvider> provider = surface->Provider();
if (!provider) {
MOZ_ASSERT_UNREACHABLE("Not a placeholder, but no ISurfaceProvider?");
RefPtr<CachedSurface> surface;
DrawableFrameRef ref;
MatchType matchType = MatchType::NOT_FOUND;
while (true) {
Tie(surface, matchType) = cache->LookupBestMatch(aSurfaceKey);
if (!surface) {
return LookupResult(matchType); // Lookup in the per-image cache missed.
}
ref = surface->DrawableRef();
if (ref) {
break;
}
// The surface was released by the operating system. Remove the cache
// entry as well.
Remove(surface);
return LookupResult(MatchType::NOT_FOUND);
}
MOZ_ASSERT_IF(matchType == MatchType::EXACT,
@ -665,7 +663,7 @@ public:
MarkUsed(surface, cache);
}
return LookupResult(Move(provider), matchType);
return LookupResult(Move(ref), matchType);
}
bool CanHold(const Cost aCost) const

Просмотреть файл

@ -194,33 +194,34 @@ struct SurfaceCache
static void Shutdown();
/**
* Looks up and returns the requested cache entry.
* Looks up the requested cache entry and returns a drawable reference to its
* associated surface.
*
* If the image associated with the cache entry is locked, then the entry will
* be locked before it is returned.
*
* This function returns an ISurfaceProvider, but it does not guarantee that
* the ISurfaceProvider can give the caller a drawable surface. Lookup()
* callers should check that ISurfaceProvider::DrawableRef() returns a
* non-empty value; if not, some sort of serious failure has occurred, and the
* best bet is to remove all existing surfaces for the image from the cache
* using RemoveImage() and try to recover. The most likely cause for this kind
* of failure is the surface's volatile buffer being freed by the operating
* system due to extreme memory pressure.
* If a matching ISurfaceProvider was found in the cache, but SurfaceCache
* couldn't obtain a surface from it (e.g. because it 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 LookupResult is returned.
* Note that this will never happen to ISurfaceProviders associated with a
* locked image; SurfaceCache tells such ISurfaceProviders to keep a strong
* references to their data internally.
*
* @param aImageKey Key data identifying which image the cache entry
* belongs to.
* @param aSurfaceKey Key data which uniquely identifies the requested
* cache entry.
* @return a LookupResult which will contain an ISurfaceProvider
* for the requested surface if a matching cache entry
* was found.
* @return a LookupResult, which will either contain a
* DrawableFrameRef to a surface, or an empty
* DrawableFrameRef if the cache entry was not found.
*/
static LookupResult Lookup(const ImageKey aImageKey,
const SurfaceKey& aSurfaceKey);
/**
* Looks up and returns the best matching cache entry.
* Looks up the best matching cache entry and returns a drawable reference to
* its associated surface.
*
* The result may vary from the requested cache entry only in terms of size.
*
@ -228,12 +229,12 @@ struct SurfaceCache
* belongs to.
* @param aSurfaceKey Key data which uniquely identifies the requested
* cache entry.
* @return a LookupResult which will contain either an
* ISurfaceProvider for a surface similar to the one
* the caller requested, or no ISurfaceProvider if no
* acceptable match was found. Callers can use
* LookupResult::IsExactMatch() to check whether the
* returned ISurfaceProvider exactly matches
* @return a LookupResult, which will either contain a
* DrawableFrameRef to a surface similar to the
* the one the caller requested, or an empty
* DrawableFrameRef if no acceptable match was found.
* Callers can use LookupResult::IsExactMatch() to check
* whether the returned surface exactly matches
* @aSurfaceKey.
*/
static LookupResult LookupBestMatch(const ImageKey aImageKey,

Просмотреть файл

@ -859,55 +859,34 @@ VectorImage::Draw(gfxContext* aContext,
SVGDrawingParameters params(aContext, aSize, aRegion, aSamplingFilter,
svgContext, animTime, aFlags);
// If we have an prerasterized version of this image that matches the
// drawing parameters, use that.
RefPtr<gfxDrawable> svgDrawable = LookupCachedSurface(params);
if (svgDrawable) {
Show(svgDrawable, params);
if (aFlags & FLAG_BYPASS_SURFACE_CACHE) {
CreateSurfaceAndShow(params);
return DrawResult::SUCCESS;
}
// We didn't get a hit in the surface cache, so we'll need to rerasterize.
CreateSurfaceAndShow(params);
return DrawResult::SUCCESS;
}
already_AddRefed<gfxDrawable>
VectorImage::LookupCachedSurface(const SVGDrawingParameters& aParams)
{
// If we're not allowed to use a cached surface, don't attempt a lookup.
if (aParams.flags & FLAG_BYPASS_SURFACE_CACHE) {
return nullptr;
}
LookupResult result =
SurfaceCache::Lookup(ImageKey(this),
VectorSurfaceKey(aParams.size,
aParams.svgContext,
aParams.animationTime));
if (!result) {
return nullptr; // No matching surface.
}
VectorSurfaceKey(params.size,
params.svgContext,
params.animationTime));
DrawableFrameRef drawableRef = result.Provider()->DrawableRef();
if (!drawableRef) {
// Something went wrong. (Probably the OS freeing our volatile buffer due to
// low memory.) Attempt to recover.
// Draw.
if (result) {
RefPtr<SourceSurface> surface = result.DrawableRef()->GetSurface();
if (surface) {
RefPtr<gfxDrawable> svgDrawable =
new gfxSurfaceDrawable(surface, result.DrawableRef()->GetSize());
Show(svgDrawable, params);
return DrawResult::SUCCESS;
}
// We lost our surface due to some catastrophic event.
RecoverFromLossOfSurfaces();
return nullptr;
}
RefPtr<SourceSurface> surface = drawableRef->GetSurface();
if (!surface) {
// Something went wrong. (Probably a GPU driver crash or device reset.)
// Attempt to recover.
RecoverFromLossOfSurfaces();
return nullptr;
}
CreateSurfaceAndShow(params);
RefPtr<gfxDrawable> svgDrawable =
new gfxSurfaceDrawable(surface, drawableRef->GetSize());
return svgDrawable.forget();
return DrawResult::SUCCESS;
}
void

Просмотреть файл

@ -78,14 +78,10 @@ protected:
virtual nsresult StopAnimation() override;
virtual bool ShouldAnimate() override;
private:
/// Attempt to find a cached surface matching @aParams in the SurfaceCache.
already_AddRefed<gfxDrawable>
LookupCachedSurface(const SVGDrawingParameters& aParams);
void CreateSurfaceAndShow(const SVGDrawingParameters& aParams);
void Show(gfxDrawable* aDrawable, const SVGDrawingParameters& aParams);
private:
nsresult Init(const char* aMimeType, uint32_t aFlags);
/**