GrOp.h revision d543e0a835002cc423de0d09c86eea99a0c0a2ba
14d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt/* 24d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * Copyright 2015 Google Inc. 34d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * 44d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * Use of this source code is governed by a BSD-style license that can be 54d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * found in the LICENSE file. 64d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt */ 74d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt 853e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon#ifndef GrOp_DEFINED 953e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon#define GrOp_DEFINED 104d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt 112c4bd0798e929acb9663668985eabe74d7378c46bungeman#include "../private/SkAtomics.h" 12294870ff119b89fc902773643b054f14e5d1f554Robert Phillips#include "GrGpuResource.h" 13dbe1e6f0c32bd07b7669b1b1ac3c7f58c9b8d773joshualitt#include "GrNonAtomicRef.h" 1488cf17d099085b8085ab11571b5094163dbb2c84bsalomon#include "SkMatrix.h" 1516b991390bb988b194a868ab8de66db4c21c7c13bsalomon#include "SkRect.h" 165346983b2e0726b4009cc546b01c58a8919e6c36bsalomon#include "SkString.h" 174d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt 182c4bd0798e929acb9663668985eabe74d7378c46bungeman#include <new> 192c4bd0798e929acb9663668985eabe74d7378c46bungeman 2016b991390bb988b194a868ab8de66db4c21c7c13bsalomonclass GrCaps; 219cb6340a62a5d748e4189d50e51fa527c8c80c03egdanielclass GrGpuCommandBuffer; 22742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomonclass GrOpFlushState; 234d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt 24abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon/** 2553e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon * GrOp is the base class for all Ganesh deferred GPU operations. To facilitate reordering and to 2653e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon * minimize draw calls, Ganesh does not generate geometry inline with draw calls. Instead, it 2753e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon * captures the arguments to the draw and then generates the geometry when flushing. This gives GrOp 2853e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon * subclasses complete freedom to decide how/when to combine in order to produce fewer draw calls 2953e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon * and minimize state changes. 304d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * 3125a880960a9a689a745a01071ecba3fe494b5940Brian Salomon * Ops of the same subclass may be merged using combineIfPossible. When two ops merge, one 3225a880960a9a689a745a01071ecba3fe494b5940Brian Salomon * takes on the union of the data and the other is left empty. The merged op becomes responsible 3325a880960a9a689a745a01071ecba3fe494b5940Brian Salomon * for drawing the data from both the original ops. 344d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * 354d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * If there are any possible optimizations which might require knowing more about the full state of 3625a880960a9a689a745a01071ecba3fe494b5940Brian Salomon * the draw, e.g. whether or not the GrOp is allowed to tweak alpha for coverage, then this 3725a880960a9a689a745a01071ecba3fe494b5940Brian Salomon * information will be communicated to the GrOp prior to geometry generation. 38db4758c75fdd30ef58096c685e2d749aacaf3d92bsalomon * 3925a880960a9a689a745a01071ecba3fe494b5940Brian Salomon * The bounds of the op must contain all the vertices in device space *irrespective* of the clip. 40db4758c75fdd30ef58096c685e2d749aacaf3d92bsalomon * The bounds are used in determining which clip elements must be applied and thus the bounds cannot 41db4758c75fdd30ef58096c685e2d749aacaf3d92bsalomon * in turn depend upon the clip. 424d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt */ 4325a880960a9a689a745a01071ecba3fe494b5940Brian Salomon#define GR_OP_SPEW 0 4425a880960a9a689a745a01071ecba3fe494b5940Brian Salomon#if GR_OP_SPEW 4525a880960a9a689a745a01071ecba3fe494b5940Brian Salomon #define GrOP_SPEW(code) code 4625a880960a9a689a745a01071ecba3fe494b5940Brian Salomon #define GrOP_INFO(...) SkDebugf(__VA_ARGS__) 47ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt#else 4825a880960a9a689a745a01071ecba3fe494b5940Brian Salomon #define GrOP_SPEW(code) 4925a880960a9a689a745a01071ecba3fe494b5940Brian Salomon #define GrOP_INFO(...) 50ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt#endif 514d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt 521b55a963a2374a14bb82eb887bb99ee91680f0ebreed// A helper macro to generate a class static id 5325a880960a9a689a745a01071ecba3fe494b5940Brian Salomon#define DEFINE_OP_CLASS_ID \ 541b55a963a2374a14bb82eb887bb99ee91680f0ebreed static uint32_t ClassID() { \ 5525a880960a9a689a745a01071ecba3fe494b5940Brian Salomon static uint32_t kClassID = GenOpClassID(); \ 561b55a963a2374a14bb82eb887bb99ee91680f0ebreed return kClassID; \ 571b55a963a2374a14bb82eb887bb99ee91680f0ebreed } 581b55a963a2374a14bb82eb887bb99ee91680f0ebreed 59f8334781914363caf537f22f012fcd5c03c60dadBrian Salomonclass GrOp : private SkNoncopyable { 604d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualittpublic: 6125a880960a9a689a745a01071ecba3fe494b5940Brian Salomon GrOp(uint32_t classID); 6225a880960a9a689a745a01071ecba3fe494b5940Brian Salomon virtual ~GrOp(); 634d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt 644d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt virtual const char* name() const = 0; 654d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt 6625a880960a9a689a745a01071ecba3fe494b5940Brian Salomon bool combineIfPossible(GrOp* that, const GrCaps& caps) { 674d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt if (this->classID() != that->classID()) { 684d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt return false; 694d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt } 704d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt 71cb02b38b2c48bfde333ce3c699dd0451e2d867fabsalomon return this->onCombineIfPossible(that, caps); 724d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt } 734d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt 7488cf17d099085b8085ab11571b5094163dbb2c84bsalomon const SkRect& bounds() const { 7588cf17d099085b8085ab11571b5094163dbb2c84bsalomon SkASSERT(kUninitialized_BoundsFlag != fBoundsFlags); 7688cf17d099085b8085ab11571b5094163dbb2c84bsalomon return fBounds; 7788cf17d099085b8085ab11571b5094163dbb2c84bsalomon } 7888cf17d099085b8085ab11571b5094163dbb2c84bsalomon 799e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon void setClippedBounds(const SkRect& clippedBounds) { 809e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon fBounds = clippedBounds; 819e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon // The clipped bounds already incorporate any effect of the bounds flags. 829e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon fBoundsFlags = 0; 839e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon } 849e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon 8588cf17d099085b8085ab11571b5094163dbb2c84bsalomon bool hasAABloat() const { 8688cf17d099085b8085ab11571b5094163dbb2c84bsalomon SkASSERT(fBoundsFlags != kUninitialized_BoundsFlag); 8788cf17d099085b8085ab11571b5094163dbb2c84bsalomon return SkToBool(fBoundsFlags & kAABloat_BoundsFlag); 8888cf17d099085b8085ab11571b5094163dbb2c84bsalomon } 8988cf17d099085b8085ab11571b5094163dbb2c84bsalomon 9088cf17d099085b8085ab11571b5094163dbb2c84bsalomon bool hasZeroArea() const { 9188cf17d099085b8085ab11571b5094163dbb2c84bsalomon SkASSERT(fBoundsFlags != kUninitialized_BoundsFlag); 9288cf17d099085b8085ab11571b5094163dbb2c84bsalomon return SkToBool(fBoundsFlags & kZeroArea_BoundsFlag); 9388cf17d099085b8085ab11571b5094163dbb2c84bsalomon } 9499c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt 954d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt void* operator new(size_t size); 964d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt void operator delete(void* target); 974d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt 984d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt void* operator new(size_t size, void* placement) { 994d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt return ::operator new(size, placement); 1004d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt } 1014d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt void operator delete(void* target, void* placement) { 1024d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt ::operator delete(target, placement); 1034d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt } 1044d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt 1054d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt /** 10625a880960a9a689a745a01071ecba3fe494b5940Brian Salomon * Helper for safely down-casting to a GrOp subclass 107abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon */ 1081b55a963a2374a14bb82eb887bb99ee91680f0ebreed template <typename T> const T& cast() const { 1091b55a963a2374a14bb82eb887bb99ee91680f0ebreed SkASSERT(T::ClassID() == this->classID()); 1101b55a963a2374a14bb82eb887bb99ee91680f0ebreed return *static_cast<const T*>(this); 1111b55a963a2374a14bb82eb887bb99ee91680f0ebreed } 1121b55a963a2374a14bb82eb887bb99ee91680f0ebreed 1131b55a963a2374a14bb82eb887bb99ee91680f0ebreed template <typename T> T* cast() { 1141b55a963a2374a14bb82eb887bb99ee91680f0ebreed SkASSERT(T::ClassID() == this->classID()); 1151b55a963a2374a14bb82eb887bb99ee91680f0ebreed return static_cast<T*>(this); 1161b55a963a2374a14bb82eb887bb99ee91680f0ebreed } 1174d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt 11825a880960a9a689a745a01071ecba3fe494b5940Brian Salomon uint32_t classID() const { SkASSERT(kIllegalOpID != fClassID); return fClassID; } 1194d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt 12008e65e718a3464a594e6dfca0351dfed19ac2445joshualitt // We lazily initialize the uniqueID because currently the only user is GrAuditTrail 1219d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary uint32_t uniqueID() const { 12225a880960a9a689a745a01071ecba3fe494b5940Brian Salomon if (kIllegalOpID == fUniqueID) { 12325a880960a9a689a745a01071ecba3fe494b5940Brian Salomon fUniqueID = GenOpID(); 12408e65e718a3464a594e6dfca0351dfed19ac2445joshualitt } 1259d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary return fUniqueID; 12608e65e718a3464a594e6dfca0351dfed19ac2445joshualitt } 127ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt 128bde428513ff3bd98a3d4f1c66ac779411233f817Brian Salomon /** 129d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon * This is called to notify the op that it has been recorded into a GrOpList. Ops can use this 130d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon * to begin preparations for the flush of the op list. Note that the op still may either be 131d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon * combined into another op or have another op combined into it via combineIfPossible() after 132d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon * this call is made. 133d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon */ 134d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon virtual void wasRecorded() {} 135d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon 136d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon /** 137bde428513ff3bd98a3d4f1c66ac779411233f817Brian Salomon * Called prior to executing. The op should perform any resource creation or data transfers 138bde428513ff3bd98a3d4f1c66ac779411233f817Brian Salomon * necessary before execute() is called. 139bde428513ff3bd98a3d4f1c66ac779411233f817Brian Salomon */ 140742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon void prepare(GrOpFlushState* state) { this->onPrepare(state); } 1415346983b2e0726b4009cc546b01c58a8919e6c36bsalomon 14225a880960a9a689a745a01071ecba3fe494b5940Brian Salomon /** Issues the op's commands to GrGpu. */ 1439e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon void execute(GrOpFlushState* state) { this->onExecute(state); } 1445346983b2e0726b4009cc546b01c58a8919e6c36bsalomon 14525a880960a9a689a745a01071ecba3fe494b5940Brian Salomon /** Used for spewing information about ops when debugging. */ 14644fbc79e069c28103a44387d11c62e049ef2967drobertphillips virtual SkString dumpInfo() const { 14744fbc79e069c28103a44387d11c62e049ef2967drobertphillips SkString string; 14825a880960a9a689a745a01071ecba3fe494b5940Brian Salomon string.appendf("OpBounds: [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n", 14944fbc79e069c28103a44387d11c62e049ef2967drobertphillips fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom); 15044fbc79e069c28103a44387d11c62e049ef2967drobertphillips return string; 15144fbc79e069c28103a44387d11c62e049ef2967drobertphillips } 1525346983b2e0726b4009cc546b01c58a8919e6c36bsalomon 1534d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualittprotected: 15488cf17d099085b8085ab11571b5094163dbb2c84bsalomon /** 15525a880960a9a689a745a01071ecba3fe494b5940Brian Salomon * Indicates that the op will produce geometry that extends beyond its bounds for the 15688cf17d099085b8085ab11571b5094163dbb2c84bsalomon * purpose of ensuring that the fragment shader runs on partially covered pixels for 15788cf17d099085b8085ab11571b5094163dbb2c84bsalomon * non-MSAA antialiasing. 15888cf17d099085b8085ab11571b5094163dbb2c84bsalomon */ 15988cf17d099085b8085ab11571b5094163dbb2c84bsalomon enum class HasAABloat { 16088cf17d099085b8085ab11571b5094163dbb2c84bsalomon kYes, 16188cf17d099085b8085ab11571b5094163dbb2c84bsalomon kNo 16288cf17d099085b8085ab11571b5094163dbb2c84bsalomon }; 16388cf17d099085b8085ab11571b5094163dbb2c84bsalomon /** 16425a880960a9a689a745a01071ecba3fe494b5940Brian Salomon * Indicates that the geometry represented by the op has zero area (e.g. it is hairline or 16525a880960a9a689a745a01071ecba3fe494b5940Brian Salomon * points). 16688cf17d099085b8085ab11571b5094163dbb2c84bsalomon */ 16788cf17d099085b8085ab11571b5094163dbb2c84bsalomon enum class IsZeroArea { 16888cf17d099085b8085ab11571b5094163dbb2c84bsalomon kYes, 16988cf17d099085b8085ab11571b5094163dbb2c84bsalomon kNo 17088cf17d099085b8085ab11571b5094163dbb2c84bsalomon }; 17188cf17d099085b8085ab11571b5094163dbb2c84bsalomon void setBounds(const SkRect& newBounds, HasAABloat aabloat, IsZeroArea zeroArea) { 17288cf17d099085b8085ab11571b5094163dbb2c84bsalomon fBounds = newBounds; 17388cf17d099085b8085ab11571b5094163dbb2c84bsalomon this->setBoundsFlags(aabloat, zeroArea); 17488cf17d099085b8085ab11571b5094163dbb2c84bsalomon } 17588cf17d099085b8085ab11571b5094163dbb2c84bsalomon void setTransformedBounds(const SkRect& srcBounds, const SkMatrix& m, 17688cf17d099085b8085ab11571b5094163dbb2c84bsalomon HasAABloat aabloat, IsZeroArea zeroArea) { 17788cf17d099085b8085ab11571b5094163dbb2c84bsalomon m.mapRect(&fBounds, srcBounds); 17888cf17d099085b8085ab11571b5094163dbb2c84bsalomon this->setBoundsFlags(aabloat, zeroArea); 17988cf17d099085b8085ab11571b5094163dbb2c84bsalomon } 18099c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt 18125a880960a9a689a745a01071ecba3fe494b5940Brian Salomon void joinBounds(const GrOp& that) { 18288cf17d099085b8085ab11571b5094163dbb2c84bsalomon if (that.hasAABloat()) { 18388cf17d099085b8085ab11571b5094163dbb2c84bsalomon fBoundsFlags |= kAABloat_BoundsFlag; 18488cf17d099085b8085ab11571b5094163dbb2c84bsalomon } 18588cf17d099085b8085ab11571b5094163dbb2c84bsalomon if (that.hasZeroArea()) { 18688cf17d099085b8085ab11571b5094163dbb2c84bsalomon fBoundsFlags |= kZeroArea_BoundsFlag; 18788cf17d099085b8085ab11571b5094163dbb2c84bsalomon } 18888cf17d099085b8085ab11571b5094163dbb2c84bsalomon return fBounds.joinPossiblyEmptyRect(that.fBounds); 18999c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt } 19099c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt 19125a880960a9a689a745a01071ecba3fe494b5940Brian Salomon void replaceBounds(const GrOp& that) { 19288cf17d099085b8085ab11571b5094163dbb2c84bsalomon fBounds = that.fBounds; 19388cf17d099085b8085ab11571b5094163dbb2c84bsalomon fBoundsFlags = that.fBoundsFlags; 19488cf17d099085b8085ab11571b5094163dbb2c84bsalomon } 1951b55a963a2374a14bb82eb887bb99ee91680f0ebreed 19625a880960a9a689a745a01071ecba3fe494b5940Brian Salomon static uint32_t GenOpClassID() { return GenID(&gCurrOpClassID); } 197abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon 198abd30f54b7ff1704a8930c4307ea242d09425d02bsalomonprivate: 19925a880960a9a689a745a01071ecba3fe494b5940Brian Salomon virtual bool onCombineIfPossible(GrOp*, const GrCaps& caps) = 0; 200abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon 201742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon virtual void onPrepare(GrOpFlushState*) = 0; 2029e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon virtual void onExecute(GrOpFlushState*) = 0; 2035346983b2e0726b4009cc546b01c58a8919e6c36bsalomon 204abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon static uint32_t GenID(int32_t* idCounter) { 2051b55a963a2374a14bb82eb887bb99ee91680f0ebreed // The atomic inc returns the old value not the incremented value. So we add 206abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon // 1 to the returned value. 207abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon uint32_t id = static_cast<uint32_t>(sk_atomic_inc(idCounter)) + 1; 208abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon if (!id) { 20925a880960a9a689a745a01071ecba3fe494b5940Brian Salomon SkFAIL("This should never wrap as it should only be called once for each GrOp " 210abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon "subclass."); 211abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon } 212abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon return id; 213abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon } 214abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon 21588cf17d099085b8085ab11571b5094163dbb2c84bsalomon void setBoundsFlags(HasAABloat aabloat, IsZeroArea zeroArea) { 21688cf17d099085b8085ab11571b5094163dbb2c84bsalomon fBoundsFlags = 0; 21788cf17d099085b8085ab11571b5094163dbb2c84bsalomon fBoundsFlags |= (HasAABloat::kYes == aabloat) ? kAABloat_BoundsFlag : 0; 21888cf17d099085b8085ab11571b5094163dbb2c84bsalomon fBoundsFlags |= (IsZeroArea ::kYes == zeroArea) ? kZeroArea_BoundsFlag : 0; 21988cf17d099085b8085ab11571b5094163dbb2c84bsalomon } 22088cf17d099085b8085ab11571b5094163dbb2c84bsalomon 221abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon enum { 22225a880960a9a689a745a01071ecba3fe494b5940Brian Salomon kIllegalOpID = 0, 223abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon }; 224abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon 22588cf17d099085b8085ab11571b5094163dbb2c84bsalomon enum BoundsFlags { 22688cf17d099085b8085ab11571b5094163dbb2c84bsalomon kAABloat_BoundsFlag = 0x1, 22788cf17d099085b8085ab11571b5094163dbb2c84bsalomon kZeroArea_BoundsFlag = 0x2, 22888cf17d099085b8085ab11571b5094163dbb2c84bsalomon SkDEBUGCODE(kUninitialized_BoundsFlag = 0x4) 22988cf17d099085b8085ab11571b5094163dbb2c84bsalomon }; 23088cf17d099085b8085ab11571b5094163dbb2c84bsalomon 23188cf17d099085b8085ab11571b5094163dbb2c84bsalomon const uint16_t fClassID; 23288cf17d099085b8085ab11571b5094163dbb2c84bsalomon uint16_t fBoundsFlags; 23388cf17d099085b8085ab11571b5094163dbb2c84bsalomon 23425a880960a9a689a745a01071ecba3fe494b5940Brian Salomon static uint32_t GenOpID() { return GenID(&gCurrOpUniqueID); } 23508e65e718a3464a594e6dfca0351dfed19ac2445joshualitt mutable uint32_t fUniqueID; 23688cf17d099085b8085ab11571b5094163dbb2c84bsalomon SkRect fBounds; 23788cf17d099085b8085ab11571b5094163dbb2c84bsalomon 23825a880960a9a689a745a01071ecba3fe494b5940Brian Salomon static int32_t gCurrOpUniqueID; 23925a880960a9a689a745a01071ecba3fe494b5940Brian Salomon static int32_t gCurrOpClassID; 240abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon}; 241abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon 2424d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt#endif 243