1 /*
2  * Copyright 2015 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef GrBatch_DEFINED
9 #define GrBatch_DEFINED
10 
11 #include <new>
12 #include "GrNonAtomicRef.h"
13 
14 #include "SkRect.h"
15 #include "SkString.h"
16 
17 class GrCaps;
18 class GrBatchFlushState;
19 class GrRenderTarget;
20 
21 /**
22  * GrBatch is the base class for all Ganesh deferred geometry generators.  To facilitate
23  * reorderable batching, Ganesh does not generate geometry inline with draw calls.  Instead, it
24  * captures the arguments to the draw and then generates the geometry on demand.  This gives GrBatch
25  * subclasses complete freedom to decide how / what they can batch.
26  *
27  * Batches are created when GrContext processes a draw call. Batches of the same  subclass may be
28  * merged using combineIfPossible. When two batches merge, one takes on the union of the data
29  * and the other is left empty. The merged batch becomes responsible for drawing the data from both
30  * the original batches.
31  *
32  * If there are any possible optimizations which might require knowing more about the full state of
33  * the draw, ie whether or not the GrBatch is allowed to tweak alpha for coverage, then this
34  * information will be communicated to the GrBatch prior to geometry generation.
35  *
36  * The bounds of the batch must contain all the vertices in device space *irrespective* of the clip.
37  * The bounds are used in determining which clip elements must be applied and thus the bounds cannot
38  * in turn depend upon the clip.
39  */
40 #define GR_BATCH_SPEW 0
41 #if GR_BATCH_SPEW
42     #define GrBATCH_INFO(...) SkDebugf(__VA_ARGS__)
43     #define GrBATCH_SPEW(code) code
44 #else
45     #define GrBATCH_SPEW(code)
46     #define GrBATCH_INFO(...)
47 #endif
48 
49 // A helper macro to generate a class static id
50 #define DEFINE_BATCH_CLASS_ID \
51     static uint32_t ClassID() { \
52         static uint32_t kClassID = GenBatchClassID(); \
53         return kClassID; \
54     }
55 
56 class GrBatch : public GrNonAtomicRef<GrBatch> {
57 public:
58     GrBatch(uint32_t classID);
59     virtual ~GrBatch();
60 
61     virtual const char* name() const = 0;
62 
combineIfPossible(GrBatch * that,const GrCaps & caps)63     bool combineIfPossible(GrBatch* that, const GrCaps& caps) {
64         if (this->classID() != that->classID()) {
65             return false;
66         }
67 
68         return this->onCombineIfPossible(that, caps);
69     }
70 
bounds()71     const SkRect& bounds() const { return fBounds; }
72 
73     void* operator new(size_t size);
74     void operator delete(void* target);
75 
new(size_t size,void * placement)76     void* operator new(size_t size, void* placement) {
77         return ::operator new(size, placement);
78     }
delete(void * target,void * placement)79     void operator delete(void* target, void* placement) {
80         ::operator delete(target, placement);
81     }
82 
83     /**
84      * Helper for safely down-casting to a GrBatch subclass
85      */
cast()86     template <typename T> const T& cast() const {
87         SkASSERT(T::ClassID() == this->classID());
88         return *static_cast<const T*>(this);
89     }
90 
cast()91     template <typename T> T* cast() {
92         SkASSERT(T::ClassID() == this->classID());
93         return static_cast<T*>(this);
94     }
95 
classID()96     uint32_t classID() const { SkASSERT(kIllegalBatchID != fClassID); return fClassID; }
97 
98 #if GR_BATCH_SPEW
uniqueID()99     uint32_t uniqueID() const { return fUniqueID; }
100 #endif
SkDEBUGCODE(bool isUsed ()const{ return fUsed; })101     SkDEBUGCODE(bool isUsed() const { return fUsed; })
102 
103     /** Called prior to drawing. The batch should perform any resource creation necessary to
104         to quickly issue its draw when draw is called. */
105     void prepare(GrBatchFlushState* state) { this->onPrepare(state); }
106 
107     /** Issues the batches commands to GrGpu. */
draw(GrBatchFlushState * state)108     void draw(GrBatchFlushState* state) { this->onDraw(state); }
109 
110     /** Used to block batching across render target changes. Remove this once we store
111         GrBatches for different RTs in different targets. */
112     virtual uint32_t renderTargetUniqueID() const = 0;
113 
114     /** Used for spewing information about batches when debugging. */
115     virtual SkString dumpInfo() const = 0;
116 
117     /** Can remove this when multi-draw-buffer lands */
118     virtual GrRenderTarget* renderTarget() const = 0;
119 
120 protected:
121     // NOTE, compute some bounds, even if extremely conservative.  Do *NOT* setLargest on the bounds
122     // rect because we outset it for dst copy textures
setBounds(const SkRect & newBounds)123     void setBounds(const SkRect& newBounds) { fBounds = newBounds; }
124 
joinBounds(const SkRect & otherBounds)125     void joinBounds(const SkRect& otherBounds) {
126         return fBounds.joinPossiblyEmptyRect(otherBounds);
127     }
128 
GenBatchClassID()129     static uint32_t GenBatchClassID() { return GenID(&gCurrBatchClassID); }
130 
131     SkRect                              fBounds;
132 
133 private:
134     virtual bool onCombineIfPossible(GrBatch*, const GrCaps& caps) = 0;
135 
136     virtual void onPrepare(GrBatchFlushState*) = 0;
137     virtual void onDraw(GrBatchFlushState*) = 0;
138 
GenID(int32_t * idCounter)139     static uint32_t GenID(int32_t* idCounter) {
140         // The atomic inc returns the old value not the incremented value. So we add
141         // 1 to the returned value.
142         uint32_t id = static_cast<uint32_t>(sk_atomic_inc(idCounter)) + 1;
143         if (!id) {
144             SkFAIL("This should never wrap as it should only be called once for each GrBatch "
145                    "subclass.");
146         }
147         return id;
148     }
149 
150     enum {
151         kIllegalBatchID = 0,
152     };
153 
154     SkDEBUGCODE(bool                    fUsed;)
155     const uint32_t                      fClassID;
156 #if GR_BATCH_SPEW
GenBatchID()157     static uint32_t GenBatchID() { return GenID(&gCurrBatchUniqueID); }
158     const uint32_t                      fUniqueID;
159     static int32_t                      gCurrBatchUniqueID;
160 #endif
161     static int32_t                      gCurrBatchClassID;
162 };
163 
164 #endif
165