зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
8c4863cd4e
Коммит
a140512abd
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче