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