diff options
-rw-r--r-- | include/gpu/GrContext.h | 2 | ||||
-rw-r--r-- | src/core/SkRemoteGlyphCache.cpp | 69 | ||||
-rw-r--r-- | src/core/SkRemoteGlyphCache.h | 17 | ||||
-rw-r--r-- | src/gpu/GrContext.cpp | 4 | ||||
-rw-r--r-- | src/gpu/GrShaderCaps.h | 2 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasTextContext.cpp | 68 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasTextContext.h | 24 | ||||
-rw-r--r-- | tests/SkRemoteGlyphCacheTest.cpp | 111 |
8 files changed, 234 insertions, 63 deletions
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h index 6a52c5c2d0..525e5d77b8 100644 --- a/include/gpu/GrContext.h +++ b/include/gpu/GrContext.h @@ -282,6 +282,8 @@ public: // Chrome is using this! void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const; + bool supportsDistanceFieldText() const; + protected: GrContext(GrBackend, int32_t id = SK_InvalidGenID); diff --git a/src/core/SkRemoteGlyphCache.cpp b/src/core/SkRemoteGlyphCache.cpp index c7f1f4497b..d5e96fce88 100644 --- a/src/core/SkRemoteGlyphCache.cpp +++ b/src/core/SkRemoteGlyphCache.cpp @@ -23,6 +23,7 @@ #if SK_SUPPORT_GPU #include "GrDrawOpAtlas.h" +#include "text/GrAtlasTextContext.h" #endif static SkDescriptor* auto_descriptor_from_desc(const SkDescriptor* source_desc, @@ -188,14 +189,18 @@ public: }; // -- SkTextBlobCacheDiffCanvas ------------------------------------------------------------------- +SkTextBlobCacheDiffCanvas::Settings::Settings() = default; +SkTextBlobCacheDiffCanvas::Settings::~Settings() = default; + SkTextBlobCacheDiffCanvas::SkTextBlobCacheDiffCanvas(int width, int height, const SkMatrix& deviceMatrix, const SkSurfaceProps& props, - SkStrikeServer* strikeSever) + SkStrikeServer* strikeSever, Settings settings) : SkNoDrawCanvas{sk_make_sp<TrackLayerDevice>(SkIRect::MakeWH(width, height), props)} , fDeviceMatrix{deviceMatrix} , fSurfaceProps{props} - , fStrikeServer{strikeSever} { + , fStrikeServer{strikeSever} + , fSettings{settings} { SkASSERT(fStrikeServer); } @@ -274,6 +279,23 @@ void SkTextBlobCacheDiffCanvas::processGlyphRun( runMatrix.preTranslate(position.x(), position.y()); runMatrix.preTranslate(it.offset().x(), it.offset().y()); +#if SK_SUPPORT_GPU + GrAtlasTextContext::Options options; + options.fMinDistanceFieldFontSize = fSettings.fMinDistanceFieldFontSize; + options.fMaxDistanceFieldFontSize = fSettings.fMaxDistanceFieldFontSize; + GrAtlasTextContext::SanitizeOptions(&options); + if (GrAtlasTextContext::CanDrawAsDistanceFields(runPaint, runMatrix, fSurfaceProps, + fSettings.fContextSupportsDistanceFieldText, + options)) { + SkScalar textRatio; + SkPaint dfPaint(runPaint); + SkScalerContextFlags flags; + GrAtlasTextContext::InitDistanceFieldPaint(nullptr, &dfPaint, runMatrix, options, + &textRatio, &flags); + this->processGlyphRunForDFT(it, dfPaint, flags); + } +#endif + // If the matrix has perspective, we fall back to using distance field text or paths. // TODO: Add distance field text support, and FallbackTextHelper logic from GrAtlasTextContext. if (SkDraw::ShouldDrawTextAsPaths(runPaint, runMatrix)) { @@ -334,9 +356,11 @@ void SkTextBlobCacheDiffCanvas::processGlyphRun( SkScalerContextRec deviceSpecificRec; SkScalerContextEffects effects; - auto* glyphCacheState = static_cast<SkStrikeServer*>(fStrikeServer) - ->getOrCreateCache(runPaint, &fSurfaceProps, &runMatrix, - &deviceSpecificRec, &effects); + auto* glyphCacheState = + static_cast<SkStrikeServer*>(fStrikeServer) + ->getOrCreateCache(runPaint, &fSurfaceProps, &runMatrix, + SkScalerContextFlags::kFakeGammaAndBoostContrast, + &deviceSpecificRec, &effects); SkASSERT(glyphCacheState); const bool asPath = false; @@ -371,11 +395,33 @@ void SkTextBlobCacheDiffCanvas::processGlyphRunForPaths(const SkTextBlobRunItera SkScalerContextRec deviceSpecificRec; SkScalerContextEffects effects; + auto* glyphCacheState = + static_cast<SkStrikeServer*>(fStrikeServer) + ->getOrCreateCache(pathPaint, &fSurfaceProps, nullptr, + SkScalerContextFlags::kFakeGammaAndBoostContrast, + &deviceSpecificRec, &effects); + + const bool asPath = true; + const SkIPoint subPixelPos{0, 0}; + const uint16_t* glyphs = it.glyphs(); + for (uint32_t index = 0; index < it.glyphCount(); index++) { + glyphCacheState->addGlyph(runPaint.getTypeface(), + effects, + SkPackedGlyphID(glyphs[index], subPixelPos.x(), subPixelPos.y()), + asPath); + } +} + +void SkTextBlobCacheDiffCanvas::processGlyphRunForDFT(const SkTextBlobRunIterator& it, + const SkPaint& runPaint, + SkScalerContextFlags flags) { + SkScalerContextRec deviceSpecificRec; + SkScalerContextEffects effects; auto* glyphCacheState = static_cast<SkStrikeServer*>(fStrikeServer) - ->getOrCreateCache(pathPaint, &fSurfaceProps, nullptr, + ->getOrCreateCache(runPaint, &fSurfaceProps, nullptr, flags, &deviceSpecificRec, &effects); - const bool asPath = true; + const bool asPath = false; const SkIPoint subPixelPos{0, 0}; const uint16_t* glyphs = it.glyphs(); for (uint32_t index = 0; index < it.glyphCount(); index++) { @@ -451,15 +497,12 @@ SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache( const SkPaint& paint, const SkSurfaceProps* props, const SkMatrix* matrix, + SkScalerContextFlags flags, SkScalerContextRec* deviceRec, SkScalerContextEffects* effects) { SkScalerContextRec keyRec; - SkScalerContext::MakeRecAndEffects(paint, props, matrix, - SkScalerContextFlags::kFakeGammaAndBoostContrast, deviceRec, - effects, true); - SkScalerContext::MakeRecAndEffects(paint, props, matrix, - SkScalerContextFlags::kFakeGammaAndBoostContrast, &keyRec, - effects, false); + SkScalerContext::MakeRecAndEffects(paint, props, matrix, flags, deviceRec, effects, true); + SkScalerContext::MakeRecAndEffects(paint, props, matrix, flags, &keyRec, effects, false); TRACE_EVENT1("skia", "RecForDesc", "rec", TRACE_STR_COPY(keyRec.dump().c_str())); // TODO: possible perf improvement - don't recompute the device desc on cache hit. diff --git a/src/core/SkRemoteGlyphCache.h b/src/core/SkRemoteGlyphCache.h index 60d880791f..d1119cf70a 100644 --- a/src/core/SkRemoteGlyphCache.h +++ b/src/core/SkRemoteGlyphCache.h @@ -28,6 +28,7 @@ class Serializer; class SkDescriptor; class SkGlyphCache; struct SkPackedGlyphID; +enum SkScalerContextFlags : uint32_t; class SkScalerContextRecDescriptor; class SkTextBlobRunIterator; class SkTypefaceProxy; @@ -51,8 +52,17 @@ using SkDescriptorSet = // which will be serialized and renderered using the SkStrikeClient. class SK_API SkTextBlobCacheDiffCanvas : public SkNoDrawCanvas { public: + struct SK_API Settings { + Settings(); + ~Settings(); + + bool fContextSupportsDistanceFieldText = true; + SkScalar fMinDistanceFieldFontSize = -1.f; + SkScalar fMaxDistanceFieldFontSize = -1.f; + }; SkTextBlobCacheDiffCanvas(int width, int height, const SkMatrix& deviceMatrix, - const SkSurfaceProps& props, SkStrikeServer* strikeserver); + const SkSurfaceProps& props, SkStrikeServer* strikeserver, + Settings settings = Settings()); ~SkTextBlobCacheDiffCanvas() override; protected: @@ -70,10 +80,13 @@ private: const SkTextBlobRunIterator& it, const SkPaint& runPaint); void processGlyphRunForPaths(const SkTextBlobRunIterator& it, const SkPaint& runPaint); + void processGlyphRunForDFT(const SkTextBlobRunIterator& it, const SkPaint& runPaint, + SkScalerContextFlags flags); const SkMatrix fDeviceMatrix; const SkSurfaceProps fSurfaceProps; SkStrikeServer* const fStrikeServer; + const Settings fSettings; }; using SkDiscardableHandleId = uint32_t; @@ -161,7 +174,7 @@ public: }; SkGlyphCacheState* getOrCreateCache(const SkPaint&, const SkSurfaceProps*, const SkMatrix*, - SkScalerContextRec* deviceRec, + SkScalerContextFlags flags, SkScalerContextRec* deviceRec, SkScalerContextEffects* effects); private: diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 5be510d131..24c28e6d86 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -1514,6 +1514,10 @@ bool GrContext::validPMUPMConversionExists() { return fPMUPMConversionsRoundTrip; } +bool GrContext::supportsDistanceFieldText() const { + return fCaps->shaderCaps()->supportsDistanceFieldText(); +} + ////////////////////////////////////////////////////////////////////////////// // DDL TODO: remove 'maxResources' diff --git a/src/gpu/GrShaderCaps.h b/src/gpu/GrShaderCaps.h index 2f2d27708a..3e85b6c1aa 100644 --- a/src/gpu/GrShaderCaps.h +++ b/src/gpu/GrShaderCaps.h @@ -37,6 +37,8 @@ public: void dumpJSON(SkJSONWriter*) const; + bool supportsDistanceFieldText() const { return fShaderDerivativeSupport; } + bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; } bool geometryShaderSupport() const { return fGeometryShaderSupport; } bool gsInvocationsSupport() const { return fGSInvocationsSupport; } diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp index 8c964ba35e..1f06cfefba 100644 --- a/src/gpu/text/GrAtlasTextContext.cpp +++ b/src/gpu/text/GrAtlasTextContext.cpp @@ -41,14 +41,8 @@ static const int kDefaultMaxDistanceFieldFontSize = 2 * kLargeDFFontSize; #endif GrAtlasTextContext::GrAtlasTextContext(const Options& options) - : fDistanceAdjustTable(new GrDistanceFieldAdjustTable) { - fMaxDistanceFieldFontSize = options.fMaxDistanceFieldFontSize < 0.f - ? kDefaultMaxDistanceFieldFontSize - : options.fMaxDistanceFieldFontSize; - fMinDistanceFieldFontSize = options.fMinDistanceFieldFontSize < 0.f - ? kDefaultMinDistanceFieldFontSize - : options.fMinDistanceFieldFontSize; - fDistanceFieldVerticesAlwaysHaveW = options.fDistanceFieldVerticesAlwaysHaveW; + : fDistanceAdjustTable(new GrDistanceFieldAdjustTable), fOptions(options) { + SanitizeOptions(&fOptions); } std::unique_ptr<GrAtlasTextContext> GrAtlasTextContext::Make(const Options& options) { @@ -211,7 +205,8 @@ void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob, } cacheBlob->setRunPaintFlags(run, runPaint.skPaint().getFlags()); - if (this->canDrawAsDistanceFields(runPaint, viewMatrix, props, shaderCaps)) { + if (CanDrawAsDistanceFields(runPaint, viewMatrix, props, + shaderCaps.supportsDistanceFieldText(), fOptions)) { switch (it.positioning()) { case SkTextBlob::kDefault_Positioning: { this->drawDFText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, @@ -274,7 +269,8 @@ GrAtlasTextContext::makeDrawTextBlob(GrTextBlobCache* blobCache, blob->initThrowawayBlob(viewMatrix, x, y); blob->setRunPaintFlags(0, paint.skPaint().getFlags()); - if (this->canDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps)) { + if (CanDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps.supportsDistanceFieldText(), + fOptions)) { this->drawDFText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix, text, byteLength, x, y); } else { @@ -304,7 +300,8 @@ GrAtlasTextContext::makeDrawPosTextBlob(GrTextBlobCache* blobCache, blob->initThrowawayBlob(viewMatrix, offset.x(), offset.y()); blob->setRunPaintFlags(0, paint.skPaint().getFlags()); - if (this->canDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps)) { + if (CanDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps.supportsDistanceFieldText(), + fOptions)) { this->drawDFPosText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix, text, byteLength, pos, scalarsPerPosition, offset); } else { @@ -565,16 +562,26 @@ void GrAtlasTextContext::BmpAppendGlyph(GrAtlasTextBlob* blob, int runIndex, textRatio, true); } -bool GrAtlasTextContext::canDrawAsDistanceFields(const SkPaint& skPaint, const SkMatrix& viewMatrix, +void GrAtlasTextContext::SanitizeOptions(Options* options) { + if (options->fMaxDistanceFieldFontSize < 0.f) { + options->fMaxDistanceFieldFontSize = kDefaultMaxDistanceFieldFontSize; + } + if (options->fMinDistanceFieldFontSize < 0.f) { + options->fMinDistanceFieldFontSize = kDefaultMinDistanceFieldFontSize; + } +} + +bool GrAtlasTextContext::CanDrawAsDistanceFields(const SkPaint& skPaint, const SkMatrix& viewMatrix, const SkSurfaceProps& props, - const GrShaderCaps& caps) const { + bool contextSupportsDistanceFieldText, + const Options& options) { if (!viewMatrix.hasPerspective()) { SkScalar maxScale = viewMatrix.getMaxScale(); SkScalar scaledTextSize = maxScale * skPaint.getTextSize(); // Hinted text looks far better at small resolutions // Scaling up beyond 2x yields undesireable artifacts - if (scaledTextSize < fMinDistanceFieldFontSize || - scaledTextSize > fMaxDistanceFieldFontSize) { + if (scaledTextSize < options.fMinDistanceFieldFontSize || + scaledTextSize > options.fMaxDistanceFieldFontSize) { return false; } @@ -589,7 +596,7 @@ bool GrAtlasTextContext::canDrawAsDistanceFields(const SkPaint& skPaint, const S } // mask filters modify alpha, which doesn't translate well to distance - if (skPaint.getMaskFilter() || !caps.shaderDerivativeSupport()) { + if (skPaint.getMaskFilter() || !contextSupportsDistanceFieldText) { return false; } @@ -601,10 +608,12 @@ bool GrAtlasTextContext::canDrawAsDistanceFields(const SkPaint& skPaint, const S return true; } -void GrAtlasTextContext::initDistanceFieldPaint(GrAtlasTextBlob* blob, +void GrAtlasTextContext::InitDistanceFieldPaint(GrAtlasTextBlob* blob, SkPaint* skPaint, + const SkMatrix& viewMatrix, + const Options& options, SkScalar* textRatio, - const SkMatrix& viewMatrix) const { + SkScalerContextFlags* flags) { SkScalar textSize = skPaint->getTextSize(); SkScalar scaledTextSize = textSize; @@ -627,7 +636,7 @@ void GrAtlasTextContext::initDistanceFieldPaint(GrAtlasTextBlob* blob, SkScalar dfMaskScaleFloor; SkScalar dfMaskScaleCeil; if (scaledTextSize <= kSmallDFFontLimit) { - dfMaskScaleFloor = fMinDistanceFieldFontSize; + dfMaskScaleFloor = options.fMinDistanceFieldFontSize; dfMaskScaleCeil = kSmallDFFontLimit; *textRatio = textSize / kSmallDFFontSize; skPaint->setTextSize(SkIntToScalar(kSmallDFFontSize)); @@ -638,7 +647,7 @@ void GrAtlasTextContext::initDistanceFieldPaint(GrAtlasTextBlob* blob, skPaint->setTextSize(SkIntToScalar(kMediumDFFontSize)); } else { dfMaskScaleFloor = kMediumDFFontLimit; - dfMaskScaleCeil = fMaxDistanceFieldFontSize; + dfMaskScaleCeil = options.fMaxDistanceFieldFontSize; *textRatio = textSize / kLargeDFFontSize; skPaint->setTextSize(SkIntToScalar(kLargeDFFontSize)); } @@ -651,7 +660,10 @@ void GrAtlasTextContext::initDistanceFieldPaint(GrAtlasTextBlob* blob, // against these values to decide if we can reuse or not(ie, will a given scale change our mip // level) SkASSERT(dfMaskScaleFloor <= scaledTextSize && scaledTextSize <= dfMaskScaleCeil); - blob->setMinAndMaxScale(dfMaskScaleFloor / scaledTextSize, dfMaskScaleCeil / scaledTextSize); + if (blob) { + blob->setMinAndMaxScale(dfMaskScaleFloor / scaledTextSize, + dfMaskScaleCeil / scaledTextSize); + } skPaint->setAntiAlias(true); skPaint->setLCDRenderText(false); @@ -660,6 +672,10 @@ void GrAtlasTextContext::initDistanceFieldPaint(GrAtlasTextBlob* blob, skPaint->setSubpixelText(true); skPaint->setMaskFilter(GrSDFMaskFilter::Make()); + + // We apply the fake-gamma by altering the distance in the shader, so we ignore the + // passed-in scaler context flags. (It's only used when we fall-back to bitmap text). + *flags = SkScalerContextFlags::kNone; } void GrAtlasTextContext::drawDFText(GrAtlasTextBlob* blob, int runIndex, @@ -745,12 +761,13 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex, return; } - bool hasWCoord = viewMatrix.hasPerspective() || fDistanceFieldVerticesAlwaysHaveW; + bool hasWCoord = viewMatrix.hasPerspective() || fOptions.fDistanceFieldVerticesAlwaysHaveW; // Setup distance field paint and text ratio SkScalar textRatio; SkPaint dfPaint(paint); - this->initDistanceFieldPaint(blob, &dfPaint, &textRatio, viewMatrix); + SkScalerContextFlags flags; + InitDistanceFieldPaint(blob, &dfPaint, viewMatrix, fOptions, &textRatio, &flags); blob->setHasDistanceField(); blob->setSubRunHasDistanceFields(runIndex, paint.skPaint().isLCDRenderText(), paint.skPaint().isAntiAlias(), hasWCoord); @@ -760,10 +777,7 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex, sk_sp<GrTextStrike> currStrike; { - // We apply the fake-gamma by altering the distance in the shader, so we ignore the - // passed-in scaler context flags. (It's only used when we fall-back to bitmap text). - auto cache = blob->setupCache(runIndex, props, SkScalerContextFlags::kNone, dfPaint, - nullptr); + auto cache = blob->setupCache(runIndex, props, flags, dfPaint, nullptr); SkPaint::GlyphCacheProc glyphCacheProc = SkPaint::GetGlyphCacheProc(dfPaint.getTextEncoding(), true); diff --git a/src/gpu/text/GrAtlasTextContext.h b/src/gpu/text/GrAtlasTextContext.h index 1342ee7ac8..e2531b3d59 100644 --- a/src/gpu/text/GrAtlasTextContext.h +++ b/src/gpu/text/GrAtlasTextContext.h @@ -60,6 +60,18 @@ public: const SkMatrix& viewMatrix, const char* text, int x, int y); + static void SanitizeOptions(Options* options); + static bool CanDrawAsDistanceFields(const SkPaint& skPaint, const SkMatrix& viewMatrix, + const SkSurfaceProps& props, + bool contextSupportsDistanceFieldText, + const Options& options); + static void InitDistanceFieldPaint(GrAtlasTextBlob* blob, + SkPaint* skPaint, + const SkMatrix& viewMatrix, + const Options& options, + SkScalar* textRatio, + SkScalerContextFlags* flags); + private: GrAtlasTextContext(const Options& options); @@ -158,9 +170,6 @@ private: const SkPoint& offset); // functions for appending distance field text - bool canDrawAsDistanceFields(const SkPaint& skPaint, const SkMatrix& viewMatrix, - const SkSurfaceProps& props, const GrShaderCaps& caps) const; - void drawDFText(GrAtlasTextBlob* blob, int runIndex, GrGlyphCache*, const SkSurfaceProps&, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix, const char text[], size_t byteLength, SkScalar x, @@ -173,11 +182,6 @@ private: size_t byteLength, const SkScalar pos[], int scalarsPerPosition, const SkPoint& offset) const; - void initDistanceFieldPaint(GrAtlasTextBlob* blob, - SkPaint* skPaint, - SkScalar* textRatio, - const SkMatrix& viewMatrix) const; - static void BmpAppendGlyph(GrAtlasTextBlob*, int runIndex, GrGlyphCache*, sk_sp<GrTextStrike>*, const SkGlyph&, SkScalar sx, SkScalar sy, GrColor color, SkGlyphCache*, SkScalar textRatio); @@ -190,9 +194,7 @@ private: sk_sp<const GrDistanceFieldAdjustTable> fDistanceAdjustTable; - SkScalar fMinDistanceFieldFontSize; - SkScalar fMaxDistanceFieldFontSize; - bool fDistanceFieldVerticesAlwaysHaveW; + Options fOptions; #if GR_TEST_UTILS static const SkScalerContextFlags kTextBlobOpScalerContextFlags = diff --git a/tests/SkRemoteGlyphCacheTest.cpp b/tests/SkRemoteGlyphCacheTest.cpp index 811bf1be50..aa26fbeea8 100644 --- a/tests/SkRemoteGlyphCacheTest.cpp +++ b/tests/SkRemoteGlyphCacheTest.cpp @@ -15,6 +15,10 @@ #include "SkTypeface_remote.h" #include "Test.h" +#if SK_SUPPORT_GPU +#include "text/GrAtlasTextContext.h" +#endif + class DiscardableManager : public SkStrikeServer::DiscardableHandleManager, public SkStrikeClient::DiscardableHandleManager { public: @@ -79,14 +83,26 @@ sk_sp<SkTextBlob> buildTextBlob(sk_sp<SkTypeface> tf, int glyphCount) { } \ } -SkBitmap RasterBlob(sk_sp<SkTextBlob> blob, int width, int height, const SkPaint& paint) { - auto surface = SkSurface::MakeRasterN32Premul(width, height); +#if SK_SUPPORT_GPU +SkTextBlobCacheDiffCanvas::Settings MakeSettings(GrContext* context) { + SkTextBlobCacheDiffCanvas::Settings settings; + settings.fContextSupportsDistanceFieldText = context->supportsDistanceFieldText(); + return settings; +} + +SkBitmap RasterBlob(sk_sp<SkTextBlob> blob, int width, int height, const SkPaint& paint, + GrContext* context, const SkMatrix* matrix = nullptr) { + const SkImageInfo info = + SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType); + auto surface = SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, info); + if (matrix) surface->getCanvas()->concat(*matrix); surface->getCanvas()->drawTextBlob(blob.get(), 0u, 0u, paint); SkBitmap bitmap; bitmap.allocN32Pixels(width, height); surface->readPixels(bitmap, 0, 0); return bitmap; } +#endif DEF_TEST(SkRemoteGlyphCache_TypefaceSerialization, reporter) { sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); @@ -100,9 +116,13 @@ DEF_TEST(SkRemoteGlyphCache_TypefaceSerialization, reporter) { REPORTER_ASSERT(reporter, client_tf); REPORTER_ASSERT(reporter, SkTypefaceProxy::DownCast(client_tf.get())->remoteTypefaceID() == server_tf->uniqueID()); + + // Must unlock everything on termination, otherwise valgrind complains about memory leaks. + discardableManager->unlockAndDeleteAll(); } -DEF_TEST(SkRemoteGlyphCache_StrikeSerialization, reporter) { +#if SK_SUPPORT_GPU +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_StrikeSerialization, reporter, ctxInfo) { sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); SkStrikeServer server(discardableManager.get()); SkStrikeClient client(discardableManager); @@ -115,7 +135,8 @@ DEF_TEST(SkRemoteGlyphCache_StrikeSerialization, reporter) { int glyphCount = 10; auto serverBlob = buildTextBlob(serverTf, glyphCount); const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType); - SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, SkMatrix::I(), props, &server); + SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, SkMatrix::I(), props, &server, + MakeSettings(ctxInfo.grContext())); cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint); std::vector<uint8_t> serverStrikeData; @@ -127,10 +148,14 @@ DEF_TEST(SkRemoteGlyphCache_StrikeSerialization, reporter) { client.readStrikeData(serverStrikeData.data(), serverStrikeData.size())); auto clientBlob = buildTextBlob(clientTf, glyphCount); - SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint); - SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint); + SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, ctxInfo.grContext()); + SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, ctxInfo.grContext()); COMPARE_BLOBS(expected, actual, reporter); + + // Must unlock everything on termination, otherwise valgrind complains about memory leaks. + discardableManager->unlockAndDeleteAll(); } +#endif DEF_TEST(SkRemoteGlyphCache_StrikeLockingServer, reporter) { sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); @@ -161,6 +186,9 @@ DEF_TEST(SkRemoteGlyphCache_StrikeLockingServer, reporter) { cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint); REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u); REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 1u); + + // Must unlock everything on termination, otherwise valgrind complains about memory leaks. + discardableManager->unlockAndDeleteAll(); } DEF_TEST(SkRemoteGlyphCache_StrikeDeletionServer, reporter) { @@ -186,6 +214,9 @@ DEF_TEST(SkRemoteGlyphCache_StrikeDeletionServer, reporter) { discardableManager->unlockAndDeleteAll(); 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. + discardableManager->unlockAndDeleteAll(); } DEF_TEST(SkRemoteGlyphCache_StrikePinningClient, reporter) { @@ -222,6 +253,9 @@ DEF_TEST(SkRemoteGlyphCache_StrikePinningClient, reporter) { discardableManager->unlockAndDeleteAll(); SkGraphics::PurgeFontCache(); REPORTER_ASSERT(reporter, clientTf->unique()); + + // Must unlock everything on termination, otherwise valgrind complains about memory leaks. + discardableManager->unlockAndDeleteAll(); } DEF_TEST(SkRemoteGlyphCache_ClientMemoryAccounting, reporter) { @@ -248,9 +282,13 @@ DEF_TEST(SkRemoteGlyphCache_ClientMemoryAccounting, reporter) { REPORTER_ASSERT(reporter, client.readStrikeData(serverStrikeData.data(), serverStrikeData.size())); SkStrikeCache::Validate(); + + // Must unlock everything on termination, otherwise valgrind complains about memory leaks. + discardableManager->unlockAndDeleteAll(); } -DEF_TEST(SkRemoteGlyphCache_DrawTextAsPath, reporter) { +#if SK_SUPPORT_GPU +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsPath, reporter, ctxInfo) { sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); SkStrikeServer server(discardableManager.get()); SkStrikeClient client(discardableManager); @@ -266,7 +304,8 @@ DEF_TEST(SkRemoteGlyphCache_DrawTextAsPath, reporter) { int glyphCount = 10; auto serverBlob = buildTextBlob(serverTf, glyphCount); const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType); - SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, SkMatrix::I(), props, &server); + SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, SkMatrix::I(), props, &server, + MakeSettings(ctxInfo.grContext())); cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint); std::vector<uint8_t> serverStrikeData; @@ -278,8 +317,60 @@ DEF_TEST(SkRemoteGlyphCache_DrawTextAsPath, reporter) { client.readStrikeData(serverStrikeData.data(), serverStrikeData.size())); auto clientBlob = buildTextBlob(clientTf, glyphCount); - SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint); - SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint); + SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, ctxInfo.grContext()); + SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, ctxInfo.grContext()); COMPARE_BLOBS(expected, actual, reporter); SkStrikeCache::Validate(); + + // Must unlock everything on termination, otherwise valgrind complains about memory leaks. + discardableManager->unlockAndDeleteAll(); +} +#endif + +#if SK_SUPPORT_GPU +DEF_GPUTEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsDFT, reporter, ctxInfo) { + sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>(); + SkStrikeServer server(discardableManager.get()); + SkStrikeClient client(discardableManager); + SkPaint paint; + + // A perspective transform forces fallback to dft. + SkMatrix matrix = SkMatrix::I(); + matrix[SkMatrix::kMPersp0] = 0.5f; + REPORTER_ASSERT(reporter, matrix.hasPerspective()); + SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry); + GrAtlasTextContext::Options options; + GrAtlasTextContext::SanitizeOptions(&options); + REPORTER_ASSERT(reporter, GrAtlasTextContext::CanDrawAsDistanceFields( + paint, matrix, surfaceProps, true, options)); + + // Server. + auto serverTf = SkTypeface::MakeFromName("monospace", SkFontStyle()); + auto serverTfData = server.serializeTypeface(serverTf.get()); + + int glyphCount = 10; + auto serverBlob = buildTextBlob(serverTf, glyphCount); + const SkSurfaceProps props(SkSurfaceProps::kLegacyFontHost_InitType); + SkTextBlobCacheDiffCanvas cache_diff_canvas(10, 10, SkMatrix::I(), props, &server, + MakeSettings(ctxInfo.grContext())); + cache_diff_canvas.concat(matrix); + cache_diff_canvas.drawTextBlob(serverBlob.get(), 0, 0, paint); + + std::vector<uint8_t> serverStrikeData; + server.writeStrikeData(&serverStrikeData); + + // Client. + auto clientTf = client.deserializeTypeface(serverTfData->data(), serverTfData->size()); + REPORTER_ASSERT(reporter, + client.readStrikeData(serverStrikeData.data(), serverStrikeData.size())); + auto clientBlob = buildTextBlob(clientTf, glyphCount); + + SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, ctxInfo.grContext(), &matrix); + SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, ctxInfo.grContext(), &matrix); + COMPARE_BLOBS(expected, actual, reporter); + SkStrikeCache::Validate(); + + // Must unlock everything on termination, otherwise valgrind complains about memory leaks. + discardableManager->unlockAndDeleteAll(); } +#endif |