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