xref: /aosp_15_r20/external/skia/src/gpu/ganesh/ops/AtlasInstancedHelper.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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