• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/ganesh/GrGeometryProcessor.h"
13 #include "src/gpu/ganesh/GrSurfaceProxyView.h"
14 #include "src/gpu/ganesh/glsl/GrGLSLUniformHandler.h"
15 
16 namespace skgpu::ganesh {
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 skgpu::Swizzle& 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.
52     void getKeyBits(KeyBuilder* b) const;
53 
54     // Appends the instanced input attribs to the back of the array that we will need in order to
55     // locate our path in the atlas.
56     void appendInstanceAttribs(
57             skia_private::TArray<GrGeometryProcessor::Attribute>* instanceAttribs) const;
58 
59     struct Instance {
InstanceInstance60         Instance(SkIPoint16 locationInAtlas, const SkIRect& pathDevIBounds, bool transposedInAtlas)
61                 : fLocationInAtlas(locationInAtlas)
62                 , fPathDevIBounds(pathDevIBounds)
63                 , fTransposedInAtlas(transposedInAtlas) {
64             SkASSERT(fLocationInAtlas.x() >= 0);
65             SkASSERT(fLocationInAtlas.y() >= 0);
66         }
67         SkIPoint16 fLocationInAtlas;
68         SkIRect fPathDevIBounds;
69         bool fTransposedInAtlas;
70     };
71 
72     // Writes out the given instance data, formatted for the specific attribs that we added during
73     // appendInstanceAttribs().
74     void writeInstanceData(VertexWriter* instanceWriter, const Instance*) const;
75 
76     // Injects vertex code, fragment code, varyings, and uniforms to ultimately multiply
77     // "args.fOutputCoverage" in the fragment shader by the atlas coverage.
78     //
79     // The caller is responsible to store "atlasAdjustUniformHandle" and pass it to
80     // setUniformData().
81     void injectShaderCode(const GrGeometryProcessor::ProgramImpl::EmitArgs&,
82                           const GrShaderVar& devCoord,
83                           GrGLSLUniformHandler::UniformHandle* atlasAdjustUniformHandle) const;
84 
85     // The atlas clip requires one uniform value -- "atlasAdjustUniform". The caller should have
86     // stored this handle after its call to injectShaderCode(). This method sets its value prior to
87     // drawing.
88     void setUniformData(const GrGLSLProgramDataManager&,
89                         const GrGLSLUniformHandler::UniformHandle& atlasAdjustUniformHandle) const;
90 
91 private:
92     const sk_sp<GrSurfaceProxy> fAtlasProxy;
93     const skgpu::Swizzle fAtlasSwizzle;
94     const ShaderFlags fShaderFlags;
95 };
96 
97 GR_MAKE_BITFIELD_CLASS_OPS(AtlasInstancedHelper::ShaderFlags)
98 
99 }  // namespace skgpu::ganesh
100 
101 #endif // AtlasInstancedHelper_DEFINED
102