Remove SkTextBlobDiffCanvas, use tracking device directly with base SkCanvas

Chromium has been updated to use makeAnalysisCanvas directly and there are
no more references to SkTextBlobDiffCanvas as a type in its code base.

Since the GlyphTrackingDevice extends SkNoPixelsDevice, any SkCanvas that
uses it is effectively a "no-draw" canvas. However, by returning a base
SkCanvas the text tracking now automatically happens in the context of
the base's AutoLayerForImageFilter handling it applies on every draw. This
means that drawing a text blob with an image filter that modifies the
transform state will now be analyzed in that context automatically
(simplifying code in chrome after this lands).

Another behavioral change is that all non-text draws will still go through
the base SkCanvas' virtuals and invoke the device function. Since it's an
SkNoPixelsDevice, it'll still be a no-op, it just happens a little later.
This won't really impact performance because oop-r already inspects their
operations and only plays back text and transform related ones to the
analysis canvas, so we shouldn't really see non-text draws being invoked
anyways.

Bug: chromium:1187246
Change-Id: I83f86571300751f385b3065dfe889f218fa1edc6
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/405196
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
Michael Ludwig 2021-05-06 08:59:26 -04:00 committed by Skia Commit-Bot
parent 722cb67b09
commit 97f85bb7fd
6 changed files with 65 additions and 117 deletions

View File

