mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1201796 (Part 2) - Add GetFrameAtSize() to support downscale-during-decode for GetFrame() use cases. r=tn
This commit is contained in:
parent
d919167ec8
commit
070157c0f4
@ -220,6 +220,16 @@ ClippedImage::GetFrame(uint32_t aWhichFrame,
|
|||||||
return GetFrameInternal(mClip.Size(), Nothing(), aWhichFrame, aFlags);
|
return GetFrameInternal(mClip.Size(), Nothing(), aWhichFrame, aFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
|
||||||
|
ClippedImage::GetFrameAtSize(const IntSize& aSize,
|
||||||
|
uint32_t aWhichFrame,
|
||||||
|
uint32_t aFlags)
|
||||||
|
{
|
||||||
|
// XXX(seth): It'd be nice to support downscale-during-decode for this case,
|
||||||
|
// but right now we just fall back to the intrinsic size.
|
||||||
|
return GetFrame(aWhichFrame, aFlags);
|
||||||
|
}
|
||||||
|
|
||||||
already_AddRefed<SourceSurface>
|
already_AddRefed<SourceSurface>
|
||||||
ClippedImage::GetFrameInternal(const nsIntSize& aSize,
|
ClippedImage::GetFrameInternal(const nsIntSize& aSize,
|
||||||
const Maybe<SVGImageContext>& aSVGContext,
|
const Maybe<SVGImageContext>& aSVGContext,
|
||||||
|
@ -37,6 +37,10 @@ public:
|
|||||||
NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) override;
|
NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) override;
|
||||||
NS_IMETHOD_(already_AddRefed<SourceSurface>)
|
NS_IMETHOD_(already_AddRefed<SourceSurface>)
|
||||||
GetFrame(uint32_t aWhichFrame, uint32_t aFlags) override;
|
GetFrame(uint32_t aWhichFrame, uint32_t aFlags) override;
|
||||||
|
NS_IMETHOD_(already_AddRefed<SourceSurface>)
|
||||||
|
GetFrameAtSize(const gfx::IntSize& aSize,
|
||||||
|
uint32_t aWhichFrame,
|
||||||
|
uint32_t aFlags) override;
|
||||||
NS_IMETHOD_(bool) IsImageContainerAvailable(layers::LayerManager* aManager,
|
NS_IMETHOD_(bool) IsImageContainerAvailable(layers::LayerManager* aManager,
|
||||||
uint32_t aFlags) override;
|
uint32_t aFlags) override;
|
||||||
NS_IMETHOD_(already_AddRefed<layers::ImageContainer>)
|
NS_IMETHOD_(already_AddRefed<layers::ImageContainer>)
|
||||||
|
@ -168,10 +168,18 @@ DynamicImage::GetFrame(uint32_t aWhichFrame,
|
|||||||
uint32_t aFlags)
|
uint32_t aFlags)
|
||||||
{
|
{
|
||||||
gfxIntSize size(mDrawable->Size());
|
gfxIntSize size(mDrawable->Size());
|
||||||
|
return GetFrameAtSize(IntSize(size.width, size.height),
|
||||||
|
aWhichFrame,
|
||||||
|
aFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
|
||||||
|
DynamicImage::GetFrameAtSize(const IntSize& aSize,
|
||||||
|
uint32_t aWhichFrame,
|
||||||
|
uint32_t aFlags)
|
||||||
|
{
|
||||||
RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()->
|
RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()->
|
||||||
CreateOffscreenContentDrawTarget(IntSize(size.width, size.height),
|
CreateOffscreenContentDrawTarget(aSize, SurfaceFormat::B8G8R8A8);
|
||||||
SurfaceFormat::B8G8R8A8);
|
|
||||||
if (!dt) {
|
if (!dt) {
|
||||||
gfxWarning() <<
|
gfxWarning() <<
|
||||||
"DynamicImage::GetFrame failed in CreateOffscreenContentDrawTarget";
|
"DynamicImage::GetFrame failed in CreateOffscreenContentDrawTarget";
|
||||||
@ -179,7 +187,7 @@ DynamicImage::GetFrame(uint32_t aWhichFrame,
|
|||||||
}
|
}
|
||||||
nsRefPtr<gfxContext> context = new gfxContext(dt);
|
nsRefPtr<gfxContext> context = new gfxContext(dt);
|
||||||
|
|
||||||
auto result = Draw(context, size, ImageRegion::Create(size),
|
auto result = Draw(context, aSize, ImageRegion::Create(aSize),
|
||||||
aWhichFrame, GraphicsFilter::FILTER_NEAREST,
|
aWhichFrame, GraphicsFilter::FILTER_NEAREST,
|
||||||
Nothing(), aFlags);
|
Nothing(), aFlags);
|
||||||
|
|
||||||
|
@ -44,6 +44,14 @@ FrozenImage::GetFrame(uint32_t aWhichFrame,
|
|||||||
return InnerImage()->GetFrame(FRAME_FIRST, aFlags);
|
return InnerImage()->GetFrame(FRAME_FIRST, aFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
|
||||||
|
FrozenImage::GetFrameAtSize(const IntSize& aSize,
|
||||||
|
uint32_t aWhichFrame,
|
||||||
|
uint32_t aFlags)
|
||||||
|
{
|
||||||
|
return InnerImage()->GetFrameAtSize(aSize, FRAME_FIRST, aFlags);
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP_(bool)
|
NS_IMETHODIMP_(bool)
|
||||||
FrozenImage::IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags)
|
FrozenImage::IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags)
|
||||||
{
|
{
|
||||||
|
@ -37,6 +37,10 @@ public:
|
|||||||
NS_IMETHOD GetAnimated(bool* aAnimated) override;
|
NS_IMETHOD GetAnimated(bool* aAnimated) override;
|
||||||
NS_IMETHOD_(already_AddRefed<SourceSurface>)
|
NS_IMETHOD_(already_AddRefed<SourceSurface>)
|
||||||
GetFrame(uint32_t aWhichFrame, uint32_t aFlags) override;
|
GetFrame(uint32_t aWhichFrame, uint32_t aFlags) override;
|
||||||
|
NS_IMETHOD_(already_AddRefed<SourceSurface>)
|
||||||
|
GetFrameAtSize(const gfx::IntSize& aSize,
|
||||||
|
uint32_t aWhichFrame,
|
||||||
|
uint32_t aFlags) override;
|
||||||
NS_IMETHOD_(bool) IsImageContainerAvailable(layers::LayerManager* aManager,
|
NS_IMETHOD_(bool) IsImageContainerAvailable(layers::LayerManager* aManager,
|
||||||
uint32_t aFlags) override;
|
uint32_t aFlags) override;
|
||||||
NS_IMETHOD_(already_AddRefed<layers::ImageContainer>)
|
NS_IMETHOD_(already_AddRefed<layers::ImageContainer>)
|
||||||
|
@ -174,6 +174,14 @@ ImageWrapper::GetFrame(uint32_t aWhichFrame,
|
|||||||
return mInnerImage->GetFrame(aWhichFrame, aFlags);
|
return mInnerImage->GetFrame(aWhichFrame, aFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
|
||||||
|
ImageWrapper::GetFrameAtSize(const IntSize& aSize,
|
||||||
|
uint32_t aWhichFrame,
|
||||||
|
uint32_t aFlags)
|
||||||
|
{
|
||||||
|
return mInnerImage->GetFrameAtSize(aSize, aWhichFrame, aFlags);
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP_(bool)
|
NS_IMETHODIMP_(bool)
|
||||||
ImageWrapper::IsOpaque()
|
ImageWrapper::IsOpaque()
|
||||||
{
|
{
|
||||||
|
@ -122,6 +122,16 @@ OrientedImage::GetFrame(uint32_t aWhichFrame,
|
|||||||
return target->Snapshot();
|
return target->Snapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
|
||||||
|
OrientedImage::GetFrameAtSize(const IntSize& aSize,
|
||||||
|
uint32_t aWhichFrame,
|
||||||
|
uint32_t aFlags)
|
||||||
|
{
|
||||||
|
// XXX(seth): It'd be nice to support downscale-during-decode for this case,
|
||||||
|
// but right now we just fall back to the intrinsic size.
|
||||||
|
return GetFrame(aWhichFrame, aFlags);
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP_(bool)
|
NS_IMETHODIMP_(bool)
|
||||||
OrientedImage::IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags)
|
OrientedImage::IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags)
|
||||||
{
|
{
|
||||||
|
@ -34,6 +34,10 @@ public:
|
|||||||
NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) override;
|
NS_IMETHOD GetIntrinsicRatio(nsSize* aRatio) override;
|
||||||
NS_IMETHOD_(already_AddRefed<SourceSurface>)
|
NS_IMETHOD_(already_AddRefed<SourceSurface>)
|
||||||
GetFrame(uint32_t aWhichFrame, uint32_t aFlags) override;
|
GetFrame(uint32_t aWhichFrame, uint32_t aFlags) override;
|
||||||
|
NS_IMETHOD_(already_AddRefed<SourceSurface>)
|
||||||
|
GetFrameAtSize(const gfx::IntSize& aSize,
|
||||||
|
uint32_t aWhichFrame,
|
||||||
|
uint32_t aFlags) override;
|
||||||
NS_IMETHOD_(bool) IsImageContainerAvailable(layers::LayerManager* aManager,
|
NS_IMETHOD_(bool) IsImageContainerAvailable(layers::LayerManager* aManager,
|
||||||
uint32_t aFlags) override;
|
uint32_t aFlags) override;
|
||||||
NS_IMETHOD_(already_AddRefed<layers::ImageContainer>)
|
NS_IMETHOD_(already_AddRefed<layers::ImageContainer>)
|
||||||
|
@ -698,14 +698,28 @@ NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
|
|||||||
RasterImage::GetFrame(uint32_t aWhichFrame,
|
RasterImage::GetFrame(uint32_t aWhichFrame,
|
||||||
uint32_t aFlags)
|
uint32_t aFlags)
|
||||||
{
|
{
|
||||||
return GetFrameInternal(aWhichFrame, aFlags).second().forget();
|
return GetFrameInternal(mSize, aWhichFrame, aFlags).second().forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
|
||||||
|
RasterImage::GetFrameAtSize(const IntSize& aSize,
|
||||||
|
uint32_t aWhichFrame,
|
||||||
|
uint32_t aFlags)
|
||||||
|
{
|
||||||
|
return GetFrameInternal(aSize, aWhichFrame, aFlags).second().forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair<DrawResult, RefPtr<SourceSurface>>
|
Pair<DrawResult, RefPtr<SourceSurface>>
|
||||||
RasterImage::GetFrameInternal(uint32_t aWhichFrame, uint32_t aFlags)
|
RasterImage::GetFrameInternal(const IntSize& aSize,
|
||||||
|
uint32_t aWhichFrame,
|
||||||
|
uint32_t aFlags)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE);
|
MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE);
|
||||||
|
|
||||||
|
if (aSize.IsEmpty()) {
|
||||||
|
return MakePair(DrawResult::BAD_ARGS, RefPtr<SourceSurface>());
|
||||||
|
}
|
||||||
|
|
||||||
if (aWhichFrame > FRAME_MAX_VALUE) {
|
if (aWhichFrame > FRAME_MAX_VALUE) {
|
||||||
return MakePair(DrawResult::BAD_ARGS, RefPtr<SourceSurface>());
|
return MakePair(DrawResult::BAD_ARGS, RefPtr<SourceSurface>());
|
||||||
}
|
}
|
||||||
@ -718,7 +732,7 @@ RasterImage::GetFrameInternal(uint32_t aWhichFrame, uint32_t aFlags)
|
|||||||
// not waiting for the data to be loaded from the network or not passing
|
// not waiting for the data to be loaded from the network or not passing
|
||||||
// FLAG_SYNC_DECODE
|
// FLAG_SYNC_DECODE
|
||||||
DrawableFrameRef frameRef =
|
DrawableFrameRef frameRef =
|
||||||
LookupFrame(GetRequestedFrameIndex(aWhichFrame), mSize, aFlags);
|
LookupFrame(GetRequestedFrameIndex(aWhichFrame), aSize, aFlags);
|
||||||
if (!frameRef) {
|
if (!frameRef) {
|
||||||
// The OS threw this frame away and we couldn't redecode it.
|
// The OS threw this frame away and we couldn't redecode it.
|
||||||
return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
|
return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
|
||||||
@ -727,15 +741,15 @@ RasterImage::GetFrameInternal(uint32_t aWhichFrame, uint32_t aFlags)
|
|||||||
// If this frame covers the entire image, we can just reuse its existing
|
// If this frame covers the entire image, we can just reuse its existing
|
||||||
// surface.
|
// surface.
|
||||||
RefPtr<SourceSurface> frameSurf;
|
RefPtr<SourceSurface> frameSurf;
|
||||||
IntRect frameRect = frameRef->GetRect();
|
if (!frameRef->NeedsPadding() &&
|
||||||
if (frameRect.x == 0 && frameRect.y == 0 &&
|
frameRef->GetSize() == aSize) {
|
||||||
frameRect.width == mSize.width &&
|
|
||||||
frameRect.height == mSize.height) {
|
|
||||||
frameSurf = frameRef->GetSurface();
|
frameSurf = frameRef->GetSurface();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The image doesn't have a usable surface because it's been optimized away or
|
// The image doesn't have a usable surface because it's been optimized away or
|
||||||
// because it's a partial update frame from an animation. Create one.
|
// because it's a partial update frame from an animation. Create one. (In this
|
||||||
|
// case we fall back to returning a surface at our intrinsic size, even if a
|
||||||
|
// different size was originally specified.)
|
||||||
if (!frameSurf) {
|
if (!frameSurf) {
|
||||||
frameSurf = CopyFrame(aWhichFrame, aFlags);
|
frameSurf = CopyFrame(aWhichFrame, aFlags);
|
||||||
}
|
}
|
||||||
@ -756,7 +770,7 @@ RasterImage::GetCurrentImage(ImageContainer* aContainer, uint32_t aFlags)
|
|||||||
DrawResult drawResult;
|
DrawResult drawResult;
|
||||||
RefPtr<SourceSurface> surface;
|
RefPtr<SourceSurface> surface;
|
||||||
Tie(drawResult, surface) =
|
Tie(drawResult, surface) =
|
||||||
GetFrameInternal(FRAME_CURRENT, aFlags | FLAG_ASYNC_NOTIFY);
|
GetFrameInternal(mSize, FRAME_CURRENT, aFlags | FLAG_ASYNC_NOTIFY);
|
||||||
if (!surface) {
|
if (!surface) {
|
||||||
// The OS threw out some or all of our buffer. We'll need to wait for the
|
// The OS threw out some or all of our buffer. We'll need to wait for the
|
||||||
// redecode (which was automatically triggered by GetFrame) to complete.
|
// redecode (which was automatically triggered by GetFrame) to complete.
|
||||||
|
@ -265,7 +265,9 @@ private:
|
|||||||
uint32_t aFlags);
|
uint32_t aFlags);
|
||||||
|
|
||||||
Pair<DrawResult, RefPtr<gfx::SourceSurface>>
|
Pair<DrawResult, RefPtr<gfx::SourceSurface>>
|
||||||
GetFrameInternal(uint32_t aWhichFrame, uint32_t aFlags);
|
GetFrameInternal(const gfx::IntSize& aSize,
|
||||||
|
uint32_t aWhichFrame,
|
||||||
|
uint32_t aFlags);
|
||||||
|
|
||||||
LookupResult LookupFrameInternal(uint32_t aFrameNum,
|
LookupResult LookupFrameInternal(uint32_t aFrameNum,
|
||||||
const gfx::IntSize& aSize,
|
const gfx::IntSize& aSize,
|
||||||
|
@ -668,19 +668,8 @@ VectorImage::IsOpaque()
|
|||||||
/* [noscript] SourceSurface getFrame(in uint32_t aWhichFrame,
|
/* [noscript] SourceSurface getFrame(in uint32_t aWhichFrame,
|
||||||
* in uint32_t aFlags; */
|
* in uint32_t aFlags; */
|
||||||
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
|
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
|
||||||
VectorImage::GetFrame(uint32_t aWhichFrame,
|
VectorImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags)
|
||||||
uint32_t aFlags)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE);
|
|
||||||
|
|
||||||
if (aWhichFrame > FRAME_MAX_VALUE) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mError || !mIsFullyLoaded) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look up height & width
|
// Look up height & width
|
||||||
// ----------------------
|
// ----------------------
|
||||||
SVGSVGElement* svgElem = mSVGDocumentWrapper->GetRootSVGElem();
|
SVGSVGElement* svgElem = mSVGDocumentWrapper->GetRootSVGElem();
|
||||||
@ -695,12 +684,32 @@ VectorImage::GetFrame(uint32_t aWhichFrame,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return GetFrameAtSize(imageIntSize, aWhichFrame, aFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
|
||||||
|
VectorImage::GetFrameAtSize(const IntSize& aSize,
|
||||||
|
uint32_t aWhichFrame,
|
||||||
|
uint32_t aFlags)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE);
|
||||||
|
|
||||||
|
if (aSize.IsEmpty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aWhichFrame > FRAME_MAX_VALUE) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mError || !mIsFullyLoaded) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Make our surface the size of what will ultimately be drawn to it.
|
// Make our surface the size of what will ultimately be drawn to it.
|
||||||
// (either the full image size, or the restricted region)
|
// (either the full image size, or the restricted region)
|
||||||
RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()->
|
RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()->
|
||||||
CreateOffscreenContentDrawTarget(IntSize(imageIntSize.width,
|
CreateOffscreenContentDrawTarget(aSize, SurfaceFormat::B8G8R8A8);
|
||||||
imageIntSize.height),
|
|
||||||
SurfaceFormat::B8G8R8A8);
|
|
||||||
if (!dt) {
|
if (!dt) {
|
||||||
NS_ERROR("Could not create a DrawTarget");
|
NS_ERROR("Could not create a DrawTarget");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -708,8 +717,8 @@ VectorImage::GetFrame(uint32_t aWhichFrame,
|
|||||||
|
|
||||||
nsRefPtr<gfxContext> context = new gfxContext(dt);
|
nsRefPtr<gfxContext> context = new gfxContext(dt);
|
||||||
|
|
||||||
auto result = Draw(context, imageIntSize,
|
auto result = Draw(context, aSize,
|
||||||
ImageRegion::Create(imageIntSize),
|
ImageRegion::Create(aSize),
|
||||||
aWhichFrame, GraphicsFilter::FILTER_NEAREST,
|
aWhichFrame, GraphicsFilter::FILTER_NEAREST,
|
||||||
Nothing(), aFlags);
|
Nothing(), aFlags);
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ native nsIntSizeByVal(nsIntSize);
|
|||||||
*
|
*
|
||||||
* Internally, imgIContainer also manages animation of images.
|
* Internally, imgIContainer also manages animation of images.
|
||||||
*/
|
*/
|
||||||
[scriptable, builtinclass, uuid(4880727a-5673-44f7-b248-f6c86e22a434)]
|
[scriptable, builtinclass, uuid(4e5a0547-6c54-4051-8b52-1f2fdd667696)]
|
||||||
interface imgIContainer : nsISupports
|
interface imgIContainer : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@ -267,6 +267,21 @@ interface imgIContainer : nsISupports
|
|||||||
[noscript, notxpcom] TempRefSourceSurface getFrame(in uint32_t aWhichFrame,
|
[noscript, notxpcom] TempRefSourceSurface getFrame(in uint32_t aWhichFrame,
|
||||||
in uint32_t aFlags);
|
in uint32_t aFlags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a surface for the given frame at the specified size. Matching the
|
||||||
|
* requested size is best effort; it's not guaranteed that the surface you get
|
||||||
|
* will be a perfect match. (Some reasons you may get a surface of a different
|
||||||
|
* size include: if you requested upscaling, if downscale-during-decode is
|
||||||
|
* disabled, or if you didn't request the first frame.)
|
||||||
|
*
|
||||||
|
* @param aSize The desired size.
|
||||||
|
* @param aWhichFrame Frame specifier of the FRAME_* variety.
|
||||||
|
* @param aFlags Flags of the FLAG_* variety
|
||||||
|
*/
|
||||||
|
[noscript, notxpcom] TempRefSourceSurface getFrameAtSize([const] in nsIntSize aSize,
|
||||||
|
in uint32_t aWhichFrame,
|
||||||
|
in uint32_t aFlags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether this image is opaque (i.e., needs a background painted behind it).
|
* Whether this image is opaque (i.e., needs a background painted behind it).
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user