mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1617493
- Rasterize SVG patterns in content process into a shared surface for WebRender. r=jrmuizel
In DrawTargetRecording::CreateSimilarDrawTarget, we would originally create a new DrawTargetRecording. For resources that are shared, such as SVG patterns, we would do the same work for each blob image tile. This can get expensive if the pattern is large. Now we check a size threshold, and if passed, we create a DrawTargetSkia backed by a SourceSurfaceSharedData. When we want a snapshot, we now try to get the shared surface instead if available. The recording infrastructure already knows how to handle the lifetimes and use of external IDs for shared surfaces, so now we rasterize the pattern once for all the blob tiles. In an ideal world we would do this in the compositor process once, but that requires more changes, and this is useful as a stopgap in the meantime. Differential Revision: https://phabricator.services.mozilla.com/D63903 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
92625e728c
commit
fbaa72bc71
19
gfx/2d/2D.h
19
gfx/2d/2D.h
@ -1072,6 +1072,16 @@ class DrawTarget : public external::AtomicRefCounted<DrawTarget> {
|
||||
*/
|
||||
virtual already_AddRefed<SourceSurface> Snapshot() = 0;
|
||||
|
||||
/**
|
||||
* Returns a SourceSurface which wraps the buffer backing the DrawTarget. The
|
||||
* contents of the buffer may change if there are drawing operations after
|
||||
* calling but only guarantees that it reflects the state at the time it was
|
||||
* called.
|
||||
*/
|
||||
virtual already_AddRefed<SourceSurface> GetBackingSurface() {
|
||||
return Snapshot();
|
||||
}
|
||||
|
||||
// Snapshots the contents and returns an alpha mask
|
||||
// based on the RGB values.
|
||||
virtual already_AddRefed<SourceSurface> IntoLuminanceSource(
|
||||
@ -1453,6 +1463,15 @@ class DrawTarget : public external::AtomicRefCounted<DrawTarget> {
|
||||
virtual already_AddRefed<DrawTarget> CreateSimilarDrawTarget(
|
||||
const IntSize& aSize, SurfaceFormat aFormat) const = 0;
|
||||
|
||||
/**
|
||||
* Create a DrawTarget whose backing surface is optimized for use with this
|
||||
* DrawTarget.
|
||||
*/
|
||||
virtual already_AddRefed<DrawTarget> CreateSimilarDrawTargetWithBacking(
|
||||
const IntSize& aSize, SurfaceFormat aFormat) const {
|
||||
return CreateSimilarDrawTarget(aSize, aFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a DrawTarget whose snapshot is optimized for use with this
|
||||
* DrawTarget and aFilter.
|
||||
|
@ -5,6 +5,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "DrawTargetRecording.h"
|
||||
#include "DrawTargetSkia.h"
|
||||
#include "PathRecording.h"
|
||||
#include <stdio.h>
|
||||
|
||||
@ -12,6 +13,7 @@
|
||||
#include "Tools.h"
|
||||
#include "Filters.h"
|
||||
#include "mozilla/gfx/DataSurfaceHelpers.h"
|
||||
#include "mozilla/layers/SourceSurfaceSharedData.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "RecordingTypes.h"
|
||||
#include "RecordedEventImpl.h"
|
||||
@ -496,6 +498,34 @@ DrawTargetRecording::CreateSourceSurfaceFromNativeSurface(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<DrawTarget>
|
||||
DrawTargetRecording::CreateSimilarDrawTargetWithBacking(
|
||||
const IntSize& aSize, SurfaceFormat aFormat) const {
|
||||
RefPtr<DrawTarget> similarDT;
|
||||
if (mFinalDT->CanCreateSimilarDrawTarget(aSize, aFormat)) {
|
||||
// If the requested similar draw target is too big, then we should try to
|
||||
// rasterize on the content side to avoid duplicating the effort when a
|
||||
// blob image gets tiled. If we fail somehow to produce it, we can fall
|
||||
// back to recording.
|
||||
constexpr int32_t kRasterThreshold = 256 * 256 * 4;
|
||||
int32_t stride = aSize.width * BytesPerPixel(aFormat);
|
||||
int32_t surfaceBytes = aSize.height * stride;
|
||||
if (surfaceBytes >= kRasterThreshold) {
|
||||
auto surface = MakeRefPtr<SourceSurfaceSharedData>();
|
||||
if (surface->Init(aSize, stride, aFormat)) {
|
||||
auto dt = MakeRefPtr<DrawTargetSkia>();
|
||||
if (dt->Init(std::move(surface))) {
|
||||
return dt.forget();
|
||||
} else {
|
||||
MOZ_ASSERT_UNREACHABLE("Skia should initialize given surface!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CreateSimilarDrawTarget(aSize, aFormat);
|
||||
}
|
||||
|
||||
already_AddRefed<DrawTarget> DrawTargetRecording::CreateSimilarDrawTarget(
|
||||
const IntSize& aSize, SurfaceFormat aFormat) const {
|
||||
RefPtr<DrawTarget> similarDT;
|
||||
|
@ -291,6 +291,13 @@ class DrawTargetRecording : public DrawTarget {
|
||||
virtual already_AddRefed<DrawTarget> CreateSimilarDrawTarget(
|
||||
const IntSize& aSize, SurfaceFormat aFormat) const override;
|
||||
|
||||
/**
|
||||
* Create a DrawTarget whose backing surface is optimized for use with this
|
||||
* DrawTarget.
|
||||
*/
|
||||
virtual already_AddRefed<DrawTarget> CreateSimilarDrawTargetWithBacking(
|
||||
const IntSize& aSize, SurfaceFormat aFormat) const override;
|
||||
|
||||
bool CanCreateSimilarDrawTarget(const IntSize& aSize,
|
||||
SurfaceFormat aFormat) const override;
|
||||
/**
|
||||
|
@ -320,6 +320,14 @@ already_AddRefed<SourceSurface> DrawTargetSkia::Snapshot() {
|
||||
return snapshot.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<SourceSurface> DrawTargetSkia::GetBackingSurface() {
|
||||
if (mBackingSurface) {
|
||||
RefPtr<SourceSurface> snapshot = mBackingSurface;
|
||||
return snapshot.forget();
|
||||
}
|
||||
return Snapshot();
|
||||
}
|
||||
|
||||
bool DrawTargetSkia::LockBits(uint8_t** aData, IntSize* aSize, int32_t* aStride,
|
||||
SurfaceFormat* aFormat, IntPoint* aOrigin) {
|
||||
SkImageInfo info;
|
||||
@ -1743,6 +1751,43 @@ bool DrawTargetSkia::Init(unsigned char* aData, const IntSize& aSize,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DrawTargetSkia::Init(RefPtr<DataSourceSurface>&& aSurface) {
|
||||
auto map =
|
||||
new DataSourceSurface::ScopedMap(aSurface, DataSourceSurface::READ_WRITE);
|
||||
if (!map->IsMapped()) {
|
||||
delete map;
|
||||
return false;
|
||||
}
|
||||
|
||||
SurfaceFormat format = aSurface->GetFormat();
|
||||
IntSize size = aSurface->GetSize();
|
||||
MOZ_ASSERT((format != SurfaceFormat::B8G8R8X8) ||
|
||||
VerifyRGBXFormat(map->GetData(), size, map->GetStride(), format));
|
||||
|
||||
SkSurfaceProps props(0, GetSkPixelGeometry());
|
||||
mSurface = SkSurface::MakeRasterDirectReleaseProc(
|
||||
MakeSkiaImageInfo(size, format), map->GetData(), map->GetStride(),
|
||||
DrawTargetSkia::ReleaseMappedSkSurface, map, &props);
|
||||
if (!mSurface) {
|
||||
delete map;
|
||||
return false;
|
||||
}
|
||||
|
||||
// map is now owned by mSurface
|
||||
mBackingSurface = std::move(aSurface);
|
||||
mSize = size;
|
||||
mFormat = format;
|
||||
mCanvas = mSurface->getCanvas();
|
||||
SetPermitSubpixelAA(IsOpaque(format));
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ void DrawTargetSkia::ReleaseMappedSkSurface(void* aPixels,
|
||||
void* aContext) {
|
||||
auto map = reinterpret_cast<DataSourceSurface::ScopedMap*>(aContext);
|
||||
delete map;
|
||||
}
|
||||
|
||||
void DrawTargetSkia::SetTransform(const Matrix& aTransform) {
|
||||
SkMatrix mat;
|
||||
GfxMatrixToSkiaMatrix(aTransform, mat);
|
||||
|
@ -24,6 +24,7 @@
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class DataSourceSurface;
|
||||
class SourceSurfaceSkia;
|
||||
class BorrowedCGContext;
|
||||
|
||||
@ -38,6 +39,7 @@ class DrawTargetSkia : public DrawTarget {
|
||||
return BackendType::SKIA;
|
||||
}
|
||||
virtual already_AddRefed<SourceSurface> Snapshot() override;
|
||||
already_AddRefed<SourceSurface> GetBackingSurface() override;
|
||||
virtual IntSize GetSize() const override { return mSize; };
|
||||
virtual bool LockBits(uint8_t** aData, IntSize* aSize, int32_t* aStride,
|
||||
SurfaceFormat* aFormat,
|
||||
@ -132,6 +134,7 @@ class DrawTargetSkia : public DrawTarget {
|
||||
bool Init(unsigned char* aData, const IntSize& aSize, int32_t aStride,
|
||||
SurfaceFormat aFormat, bool aUninitialized = false);
|
||||
bool Init(SkCanvas* aCanvas);
|
||||
bool Init(RefPtr<DataSourceSurface>&& aSurface);
|
||||
|
||||
// Skia assumes that texture sizes fit in 16-bit signed integers.
|
||||
static size_t GetMaxSurfaceSize() { return 32767; }
|
||||
@ -145,6 +148,8 @@ class DrawTargetSkia : public DrawTarget {
|
||||
private:
|
||||
friend class SourceSurfaceSkia;
|
||||
|
||||
static void ReleaseMappedSkSurface(void* aPixels, void* aContext);
|
||||
|
||||
void MarkChanged();
|
||||
|
||||
void DrawGlyphs(ScaledFont* aFont, const GlyphBuffer& aBuffer,
|
||||
@ -163,6 +168,7 @@ class DrawTargetSkia : public DrawTarget {
|
||||
IntSize mSize;
|
||||
sk_sp<SkSurface> mSurface;
|
||||
SkCanvas* mCanvas;
|
||||
RefPtr<DataSourceSurface> mBackingSurface;
|
||||
RefPtr<SourceSurfaceSkia> mSnapshot;
|
||||
Mutex mSnapshotLock;
|
||||
|
||||
|
@ -326,7 +326,7 @@ already_AddRefed<SourceSurface> nsSVGPatternFrame::PaintPattern(
|
||||
patternHeight / surfaceSize.height);
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> dt = aDrawTarget->CreateSimilarDrawTarget(
|
||||
RefPtr<DrawTarget> dt = aDrawTarget->CreateSimilarDrawTargetWithBacking(
|
||||
surfaceSize, SurfaceFormat::B8G8R8A8);
|
||||
if (!dt || !dt->IsValid()) {
|
||||
return nullptr;
|
||||
@ -377,7 +377,7 @@ already_AddRefed<SourceSurface> nsSVGPatternFrame::PaintPattern(
|
||||
}
|
||||
|
||||
// caller now owns the surface
|
||||
return dt->Snapshot();
|
||||
return dt->GetBackingSurface();
|
||||
}
|
||||
|
||||
/* Will probably need something like this... */
|
||||
|
Loading…
Reference in New Issue
Block a user