@ -223,11 +223,12 @@ class DiffCanvasBench : public Benchmark {
void onDraw(int loops, SkCanvas* modelCanvas) override {
SkSurfaceProps props;
if (modelCanvas) { modelCanvas->getProps(&props); }
SkTextBlobCacheDiffCanvas canvas{1024, 1024, props, fServer.get()};
std::unique_ptr<SkCanvas> canvas = fServer->makeAnalysisCanvas(1024, 1024, props,
nullptr, true);
loops *= 100;
while (loops --> 0) {
for (const auto& record : fTrace) {
canvas.drawTextBlob(
canvas->drawTextBlob(
record.blob.get(), record.offset.x(), record.offset.y(),record.paint);
}
}

View File

@ -512,7 +512,6 @@ private:
friend class SkFontPriv;
friend class SkGlyphRunListPainter;
friend class SkTextBlobCacheDiffCanvas;
friend class SkStrikeSpec;
};

View File

@ -809,10 +809,10 @@ RemoteStrike* SkStrikeServerImpl::getOrCreateCache(
return remoteStrikePtr;
}
// -- TrackLayerDevice -----------------------------------------------------------------------------
class SkTextBlobCacheDiffCanvas::TrackLayerDevice final : public SkNoPixelsDevice {
// -- GlyphTrackingDevice --------------------------------------------------------------------------
class GlyphTrackingDevice final : public SkNoPixelsDevice {
public:
TrackLayerDevice(
GlyphTrackingDevice(
const SkISize& dimensions, const SkSurfaceProps& props, SkStrikeServerImpl* server,
sk_sp<SkColorSpace> colorSpace, bool DFTSupport)
: SkNoPixelsDevice(SkIRect::MakeSize(dimensions), props, std::move(colorSpace))
@ -824,8 +824,8 @@ public:
SkBaseDevice* onCreateDevice(const CreateInfo& cinfo, const SkPaint*) override {
const SkSurfaceProps surfaceProps(this->surfaceProps().flags(), cinfo.fPixelGeometry);
return new TrackLayerDevice(cinfo.fInfo.dimensions(), surfaceProps, fStrikeServerImpl,
cinfo.fInfo.refColorSpace(), fDFTSupport);
return new GlyphTrackingDevice(cinfo.fInfo.dimensions(), surfaceProps, fStrikeServerImpl,
cinfo.fInfo.refColorSpace(), fDFTSupport);
}
protected:
@ -857,40 +857,6 @@ private:
SkGlyphRunListPainter fPainter;
};
// -- SkTextBlobCacheDiffCanvas -------------------------------------------------------------------
SkTextBlobCacheDiffCanvas::SkTextBlobCacheDiffCanvas(int width, int height,
const SkSurfaceProps& props,
SkStrikeServer* strikeServer,
bool DFTSupport)
: SkTextBlobCacheDiffCanvas{width, height, props, strikeServer, nullptr, DFTSupport} { }
SkTextBlobCacheDiffCanvas::SkTextBlobCacheDiffCanvas(int width, int height,
const SkSurfaceProps& props,
SkStrikeServer* strikeServer,
sk_sp<SkColorSpace> colorSpace,
bool DFTSupport)
: SkNoDrawCanvas{sk_make_sp<TrackLayerDevice>(SkISize::Make(width, height),
props,
strikeServer->impl(),
std::move(colorSpace),
DFTSupport)} { }
SkTextBlobCacheDiffCanvas::~SkTextBlobCacheDiffCanvas() = default;
SkCanvas::SaveLayerStrategy SkTextBlobCacheDiffCanvas::getSaveLayerStrategy(
const SaveLayerRec& rec) {
return kFullLayer_SaveLayerStrategy;
}
bool SkTextBlobCacheDiffCanvas::onDoSaveBehind(const SkRect*) {
return false;
}
void SkTextBlobCacheDiffCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) {
SkCanvas::onDrawTextBlob(blob, x, y, paint);
}
// -- SkStrikeServer -------------------------------------------------------------------------------
SkStrikeServer::SkStrikeServer(DiscardableHandleManager* dhm)
: fImpl(new SkStrikeServerImpl{dhm}) { }
@ -901,8 +867,11 @@ std::unique_ptr<SkCanvas> SkStrikeServer::makeAnalysisCanvas(int width, int heig
const SkSurfaceProps& props,
sk_sp<SkColorSpace> colorSpace,
bool DFTSupport) {
return std::make_unique<SkTextBlobCacheDiffCanvas>(width, height, props, this,
std::move(colorSpace), DFTSupport);
sk_sp<SkBaseDevice> trackingDevice(new GlyphTrackingDevice(SkISize::Make(width, height),
props, this->impl(),
std::move(colorSpace),
DFTSupport));
return std::make_unique<SkCanvas>(std::move(trackingDevice));
}
sk_sp<SkData> SkStrikeServer::serializeTypeface(SkTypeface* tf) {

View File

@ -28,31 +28,6 @@ class SkStrikeServer;
class SkStrikeServerImpl;
class SkTypeface;
// A SkTextBlobCacheDiffCanvas is used to populate the SkStrikeServer with ops
// which will be serialized and rendered using the SkStrikeClient.
class SkTextBlobCacheDiffCanvas : public SkNoDrawCanvas {
public:
// For testing use only
SkTextBlobCacheDiffCanvas(int width, int height, const SkSurfaceProps& props,
SkStrikeServer* strikeServer, bool DFTSupport = true);
SK_SPI SkTextBlobCacheDiffCanvas(int width, int height, const SkSurfaceProps& props,
SkStrikeServer* strikeServer, sk_sp<SkColorSpace> colorSpace,
bool DFTSupport);
SK_SPI ~SkTextBlobCacheDiffCanvas() override;
protected:
SkCanvas::SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override;
bool onDoSaveBehind(const SkRect*) override;
void onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
const SkPaint& paint) override;
private:
class TrackLayerDevice;
};
using SkDiscardableHandleId = uint32_t;
// This class is not thread-safe.
class SkStrikeServer {
@ -94,7 +69,7 @@ public:
// Serializes the typeface to be transmitted using this server.
SK_SPI sk_sp<SkData> serializeTypeface(SkTypeface*);
// Serializes the strike data captured using a SkTextBlobCacheDiffCanvas. Any
// Serializes the strike data captured using a canvas returned by ::makeAnalysisCanvas. Any
// handles locked using the DiscardableHandleManager will be assumed to be
// unlocked after this call.
SK_SPI void writeStrikeData(std::vector<uint8_t>* memory);
@ -104,7 +79,6 @@ public:
size_t remoteStrikeMapSizeForTesting() const;
private:
friend class SkTextBlobCacheDiffCanvas;
SkStrikeServerImpl* impl();
std::unique_ptr<SkStrikeServerImpl> fImpl;

View File

@ -213,9 +213,9 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_StrikeSerialization, repor
int glyphCount = 10;
auto serverBlob = buildTextBlob(serverTf, glyphCount);
auto props = FindSurfaceProps(dContext);
SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, props, &server,
dContext->supportsDistanceFieldText());
cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
10, 10, props, nullptr, dContext->supportsDistanceFieldText());
cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
std::vector<uint8_t> serverStrikeData;
server.writeStrikeData(&serverStrikeData);
@ -250,9 +250,9 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_ReleaseTypeFace, reporter,
int glyphCount = 10;
auto serverBlob = buildTextBlob(serverTf, glyphCount);
const SkSurfaceProps props;
SkTextBlobCacheDiffCanvas cache_diff_canvas(
10, 10, props, &server, ctxInfo.directContext()->supportsDistanceFieldText());
cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
10, 10, props, nullptr, ctxInfo.directContext()->supportsDistanceFieldText());
cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
REPORTER_ASSERT(reporter, !serverTf->unique());
std::vector<uint8_t> serverStrikeData;
@ -275,9 +275,10 @@ DEF_TEST(SkRemoteGlyphCache_StrikeLockingServer, reporter) {
auto serverBlob = buildTextBlob(serverTf, glyphCount);
const SkSurfaceProps props;
SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, props, &server);
std::unique_ptr<SkCanvas> cache_diff_canvas =
server.makeAnalysisCanvas(10, 10, props, nullptr, true);
SkPaint paint;
cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
// The strike from the blob should be locked after it has been drawn on the canvas.
REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u);
@ -290,7 +291,7 @@ DEF_TEST(SkRemoteGlyphCache_StrikeLockingServer, reporter) {
discardableManager->unlockAll();
REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 0u);
cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u);
REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 1u);
@ -309,9 +310,10 @@ DEF_TEST(SkRemoteGlyphCache_StrikeDeletionServer, reporter) {
auto serverBlob = buildTextBlob(serverTf, glyphCount);
const SkSurfaceProps props;
SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, props, &server);
std::unique_ptr<SkCanvas> cache_diff_canvas =
server.makeAnalysisCanvas(10, 10, props, nullptr, true);
SkPaint paint;
cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u);
// Write the strike data and delete all the handles. Re-analyzing the blob should create new
@ -321,12 +323,12 @@ DEF_TEST(SkRemoteGlyphCache_StrikeDeletionServer, reporter) {
// Another analysis pass, to ensure that deleting handles after a complete cache hit still
// works. This is a regression test for crbug.com/999682.
cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
server.writeStrikeData(&fontData);
REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u);
discardableManager->unlockAndDeleteAll();
cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
REPORTER_ASSERT(reporter, discardableManager->handleCount() == 2u);
// Must unlock everything on termination, otherwise valgrind complains about memory leaks.
@ -346,9 +348,10 @@ DEF_TEST(SkRemoteGlyphCache_StrikePinningClient, reporter) {
auto serverBlob = buildTextBlob(serverTf, glyphCount);
const SkSurfaceProps props;
SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, props, &server);
std::unique_ptr<SkCanvas> cache_diff_canvas =
server.makeAnalysisCanvas(10, 10, props, nullptr, true);
SkPaint paint;
cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
std::vector<uint8_t> serverStrikeData;
server.writeStrikeData(&serverStrikeData);
@ -385,9 +388,10 @@ DEF_TEST(SkRemoteGlyphCache_ClientMemoryAccounting, reporter) {
auto serverBlob = buildTextBlob(serverTf, glyphCount);
const SkSurfaceProps props;
SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, props, &server);
std::unique_ptr<SkCanvas> cache_diff_canvas =
server.makeAnalysisCanvas(10, 10, props, nullptr, true);
SkPaint paint;
cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
std::vector<uint8_t> serverStrikeData;
server.writeStrikeData(&serverStrikeData);
@ -412,10 +416,11 @@ DEF_TEST(SkRemoteGlyphCache_PurgesServerEntries, reporter) {
auto serverBlob = buildTextBlob(serverTf, glyphCount);
const SkSurfaceProps props;
SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, props, &server);
std::unique_ptr<SkCanvas> cache_diff_canvas =
server.makeAnalysisCanvas(10, 10, props, nullptr, true);
SkPaint paint;
REPORTER_ASSERT(reporter, server.remoteStrikeMapSizeForTesting() == 0u);
cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
REPORTER_ASSERT(reporter, server.remoteStrikeMapSizeForTesting() == 1u);
}
@ -433,10 +438,11 @@ DEF_TEST(SkRemoteGlyphCache_PurgesServerEntries, reporter) {
auto serverBlob = buildTextBlob(serverTf, glyphCount);
const SkSurfaceProps props;
SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, props, &server);
std::unique_ptr<SkCanvas> cache_diff_canvas =
server.makeAnalysisCanvas(10, 10, props, nullptr, true);
SkPaint paint;
REPORTER_ASSERT(reporter, server.remoteStrikeMapSizeForTesting() == 1u);
cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
REPORTER_ASSERT(reporter, server.remoteStrikeMapSizeForTesting() == 1u);
}
@ -462,9 +468,9 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsPath, reporter,
int glyphCount = 10;
auto serverBlob = buildTextBlob(serverTf, glyphCount);
auto props = FindSurfaceProps(direct);
SkTextBlobCacheDiffCanvas cache_diff_canvas(
10, 10, props, &server, direct->supportsDistanceFieldText());
cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
10, 10, props, nullptr, direct->supportsDistanceFieldText());
cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
std::vector<uint8_t> serverStrikeData;
server.writeStrikeData(&serverStrikeData);
@ -538,9 +544,9 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsMaskWithPathFall
auto serverBlob = make_blob_causing_fallback(serverTf, serverTf.get(), reporter);
auto props = FindSurfaceProps(direct);
SkTextBlobCacheDiffCanvas cache_diff_canvas(
10, 10, props, &server, direct->supportsDistanceFieldText());
cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
10, 10, props, nullptr, direct->supportsDistanceFieldText());
cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
std::vector<uint8_t> serverStrikeData;
server.writeStrikeData(&serverStrikeData);
@ -609,9 +615,9 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsSDFTWithAllARGBF
auto serverBlob = makeBlob(serverTf);
auto props = FindSurfaceProps(ctxInfo.grContext());
SkTextBlobCacheDiffCanvas cache_diff_canvas(
800, 800, props, &server, ctxInfo.grContext()->supportsDistanceFieldText());
cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 400, paint);
std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
10, 10, props, nullptr, ctxInfo.directContext()->supportsDistanceFieldText());
cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 400, paint);
std::vector<uint8_t> serverStrikeData;
server.writeStrikeData(&serverStrikeData);
@ -651,9 +657,9 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextXY, reporter, ctxI
int glyphCount = 10;
auto serverBlob = buildTextBlob(serverTf, glyphCount);
auto props = FindSurfaceProps(direct);
SkTextBlobCacheDiffCanvas cache_diff_canvas(
10, 10, props, &server, direct->supportsDistanceFieldText());
cache_diff_canvas.drawTextBlob(serverBlob.get(), 0.5, 0, paint);
std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
10, 10, props, nullptr, direct->supportsDistanceFieldText());
cache_diff_canvas->drawTextBlob(serverBlob.get(), 0.5, 0, paint);
std::vector<uint8_t> serverStrikeData;
server.writeStrikeData(&serverStrikeData);
@ -693,10 +699,10 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsDFT, reporter, c
int glyphCount = 10;
auto serverBlob = buildTextBlob(serverTf, glyphCount);
const SkSurfaceProps props;
SkTextBlobCacheDiffCanvas cache_diff_canvas(
10, 10, props, &server, direct->supportsDistanceFieldText());
cache_diff_canvas.concat(matrix);
cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint);
std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
10, 10, props, nullptr, direct->supportsDistanceFieldText());
cache_diff_canvas->concat(matrix);
cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
std::vector<uint8_t> serverStrikeData;
server.writeStrikeData(&serverStrikeData);
@ -781,13 +787,14 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_TypefaceWithNoPaths, repor
auto serverTfData = server.serializeTypeface(serverTf.get());
auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size());
auto props = FindSurfaceProps(direct);
std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
500, 500, props, nullptr, direct->supportsDistanceFieldText());
for (SkScalar textSize : { 70, 180, 270, 340}) {
auto serverBlob = MakeEmojiBlob(serverTf, textSize);
auto props = FindSurfaceProps(direct);
SkTextBlobCacheDiffCanvas cache_diff_canvas(
500, 500, props, &server, direct->supportsDistanceFieldText());
SkPaint paint;
cache_diff_canvas.drawTextBlob(serverBlob.get(), 100, 100, paint);
cache_diff_canvas->drawTextBlob(serverBlob.get(), 100, 100, paint);
std::vector<uint8_t> serverStrikeData;
server.writeStrikeData(&serverStrikeData);
@ -807,4 +814,3 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_TypefaceWithNoPaths, repor
// Must unlock everything on termination, otherwise valgrind complains about memory leaks.
discardableManager->unlockAndDeleteAll();
}

View File

@ -136,9 +136,9 @@ static bool push_font_data(const SkPicture& pic, SkStrikeServer* strikeServer,
sk_sp<SkColorSpace> colorSpace, int writeFd) {
const SkIRect bounds = pic.cullRect().round();
const SkSurfaceProps props(0, kRGB_H_SkPixelGeometry);
SkTextBlobCacheDiffCanvas filter(bounds.width(), bounds.height(), props,
strikeServer, std::move(colorSpace), true);
pic.playback(&filter);
std::unique_ptr<SkCanvas> filter = strikeServer->makeAnalysisCanvas(
bounds.width(), bounds.height(), props, std::move(colorSpace), true);
pic.playback(filter.get());
std::vector<uint8_t> fontData;
strikeServer->writeStrikeData(&fontData);
@ -324,4 +324,3 @@ int main(int argc, char** argv) {
return 0;
}