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