зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1711061 - Part 13. Remove the now unused ImageContainer and related code for images. r=tnikkel
Differential Revision: https://phabricator.services.mozilla.com/D126606
This commit is contained in:
Родитель
af4570762c
Коммит
72d1c14b24
|
@ -28,7 +28,6 @@
|
|||
#include "mozilla/layers/LayersMessages.h"
|
||||
#include "mozilla/layers/SharedPlanarYCbCrImage.h"
|
||||
#include "mozilla/layers/SharedRGBImage.h"
|
||||
#include "mozilla/layers/SharedSurfacesChild.h" // for SharedSurfacesAnimation
|
||||
#include "mozilla/layers/TextureClientRecycleAllocator.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsISupportsUtils.h" // for NS_IF_ADDREF
|
||||
|
@ -175,13 +174,6 @@ void ImageContainer::EnsureImageClient() {
|
|||
}
|
||||
}
|
||||
|
||||
SharedSurfacesAnimation* ImageContainer::EnsureSharedSurfacesAnimation() {
|
||||
if (!mSharedAnimation) {
|
||||
mSharedAnimation = new SharedSurfacesAnimation();
|
||||
}
|
||||
return mSharedAnimation;
|
||||
}
|
||||
|
||||
ImageContainer::ImageContainer(Mode flag)
|
||||
: mRecursiveMutex("ImageContainer.mRecursiveMutex"),
|
||||
mGenerationCounter(++sGenerationCounter),
|
||||
|
@ -220,9 +212,6 @@ ImageContainer::~ImageContainer() {
|
|||
imageBridge->ForgetImageContainer(mAsyncContainerHandle);
|
||||
}
|
||||
}
|
||||
if (mSharedAnimation) {
|
||||
mSharedAnimation->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
Maybe<SurfaceDescriptor> Image::GetDesc() { return {}; }
|
||||
|
|
|
@ -48,7 +48,6 @@ class ImageCompositeNotification;
|
|||
class ImageContainer;
|
||||
class ImageContainerChild;
|
||||
class SharedPlanarYCbCrImage;
|
||||
class SharedSurfacesAnimation;
|
||||
class SurfaceDescriptor;
|
||||
class PlanarYCbCrImage;
|
||||
class TextureClient;
|
||||
|
@ -529,12 +528,6 @@ class ImageContainer final : public SupportsThreadSafeWeakPtr<ImageContainer> {
|
|||
|
||||
void DropImageClient();
|
||||
|
||||
SharedSurfacesAnimation* GetSharedSurfacesAnimation() const {
|
||||
return mSharedAnimation;
|
||||
}
|
||||
|
||||
SharedSurfacesAnimation* EnsureSharedSurfacesAnimation();
|
||||
|
||||
private:
|
||||
typedef mozilla::RecursiveMutex RecursiveMutex;
|
||||
|
||||
|
@ -599,8 +592,6 @@ class ImageContainer final : public SupportsThreadSafeWeakPtr<ImageContainer> {
|
|||
// than asynchronusly using the ImageBridge IPDL protocol.
|
||||
RefPtr<ImageClient> mImageClient;
|
||||
|
||||
RefPtr<SharedSurfacesAnimation> mSharedAnimation;
|
||||
|
||||
bool mIsAsync;
|
||||
CompositableHandle mAsyncContainerHandle;
|
||||
|
||||
|
|
|
@ -323,80 +323,6 @@ nsresult SharedSurfacesChild::Share(SourceSurface* aSurface,
|
|||
return Share(sharedSurface, aManager, aResources, aKey);
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult SharedSurfacesChild::Share(ImageContainer* aContainer,
|
||||
RenderRootStateManager* aManager,
|
||||
wr::IpcResourceUpdateQueue& aResources,
|
||||
wr::ImageKey& aKey,
|
||||
ContainerProducerID aProducerId) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aContainer);
|
||||
MOZ_ASSERT(aManager);
|
||||
|
||||
if (aContainer->IsAsync()) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
AutoTArray<ImageContainer::OwningImage, 4> images;
|
||||
aContainer->GetCurrentImages(&images);
|
||||
if (images.IsEmpty()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (aProducerId != kContainerProducerID_Invalid &&
|
||||
images[0].mProducerID != aProducerId) {
|
||||
// If the producer ID of the surface in the container does not match the
|
||||
// expected producer ID, then we do not want to proceed with sharing. This
|
||||
// is useful for when callers are unsure if given container is for the same
|
||||
// producer / underlying image request.
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
RefPtr<gfx::SourceSurface> surface = images[0].mImage->GetAsSourceSurface();
|
||||
if (!surface) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
auto sharedSurface = AsSourceSurfaceSharedData(surface);
|
||||
if (!sharedSurface) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
SharedSurfacesAnimation* anim = aContainer->GetSharedSurfacesAnimation();
|
||||
if (anim) {
|
||||
return anim->UpdateKey(sharedSurface, aManager, aResources, aKey);
|
||||
}
|
||||
|
||||
return Share(sharedSurface, aManager, aResources, aKey);
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult SharedSurfacesChild::ShareBlob(ImageContainer* aContainer,
|
||||
RenderRootStateManager* aManager,
|
||||
wr::IpcResourceUpdateQueue& aResources,
|
||||
wr::BlobImageKey& aKey) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aContainer);
|
||||
MOZ_ASSERT(aManager);
|
||||
|
||||
if (aContainer->IsAsync()) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
AutoTArray<ImageContainer::OwningImage, 4> images;
|
||||
aContainer->GetCurrentImages(&images);
|
||||
if (images.IsEmpty()) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
RefPtr<gfx::SourceSurface> surface = images[0].mImage->GetAsSourceSurface();
|
||||
if (!surface || surface->GetType() != SurfaceType::BLOB_IMAGE) {
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult SharedSurfacesChild::Share(SourceSurface* aSurface,
|
||||
wr::ExternalImageId& aId) {
|
||||
|
@ -466,28 +392,6 @@ void SharedSurfacesChild::Unshare(const wr::ExternalImageId& aId,
|
|||
return Some(data->Id());
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult SharedSurfacesChild::UpdateAnimation(ImageContainer* aContainer,
|
||||
SourceSurface* aSurface,
|
||||
const IntRect& aDirtyRect) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aContainer);
|
||||
MOZ_ASSERT(!aContainer->IsAsync());
|
||||
MOZ_ASSERT(aSurface);
|
||||
|
||||
// If we aren't using shared surfaces, then is nothing to do.
|
||||
auto sharedSurface = SharedSurfacesChild::AsSourceSurfaceSharedData(aSurface);
|
||||
if (!sharedSurface) {
|
||||
MOZ_ASSERT(!aContainer->GetSharedSurfacesAnimation());
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
SharedSurfacesAnimation* anim = aContainer->EnsureSharedSurfacesAnimation();
|
||||
MOZ_ASSERT(anim);
|
||||
|
||||
return anim->SetCurrentFrame(sharedSurface, aDirtyRect);
|
||||
}
|
||||
|
||||
AnimationImageKeyData::AnimationImageKeyData(RenderRootStateManager* aManager,
|
||||
const wr::ImageKey& aImageKey)
|
||||
: SharedSurfacesChild::ImageKeyData(aManager, aImageKey) {}
|
||||
|
|
|
@ -44,7 +44,6 @@ class IpcResourceUpdateQueue;
|
|||
namespace layers {
|
||||
|
||||
class CompositorManagerChild;
|
||||
class ImageContainer;
|
||||
class RenderRootStateManager;
|
||||
|
||||
class SharedSurfacesChild {
|
||||
|
@ -85,23 +84,6 @@ class SharedSurfacesChild {
|
|||
wr::IpcResourceUpdateQueue& aResources,
|
||||
wr::ImageKey& aKey);
|
||||
|
||||
/**
|
||||
* Request that the first surface in the image container's current images be
|
||||
* mapped into the compositor thread's memory space, and a valid ImageKey be
|
||||
* generated for it for use with WebRender. If a different method should be
|
||||
* used to share the image data for this particular container, it will return
|
||||
* NS_ERROR_NOT_IMPLEMENTED. This must be called from the main thread.
|
||||
*/
|
||||
static nsresult Share(ImageContainer* aContainer,
|
||||
RenderRootStateManager* aManager,
|
||||
wr::IpcResourceUpdateQueue& aResources,
|
||||
wr::ImageKey& aKey, ContainerProducerID aProducerId);
|
||||
|
||||
static nsresult ShareBlob(ImageContainer* aContainer,
|
||||
RenderRootStateManager* aManager,
|
||||
wr::IpcResourceUpdateQueue& aResources,
|
||||
wr::BlobImageKey& aKey);
|
||||
|
||||
/**
|
||||
* Get the external ID, if any, bound to the shared surface. Used for memory
|
||||
* reporting purposes.
|
||||
|
@ -116,10 +98,6 @@ class SharedSurfacesChild {
|
|||
static gfx::SourceSurfaceSharedData* AsSourceSurfaceSharedData(
|
||||
gfx::SourceSurface* aSurface);
|
||||
|
||||
static nsresult UpdateAnimation(ImageContainer* aContainer,
|
||||
gfx::SourceSurface* aSurface,
|
||||
const gfx::IntRect& aDirtyRect);
|
||||
|
||||
class ImageKeyData {
|
||||
public:
|
||||
ImageKeyData(RenderRootStateManager* aManager,
|
||||
|
|
|
@ -100,12 +100,12 @@ WebRenderBridgeChild* WebRenderUserData::WrBridge() const {
|
|||
|
||||
WebRenderImageData::WebRenderImageData(RenderRootStateManager* aManager,
|
||||
nsDisplayItem* aItem)
|
||||
: WebRenderUserData(aManager, aItem), mOwnsKey(false) {}
|
||||
: WebRenderUserData(aManager, aItem) {}
|
||||
|
||||
WebRenderImageData::WebRenderImageData(RenderRootStateManager* aManager,
|
||||
uint32_t aDisplayItemKey,
|
||||
nsIFrame* aFrame)
|
||||
: WebRenderUserData(aManager, aDisplayItemKey, aFrame), mOwnsKey(false) {}
|
||||
: WebRenderUserData(aManager, aDisplayItemKey, aFrame) {}
|
||||
|
||||
WebRenderImageData::~WebRenderImageData() {
|
||||
ClearImageKey();
|
||||
|
@ -115,35 +115,15 @@ WebRenderImageData::~WebRenderImageData() {
|
|||
}
|
||||
}
|
||||
|
||||
bool WebRenderImageData::UsingSharedSurface(
|
||||
ContainerProducerID aProducerId) const {
|
||||
if (!mContainer || !mKey || mOwnsKey) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this is just an update with the same image key, then we know that the
|
||||
// share request initiated an asynchronous update so that we don't need to
|
||||
// rebuild the scene.
|
||||
wr::ImageKey key;
|
||||
nsresult rv = SharedSurfacesChild::Share(
|
||||
mContainer, mManager, mManager->AsyncResourceUpdates(), key, aProducerId);
|
||||
return NS_SUCCEEDED(rv) && mKey.ref() == key;
|
||||
}
|
||||
|
||||
void WebRenderImageData::ClearImageKey() {
|
||||
if (mKey) {
|
||||
// If we don't own the key, then the owner is responsible for discarding the
|
||||
// key when appropriate.
|
||||
if (mOwnsKey) {
|
||||
mManager->AddImageKeyForDiscard(mKey.value());
|
||||
if (mTextureOfImage) {
|
||||
WrBridge()->ReleaseTextureOfImage(mKey.value());
|
||||
mTextureOfImage = nullptr;
|
||||
}
|
||||
mManager->AddImageKeyForDiscard(mKey.value());
|
||||
if (mTextureOfImage) {
|
||||
WrBridge()->ReleaseTextureOfImage(mKey.value());
|
||||
mTextureOfImage = nullptr;
|
||||
}
|
||||
mKey.reset();
|
||||
}
|
||||
mOwnsKey = false;
|
||||
MOZ_ASSERT(!mTextureOfImage);
|
||||
}
|
||||
|
||||
|
@ -156,26 +136,6 @@ Maybe<wr::ImageKey> WebRenderImageData::UpdateImageKey(
|
|||
mContainer = aContainer;
|
||||
}
|
||||
|
||||
wr::WrImageKey key;
|
||||
if (!aFallback) {
|
||||
nsresult rv = SharedSurfacesChild::Share(aContainer, mManager, aResources,
|
||||
key, kContainerProducerID_Invalid);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Ensure that any previously owned keys are released before replacing. We
|
||||
// don't own this key, the surface itself owns it, so that it can be
|
||||
// shared across multiple elements.
|
||||
ClearImageKey();
|
||||
mKey = Some(key);
|
||||
return mKey;
|
||||
}
|
||||
|
||||
if (rv != NS_ERROR_NOT_IMPLEMENTED) {
|
||||
// We should be using the shared surface but somehow sharing it failed.
|
||||
ClearImageKey();
|
||||
return Nothing();
|
||||
}
|
||||
}
|
||||
|
||||
CreateImageClientIfNeeded();
|
||||
if (!mImageClient) {
|
||||
return Nothing();
|
||||
|
@ -216,15 +176,13 @@ Maybe<wr::ImageKey> WebRenderImageData::UpdateImageKey(
|
|||
extId.ref(), mKey.ref(), currentTexture, /* aIsUpdate */ true);
|
||||
} else {
|
||||
ClearImageKey();
|
||||
key = WrBridge()->GetNextImageKey();
|
||||
wr::WrImageKey key = WrBridge()->GetNextImageKey();
|
||||
aResources.PushExternalImageForTexture(extId.ref(), key, currentTexture,
|
||||
/* aIsUpdate */ false);
|
||||
mKey = Some(key);
|
||||
}
|
||||
|
||||
mTextureOfImage = currentTexture;
|
||||
mOwnsKey = true;
|
||||
|
||||
return mKey;
|
||||
}
|
||||
|
||||
|
|
|
@ -172,8 +172,6 @@ class WebRenderImageData : public WebRenderUserData {
|
|||
|
||||
bool IsAsync() { return mPipelineId.isSome(); }
|
||||
|
||||
bool UsingSharedSurface(ContainerProducerID aProducerId) const;
|
||||
|
||||
void ClearImageKey();
|
||||
|
||||
protected:
|
||||
|
@ -182,11 +180,6 @@ class WebRenderImageData : public WebRenderUserData {
|
|||
RefPtr<ImageClient> mImageClient;
|
||||
Maybe<wr::PipelineId> mPipelineId;
|
||||
RefPtr<ImageContainer> mContainer;
|
||||
// The key can be owned by a shared surface that is used by several elements.
|
||||
// when this is the case the shared surface is responsible for managing the
|
||||
// destruction of the key.
|
||||
// TODO: we surely can come up with a simpler/safer way to model this.
|
||||
bool mOwnsKey;
|
||||
};
|
||||
|
||||
/// Holds some data used to share ImageLib results with the parent process.
|
||||
|
|
|
@ -297,27 +297,6 @@ ClippedImage::IsImageContainerAvailable(WindowRenderer* aRenderer,
|
|||
return false;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(ImgDrawResult)
|
||||
ClippedImage::GetImageContainerAtSize(WindowRenderer* aRenderer,
|
||||
const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion,
|
||||
uint32_t aFlags,
|
||||
layers::ImageContainer** aOutContainer) {
|
||||
// XXX(seth): We currently don't have a way of clipping the result of
|
||||
// GetImageContainer. We work around this by always returning null, but if it
|
||||
// ever turns out that ClippedImage is widely used on codepaths that can
|
||||
// actually benefit from GetImageContainer, it would be a good idea to fix
|
||||
// that method for performance reasons.
|
||||
|
||||
if (!ShouldClip()) {
|
||||
return InnerImage()->GetImageContainerAtSize(
|
||||
aRenderer, aSize, aSVGContext, aRegion, aFlags, aOutContainer);
|
||||
}
|
||||
|
||||
return ImgDrawResult::NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(ImgDrawResult)
|
||||
ClippedImage::GetImageProvider(WindowRenderer* aRenderer,
|
||||
const gfx::IntSize& aSize,
|
||||
|
|
|
@ -46,11 +46,6 @@ class ClippedImage : public ImageWrapper {
|
|||
IsImageContainerAvailable(WindowRenderer* aRenderer,
|
||||
uint32_t aFlags) override;
|
||||
NS_IMETHOD_(ImgDrawResult)
|
||||
GetImageContainerAtSize(WindowRenderer* aRenderer, const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion, uint32_t aFlags,
|
||||
layers::ImageContainer** aOutContainer) override;
|
||||
NS_IMETHOD_(ImgDrawResult)
|
||||
GetImageProvider(WindowRenderer* aRenderer, const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion, uint32_t aFlags,
|
||||
|
|
|
@ -120,12 +120,6 @@ DynamicImage::GetType(uint16_t* aType) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DynamicImage::GetProducerId(uint32_t* aId) {
|
||||
*aId = 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DynamicImage::GetProviderId(uint32_t* aId) {
|
||||
*aId = 0;
|
||||
|
@ -173,16 +167,6 @@ DynamicImage::IsImageContainerAvailable(WindowRenderer* aRenderer,
|
|||
return false;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(ImgDrawResult)
|
||||
DynamicImage::GetImageContainerAtSize(WindowRenderer* aRenderer,
|
||||
const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion,
|
||||
uint32_t aFlags,
|
||||
layers::ImageContainer** aContainer) {
|
||||
return ImgDrawResult::NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(ImgDrawResult)
|
||||
DynamicImage::GetImageProvider(WindowRenderer* aRenderer,
|
||||
const gfx::IntSize& aSize,
|
||||
|
|
|
@ -59,26 +59,6 @@ FrozenImage::IsImageContainerAvailable(WindowRenderer* aRenderer,
|
|||
return false;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(ImgDrawResult)
|
||||
FrozenImage::GetImageContainerAtSize(WindowRenderer* aRenderer,
|
||||
const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion,
|
||||
uint32_t aFlags,
|
||||
layers::ImageContainer** aOutContainer) {
|
||||
if (IsNonAnimated()) {
|
||||
return InnerImage()->GetImageContainerAtSize(
|
||||
aRenderer, aSize, aSVGContext, aRegion, aFlags, aOutContainer);
|
||||
}
|
||||
|
||||
// XXX(seth): GetImageContainer does not currently support anything but the
|
||||
// current frame. We work around this by always returning null, but if it ever
|
||||
// turns out that FrozenImage is widely used on codepaths that can actually
|
||||
// benefit from GetImageContainer, it would be a good idea to fix that method
|
||||
// for performance reasons.
|
||||
return ImgDrawResult::NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(ImgDrawResult)
|
||||
FrozenImage::GetImageProvider(WindowRenderer* aRenderer,
|
||||
const gfx::IntSize& aSize,
|
||||
|
|
|
@ -45,11 +45,6 @@ class FrozenImage : public ImageWrapper {
|
|||
IsImageContainerAvailable(WindowRenderer* aRenderer,
|
||||
uint32_t aFlags) override;
|
||||
NS_IMETHOD_(ImgDrawResult)
|
||||
GetImageContainerAtSize(WindowRenderer* aRenderer, const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion, uint32_t aFlags,
|
||||
layers::ImageContainer** aOutContainer) override;
|
||||
NS_IMETHOD_(ImgDrawResult)
|
||||
GetImageProvider(WindowRenderer* aRenderer, const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion, uint32_t aFlags,
|
||||
|
|
278
image/Image.cpp
278
image/Image.cpp
|
@ -120,284 +120,10 @@ bool ImageResource::GetSpecTruncatedTo1k(nsCString& aSpec) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
void ImageResource::SetCurrentImage(layers::ImageContainer* aContainer,
|
||||
gfx::SourceSurface* aSurface,
|
||||
const Maybe<gfx::IntRect>& aDirtyRect) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aContainer);
|
||||
|
||||
if (!aSurface) {
|
||||
// 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.
|
||||
return;
|
||||
}
|
||||
|
||||
// |image| holds a reference to a SourceSurface which in turn holds a lock on
|
||||
// the current frame's data buffer, ensuring that it doesn't get freed as
|
||||
// long as the layer system keeps this ImageContainer alive.
|
||||
RefPtr<layers::Image> image = new layers::SourceSurfaceImage(aSurface);
|
||||
|
||||
// We can share the producer ID with other containers because it is only
|
||||
// used internally to validate the frames given to a particular container
|
||||
// so that another object cannot add its own. Similarly the frame ID is
|
||||
// only used internally to ensure it is always increasing, and skipping
|
||||
// IDs from an individual container's perspective is acceptable.
|
||||
AutoTArray<layers::ImageContainer::NonOwningImage, 1> imageList;
|
||||
imageList.AppendElement(layers::ImageContainer::NonOwningImage(
|
||||
image, TimeStamp(), mLastFrameID++, mImageProducerID));
|
||||
|
||||
if (aDirtyRect) {
|
||||
aContainer->SetCurrentImagesInTransaction(imageList);
|
||||
} else {
|
||||
aContainer->SetCurrentImages(imageList);
|
||||
}
|
||||
|
||||
// If we are animated, then we should request that the image container be
|
||||
// treated as such, to avoid display list rebuilding to update frames for
|
||||
// WebRender.
|
||||
if (mProgressTracker->GetProgress() & FLAG_IS_ANIMATED) {
|
||||
if (aDirtyRect) {
|
||||
layers::SharedSurfacesChild::UpdateAnimation(aContainer, aSurface,
|
||||
aDirtyRect.ref());
|
||||
} else {
|
||||
gfx::IntRect dirtyRect(gfx::IntPoint(0, 0), aSurface->GetSize());
|
||||
layers::SharedSurfacesChild::UpdateAnimation(aContainer, aSurface,
|
||||
dirtyRect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImgDrawResult ImageResource::GetImageContainerImpl(
|
||||
WindowRenderer* aRenderer, const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion, uint32_t aFlags,
|
||||
layers::ImageContainer** aOutContainer) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aRenderer);
|
||||
MOZ_ASSERT(
|
||||
(aFlags & ~(FLAG_SYNC_DECODE | FLAG_SYNC_DECODE_IF_FAST |
|
||||
FLAG_ASYNC_NOTIFY | FLAG_HIGH_QUALITY_SCALING)) == FLAG_NONE,
|
||||
"Unsupported flag passed to GetImageContainer");
|
||||
|
||||
ImgDrawResult drawResult;
|
||||
gfx::IntSize size;
|
||||
Tie(drawResult, size) = GetImageContainerSize(aRenderer, aSize, aFlags);
|
||||
if (drawResult != ImgDrawResult::SUCCESS) {
|
||||
return drawResult;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!size.IsEmpty());
|
||||
|
||||
if (mAnimationConsumers == 0) {
|
||||
SendOnUnlockedDraw(aFlags);
|
||||
}
|
||||
|
||||
uint32_t flags = (aFlags & ~(FLAG_SYNC_DECODE | FLAG_SYNC_DECODE_IF_FAST)) |
|
||||
FLAG_ASYNC_NOTIFY;
|
||||
RefPtr<layers::ImageContainer> container;
|
||||
ImageContainerEntry* entry = nullptr;
|
||||
int i = mImageContainers.Length() - 1;
|
||||
for (; i >= 0; --i) {
|
||||
entry = &mImageContainers[i];
|
||||
if (size == entry->mSize && flags == entry->mFlags &&
|
||||
aSVGContext == entry->mSVGContext && aRegion == entry->mRegion) {
|
||||
// Lack of a container is handled below.
|
||||
container = RefPtr<layers::ImageContainer>(entry->mContainer);
|
||||
break;
|
||||
} else if (entry->mContainer.IsDead()) {
|
||||
// Stop tracking if our weak pointer to the image container was freed.
|
||||
mImageContainers.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (container) {
|
||||
switch (entry->mLastDrawResult) {
|
||||
case ImgDrawResult::SUCCESS:
|
||||
case ImgDrawResult::BAD_IMAGE:
|
||||
case ImgDrawResult::BAD_ARGS:
|
||||
case ImgDrawResult::NOT_SUPPORTED:
|
||||
container.forget(aOutContainer);
|
||||
return entry->mLastDrawResult;
|
||||
case ImgDrawResult::NOT_READY:
|
||||
case ImgDrawResult::INCOMPLETE:
|
||||
case ImgDrawResult::TEMPORARY_ERROR:
|
||||
// Temporary conditions where we need to rerequest the frame to recover.
|
||||
break;
|
||||
case ImgDrawResult::WRONG_SIZE:
|
||||
// Unused by GetFrameInternal
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unhandled ImgDrawResult type!");
|
||||
container.forget(aOutContainer);
|
||||
return entry->mLastDrawResult;
|
||||
}
|
||||
}
|
||||
|
||||
AutoProfilerImagePaintMarker PROFILER_RAII(this);
|
||||
#ifdef DEBUG
|
||||
NotifyDrawingObservers();
|
||||
#endif
|
||||
|
||||
gfx::IntSize bestSize;
|
||||
RefPtr<gfx::SourceSurface> surface;
|
||||
Tie(drawResult, bestSize, surface) = GetFrameInternal(
|
||||
size, aSVGContext, aRegion, FRAME_CURRENT, aFlags | FLAG_ASYNC_NOTIFY);
|
||||
|
||||
// The requested size might be refused by the surface cache (i.e. due to
|
||||
// factor-of-2 mode). In that case we don't want to create an entry for this
|
||||
// specific size, but rather re-use the entry for the substituted size.
|
||||
if (bestSize != size) {
|
||||
MOZ_ASSERT(!bestSize.IsEmpty());
|
||||
|
||||
// We can only remove the entry if we no longer have a container, because if
|
||||
// there are strong references to it remaining, we need to still update it
|
||||
// in UpdateImageContainer.
|
||||
if (i >= 0 && !container) {
|
||||
mImageContainers.RemoveElementAt(i);
|
||||
}
|
||||
|
||||
// Forget about the stale container, if any. This lets the entry creation
|
||||
// logic do its job below, if it turns out there is no existing best entry
|
||||
// or the best entry doesn't have a container.
|
||||
container = nullptr;
|
||||
|
||||
// We need to do the entry search again for the new size. We skip pruning
|
||||
// because we did this above once already, but ImageContainer is threadsafe,
|
||||
// so there is a remote possibility it got freed.
|
||||
i = mImageContainers.Length() - 1;
|
||||
for (; i >= 0; --i) {
|
||||
entry = &mImageContainers[i];
|
||||
if (bestSize == entry->mSize && flags == entry->mFlags &&
|
||||
aSVGContext == entry->mSVGContext && aRegion == entry->mRegion) {
|
||||
container = RefPtr<layers::ImageContainer>(entry->mContainer);
|
||||
if (container) {
|
||||
switch (entry->mLastDrawResult) {
|
||||
case ImgDrawResult::SUCCESS:
|
||||
case ImgDrawResult::BAD_IMAGE:
|
||||
case ImgDrawResult::BAD_ARGS:
|
||||
case ImgDrawResult::NOT_SUPPORTED:
|
||||
container.forget(aOutContainer);
|
||||
return entry->mLastDrawResult;
|
||||
case ImgDrawResult::NOT_READY:
|
||||
case ImgDrawResult::INCOMPLETE:
|
||||
case ImgDrawResult::TEMPORARY_ERROR:
|
||||
// Temporary conditions where we need to rerequest the frame to
|
||||
// recover. We have already done so!
|
||||
break;
|
||||
case ImgDrawResult::WRONG_SIZE:
|
||||
// Unused by GetFrameInternal
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unhandled DrawResult type!");
|
||||
container.forget(aOutContainer);
|
||||
return entry->mLastDrawResult;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!container) {
|
||||
// We need a new ImageContainer, so create one.
|
||||
container = MakeAndAddRef<layers::ImageContainer>();
|
||||
|
||||
if (i >= 0) {
|
||||
entry->mContainer = container;
|
||||
} else {
|
||||
entry = mImageContainers.AppendElement(ImageContainerEntry(
|
||||
bestSize, aSVGContext, aRegion, container.get(), flags));
|
||||
}
|
||||
}
|
||||
|
||||
SetCurrentImage(container, surface, Nothing());
|
||||
entry->mLastDrawResult = drawResult;
|
||||
container.forget(aOutContainer);
|
||||
return drawResult;
|
||||
}
|
||||
|
||||
bool ImageResource::UpdateImageContainer(
|
||||
const Maybe<gfx::IntRect>& aDirtyRect) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
for (int i = mImageContainers.Length() - 1; i >= 0; --i) {
|
||||
ImageContainerEntry& entry = mImageContainers[i];
|
||||
RefPtr<layers::ImageContainer> container(entry.mContainer);
|
||||
if (container) {
|
||||
gfx::IntSize bestSize;
|
||||
RefPtr<gfx::SourceSurface> surface;
|
||||
Tie(entry.mLastDrawResult, bestSize, surface) =
|
||||
GetFrameInternal(entry.mSize, entry.mSVGContext, entry.mRegion,
|
||||
FRAME_CURRENT, entry.mFlags);
|
||||
|
||||
// It is possible that this is a factor-of-2 substitution. Since we
|
||||
// managed to convert the weak reference into a strong reference, that
|
||||
// means that an imagelib user still is holding onto the container. thus
|
||||
// we cannot consolidate and must keep updating the duplicate container.
|
||||
if (aDirtyRect) {
|
||||
SetCurrentImage(container, surface, aDirtyRect);
|
||||
} else {
|
||||
gfx::IntRect dirtyRect(gfx::IntPoint(0, 0), bestSize);
|
||||
SetCurrentImage(container, surface, Some(dirtyRect));
|
||||
}
|
||||
} else {
|
||||
// Stop tracking if our weak pointer to the image container was freed.
|
||||
mImageContainers.RemoveElementAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
return !mImageContainers.IsEmpty();
|
||||
}
|
||||
|
||||
void ImageResource::CollectSizeOfSurfaces(
|
||||
nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf) const {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
for (const auto& entry : mImageContainers) {
|
||||
RefPtr<layers::ImageContainer> container(entry.mContainer);
|
||||
if (!container) {
|
||||
continue;
|
||||
}
|
||||
|
||||
AutoTArray<layers::ImageContainer::OwningImage, 1> images;
|
||||
container->GetCurrentImages(&images);
|
||||
if (images.IsEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RefPtr<gfx::SourceSurface> surface = images[0].mImage->GetAsSourceSurface();
|
||||
if (!surface) {
|
||||
MOZ_ASSERT_UNREACHABLE("No surface in container!");
|
||||
continue;
|
||||
}
|
||||
|
||||
// The surface isn't in the report, so it isn't stored in SurfaceCache. We
|
||||
// need to add our own entry here so that it will be included in the memory
|
||||
// report.
|
||||
gfx::SourceSurface::SizeOfInfo info;
|
||||
surface->SizeOfExcludingThis(aMallocSizeOf, info);
|
||||
|
||||
uint32_t heapBytes = aMallocSizeOf(surface);
|
||||
SurfaceKey key = ContainerSurfaceKey(surface->GetSize(), entry.mSVGContext,
|
||||
ToSurfaceFlags(entry.mFlags));
|
||||
SurfaceMemoryCounter counter(key, /* aIsLocked */ false,
|
||||
/* aCannotSubstitute */ false,
|
||||
/* aIsFactor2 */ false, /* aFinished */ true,
|
||||
SurfaceMemoryCounterType::CONTAINER);
|
||||
|
||||
counter.Values().SetDecodedHeap(info.mHeapBytes + heapBytes);
|
||||
counter.Values().SetDecodedNonHeap(info.mNonHeapBytes);
|
||||
counter.Values().SetDecodedUnknown(info.mUnknownBytes);
|
||||
counter.Values().SetExternalHandles(info.mExternalHandles);
|
||||
counter.Values().SetExternalId(info.mExternalId);
|
||||
counter.Values().SetSurfaceTypes(info.mTypes);
|
||||
|
||||
aCounters.AppendElement(counter);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageResource::ReleaseImageContainer() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
mImageContainers.Clear();
|
||||
SurfaceCache::CollectSizeOfSurfaces(ImageKey(this), aCounters, aMallocSizeOf);
|
||||
}
|
||||
|
||||
// Constructor
|
||||
|
@ -409,8 +135,6 @@ ImageResource::ImageResource(nsIURI* aURI)
|
|||
mInitialized(false),
|
||||
mAnimating(false),
|
||||
mError(false),
|
||||
mImageProducerID(layers::ImageContainer::AllocateProducerID()),
|
||||
mLastFrameID(0),
|
||||
mProviderId(WebRenderImageProvider::AllocateProviderId()) {}
|
||||
|
||||
ImageResource::~ImageResource() {
|
||||
|
|
|
@ -332,10 +332,6 @@ class ImageResource : public Image {
|
|||
explicit ImageResource(nsIURI* aURI);
|
||||
~ImageResource();
|
||||
|
||||
layers::ContainerProducerID GetImageProducerId() const {
|
||||
return mImageProducerID;
|
||||
}
|
||||
|
||||
bool GetSpecTruncatedTo1k(nsCString& aSpec) const;
|
||||
|
||||
// Shared functionality for implementors of imgIContainer. Every
|
||||
|
@ -389,60 +385,6 @@ class ImageResource : public Image {
|
|||
bool mAnimating : 1; // Are we currently animating?
|
||||
bool mError : 1; // Error handling
|
||||
|
||||
/**
|
||||
* Attempt to find a matching cached surface in the SurfaceCache, and if not
|
||||
* available, request the production of such a surface (either synchronously
|
||||
* or asynchronously).
|
||||
*
|
||||
* If the draw result is BAD_IMAGE, BAD_ARGS or NOT_READY, the size will be
|
||||
* the same as aSize. If it is TEMPORARY_ERROR, INCOMPLETE, or SUCCESS, the
|
||||
* size is a hint as to what we expect the surface size to be, once the best
|
||||
* fitting size is available. It may or may not match the size of the surface
|
||||
* returned at this moment. This is useful for choosing how to store the final
|
||||
* result (e.g. if going into an ImageContainer, ideally we would share the
|
||||
* same container for many requested sizes, if they all end up with the same
|
||||
* best fit size in the end).
|
||||
*
|
||||
* A valid surface should only be returned for SUCCESS and INCOMPLETE.
|
||||
*
|
||||
* Any other draw result is invalid.
|
||||
*/
|
||||
virtual Tuple<ImgDrawResult, gfx::IntSize, RefPtr<gfx::SourceSurface>>
|
||||
GetFrameInternal(const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion, uint32_t aWhichFrame,
|
||||
uint32_t aFlags) {
|
||||
return MakeTuple(ImgDrawResult::BAD_IMAGE, aSize,
|
||||
RefPtr<gfx::SourceSurface>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the estimated size to use for an image container with the given
|
||||
* parameters. It may not be the same as the given size, and it may not be
|
||||
* the same as the size of the surface in the image container, but it is the
|
||||
* best effort estimate.
|
||||
*/
|
||||
virtual Tuple<ImgDrawResult, gfx::IntSize> GetImageContainerSize(
|
||||
WindowRenderer* aRenderer, const gfx::IntSize& aSize, uint32_t aFlags) {
|
||||
return MakeTuple(ImgDrawResult::NOT_SUPPORTED, gfx::IntSize(0, 0));
|
||||
}
|
||||
|
||||
ImgDrawResult GetImageContainerImpl(WindowRenderer* aRenderer,
|
||||
const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion,
|
||||
uint32_t aFlags,
|
||||
layers::ImageContainer** aContainer);
|
||||
|
||||
/**
|
||||
* Re-requests the appropriate frames for each image container using
|
||||
* GetFrameInternal.
|
||||
* @returns True if any image containers were updated, else false.
|
||||
*/
|
||||
bool UpdateImageContainer(const Maybe<gfx::IntRect>& aDirtyRect);
|
||||
|
||||
void ReleaseImageContainer();
|
||||
|
||||
class MOZ_RAII AutoProfilerImagePaintMarker {
|
||||
public:
|
||||
explicit AutoProfilerImagePaintMarker(ImageResource* self)
|
||||
|
@ -471,39 +413,6 @@ class ImageResource : public Image {
|
|||
};
|
||||
|
||||
private:
|
||||
void SetCurrentImage(layers::ImageContainer* aContainer,
|
||||
gfx::SourceSurface* aSurface,
|
||||
const Maybe<gfx::IntRect>& aDirtyRect);
|
||||
|
||||
struct ImageContainerEntry {
|
||||
ImageContainerEntry(const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion,
|
||||
layers::ImageContainer* aContainer, uint32_t aFlags)
|
||||
: mSize(aSize),
|
||||
mSVGContext(aSVGContext),
|
||||
mRegion(aRegion),
|
||||
mContainer(aContainer),
|
||||
mLastDrawResult(ImgDrawResult::NOT_READY),
|
||||
mFlags(aFlags) {}
|
||||
|
||||
gfx::IntSize mSize;
|
||||
Maybe<SVGImageContext> mSVGContext;
|
||||
Maybe<ImageIntRegion> mRegion;
|
||||
// A weak pointer to our ImageContainer, which stays alive only as long as
|
||||
// the layer system needs it.
|
||||
ThreadSafeWeakPtr<layers::ImageContainer> mContainer;
|
||||
// If mContainer is non-null, this contains the ImgDrawResult we obtained
|
||||
// the last time we updated it.
|
||||
ImgDrawResult mLastDrawResult;
|
||||
// Cached flags to use for decoding. FLAG_ASYNC_NOTIFY should always be set
|
||||
// but FLAG_HIGH_QUALITY_SCALING may vary.
|
||||
uint32_t mFlags;
|
||||
};
|
||||
|
||||
AutoTArray<ImageContainerEntry, 1> mImageContainers;
|
||||
layers::ImageContainer::ProducerID mImageProducerID;
|
||||
layers::ImageContainer::FrameID mLastFrameID;
|
||||
ImageProviderId mProviderId;
|
||||
};
|
||||
|
||||
|
|
|
@ -137,11 +137,6 @@ ImageWrapper::GetResolution() { return mInnerImage->GetResolution(); }
|
|||
NS_IMETHODIMP
|
||||
ImageWrapper::GetType(uint16_t* aType) { return mInnerImage->GetType(aType); }
|
||||
|
||||
NS_IMETHODIMP
|
||||
ImageWrapper::GetProducerId(uint32_t* aId) {
|
||||
return mInnerImage->GetProducerId(aId);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ImageWrapper::GetProviderId(uint32_t* aId) {
|
||||
return mInnerImage->GetProviderId(aId);
|
||||
|
@ -172,17 +167,6 @@ ImageWrapper::IsImageContainerAvailable(WindowRenderer* aRenderer,
|
|||
return mInnerImage->IsImageContainerAvailable(aRenderer, aFlags);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(ImgDrawResult)
|
||||
ImageWrapper::GetImageContainerAtSize(WindowRenderer* aRenderer,
|
||||
const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion,
|
||||
uint32_t aFlags,
|
||||
layers::ImageContainer** aOutContainer) {
|
||||
return mInnerImage->GetImageContainerAtSize(aRenderer, aSize, aSVGContext,
|
||||
aRegion, aFlags, aOutContainer);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(ImgDrawResult)
|
||||
ImageWrapper::GetImageProvider(WindowRenderer* aRenderer,
|
||||
const gfx::IntSize& aSize,
|
||||
|
|
|
@ -155,26 +155,6 @@ OrientedImage::IsImageContainerAvailable(WindowRenderer* aRenderer,
|
|||
return false;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(ImgDrawResult)
|
||||
OrientedImage::GetImageContainerAtSize(
|
||||
WindowRenderer* aRenderer, const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion, uint32_t aFlags,
|
||||
layers::ImageContainer** aOutContainer) {
|
||||
// XXX(seth): We currently don't have a way of orienting the result of
|
||||
// GetImageContainer. We work around this by always returning null, but if it
|
||||
// ever turns out that OrientedImage is widely used on codepaths that can
|
||||
// actually benefit from GetImageContainer, it would be a good idea to fix
|
||||
// that method for performance reasons.
|
||||
|
||||
if (mOrientation.IsIdentity()) {
|
||||
return InnerImage()->GetImageContainerAtSize(
|
||||
aRenderer, aSize, aSVGContext, aRegion, aFlags, aOutContainer);
|
||||
}
|
||||
|
||||
return ImgDrawResult::NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(ImgDrawResult)
|
||||
OrientedImage::GetImageProvider(WindowRenderer* aRenderer,
|
||||
const gfx::IntSize& aSize,
|
||||
|
|
|
@ -41,11 +41,6 @@ class OrientedImage : public ImageWrapper {
|
|||
IsImageContainerAvailable(WindowRenderer* aRenderer,
|
||||
uint32_t aFlags) override;
|
||||
NS_IMETHOD_(ImgDrawResult)
|
||||
GetImageContainerAtSize(WindowRenderer* aRenderer, const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion, uint32_t aFlags,
|
||||
layers::ImageContainer** aOutContainer) override;
|
||||
NS_IMETHOD_(ImgDrawResult)
|
||||
GetImageProvider(WindowRenderer* aRenderer, const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion, uint32_t aFlags,
|
||||
|
|
|
@ -272,14 +272,6 @@ RasterImage::GetType(uint16_t* aType) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RasterImage::GetProducerId(uint32_t* aId) {
|
||||
NS_ENSURE_ARG_POINTER(aId);
|
||||
|
||||
*aId = ImageResource::GetImageProducerId();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RasterImage::GetProviderId(uint32_t* aId) {
|
||||
NS_ENSURE_ARG_POINTER(aId);
|
||||
|
@ -487,7 +479,6 @@ void RasterImage::OnSurfaceDiscardedInternal(bool aAnimatedFramesDiscarded) {
|
|||
|
||||
if (aAnimatedFramesDiscarded && mAnimationState) {
|
||||
MOZ_ASSERT(StaticPrefs::image_mem_animated_discardable_AtStartup());
|
||||
ReleaseImageContainer();
|
||||
|
||||
IntRect rect = mAnimationState->UpdateState(this, mSize.ToUnknownSize());
|
||||
|
||||
|
@ -554,91 +545,30 @@ RasterImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) {
|
|||
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
|
||||
RasterImage::GetFrameAtSize(const IntSize& aSize, uint32_t aWhichFrame,
|
||||
uint32_t aFlags) {
|
||||
MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE);
|
||||
|
||||
AutoProfilerImagePaintMarker PROFILER_RAII(this);
|
||||
#ifdef DEBUG
|
||||
NotifyDrawingObservers();
|
||||
#endif
|
||||
|
||||
auto result =
|
||||
GetFrameInternal(aSize, Nothing(), Nothing(), aWhichFrame, aFlags);
|
||||
return mozilla::Get<2>(result).forget();
|
||||
}
|
||||
|
||||
Tuple<ImgDrawResult, IntSize, RefPtr<SourceSurface>>
|
||||
RasterImage::GetFrameInternal(const IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion,
|
||||
uint32_t aWhichFrame, uint32_t aFlags) {
|
||||
MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE);
|
||||
if (aSize.IsEmpty() || aWhichFrame > FRAME_MAX_VALUE || mError) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto size = OrientedIntSize::FromUnknownSize(aSize);
|
||||
|
||||
if (aSize.IsEmpty() || aWhichFrame > FRAME_MAX_VALUE) {
|
||||
return MakeTuple(ImgDrawResult::BAD_ARGS, aSize, RefPtr<SourceSurface>());
|
||||
}
|
||||
|
||||
if (mError) {
|
||||
return MakeTuple(ImgDrawResult::BAD_IMAGE, aSize, RefPtr<SourceSurface>());
|
||||
}
|
||||
|
||||
// Get the frame. If it's not there, it's probably the caller's fault for
|
||||
// not waiting for the data to be loaded from the network or not passing
|
||||
// FLAG_SYNC_DECODE.
|
||||
LookupResult result = LookupFrame(size, aFlags, ToPlaybackType(aWhichFrame),
|
||||
/* aMarkUsed = */ true);
|
||||
|
||||
// The surface cache may have suggested we use a different size than the
|
||||
// given size in the future. This may or may not be accompanied by an
|
||||
// actual surface, depending on what it has in its cache.
|
||||
auto suggestedSize = OrientedIntSize::FromUnknownSize(result.SuggestedSize());
|
||||
if (suggestedSize.IsEmpty()) {
|
||||
suggestedSize = size;
|
||||
}
|
||||
MOZ_ASSERT_IF(result.Type() == MatchType::SUBSTITUTE_BECAUSE_BEST,
|
||||
suggestedSize != size);
|
||||
|
||||
if (!result) {
|
||||
// The OS threw this frame away and we couldn't redecode it.
|
||||
return MakeTuple(ImgDrawResult::TEMPORARY_ERROR,
|
||||
suggestedSize.ToUnknownSize(), RefPtr<SourceSurface>());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<SourceSurface> surface = result.Surface()->GetSourceSurface();
|
||||
if (!result.Surface()->IsFinished()) {
|
||||
return MakeTuple(ImgDrawResult::INCOMPLETE, suggestedSize.ToUnknownSize(),
|
||||
std::move(surface));
|
||||
}
|
||||
|
||||
return MakeTuple(ImgDrawResult::SUCCESS, suggestedSize.ToUnknownSize(),
|
||||
std::move(surface));
|
||||
}
|
||||
|
||||
Tuple<ImgDrawResult, IntSize> RasterImage::GetImageContainerSize(
|
||||
WindowRenderer* aRenderer, const IntSize& aRequestedSize, uint32_t aFlags) {
|
||||
if (!LoadHasSize()) {
|
||||
return MakeTuple(ImgDrawResult::NOT_READY, IntSize(0, 0));
|
||||
}
|
||||
|
||||
if (aRequestedSize.IsEmpty()) {
|
||||
return MakeTuple(ImgDrawResult::BAD_ARGS, IntSize(0, 0));
|
||||
}
|
||||
|
||||
// We check the minimum size because while we support downscaling, we do not
|
||||
// support upscaling. If aRequestedSize > mSize, we will never give a larger
|
||||
// surface than mSize. If mSize > aRequestedSize, and mSize > maxTextureSize,
|
||||
// we still want to use image containers if aRequestedSize <= maxTextureSize.
|
||||
int32_t maxTextureSize = aRenderer->GetMaxTextureSize();
|
||||
if (min(mSize.width, aRequestedSize.width) > maxTextureSize ||
|
||||
min(mSize.height, aRequestedSize.height) > maxTextureSize) {
|
||||
return MakeTuple(ImgDrawResult::NOT_SUPPORTED, IntSize(0, 0));
|
||||
}
|
||||
|
||||
auto requestedSize = OrientedIntSize::FromUnknownSize(aRequestedSize);
|
||||
if (!CanDownscaleDuringDecode(requestedSize, aFlags)) {
|
||||
return MakeTuple(ImgDrawResult::SUCCESS, mSize.ToUnknownSize());
|
||||
}
|
||||
|
||||
return MakeTuple(ImgDrawResult::SUCCESS, aRequestedSize);
|
||||
return result.Surface()->GetSourceSurface();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
|
@ -647,20 +577,6 @@ RasterImage::IsImageContainerAvailable(WindowRenderer* aRenderer,
|
|||
return LoadHasSize();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(ImgDrawResult)
|
||||
RasterImage::GetImageContainerAtSize(WindowRenderer* aRenderer,
|
||||
const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion,
|
||||
uint32_t aFlags,
|
||||
layers::ImageContainer** aOutContainer) {
|
||||
// We do not pass in the given SVG context because in theory it could differ
|
||||
// between calls, but actually have no impact on the actual contents of the
|
||||
// image container.
|
||||
return GetImageContainerImpl(aRenderer, aSize, Nothing(), Nothing(), aFlags,
|
||||
aOutContainer);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(ImgDrawResult)
|
||||
RasterImage::GetImageProvider(WindowRenderer* aRenderer,
|
||||
const gfx::IntSize& aSize,
|
||||
|
@ -724,13 +640,6 @@ size_t RasterImage::SizeOfSourceWithComputedFallback(
|
|||
aState.mMallocSizeOf);
|
||||
}
|
||||
|
||||
void RasterImage::CollectSizeOfSurfaces(
|
||||
nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf) const {
|
||||
SurfaceCache::CollectSizeOfSurfaces(ImageKey(this), aCounters, aMallocSizeOf);
|
||||
ImageResource::CollectSizeOfSurfaces(aCounters, aMallocSizeOf);
|
||||
}
|
||||
|
||||
bool RasterImage::SetMetadata(const ImageMetadata& aMetadata,
|
||||
bool aFromMetadataDecode) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
@ -1058,8 +967,6 @@ void RasterImage::Discard() {
|
|||
SurfaceCache::RemoveImage(ImageKey(this));
|
||||
|
||||
if (mAnimationState) {
|
||||
ReleaseImageContainer();
|
||||
|
||||
IntRect rect = mAnimationState->UpdateState(this, mSize.ToUnknownSize());
|
||||
|
||||
auto dirtyRect = OrientedIntRect::FromUnknownRect(rect);
|
||||
|
@ -1663,13 +1570,6 @@ void RasterImage::NotifyProgress(
|
|||
}
|
||||
}
|
||||
|
||||
const bool wasDefaultFlags = aSurfaceFlags == DefaultSurfaceFlags();
|
||||
|
||||
if (!invalidRect.IsEmpty() && wasDefaultFlags) {
|
||||
// Update our image container since we're invalidating.
|
||||
UpdateImageContainer(Some(invalidRect.ToUnknownRect()));
|
||||
}
|
||||
|
||||
// Tell the observers what happened.
|
||||
image->mProgressTracker->SyncNotifyProgress(aProgress,
|
||||
invalidRect.ToUnknownRect());
|
||||
|
|
|
@ -166,8 +166,6 @@ class RasterImage final : public ImageResource,
|
|||
|
||||
virtual size_t SizeOfSourceWithComputedFallback(
|
||||
SizeOfState& aState) const override;
|
||||
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
/* Triggers discarding. */
|
||||
void Discard();
|
||||
|
@ -292,16 +290,6 @@ class RasterImage final : public ImageResource,
|
|||
gfx::SamplingFilter aSamplingFilter,
|
||||
uint32_t aFlags, float aOpacity);
|
||||
|
||||
Tuple<ImgDrawResult, gfx::IntSize, RefPtr<gfx::SourceSurface>>
|
||||
GetFrameInternal(const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion, uint32_t aWhichFrame,
|
||||
uint32_t aFlags) override;
|
||||
|
||||
Tuple<ImgDrawResult, gfx::IntSize> GetImageContainerSize(
|
||||
WindowRenderer* aRenderer, const gfx::IntSize& aSize,
|
||||
uint32_t aFlags) override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Decoding.
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -102,9 +102,6 @@ class SurfaceKey {
|
|||
const Maybe<ImageIntRegion>&,
|
||||
const Maybe<SVGImageContext>&,
|
||||
SurfaceFlags, PlaybackType);
|
||||
friend SurfaceKey ContainerSurfaceKey(
|
||||
const gfx::IntSize& aSize, const Maybe<SVGImageContext>& aSVGContext,
|
||||
SurfaceFlags aFlags);
|
||||
|
||||
IntSize mSize;
|
||||
Maybe<ImageIntRegion> mRegion;
|
||||
|
@ -138,13 +135,6 @@ inline SurfaceKey VectorSurfaceKey(const gfx::IntSize& aSize,
|
|||
DefaultSurfaceFlags());
|
||||
}
|
||||
|
||||
inline SurfaceKey ContainerSurfaceKey(const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
SurfaceFlags aFlags) {
|
||||
return SurfaceKey(aSize, Nothing(), aSVGContext, PlaybackType::eStatic,
|
||||
aFlags);
|
||||
}
|
||||
|
||||
/**
|
||||
* AvailabilityState is used to track whether an ISurfaceProvider has a surface
|
||||
* available or is just a placeholder.
|
||||
|
|
|
@ -372,13 +372,6 @@ size_t VectorImage::SizeOfSourceWithComputedFallback(
|
|||
return windowSizes.getTotalSize();
|
||||
}
|
||||
|
||||
void VectorImage::CollectSizeOfSurfaces(
|
||||
nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf) const {
|
||||
SurfaceCache::CollectSizeOfSurfaces(ImageKey(this), aCounters, aMallocSizeOf);
|
||||
ImageResource::CollectSizeOfSurfaces(aCounters, aMallocSizeOf);
|
||||
}
|
||||
|
||||
nsresult VectorImage::OnImageDataComplete(nsIRequest* aRequest,
|
||||
nsresult aStatus, bool aLastPart) {
|
||||
// Call our internal OnStopRequest method, which only talks to our embedded
|
||||
|
@ -615,15 +608,6 @@ VectorImage::GetType(uint16_t* aType) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
NS_IMETHODIMP
|
||||
VectorImage::GetProducerId(uint32_t* aId) {
|
||||
NS_ENSURE_ARG_POINTER(aId);
|
||||
|
||||
*aId = ImageResource::GetImageProducerId();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
NS_IMETHODIMP
|
||||
VectorImage::GetProviderId(uint32_t* aId) {
|
||||
|
@ -692,33 +676,16 @@ VectorImage::GetFrame(uint32_t aWhichFrame, uint32_t aFlags) {
|
|||
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
|
||||
VectorImage::GetFrameAtSize(const IntSize& aSize, uint32_t aWhichFrame,
|
||||
uint32_t aFlags) {
|
||||
MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE);
|
||||
|
||||
AutoProfilerImagePaintMarker PROFILER_RAII(this);
|
||||
#ifdef DEBUG
|
||||
NotifyDrawingObservers();
|
||||
#endif
|
||||
|
||||
auto result =
|
||||
GetFrameInternal(aSize, Nothing(), Nothing(), aWhichFrame, aFlags);
|
||||
return Get<2>(result).forget();
|
||||
}
|
||||
|
||||
Tuple<ImgDrawResult, IntSize, RefPtr<SourceSurface>>
|
||||
VectorImage::GetFrameInternal(const IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion,
|
||||
uint32_t aWhichFrame, uint32_t aFlags) {
|
||||
MOZ_ASSERT(aWhichFrame <= FRAME_MAX_VALUE);
|
||||
|
||||
if (aSize.IsEmpty() || aWhichFrame > FRAME_MAX_VALUE) {
|
||||
return MakeTuple(ImgDrawResult::BAD_ARGS, aSize, RefPtr<SourceSurface>());
|
||||
}
|
||||
|
||||
if (mError) {
|
||||
return MakeTuple(ImgDrawResult::BAD_IMAGE, aSize, RefPtr<SourceSurface>());
|
||||
}
|
||||
|
||||
if (!mIsFullyLoaded) {
|
||||
return MakeTuple(ImgDrawResult::NOT_READY, aSize, RefPtr<SourceSurface>());
|
||||
if (aSize.IsEmpty() || aWhichFrame > FRAME_MAX_VALUE || mError ||
|
||||
!mIsFullyLoaded) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t whichFrame = mHaveAnimations ? aWhichFrame : FRAME_FIRST;
|
||||
|
@ -726,80 +693,44 @@ VectorImage::GetFrameInternal(const IntSize& aSize,
|
|||
RefPtr<SourceSurface> sourceSurface;
|
||||
IntSize decodeSize;
|
||||
Tie(sourceSurface, decodeSize) =
|
||||
LookupCachedSurface(aSize, aSVGContext, aFlags);
|
||||
LookupCachedSurface(aSize, Nothing(), aFlags);
|
||||
if (sourceSurface) {
|
||||
return MakeTuple(ImgDrawResult::SUCCESS, decodeSize,
|
||||
std::move(sourceSurface));
|
||||
return sourceSurface.forget();
|
||||
}
|
||||
|
||||
if (mSVGDocumentWrapper->IsDrawing()) {
|
||||
NS_WARNING("Refusing to make re-entrant call to VectorImage::Draw");
|
||||
return MakeTuple(ImgDrawResult::TEMPORARY_ERROR, decodeSize,
|
||||
RefPtr<SourceSurface>());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
float animTime = (whichFrame == FRAME_FIRST)
|
||||
? 0.0f
|
||||
: mSVGDocumentWrapper->GetCurrentTimeAsFloat();
|
||||
|
||||
// If we aren't given a region, create one that covers the whole SVG image.
|
||||
ImageRegion region =
|
||||
aRegion ? aRegion->ToImageRegion() : ImageRegion::Create(decodeSize);
|
||||
|
||||
// By using a null gfxContext, we ensure that we will always attempt to
|
||||
// create a surface, even if we aren't capable of caching it (e.g. due to our
|
||||
// flags, having an animation, etc). Otherwise CreateSurface will assume that
|
||||
// the caller is capable of drawing directly to its own draw target if we
|
||||
// cannot cache.
|
||||
SVGDrawingParameters params(nullptr, decodeSize, aSize, region,
|
||||
SamplingFilter::POINT, aSVGContext, animTime,
|
||||
aFlags, 1.0);
|
||||
Maybe<SVGImageContext> svgContext;
|
||||
SVGDrawingParameters params(
|
||||
nullptr, decodeSize, aSize, ImageRegion::Create(decodeSize),
|
||||
SamplingFilter::POINT, svgContext, animTime, aFlags, 1.0);
|
||||
|
||||
bool didCache; // Was the surface put into the cache?
|
||||
bool contextPaint = aSVGContext && aSVGContext->GetContextPaint();
|
||||
|
||||
AutoRestoreSVGState autoRestore(params, mSVGDocumentWrapper, contextPaint);
|
||||
AutoRestoreSVGState autoRestore(params, mSVGDocumentWrapper,
|
||||
/* aContextPaint */ false);
|
||||
|
||||
RefPtr<gfxDrawable> svgDrawable = CreateSVGDrawable(params);
|
||||
RefPtr<SourceSurface> surface = CreateSurface(params, svgDrawable, didCache);
|
||||
if (!surface) {
|
||||
MOZ_ASSERT(!didCache);
|
||||
return MakeTuple(ImgDrawResult::TEMPORARY_ERROR, decodeSize,
|
||||
RefPtr<SourceSurface>());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SendFrameComplete(didCache, params.flags);
|
||||
return MakeTuple(ImgDrawResult::SUCCESS, decodeSize, std::move(surface));
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
Tuple<ImgDrawResult, IntSize> VectorImage::GetImageContainerSize(
|
||||
WindowRenderer* aRenderer, const IntSize& aSize, uint32_t aFlags) {
|
||||
if (mError) {
|
||||
return MakeTuple(ImgDrawResult::BAD_IMAGE, IntSize(0, 0));
|
||||
}
|
||||
|
||||
if (!mIsFullyLoaded) {
|
||||
return MakeTuple(ImgDrawResult::NOT_READY, IntSize(0, 0));
|
||||
}
|
||||
|
||||
if (mHaveAnimations && !StaticPrefs::image_svg_blob_image()) {
|
||||
// We don't support rasterizing animation SVGs. We can put them in a blob
|
||||
// recording however instead of using fallback.
|
||||
return MakeTuple(ImgDrawResult::NOT_SUPPORTED, IntSize(0, 0));
|
||||
}
|
||||
|
||||
if (aRenderer->GetBackendType() != LayersBackend::LAYERS_WR) {
|
||||
return MakeTuple(ImgDrawResult::NOT_SUPPORTED, IntSize(0, 0));
|
||||
}
|
||||
|
||||
// We don't need to check if the size is too big since we only support
|
||||
// WebRender backends.
|
||||
if (aSize.IsEmpty()) {
|
||||
return MakeTuple(ImgDrawResult::BAD_ARGS, IntSize(0, 0));
|
||||
}
|
||||
|
||||
return MakeTuple(ImgDrawResult::SUCCESS, aSize);
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(bool)
|
||||
|
@ -819,34 +750,6 @@ VectorImage::IsImageContainerAvailable(WindowRenderer* aRenderer,
|
|||
return true;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
NS_IMETHODIMP_(ImgDrawResult)
|
||||
VectorImage::GetImageContainerAtSize(WindowRenderer* aRenderer,
|
||||
const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion,
|
||||
uint32_t aFlags,
|
||||
layers::ImageContainer** aOutContainer) {
|
||||
Maybe<SVGImageContext> newSVGContext;
|
||||
MaybeRestrictSVGContext(newSVGContext, aSVGContext, aFlags);
|
||||
|
||||
// The aspect ratio flag was already handled as part of the SVG context
|
||||
// restriction above.
|
||||
uint32_t flags = aFlags & ~(FLAG_FORCE_PRESERVEASPECTRATIO_NONE);
|
||||
auto rv = GetImageContainerImpl(aRenderer, aSize,
|
||||
newSVGContext ? newSVGContext : aSVGContext,
|
||||
aRegion, flags, aOutContainer);
|
||||
|
||||
// Invalidations may still be suspended if we had a refresh tick and there
|
||||
// were no image containers remaining. If we created a new container, we
|
||||
// should resume invalidations to allow animations to progress.
|
||||
if (*aOutContainer && mRenderingObserver) {
|
||||
mRenderingObserver->ResumeHonoringInvalidations();
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
//******************************************************************************
|
||||
NS_IMETHODIMP_(ImgDrawResult)
|
||||
VectorImage::GetImageProvider(WindowRenderer* aRenderer,
|
||||
|
|
|
@ -41,8 +41,6 @@ class VectorImage final : public ImageResource, public nsIStreamListener {
|
|||
size_t GetNativeSizesLength() const override;
|
||||
virtual size_t SizeOfSourceWithComputedFallback(
|
||||
SizeOfState& aState) const override;
|
||||
virtual void CollectSizeOfSurfaces(nsTArray<SurfaceMemoryCounter>& aCounters,
|
||||
MallocSizeOf aMallocSizeOf) const override;
|
||||
|
||||
virtual nsresult OnImageDataAvailable(nsIRequest* aRequest,
|
||||
nsIInputStream* aInStr,
|
||||
|
@ -81,16 +79,6 @@ class VectorImage final : public ImageResource, public nsIStreamListener {
|
|||
private:
|
||||
friend class SourceSurfaceBlobImage;
|
||||
|
||||
Tuple<ImgDrawResult, gfx::IntSize, RefPtr<gfx::SourceSurface>>
|
||||
GetFrameInternal(const gfx::IntSize& aSize,
|
||||
const Maybe<SVGImageContext>& aSVGContext,
|
||||
const Maybe<ImageIntRegion>& aRegion, uint32_t aWhichFrame,
|
||||
uint32_t aFlags) override;
|
||||
|
||||
Tuple<ImgDrawResult, gfx::IntSize> GetImageContainerSize(
|
||||
WindowRenderer* aRenderer, const gfx::IntSize& aSize,
|
||||
uint32_t aFlags) override;
|
||||
|
||||
/**
|
||||
* Attempt to find a matching cached surface in the SurfaceCache. Returns the
|
||||
* cached surface, if found, and the size to rasterize at, if applicable.
|
||||
|
|
|
@ -169,11 +169,6 @@ interface imgIContainer : nsISupports
|
|||
*/
|
||||
readonly attribute boolean animated;
|
||||
|
||||
/**
|
||||
* Producer ID for image containers created by this image.
|
||||
*/
|
||||
[infallible] readonly attribute unsigned long producerId;
|
||||
|
||||
/**
|
||||
* Provider ID for image providers created by this image.
|
||||
*/
|
||||
|
@ -330,35 +325,6 @@ interface imgIContainer : nsISupports
|
|||
[noscript, notxpcom] boolean isImageContainerAvailable(in WindowRenderer aRenderer,
|
||||
in uint32_t aFlags);
|
||||
|
||||
/**
|
||||
* Attempts to create an ImageContainer (and Image) containing the current
|
||||
* frame at the given size. Match 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, or if downscale-during-decode is disabled.)
|
||||
*
|
||||
* Avoid calling this unless you're actually going to layerize this image.
|
||||
*
|
||||
* @param aRenderer The WindowRenderer which will be used to render the
|
||||
* ImageContainer.
|
||||
* @param aSVGContext If specified, SVG-related rendering context, such as
|
||||
* overridden attributes on the image document's root <svg>
|
||||
* node, and the size of the viewport that the full image
|
||||
* would occupy. Ignored for raster images.
|
||||
* @param aFlags Decoding / drawing flags (in other words, FLAG_* flags).
|
||||
* Currently only FLAG_SYNC_DECODE and FLAG_SYNC_DECODE_IF_FAST
|
||||
* are supported.
|
||||
* @param aContainer Return value for ImageContainer for the current frame.
|
||||
* May be null depending on the draw result.
|
||||
* @return The draw result for the current frame.
|
||||
*/
|
||||
[noscript, notxpcom] ImgDrawResult getImageContainerAtSize(in WindowRenderer aRenderer,
|
||||
[const] in nsIntSize aSize,
|
||||
[const] in MaybeSVGImageContext aSVGContext,
|
||||
[const] in MaybeImageIntRegion aRegion,
|
||||
in uint32_t aFlags,
|
||||
out ImageContainer aOutContainer);
|
||||
|
||||
/**
|
||||
* Attempts to find a WebRenderImageProvider containing the current frame at
|
||||
* the given size. Match the requested size is best effort; it's not
|
||||
|
|
|
@ -30,11 +30,6 @@ interface imgIRequest : nsIRequest
|
|||
*/
|
||||
readonly attribute imgIContainer image;
|
||||
|
||||
/**
|
||||
* Producer ID for image containers created by this image.
|
||||
*/
|
||||
[infallible] readonly attribute unsigned long producerId;
|
||||
|
||||
/**
|
||||
* Provider ID for image providers created by this image.
|
||||
*/
|
||||
|
|
|
@ -666,21 +666,6 @@ imgRequestProxy::GetImage(imgIContainer** aImage) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
imgRequestProxy::GetProducerId(uint32_t* aId) {
|
||||
NS_ENSURE_TRUE(aId, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsCOMPtr<imgIContainer> image;
|
||||
nsresult rv = GetImage(getter_AddRefs(image));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
*aId = image->GetProducerId();
|
||||
} else {
|
||||
*aId = layers::kContainerProducerID_Invalid;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
imgRequestProxy::GetProviderId(uint32_t* aId) {
|
||||
NS_ENSURE_TRUE(aId, NS_ERROR_NULL_POINTER);
|
||||
|
|
|
@ -1,107 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "WindowRenderer.h"
|
||||
#include "Common.h"
|
||||
#include "imgIContainer.h"
|
||||
#include "ImageFactory.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsString.h"
|
||||
#include "ProgressTracker.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::image;
|
||||
|
||||
class ImageContainers : public ::testing::Test {
|
||||
protected:
|
||||
AutoInitializeImageLib mInit;
|
||||
};
|
||||
|
||||
TEST_F(ImageContainers, RasterImageContainer) {
|
||||
ImageTestCase testCase = GreenPNGTestCase();
|
||||
|
||||
// Create an image.
|
||||
RefPtr<Image> image = ImageFactory::CreateAnonymousImage(
|
||||
nsDependentCString(testCase.mMimeType));
|
||||
ASSERT_TRUE(!image->HasError());
|
||||
|
||||
nsCOMPtr<nsIInputStream> inputStream = LoadFile(testCase.mPath);
|
||||
ASSERT_TRUE(inputStream);
|
||||
|
||||
// Figure out how much data we have.
|
||||
uint64_t length;
|
||||
nsresult rv = inputStream->Available(&length);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
// Write the data into the image.
|
||||
rv = image->OnImageDataAvailable(nullptr, inputStream, 0,
|
||||
static_cast<uint32_t>(length));
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
// Let the image know we've sent all the data.
|
||||
rv = image->OnImageDataComplete(nullptr, NS_OK, true);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
|
||||
tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE);
|
||||
|
||||
RefPtr<WindowRenderer> renderer = new FallbackRenderer;
|
||||
|
||||
// Get at native size.
|
||||
ImgDrawResult drawResult;
|
||||
RefPtr<layers::ImageContainer> nativeContainer;
|
||||
drawResult = image->GetImageContainerAtSize(
|
||||
renderer, testCase.mSize, Nothing(), Nothing(),
|
||||
imgIContainer::FLAG_SYNC_DECODE, getter_AddRefs(nativeContainer));
|
||||
EXPECT_EQ(drawResult, ImgDrawResult::SUCCESS);
|
||||
ASSERT_TRUE(nativeContainer != nullptr);
|
||||
IntSize containerSize = nativeContainer->GetCurrentSize();
|
||||
EXPECT_EQ(testCase.mSize.width, containerSize.width);
|
||||
EXPECT_EQ(testCase.mSize.height, containerSize.height);
|
||||
|
||||
// Upscaling should give the native size.
|
||||
IntSize requestedSize = testCase.mSize;
|
||||
requestedSize.Scale(2, 2);
|
||||
RefPtr<layers::ImageContainer> upscaleContainer;
|
||||
drawResult = image->GetImageContainerAtSize(
|
||||
renderer, requestedSize, Nothing(), Nothing(),
|
||||
imgIContainer::FLAG_SYNC_DECODE |
|
||||
imgIContainer::FLAG_HIGH_QUALITY_SCALING,
|
||||
getter_AddRefs(upscaleContainer));
|
||||
EXPECT_EQ(drawResult, ImgDrawResult::SUCCESS);
|
||||
ASSERT_TRUE(upscaleContainer != nullptr);
|
||||
containerSize = upscaleContainer->GetCurrentSize();
|
||||
EXPECT_EQ(testCase.mSize.width, containerSize.width);
|
||||
EXPECT_EQ(testCase.mSize.height, containerSize.height);
|
||||
|
||||
// Downscaling should give the downscaled size.
|
||||
requestedSize = testCase.mSize;
|
||||
requestedSize.width /= 2;
|
||||
requestedSize.height /= 2;
|
||||
RefPtr<layers::ImageContainer> downscaleContainer;
|
||||
drawResult = image->GetImageContainerAtSize(
|
||||
renderer, requestedSize, Nothing(), Nothing(),
|
||||
imgIContainer::FLAG_SYNC_DECODE |
|
||||
imgIContainer::FLAG_HIGH_QUALITY_SCALING,
|
||||
getter_AddRefs(downscaleContainer));
|
||||
EXPECT_EQ(drawResult, ImgDrawResult::SUCCESS);
|
||||
ASSERT_TRUE(downscaleContainer != nullptr);
|
||||
containerSize = downscaleContainer->GetCurrentSize();
|
||||
EXPECT_EQ(requestedSize.width, containerSize.width);
|
||||
EXPECT_EQ(requestedSize.height, containerSize.height);
|
||||
|
||||
// Get at native size again. Should give same container.
|
||||
RefPtr<layers::ImageContainer> againContainer;
|
||||
drawResult = image->GetImageContainerAtSize(
|
||||
renderer, testCase.mSize, Nothing(), Nothing(),
|
||||
imgIContainer::FLAG_SYNC_DECODE, getter_AddRefs(againContainer));
|
||||
EXPECT_EQ(drawResult, ImgDrawResult::SUCCESS);
|
||||
ASSERT_EQ(nativeContainer.get(), againContainer.get());
|
||||
}
|
|
@ -11,7 +11,6 @@ UNIFIED_SOURCES = [
|
|||
"TestADAM7InterpolatingFilter.cpp",
|
||||
"TestAnimationFrameBuffer.cpp",
|
||||
"TestBlendAnimationFilter.cpp",
|
||||
"TestContainers.cpp",
|
||||
"TestCopyOnWrite.cpp",
|
||||
"TestDeinterlacingFilter.cpp",
|
||||
"TestFrameAnimator.cpp",
|
||||
|
|
Загрузка…
Ссылка в новой задаче