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
68b493eebca14aefbd5f22fb5d45ba978b19db4b18Robert Phillips    typedef std::function<void(GrSurfaceProxy*)> VisitProxyFunc;
69b493eebca14aefbd5f22fb5d45ba978b19db4b18Robert Phillips
70f1748f5a9238a0d3e189d50fc5e57ae8b8ec087cRobert Phillips    virtual void visitProxies(const VisitProxyFunc&) const {
71b493eebca14aefbd5f22fb5d45ba978b19db4b18Robert Phillips        // This default implementation assumes the op has no proxies
72b493eebca14aefbd5f22fb5d45ba978b19db4b18Robert Phillips    }
73b493eebca14aefbd5f22fb5d45ba978b19db4b18Robert Phillips
7425a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    bool combineIfPossible(GrOp* that, const GrCaps& caps) {
754d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt        if (this->classID() != that->classID()) {
764d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt            return false;
774d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt        }
784d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
79cb02b38b2c48bfde333ce3c699dd0451e2d867fabsalomon        return this->onCombineIfPossible(that, caps);
804d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    }
814d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
8288cf17d099085b8085ab11571b5094163dbb2c84bsalomon    const SkRect& bounds() const {
8388cf17d099085b8085ab11571b5094163dbb2c84bsalomon        SkASSERT(kUninitialized_BoundsFlag != fBoundsFlags);
8488cf17d099085b8085ab11571b5094163dbb2c84bsalomon        return fBounds;
8588cf17d099085b8085ab11571b5094163dbb2c84bsalomon    }
8688cf17d099085b8085ab11571b5094163dbb2c84bsalomon
879e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon    void setClippedBounds(const SkRect& clippedBounds) {
889e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon        fBounds = clippedBounds;
899e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon        // The clipped bounds already incorporate any effect of the bounds flags.
909e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon        fBoundsFlags = 0;
919e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon    }
929e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon
9388cf17d099085b8085ab11571b5094163dbb2c84bsalomon    bool hasAABloat() const {
9488cf17d099085b8085ab11571b5094163dbb2c84bsalomon        SkASSERT(fBoundsFlags != kUninitialized_BoundsFlag);
9588cf17d099085b8085ab11571b5094163dbb2c84bsalomon        return SkToBool(fBoundsFlags & kAABloat_BoundsFlag);
9688cf17d099085b8085ab11571b5094163dbb2c84bsalomon    }
9788cf17d099085b8085ab11571b5094163dbb2c84bsalomon
9888cf17d099085b8085ab11571b5094163dbb2c84bsalomon    bool hasZeroArea() const {
9988cf17d099085b8085ab11571b5094163dbb2c84bsalomon        SkASSERT(fBoundsFlags != kUninitialized_BoundsFlag);
10088cf17d099085b8085ab11571b5094163dbb2c84bsalomon        return SkToBool(fBoundsFlags & kZeroArea_BoundsFlag);
10188cf17d099085b8085ab11571b5094163dbb2c84bsalomon    }
10299c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt
1034d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    void* operator new(size_t size);
1044d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    void operator delete(void* target);
1054d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
1064d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    void* operator new(size_t size, void* placement) {
1074d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt        return ::operator new(size, placement);
1084d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    }
1094d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    void operator delete(void* target, void* placement) {
1104d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt        ::operator delete(target, placement);
1114d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    }
1124d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
1134d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    /**
11425a880960a9a689a745a01071ecba3fe494b5940Brian Salomon     * Helper for safely down-casting to a GrOp subclass
115abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon     */
1161b55a963a2374a14bb82eb887bb99ee91680f0ebreed    template <typename T> const T& cast() const {
1171b55a963a2374a14bb82eb887bb99ee91680f0ebreed        SkASSERT(T::ClassID() == this->classID());
1181b55a963a2374a14bb82eb887bb99ee91680f0ebreed        return *static_cast<const T*>(this);
1191b55a963a2374a14bb82eb887bb99ee91680f0ebreed    }
1201b55a963a2374a14bb82eb887bb99ee91680f0ebreed
1211b55a963a2374a14bb82eb887bb99ee91680f0ebreed    template <typename T> T* cast() {
1221b55a963a2374a14bb82eb887bb99ee91680f0ebreed        SkASSERT(T::ClassID() == this->classID());
1231b55a963a2374a14bb82eb887bb99ee91680f0ebreed        return static_cast<T*>(this);
1241b55a963a2374a14bb82eb887bb99ee91680f0ebreed    }
1254d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
12625a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    uint32_t classID() const { SkASSERT(kIllegalOpID != fClassID); return fClassID; }
1274d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
12808e65e718a3464a594e6dfca0351dfed19ac2445joshualitt    // We lazily initialize the uniqueID because currently the only user is GrAuditTrail
1299d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary    uint32_t uniqueID() const {
13025a880960a9a689a745a01071ecba3fe494b5940Brian Salomon        if (kIllegalOpID == fUniqueID) {
13125a880960a9a689a745a01071ecba3fe494b5940Brian Salomon            fUniqueID = GenOpID();
13208e65e718a3464a594e6dfca0351dfed19ac2445joshualitt        }
1339d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary        return fUniqueID;
13408e65e718a3464a594e6dfca0351dfed19ac2445joshualitt    }
135ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt
136bde428513ff3bd98a3d4f1c66ac779411233f817Brian Salomon    /**
137d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon     * This is called to notify the op that it has been recorded into a GrOpList. Ops can use this
138d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon     * to begin preparations for the flush of the op list. Note that the op still may either be
139d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon     * combined into another op or have another op combined into it via combineIfPossible() after
140d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon     * this call is made.
141d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon     */
142e3302dfb81865051ad19cd1c91e2ec3a27df3417Robert Phillips    virtual void wasRecorded(GrRenderTargetOpList*) {}
143d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon
144d543e0a835002cc423de0d09c86eea99a0c0a2baBrian Salomon    /**
145bde428513ff3bd98a3d4f1c66ac779411233f817Brian Salomon     * Called prior to executing. The op should perform any resource creation or data transfers
146bde428513ff3bd98a3d4f1c66ac779411233f817Brian Salomon     * necessary before execute() is called.
147bde428513ff3bd98a3d4f1c66ac779411233f817Brian Salomon     */
148742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon    void prepare(GrOpFlushState* state) { this->onPrepare(state); }
1495346983b2e0726b4009cc546b01c58a8919e6c36bsalomon
15025a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    /** Issues the op's commands to GrGpu. */
1519e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon    void execute(GrOpFlushState* state) { this->onExecute(state); }
1525346983b2e0726b4009cc546b01c58a8919e6c36bsalomon
15325a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    /** Used for spewing information about ops when debugging. */
15444fbc79e069c28103a44387d11c62e049ef2967drobertphillips    virtual SkString dumpInfo() const {
15544fbc79e069c28103a44387d11c62e049ef2967drobertphillips        SkString string;
15625a880960a9a689a745a01071ecba3fe494b5940Brian Salomon        string.appendf("OpBounds: [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
15744fbc79e069c28103a44387d11c62e049ef2967drobertphillips                       fBounds.fLeft, fBounds.fTop, fBounds.fRight, fBounds.fBottom);
15844fbc79e069c28103a44387d11c62e049ef2967drobertphillips        return string;
15944fbc79e069c28103a44387d11c62e049ef2967drobertphillips    }
1605346983b2e0726b4009cc546b01c58a8919e6c36bsalomon
1614d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualittprotected:
16288cf17d099085b8085ab11571b5094163dbb2c84bsalomon    /**
16325a880960a9a689a745a01071ecba3fe494b5940Brian Salomon     * Indicates that the op will produce geometry that extends beyond its bounds for the
16488cf17d099085b8085ab11571b5094163dbb2c84bsalomon     * purpose of ensuring that the fragment shader runs on partially covered pixels for
16588cf17d099085b8085ab11571b5094163dbb2c84bsalomon     * non-MSAA antialiasing.
16688cf17d099085b8085ab11571b5094163dbb2c84bsalomon     */
1673b51df12119d82661ed64efa87d5ccfe2d32f625Chris Dalton    enum class HasAABloat : bool {
1683b51df12119d82661ed64efa87d5ccfe2d32f625Chris Dalton        kNo = false,
1693b51df12119d82661ed64efa87d5ccfe2d32f625Chris Dalton        kYes = true
17088cf17d099085b8085ab11571b5094163dbb2c84bsalomon    };
17188cf17d099085b8085ab11571b5094163dbb2c84bsalomon    /**
17225a880960a9a689a745a01071ecba3fe494b5940Brian Salomon     * Indicates that the geometry represented by the op has zero area (e.g. it is hairline or
17325a880960a9a689a745a01071ecba3fe494b5940Brian Salomon     * points).
17488cf17d099085b8085ab11571b5094163dbb2c84bsalomon     */
1753b51df12119d82661ed64efa87d5ccfe2d32f625Chris Dalton    enum class IsZeroArea : bool {
1763b51df12119d82661ed64efa87d5ccfe2d32f625Chris Dalton        kNo = false,
1773b51df12119d82661ed64efa87d5ccfe2d32f625Chris Dalton        kYes = true
17888cf17d099085b8085ab11571b5094163dbb2c84bsalomon    };
17965a88fadab72abd104fdf4cc4a97488b2e901c60Robert Phillips
18088cf17d099085b8085ab11571b5094163dbb2c84bsalomon    void setBounds(const SkRect& newBounds, HasAABloat aabloat, IsZeroArea zeroArea) {
18188cf17d099085b8085ab11571b5094163dbb2c84bsalomon        fBounds = newBounds;
18288cf17d099085b8085ab11571b5094163dbb2c84bsalomon        this->setBoundsFlags(aabloat, zeroArea);
18388cf17d099085b8085ab11571b5094163dbb2c84bsalomon    }
18488cf17d099085b8085ab11571b5094163dbb2c84bsalomon    void setTransformedBounds(const SkRect& srcBounds, const SkMatrix& m,
18588cf17d099085b8085ab11571b5094163dbb2c84bsalomon                              HasAABloat aabloat, IsZeroArea zeroArea) {
18688cf17d099085b8085ab11571b5094163dbb2c84bsalomon        m.mapRect(&fBounds, srcBounds);
18788cf17d099085b8085ab11571b5094163dbb2c84bsalomon        this->setBoundsFlags(aabloat, zeroArea);
18888cf17d099085b8085ab11571b5094163dbb2c84bsalomon    }
18965a88fadab72abd104fdf4cc4a97488b2e901c60Robert Phillips    void makeFullScreen(GrSurfaceProxy* proxy) {
19065a88fadab72abd104fdf4cc4a97488b2e901c60Robert Phillips        this->setBounds(SkRect::MakeIWH(proxy->width(), proxy->height()),
19165a88fadab72abd104fdf4cc4a97488b2e901c60Robert Phillips                        HasAABloat::kNo, IsZeroArea::kNo);
19265a88fadab72abd104fdf4cc4a97488b2e901c60Robert Phillips    }
19399c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt
19425a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    void joinBounds(const GrOp& that) {
19588cf17d099085b8085ab11571b5094163dbb2c84bsalomon        if (that.hasAABloat()) {
19688cf17d099085b8085ab11571b5094163dbb2c84bsalomon            fBoundsFlags |= kAABloat_BoundsFlag;
19788cf17d099085b8085ab11571b5094163dbb2c84bsalomon        }
19888cf17d099085b8085ab11571b5094163dbb2c84bsalomon        if (that.hasZeroArea()) {
19988cf17d099085b8085ab11571b5094163dbb2c84bsalomon            fBoundsFlags |= kZeroArea_BoundsFlag;
20088cf17d099085b8085ab11571b5094163dbb2c84bsalomon        }
20188cf17d099085b8085ab11571b5094163dbb2c84bsalomon        return fBounds.joinPossiblyEmptyRect(that.fBounds);
20299c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt    }
20399c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt
20425a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    void replaceBounds(const GrOp& that) {
20588cf17d099085b8085ab11571b5094163dbb2c84bsalomon        fBounds = that.fBounds;
20688cf17d099085b8085ab11571b5094163dbb2c84bsalomon        fBoundsFlags = that.fBoundsFlags;
20788cf17d099085b8085ab11571b5094163dbb2c84bsalomon    }
2081b55a963a2374a14bb82eb887bb99ee91680f0ebreed
20925a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    static uint32_t GenOpClassID() { return GenID(&gCurrOpClassID); }
210abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon
211abd30f54b7ff1704a8930c4307ea242d09425d02bsalomonprivate:
21225a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    virtual bool onCombineIfPossible(GrOp*, const GrCaps& caps) = 0;
213abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon
214742e31de1599f3902810aecdf2e2e3eed3b40a09Brian Salomon    virtual void onPrepare(GrOpFlushState*) = 0;
2159e50f7b11e9a9d3dc23c924bbb0f0b85c6f1d6cbBrian Salomon    virtual void onExecute(GrOpFlushState*) = 0;
2165346983b2e0726b4009cc546b01c58a8919e6c36bsalomon
217abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon    static uint32_t GenID(int32_t* idCounter) {
2181b55a963a2374a14bb82eb887bb99ee91680f0ebreed        // The atomic inc returns the old value not the incremented value. So we add
219abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        // 1 to the returned value.
220abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        uint32_t id = static_cast<uint32_t>(sk_atomic_inc(idCounter)) + 1;
221abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        if (!id) {
222b4aab9ae6d27c446af8302b79d15b832c816c633Ben Wagner            SK_ABORT("This should never wrap as it should only be called once for each GrOp "
223abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon                   "subclass.");
224abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        }
225abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        return id;
226abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon    }
227abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon
22888cf17d099085b8085ab11571b5094163dbb2c84bsalomon    void setBoundsFlags(HasAABloat aabloat, IsZeroArea zeroArea) {
22988cf17d099085b8085ab11571b5094163dbb2c84bsalomon        fBoundsFlags = 0;
23088cf17d099085b8085ab11571b5094163dbb2c84bsalomon        fBoundsFlags |= (HasAABloat::kYes == aabloat) ? kAABloat_BoundsFlag : 0;
23188cf17d099085b8085ab11571b5094163dbb2c84bsalomon        fBoundsFlags |= (IsZeroArea ::kYes == zeroArea) ? kZeroArea_BoundsFlag : 0;
23288cf17d099085b8085ab11571b5094163dbb2c84bsalomon    }
23388cf17d099085b8085ab11571b5094163dbb2c84bsalomon
234abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon    enum {
23525a880960a9a689a745a01071ecba3fe494b5940Brian Salomon        kIllegalOpID = 0,
236abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon    };
237abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon
23888cf17d099085b8085ab11571b5094163dbb2c84bsalomon    enum BoundsFlags {
23988cf17d099085b8085ab11571b5094163dbb2c84bsalomon        kAABloat_BoundsFlag                     = 0x1,
24088cf17d099085b8085ab11571b5094163dbb2c84bsalomon        kZeroArea_BoundsFlag                    = 0x2,
24188cf17d099085b8085ab11571b5094163dbb2c84bsalomon        SkDEBUGCODE(kUninitialized_BoundsFlag   = 0x4)
24288cf17d099085b8085ab11571b5094163dbb2c84bsalomon    };
24388cf17d099085b8085ab11571b5094163dbb2c84bsalomon
24488cf17d099085b8085ab11571b5094163dbb2c84bsalomon    const uint16_t                      fClassID;
24588cf17d099085b8085ab11571b5094163dbb2c84bsalomon    uint16_t                            fBoundsFlags;
24688cf17d099085b8085ab11571b5094163dbb2c84bsalomon
24725a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    static uint32_t GenOpID() { return GenID(&gCurrOpUniqueID); }
24808e65e718a3464a594e6dfca0351dfed19ac2445joshualitt    mutable uint32_t                    fUniqueID;
24988cf17d099085b8085ab11571b5094163dbb2c84bsalomon    SkRect                              fBounds;
25088cf17d099085b8085ab11571b5094163dbb2c84bsalomon
25125a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    static int32_t                      gCurrOpUniqueID;
25225a880960a9a689a745a01071ecba3fe494b5940Brian Salomon    static int32_t                      gCurrOpClassID;
253abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon};
254abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon
2554d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt#endif
256