xref: /aosp_15_r20/external/skia/src/gpu/ganesh/ops/GrOp.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2015 Google Inc.
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 GrOp_DEFINED
9*c8dee2aaSAndroid Build Coastguard Worker #define GrOp_DEFINED
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/SkColorData.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkNoncopyable.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTraceEvent.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurfaceProxy.h"
22*c8dee2aaSAndroid Build Coastguard Worker 
23*c8dee2aaSAndroid Build Coastguard Worker #include <atomic>
24*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
25*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
26*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
27*c8dee2aaSAndroid Build Coastguard Worker #include <new>
28*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
29*c8dee2aaSAndroid Build Coastguard Worker 
30*c8dee2aaSAndroid Build Coastguard Worker class GrAppliedClip;
31*c8dee2aaSAndroid Build Coastguard Worker class GrCaps;
32*c8dee2aaSAndroid Build Coastguard Worker class GrDstProxyView;
33*c8dee2aaSAndroid Build Coastguard Worker class GrOpFlushState;
34*c8dee2aaSAndroid Build Coastguard Worker class GrPaint;
35*c8dee2aaSAndroid Build Coastguard Worker class GrRecordingContext;
36*c8dee2aaSAndroid Build Coastguard Worker class GrSurfaceProxyView;
37*c8dee2aaSAndroid Build Coastguard Worker class SkArenaAlloc;
38*c8dee2aaSAndroid Build Coastguard Worker enum class GrXferBarrierFlags;
39*c8dee2aaSAndroid Build Coastguard Worker 
40*c8dee2aaSAndroid Build Coastguard Worker /**
41*c8dee2aaSAndroid Build Coastguard Worker  * GrOp is the base class for all Ganesh deferred GPU operations. To facilitate reordering and to
42*c8dee2aaSAndroid Build Coastguard Worker  * minimize draw calls, Ganesh does not generate geometry inline with draw calls. Instead, it
43*c8dee2aaSAndroid Build Coastguard Worker  * captures the arguments to the draw and then generates the geometry when flushing. This gives GrOp
44*c8dee2aaSAndroid Build Coastguard Worker  * subclasses complete freedom to decide how/when to combine in order to produce fewer draw calls
45*c8dee2aaSAndroid Build Coastguard Worker  * and minimize state changes.
46*c8dee2aaSAndroid Build Coastguard Worker  *
47*c8dee2aaSAndroid Build Coastguard Worker  * Ops of the same subclass may be merged or chained using combineIfPossible. When two ops merge,
48*c8dee2aaSAndroid Build Coastguard Worker  * one takes on the union of the data and the other is left empty. The merged op becomes responsible
49*c8dee2aaSAndroid Build Coastguard Worker  * for drawing the data from both the original ops. When ops are chained each op maintains its own
50*c8dee2aaSAndroid Build Coastguard Worker  * data but they are linked in a list and the head op becomes responsible for executing the work for
51*c8dee2aaSAndroid Build Coastguard Worker  * the chain.
52*c8dee2aaSAndroid Build Coastguard Worker  *
53*c8dee2aaSAndroid Build Coastguard Worker  * It is required that chainability is transitive. Moreover, if op A is able to merge with B then
54*c8dee2aaSAndroid Build Coastguard Worker  * it must be the case that any op that can chain with A will either merge or chain with any op
55*c8dee2aaSAndroid Build Coastguard Worker  * that can chain to B.
56*c8dee2aaSAndroid Build Coastguard Worker  *
57*c8dee2aaSAndroid Build Coastguard Worker  * The bounds of the op must contain all the vertices in device space *irrespective* of the clip.
58*c8dee2aaSAndroid Build Coastguard Worker  * The bounds are used in determining which clip elements must be applied and thus the bounds cannot
59*c8dee2aaSAndroid Build Coastguard Worker  * in turn depend upon the clip.
60*c8dee2aaSAndroid Build Coastguard Worker  */
61*c8dee2aaSAndroid Build Coastguard Worker #define GR_OP_SPEW 0
62*c8dee2aaSAndroid Build Coastguard Worker #if GR_OP_SPEW
63*c8dee2aaSAndroid Build Coastguard Worker     #define GrOP_SPEW(code) code
64*c8dee2aaSAndroid Build Coastguard Worker     #define GrOP_INFO(...) SkDebugf(__VA_ARGS__)
65*c8dee2aaSAndroid Build Coastguard Worker #else
66*c8dee2aaSAndroid Build Coastguard Worker     #define GrOP_SPEW(code)
67*c8dee2aaSAndroid Build Coastguard Worker     #define GrOP_INFO(...)
68*c8dee2aaSAndroid Build Coastguard Worker #endif
69*c8dee2aaSAndroid Build Coastguard Worker 
70*c8dee2aaSAndroid Build Coastguard Worker // Print out op information at flush time
71*c8dee2aaSAndroid Build Coastguard Worker #define GR_FLUSH_TIME_OP_SPEW 0
72*c8dee2aaSAndroid Build Coastguard Worker 
73*c8dee2aaSAndroid Build Coastguard Worker // A helper macro to generate a class static id
74*c8dee2aaSAndroid Build Coastguard Worker #define DEFINE_OP_CLASS_ID \
75*c8dee2aaSAndroid Build Coastguard Worker     static uint32_t ClassID() { \
76*c8dee2aaSAndroid Build Coastguard Worker         static uint32_t kClassID = GenOpClassID(); \
77*c8dee2aaSAndroid Build Coastguard Worker         return kClassID; \
78*c8dee2aaSAndroid Build Coastguard Worker     }
79*c8dee2aaSAndroid Build Coastguard Worker 
80*c8dee2aaSAndroid Build Coastguard Worker class GrOp : private SkNoncopyable {
81*c8dee2aaSAndroid Build Coastguard Worker public:
82*c8dee2aaSAndroid Build Coastguard Worker     using Owner = std::unique_ptr<GrOp>;
83*c8dee2aaSAndroid Build Coastguard Worker 
84*c8dee2aaSAndroid Build Coastguard Worker     template<typename Op, typename... Args>
Make(GrRecordingContext * context,Args &&...args)85*c8dee2aaSAndroid Build Coastguard Worker     static Owner Make(GrRecordingContext* context, Args&&... args) {
86*c8dee2aaSAndroid Build Coastguard Worker         return Owner{new Op(std::forward<Args>(args)...)};
87*c8dee2aaSAndroid Build Coastguard Worker     }
88*c8dee2aaSAndroid Build Coastguard Worker 
89*c8dee2aaSAndroid Build Coastguard Worker     template<typename Op, typename... Args>
90*c8dee2aaSAndroid Build Coastguard Worker     static Owner MakeWithProcessorSet(
91*c8dee2aaSAndroid Build Coastguard Worker             GrRecordingContext* context, const SkPMColor4f& color,
92*c8dee2aaSAndroid Build Coastguard Worker             GrPaint&& paint, Args&&... args);
93*c8dee2aaSAndroid Build Coastguard Worker 
94*c8dee2aaSAndroid Build Coastguard Worker     template<typename Op, typename... Args>
MakeWithExtraMemory(GrRecordingContext * context,size_t extraSize,Args &&...args)95*c8dee2aaSAndroid Build Coastguard Worker     static Owner MakeWithExtraMemory(
96*c8dee2aaSAndroid Build Coastguard Worker             GrRecordingContext* context, size_t extraSize, Args&&... args) {
97*c8dee2aaSAndroid Build Coastguard Worker         void* bytes = ::operator new(sizeof(Op) + extraSize);
98*c8dee2aaSAndroid Build Coastguard Worker         return Owner{new (bytes) Op(std::forward<Args>(args)...)};
99*c8dee2aaSAndroid Build Coastguard Worker     }
100*c8dee2aaSAndroid Build Coastguard Worker 
101*c8dee2aaSAndroid Build Coastguard Worker     virtual ~GrOp() = default;
102*c8dee2aaSAndroid Build Coastguard Worker 
103*c8dee2aaSAndroid Build Coastguard Worker     virtual const char* name() const = 0;
104*c8dee2aaSAndroid Build Coastguard Worker 
visitProxies(const GrVisitProxyFunc &)105*c8dee2aaSAndroid Build Coastguard Worker     virtual void visitProxies(const GrVisitProxyFunc&) const {
106*c8dee2aaSAndroid Build Coastguard Worker         // This default implementation assumes the op has no proxies
107*c8dee2aaSAndroid Build Coastguard Worker     }
108*c8dee2aaSAndroid Build Coastguard Worker 
109*c8dee2aaSAndroid Build Coastguard Worker     enum class CombineResult {
110*c8dee2aaSAndroid Build Coastguard Worker         /**
111*c8dee2aaSAndroid Build Coastguard Worker          * The op that combineIfPossible was called on now represents its own work plus that of
112*c8dee2aaSAndroid Build Coastguard Worker          * the passed op. The passed op should be destroyed without being flushed. Currently it
113*c8dee2aaSAndroid Build Coastguard Worker          * is not legal to merge an op passed to combineIfPossible() the passed op is already in a
114*c8dee2aaSAndroid Build Coastguard Worker          * chain (though the op on which combineIfPossible() was called may be).
115*c8dee2aaSAndroid Build Coastguard Worker          */
116*c8dee2aaSAndroid Build Coastguard Worker         kMerged,
117*c8dee2aaSAndroid Build Coastguard Worker         /**
118*c8dee2aaSAndroid Build Coastguard Worker          * The caller *may* (but is not required) to chain these ops together. If they are chained
119*c8dee2aaSAndroid Build Coastguard Worker          * then prepare() and execute() will be called on the head op but not the other ops in the
120*c8dee2aaSAndroid Build Coastguard Worker          * chain. The head op will prepare and execute on behalf of all the ops in the chain.
121*c8dee2aaSAndroid Build Coastguard Worker          */
122*c8dee2aaSAndroid Build Coastguard Worker         kMayChain,
123*c8dee2aaSAndroid Build Coastguard Worker         /**
124*c8dee2aaSAndroid Build Coastguard Worker          * The ops cannot be combined.
125*c8dee2aaSAndroid Build Coastguard Worker          */
126*c8dee2aaSAndroid Build Coastguard Worker         kCannotCombine
127*c8dee2aaSAndroid Build Coastguard Worker     };
128*c8dee2aaSAndroid Build Coastguard Worker 
129*c8dee2aaSAndroid Build Coastguard Worker     // The arenas are the same as what was available when the op was created.
130*c8dee2aaSAndroid Build Coastguard Worker     CombineResult combineIfPossible(GrOp* that, SkArenaAlloc* alloc, const GrCaps& caps);
131*c8dee2aaSAndroid Build Coastguard Worker 
bounds()132*c8dee2aaSAndroid Build Coastguard Worker     const SkRect& bounds() const {
133*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(kUninitialized_BoundsFlag != fBoundsFlags);
134*c8dee2aaSAndroid Build Coastguard Worker         return fBounds;
135*c8dee2aaSAndroid Build Coastguard Worker     }
136*c8dee2aaSAndroid Build Coastguard Worker 
setClippedBounds(const SkRect & clippedBounds)137*c8dee2aaSAndroid Build Coastguard Worker     void setClippedBounds(const SkRect& clippedBounds) {
138*c8dee2aaSAndroid Build Coastguard Worker         fBounds = clippedBounds;
139*c8dee2aaSAndroid Build Coastguard Worker         // The clipped bounds already incorporate any effect of the bounds flags.
140*c8dee2aaSAndroid Build Coastguard Worker         fBoundsFlags = 0;
141*c8dee2aaSAndroid Build Coastguard Worker     }
142*c8dee2aaSAndroid Build Coastguard Worker 
hasAABloat()143*c8dee2aaSAndroid Build Coastguard Worker     bool hasAABloat() const {
144*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fBoundsFlags != kUninitialized_BoundsFlag);
145*c8dee2aaSAndroid Build Coastguard Worker         return SkToBool(fBoundsFlags & kAABloat_BoundsFlag);
146*c8dee2aaSAndroid Build Coastguard Worker     }
147*c8dee2aaSAndroid Build Coastguard Worker 
hasZeroArea()148*c8dee2aaSAndroid Build Coastguard Worker     bool hasZeroArea() const {
149*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(fBoundsFlags != kUninitialized_BoundsFlag);
150*c8dee2aaSAndroid Build Coastguard Worker         return SkToBool(fBoundsFlags & kZeroArea_BoundsFlag);
151*c8dee2aaSAndroid Build Coastguard Worker     }
152*c8dee2aaSAndroid Build Coastguard Worker 
delete(void * p)153*c8dee2aaSAndroid Build Coastguard Worker     void operator delete(void* p) { ::operator delete(p); }
154*c8dee2aaSAndroid Build Coastguard Worker 
155*c8dee2aaSAndroid Build Coastguard Worker     /**
156*c8dee2aaSAndroid Build Coastguard Worker      * Helper for safely down-casting to a GrOp subclass
157*c8dee2aaSAndroid Build Coastguard Worker      */
cast()158*c8dee2aaSAndroid Build Coastguard Worker     template <typename T> const T& cast() const {
159*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(T::ClassID() == this->classID());
160*c8dee2aaSAndroid Build Coastguard Worker         return *static_cast<const T*>(this);
161*c8dee2aaSAndroid Build Coastguard Worker     }
162*c8dee2aaSAndroid Build Coastguard Worker 
cast()163*c8dee2aaSAndroid Build Coastguard Worker     template <typename T> T* cast() {
164*c8dee2aaSAndroid Build Coastguard Worker         SkASSERT(T::ClassID() == this->classID());
165*c8dee2aaSAndroid Build Coastguard Worker         return static_cast<T*>(this);
166*c8dee2aaSAndroid Build Coastguard Worker     }
167*c8dee2aaSAndroid Build Coastguard Worker 
classID()168*c8dee2aaSAndroid Build Coastguard Worker     uint32_t classID() const { SkASSERT(kIllegalOpID != fClassID); return fClassID; }
169*c8dee2aaSAndroid Build Coastguard Worker 
170*c8dee2aaSAndroid Build Coastguard Worker     // We lazily initialize the uniqueID because currently the only user is GrAuditTrail
uniqueID()171*c8dee2aaSAndroid Build Coastguard Worker     uint32_t uniqueID() const {
172*c8dee2aaSAndroid Build Coastguard Worker         if (kIllegalOpID == fUniqueID) {
173*c8dee2aaSAndroid Build Coastguard Worker             fUniqueID = GenOpID();
174*c8dee2aaSAndroid Build Coastguard Worker         }
175*c8dee2aaSAndroid Build Coastguard Worker         return fUniqueID;
176*c8dee2aaSAndroid Build Coastguard Worker     }
177*c8dee2aaSAndroid Build Coastguard Worker 
178*c8dee2aaSAndroid Build Coastguard Worker     /**
179*c8dee2aaSAndroid Build Coastguard Worker      * This can optionally be called before 'prepare' (but after sorting). Each op that overrides
180*c8dee2aaSAndroid Build Coastguard Worker      * onPrePrepare must be prepared to handle both cases (when onPrePrepare has been called
181*c8dee2aaSAndroid Build Coastguard Worker      * ahead of time and when it has not been called).
182*c8dee2aaSAndroid Build Coastguard Worker      */
prePrepare(GrRecordingContext * context,const GrSurfaceProxyView & dstView,GrAppliedClip * clip,const GrDstProxyView & dstProxyView,GrXferBarrierFlags renderPassXferBarriers,GrLoadOp colorLoadOp)183*c8dee2aaSAndroid Build Coastguard Worker     void prePrepare(GrRecordingContext* context, const GrSurfaceProxyView& dstView,
184*c8dee2aaSAndroid Build Coastguard Worker                     GrAppliedClip* clip, const GrDstProxyView& dstProxyView,
185*c8dee2aaSAndroid Build Coastguard Worker                     GrXferBarrierFlags renderPassXferBarriers, GrLoadOp colorLoadOp) {
186*c8dee2aaSAndroid Build Coastguard Worker         TRACE_EVENT0_ALWAYS("skia.gpu", TRACE_STR_STATIC(name()));
187*c8dee2aaSAndroid Build Coastguard Worker         this->onPrePrepare(context, dstView, clip, dstProxyView, renderPassXferBarriers,
188*c8dee2aaSAndroid Build Coastguard Worker                            colorLoadOp);
189*c8dee2aaSAndroid Build Coastguard Worker     }
190*c8dee2aaSAndroid Build Coastguard Worker 
191*c8dee2aaSAndroid Build Coastguard Worker     /**
192*c8dee2aaSAndroid Build Coastguard Worker      * Called prior to executing. The op should perform any resource creation or data transfers
193*c8dee2aaSAndroid Build Coastguard Worker      * necessary before execute() is called.
194*c8dee2aaSAndroid Build Coastguard Worker      */
prepare(GrOpFlushState * state)195*c8dee2aaSAndroid Build Coastguard Worker     void prepare(GrOpFlushState* state) {
196*c8dee2aaSAndroid Build Coastguard Worker         TRACE_EVENT0_ALWAYS("skia.gpu", TRACE_STR_STATIC(name()));
197*c8dee2aaSAndroid Build Coastguard Worker         this->onPrepare(state);
198*c8dee2aaSAndroid Build Coastguard Worker     }
199*c8dee2aaSAndroid Build Coastguard Worker 
200*c8dee2aaSAndroid Build Coastguard Worker     /** Issues the op's commands to GrGpu. */
execute(GrOpFlushState * state,const SkRect & chainBounds)201*c8dee2aaSAndroid Build Coastguard Worker     void execute(GrOpFlushState* state, const SkRect& chainBounds) {
202*c8dee2aaSAndroid Build Coastguard Worker         TRACE_EVENT0_ALWAYS("skia.gpu", TRACE_STR_STATIC(name()));
203*c8dee2aaSAndroid Build Coastguard Worker         this->onExecute(state, chainBounds);
204*c8dee2aaSAndroid Build Coastguard Worker     }
205*c8dee2aaSAndroid Build Coastguard Worker 
206*c8dee2aaSAndroid Build Coastguard Worker     /** Used for spewing information about ops when debugging. */
207*c8dee2aaSAndroid Build Coastguard Worker #if defined(GPU_TEST_UTILS)
dumpInfo()208*c8dee2aaSAndroid Build Coastguard Worker     virtual SkString dumpInfo() const final {
209*c8dee2aaSAndroid Build Coastguard Worker         return SkStringPrintf("%s\nOpBounds: [L: %.2f, T: %.2f, R: %.2f, B: %.2f]",
210*c8dee2aaSAndroid Build Coastguard Worker                               this->onDumpInfo().c_str(), fBounds.fLeft, fBounds.fTop,
211*c8dee2aaSAndroid Build Coastguard Worker                               fBounds.fRight, fBounds.fBottom);
212*c8dee2aaSAndroid Build Coastguard Worker     }
213*c8dee2aaSAndroid Build Coastguard Worker #endif
214*c8dee2aaSAndroid Build Coastguard Worker 
215*c8dee2aaSAndroid Build Coastguard Worker     /**
216*c8dee2aaSAndroid Build Coastguard Worker      * A helper for iterating over an op chain in a range for loop that also downcasts to a GrOp
217*c8dee2aaSAndroid Build Coastguard Worker      * subclass. E.g.:
218*c8dee2aaSAndroid Build Coastguard Worker      *     for (MyOpSubClass& op : ChainRange<MyOpSubClass>(this)) {
219*c8dee2aaSAndroid Build Coastguard Worker      *         // ...
220*c8dee2aaSAndroid Build Coastguard Worker      *     }
221*c8dee2aaSAndroid Build Coastguard Worker      */
222*c8dee2aaSAndroid Build Coastguard Worker     template <typename OpSubclass = GrOp> class ChainRange {
223*c8dee2aaSAndroid Build Coastguard Worker     private:
224*c8dee2aaSAndroid Build Coastguard Worker         class Iter {
225*c8dee2aaSAndroid Build Coastguard Worker         public:
Iter(const OpSubclass * head)226*c8dee2aaSAndroid Build Coastguard Worker             explicit Iter(const OpSubclass* head) : fCurr(head) {}
227*c8dee2aaSAndroid Build Coastguard Worker             inline Iter& operator++() {
228*c8dee2aaSAndroid Build Coastguard Worker                 return *this = Iter(static_cast<const OpSubclass*>(fCurr->nextInChain()));
229*c8dee2aaSAndroid Build Coastguard Worker             }
230*c8dee2aaSAndroid Build Coastguard Worker             const OpSubclass& operator*() const { return *fCurr; }
231*c8dee2aaSAndroid Build Coastguard Worker             bool operator!=(const Iter& that) const { return fCurr != that.fCurr; }
232*c8dee2aaSAndroid Build Coastguard Worker 
233*c8dee2aaSAndroid Build Coastguard Worker         private:
234*c8dee2aaSAndroid Build Coastguard Worker             const OpSubclass* fCurr;
235*c8dee2aaSAndroid Build Coastguard Worker         };
236*c8dee2aaSAndroid Build Coastguard Worker         const OpSubclass* fHead;
237*c8dee2aaSAndroid Build Coastguard Worker 
238*c8dee2aaSAndroid Build Coastguard Worker     public:
ChainRange(const OpSubclass * head)239*c8dee2aaSAndroid Build Coastguard Worker         explicit ChainRange(const OpSubclass* head) : fHead(head) {}
begin()240*c8dee2aaSAndroid Build Coastguard Worker         Iter begin() { return Iter(fHead); }
end()241*c8dee2aaSAndroid Build Coastguard Worker         Iter end() { return Iter(nullptr); }
242*c8dee2aaSAndroid Build Coastguard Worker     };
243*c8dee2aaSAndroid Build Coastguard Worker 
244*c8dee2aaSAndroid Build Coastguard Worker     /**
245*c8dee2aaSAndroid Build Coastguard Worker      * Concatenates two op chains. This op must be a tail and the passed op must be a head. The ops
246*c8dee2aaSAndroid Build Coastguard Worker      * must be of the same subclass.
247*c8dee2aaSAndroid Build Coastguard Worker      */
248*c8dee2aaSAndroid Build Coastguard Worker     void chainConcat(GrOp::Owner);
249*c8dee2aaSAndroid Build Coastguard Worker     /** Returns true if this is the head of a chain (including a length 1 chain). */
isChainHead()250*c8dee2aaSAndroid Build Coastguard Worker     bool isChainHead() const { return !fPrevInChain; }
251*c8dee2aaSAndroid Build Coastguard Worker     /** Returns true if this is the tail of a chain (including a length 1 chain). */
isChainTail()252*c8dee2aaSAndroid Build Coastguard Worker     bool isChainTail() const { return !fNextInChain; }
253*c8dee2aaSAndroid Build Coastguard Worker     /** The next op in the chain. */
nextInChain()254*c8dee2aaSAndroid Build Coastguard Worker     GrOp* nextInChain() const { return fNextInChain.get(); }
255*c8dee2aaSAndroid Build Coastguard Worker     /** The previous op in the chain. */
prevInChain()256*c8dee2aaSAndroid Build Coastguard Worker     GrOp* prevInChain() const { return fPrevInChain; }
257*c8dee2aaSAndroid Build Coastguard Worker     /**
258*c8dee2aaSAndroid Build Coastguard Worker      * Cuts the chain after this op. The returned op is the op that was previously next in the
259*c8dee2aaSAndroid Build Coastguard Worker      * chain or null if this was already a tail.
260*c8dee2aaSAndroid Build Coastguard Worker      */
261*c8dee2aaSAndroid Build Coastguard Worker     GrOp::Owner cutChain();
SkDEBUGCODE(void validateChain (GrOp * expectedTail=nullptr)const;)262*c8dee2aaSAndroid Build Coastguard Worker     SkDEBUGCODE(void validateChain(GrOp* expectedTail = nullptr) const;)
263*c8dee2aaSAndroid Build Coastguard Worker 
264*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_DEBUG
265*c8dee2aaSAndroid Build Coastguard Worker     virtual void validate() const {}
266*c8dee2aaSAndroid Build Coastguard Worker #endif
267*c8dee2aaSAndroid Build Coastguard Worker 
268*c8dee2aaSAndroid Build Coastguard Worker protected:
269*c8dee2aaSAndroid Build Coastguard Worker     GrOp(uint32_t classID);
270*c8dee2aaSAndroid Build Coastguard Worker 
271*c8dee2aaSAndroid Build Coastguard Worker     /**
272*c8dee2aaSAndroid Build Coastguard Worker      * Indicates that the op will produce geometry that extends beyond its bounds for the
273*c8dee2aaSAndroid Build Coastguard Worker      * purpose of ensuring that the fragment shader runs on partially covered pixels for
274*c8dee2aaSAndroid Build Coastguard Worker      * non-MSAA antialiasing.
275*c8dee2aaSAndroid Build Coastguard Worker      */
276*c8dee2aaSAndroid Build Coastguard Worker     enum class HasAABloat : bool {
277*c8dee2aaSAndroid Build Coastguard Worker         kNo = false,
278*c8dee2aaSAndroid Build Coastguard Worker         kYes = true
279*c8dee2aaSAndroid Build Coastguard Worker     };
280*c8dee2aaSAndroid Build Coastguard Worker     /**
281*c8dee2aaSAndroid Build Coastguard Worker      * Indicates that the geometry being drawn in a hairline stroke. A point that is drawn in device
282*c8dee2aaSAndroid Build Coastguard Worker      * space is also considered a hairline.
283*c8dee2aaSAndroid Build Coastguard Worker      */
284*c8dee2aaSAndroid Build Coastguard Worker     enum class IsHairline : bool {
285*c8dee2aaSAndroid Build Coastguard Worker         kNo = false,
286*c8dee2aaSAndroid Build Coastguard Worker         kYes = true
287*c8dee2aaSAndroid Build Coastguard Worker     };
288*c8dee2aaSAndroid Build Coastguard Worker 
setBounds(const SkRect & newBounds,HasAABloat aabloat,IsHairline zeroArea)289*c8dee2aaSAndroid Build Coastguard Worker     void setBounds(const SkRect& newBounds, HasAABloat aabloat, IsHairline zeroArea) {
290*c8dee2aaSAndroid Build Coastguard Worker         fBounds = newBounds;
291*c8dee2aaSAndroid Build Coastguard Worker         this->setBoundsFlags(aabloat, zeroArea);
292*c8dee2aaSAndroid Build Coastguard Worker     }
setTransformedBounds(const SkRect & srcBounds,const SkMatrix & m,HasAABloat aabloat,IsHairline zeroArea)293*c8dee2aaSAndroid Build Coastguard Worker     void setTransformedBounds(const SkRect& srcBounds, const SkMatrix& m,
294*c8dee2aaSAndroid Build Coastguard Worker                               HasAABloat aabloat, IsHairline zeroArea) {
295*c8dee2aaSAndroid Build Coastguard Worker         m.mapRect(&fBounds, srcBounds);
296*c8dee2aaSAndroid Build Coastguard Worker         this->setBoundsFlags(aabloat, zeroArea);
297*c8dee2aaSAndroid Build Coastguard Worker     }
makeFullScreen(GrSurfaceProxy * proxy)298*c8dee2aaSAndroid Build Coastguard Worker     void makeFullScreen(GrSurfaceProxy* proxy) {
299*c8dee2aaSAndroid Build Coastguard Worker         this->setBounds(proxy->getBoundsRect(), HasAABloat::kNo, IsHairline::kNo);
300*c8dee2aaSAndroid Build Coastguard Worker     }
301*c8dee2aaSAndroid Build Coastguard Worker 
GenOpClassID()302*c8dee2aaSAndroid Build Coastguard Worker     static uint32_t GenOpClassID() { return GenID(&gCurrOpClassID); }
303*c8dee2aaSAndroid Build Coastguard Worker 
304*c8dee2aaSAndroid Build Coastguard Worker private:
joinBounds(const GrOp & that)305*c8dee2aaSAndroid Build Coastguard Worker     void joinBounds(const GrOp& that) {
306*c8dee2aaSAndroid Build Coastguard Worker         if (that.hasAABloat()) {
307*c8dee2aaSAndroid Build Coastguard Worker             fBoundsFlags |= kAABloat_BoundsFlag;
308*c8dee2aaSAndroid Build Coastguard Worker         }
309*c8dee2aaSAndroid Build Coastguard Worker         if (that.hasZeroArea()) {
310*c8dee2aaSAndroid Build Coastguard Worker             fBoundsFlags |= kZeroArea_BoundsFlag;
311*c8dee2aaSAndroid Build Coastguard Worker         }
312*c8dee2aaSAndroid Build Coastguard Worker         return fBounds.joinPossiblyEmptyRect(that.fBounds);
313*c8dee2aaSAndroid Build Coastguard Worker     }
314*c8dee2aaSAndroid Build Coastguard Worker 
onCombineIfPossible(GrOp *,SkArenaAlloc *,const GrCaps &)315*c8dee2aaSAndroid Build Coastguard Worker     virtual CombineResult onCombineIfPossible(GrOp*, SkArenaAlloc*, const GrCaps&) {
316*c8dee2aaSAndroid Build Coastguard Worker         return CombineResult::kCannotCombine;
317*c8dee2aaSAndroid Build Coastguard Worker     }
318*c8dee2aaSAndroid Build Coastguard Worker 
319*c8dee2aaSAndroid Build Coastguard Worker     // TODO: the parameters to onPrePrepare mirror GrOpFlushState::OpArgs - fuse the two?
320*c8dee2aaSAndroid Build Coastguard Worker     virtual void onPrePrepare(GrRecordingContext*,
321*c8dee2aaSAndroid Build Coastguard Worker                               const GrSurfaceProxyView& writeView,
322*c8dee2aaSAndroid Build Coastguard Worker                               GrAppliedClip*,
323*c8dee2aaSAndroid Build Coastguard Worker                               const GrDstProxyView&,
324*c8dee2aaSAndroid Build Coastguard Worker                               GrXferBarrierFlags renderPassXferBarriers,
325*c8dee2aaSAndroid Build Coastguard Worker                               GrLoadOp colorLoadOp) = 0;
326*c8dee2aaSAndroid Build Coastguard Worker     virtual void onPrepare(GrOpFlushState*) = 0;
327*c8dee2aaSAndroid Build Coastguard Worker     // If this op is chained then chainBounds is the union of the bounds of all ops in the chain.
328*c8dee2aaSAndroid Build Coastguard Worker     // Otherwise, this op's bounds.
329*c8dee2aaSAndroid Build Coastguard Worker     virtual void onExecute(GrOpFlushState*, const SkRect& chainBounds) = 0;
330*c8dee2aaSAndroid Build Coastguard Worker #if defined(GPU_TEST_UTILS)
onDumpInfo()331*c8dee2aaSAndroid Build Coastguard Worker     virtual SkString onDumpInfo() const { return SkString(); }
332*c8dee2aaSAndroid Build Coastguard Worker #endif
333*c8dee2aaSAndroid Build Coastguard Worker 
GenID(std::atomic<uint32_t> * idCounter)334*c8dee2aaSAndroid Build Coastguard Worker     static uint32_t GenID(std::atomic<uint32_t>* idCounter) {
335*c8dee2aaSAndroid Build Coastguard Worker         uint32_t id = idCounter->fetch_add(1, std::memory_order_relaxed);
336*c8dee2aaSAndroid Build Coastguard Worker         if (id == 0) {
337*c8dee2aaSAndroid Build Coastguard Worker             SK_ABORT("This should never wrap as it should only be called once for each GrOp "
338*c8dee2aaSAndroid Build Coastguard Worker                      "subclass.");
339*c8dee2aaSAndroid Build Coastguard Worker         }
340*c8dee2aaSAndroid Build Coastguard Worker         return id;
341*c8dee2aaSAndroid Build Coastguard Worker     }
342*c8dee2aaSAndroid Build Coastguard Worker 
setBoundsFlags(HasAABloat aabloat,IsHairline zeroArea)343*c8dee2aaSAndroid Build Coastguard Worker     void setBoundsFlags(HasAABloat aabloat, IsHairline zeroArea) {
344*c8dee2aaSAndroid Build Coastguard Worker         fBoundsFlags = 0;
345*c8dee2aaSAndroid Build Coastguard Worker         fBoundsFlags |= (HasAABloat::kYes == aabloat) ? kAABloat_BoundsFlag : 0;
346*c8dee2aaSAndroid Build Coastguard Worker         fBoundsFlags |= (IsHairline ::kYes == zeroArea) ? kZeroArea_BoundsFlag : 0;
347*c8dee2aaSAndroid Build Coastguard Worker     }
348*c8dee2aaSAndroid Build Coastguard Worker 
349*c8dee2aaSAndroid Build Coastguard Worker     static constexpr uint16_t kIllegalOpID = 0;
350*c8dee2aaSAndroid Build Coastguard Worker 
351*c8dee2aaSAndroid Build Coastguard Worker     enum BoundsFlags {
352*c8dee2aaSAndroid Build Coastguard Worker         kAABloat_BoundsFlag                     = 0x1,
353*c8dee2aaSAndroid Build Coastguard Worker         kZeroArea_BoundsFlag                    = 0x2,
354*c8dee2aaSAndroid Build Coastguard Worker         SkDEBUGCODE(kUninitialized_BoundsFlag   = 0x4)
355*c8dee2aaSAndroid Build Coastguard Worker     };
356*c8dee2aaSAndroid Build Coastguard Worker 
357*c8dee2aaSAndroid Build Coastguard Worker     Owner                               fNextInChain{nullptr};
358*c8dee2aaSAndroid Build Coastguard Worker     GrOp*                               fPrevInChain = nullptr;
359*c8dee2aaSAndroid Build Coastguard Worker     const uint16_t                      fClassID;
360*c8dee2aaSAndroid Build Coastguard Worker     uint16_t                            fBoundsFlags;
361*c8dee2aaSAndroid Build Coastguard Worker 
GenOpID()362*c8dee2aaSAndroid Build Coastguard Worker     static uint32_t GenOpID() { return GenID(&gCurrOpUniqueID); }
363*c8dee2aaSAndroid Build Coastguard Worker     mutable uint32_t                    fUniqueID = SK_InvalidUniqueID;
364*c8dee2aaSAndroid Build Coastguard Worker     SkRect                              fBounds;
365*c8dee2aaSAndroid Build Coastguard Worker 
366*c8dee2aaSAndroid Build Coastguard Worker     static std::atomic<uint32_t> gCurrOpUniqueID;
367*c8dee2aaSAndroid Build Coastguard Worker     static std::atomic<uint32_t> gCurrOpClassID;
368*c8dee2aaSAndroid Build Coastguard Worker };
369*c8dee2aaSAndroid Build Coastguard Worker 
370*c8dee2aaSAndroid Build Coastguard Worker #endif
371