[graphite] Set up ContextOptions for text
Bug: skia:13118
Change-Id: I90aee8cff625ad822fa9d62f803a8badbe51925e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/552676
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/include/gpu/graphite/ContextOptions.h b/include/gpu/graphite/ContextOptions.h
index 0ec68b9..05eeed6 100644
--- a/include/gpu/graphite/ContextOptions.h
+++ b/include/gpu/graphite/ContextOptions.h
@@ -20,6 +20,57 @@
* via SkDebugf and assert.
*/
skgpu::ShaderErrorHandler* fShaderErrorHandler = nullptr;
+
+ /**
+ * The maximum size of cache textures used for Skia's Glyph cache.
+ */
+ size_t fGlyphCacheTextureMaximumBytes = 2048 * 1024 * 4;
+
+ /**
+ * Below this threshold size in device space distance field fonts won't be used. Distance field
+ * fonts don't support hinting which is more important at smaller sizes.
+ */
+ float fMinDistanceFieldFontSize = 18;
+
+ /**
+ * Above this threshold size in device space glyphs are drawn as individual paths.
+ */
+#if defined(SK_BUILD_FOR_ANDROID)
+ float fGlyphsAsPathsFontSize = 384;
+#elif defined(SK_BUILD_FOR_MAC)
+ float fGlyphsAsPathsFontSize = 256;
+#else
+ float fGlyphsAsPathsFontSize = 324;
+#endif
+
+ /**
+ * Can the glyph atlas use multiple textures. If allowed, the each texture's size is bound by
+ * fGlypheCacheTextureMaximumBytes.
+ */
+ bool fAllowMultipleGlyphCacheTextures = true;
+
+ /**
+ * If true, then add 1 pixel padding to all glyph masks in the atlas to support bi-lerp
+ * rendering of all glyphs. This must be set to true to use Slugs.
+ */
+ #if defined(SK_EXPERIMENTAL_SIMULATE_DRAWGLYPHRUNLIST_WITH_SLUG) || \
+ defined(SK_EXPERIMENTAL_SIMULATE_DRAWGLYPHRUNLIST_WITH_SLUG_SERIALIZE) || \
+ defined(SK_EXPERIMENTAL_SIMULATE_DRAWGLYPHRUNLIST_WITH_SLUG_STRIKE_SERIALIZE)
+ bool fSupportBilerpFromGlyphAtlas = true;
+ #else
+ bool fSupportBilerpFromGlyphAtlas = false;
+ #endif
+
+#if GRAPHITE_TEST_UTILS
+ /**
+ * Private options that are only meant for testing within Skia's tools.
+ */
+
+ /**
+ * Maximum width and height of internal texture atlases.
+ */
+ int fMaxTextureAtlasSize = 2048;
+#endif
};
} // namespace skgpu::graphite
diff --git a/src/gpu/ganesh/GrShaderCaps.h b/src/gpu/ganesh/GrShaderCaps.h
index b8100c0..e7b48ba 100644
--- a/src/gpu/ganesh/GrShaderCaps.h
+++ b/src/gpu/ganesh/GrShaderCaps.h
@@ -20,8 +20,6 @@
void dumpJSON(SkJSONWriter*) const;
- bool supportsDistanceFieldText() const { return fShaderDerivativeSupport; }
-
const char* noperspectiveInterpolationExtensionString() const {
SkASSERT(this->fNoPerspectiveInterpolationSupport);
return fNoPerspectiveInterpolationExtensionString;
diff --git a/src/gpu/graphite/Caps.cpp b/src/gpu/graphite/Caps.cpp
index c6be6bd..caf8cdc 100644
--- a/src/gpu/graphite/Caps.cpp
+++ b/src/gpu/graphite/Caps.cpp
@@ -25,6 +25,15 @@
} else {
fShaderErrorHandler = DefaultShaderErrorHandler();
}
+
+#if GRAPHITE_TEST_UTILS
+ fMaxTextureAtlasSize = options.fMaxTextureAtlasSize;
+#endif
+ fGlyphCacheTextureMaximumBytes = options.fGlyphCacheTextureMaximumBytes;
+ fMinDistanceFieldFontSize = options.fMinDistanceFieldFontSize;
+ fGlyphsAsPathsFontSize = options.fGlyphsAsPathsFontSize;
+ fAllowMultipleGlyphCacheTextures = options.fAllowMultipleGlyphCacheTextures;
+ fSupportBilerpFromGlyphAtlas = options.fSupportBilerpFromGlyphAtlas;
}
bool Caps::isTexturable(const TextureInfo& info) const {
diff --git a/src/gpu/graphite/Caps.h b/src/gpu/graphite/Caps.h
index b6557fd..68491e2 100644
--- a/src/gpu/graphite/Caps.h
+++ b/src/gpu/graphite/Caps.h
@@ -81,6 +81,14 @@
skgpu::ShaderErrorHandler* shaderErrorHandler() const { return fShaderErrorHandler; }
+ float minDistanceFieldFontSize() const { return fMinDistanceFieldFontSize; }
+ float glyphsAsPathsFontSize() const { return fGlyphsAsPathsFontSize; }
+
+ size_t glyphCacheTextureMaximumBytes() const { return fGlyphCacheTextureMaximumBytes; }
+
+ bool allowMultipleGlyphCacheTextures() const { return fAllowMultipleGlyphCacheTextures; }
+ bool supportBilerpFromGlyphAtlas() const { return fSupportBilerpFromGlyphAtlas; }
+
protected:
Caps();
@@ -123,6 +131,17 @@
*/
ShaderErrorHandler* fShaderErrorHandler = nullptr;
+#if GRAPHITE_TEST_UTILS
+ int fMaxTextureAtlasSize = 2048;
+#endif
+ size_t fGlyphCacheTextureMaximumBytes = 2048 * 1024 * 4;
+
+ float fMinDistanceFieldFontSize = 18;
+ float fGlyphsAsPathsFontSize = 324;
+
+ bool fAllowMultipleGlyphCacheTextures = true;
+ bool fSupportBilerpFromGlyphAtlas = false;
+
private:
virtual bool onIsTexturable(const TextureInfo&) const = 0;
virtual const ColorTypeInfo* getColorTypeInfo(SkColorType, const TextureInfo&) const = 0;
diff --git a/src/gpu/graphite/Device.cpp b/src/gpu/graphite/Device.cpp
index 321fadf..daa26f4 100644
--- a/src/gpu/graphite/Device.cpp
+++ b/src/gpu/graphite/Device.cpp
@@ -210,8 +210,7 @@
, fDisjointStencilSet(std::make_unique<IntersectionTreeSet>())
, fCachedLocalToDevice(SkM44())
, fCurrentDepth(DrawOrder::kClearDepth)
- // TODO: set this up based on ContextOptions
- , fSDFTControl(true, false, 18, 324, true)
+ , fSDFTControl(recorder->priv().getSDFTControl(false))
, fDrawsOverlap(false) {
SkASSERT(SkToBool(fDC) && SkToBool(fRecorder));
fRecorder->registerDevice(this);
diff --git a/src/gpu/graphite/Recorder.cpp b/src/gpu/graphite/Recorder.cpp
index 1064e6d..52c580e 100644
--- a/src/gpu/graphite/Recorder.cpp
+++ b/src/gpu/graphite/Recorder.cpp
@@ -44,10 +44,7 @@
, fUniformDataCache(new UniformDataCache)
, fTextureDataCache(new TextureDataCache)
, fRecorderID(next_id())
- // TODO: add config to control maxTextureBytes
- , fAtlasManager(std::make_unique<AtlasManager>(this, 2048*2048,
- DrawAtlas::AllowMultitexturing::kYes,
- false))
+ , fAtlasManager(std::make_unique<AtlasManager>(this))
, fTokenTracker(std::make_unique<TokenTracker>())
, fStrikeCache(std::make_unique<sktext::gpu::StrikeCache>())
, fTextBlobCache(std::make_unique<sktext::gpu::TextBlobRedrawCoordinator>(fRecorderID)) {
diff --git a/src/gpu/graphite/RecorderPriv.cpp b/src/gpu/graphite/RecorderPriv.cpp
index 9639af6..4ce8bfc 100644
--- a/src/gpu/graphite/RecorderPriv.cpp
+++ b/src/gpu/graphite/RecorderPriv.cpp
@@ -11,6 +11,7 @@
#include "src/gpu/graphite/Device.h"
#include "src/gpu/graphite/Gpu.h"
#include "src/gpu/graphite/TaskGraph.h"
+#include "src/sksl/SkSLUtil.h"
namespace skgpu::graphite {
@@ -60,6 +61,15 @@
return fRecorder->fTextBlobCache.get();
}
+sktext::gpu::SDFTControl RecorderPriv::getSDFTControl(bool useSDFTForSmallText) const {
+ return sktext::gpu::SDFTControl{
+ this->caps()->shaderCaps()->supportsDistanceFieldText(),
+ useSDFTForSmallText,
+ this->caps()->minDistanceFieldFontSize(),
+ this->caps()->glyphsAsPathsFontSize(),
+ true /*forcePaths*/};
+}
+
void RecorderPriv::add(sk_sp<Task> task) {
ASSERT_SINGLE_OWNER
fRecorder->fGraph->add(std::move(task));
diff --git a/src/gpu/graphite/RecorderPriv.h b/src/gpu/graphite/RecorderPriv.h
index 2bc8c73..e8c4a07 100644
--- a/src/gpu/graphite/RecorderPriv.h
+++ b/src/gpu/graphite/RecorderPriv.h
@@ -9,6 +9,7 @@
#define skgpu_graphite_RecorderPriv_DEFINED
#include "include/gpu/graphite/Recorder.h"
+#include "src/text/gpu/SDFTControl.h"
namespace skgpu::graphite {
@@ -25,6 +26,7 @@
TokenTracker* tokenTracker();
sktext::gpu::StrikeCache* strikeCache();
sktext::gpu::TextBlobRedrawCoordinator* textBlobCache();
+ sktext::gpu::SDFTControl getSDFTControl(bool useSDFTForSmallText) const;
const Caps* caps() const;
sk_sp<const Caps> refCaps() const;
diff --git a/src/gpu/graphite/text/AtlasManager.cpp b/src/gpu/graphite/text/AtlasManager.cpp
index 1a20a9a..879a102 100644
--- a/src/gpu/graphite/text/AtlasManager.cpp
+++ b/src/gpu/graphite/text/AtlasManager.cpp
@@ -15,6 +15,7 @@
#include "src/gpu/graphite/DrawAtlas.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/TextureProxy.h"
+#include "src/sksl/SkSLUtil.h"
#include "src/text/gpu/Glyph.h"
#include "src/text/gpu/GlyphVector.h"
#include "src/text/gpu/StrikeCache.h"
@@ -23,14 +24,20 @@
namespace skgpu::graphite {
-AtlasManager::AtlasManager(Recorder* recorder,
- size_t maxTextureBytes,
- DrawAtlas::AllowMultitexturing allowMultitexturing,
- bool supportBilerpAtlas)
+AtlasManager::AtlasManager(Recorder* recorder)
: fRecorder(recorder)
- , fAllowMultitexturing{allowMultitexturing}
- , fSupportBilerpAtlas{supportBilerpAtlas}
- , fAtlasConfig{recorder->priv().caps()->maxTextureSize(), maxTextureBytes} { }
+ , fSupportBilerpAtlas{recorder->priv().caps()->supportBilerpFromGlyphAtlas()}
+ , fAtlasConfig{recorder->priv().caps()->maxTextureSize(),
+ recorder->priv().caps()->glyphCacheTextureMaximumBytes()} {
+ if (!recorder->priv().caps()->allowMultipleGlyphCacheTextures() ||
+ // multitexturing supported only if range can represent the index + texcoords fully
+ !(recorder->priv().caps()->shaderCaps()->fFloatIs32Bits ||
+ recorder->priv().caps()->shaderCaps()->fIntegerSupport)) {
+ fAllowMultitexturing = DrawAtlas::AllowMultitexturing::kNo;
+ } else {
+ fAllowMultitexturing = DrawAtlas::AllowMultitexturing::kYes;
+ }
+}
AtlasManager::~AtlasManager() = default;
diff --git a/src/gpu/graphite/text/AtlasManager.h b/src/gpu/graphite/text/AtlasManager.h
index 097c772..175cfe6 100644
--- a/src/gpu/graphite/text/AtlasManager.h
+++ b/src/gpu/graphite/text/AtlasManager.h
@@ -28,10 +28,7 @@
*/
class AtlasManager : public AtlasGenerationCounter {
public:
- AtlasManager(Recorder*,
- size_t maxTextureBytes,
- DrawAtlas::AllowMultitexturing,
- bool supportBilerpAtlas);
+ AtlasManager(Recorder*);
~AtlasManager();
// Used to get proxies for test rendering
diff --git a/src/sksl/SkSLUtil.h b/src/sksl/SkSLUtil.h
index efb7eeb..4ff306d 100644
--- a/src/sksl/SkSLUtil.h
+++ b/src/sksl/SkSLUtil.h
@@ -79,6 +79,8 @@
return SkSL::Version::k100;
}
+ bool supportsDistanceFieldText() const { return fShaderDerivativeSupport; }
+
SkSL::GLSLGeneration fGLSLGeneration = SkSL::GLSLGeneration::k330;
bool fShaderDerivativeSupport = false;