зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1057906 - Use RawAccessFrameRef in the HQ-scaling code and clean up. r=tn
This commit is contained in:
Родитель
e5a303a93b
Коммит
946ca45284
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
@ -188,21 +189,21 @@ class ScaleRequest
|
|||
public:
|
||||
ScaleRequest(RasterImage* aImage,
|
||||
const nsIntSize& aSize,
|
||||
imgFrame* aSrcFrame)
|
||||
: dstSize(aSize)
|
||||
, dstLocked(false)
|
||||
RawAccessFrameRef&& aSrcRef)
|
||||
: weakImage(aImage)
|
||||
, srcRef(Move(aSrcRef))
|
||||
, srcRect(srcRef->GetRect())
|
||||
, dstSize(aSize)
|
||||
, done(false)
|
||||
, stopped(false)
|
||||
{
|
||||
MOZ_ASSERT(!aSrcFrame->GetIsPaletted());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!srcRef->GetIsPaletted());
|
||||
MOZ_ASSERT(aSize.width > 0 && aSize.height > 0);
|
||||
|
||||
weakImage = aImage;
|
||||
srcRect = aSrcFrame->GetRect();
|
||||
}
|
||||
|
||||
// This can only be called on the main thread.
|
||||
bool GetSurfaces(imgFrame* srcFrame)
|
||||
bool AcquireResources()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
|
@ -211,80 +212,68 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
if (!dstLocked) {
|
||||
if (!dstFrame) {
|
||||
// We need to hold a lock onto the RasterImage object itself so that
|
||||
// it (and its associated imgFrames) aren't marked as discardable.
|
||||
bool imgLocked = NS_SUCCEEDED(image->LockImage());
|
||||
bool srcLocked = NS_SUCCEEDED(srcFrame->LockImageData());
|
||||
srcSurface = srcFrame->GetSurface();
|
||||
|
||||
dstLocked = NS_SUCCEEDED(dstFrame->LockImageData());
|
||||
dstSurface = dstFrame->GetSurface();
|
||||
|
||||
success = imgLocked && srcLocked && dstLocked && srcSurface && dstSurface;
|
||||
|
||||
if (success) {
|
||||
srcData = srcFrame->GetImageData();
|
||||
dstData = dstFrame->GetImageData();
|
||||
srcStride = srcFrame->GetImageBytesPerRow();
|
||||
dstStride = dstFrame->GetImageBytesPerRow();
|
||||
srcFormat = srcFrame->GetFormat();
|
||||
if (NS_FAILED(image->LockImage())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We have references to the surfaces, so we don't need to leave
|
||||
// the source frame (that we don't own) locked. We'll unlock the
|
||||
// destination frame in ReleaseSurfaces(), below.
|
||||
if (srcLocked) {
|
||||
success = NS_SUCCEEDED(srcFrame->UnlockImageData()) && success;
|
||||
// We'll need a destination frame. It's unconditionally ARGB32 because
|
||||
// that's what the scaler outputs.
|
||||
nsRefPtr<imgFrame> tentativeDstFrame = new imgFrame();
|
||||
nsresult rv =
|
||||
tentativeDstFrame->Init(0, 0, dstSize.width, dstSize.height,
|
||||
SurfaceFormat::B8G8R8A8);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We need a strong reference to the raw data for the destination frame.
|
||||
// (We already got one for the source frame in the constructor.)
|
||||
RawAccessFrameRef tentativeDstRef = tentativeDstFrame->RawAccessRef();
|
||||
if (!tentativeDstRef) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dstFrame = tentativeDstFrame.forget();
|
||||
dstRef = Move(tentativeDstRef);
|
||||
}
|
||||
|
||||
return success;
|
||||
return true;
|
||||
}
|
||||
|
||||
// This can only be called on the main thread.
|
||||
bool ReleaseSurfaces()
|
||||
void ReleaseResources()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsRefPtr<RasterImage> image = weakImage.get();
|
||||
if (!image) {
|
||||
return false;
|
||||
if (image) {
|
||||
image->UnlockImage();
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
if (dstLocked) {
|
||||
if (DiscardingEnabled())
|
||||
dstFrame->SetDiscardable();
|
||||
success = NS_SUCCEEDED(dstFrame->UnlockImageData());
|
||||
success = success && NS_SUCCEEDED(image->UnlockImage());
|
||||
|
||||
dstLocked = false;
|
||||
srcData = nullptr;
|
||||
dstData = nullptr;
|
||||
srcSurface = nullptr;
|
||||
dstSurface = nullptr;
|
||||
if (DiscardingEnabled() && dstFrame) {
|
||||
dstFrame->SetDiscardable();
|
||||
}
|
||||
return success;
|
||||
|
||||
// Release everything except dstFrame, which we keep around for RasterImage
|
||||
// to retrieve.
|
||||
srcRef.reset();
|
||||
dstRef.reset();
|
||||
}
|
||||
|
||||
// These values may only be touched on the main thread.
|
||||
// These values may only be modified on the main thread.
|
||||
WeakPtr<RasterImage> weakImage;
|
||||
nsRefPtr<imgFrame> dstFrame;
|
||||
RefPtr<SourceSurface> srcSurface;
|
||||
RefPtr<SourceSurface> dstSurface;
|
||||
RawAccessFrameRef srcRef;
|
||||
RawAccessFrameRef dstRef;
|
||||
|
||||
// Below are the values that may be touched on the scaling thread.
|
||||
uint8_t* srcData;
|
||||
uint8_t* dstData;
|
||||
// Below are the values that may be modified on the scaling thread.
|
||||
nsIntRect srcRect;
|
||||
nsIntSize dstSize;
|
||||
uint32_t srcStride;
|
||||
uint32_t dstStride;
|
||||
SurfaceFormat srcFormat;
|
||||
bool dstLocked;
|
||||
bool done;
|
||||
|
||||
// This boolean is accessed from both threads simultaneously without locking.
|
||||
// That's safe because stopping a ScaleRequest is strictly an optimization;
|
||||
// if we're not cache-coherent, at worst we'll do extra work.
|
||||
|
@ -300,11 +289,13 @@ public:
|
|||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
// ScaleWorker is finished with this request, so we can unlock the data now.
|
||||
mScaleRequest->ReleaseSurfaces();
|
||||
|
||||
// Grab the weak image pointer before the request releases it.
|
||||
nsRefPtr<RasterImage> image = mScaleRequest->weakImage.get();
|
||||
|
||||
// ScaleWorker is finished with this request, so release everything that we
|
||||
// don't need anymore.
|
||||
mScaleRequest->ReleaseResources();
|
||||
|
||||
if (image) {
|
||||
RasterImage::ScaleStatus status;
|
||||
if (mScaleRequest->done) {
|
||||
|
@ -328,36 +319,36 @@ class ScaleRunner : public nsRunnable
|
|||
public:
|
||||
ScaleRunner(RasterImage* aImage,
|
||||
const nsIntSize& aSize,
|
||||
imgFrame* aSrcFrame)
|
||||
RawAccessFrameRef&& aSrcRef)
|
||||
{
|
||||
nsAutoPtr<ScaleRequest> request(new ScaleRequest(aImage, aSize, aSrcFrame));
|
||||
|
||||
// Destination is unconditionally ARGB32 because that's what the scaler
|
||||
// outputs.
|
||||
request->dstFrame = new imgFrame();
|
||||
nsresult rv = request->dstFrame->Init(0, 0, request->dstSize.width, request->dstSize.height,
|
||||
SurfaceFormat::B8G8R8A8);
|
||||
|
||||
if (NS_FAILED(rv) || !request->GetSurfaces(aSrcFrame)) {
|
||||
nsAutoPtr<ScaleRequest> req(new ScaleRequest(aImage, aSize, Move(aSrcRef)));
|
||||
if (!req->AcquireResources()) {
|
||||
return;
|
||||
}
|
||||
|
||||
aImage->ScalingStart(request);
|
||||
|
||||
mScaleRequest = request;
|
||||
aImage->ScalingStart(req);
|
||||
mScaleRequest = req;
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
// An alias just for ease of typing
|
||||
ScaleRequest* request = mScaleRequest;
|
||||
ScaleRequest* req = mScaleRequest.get();
|
||||
|
||||
if (!request->stopped) {
|
||||
request->done = gfx::Scale(request->srcData, request->srcRect.width, request->srcRect.height, request->srcStride,
|
||||
request->dstData, request->dstSize.width, request->dstSize.height, request->dstStride,
|
||||
request->srcFormat);
|
||||
if (!req->stopped) {
|
||||
// Collect information from the frames that we need to scale.
|
||||
uint8_t* srcData = req->srcRef->GetImageData();
|
||||
uint8_t* dstData = req->dstRef->GetImageData();
|
||||
uint32_t srcStride = req->srcRef->GetImageBytesPerRow();
|
||||
uint32_t dstStride = req->dstRef->GetImageBytesPerRow();
|
||||
SurfaceFormat srcFormat = req->srcRef->GetFormat();
|
||||
|
||||
// Actually do the scaling.
|
||||
req->done =
|
||||
gfx::Scale(srcData, req->srcRect.width, req->srcRect.height, srcStride,
|
||||
dstData, req->dstSize.width, req->dstSize.height, dstStride,
|
||||
srcFormat);
|
||||
} else {
|
||||
request->done = false;
|
||||
req->done = false;
|
||||
}
|
||||
|
||||
// OK, we've got a new scaled image. Let's get the main thread to unlock and
|
||||
|
@ -2624,8 +2615,8 @@ RasterImage::RequestScale(imgFrame* aFrame, nsIntSize aSize)
|
|||
}
|
||||
|
||||
// We also can't scale if we can't lock the image data for this frame.
|
||||
if (NS_FAILED(aFrame->LockImageData())) {
|
||||
aFrame->UnlockImageData();
|
||||
RawAccessFrameRef frameRef = aFrame->RawAccessRef();
|
||||
if (!frameRef) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2634,7 +2625,7 @@ RasterImage::RequestScale(imgFrame* aFrame, nsIntSize aSize)
|
|||
mScaleRequest->stopped = true;
|
||||
}
|
||||
|
||||
nsRefPtr<ScaleRunner> runner = new ScaleRunner(this, aSize, aFrame);
|
||||
nsRefPtr<ScaleRunner> runner = new ScaleRunner(this, aSize, Move(frameRef));
|
||||
if (runner->IsOK()) {
|
||||
if (!sScaleWorkerThread) {
|
||||
NS_NewNamedThread("Image Scaler", getter_AddRefs(sScaleWorkerThread));
|
||||
|
@ -2643,8 +2634,6 @@ RasterImage::RequestScale(imgFrame* aFrame, nsIntSize aSize)
|
|||
|
||||
sScaleWorkerThread->Dispatch(runner, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
aFrame->UnlockImageData();
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
Загрузка…
Ссылка в новой задаче