/src/skia/src/gpu/graphite/render/BitmapTextRenderStep.cpp
Line | Count | Source (jump to first uncovered line) |
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/gpu/graphite/Recorder.h" |
12 | | #include "src/gpu/graphite/AtlasProvider.h" |
13 | | #include "src/gpu/graphite/ContextUtils.h" |
14 | | #include "src/gpu/graphite/DrawParams.h" |
15 | | #include "src/gpu/graphite/DrawWriter.h" |
16 | | #include "src/gpu/graphite/PipelineData.h" |
17 | | #include "src/gpu/graphite/RecorderPriv.h" |
18 | | #include "src/gpu/graphite/render/CommonDepthStencilSettings.h" |
19 | | #include "src/gpu/graphite/text/TextAtlasManager.h" |
20 | | #include "src/sksl/SkSLString.h" |
21 | | #include "src/text/gpu/SubRunContainer.h" |
22 | | #include "src/text/gpu/VertexFiller.h" |
23 | | |
24 | | using AtlasSubRun = sktext::gpu::AtlasSubRun; |
25 | | |
26 | | namespace skgpu::graphite { |
27 | | |
28 | | namespace { |
29 | | |
30 | | // We are expecting to sample from up to 4 textures |
31 | | constexpr int kNumTextAtlasTextures = 4; |
32 | | |
33 | | } // namespace |
34 | | |
35 | | BitmapTextRenderStep::BitmapTextRenderStep(bool isLCD) |
36 | | : RenderStep("BitmapTextRenderStep", |
37 | | "", |
38 | | isLCD ? Flags::kPerformsShading | Flags::kHasTextures | Flags::kEmitsCoverage | |
39 | | Flags::kLCDCoverage |
40 | | : Flags::kPerformsShading | Flags::kHasTextures | Flags::kEmitsCoverage, |
41 | | /*uniforms=*/{{"subRunDeviceMatrix", SkSLType::kFloat4x4}, |
42 | | {"deviceToLocal" , SkSLType::kFloat4x4}, |
43 | | {"atlasSizeInv" , SkSLType::kFloat2}}, |
44 | | PrimitiveType::kTriangleStrip, |
45 | | kDirectDepthGEqualPass, |
46 | | /*vertexAttrs=*/ {}, |
47 | | /*instanceAttrs=*/ |
48 | | {{"size", VertexAttribType::kUShort2, SkSLType::kUShort2}, |
49 | | {"uvPos", VertexAttribType::kUShort2, SkSLType::kUShort2}, |
50 | | {"xyPos", VertexAttribType::kFloat2, SkSLType::kFloat2}, |
51 | | {"indexAndFlags", VertexAttribType::kUShort2, SkSLType::kUShort2}, |
52 | | {"strikeToSourceScale", VertexAttribType::kFloat, SkSLType::kFloat}, |
53 | | {"depth", VertexAttribType::kFloat, SkSLType::kFloat}, |
54 | | {"ssboIndices", VertexAttribType::kUShort2, SkSLType::kUShort2}}, |
55 | | /*varyings=*/ |
56 | | {{"textureCoords", SkSLType::kFloat2}, |
57 | | {"texIndex", SkSLType::kHalf}, |
58 | 0 | {"maskFormat", SkSLType::kHalf}}) {} |
59 | | |
60 | 0 | BitmapTextRenderStep::~BitmapTextRenderStep() {} |
61 | | |
62 | 0 | std::string BitmapTextRenderStep::vertexSkSL() const { |
63 | | // Returns the body of a vertex function, which must define a float4 devPosition variable and |
64 | | // must write to an already-defined float2 stepLocalCoords variable. |
65 | 0 | return "texIndex = half(indexAndFlags.x);" |
66 | 0 | "maskFormat = half(indexAndFlags.y);" |
67 | 0 | "float2 unormTexCoords;" |
68 | 0 | "float4 devPosition = text_vertex_fn(float2(sk_VertexID >> 1, sk_VertexID & 1), " |
69 | 0 | "subRunDeviceMatrix, " |
70 | 0 | "deviceToLocal, " |
71 | 0 | "atlasSizeInv, " |
72 | 0 | "float2(size), " |
73 | 0 | "float2(uvPos), " |
74 | 0 | "xyPos, " |
75 | 0 | "strikeToSourceScale, " |
76 | 0 | "depth, " |
77 | 0 | "textureCoords, " |
78 | 0 | "unormTexCoords, " |
79 | 0 | "stepLocalCoords);"; |
80 | 0 | } |
81 | | |
82 | | std::string BitmapTextRenderStep::texturesAndSamplersSkSL( |
83 | 0 | const ResourceBindingRequirements& bindingReqs, int* nextBindingIndex) const { |
84 | 0 | std::string result; |
85 | |
|
86 | 0 | for (unsigned int i = 0; i < kNumTextAtlasTextures; ++i) { |
87 | 0 | result += EmitSamplerLayout(bindingReqs, nextBindingIndex); |
88 | 0 | SkSL::String::appendf(&result, " sampler2D text_atlas_%u;\n", i); |
89 | 0 | } |
90 | |
|
91 | 0 | return result; |
92 | 0 | } |
93 | | |
94 | 0 | const char* BitmapTextRenderStep::fragmentCoverageSkSL() const { |
95 | | // The returned SkSL must write its coverage into a 'half4 outputCoverage' variable (defined in |
96 | | // the calling code) with the actual coverage splatted out into all four channels. |
97 | 0 | static_assert(kNumTextAtlasTextures == 4); |
98 | 0 | return "outputCoverage = bitmap_text_coverage_fn(sample_indexed_atlas(textureCoords, " |
99 | 0 | "int(texIndex), " |
100 | 0 | "text_atlas_0, " |
101 | 0 | "text_atlas_1, " |
102 | 0 | "text_atlas_2, " |
103 | 0 | "text_atlas_3), " |
104 | 0 | "int(maskFormat));"; |
105 | 0 | } |
106 | | |
107 | | void BitmapTextRenderStep::writeVertices(DrawWriter* dw, |
108 | | const DrawParams& params, |
109 | 0 | skvx::ushort2 ssboIndices) const { |
110 | 0 | const SubRunData& subRunData = params.geometry().subRunData(); |
111 | |
|
112 | 0 | subRunData.subRun()->vertexFiller().fillInstanceData(dw, |
113 | 0 | subRunData.startGlyphIndex(), |
114 | 0 | subRunData.glyphCount(), |
115 | 0 | subRunData.subRun()->instanceFlags(), |
116 | 0 | ssboIndices, |
117 | 0 | subRunData.subRun()->glyphs(), |
118 | 0 | params.order().depthAsFloat()); |
119 | 0 | } |
120 | | |
121 | | void BitmapTextRenderStep::writeUniformsAndTextures(const DrawParams& params, |
122 | 0 | PipelineDataGatherer* gatherer) const { |
123 | 0 | SkDEBUGCODE(UniformExpectationsValidator uev(gatherer, this->uniforms());) |
124 | |
|
125 | 0 | const SubRunData& subRunData = params.geometry().subRunData(); |
126 | 0 | unsigned int numProxies; |
127 | 0 | Recorder* recorder = subRunData.recorder(); |
128 | 0 | const sk_sp<TextureProxy>* proxies = |
129 | 0 | recorder->priv().atlasProvider()->textAtlasManager()->getProxies( |
130 | 0 | subRunData.subRun()->maskFormat(), &numProxies); |
131 | 0 | SkASSERT(proxies && numProxies > 0); |
132 | | |
133 | | // write uniforms |
134 | 0 | gatherer->write(params.transform().matrix()); // subRunDeviceMatrix |
135 | 0 | gatherer->write(subRunData.deviceToLocal()); |
136 | 0 | SkV2 atlasDimensionsInverse = {1.f/proxies[0]->dimensions().width(), |
137 | 0 | 1.f/proxies[0]->dimensions().height()}; |
138 | 0 | gatherer->write(atlasDimensionsInverse); |
139 | | |
140 | | // write textures and samplers |
141 | 0 | const SkSamplingOptions kSamplingOptions(SkFilterMode::kNearest); |
142 | 0 | constexpr SkTileMode kTileModes[2] = { SkTileMode::kClamp, SkTileMode::kClamp }; |
143 | 0 | for (unsigned int i = 0; i < numProxies; ++i) { |
144 | 0 | gatherer->add(kSamplingOptions, kTileModes, proxies[i]); |
145 | 0 | } |
146 | | // If the atlas has less than 4 active proxies we still need to set up samplers for the shader. |
147 | 0 | for (unsigned int i = numProxies; i < kNumTextAtlasTextures; ++i) { |
148 | 0 | gatherer->add(kSamplingOptions, kTileModes, proxies[0]); |
149 | 0 | } |
150 | 0 | } Unexecuted instantiation: skgpu::graphite::BitmapTextRenderStep::writeUniformsAndTextures(skgpu::graphite::DrawParams const&, skgpu::graphite::PipelineDataGatherer*) const Unexecuted instantiation: skgpu::graphite::BitmapTextRenderStep::writeUniformsAndTextures(skgpu::graphite::DrawParams const&, skgpu::graphite::PipelineDataGatherer*) const |
151 | | |
152 | | } // namespace skgpu::graphite |