xref: /aosp_15_r20/external/skia/src/gpu/graphite/render/BitmapTextRenderStep.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1  /*
2   * Copyright 2022 Google LLC
3   *
4   * Use of this source code is governed by a BSD-style license that can be
5   * found in the LICENSE file.
6   */
7  
8  #include "src/gpu/graphite/render/BitmapTextRenderStep.h"
9  
10  #include "include/core/SkM44.h"
11  #include "include/core/SkRefCnt.h"
12  #include "include/core/SkSamplingOptions.h"
13  #include "include/core/SkSize.h"
14  #include "include/core/SkTileMode.h"
15  #include "include/gpu/graphite/Recorder.h"
16  #include "include/private/base/SkAssert.h"
17  #include "include/private/base/SkDebug.h"
18  #include "src/core/SkSLTypeShared.h"
19  #include "src/gpu/AtlasTypes.h"
20  #include "src/gpu/graphite/AtlasProvider.h"
21  #include "src/gpu/graphite/Attribute.h"
22  #include "src/gpu/graphite/ContextUtils.h"
23  #include "src/gpu/graphite/DrawOrder.h"
24  #include "src/gpu/graphite/DrawParams.h"
25  #include "src/gpu/graphite/DrawTypes.h"
26  #include "src/gpu/graphite/PipelineData.h"
27  #include "src/gpu/graphite/RecorderPriv.h"
28  #include "src/gpu/graphite/TextureProxy.h"
29  #include "src/gpu/graphite/geom/Geometry.h"
30  #include "src/gpu/graphite/geom/SubRunData.h"
31  #include "src/gpu/graphite/geom/Transform_graphite.h"
32  #include "src/gpu/graphite/render/CommonDepthStencilSettings.h"
33  #include "src/gpu/graphite/text/TextAtlasManager.h"
34  #include "src/sksl/SkSLString.h"
35  #include "src/text/gpu/SubRunContainer.h"
36  #include "src/text/gpu/VertexFiller.h"
37  
38  #include <string_view>
39  
40  using AtlasSubRun = sktext::gpu::AtlasSubRun;
41  
42  namespace skgpu::graphite {
43  
44  namespace {
45  
46  // We are expecting to sample from up to 4 textures
47  constexpr int kNumTextAtlasTextures = 4;
48  
variant_name(skgpu::MaskFormat variant)49  std::string variant_name(skgpu::MaskFormat variant) {
50      switch (variant) {
51          case skgpu::MaskFormat::kA8:
52              return "mask";
53          case skgpu::MaskFormat::kA565:
54              return "LCD";
55          case skgpu::MaskFormat::kARGB:
56              return "color";
57          default:
58              SkUNREACHABLE;
59      }
60  }
61  
62  }  // namespace
63  
BitmapTextRenderStep(skgpu::MaskFormat variant)64  BitmapTextRenderStep::BitmapTextRenderStep(skgpu::MaskFormat variant)
65          : RenderStep("BitmapTextRenderStep",
66                       variant_name(variant),
67                       Flags(variant),
68                       /*uniforms=*/{{"subRunDeviceMatrix", SkSLType::kFloat4x4},
69                                     {"deviceToLocal"     , SkSLType::kFloat4x4},
70                                     {"atlasSizeInv"      , SkSLType::kFloat2}},
71                       PrimitiveType::kTriangleStrip,
72                       kDirectDepthGEqualPass,
73                       /*vertexAttrs=*/ {},
74                       /*instanceAttrs=*/
75                       {{"size", VertexAttribType::kUShort2, SkSLType::kUShort2},
76                        {"uvPos", VertexAttribType::kUShort2, SkSLType::kUShort2},
77                        {"xyPos", VertexAttribType::kFloat2, SkSLType::kFloat2},
78                        {"indexAndFlags", VertexAttribType::kUShort2, SkSLType::kUShort2},
79                        {"strikeToSourceScale", VertexAttribType::kFloat, SkSLType::kFloat},
80                        {"depth", VertexAttribType::kFloat, SkSLType::kFloat},
81                        {"ssboIndices", VertexAttribType::kUInt2, SkSLType::kUInt2}},
82                       /*varyings=*/
83                       {{"textureCoords", SkSLType::kFloat2},
84                        {"texIndex", SkSLType::kHalf},
85                        {"maskFormat", SkSLType::kHalf}}) {}
86  
~BitmapTextRenderStep()87  BitmapTextRenderStep::~BitmapTextRenderStep() {}
88  
Flags(skgpu::MaskFormat variant)89  SkEnumBitMask<RenderStep::Flags> BitmapTextRenderStep::Flags(skgpu::MaskFormat variant) {
90      switch (variant) {
91          case skgpu::MaskFormat::kA8:
92              return Flags::kPerformsShading | Flags::kHasTextures | Flags::kEmitsCoverage;
93          case skgpu::MaskFormat::kA565:
94              return Flags::kPerformsShading | Flags::kHasTextures | Flags::kEmitsCoverage |
95                     Flags::kLCDCoverage;
96          case skgpu::MaskFormat::kARGB:
97              return Flags::kPerformsShading | Flags::kHasTextures | Flags::kEmitsPrimitiveColor;
98          default:
99              SkUNREACHABLE;
100      }
101  }
102  
vertexSkSL() const103  std::string BitmapTextRenderStep::vertexSkSL() const {
104      // Returns the body of a vertex function, which must define a float4 devPosition variable and
105      // must write to an already-defined float2 stepLocalCoords variable.
106      return "texIndex = half(indexAndFlags.x);"
107             "maskFormat = half(indexAndFlags.y);"
108             "float2 unormTexCoords;"
109             "float4 devPosition = text_vertex_fn(float2(sk_VertexID >> 1, sk_VertexID & 1), "
110                                                 "subRunDeviceMatrix, "
111                                                 "deviceToLocal, "
112                                                 "atlasSizeInv, "
113                                                 "float2(size), "
114                                                 "float2(uvPos), "
115                                                 "xyPos, "
116                                                 "strikeToSourceScale, "
117                                                 "depth, "
118                                                 "textureCoords, "
119                                                 "unormTexCoords, "
120                                                 "stepLocalCoords);";
121  }
122  
texturesAndSamplersSkSL(const ResourceBindingRequirements & bindingReqs,int * nextBindingIndex) const123  std::string BitmapTextRenderStep::texturesAndSamplersSkSL(
124          const ResourceBindingRequirements& bindingReqs, int* nextBindingIndex) const {
125      std::string result;
126  
127      for (unsigned int i = 0; i < kNumTextAtlasTextures; ++i) {
128          result += EmitSamplerLayout(bindingReqs, nextBindingIndex);
129          SkSL::String::appendf(&result, " sampler2D text_atlas_%u;\n", i);
130      }
131  
132      return result;
133  }
134  
135  
fragmentColorSkSL() const136  const char* BitmapTextRenderStep::fragmentColorSkSL() const {
137      // The returned SkSL must write its color into a 'half4 primitiveColor' variable
138      // (defined in the calling code).
139      static_assert(kNumTextAtlasTextures == 4);
140      return "primitiveColor = sample_indexed_atlas(textureCoords, "
141                                                   "int(texIndex), "
142                                                   "text_atlas_0, "
143                                                   "text_atlas_1, "
144                                                   "text_atlas_2, "
145                                                   "text_atlas_3);";
146  }
147  
fragmentCoverageSkSL() const148  const char* BitmapTextRenderStep::fragmentCoverageSkSL() const {
149      // The returned SkSL must write its coverage into a 'half4 outputCoverage' variable (defined in
150      // the calling code) with the actual coverage splatted out into all four channels.
151      static_assert(kNumTextAtlasTextures == 4);
152      return "outputCoverage = bitmap_text_coverage_fn(sample_indexed_atlas(textureCoords, "
153                                                                           "int(texIndex), "
154                                                                           "text_atlas_0, "
155                                                                           "text_atlas_1, "
156                                                                           "text_atlas_2, "
157                                                                           "text_atlas_3), "
158                                                      "int(maskFormat));";
159  }
160  
writeVertices(DrawWriter * dw,const DrawParams & params,skvx::uint2 ssboIndices) const161  void BitmapTextRenderStep::writeVertices(DrawWriter* dw,
162                                           const DrawParams& params,
163                                           skvx::uint2 ssboIndices) const {
164      const SubRunData& subRunData = params.geometry().subRunData();
165  
166      subRunData.subRun()->vertexFiller().fillInstanceData(dw,
167                                                           subRunData.startGlyphIndex(),
168                                                           subRunData.glyphCount(),
169                                                           subRunData.subRun()->instanceFlags(),
170                                                           ssboIndices,
171                                                           subRunData.subRun()->glyphs(),
172                                                           params.order().depthAsFloat());
173  }
174  
writeUniformsAndTextures(const DrawParams & params,PipelineDataGatherer * gatherer) const175  void BitmapTextRenderStep::writeUniformsAndTextures(const DrawParams& params,
176                                                      PipelineDataGatherer* gatherer) const {
177      SkDEBUGCODE(UniformExpectationsValidator uev(gatherer, this->uniforms());)
178  
179      const SubRunData& subRunData = params.geometry().subRunData();
180      unsigned int numProxies;
181      Recorder* recorder = subRunData.recorder();
182      const sk_sp<TextureProxy>* proxies =
183              recorder->priv().atlasProvider()->textAtlasManager()->getProxies(
184                      subRunData.subRun()->maskFormat(), &numProxies);
185      SkASSERT(proxies && numProxies > 0);
186  
187      // write uniforms
188      gatherer->write(params.transform().matrix());  // subRunDeviceMatrix
189      gatherer->write(subRunData.deviceToLocal());
190      SkV2 atlasDimensionsInverse = {1.f/proxies[0]->dimensions().width(),
191                                     1.f/proxies[0]->dimensions().height()};
192      gatherer->write(atlasDimensionsInverse);
193  
194      // write textures and samplers
195      for (unsigned int i = 0; i < numProxies; ++i) {
196          gatherer->add(proxies[i], {SkFilterMode::kNearest, SkTileMode::kClamp});
197      }
198      // If the atlas has less than 4 active proxies we still need to set up samplers for the shader.
199      for (unsigned int i = numProxies; i < kNumTextAtlasTextures; ++i) {
200          gatherer->add(proxies[0], {SkFilterMode::kNearest, SkTileMode::kClamp});
201      }
202  }
203  
204  }  // namespace skgpu::graphite
205