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