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