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"
1454d212e1bfaea0be88c3c40820d0b1ae0daebecfBrian Salomon#include "GrXferProcessor.h"
1588cf17d099085b8085ab11571b5094163dbb2c84bsalomon#include "SkMatrix.h"
1616b991390bb988b194a868ab8de66db4c21c7c13bsalomon#include "SkRect.h"
175346983b2e0726b4009cc546b01c58a8919e6c36bsalomon#include "SkString.h"
184d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
192c4bd0798e929acb9663668985eabe74d7378c46bungeman#include <new>
202c4bd0798e929acb9663668985eabe74d7378c46bungeman
2116b991390bb988b194a868ab8de66db4c21c7c13bsalomonclass GrCaps;
229cb6340a62a5d748e4189d50e51fa527c8c80c03egdanielclass GrGpuCommandBuffer;
23742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomonclass GrOpFlushState;
24e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillipsclass GrRenderTargetOpList;
254d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
26abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon/**
2753e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon * GrOp is the base class for all Ganesh deferred GPU operations. To facilitate reordering and to
2853e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon * minimize draw calls, Ganesh does not generate geometry inline with draw calls. Instead, it
2953e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon * captures the arguments to the draw and then generates the geometry when flushing. This gives GrOp
3053e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon * subclasses complete freedom to decide how/when to combine in order to produce fewer draw calls
3153e4c3c0da40b58638d05e0f753ab6d450b961f5Brian Salomon * and minimize state changes.
324d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt *
3325a880960a9a689a745a01071ecba3fe494b5940Brian Salomon * Ops of the same subclass may be merged using combineIfPossible. When two ops merge, one
3425a880960a9a689a745a01071ecba3fe494b5940Brian Salomon * takes on the union of the data and the other is left empty. The merged op becomes responsible
3525a880960a9a689a745a01071ecba3fe494b5940Brian Salomon * for drawing the data from both the original ops.
364d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt *
374d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * If there are any possible optimizations which might require knowing more about the full state of
3825a880960a9a689a745a01071ecba3fe494b5940Brian Salomon * the draw, e.g. whether or not the GrOp is allowed to tweak alpha for coverage, then this
3925a880960a9a689a745a01071ecba3fe494b5940Brian Salomon * information will be communicated to the GrOp prior to geometry generation.
40db4758c75fdd30ef58096c685e2d749aacaf3d92bsalomon *
4125a880960a9a689a745a01071ecba3fe494b5940Brian Salomon * The bounds of the op must contain all the vertices in device space *irrespective* of the clip.
42db4758c75fdd30ef58096c685e2d749aacaf3d92bsalomon * The bounds are used in determining which clip elements must be applied and thus the bounds cannot
43db4758c75fdd30ef58096c685e2d749aacaf3d92bsalomon * in turn depend upon the clip.
444d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt */
4525a880960a9a689a745a01071ecba3fe494b5940Brian Salomon#define GR_OP_SPEW 0
4625a880960a9a689a745a01071ecba3fe494b5940Brian Salomon#if GR_OP_SPEW
4725a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    #define GrOP_SPEW(code) code
4825a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    #define GrOP_INFO(...) SkDebugf(__VA_ARGS__)
49ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt#else
5025a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    #define GrOP_SPEW(code)
5125a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    #define GrOP_INFO(...)
52ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt#endif
534d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
541b55a963a2374a14bb82eb887bb99ee91680f0ebreed// A helper macro to generate a class static id
5525a880960a9a689a745a01071ecba3fe494b5940Brian Salomon#define DEFINE_OP_CLASS_ID \
561b55a963a2374a14bb82eb887bb99ee91680f0ebreed    static uint32_t ClassID() { \
5725a880960a9a689a745a01071ecba3fe494b5940Brian Salomon        static uint32_t kClassID = GenOpClassID(); \
581b55a963a2374a14bb82eb887bb99ee91680f0ebreed        return kClassID; \
591b55a963a2374a14bb82eb887bb99ee91680f0ebreed    }
601b55a963a2374a14bb82eb887bb99ee91680f0ebreed
61f8334781914363caf537f22f012fcd5c03c60dadBrian Salomonclass GrOp : private SkNoncopyable {
624d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualittpublic:
6325a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    GrOp(uint32_t classID);
6425a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    virtual ~GrOp();
654d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
664d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    virtual const char* name() const = 0;
674d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
6825a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    bool combineIfPossible(GrOp* that, const GrCaps& caps) {
694d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt        if (this->classID() != that->classID()) {
704d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt            return false;
714d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt        }
724d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
73cb02b38b2c48bfde333ce3c699dd0451e2d867fabsalomon        return this->onCombineIfPossible(that, caps);
744d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    }
754d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
7688cf17d099085b8085ab11571b5094163dbb2c84bsalomon    const SkRect& bounds() const {
7788cf17d099085b8085ab11571b5094163dbb2c84bsalomon        SkASSERT(kUninitialized_BoundsFlag != fBoundsFlags);
7888cf17d099085b8085ab11571b5094163dbb2c84bsalomon        return fBounds;
7988cf17d099085b8085ab11571b5094163dbb2c84bsalomon    }
8088cf17d099085b8085ab11571b5094163dbb2c84bsalomon
819e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon    void setClippedBounds(const SkRect& clippedBounds) {
829e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon        fBounds = clippedBounds;
839e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon        // The clipped bounds already incorporate any effect of the bounds flags.
849e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon        fBoundsFlags = 0;
859e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon    }
869e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon
8788cf17d099085b8085ab11571b5094163dbb2c84bsalomon    bool hasAABloat() const {
8888cf17d099085b8085ab11571b5094163dbb2c84bsalomon        SkASSERT(fBoundsFlags != kUninitialized_BoundsFlag);
8988cf17d099085b8085ab11571b5094163dbb2c84bsalomon        return SkToBool(fBoundsFlags & kAABloat_BoundsFlag);
9088cf17d099085b8085ab11571b5094163dbb2c84bsalomon    }
9188cf17d099085b8085ab11571b5094163dbb2c84bsalomon
9288cf17d099085b8085ab11571b5094163dbb2c84bsalomon    bool hasZeroArea() const {
9388cf17d099085b8085ab11571b5094163dbb2c84bsalomon        SkASSERT(fBoundsFlags != kUninitialized_BoundsFlag);
9488cf17d099085b8085ab11571b5094163dbb2c84bsalomon        return SkToBool(fBoundsFlags & kZeroArea_BoundsFlag);
9588cf17d099085b8085ab11571b5094163dbb2c84bsalomon    }
9699c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt
974d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    void* operator new(size_t size);
984d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    void operator delete(void* target);
994d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
1004d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    void* operator new(size_t size, void* placement) {
1014d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt        return ::operator new(size, placement);
1024d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    }
1034d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    void operator delete(void* target, void* placement) {
1044d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt        ::operator delete(target, placement);
1054d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    }
1064d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
1074d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    /**
10825a880960a9a689a745a01071ecba3fe494b5940Brian Salomon     * Helper for safely down-casting to a GrOp subclass
109abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon     */
1101b55a963a2374a14bb82eb887bb99ee91680f0ebreed    template <typename T> const T& cast() const {
1111b55a963a2374a14bb82eb887bb99ee91680f0ebreed        SkASSERT(T::ClassID() == this->classID());
1121b55a963a2374a14bb82eb887bb99ee91680f0ebreed        return *static_cast<const T*>(this);
1131b55a963a2374a14bb82eb887bb99ee91680f0ebreed    }
1141b55a963a2374a14bb82eb887bb99ee91680f0ebreed
1151b55a963a2374a14bb82eb887bb99ee91680f0ebreed    template <typename T> T* cast() {
1161b55a963a2374a14bb82eb887bb99ee91680f0ebreed        SkASSERT(T::ClassID() == this->classID());
1171b55a963a2374a14bb82eb887bb99ee91680f0ebreed        return static_cast<T*>(this);
1181b55a963a2374a14bb82eb887bb99ee91680f0ebreed    }
1194d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
12025a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    uint32_t classID() const { SkASSERT(kIllegalOpID != fClassID); return fClassID; }
1214d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
12208e65e718a3464a594e6dfca0351dfed19ac2445joshualitt    // We lazily initialize the uniqueID because currently the only user is GrAuditTrail
1239d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    uint32_t uniqueID() const {
12425a880960a9a689a745a01071ecba3fe494b5940Brian Salomon        if (kIllegalOpID == fUniqueID) {
12525a880960a9a689a745a01071ecba3fe494b5940Brian Salomon            fUniqueID = GenOpID();
12608e65e718a3464a594e6dfca0351dfed19ac2445joshualitt        }
1279d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        return fUniqueID;
12808e65e718a3464a594e6dfca0351dfed19ac2445joshualitt    }
129ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt
130bde428513ff3bd98a3d4f1c66ac779411233f817Brian Salomon    /**
131d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon     * This is called to notify the op that it has been recorded into a GrOpList. Ops can use this
132d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon     * to begin preparations for the flush of the op list. Note that the op still may either be
133d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon     * combined into another op or have another op combined into it via combineIfPossible() after
134d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon     * this call is made.
135d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon     */
136e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips    virtual void wasRecorded(GrRenderTargetOpList*) {}
137d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon
138d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon    /**
139bde428513ff3bd98a3d4f1c66ac779411233f817Brian Salomon     * Called prior to executing. The op should perform any resource creation or data transfers
140bde428513ff3bd98a3d4f1c66ac779411233f817Brian Salomon     * necessary before execute() is called.
141bde428513ff3bd98a3d4f1c66ac779411233f817Brian Salomon     */
142742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon    void prepare(GrOpFlushState* state) { this->onPrepare(state); }
1435346983b2e0726b4009cc546b01c58a8919e6c36bsalomon
14425a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    /** Issues the op's commands to GrGpu. */
1459e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon    void execute(GrOpFlushState* state) { this->onExecute(state); }
1465346983b2e0726b4009cc546b01c58a8919e6c36bsalomon
14725a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    /** Used for spewing information about ops when debugging. */
14844fbc79e069c28103a44387d11c62e049ef2967drobertphillips    virtual SkString dumpInfo() const {
14944fbc79e069c28103a44387d11c62e049ef2967drobertphillips        SkString string;
15025a880960a9a689a745a01071ecba3fe494b5940Brian Salomon        string.appendf("OpBounds: [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
15144fbc79e069c28103a44387d11c62e049ef2967drobertphillips                       fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom);
15244fbc79e069c28103a44387d11c62e049ef2967drobertphillips        return string;
15344fbc79e069c28103a44387d11c62e049ef2967drobertphillips    }
1545346983b2e0726b4009cc546b01c58a8919e6c36bsalomon
155178ce3eddd326feee608af65cdeedb08e1af91c3Robert Phillips    virtual bool needsCommandBufferIsolation() const { return false; }
156178ce3eddd326feee608af65cdeedb08e1af91c3Robert Phillips
1574d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualittprotected:
15888cf17d099085b8085ab11571b5094163dbb2c84bsalomon    /**
15925a880960a9a689a745a01071ecba3fe494b5940Brian Salomon     * Indicates that the op will produce geometry that extends beyond its bounds for the
16088cf17d099085b8085ab11571b5094163dbb2c84bsalomon     * purpose of ensuring that the fragment shader runs on partially covered pixels for
16188cf17d099085b8085ab11571b5094163dbb2c84bsalomon     * non-MSAA antialiasing.
16288cf17d099085b8085ab11571b5094163dbb2c84bsalomon     */
16388cf17d099085b8085ab11571b5094163dbb2c84bsalomon    enum class HasAABloat {
16488cf17d099085b8085ab11571b5094163dbb2c84bsalomon        kYes,
16588cf17d099085b8085ab11571b5094163dbb2c84bsalomon        kNo
16688cf17d099085b8085ab11571b5094163dbb2c84bsalomon    };
16788cf17d099085b8085ab11571b5094163dbb2c84bsalomon    /**
16825a880960a9a689a745a01071ecba3fe494b5940Brian Salomon     * Indicates that the geometry represented by the op has zero area (e.g. it is hairline or
16925a880960a9a689a745a01071ecba3fe494b5940Brian Salomon     * points).
17088cf17d099085b8085ab11571b5094163dbb2c84bsalomon     */
17188cf17d099085b8085ab11571b5094163dbb2c84bsalomon    enum class IsZeroArea {
17288cf17d099085b8085ab11571b5094163dbb2c84bsalomon        kYes,
17388cf17d099085b8085ab11571b5094163dbb2c84bsalomon        kNo
17488cf17d099085b8085ab11571b5094163dbb2c84bsalomon    };
17588cf17d099085b8085ab11571b5094163dbb2c84bsalomon    void setBounds(const SkRect& newBounds, HasAABloat aabloat, IsZeroArea zeroArea) {
17688cf17d099085b8085ab11571b5094163dbb2c84bsalomon        fBounds = newBounds;
17788cf17d099085b8085ab11571b5094163dbb2c84bsalomon        this->setBoundsFlags(aabloat, zeroArea);
17888cf17d099085b8085ab11571b5094163dbb2c84bsalomon    }
17988cf17d099085b8085ab11571b5094163dbb2c84bsalomon    void setTransformedBounds(const SkRect& srcBounds, const SkMatrix& m,
18088cf17d099085b8085ab11571b5094163dbb2c84bsalomon                              HasAABloat aabloat, IsZeroArea zeroArea) {
18188cf17d099085b8085ab11571b5094163dbb2c84bsalomon        m.mapRect(&fBounds, srcBounds);
18288cf17d099085b8085ab11571b5094163dbb2c84bsalomon        this->setBoundsFlags(aabloat, zeroArea);
18388cf17d099085b8085ab11571b5094163dbb2c84bsalomon    }
18499c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt
18525a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    void joinBounds(const GrOp& that) {
18688cf17d099085b8085ab11571b5094163dbb2c84bsalomon        if (that.hasAABloat()) {
18788cf17d099085b8085ab11571b5094163dbb2c84bsalomon            fBoundsFlags |= kAABloat_BoundsFlag;
18888cf17d099085b8085ab11571b5094163dbb2c84bsalomon        }
18988cf17d099085b8085ab11571b5094163dbb2c84bsalomon        if (that.hasZeroArea()) {
19088cf17d099085b8085ab11571b5094163dbb2c84bsalomon            fBoundsFlags |= kZeroArea_BoundsFlag;
19188cf17d099085b8085ab11571b5094163dbb2c84bsalomon        }
19288cf17d099085b8085ab11571b5094163dbb2c84bsalomon        return fBounds.joinPossiblyEmptyRect(that.fBounds);
19399c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt    }
19499c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt
19525a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    void replaceBounds(const GrOp& that) {
19688cf17d099085b8085ab11571b5094163dbb2c84bsalomon        fBounds = that.fBounds;
19788cf17d099085b8085ab11571b5094163dbb2c84bsalomon        fBoundsFlags = that.fBoundsFlags;
19888cf17d099085b8085ab11571b5094163dbb2c84bsalomon    }
1991b55a963a2374a14bb82eb887bb99ee91680f0ebreed
20025a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    static uint32_t GenOpClassID() { return GenID(&gCurrOpClassID); }
201abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon
202abd30f54b7ff1704a8930c4307ea242d09425d02bsalomonprivate:
20325a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    virtual bool onCombineIfPossible(GrOp*, const GrCaps& caps) = 0;
204abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon
205742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon    virtual void onPrepare(GrOpFlushState*) = 0;
2069e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon    virtual void onExecute(GrOpFlushState*) = 0;
2075346983b2e0726b4009cc546b01c58a8919e6c36bsalomon
208abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon    static uint32_t GenID(int32_t* idCounter) {
2091b55a963a2374a14bb82eb887bb99ee91680f0ebreed        // The atomic inc returns the old value not the incremented value. So we add
210abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        // 1 to the returned value.
211abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        uint32_t id = static_cast<uint32_t>(sk_atomic_inc(idCounter)) + 1;
212abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        if (!id) {
21325a880960a9a689a745a01071ecba3fe494b5940Brian Salomon            SkFAIL("This should never wrap as it should only be called once for each GrOp "
214abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon                   "subclass.");
215abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        }
216abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        return id;
217abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon    }
218abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon
21988cf17d099085b8085ab11571b5094163dbb2c84bsalomon    void setBoundsFlags(HasAABloat aabloat, IsZeroArea zeroArea) {
22088cf17d099085b8085ab11571b5094163dbb2c84bsalomon        fBoundsFlags = 0;
22188cf17d099085b8085ab11571b5094163dbb2c84bsalomon        fBoundsFlags |= (HasAABloat::kYes == aabloat) ? kAABloat_BoundsFlag : 0;
22288cf17d099085b8085ab11571b5094163dbb2c84bsalomon        fBoundsFlags |= (IsZeroArea ::kYes == zeroArea) ? kZeroArea_BoundsFlag : 0;
22388cf17d099085b8085ab11571b5094163dbb2c84bsalomon    }
22488cf17d099085b8085ab11571b5094163dbb2c84bsalomon
225abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon    enum {
22625a880960a9a689a745a01071ecba3fe494b5940Brian Salomon        kIllegalOpID = 0,
227abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon    };
228abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon
22988cf17d099085b8085ab11571b5094163dbb2c84bsalomon    enum BoundsFlags {
23088cf17d099085b8085ab11571b5094163dbb2c84bsalomon        kAABloat_BoundsFlag                     = 0x1,
23188cf17d099085b8085ab11571b5094163dbb2c84bsalomon        kZeroArea_BoundsFlag                    = 0x2,
23288cf17d099085b8085ab11571b5094163dbb2c84bsalomon        SkDEBUGCODE(kUninitialized_BoundsFlag   = 0x4)
23388cf17d099085b8085ab11571b5094163dbb2c84bsalomon    };
23488cf17d099085b8085ab11571b5094163dbb2c84bsalomon
23588cf17d099085b8085ab11571b5094163dbb2c84bsalomon    const uint16_t                      fClassID;
23688cf17d099085b8085ab11571b5094163dbb2c84bsalomon    uint16_t                            fBoundsFlags;
23788cf17d099085b8085ab11571b5094163dbb2c84bsalomon
23825a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    static uint32_t GenOpID() { return GenID(&gCurrOpUniqueID); }
23908e65e718a3464a594e6dfca0351dfed19ac2445joshualitt    mutable uint32_t                    fUniqueID;
24088cf17d099085b8085ab11571b5094163dbb2c84bsalomon    SkRect                              fBounds;
24188cf17d099085b8085ab11571b5094163dbb2c84bsalomon
24225a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    static int32_t                      gCurrOpUniqueID;
24325a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    static int32_t                      gCurrOpClassID;
244abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon};
245abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon
2464d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt#endif
247