Bug 1704792 - Part 7. Integrate use of ImageIntRegion with WebRender display lists. r=jrmuizel

This patch hooks up the ImageIntRegion to the blob recording and makes
any necessary adjusts to the display list creation to take advantage of
it.

Differential Revision: https://phabricator.services.mozilla.com/D114986
This commit is contained in:
Andrew Osmond 2021-05-13 16:24:08 +00:00
Родитель 8c4863cd4e
Коммит a140512abd
5 изменённых файлов: 59 добавлений и 30 удалений

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

@ -22,10 +22,12 @@ namespace mozilla::image {
SourceSurfaceBlobImage::SourceSurfaceBlobImage(
image::SVGDocumentWrapper* aSVGDocumentWrapper,
const Maybe<SVGImageContext>& aSVGContext, const IntSize& aSize,
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),
mImageFlags(aImageFlags) {
@ -138,7 +140,10 @@ Maybe<BlobImageKeyData> SourceSurfaceBlobImage::RecordDrawing(
// re-record the SVG image draw commands.
auto* rootManager = aManager->GetRenderRootStateManager();
auto* wrBridge = aManager->WrBridge();
IntRect imageRect(IntPoint(0, 0), mSize);
IntRect imageRect =
mRegion ? mRegion->Rect() : IntRect(IntPoint(0, 0), mSize);
IntRect imageRectOrigin = imageRect - imageRect.TopLeft();
std::vector<RefPtr<ScaledFont>> fonts;
bool validFonts = true;
@ -166,7 +171,7 @@ Maybe<BlobImageKeyData> SourceSurfaceBlobImage::RecordDrawing(
RefPtr<DrawTarget> dummyDt = Factory::CreateDrawTarget(
BackendType::SKIA, IntSize(1, 1), SurfaceFormat::OS_RGBA);
RefPtr<DrawTarget> dt =
Factory::CreateRecordingDrawTarget(recorder, dummyDt, imageRect);
Factory::CreateRecordingDrawTarget(recorder, dummyDt, imageRectOrigin);
if (!dt || !dt->IsValid()) {
return Nothing();
@ -179,9 +184,15 @@ Maybe<BlobImageKeyData> SourceSurfaceBlobImage::RecordDrawing(
? 0.0f
: mSVGDocumentWrapper->GetCurrentTimeAsFloat();
SVGDrawingParameters params(
nullptr, mSize, mSize, ImageRegion::Create(mSize),
SamplingFilter::POINT, mSVGContext, animTime, mImageFlags, 1.0);
auto region =
mRegion
? mRegion->ToImageRegion()
: ImageRegion::Create(gfxRect(imageRect.x, imageRect.y,
imageRect.width, imageRect.height));
SVGDrawingParameters params(nullptr, mSize, mSize, region,
SamplingFilter::POINT, mSVGContext, animTime,
mImageFlags, 1.0);
AutoRestoreSVGState autoRestore(params, mSVGDocumentWrapper, contextPaint);
@ -195,13 +206,16 @@ Maybe<BlobImageKeyData> SourceSurfaceBlobImage::RecordDrawing(
// Draw using the drawable the caller provided.
RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(dt);
MOZ_ASSERT(ctx); // Already checked the draw target above.
gfxUtils::DrawPixelSnapped(
ctx, svgDrawable, SizeDouble(mSize),
image::ImageRegion::Create(ThebesRect(imageRect)),
SurfaceFormat::OS_RGBA, SamplingFilter::POINT, mImageFlags);
ctx->SetMatrix(
ctx->CurrentMatrix().PreTranslate(-imageRect.x, -imageRect.y));
gfxUtils::DrawPixelSnapped(ctx, svgDrawable, SizeDouble(mSize), region,
SurfaceFormat::OS_RGBA, SamplingFilter::POINT,
mImageFlags);
}
recorder->FlushItem(imageRect);
recorder->FlushItem(imageRectOrigin);
recorder->Finish();
if (!validFonts) {
@ -214,10 +228,10 @@ Maybe<BlobImageKeyData> SourceSurfaceBlobImage::RecordDrawing(
wr::BlobImageKey key = aBlobKey
? aBlobKey.value()
: wr::BlobImageKey{wrBridge->GetNextImageKey()};
wr::ImageDescriptor descriptor(mSize, 0, SurfaceFormat::OS_RGBA,
wr::ImageDescriptor descriptor(imageRect.Size(), 0, SurfaceFormat::OS_RGBA,
wr::OpacityType::HasAlphaChannel);
ImageIntRect visibleRect(0, 0, mSize.width, mSize.height);
auto visibleRect = ImageIntRect::FromUnknownRect(imageRectOrigin);
if (aBlobKey) {
if (!aResources.UpdateBlobImage(key, descriptor, bytes, visibleRect,
visibleRect)) {

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

@ -11,6 +11,7 @@
#include "mozilla/SVGImageContext.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/layers/WebRenderLayerManager.h"
#include "ImageRegion.h"
#include <vector>
@ -79,6 +80,7 @@ class SourceSurfaceBlobImage final : public gfx::SourceSurface {
SourceSurfaceBlobImage(SVGDocumentWrapper* aSVGDocumentWrapper,
const Maybe<SVGImageContext>& aSVGContext,
const Maybe<ImageIntRegion>& aRegion,
const gfx::IntSize& aSize, uint32_t aWhichFrame,
uint32_t aImageFlags);
@ -116,6 +118,7 @@ class SourceSurfaceBlobImage final : public gfx::SourceSurface {
RefPtr<image::SVGDocumentWrapper> mSVGDocumentWrapper;
Maybe<SVGImageContext> mSVGContext;
Maybe<ImageIntRegion> mRegion;
gfx::IntSize mSize;
uint32_t mWhichFrame;
uint32_t mImageFlags;

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

@ -735,21 +735,26 @@ VectorImage::GetFrameInternal(const IntSize& aSize,
? 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, ImageRegion::Create(decodeSize),
SamplingFilter::POINT, aSVGContext, animTime, aFlags, 1.0);
SVGDrawingParameters params(nullptr, decodeSize, aSize, region,
SamplingFilter::POINT, aSVGContext, animTime,
aFlags, 1.0);
// Blob recorded vector images just create a simple surface responsible for
// generating blob keys and recording bindings. The recording won't happen
// until the caller requests the key after GetImageContainerAtSize.
if (aFlags & FLAG_RECORD_BLOB) {
RefPtr<SourceSurface> surface = new SourceSurfaceBlobImage(
mSVGDocumentWrapper, aSVGContext, decodeSize, whichFrame, aFlags);
RefPtr<SourceSurface> surface =
new SourceSurfaceBlobImage(mSVGDocumentWrapper, aSVGContext, aRegion,
decodeSize, whichFrame, aFlags);
return MakeTuple(ImgDrawResult::SUCCESS, decodeSize, std::move(surface));
}

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

@ -581,6 +581,11 @@ ImgDrawResult nsImageRenderer::BuildWebRenderDisplayItems(
}
case StyleImage::Tag::Rect:
case StyleImage::Tag::Url: {
ExtendMode extendMode = mExtendMode;
if (aDest.Contains(aFill)) {
extendMode = ExtendMode::CLAMP;
}
uint32_t containerFlags = imgIContainer::FLAG_ASYNC_NOTIFY;
if (mFlags & (nsImageRenderer::FLAG_PAINTING_TO_WINDOW |
nsImageRenderer::FLAG_HIGH_QUALITY_SCALING)) {
@ -589,7 +594,7 @@ ImgDrawResult nsImageRenderer::BuildWebRenderDisplayItems(
if (mFlags & nsImageRenderer::FLAG_SYNC_DECODE_IMAGES) {
containerFlags |= imgIContainer::FLAG_SYNC_DECODE;
}
if (mExtendMode == ExtendMode::CLAMP &&
if (extendMode == ExtendMode::CLAMP &&
StaticPrefs::image_svg_blob_image() &&
mImageContainer->GetType() == imgIContainer::TYPE_VECTOR) {
containerFlags |= imgIContainer::FLAG_RECORD_BLOB;
@ -607,13 +612,19 @@ ImgDrawResult nsImageRenderer::BuildWebRenderDisplayItems(
mForFrame->PresContext()->AppUnitsPerDevPixel();
LayoutDeviceRect destRect =
LayoutDeviceRect::FromAppUnits(aDest, appUnitsPerDevPixel);
LayoutDeviceRect clipRect =
LayoutDeviceRect::FromAppUnits(aFill, appUnitsPerDevPixel);
auto stretchSize = wr::ToLayoutSize(destRect.Size());
gfx::IntSize decodeSize =
nsLayoutUtils::ComputeImageContainerDrawingParameters(
mImageContainer, mForFrame, destRect, destRect, aSc,
mImageContainer, mForFrame, destRect, clipRect, aSc,
containerFlags, svgContext, region);
if (extendMode != ExtendMode::CLAMP) {
region = Nothing();
}
RefPtr<layers::ImageContainer> container;
drawResult = mImageContainer->GetImageContainerAtSize(
aManager->LayerManager(), decodeSize, svgContext, region,
@ -624,11 +635,9 @@ ImgDrawResult nsImageRenderer::BuildWebRenderDisplayItems(
}
if (containerFlags & imgIContainer::FLAG_RECORD_BLOB) {
MOZ_ASSERT(mExtendMode == ExtendMode::CLAMP);
LayoutDeviceRect clipRect =
LayoutDeviceRect::FromAppUnits(aFill, appUnitsPerDevPixel);
MOZ_ASSERT(extendMode == ExtendMode::CLAMP);
aManager->CommandBuilder().PushBlobImage(
aItem, container, aBuilder, aResources, destRect, clipRect);
aItem, container, aBuilder, aResources, clipRect, clipRect);
break;
}
@ -644,11 +653,9 @@ ImgDrawResult nsImageRenderer::BuildWebRenderDisplayItems(
}
wr::LayoutRect dest = wr::ToLayoutRect(destRect);
wr::LayoutRect clip = wr::ToLayoutRect(clipRect);
wr::LayoutRect clip = wr::ToLayoutRect(
LayoutDeviceRect::FromAppUnits(aFill, appUnitsPerDevPixel));
if (mExtendMode == ExtendMode::CLAMP) {
if (extendMode == ExtendMode::CLAMP) {
// The image is not repeating. Just push as a regular image.
aBuilder.PushImage(dest, clip, !aItem->BackfaceIsHidden(), rendering,
key.value());
@ -662,7 +669,7 @@ ImgDrawResult nsImageRenderer::BuildWebRenderDisplayItems(
appUnitsPerDevPixel);
wr::LayoutRect fill = wr::ToLayoutRect(fillRect);
switch (mExtendMode) {
switch (extendMode) {
case ExtendMode::REPEAT_Y:
fill.origin.x = dest.origin.x;
fill.size.width = dest.size.width;

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

@ -614,7 +614,7 @@ bool SVGImageFrame::CreateWebRenderCommands(
Maybe<ImageIntRegion> region;
IntSize decodeSize = nsLayoutUtils::ComputeImageContainerDrawingParameters(
mImageContainer, this, destRect, destRect, aSc, flags, svgContext,
mImageContainer, this, destRect, clipRect, aSc, flags, svgContext,
region);
RefPtr<layers::ImageContainer> container;