mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1054079 (Part 2) - Make it possible to initialize an imgFrame with a gfxDrawable. r=tn,mwu,mattwoodrow
This commit is contained in:
parent
c636e71b32
commit
6e8296e45b
@ -11,6 +11,9 @@
|
||||
#include "pixman.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using namespace gfx;
|
||||
|
||||
namespace image {
|
||||
|
||||
FrameBlender::FrameBlender(FrameSequence* aSequenceToUse /* = nullptr */)
|
||||
@ -258,8 +261,8 @@ FrameBlender::DoBlend(nsIntRect* aDirtyRect,
|
||||
// Create the Compositing Frame
|
||||
if (!mAnim->compositingFrame) {
|
||||
mAnim->compositingFrame.SetFrame(new imgFrame());
|
||||
nsresult rv = mAnim->compositingFrame->Init(0, 0, mSize.width, mSize.height,
|
||||
gfx::SurfaceFormat::B8G8R8A8);
|
||||
nsresult rv =
|
||||
mAnim->compositingFrame->InitForDecoder(mSize, SurfaceFormat::B8G8R8A8);
|
||||
if (NS_FAILED(rv)) {
|
||||
mAnim->compositingFrame.SetFrame(nullptr);
|
||||
return false;
|
||||
@ -388,8 +391,9 @@ FrameBlender::DoBlend(nsIntRect* aDirtyRect,
|
||||
// overwrite.
|
||||
if (!mAnim->compositingPrevFrame) {
|
||||
mAnim->compositingPrevFrame.SetFrame(new imgFrame());
|
||||
nsresult rv = mAnim->compositingPrevFrame->Init(0, 0, mSize.width, mSize.height,
|
||||
gfx::SurfaceFormat::B8G8R8A8);
|
||||
nsresult rv =
|
||||
mAnim->compositingPrevFrame->InitForDecoder(mSize,
|
||||
SurfaceFormat::B8G8R8A8);
|
||||
if (NS_FAILED(rv)) {
|
||||
mAnim->compositingPrevFrame.SetFrame(nullptr);
|
||||
return false;
|
||||
|
@ -223,8 +223,7 @@ public:
|
||||
// that's what the scaler outputs.
|
||||
nsRefPtr<imgFrame> tentativeDstFrame = new imgFrame();
|
||||
nsresult rv =
|
||||
tentativeDstFrame->Init(0, 0, dstSize.width, dstSize.height,
|
||||
SurfaceFormat::B8G8R8A8);
|
||||
tentativeDstFrame->InitForDecoder(dstSize, SurfaceFormat::B8G8R8A8);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
@ -1174,7 +1173,8 @@ RasterImage::InternalAddFrame(uint32_t framenum,
|
||||
|
||||
nsRefPtr<imgFrame> frame(new imgFrame());
|
||||
|
||||
nsresult rv = frame->Init(aX, aY, aWidth, aHeight, aFormat, aPaletteDepth);
|
||||
nsIntRect frameRect(aX, aY, aWidth, aHeight);
|
||||
nsresult rv = frame->InitForDecoder(frameRect, aFormat, aPaletteDepth);
|
||||
if (!(mSize.width > 0 && mSize.height > 0))
|
||||
NS_WARNING("Shouldn't call InternalAddFrame with zero size");
|
||||
if (!NS_SUCCEEDED(rv))
|
||||
@ -1358,7 +1358,8 @@ RasterImage::EnsureFrame(uint32_t aFrameNum, int32_t aX, int32_t aY,
|
||||
|
||||
mFrameBlender.RemoveFrame(aFrameNum);
|
||||
nsRefPtr<imgFrame> newFrame(new imgFrame());
|
||||
nsresult rv = newFrame->Init(aX, aY, aWidth, aHeight, aFormat, aPaletteDepth);
|
||||
nsIntRect frameRect(aX, aY, aWidth, aHeight);
|
||||
nsresult rv = newFrame->InitForDecoder(frameRect, aFormat, aPaletteDepth);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return InternalAddFrameHelper(aFrameNum, newFrame, imageData, imageLength,
|
||||
paletteData, paletteLength, aRetFrame);
|
||||
|
@ -143,17 +143,20 @@ imgFrame::~imgFrame()
|
||||
}
|
||||
}
|
||||
|
||||
nsresult imgFrame::Init(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight,
|
||||
SurfaceFormat aFormat, uint8_t aPaletteDepth /* = 0 */)
|
||||
nsresult
|
||||
imgFrame::InitForDecoder(const nsIntRect& aRect,
|
||||
SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth /* = 0 */)
|
||||
{
|
||||
// assert for properties that should be verified by decoders, warn for properties related to bad content
|
||||
if (!AllowedImageSize(aWidth, aHeight)) {
|
||||
// Assert for properties that should be verified by decoders,
|
||||
// warn for properties related to bad content.
|
||||
if (!AllowedImageSize(aRect.width, aRect.height)) {
|
||||
NS_WARNING("Should have legal image size");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mOffset.MoveTo(aX, aY);
|
||||
mSize.SizeTo(aWidth, aHeight);
|
||||
mOffset.MoveTo(aRect.x, aRect.y);
|
||||
mSize.SizeTo(aRect.width, aRect.height);
|
||||
|
||||
mFormat = aFormat;
|
||||
mPaletteDepth = aPaletteDepth;
|
||||
@ -172,32 +175,121 @@ nsresult imgFrame::Init(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight,
|
||||
NS_WARNING("moz_malloc for paletted image data should succeed");
|
||||
NS_ENSURE_TRUE(mPalettedImageData, NS_ERROR_OUT_OF_MEMORY);
|
||||
} else {
|
||||
MOZ_ASSERT(!mImageSurface, "Called imgFrame::InitForDecoder() twice?");
|
||||
|
||||
// Inform the discard tracker that we are going to allocate some memory.
|
||||
if (!DiscardTracker::TryAllocation(4 * mSize.width * mSize.height)) {
|
||||
NS_WARNING("Exceed the hard limit of decode image size");
|
||||
mInformedDiscardTracker =
|
||||
DiscardTracker::TryAllocation(4 * mSize.width * mSize.height);
|
||||
if (!mInformedDiscardTracker) {
|
||||
NS_WARNING("Exceeded the image decode size hard limit");
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
if (!mImageSurface) {
|
||||
mVBuf = AllocateBufferForImage(mSize, mFormat);
|
||||
if (!mVBuf) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
if (mVBuf->OnHeap()) {
|
||||
int32_t stride = VolatileSurfaceStride(mSize, mFormat);
|
||||
VolatileBufferPtr<uint8_t> ptr(mVBuf);
|
||||
memset(ptr, 0, stride * mSize.height);
|
||||
}
|
||||
mImageSurface = CreateLockedSurface(mVBuf, mSize, mFormat);
|
||||
mVBuf = AllocateBufferForImage(mSize, mFormat);
|
||||
if (!mVBuf) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
if (mVBuf->OnHeap()) {
|
||||
int32_t stride = VolatileSurfaceStride(mSize, mFormat);
|
||||
VolatileBufferPtr<uint8_t> ptr(mVBuf);
|
||||
memset(ptr, 0, stride * mSize.height);
|
||||
}
|
||||
mImageSurface = CreateLockedSurface(mVBuf, mSize, mFormat);
|
||||
|
||||
if (!mImageSurface) {
|
||||
NS_WARNING("Failed to create VolatileDataSourceSurface");
|
||||
// Image surface allocation is failed, need to return
|
||||
// the booked buffer size.
|
||||
DiscardTracker::InformDeallocation(4 * mSize.width * mSize.height);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
mInformedDiscardTracker = true;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
imgFrame::InitWithDrawable(gfxDrawable* aDrawable,
|
||||
const nsIntSize& aSize,
|
||||
const SurfaceFormat aFormat,
|
||||
GraphicsFilter aFilter,
|
||||
uint32_t aImageFlags)
|
||||
{
|
||||
// Assert for properties that should be verified by decoders,
|
||||
// warn for properties related to bad content.
|
||||
if (!AllowedImageSize(aSize.width, aSize.height)) {
|
||||
NS_WARNING("Should have legal image size");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mOffset.MoveTo(0, 0);
|
||||
mSize.SizeTo(aSize.width, aSize.height);
|
||||
|
||||
mFormat = aFormat;
|
||||
mPaletteDepth = 0;
|
||||
|
||||
// Inform the discard tracker that we are going to allocate some memory.
|
||||
mInformedDiscardTracker =
|
||||
DiscardTracker::TryAllocation(4 * mSize.width * mSize.height);
|
||||
if (!mInformedDiscardTracker) {
|
||||
NS_WARNING("Exceed the image decode size hard limit");
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> target;
|
||||
|
||||
bool canUseDataSurface =
|
||||
gfxPlatform::GetPlatform()->CanRenderContentToDataSurface();
|
||||
|
||||
if (canUseDataSurface) {
|
||||
// It's safe to use data surfaces for content on this platform, so we can
|
||||
// get away with using volatile buffers.
|
||||
MOZ_ASSERT(!mImageSurface, "Called imgFrame::InitWithDrawable() twice?");
|
||||
|
||||
mVBuf = AllocateBufferForImage(mSize, mFormat);
|
||||
if (!mVBuf) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
int32_t stride = VolatileSurfaceStride(mSize, mFormat);
|
||||
VolatileBufferPtr<uint8_t> ptr(mVBuf);
|
||||
if (!ptr) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
if (mVBuf->OnHeap()) {
|
||||
memset(ptr, 0, stride * mSize.height);
|
||||
}
|
||||
mImageSurface = CreateLockedSurface(mVBuf, mSize, mFormat);
|
||||
|
||||
target = gfxPlatform::GetPlatform()->
|
||||
CreateDrawTargetForData(ptr, mSize, stride, mFormat);
|
||||
} else {
|
||||
// We can't use data surfaces for content, so we'll create an offscreen
|
||||
// surface instead. This means if someone later calls RawAccessRef(), we
|
||||
// may have to do an expensive readback, but we warned callers about that in
|
||||
// the documentation for this method.
|
||||
MOZ_ASSERT(!mOptSurface, "Called imgFrame::InitWithDrawable() twice?");
|
||||
|
||||
target = gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenContentDrawTarget(mSize, mFormat);
|
||||
}
|
||||
|
||||
if (!target) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// Draw using the drawable the caller provided.
|
||||
nsIntRect imageRect(0, 0, mSize.width, mSize.height);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(target);
|
||||
gfxUtils::DrawPixelSnapped(ctx, aDrawable, ThebesIntSize(mSize),
|
||||
ImageRegion::Create(imageRect),
|
||||
mFormat, aFilter, aImageFlags);
|
||||
|
||||
if (canUseDataSurface && !mImageSurface) {
|
||||
NS_WARNING("Failed to create VolatileDataSourceSurface");
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (!canUseDataSurface) {
|
||||
// We used an offscreen surface, which is an "optimized" surface from
|
||||
// imgFrame's perspective.
|
||||
mOptSurface = target->Snapshot();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -36,7 +36,44 @@ public:
|
||||
|
||||
imgFrame();
|
||||
|
||||
nsresult Init(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight, SurfaceFormat aFormat, uint8_t aPaletteDepth = 0);
|
||||
/**
|
||||
* Initialize this imgFrame with an empty surface and prepare it for being
|
||||
* written to by a decoder.
|
||||
*
|
||||
* This is appropriate for use with decoded images, but it should not be used
|
||||
* when drawing content into an imgFrame, as it may use a different graphics
|
||||
* backend than normal content drawing.
|
||||
*/
|
||||
nsresult InitForDecoder(const nsIntRect& aRect,
|
||||
SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth = 0);
|
||||
|
||||
nsresult InitForDecoder(const nsIntSize& aSize,
|
||||
SurfaceFormat aFormat,
|
||||
uint8_t aPaletteDepth = 0)
|
||||
{
|
||||
return InitForDecoder(nsIntRect(0, 0, aSize.width, aSize.height),
|
||||
aFormat, aPaletteDepth);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize this imgFrame with a new surface and draw the provided
|
||||
* gfxDrawable into it.
|
||||
*
|
||||
* This is appropriate to use when drawing content into an imgFrame, as it
|
||||
* uses the same graphics backend as normal content drawing. The downside is
|
||||
* that the underlying surface may not be stored in a volatile buffer on all
|
||||
* platforms, and raw access to the surface (using RawAccessRef() or
|
||||
* LockImageData()) may be much more expensive than in the InitForDecoder()
|
||||
* case.
|
||||
*/
|
||||
nsresult InitWithDrawable(gfxDrawable* aDrawable,
|
||||
const nsIntSize& aSize,
|
||||
const SurfaceFormat aFormat,
|
||||
GraphicsFilter aFilter,
|
||||
uint32_t aImageFlags);
|
||||
|
||||
nsresult Optimize();
|
||||
|
||||
DrawableFrameRef DrawableRef();
|
||||
|
Loading…
Reference in New Issue
Block a user