mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1081926 - Fallback on a simple image lookup when the normal lookup fails. r=mattwoodrow
This commit is contained in:
parent
9f20b8bd1c
commit
8429e6cc7f
@ -82,6 +82,36 @@ public:
|
||||
nsAutoPtr<ImageCacheEntryData> mData;
|
||||
};
|
||||
|
||||
class SimpleImageCacheEntry : public PLDHashEntryHdr {
|
||||
public:
|
||||
typedef imgIRequest& KeyType;
|
||||
typedef const imgIRequest* KeyTypePointer;
|
||||
|
||||
explicit SimpleImageCacheEntry(KeyTypePointer aKey)
|
||||
: mRequest(const_cast<imgIRequest*>(aKey))
|
||||
{}
|
||||
SimpleImageCacheEntry(const SimpleImageCacheEntry &toCopy)
|
||||
: mRequest(toCopy.mRequest)
|
||||
, mSourceSurface(toCopy.mSourceSurface)
|
||||
{}
|
||||
~SimpleImageCacheEntry() {}
|
||||
|
||||
bool KeyEquals(KeyTypePointer key) const
|
||||
{
|
||||
return key == mRequest;
|
||||
}
|
||||
|
||||
static KeyTypePointer KeyToPointer(KeyType key) { return &key; }
|
||||
static PLDHashNumber HashKey(KeyTypePointer key)
|
||||
{
|
||||
return NS_PTR_TO_UINT32(key) >> 2;
|
||||
}
|
||||
enum { ALLOW_MEMMOVE = true };
|
||||
|
||||
nsCOMPtr<imgIRequest> mRequest;
|
||||
RefPtr<SourceSurface> mSourceSurface;
|
||||
};
|
||||
|
||||
static bool sPrefsInitialized = false;
|
||||
static int32_t sCanvasImageCacheLimit = 0;
|
||||
|
||||
@ -99,10 +129,12 @@ public:
|
||||
mTotal -= aObject->SizeInBytes();
|
||||
RemoveObject(aObject);
|
||||
// Deleting the entry will delete aObject since the entry owns aObject
|
||||
mSimpleCache.RemoveEntry(*aObject->mRequest);
|
||||
mCache.RemoveEntry(ImageCacheKey(aObject->mImage, aObject->mCanvas));
|
||||
}
|
||||
|
||||
nsTHashtable<ImageCacheEntry> mCache;
|
||||
nsTHashtable<SimpleImageCacheEntry> mSimpleCache;
|
||||
size_t mTotal;
|
||||
nsRefPtr<ImageCacheObserver> mImageCacheObserver;
|
||||
};
|
||||
@ -230,6 +262,12 @@ CanvasImageCache::NotifyDrawImage(Element* aImage,
|
||||
entry->mData->mSize = aSize;
|
||||
|
||||
gImageCache->mTotal += entry->mData->SizeInBytes();
|
||||
|
||||
if (entry->mData->mRequest) {
|
||||
SimpleImageCacheEntry* simpleentry =
|
||||
gImageCache->mSimpleCache.PutEntry(*entry->mData->mRequest);
|
||||
simpleentry->mSourceSurface = aSource;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sCanvasImageCacheLimit)
|
||||
@ -263,6 +301,29 @@ CanvasImageCache::Lookup(Element* aImage,
|
||||
return entry->mData->mSourceSurface;
|
||||
}
|
||||
|
||||
SourceSurface*
|
||||
CanvasImageCache::SimpleLookup(Element* aImage)
|
||||
{
|
||||
if (!gImageCache)
|
||||
return nullptr;
|
||||
|
||||
nsCOMPtr<imgIRequest> request;
|
||||
nsCOMPtr<nsIImageLoadingContent> ilc = do_QueryInterface(aImage);
|
||||
if (!ilc)
|
||||
return nullptr;
|
||||
|
||||
ilc->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
|
||||
getter_AddRefs(request));
|
||||
if (!request)
|
||||
return nullptr;
|
||||
|
||||
SimpleImageCacheEntry* entry = gImageCache->mSimpleCache.GetEntry(*request);
|
||||
if (!entry)
|
||||
return nullptr;
|
||||
|
||||
return entry->mSourceSurface;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(CanvasImageCacheShutdownObserver, nsIObserver)
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -44,6 +44,13 @@ public:
|
||||
static SourceSurface* Lookup(dom::Element* aImage,
|
||||
dom::HTMLCanvasElement* aCanvas,
|
||||
gfxIntSize* aSize);
|
||||
|
||||
/**
|
||||
* This is the same as Lookup, except it works on any image recently drawn
|
||||
* into any canvas. Security checks need to be done again if using the
|
||||
* results from this.
|
||||
*/
|
||||
static SourceSurface* SimpleLookup(dom::Element* aImage);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -3880,6 +3880,56 @@ ExtractSubrect(SourceSurface* aSurface, mgfx::Rect* aSourceRect, DrawTarget* aTa
|
||||
return subrectDT->Snapshot();
|
||||
}
|
||||
|
||||
// Acts like nsLayoutUtils::SurfaceFromElement, but it'll attempt
|
||||
// to pull a SourceSurface from our cache. This allows us to avoid
|
||||
// reoptimizing surfaces if content and canvas backends are different.
|
||||
nsLayoutUtils::SurfaceFromElementResult
|
||||
CanvasRenderingContext2D::CachedSurfaceFromElement(Element* aElement)
|
||||
{
|
||||
nsLayoutUtils::SurfaceFromElementResult res;
|
||||
|
||||
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(aElement);
|
||||
if (!imageLoader) {
|
||||
return res;
|
||||
}
|
||||
|
||||
nsCOMPtr<imgIRequest> imgRequest;
|
||||
imageLoader->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
|
||||
getter_AddRefs(imgRequest));
|
||||
if (!imgRequest) {
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t status;
|
||||
if (NS_FAILED(imgRequest->GetImageStatus(&status)) ||
|
||||
!(status & imgIRequest::STATUS_LOAD_COMPLETE)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
if (NS_FAILED(imgRequest->GetImagePrincipal(getter_AddRefs(principal))) ||
|
||||
!principal) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res.mSourceSurface = CanvasImageCache::SimpleLookup(aElement);
|
||||
if (!res.mSourceSurface) {
|
||||
return res;
|
||||
}
|
||||
|
||||
int32_t corsmode = imgIRequest::CORS_NONE;
|
||||
if (NS_SUCCEEDED(imgRequest->GetCORSMode(&corsmode))) {
|
||||
res.mCORSUsed = corsmode != imgIRequest::CORS_NONE;
|
||||
}
|
||||
|
||||
res.mSize = ThebesIntSize(res.mSourceSurface->GetSize());
|
||||
res.mPrincipal = principal.forget();
|
||||
res.mIsWriteOnly = false;
|
||||
res.mImageRequest = imgRequest.forget();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//
|
||||
// image
|
||||
//
|
||||
@ -3940,8 +3990,15 @@ CanvasRenderingContext2D::DrawImage(const HTMLImageOrCanvasOrVideoElement& image
|
||||
// of animated images. We also don't want to rasterize vector images.
|
||||
uint32_t sfeFlags = nsLayoutUtils::SFE_WANT_FIRST_FRAME |
|
||||
nsLayoutUtils::SFE_NO_RASTERIZING_VECTORS;
|
||||
// The cache lookup can miss even if the image is already in the cache
|
||||
// if the image is coming from a different element or cached for a
|
||||
// different canvas. This covers the case when we miss due to caching
|
||||
// for a different canvas, but CanvasImageCache should be fixed if we
|
||||
// see misses due to different elements drawing the same image.
|
||||
nsLayoutUtils::SurfaceFromElementResult res =
|
||||
nsLayoutUtils::SurfaceFromElement(element, sfeFlags, mTarget);
|
||||
CachedSurfaceFromElement(element);
|
||||
if (!res.mSourceSurface)
|
||||
res = nsLayoutUtils::SurfaceFromElement(element, sfeFlags, mTarget);
|
||||
|
||||
if (!res.mSourceSurface && !res.mDrawInfo.mImgContainer) {
|
||||
// Spec says to silently do nothing if the element is still loading.
|
||||
|
@ -714,6 +714,9 @@ protected:
|
||||
*/
|
||||
void UpdateFilter();
|
||||
|
||||
nsLayoutUtils::SurfaceFromElementResult
|
||||
CachedSurfaceFromElement(Element* aElement);
|
||||
|
||||
void DrawImage(const HTMLImageOrCanvasOrVideoElement &imgElt,
|
||||
double sx, double sy, double sw, double sh,
|
||||
double dx, double dy, double dw, double dh,
|
||||
|
Loading…
Reference in New Issue
Block a user