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