1 /* 2 * Copyright 2021 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 #ifndef AtlasInstancedHelper_DEFINED 9 #define AtlasInstancedHelper_DEFINED 10 11 #include "src/core/SkIPoint16.h" 12 #include "src/gpu/GrGeometryProcessor.h" 13 #include "src/gpu/GrSurfaceProxyView.h" 14 #include "src/gpu/glsl/GrGLSLUniformHandler.h" 15 16 namespace skgpu::v1 { 17 18 // This class encapsulates all the necessary steps for an instanced GrGeometryProcessor to clip 19 // against a path mask from an atlas. 20 class AtlasInstancedHelper { 21 public: 22 enum class ShaderFlags { 23 kNone = 0, 24 kInvertCoverage = 1 << 0, 25 kCheckBounds = 1 << 1 26 }; 27 28 GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(ShaderFlags); 29 30 constexpr static int kNumShaderFlags = 2; 31 AtlasInstancedHelper(GrSurfaceProxyView atlasView,ShaderFlags shaderFlags)32 AtlasInstancedHelper(GrSurfaceProxyView atlasView, ShaderFlags shaderFlags) 33 : fAtlasProxy(atlasView.detachProxy()) 34 , fAtlasSwizzle(atlasView.swizzle()) 35 , fShaderFlags(shaderFlags) { 36 // Bottom left origin is not supported. 37 SkASSERT(atlasView.origin() == kTopLeft_GrSurfaceOrigin); 38 } 39 proxy()40 GrSurfaceProxy* proxy() const { return fAtlasProxy.get(); } atlasSwizzle()41 const GrSwizzle& atlasSwizzle() const { return fAtlasSwizzle; } 42 43 // Returns whether the two helpers can be batched together in a single draw. isCompatible(const AtlasInstancedHelper & helper)44 bool isCompatible(const AtlasInstancedHelper& helper) { 45 // TODO: We may want to consider two helpers compatible if they only differ in the 46 // kCheckBounds flag -- we can always promote one to checking its bounds. 47 SkASSERT(fAtlasProxy != helper.fAtlasProxy || fAtlasSwizzle == helper.fAtlasSwizzle); 48 return fAtlasProxy == helper.fAtlasProxy && fShaderFlags == helper.fShaderFlags; 49 } 50 51 // Adds bits to the shader key that uniquely identify this specific helper's shader code. getKeyBits(GrProcessorKeyBuilder * b)52 void getKeyBits(GrProcessorKeyBuilder* b) const { 53 b->addBits(kNumShaderFlags, (int)fShaderFlags, "atlasFlags"); 54 } 55 56 // Appends the instanced input attribs to the back of the array that we will need in order to 57 // locate our path in the atlas. 58 void appendInstanceAttribs(SkTArray<GrGeometryProcessor::Attribute>* instanceAttribs) const; 59 60 struct Instance { InstanceInstance61 Instance(SkIPoint16 locationInAtlas, const SkIRect& pathDevIBounds, bool transposedInAtlas) 62 : fLocationInAtlas(locationInAtlas) 63 , fPathDevIBounds(pathDevIBounds) 64 , fTransposedInAtlas(transposedInAtlas) { 65 SkASSERT(fLocationInAtlas.x() >= 0); 66 SkASSERT(fLocationInAtlas.y() >= 0); 67 } 68 SkIPoint16 fLocationInAtlas; 69 SkIRect fPathDevIBounds; 70 bool fTransposedInAtlas; 71 }; 72 73 // Writes out the given instance data, formatted for the specific attribs that we added during 74 // appendInstanceAttribs(). 75 void writeInstanceData(VertexWriter* instanceWriter, const Instance*) const; 76 77 // Injects vertex code, fragment code, varyings, and uniforms to ultimately multiply 78 // "args.fOutputCoverage" in the fragment shader by the atlas coverage. 79 // 80 // The caller is responsible to store "atlasAdjustUniformHandle" and pass it to 81 // setUniformData(). 82 void injectShaderCode(const GrGeometryProcessor::ProgramImpl::EmitArgs&, 83 const GrShaderVar& devCoord, 84 GrGLSLUniformHandler::UniformHandle* atlasAdjustUniformHandle) const; 85 86 // The atlas clip requires one uniform value -- "atlasAdjustUniform". The caller should have 87 // stored this handle after its call to injectShaderCode(). This method sets its value prior to 88 // drawing. 89 void setUniformData(const GrGLSLProgramDataManager&, 90 const GrGLSLUniformHandler::UniformHandle& atlasAdjustUniformHandle) const; 91 92 private: 93 const sk_sp<GrSurfaceProxy> fAtlasProxy; 94 const GrSwizzle fAtlasSwizzle; 95 const ShaderFlags fShaderFlags; 96 }; 97 98 GR_MAKE_BITFIELD_CLASS_OPS(AtlasInstancedHelper::ShaderFlags); 99 100 } // namespace skgpu::v1 101 102 #endif // AtlasInstancedHelper_DEFINED 103