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