GrOp.h revision 1b55a963a2374a14bb82eb887bb99ee91680f0eb
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
84d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt#ifndef GrBatch_DEFINED
94d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt#define GrBatch_DEFINED
104d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
114d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt#include <new>
12dbe1e6f0c32bd07b7669b1b1ac3c7f58c9b8d773joshualitt#include "GrNonAtomicRef.h"
134d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
1416b991390bb988b194a868ab8de66db4c21c7c13bsalomon#include "SkRect.h"
155346983b2e0726b4009cc546b01c58a8919e6c36bsalomon#include "SkString.h"
164d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
1716b991390bb988b194a868ab8de66db4c21c7c13bsalomonclass GrCaps;
185346983b2e0726b4009cc546b01c58a8919e6c36bsalomonclass GrBatchFlushState;
194d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
20abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon/**
214d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * GrBatch is the base class for all Ganesh deferred geometry generators.  To facilitate
224d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * reorderable batching, Ganesh does not generate geometry inline with draw calls.  Instead, it
234d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * captures the arguments to the draw and then generates the geometry on demand.  This gives GrBatch
244d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * subclasses complete freedom to decide how / what they can batch.
254d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt *
264d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * Batches are created when GrContext processes a draw call. Batches of the same  subclass may be
274d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * merged using combineIfPossible. When two batches merge, one takes on the union of the data
284d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * and the other is left empty. The merged batch becomes responsible for drawing the data from both
294d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * the original batches.
304d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt *
314d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * If there are any possible optimizations which might require knowing more about the full state of
324d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * the draw, ie whether or not the GrBatch is allowed to tweak alpha for coverage, then this
334d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt * information will be communicated to the GrBatch prior to geometry generation.
344d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt */
35ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt#define GR_BATCH_SPEW 0
36ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt#if GR_BATCH_SPEW
37ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt    #define GrBATCH_INFO(...) SkDebugf(__VA_ARGS__)
38ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt    #define GrBATCH_SPEW(code) code
39ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt#else
40ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt    #define GrBATCH_SPEW(code)
41ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt    #define GrBATCH_INFO(...)
42ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt#endif
434d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
441b55a963a2374a14bb82eb887bb99ee91680f0ebreed// A helper macro to generate a class static id
451b55a963a2374a14bb82eb887bb99ee91680f0ebreed#define DEFINE_BATCH_CLASS_ID \
461b55a963a2374a14bb82eb887bb99ee91680f0ebreed    static uint32_t ClassID() { \
471b55a963a2374a14bb82eb887bb99ee91680f0ebreed        static uint32_t kClassID = GenBatchClassID(); \
481b55a963a2374a14bb82eb887bb99ee91680f0ebreed        return kClassID; \
491b55a963a2374a14bb82eb887bb99ee91680f0ebreed    }
501b55a963a2374a14bb82eb887bb99ee91680f0ebreed
51dbe1e6f0c32bd07b7669b1b1ac3c7f58c9b8d773joshualittclass GrBatch : public GrNonAtomicRef {
524d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualittpublic:
531b55a963a2374a14bb82eb887bb99ee91680f0ebreed    GrBatch(uint32_t classID);
54a387a11f9e10ee828fd0e0257cc3ee3f6262f7cabsalomon    ~GrBatch() override;
554d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
564d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    virtual const char* name() const = 0;
574d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
58cb02b38b2c48bfde333ce3c699dd0451e2d867fabsalomon    bool combineIfPossible(GrBatch* that, const GrCaps& caps) {
594d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt        if (this->classID() != that->classID()) {
604d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt            return false;
614d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt        }
624d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
63cb02b38b2c48bfde333ce3c699dd0451e2d867fabsalomon        return this->onCombineIfPossible(that, caps);
644d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    }
654d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
6699c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt    const SkRect& bounds() const { return fBounds; }
6799c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt
684d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    void* operator new(size_t size);
694d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    void operator delete(void* target);
704d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
714d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    void* operator new(size_t size, void* placement) {
724d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt        return ::operator new(size, placement);
734d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    }
744d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    void operator delete(void* target, void* placement) {
754d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt        ::operator delete(target, placement);
764d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    }
774d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
784d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt    /**
791b55a963a2374a14bb82eb887bb99ee91680f0ebreed     * Helper for safely down-casting to a GrBatch subclass
80abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon     */
811b55a963a2374a14bb82eb887bb99ee91680f0ebreed    template <typename T> const T& cast() const {
821b55a963a2374a14bb82eb887bb99ee91680f0ebreed        SkASSERT(T::ClassID() == this->classID());
831b55a963a2374a14bb82eb887bb99ee91680f0ebreed        return *static_cast<const T*>(this);
841b55a963a2374a14bb82eb887bb99ee91680f0ebreed    }
851b55a963a2374a14bb82eb887bb99ee91680f0ebreed
861b55a963a2374a14bb82eb887bb99ee91680f0ebreed    template <typename T> T* cast() {
871b55a963a2374a14bb82eb887bb99ee91680f0ebreed        SkASSERT(T::ClassID() == this->classID());
881b55a963a2374a14bb82eb887bb99ee91680f0ebreed        return static_cast<T*>(this);
891b55a963a2374a14bb82eb887bb99ee91680f0ebreed    }
904d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
91ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt    uint32_t classID() const { SkASSERT(kIllegalBatchID != fClassID); return fClassID; }
924d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt
93ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt#if GR_BATCH_SPEW
94ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt    uint32_t uniqueID() const { return fUniqueID; }
95ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt#endif
96abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon    SkDEBUGCODE(bool isUsed() const { return fUsed; })
97ca1f07eb5f976a39845721b434b780c5a705f3d9joshualitt
985346983b2e0726b4009cc546b01c58a8919e6c36bsalomon    /** Called prior to drawing. The batch should perform any resource creation necessary to
995346983b2e0726b4009cc546b01c58a8919e6c36bsalomon        to quickly issue its draw when draw is called. */
1005346983b2e0726b4009cc546b01c58a8919e6c36bsalomon    void prepare(GrBatchFlushState* state) { this->onPrepare(state); }
1015346983b2e0726b4009cc546b01c58a8919e6c36bsalomon
1025346983b2e0726b4009cc546b01c58a8919e6c36bsalomon    /** Issues the batches commands to GrGpu. */
1035346983b2e0726b4009cc546b01c58a8919e6c36bsalomon    void draw(GrBatchFlushState* state) { this->onDraw(state); }
1045346983b2e0726b4009cc546b01c58a8919e6c36bsalomon
1055346983b2e0726b4009cc546b01c58a8919e6c36bsalomon    /** Used to block batching across render target changes. Remove this once we store
1065346983b2e0726b4009cc546b01c58a8919e6c36bsalomon        GrBatches for different RTs in different targets. */
1075346983b2e0726b4009cc546b01c58a8919e6c36bsalomon    virtual uint32_t renderTargetUniqueID() const = 0;
1085346983b2e0726b4009cc546b01c58a8919e6c36bsalomon
1095346983b2e0726b4009cc546b01c58a8919e6c36bsalomon    /** Used for spewing information about batches when debugging. */
1105346983b2e0726b4009cc546b01c58a8919e6c36bsalomon    virtual SkString dumpInfo() const = 0;
1115346983b2e0726b4009cc546b01c58a8919e6c36bsalomon
1124d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualittprotected:
11399c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt    // NOTE, compute some bounds, even if extremely conservative.  Do *NOT* setLargest on the bounds
11499c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt    // rect because we outset it for dst copy textures
11599c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt    void setBounds(const SkRect& newBounds) { fBounds = newBounds; }
11699c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt
11799c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt    void joinBounds(const SkRect& otherBounds) {
11899c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt        return fBounds.joinPossiblyEmptyRect(otherBounds);
11999c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt    }
12099c7c07e0f1f7b78980eb21d84bebda8b45a7178joshualitt
1211b55a963a2374a14bb82eb887bb99ee91680f0ebreed    static uint32_t GenBatchClassID() { return GenID(&gCurrBatchClassID); }
1221b55a963a2374a14bb82eb887bb99ee91680f0ebreed
123abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon    SkRect                              fBounds;
124abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon
125abd30f54b7ff1704a8930c4307ea242d09425d02bsalomonprivate:
126abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon    virtual bool onCombineIfPossible(GrBatch*, const GrCaps& caps) = 0;
127abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon
1285346983b2e0726b4009cc546b01c58a8919e6c36bsalomon    virtual void onPrepare(GrBatchFlushState*) = 0;
1295346983b2e0726b4009cc546b01c58a8919e6c36bsalomon    virtual void onDraw(GrBatchFlushState*) = 0;
1305346983b2e0726b4009cc546b01c58a8919e6c36bsalomon
131abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon    static uint32_t GenID(int32_t* idCounter) {
1321b55a963a2374a14bb82eb887bb99ee91680f0ebreed        // The atomic inc returns the old value not the incremented value. So we add
133abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        // 1 to the returned value.
134abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        uint32_t id = static_cast<uint32_t>(sk_atomic_inc(idCounter)) + 1;
135abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        if (!id) {
136abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon            SkFAIL("This should never wrap as it should only be called once for each GrBatch "
137abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon                   "subclass.");
138abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        }
139abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        return id;
140abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon    }
141abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon
142abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon    enum {
143abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon        kIllegalBatchID = 0,
144abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon    };
145abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon
146abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon    SkDEBUGCODE(bool                    fUsed;)
1471b55a963a2374a14bb82eb887bb99ee91680f0ebreed    const uint32_t                      fClassID;
148abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon#if GR_BATCH_SPEW
1491b55a963a2374a14bb82eb887bb99ee91680f0ebreed    static uint32_t GenBatchID() { return GenID(&gCurrBatchUniqueID); }
1501b55a963a2374a14bb82eb887bb99ee91680f0ebreed    const uint32_t                      fUniqueID;
1511b55a963a2374a14bb82eb887bb99ee91680f0ebreed    static int32_t                      gCurrBatchUniqueID;
152abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon#endif
1531b55a963a2374a14bb82eb887bb99ee91680f0ebreed    static int32_t                      gCurrBatchClassID;
154abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon    typedef GrNonAtomicRef INHERITED;
155abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon};
156abd30f54b7ff1704a8930c4307ea242d09425d02bsalomon
1574d8da81562852e0ff7e18b66ee1cebd50ad81ee8joshualitt#endif
158