[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;