зеркало из https://github.com/mozilla/gecko-dev.git
Bug 980037 - Store scaled images in volatile buffers, r=seth
This commit is contained in:
Родитель
f7924f86f2
Коммит
62932af45c
|
@ -249,6 +249,8 @@ public:
|
|||
|
||||
bool success = false;
|
||||
if (dstLocked) {
|
||||
if (DiscardingEnabled())
|
||||
dstFrame->SetDiscardable();
|
||||
success = NS_SUCCEEDED(dstFrame->UnlockImageData());
|
||||
|
||||
dstLocked = false;
|
||||
|
@ -2563,7 +2565,7 @@ RasterImage::ScalingDone(ScaleRequest* request, ScaleStatus status)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
RasterImage::DrawWithPreDownscaleIfNeeded(imgFrame *aFrame,
|
||||
gfxContext *aContext,
|
||||
GraphicsFilter aFilter,
|
||||
|
@ -2579,8 +2581,9 @@ RasterImage::DrawWithPreDownscaleIfNeeded(imgFrame *aFrame,
|
|||
imageSpaceToUserSpace.Invert();
|
||||
gfx::Size scale = ToSize(imageSpaceToUserSpace.ScaleFactors(true));
|
||||
nsIntRect subimage = aSubimage;
|
||||
nsRefPtr<gfxASurface> surf;
|
||||
|
||||
if (CanScale(aFilter, scale, aFlags)) {
|
||||
if (CanScale(aFilter, scale, aFlags) && !frame->IsSinglePixel()) {
|
||||
// If scale factor is still the same that we scaled for and
|
||||
// ScaleWorker isn't still working, then we can use pre-downscaled frame.
|
||||
// If scale factor has changed, order new request.
|
||||
|
@ -2589,21 +2592,35 @@ RasterImage::DrawWithPreDownscaleIfNeeded(imgFrame *aFrame,
|
|||
// pre-downscaled frame only for the latest requested scale.
|
||||
// The solution is to cache more than one scaled image frame
|
||||
// for each RasterImage.
|
||||
bool needScaleReq;
|
||||
if (mScaleResult.status == SCALE_DONE && mScaleResult.scale == scale) {
|
||||
frame = mScaleResult.frame;
|
||||
userSpaceToImageSpace.Multiply(gfxMatrix().Scale(scale.width, scale.height));
|
||||
// Grab and hold the surface to make sure the OS didn't destroy it
|
||||
mScaleResult.frame->GetSurface(getter_AddRefs(surf));
|
||||
needScaleReq = !surf;
|
||||
if (surf) {
|
||||
frame = mScaleResult.frame;
|
||||
userSpaceToImageSpace.Multiply(gfxMatrix().Scale(scale.width,
|
||||
scale.height));
|
||||
|
||||
// Since we're switching to a scaled image, we need to transform the
|
||||
// area of the subimage to draw accordingly, since imgFrame::Draw()
|
||||
// doesn't know about scaled frames.
|
||||
subimage.ScaleRoundOut(scale.width, scale.height);
|
||||
// Since we're switching to a scaled image, we need to transform the
|
||||
// area of the subimage to draw accordingly, since imgFrame::Draw()
|
||||
// doesn't know about scaled frames.
|
||||
subimage.ScaleRoundOut(scale.width, scale.height);
|
||||
}
|
||||
} else {
|
||||
needScaleReq = !(mScaleResult.status == SCALE_PENDING &&
|
||||
mScaleResult.scale == scale);
|
||||
}
|
||||
|
||||
// If we're not waiting for exactly this result, and there's only one
|
||||
// instance of this image on this page, ask for a scale.
|
||||
else if (!(mScaleResult.status == SCALE_PENDING && mScaleResult.scale == scale) &&
|
||||
mLockCount == 1) {
|
||||
// If we have an oustanding request, signal it to stop (if it can).
|
||||
if (needScaleReq && mLockCount == 1) {
|
||||
if (NS_FAILED(frame->LockImageData())) {
|
||||
frame->UnlockImageData();
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we have an outstanding request, signal it to stop (if it can).
|
||||
if (mScaleRequest) {
|
||||
mScaleRequest->stopped = true;
|
||||
}
|
||||
|
@ -2617,6 +2634,7 @@ RasterImage::DrawWithPreDownscaleIfNeeded(imgFrame *aFrame,
|
|||
|
||||
sScaleWorkerThread->Dispatch(runner, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
frame->UnlockImageData();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2625,8 +2643,8 @@ RasterImage::DrawWithPreDownscaleIfNeeded(imgFrame *aFrame,
|
|||
mSize.height - framerect.YMost(),
|
||||
framerect.x);
|
||||
|
||||
frame->Draw(aContext, aFilter, userSpaceToImageSpace, aFill, padding, subimage,
|
||||
aFlags);
|
||||
return frame->Draw(aContext, aFilter, userSpaceToImageSpace,
|
||||
aFill, padding, subimage, aFlags);
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
|
@ -2718,19 +2736,16 @@ RasterImage::Draw(gfxContext *aContext,
|
|||
return NS_OK; // Getting the frame (above) touches the image and kicks off decoding
|
||||
}
|
||||
|
||||
nsRefPtr<gfxASurface> surf;
|
||||
if (!frame->IsSinglePixel()) {
|
||||
frame->GetSurface(getter_AddRefs(surf));
|
||||
if (!surf) {
|
||||
// The OS threw out some or all of our buffer. Start decoding again.
|
||||
ForceDiscard();
|
||||
WantDecodedFrames();
|
||||
return NS_OK;
|
||||
}
|
||||
bool drawn = DrawWithPreDownscaleIfNeeded(frame, aContext, aFilter,
|
||||
aUserSpaceToImageSpace, aFill,
|
||||
aSubimage, aFlags);
|
||||
if (!drawn) {
|
||||
// The OS threw out some or all of our buffer. Start decoding again.
|
||||
ForceDiscard();
|
||||
WantDecodedFrames();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
DrawWithPreDownscaleIfNeeded(frame, aContext, aFilter, aUserSpaceToImageSpace, aFill, aSubimage, aFlags);
|
||||
|
||||
if (mDecoded && !mDrawStartTime.IsNull()) {
|
||||
TimeDuration drawLatency = TimeStamp::Now() - mDrawStartTime;
|
||||
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_ON_DRAW_LATENCY, int32_t(drawLatency.ToMicroseconds()));
|
||||
|
|
|
@ -545,7 +545,7 @@ private:
|
|||
nsresult FinishedSomeDecoding(eShutdownIntent intent = eShutdownIntent_Done,
|
||||
DecodeRequest* request = nullptr);
|
||||
|
||||
void DrawWithPreDownscaleIfNeeded(imgFrame *aFrame,
|
||||
bool DrawWithPreDownscaleIfNeeded(imgFrame *aFrame,
|
||||
gfxContext *aContext,
|
||||
GraphicsFilter aFilter,
|
||||
const gfxMatrix &aUserSpaceToImageSpace,
|
||||
|
|
|
@ -419,12 +419,13 @@ imgFrame::SurfaceForDrawing(bool aDoPadding,
|
|||
gfxRect& aFill,
|
||||
gfxRect& aSubimage,
|
||||
gfxRect& aSourceRect,
|
||||
gfxRect& aImageRect)
|
||||
gfxRect& aImageRect,
|
||||
gfxASurface* aSurface)
|
||||
{
|
||||
IntSize size(int32_t(aImageRect.Width()), int32_t(aImageRect.Height()));
|
||||
if (!aDoPadding && !aDoPartialDecode) {
|
||||
NS_ASSERTION(!mSinglePixel, "This should already have been handled");
|
||||
return SurfaceWithFormat(new gfxSurfaceDrawable(ThebesSurface(), ThebesIntSize(size)), mFormat);
|
||||
return SurfaceWithFormat(new gfxSurfaceDrawable(aSurface, ThebesIntSize(size)), mFormat);
|
||||
}
|
||||
|
||||
gfxRect available = gfxRect(mDecoded.x, mDecoded.y, mDecoded.width, mDecoded.height);
|
||||
|
@ -445,7 +446,7 @@ imgFrame::SurfaceForDrawing(bool aDoPadding,
|
|||
if (mSinglePixel) {
|
||||
tmpCtx.SetDeviceColor(mSinglePixelColor);
|
||||
} else {
|
||||
tmpCtx.SetSource(ThebesSurface(), gfxPoint(aPadding.left, aPadding.top));
|
||||
tmpCtx.SetSource(aSurface, gfxPoint(aPadding.left, aPadding.top));
|
||||
}
|
||||
tmpCtx.Rectangle(available);
|
||||
tmpCtx.Fill();
|
||||
|
@ -467,12 +468,11 @@ imgFrame::SurfaceForDrawing(bool aDoPadding,
|
|||
aImageRect = gfxRect(0, 0, mSize.width, mSize.height);
|
||||
|
||||
gfxIntSize availableSize(mDecoded.width, mDecoded.height);
|
||||
return SurfaceWithFormat(new gfxSurfaceDrawable(ThebesSurface(),
|
||||
availableSize),
|
||||
return SurfaceWithFormat(new gfxSurfaceDrawable(aSurface, availableSize),
|
||||
mFormat);
|
||||
}
|
||||
|
||||
void imgFrame::Draw(gfxContext *aContext, GraphicsFilter aFilter,
|
||||
bool imgFrame::Draw(gfxContext *aContext, GraphicsFilter aFilter,
|
||||
const gfxMatrix &aUserSpaceToImageSpace, const gfxRect& aFill,
|
||||
const nsIntMargin &aPadding, const nsIntRect &aSubimage,
|
||||
uint32_t aImageFlags)
|
||||
|
@ -487,7 +487,7 @@ void imgFrame::Draw(gfxContext *aContext, GraphicsFilter aFilter,
|
|||
|
||||
if (mSinglePixel && !doPadding && !doPartialDecode) {
|
||||
DoSingleColorFastPath(aContext, mSinglePixelColor, aFill);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
gfxMatrix userSpaceToImageSpace = aUserSpaceToImageSpace;
|
||||
|
@ -500,12 +500,19 @@ void imgFrame::Draw(gfxContext *aContext, GraphicsFilter aFilter,
|
|||
NS_ASSERTION(!sourceRect.Intersect(subimage).IsEmpty(),
|
||||
"We must be allowed to sample *some* source pixels!");
|
||||
|
||||
nsRefPtr<gfxASurface> surf;
|
||||
if (!mSinglePixel) {
|
||||
surf = ThebesSurface();
|
||||
if (!surf)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool doTile = !imageRect.Contains(sourceRect) &&
|
||||
!(aImageFlags & imgIContainer::FLAG_CLAMP);
|
||||
SurfaceWithFormat surfaceResult =
|
||||
SurfaceForDrawing(doPadding, doPartialDecode, doTile, aPadding,
|
||||
userSpaceToImageSpace, fill, subimage, sourceRect,
|
||||
imageRect);
|
||||
imageRect, surf);
|
||||
|
||||
if (surfaceResult.IsValid()) {
|
||||
gfxUtils::DrawPixelSnapped(aContext, surfaceResult.mDrawable,
|
||||
|
@ -513,6 +520,7 @@ void imgFrame::Draw(gfxContext *aContext, GraphicsFilter aFilter,
|
|||
subimage, sourceRect, imageRect, fill,
|
||||
surfaceResult.mFormat, aFilter, aImageFlags);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// This can be called from any thread, but not simultaneously.
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
nsresult Init(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight, gfxImageFormat aFormat, uint8_t aPaletteDepth = 0);
|
||||
nsresult Optimize();
|
||||
|
||||
void Draw(gfxContext *aContext, GraphicsFilter aFilter,
|
||||
bool Draw(gfxContext *aContext, GraphicsFilter aFilter,
|
||||
const gfxMatrix &aUserSpaceToImageSpace, const gfxRect& aFill,
|
||||
const nsIntMargin &aPadding, const nsIntRect &aSubimage,
|
||||
uint32_t aImageFlags = imgIContainer::FLAG_NONE);
|
||||
|
@ -182,7 +182,8 @@ private: // methods
|
|||
gfxRect& aFill,
|
||||
gfxRect& aSubimage,
|
||||
gfxRect& aSourceRect,
|
||||
gfxRect& aImageRect);
|
||||
gfxRect& aImageRect,
|
||||
gfxASurface* aSurface);
|
||||
|
||||
private: // data
|
||||
nsRefPtr<gfxImageSurface> mImageSurface;
|
||||
|
|
Загрузка…
Ссылка в новой задаче