Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SDFTextRenderStep.cpp
Go to the documentation of this file.
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
9
10#include "include/core/SkM44.h"
20#include "src/sksl/SkSLString.h"
23
24namespace skgpu::graphite {
25
26namespace {
27
28// We are expecting to sample from up to 4 textures
29constexpr int kNumSDFAtlasTextures = 4;
30
31} // namespace
32
34 : RenderStep("SDFTextRenderStep",
35 isLCD ? "565" : "A8",
36 isLCD ? Flags::kPerformsShading | Flags::kHasTextures | Flags::kEmitsCoverage |
37 Flags::kLCDCoverage
38 : Flags::kPerformsShading | Flags::kHasTextures | Flags::kEmitsCoverage,
39 /*uniforms=*/{{"subRunDeviceMatrix", SkSLType::kFloat4x4},
40 {"deviceToLocal", SkSLType::kFloat4x4},
41 {"atlasSizeInv", SkSLType::kFloat2},
42 {"distAdjust", SkSLType::kFloat}},
45 /*vertexAttrs=*/ {},
46 /*instanceAttrs=*/
51 {"strikeToSourceScale", VertexAttribType::kFloat, SkSLType::kFloat},
54 /*varyings=*/
55 {{"unormTexCoords", SkSLType::kFloat2},
56 {"textureCoords", SkSLType::kFloat2},
57 {"texIndex", SkSLType::kFloat}}) {
58 // TODO: store if it's A8 and adjust shader
59}
60
62
63std::string SDFTextRenderStep::vertexSkSL() const {
64 // Returns the body of a vertex function, which must define a float4 devPosition variable and
65 // must write to an already-defined float2 stepLocalCoords variable.
66 return "texIndex = half(indexAndFlags.x);"
67 "float4 devPosition = text_vertex_fn(float2(sk_VertexID >> 1, sk_VertexID & 1), "
68 "subRunDeviceMatrix, "
69 "deviceToLocal, "
70 "atlasSizeInv, "
71 "float2(size), "
72 "float2(uvPos), "
73 "xyPos, "
74 "strikeToSourceScale, "
75 "depth, "
76 "textureCoords, "
77 "unormTexCoords, "
78 "stepLocalCoords);";
79}
80
82 const ResourceBindingRequirements& bindingReqs, int* nextBindingIndex) const {
83 std::string result;
84
85 for (unsigned int i = 0; i < kNumSDFAtlasTextures; ++i) {
86 result += EmitSamplerLayout(bindingReqs, nextBindingIndex);
87 SkSL::String::appendf(&result, " sampler2D sdf_atlas_%u;\n", i);
88 }
89
90 return result;
91}
92
94 // The returned SkSL must write its coverage into a 'half4 outputCoverage' variable (defined in
95 // the calling code) with the actual coverage splatted out into all four channels.
96
97 // TODO: To minimize the number of shaders generated this is the full affine shader.
98 // For best performance it may be worth creating the uniform scale shader as well,
99 // as that's the most common case.
100 // TODO: Need to add 565 support.
101 // TODO: Need aliased and possibly sRGB support.
102 static_assert(kNumSDFAtlasTextures == 4);
103 return "outputCoverage = sdf_text_coverage_fn(sample_indexed_atlas(textureCoords, "
104 "int(texIndex), "
105 "sdf_atlas_0, "
106 "sdf_atlas_1, "
107 "sdf_atlas_2, "
108 "sdf_atlas_3).r, "
109 "half(distAdjust), "
110 "unormTexCoords);";
111}
112
114 const DrawParams& params,
115 skvx::ushort2 ssboIndices) const {
116 const SubRunData& subRunData = params.geometry().subRunData();
117 subRunData.subRun()->vertexFiller().fillInstanceData(dw,
118 subRunData.startGlyphIndex(),
119 subRunData.glyphCount(),
120 subRunData.subRun()->instanceFlags(),
121 ssboIndices,
122 subRunData.subRun()->glyphs(),
123 params.order().depthAsFloat());
124}
125
127 PipelineDataGatherer* gatherer) const {
128 SkDEBUGCODE(UniformExpectationsValidator uev(gatherer, this->uniforms());)
129
130 const SubRunData& subRunData = params.geometry().subRunData();
131 unsigned int numProxies;
132 Recorder* recorder = subRunData.recorder();
133 const sk_sp<TextureProxy>* proxies =
135 subRunData.subRun()->maskFormat(), &numProxies);
136 SkASSERT(proxies && numProxies > 0);
137
138 // write uniforms
139 gatherer->write(params.transform().matrix()); // subRunDeviceMatrix
140 gatherer->write(subRunData.deviceToLocal());
141 SkV2 atlasDimensionsInverse = {1.f/proxies[0]->dimensions().width(),
142 1.f/proxies[0]->dimensions().height()};
143 gatherer->write(atlasDimensionsInverse);
144
145 // TODO: get this from DistanceFieldAdjustTable and luminance color (set in SubRunData?)
146 float gammaCorrection = 0.f;
147 gatherer->write(gammaCorrection);
148
149 // write textures and samplers
150 const SkSamplingOptions kSamplingOptions(SkFilterMode::kLinear);
151 constexpr SkTileMode kTileModes[2] = { SkTileMode::kClamp, SkTileMode::kClamp };
152 for (unsigned int i = 0; i < numProxies; ++i) {
153 gatherer->add(kSamplingOptions, kTileModes, proxies[i]);
154 }
155 // If the atlas has less than 4 active proxies we still need to set up samplers for the shader.
156 for (unsigned int i = numProxies; i < kNumSDFAtlasTextures; ++i) {
157 gatherer->add(kSamplingOptions, kTileModes, proxies[0]);
158 }
159}
160
161} // namespace skgpu::graphite
#define SkASSERT(cond)
Definition SkAssert.h:116
#define SkDEBUGCODE(...)
Definition SkDebug.h:23
static bool isLCD(const SkScalerContextRec &rec)
SkTileMode
Definition SkTileMode.h:13
TextAtlasManager * textAtlasManager() const
AtlasProvider * atlasProvider()
SkSpan< const Uniform > uniforms() const
Definition Renderer.h:143
std::string vertexSkSL() const override
void writeUniformsAndTextures(const DrawParams &, PipelineDataGatherer *) const override
std::string texturesAndSamplersSkSL(const ResourceBindingRequirements &, int *nextBindingIndex) const override
const char * fragmentCoverageSkSL() const override
void writeVertices(DrawWriter *, const DrawParams &, skvx::ushort2 ssboIndices) const override
const sktext::gpu::AtlasSubRun * subRun() const
Definition SubRunData.h:72
const sk_sp< TextureProxy > * getProxies(MaskFormat format, unsigned int *numActiveProxies)
virtual const VertexFiller & vertexFiller() const =0
virtual unsigned short instanceFlags() const =0
virtual SkSpan< const Glyph * > glyphs() const =0
void fillInstanceData(skgpu::graphite::DrawWriter *dw, int offset, int count, unsigned short flags, skvx::ushort2 ssboIndex, SkSpan< const Glyph * > glyphs, SkScalar depth) const
const EmbeddedViewParams * params
GAsyncResult * result
std::string void appendf(std::string *str, const char *fmt,...) SK_PRINTF_LIKE(2
static constexpr DepthStencilSettings kDirectDepthGEqualPass
std::string EmitSamplerLayout(const ResourceBindingRequirements &bindingReqs, int *binding)
Definition SkM44.h:19