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