Bug 1711061 - Part 10. Implement BlobSurfaceProvider for non-rasterized blob recordings. r=tnikkel

This WebRenderImageProvider/ISurfaceProvider subclass provides the
implementation for blob recordings. This is mostly just taking the
functionality that was previously in SourceSurfaceBlobImage.

Differential Revision: https://phabricator.services.mozilla.com/D126602
This commit is contained in:
Andrew Osmond 2021-11-27 11:47:39 +00:00
Родитель ba2c6dea3f
Коммит 6c26762435
2 изменённых файлов: 84 добавлений и 70 удалений

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

@ -20,23 +20,18 @@ using namespace mozilla::layers;
namespace mozilla::image {
SourceSurfaceBlobImage::SourceSurfaceBlobImage(
image::SVGDocumentWrapper* aSVGDocumentWrapper,
const Maybe<SVGImageContext>& aSVGContext,
const Maybe<ImageIntRegion>& aRegion, const IntSize& aSize,
uint32_t aWhichFrame, uint32_t aImageFlags)
: mSVGDocumentWrapper(aSVGDocumentWrapper),
mSVGContext(aSVGContext),
mRegion(aRegion),
mSize(aSize),
mWhichFrame(aWhichFrame),
BlobSurfaceProvider::BlobSurfaceProvider(
const ImageKey aImageKey, const SurfaceKey& aSurfaceKey,
image::SVGDocumentWrapper* aSVGDocumentWrapper, uint32_t aImageFlags)
: ISurfaceProvider(aImageKey, aSurfaceKey,
AvailabilityState::StartAvailable()),
mSVGDocumentWrapper(aSVGDocumentWrapper),
mImageFlags(aImageFlags) {
MOZ_ASSERT(mSVGDocumentWrapper);
MOZ_ASSERT(aWhichFrame <= imgIContainer::FRAME_MAX_VALUE);
MOZ_ASSERT(aImageFlags & imgIContainer::FLAG_RECORD_BLOB);
}
SourceSurfaceBlobImage::~SourceSurfaceBlobImage() {
BlobSurfaceProvider::~BlobSurfaceProvider() {
if (NS_IsMainThread()) {
DestroyKeys(mKeys);
return;
@ -49,7 +44,7 @@ SourceSurfaceBlobImage::~SourceSurfaceBlobImage() {
[keys = std::move(mKeys)] { DestroyKeys(keys); }));
}
/* static */ void SourceSurfaceBlobImage::DestroyKeys(
/* static */ void BlobSurfaceProvider::DestroyKeys(
const AutoTArray<BlobImageKeyData, 1>& aKeys) {
for (const auto& entry : aKeys) {
if (!entry.mManager->IsDestroyed()) {
@ -59,10 +54,14 @@ SourceSurfaceBlobImage::~SourceSurfaceBlobImage() {
}
}
Maybe<wr::BlobImageKey> SourceSurfaceBlobImage::UpdateKey(
WebRenderLayerManager* aManager, wr::IpcResourceUpdateQueue& aResources) {
nsresult BlobSurfaceProvider::UpdateKey(
layers::RenderRootStateManager* aManager,
wr::IpcResourceUpdateQueue& aResources, wr::ImageKey& aKey) {
MOZ_ASSERT(NS_IsMainThread());
layers::WebRenderLayerManager* manager = aManager->LayerManager();
MOZ_ASSERT(manager);
Maybe<wr::BlobImageKey> key;
auto i = mKeys.Length();
while (i > 0) {
@ -70,8 +69,8 @@ Maybe<wr::BlobImageKey> SourceSurfaceBlobImage::UpdateKey(
BlobImageKeyData& entry = mKeys[i];
if (entry.mManager->IsDestroyed()) {
mKeys.RemoveElementAt(i);
} else if (entry.mManager == aManager) {
WebRenderBridgeChild* wrBridge = aManager->WrBridge();
} else if (entry.mManager == manager) {
WebRenderBridgeChild* wrBridge = manager->WrBridge();
MOZ_ASSERT(wrBridge);
bool ownsKey = wrBridge->MatchesNamespace(entry.mBlobKey);
@ -84,12 +83,11 @@ Maybe<wr::BlobImageKey> SourceSurfaceBlobImage::UpdateKey(
// can change state. Either our namespace differs, and our old key has
// already been discarded, or the blob has changed. Either way, we need
// to rerecord it.
auto newEntry = RecordDrawing(aManager, aResources,
auto newEntry = RecordDrawing(manager, aResources,
ownsKey ? Some(entry.mBlobKey) : Nothing());
if (!newEntry) {
if (ownsKey) {
aManager->GetRenderRootStateManager()->AddBlobImageKeyForDiscard(
entry.mBlobKey);
aManager->AddBlobImageKeyForDiscard(entry.mBlobKey);
}
mKeys.RemoveElementAt(i);
continue;
@ -103,17 +101,22 @@ Maybe<wr::BlobImageKey> SourceSurfaceBlobImage::UpdateKey(
// We didn't find an entry. Attempt to record the blob with a new key.
if (!key) {
auto newEntry = RecordDrawing(aManager, aResources, Nothing());
auto newEntry = RecordDrawing(manager, aResources, Nothing());
if (newEntry) {
key.emplace(newEntry.ref().mBlobKey);
mKeys.AppendElement(std::move(newEntry.ref()));
}
}
return key;
if (key) {
aKey = wr::AsImageKey(key.value());
return NS_OK;
}
return NS_ERROR_FAILURE;
}
void SourceSurfaceBlobImage::MarkDirty() {
void BlobSurfaceProvider::InvalidateRecording() {
MOZ_ASSERT(NS_IsMainThread());
auto i = mKeys.Length();
@ -128,7 +131,7 @@ void SourceSurfaceBlobImage::MarkDirty() {
}
}
Maybe<BlobImageKeyData> SourceSurfaceBlobImage::RecordDrawing(
Maybe<BlobImageKeyData> BlobSurfaceProvider::RecordDrawing(
WebRenderLayerManager* aManager, wr::IpcResourceUpdateQueue& aResources,
Maybe<wr::BlobImageKey> aBlobKey) {
MOZ_ASSERT(!aManager->IsDestroyed());
@ -142,8 +145,11 @@ Maybe<BlobImageKeyData> SourceSurfaceBlobImage::RecordDrawing(
auto* rootManager = aManager->GetRenderRootStateManager();
auto* wrBridge = aManager->WrBridge();
IntRect imageRect =
mRegion ? mRegion->Rect() : IntRect(IntPoint(0, 0), mSize);
const auto& size = GetSurfaceKey().Size();
const auto& region = GetSurfaceKey().Region();
const auto& svgContext = GetSurfaceKey().SVGContext();
IntRect imageRect = region ? region->Rect() : IntRect(IntPoint(0, 0), size);
IntRect imageRectOrigin = imageRect - imageRect.TopLeft();
std::vector<RefPtr<ScaledFont>> fonts;
@ -178,15 +184,15 @@ Maybe<BlobImageKeyData> SourceSurfaceBlobImage::RecordDrawing(
return Nothing();
}
bool contextPaint = mSVGContext && mSVGContext->GetContextPaint();
bool contextPaint = svgContext && svgContext->GetContextPaint();
float animTime = (mWhichFrame == imgIContainer::FRAME_FIRST)
float animTime = (GetSurfaceKey().Playback() == PlaybackType::eStatic)
? 0.0f
: mSVGDocumentWrapper->GetCurrentTimeAsFloat();
IntSize viewportSize = mSize;
if (mSVGContext) {
auto cssViewportSize = mSVGContext->GetViewportSize();
IntSize viewportSize = size;
if (svgContext) {
auto cssViewportSize = svgContext->GetViewportSize();
if (cssViewportSize) {
// XXX losing unit
viewportSize.SizeTo(cssViewportSize->width, cssViewportSize->height);
@ -206,11 +212,11 @@ Maybe<BlobImageKeyData> SourceSurfaceBlobImage::RecordDrawing(
AUTO_PROFILER_LABEL_DYNAMIC_NSCSTRING(
"SVG Image recording", GRAPHICS,
nsPrintfCString("(%d,%d) %dx%d from %dx%d %s", imageRect.x, imageRect.y,
imageRect.width, imageRect.height, mSize.width,
mSize.height,
imageRect.width, imageRect.height, size.width,
size.height,
uri ? uri->GetSpecOrDefault().get() : "N/A"));
AutoRestoreSVGState autoRestore(mSVGContext, animTime, mSVGDocumentWrapper,
AutoRestoreSVGState autoRestore(svgContext, animTime, mSVGDocumentWrapper,
contextPaint);
mSVGDocumentWrapper->UpdateViewportBounds(viewportSize);
@ -221,9 +227,9 @@ Maybe<BlobImageKeyData> SourceSurfaceBlobImage::RecordDrawing(
nsRect svgRect;
auto auPerDevPixel = presContext->AppUnitsPerDevPixel();
if (mSize != viewportSize) {
auto scaleX = double(mSize.width) / viewportSize.width;
auto scaleY = double(mSize.height) / viewportSize.height;
if (size != viewportSize) {
auto scaleX = double(size.width) / viewportSize.width;
auto scaleY = double(size.height) / viewportSize.height;
ctx->SetMatrix(Matrix::Scaling(float(scaleX), float(scaleY)));
auto scaledVisibleRect = IntRectToRect(imageRect);

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

@ -12,6 +12,7 @@
#include "mozilla/gfx/2D.h"
#include "mozilla/layers/WebRenderLayerManager.h"
#include "ImageRegion.h"
#include "ISurfaceProvider.h"
#include <vector>
@ -70,45 +71,56 @@ namespace image {
class SVGDocumentWrapper;
/**
* This class is used to wrap blob recordings stored in ImageContainers, used
* by SVG images. Unlike rasterized images stored in SourceSurfaceSharedData,
* each SourceSurfaceBlobImage can only be used by one WebRenderLayerManager
* because the recording is tied to a particular instance.
* An ISurfaceProvider that manages blob recordings of SVG images. Unlike the
* rasterized ISurfaceProviders, it only provides a recording which may be
* replayed in the compositor process by WebRender. It may be invalidated
* directly in order to reuse the resource ids and underlying buffers when the
* SVG image has changed (e.g. it is animated).
*/
class SourceSurfaceBlobImage final : public gfx::SourceSurface {
class BlobSurfaceProvider final : public ISurfaceProvider {
public:
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceBlobImage, override)
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BlobSurfaceProvider, override)
SourceSurfaceBlobImage(SVGDocumentWrapper* aSVGDocumentWrapper,
const Maybe<SVGImageContext>& aSVGContext,
const Maybe<ImageIntRegion>& aRegion,
const gfx::IntSize& aSize, uint32_t aWhichFrame,
uint32_t aImageFlags);
BlobSurfaceProvider(ImageKey aImageKey, const SurfaceKey& aSurfaceKey,
SVGDocumentWrapper* aSVGDocumentWrapper,
uint32_t aImageFlags);
Maybe<wr::BlobImageKey> UpdateKey(layers::WebRenderLayerManager* aManager,
wr::IpcResourceUpdateQueue& aResources);
bool IsFinished() const override { return true; }
void MarkDirty();
gfx::SurfaceType GetType() const override {
return gfx::SurfaceType::BLOB_IMAGE;
}
gfx::IntSize GetSize() const override { return mSize; }
gfx::SurfaceFormat GetFormat() const override {
return gfx::SurfaceFormat::OS_RGBA;
}
already_AddRefed<gfx::DataSourceSurface> GetDataSurface() override {
return nullptr;
size_t LogicalSizeInBytes() const override {
const gfx::IntSize& size = GetSurfaceKey().Size();
return size.width * size.height * sizeof(uint32_t);
}
void SizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
SizeOfInfo& aInfo) const override {
aInfo.AddType(gfx::SurfaceType::BLOB_IMAGE);
aInfo.mHeapBytes += mKeys.ShallowSizeOfExcludingThis(aMallocSizeOf);
nsresult UpdateKey(layers::RenderRootStateManager* aManager,
wr::IpcResourceUpdateQueue& aResources,
wr::ImageKey& aKey) override;
void InvalidateRecording() override;
void AddSizeOfExcludingThis(MallocSizeOf aMallocSizeOf,
const AddSizeOfCb& aCallback) override {
AddSizeOfCbData metadata;
metadata.mFinished = true;
metadata.mHeapBytes += mKeys.ShallowSizeOfExcludingThis(aMallocSizeOf);
gfx::SourceSurface::SizeOfInfo info;
info.AddType(gfx::SurfaceType::BLOB_IMAGE);
metadata.Accumulate(info);
aCallback(metadata);
}
protected:
DrawableFrameRef DrawableRef(size_t aFrame) override {
MOZ_ASSERT_UNREACHABLE("BlobSurfaceProvider::DrawableRef not supported!");
return DrawableFrameRef();
}
bool IsLocked() const override { return true; }
void SetLocked(bool) override {}
private:
~SourceSurfaceBlobImage() override;
~BlobSurfaceProvider() override;
Maybe<BlobImageKeyData> RecordDrawing(layers::WebRenderLayerManager* aManager,
wr::IpcResourceUpdateQueue& aResources,
@ -119,10 +131,6 @@ class SourceSurfaceBlobImage final : public gfx::SourceSurface {
AutoTArray<BlobImageKeyData, 1> mKeys;
RefPtr<image::SVGDocumentWrapper> mSVGDocumentWrapper;
Maybe<SVGImageContext> mSVGContext;
Maybe<ImageIntRegion> mRegion;
gfx::IntSize mSize;
uint32_t mWhichFrame;
uint32_t mImageFlags;
};