working serialize Slugs with DirectMask runs

Add fully functional flatten, and MakeFromBuffer functionality
for the DirectMaskSubRunSlug type. The other runs will need to come
later.

Add MakeFromBuffer stubs for all the rest of the subrun types.

This has a single unit test to check basic functionality of
flatten and MakeFromBuffer calls.

Change-Id: I379ded4609a2160170ed6a3670c7c7b6ed2c5b2e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/509137
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2022-02-07 10:30:47 -05:00 committed by SkCQ
parent e39f253c2a
commit d3243f660e
2 changed files with 157 additions and 18 deletions

View File

@ -520,6 +520,12 @@ public:
return true;
}
const GrAtlasSubRun* testingOnly_atlasSubRun() const override { return nullptr; }
static GrSubRunOwner MakeFromBuffer(const GrTextReferenceFrame* referenceFrame,
SkReadBuffer& buffer,
GrSubRunAllocator* alloc,
const SkStrikeClient* client) {
return nullptr;
}
protected:
SubRunType subRunType() const override { return kPath; }
@ -641,7 +647,15 @@ GrSubRunOwner make_drawable_sub_run(const SkZip<SkGlyphVariant, SkPoint>& drawab
// -- DrawableSubRunSlug ---------------------------------------------------------------------------
class DrawableSubRunSlug : public GrSubRun {
public:
DrawableSubRunSlug(DrawableOpSubmitter&& drawingDrawing) : fDrawingDrawing(std::move(drawingDrawing)) {}
DrawableSubRunSlug(DrawableOpSubmitter&& drawingDrawing)
: fDrawingDrawing(std::move(drawingDrawing)) {}
static GrSubRunOwner MakeFromBuffer(const GrTextReferenceFrame* referenceFrame,
SkReadBuffer& buffer,
GrSubRunAllocator* alloc,
const SkStrikeClient* client) {
return nullptr;
}
void draw(SkCanvas* canvas,
const GrClip* clip,
@ -1109,6 +1123,13 @@ public:
GrMaskFormat format,
GrSubRunAllocator* alloc);
static GrSubRunOwner MakeFromBuffer(const GrTextReferenceFrame* referenceFrame,
SkReadBuffer& buffer,
GrSubRunAllocator* alloc,
const SkStrikeClient* client) {
return nullptr;
}
void draw(SkCanvas*,
const GrClip*,
const SkMatrixProvider& viewMatrix,
@ -1326,6 +1347,13 @@ public:
const GrSDFTMatrixRange& matrixRange,
GrSubRunAllocator* alloc);
static GrSubRunOwner MakeFromBuffer(const GrTextReferenceFrame* referenceFrame,
SkReadBuffer& buffer,
GrSubRunAllocator* alloc,
const SkStrikeClient* client) {
return nullptr;
}
void draw(SkCanvas*,
const GrClip*,
const SkMatrixProvider& viewMatrix,
@ -2777,6 +2805,11 @@ public:
GrMaskFormat format,
GrSubRunAllocator* alloc);
static GrSubRunOwner MakeFromBuffer(const GrTextReferenceFrame* referenceFrame,
SkReadBuffer& buffer,
GrSubRunAllocator* alloc,
const SkStrikeClient* client);
void draw(SkCanvas*,
const GrClip* clip,
const SkMatrixProvider& viewMatrix,
@ -2816,9 +2849,7 @@ public:
protected:
SubRunType subRunType() const override { return kDirectMask; }
void doFlatten(SkWriteBuffer& buffer) const override {
SK_ABORT("Not implemented.");
}
void doFlatten(SkWriteBuffer& buffer) const override;
private:
// Return true if the positionMatrix represents an integer translation. Return the device
@ -2891,6 +2922,54 @@ GrSubRunOwner DirectMaskSubRunSlug::Make(const GrTextReferenceFrame* referenceFr
GrGlyphVector{std::move(strike), {glyphIDs, goodPosCount}});
}
template <typename T>
static bool pun_read(SkReadBuffer& buffer, T* dst) {
return buffer.readPad32(dst, sizeof(T));
}
GrSubRunOwner DirectMaskSubRunSlug::MakeFromBuffer(const GrTextReferenceFrame* referenceFrame,
SkReadBuffer& buffer,
GrSubRunAllocator* alloc,
const SkStrikeClient*) {
GrMaskFormat format = (GrMaskFormat)buffer.readInt();
SkGlyphRect runBounds;
pun_read(buffer, &runBounds);
int glyphCount = buffer.readInt();
SkASSERT(0 < glyphCount);
if (glyphCount <= 0) { return nullptr; }
DevicePosition* positionsData = alloc->makePODArray<DevicePosition>(glyphCount);
for (int i = 0; i < glyphCount; ++i) {
pun_read(buffer, &positionsData[i]);
}
SkSpan<DevicePosition> positions(positionsData, glyphCount);
auto glyphVector = GrGlyphVector::MakeFromBuffer(buffer, alloc);
SkASSERT(glyphVector.has_value());
if (!glyphVector) { return nullptr; }
SkASSERT(SkTo<int>(glyphVector->glyphs().size()) == glyphCount);
if (SkTo<int>(glyphVector->glyphs().size()) != glyphCount) { return nullptr; }
return alloc->makeUnique<DirectMaskSubRunSlug>(
referenceFrame, format, runBounds, positions, std::move(glyphVector.value()));
}
template <typename T>
static void pun_write(SkWriteBuffer& buffer, const T& src) {
buffer.writePad32(&src, sizeof(T));
}
void DirectMaskSubRunSlug::doFlatten(SkWriteBuffer& buffer) const {
buffer.writeInt(fMaskFormat);
pun_write(buffer, fGlyphDeviceBounds);
int glyphCount = SkTo<int>(fLeftTopDevicePos.size());
buffer.writeInt(glyphCount);
for (auto pos : fLeftTopDevicePos) {
pun_write(buffer, pos);
}
fGlyphs.flatten(buffer);
}
int DirectMaskSubRunSlug::unflattenSize() const {
return sizeof(DirectMaskSubRunSlug) +
fGlyphs.unflattenSize() +
@ -3177,12 +3256,10 @@ sk_sp<Slug> Slug::Make(const SkMatrixProvider& viewMatrix,
size_t allocationSize = sizeof(GrTextBlob) + bytesNeededForSubRun;
void* allocation = ::operator new (allocationSize);
const SkMatrix positionMatrix =
position_matrix(viewMatrix.localToDevice(), glyphRunList.origin());
sk_sp<Slug> slug{new (allocation)
sk_sp<Slug> slug{new (::operator new (allocationSize))
Slug(glyphRunList.sourceBounds(),
paint,
positionMatrix,
@ -3196,7 +3273,7 @@ sk_sp<Slug> Slug::Make(const SkMatrixProvider& viewMatrix,
positionMatrix,
paint,
control,
"Slug",
"Make Slug",
uniqueID);
}
@ -3305,11 +3382,11 @@ GrSubRunOwner GrSubRun::MakeFromBuffer(const GrTextReferenceFrame* referenceFram
/* The makers will be populated in the next CL. */
static Maker makers[kSubRunTypeCount] = {
nullptr, // 0 index is bad.
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
DirectMaskSubRunSlug::MakeFromBuffer,
SDFTSubRun::MakeFromBuffer,
TransformedMaskSubRun::MakeFromBuffer,
PathSubRun::MakeFromBuffer,
DrawableSubRunSlug::MakeFromBuffer,
};
int subRunTypeInt = buffer.readInt();
SkASSERT(kBad < subRunTypeInt && subRunTypeInt < kSubRunTypeCount);
@ -3318,7 +3395,7 @@ GrSubRunOwner GrSubRun::MakeFromBuffer(const GrTextReferenceFrame* referenceFram
}
auto maker = makers[subRunTypeInt];
if (!buffer.validate(maker != nullptr)) { return nullptr; }
return makers[subRunTypeInt](referenceFrame, buffer, alloc, client);
return maker(referenceFrame, buffer, alloc, client);
}
sk_sp<GrSlug> SkMakeSlugFromBuffer(SkReadBuffer& buffer, const SkStrikeClient* client) {

View File

@ -15,6 +15,7 @@
#include "include/private/chromium/SkChromeRemoteGlyphCache.h"
#include "src/core/SkDraw.h"
#include "src/core/SkFontPriv.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkScalerCache.h"
#include "src/core/SkStrikeCache.h"
#include "src/core/SkStrikeSpec.h"
@ -187,7 +188,23 @@ SkBitmap RasterBlob(sk_sp<SkTextBlob> blob, int width, int height, const SkPaint
return bitmap;
}
SkBitmap RasterSlug(sk_sp<SkTextBlob> blob, int width, int height, const SkPaint& paint,
SkBitmap RasterBlobThroughSlug(sk_sp<SkTextBlob> blob, int width, int height, const SkPaint& paint,
GrRecordingContext* rContext, const SkMatrix* matrix = nullptr,
SkScalar x = 0) {
auto surface = MakeSurface(width, height, rContext);
if (matrix) {
surface->getCanvas()->concat(*matrix);
}
auto canvas = surface->getCanvas();
auto slug = GrSlug::ConvertBlob(canvas, *blob, {x, height/2.0f}, paint);
slug->draw(canvas);
SkBitmap bitmap;
bitmap.allocN32Pixels(width, height);
surface->readPixels(bitmap, 0, 0);
return bitmap;
}
SkBitmap RasterSlug(sk_sp<GrSlug> slug, int width, int height, const SkPaint& paint,
GrRecordingContext* rContext, const SkMatrix* matrix = nullptr,
SkScalar x = 0) {
auto surface = MakeSurface(width, height, rContext);
@ -195,7 +212,6 @@ SkBitmap RasterSlug(sk_sp<SkTextBlob> blob, int width, int height, const SkPaint
surface->getCanvas()->concat(*matrix);
}
auto canvas = surface->getCanvas();
auto slug = GrSlug::ConvertBlob(canvas, *blob, {x, height/2.0f}, paint);
slug->draw(canvas);
SkBitmap bitmap;
bitmap.allocN32Pixels(width, height);
@ -291,8 +307,54 @@ DEF_GPUTEST_FOR_CONTEXTS(SkRemoteGlyphCache_StrikeSerializationSlug,
client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
auto clientBlob = buildTextBlob(clientTf, glyphCount);
SkBitmap expected = RasterSlug(serverBlob, 10, 10, paint, dContext);
SkBitmap actual = RasterSlug(clientBlob, 10, 10, paint, dContext);
SkBitmap expected = RasterBlobThroughSlug(serverBlob, 10, 10, paint, dContext);
SkBitmap actual = RasterBlobThroughSlug(clientBlob, 10, 10, paint, dContext);
compare_blobs(expected, actual, reporter);
REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
// Must unlock everything on termination, otherwise valgrind complains about memory leaks.
discardableManager->unlockAndDeleteAll();
}
DEF_GPUTEST_FOR_CONTEXTS(SkRemoteGlyphCache_SlugSerialization,
sk_gpu_test::GrContextFactory::IsRenderingContext,
reporter, ctxInfo, use_padding_options) {
auto dContext = ctxInfo.directContext();
sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
SkStrikeServer server(discardableManager.get());
SkStrikeClient client(discardableManager, false);
const SkPaint paint;
// Server.
auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle());
auto serverTfData = server.serializeTypeface(serverTf.get());
int glyphCount = 10;
auto serverBlob = buildTextBlob(serverTf, glyphCount);
auto props = FindSurfaceProps(dContext);
std::unique_ptr<SkCanvas> analysisCanvas = server.makeAnalysisCanvas(
10, 10, props, nullptr, dContext->supportsDistanceFieldText());
// Generate strike updates.
auto srcSlug = GrSlug::ConvertBlob(analysisCanvas.get(), *serverBlob, {0, 0}, paint);
SkBinaryWriteBuffer writeBuffer;
srcSlug->flatten(writeBuffer);
auto data = writeBuffer.snapshotAsData();
SkReadBuffer readBuffer(data->data(), data->size());
auto dstSlug = client.makeSlugFromBuffer(readBuffer);
REPORTER_ASSERT(reporter, dstSlug != nullptr);
std::vector<uint8_t> serverStrikeData;
server.writeStrikeData(&serverStrikeData);
// Client.
REPORTER_ASSERT(reporter,
client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
SkBitmap expected = RasterSlug(srcSlug, 10, 10, paint, dContext);
SkBitmap actual = RasterSlug(dstSlug, 10, 10, paint, dContext);
compare_blobs(expected, actual, reporter);
REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());