blob: 755cac2f3db9b94a441ba77805ee6fe6b3280f66 [file] [log] [blame]
Chris Daltonb1fd64e2021-07-08 15:38:51 -06001/*
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
Robert Phillipsef80d7b2021-09-14 16:10:56 -04008#ifndef AtlasInstancedHelper_DEFINED
9#define AtlasInstancedHelper_DEFINED
Chris Daltonb1fd64e2021-07-08 15:38:51 -060010
11#include "src/core/SkIPoint16.h"
12#include "src/gpu/GrGeometryProcessor.h"
13#include "src/gpu/GrSurfaceProxyView.h"
Chris Daltonb1fd64e2021-07-08 15:38:51 -060014#include "src/gpu/glsl/GrGLSLUniformHandler.h"
15
16struct GrVertexWriter;
17
Robert Phillipsef80d7b2021-09-14 16:10:56 -040018namespace skgpu::v1 {
19
Chris Daltonb1fd64e2021-07-08 15:38:51 -060020// This class encapsulates all the necessary steps for an instanced GrGeometryProcessor to clip
21// against a path mask from an atlas.
Robert Phillipsef80d7b2021-09-14 16:10:56 -040022class AtlasInstancedHelper {
Chris Daltonb1fd64e2021-07-08 15:38:51 -060023public:
24 enum class ShaderFlags {
25 kNone = 0,
26 kInvertCoverage = 1 << 0,
27 kCheckBounds = 1 << 1
28 };
29
30 GR_DECL_BITFIELD_CLASS_OPS_FRIENDS(ShaderFlags);
31
32 constexpr static int kNumShaderFlags = 2;
33
Robert Phillipsef80d7b2021-09-14 16:10:56 -040034 AtlasInstancedHelper(GrSurfaceProxyView atlasView, ShaderFlags shaderFlags)
Chris Daltonb1fd64e2021-07-08 15:38:51 -060035 : fAtlasProxy(atlasView.detachProxy())
36 , fAtlasSwizzle(atlasView.swizzle())
37 , fShaderFlags(shaderFlags) {
38 // Bottom left origin is not supported.
39 SkASSERT(atlasView.origin() == kTopLeft_GrSurfaceOrigin);
40 }
41
42 GrSurfaceProxy* proxy() const { return fAtlasProxy.get(); }
43 const GrSwizzle& atlasSwizzle() const { return fAtlasSwizzle; }
44
45 // Returns whether the two helpers can be batched together in a single draw.
Robert Phillipsef80d7b2021-09-14 16:10:56 -040046 bool isCompatible(const AtlasInstancedHelper& helper) {
Chris Daltonb1fd64e2021-07-08 15:38:51 -060047 // TODO: We may want to consider two helpers compatible if they only differ in the
48 // kCheckBounds flag -- we can always promote one to checking its bounds.
49 SkASSERT(fAtlasProxy != helper.fAtlasProxy || fAtlasSwizzle == helper.fAtlasSwizzle);
50 return fAtlasProxy == helper.fAtlasProxy && fShaderFlags == helper.fShaderFlags;
51 }
52
53 // Adds bits to the shader key that uniquely identify this specific helper's shader code.
54 void getKeyBits(GrProcessorKeyBuilder* b) const {
55 b->addBits(kNumShaderFlags, (int)fShaderFlags, "atlasFlags");
56 }
57
58 // Appends the instanced input attribs to the back of the array that we will need in order to
59 // locate our path in the atlas.
60 void appendInstanceAttribs(SkTArray<GrGeometryProcessor::Attribute>* instanceAttribs) const;
61
62 struct Instance {
63 Instance(SkIPoint16 locationInAtlas, const SkIRect& pathDevIBounds, bool transposedInAtlas)
64 : fLocationInAtlas(locationInAtlas)
65 , fPathDevIBounds(pathDevIBounds)
66 , fTransposedInAtlas(transposedInAtlas) {
67 SkASSERT(fLocationInAtlas.x() >= 0);
68 SkASSERT(fLocationInAtlas.y() >= 0);
69 }
70 SkIPoint16 fLocationInAtlas;
71 SkIRect fPathDevIBounds;
72 bool fTransposedInAtlas;
73 };
74
75 // Writes out the given instance data, formatted for the specific attribs that we added during
76 // appendInstanceAttribs().
77 void writeInstanceData(GrVertexWriter* instanceWriter, const Instance*) const;
78
79 // Injects vertex code, fragment code, varyings, and uniforms to ultimately multiply
80 // "args.fOutputCoverage" in the fragment shader by the atlas coverage.
81 //
82 // The caller is responsible to store "atlasAdjustUniformHandle" and pass it to
83 // setUniformData().
Brian Salomonf95940b2021-08-09 15:56:24 -040084 void injectShaderCode(const GrGeometryProcessor::ProgramImpl::EmitArgs&,
85 const GrShaderVar& devCoord,
Chris Daltonb1fd64e2021-07-08 15:38:51 -060086 GrGLSLUniformHandler::UniformHandle* atlasAdjustUniformHandle) const;
87
88 // The atlas clip requires one uniform value -- "atlasAdjustUniform". The caller should have
89 // stored this handle after its call to injectShaderCode(). This method sets its value prior to
90 // drawing.
91 void setUniformData(const GrGLSLProgramDataManager&,
92 const GrGLSLUniformHandler::UniformHandle& atlasAdjustUniformHandle) const;
93
94private:
95 const sk_sp<GrSurfaceProxy> fAtlasProxy;
96 const GrSwizzle fAtlasSwizzle;
97 const ShaderFlags fShaderFlags;
98};
99
Robert Phillipsef80d7b2021-09-14 16:10:56 -0400100GR_MAKE_BITFIELD_CLASS_OPS(AtlasInstancedHelper::ShaderFlags);
Chris Daltonb1fd64e2021-07-08 15:38:51 -0600101
Robert Phillipsef80d7b2021-09-14 16:10:56 -0400102} // namespace skgpu::v1
103
104#endif // AtlasInstancedHelper_DEFINED