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:
Andrew Osmond 2021-11-27 11:47:40 +00:00
Родитель af4570762c
Коммит 72d1c14b24
26 изменённых файлов: 31 добавлений и 1086 удалений

Просмотреть файл

@ -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,

Просмотреть файл

@ -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",