aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/gpu/GrContext.h2
-rw-r--r--src/core/SkRemoteGlyphCache.cpp69
-rw-r--r--src/core/SkRemoteGlyphCache.h17
-rw-r--r--src/gpu/GrContext.cpp4
-rw-r--r--src/gpu/GrShaderCaps.h2
-rw-r--r--src/gpu/text/GrAtlasTextContext.cpp68
-rw-r--r--src/gpu/text/GrAtlasTextContext.h24
-rw-r--r--tests/SkRemoteGlyphCacheTest.cpp111
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