Home | History | Annotate | Download | only in gpu
      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 "GrBatchTarget.h"
     13 #include "GrGeometryProcessor.h"
     14 #include "GrVertices.h"
     15 #include "SkRefCnt.h"
     16 #include "SkThread.h"
     17 #include "SkTypes.h"
     18 
     19 class GrGpu;
     20 class GrPipeline;
     21 
     22 struct GrInitInvariantOutput;
     23 
     24 /*
     25  * GrBatch is the base class for all Ganesh deferred geometry generators.  To facilitate
     26  * reorderable batching, Ganesh does not generate geometry inline with draw calls.  Instead, it
     27  * captures the arguments to the draw and then generates the geometry on demand.  This gives GrBatch
     28  * subclasses complete freedom to decide how / what they can batch.
     29  *
     30  * Batches are created when GrContext processes a draw call. Batches of the same  subclass may be
     31  * merged using combineIfPossible. When two batches merge, one takes on the union of the data
     32  * and the other is left empty. The merged batch becomes responsible for drawing the data from both
     33  * the original batches.
     34  *
     35  * If there are any possible optimizations which might require knowing more about the full state of
     36  * the draw, ie whether or not the GrBatch is allowed to tweak alpha for coverage, then this
     37  * information will be communicated to the GrBatch prior to geometry generation.
     38  */
     39 
     40 class GrBatch : public SkRefCnt {
     41 public:
     42     SK_DECLARE_INST_COUNT(GrBatch)
     43     GrBatch() : fClassID(kIllegalBatchClassID), fNumberOfDraws(0) { SkDEBUGCODE(fUsed = false;) }
     44     virtual ~GrBatch() {}
     45 
     46     virtual const char* name() const = 0;
     47     virtual void getInvariantOutputColor(GrInitInvariantOutput* out) const = 0;
     48     virtual void getInvariantOutputCoverage(GrInitInvariantOutput* out) const = 0;
     49 
     50     /*
     51      * initBatchTracker is a hook for the some additional overrides / optimization possibilities
     52      * from the GrXferProcessor.
     53      */
     54     virtual void initBatchTracker(const GrPipelineInfo& init) = 0;
     55 
     56     bool combineIfPossible(GrBatch* that) {
     57         if (this->classID() != that->classID()) {
     58             return false;
     59         }
     60 
     61         return this->onCombineIfPossible(that);
     62     }
     63 
     64     virtual bool onCombineIfPossible(GrBatch*) = 0;
     65 
     66     virtual void generateGeometry(GrBatchTarget*, const GrPipeline*) = 0;
     67 
     68     const SkRect& bounds() const { return fBounds; }
     69 
     70     // TODO this goes away when batches are everywhere
     71     void setNumberOfDraws(int numberOfDraws) { fNumberOfDraws = numberOfDraws; }
     72     int numberOfDraws() const { return fNumberOfDraws; }
     73 
     74     void* operator new(size_t size);
     75     void operator delete(void* target);
     76 
     77     void* operator new(size_t size, void* placement) {
     78         return ::operator new(size, placement);
     79     }
     80     void operator delete(void* target, void* placement) {
     81         ::operator delete(target, placement);
     82     }
     83 
     84     /**
     85       * Helper for down-casting to a GrBatch subclass
     86       */
     87     template <typename T> const T& cast() const { return *static_cast<const T*>(this); }
     88     template <typename T> T* cast() { return static_cast<T*>(this); }
     89 
     90     uint32_t classID() const { SkASSERT(kIllegalBatchClassID != fClassID); return fClassID; }
     91 
     92     // TODO no GrPrimitiveProcessors yet read fragment position
     93     bool willReadFragmentPosition() const { return false; }
     94 
     95     SkDEBUGCODE(bool isUsed() const { return fUsed; })
     96 
     97 protected:
     98     template <typename PROC_SUBCLASS> void initClassID() {
     99          static uint32_t kClassID = GenClassID();
    100          fClassID = kClassID;
    101     }
    102 
    103     uint32_t fClassID;
    104 
    105     // NOTE, compute some bounds, even if extremely conservative.  Do *NOT* setLargest on the bounds
    106     // rect because we outset it for dst copy textures
    107     void setBounds(const SkRect& newBounds) { fBounds = newBounds; }
    108 
    109     void joinBounds(const SkRect& otherBounds) {
    110         return fBounds.joinPossiblyEmptyRect(otherBounds);
    111     }
    112 
    113     /** Helper for rendering instances using an instanced index index buffer. This class creates the
    114         space for the vertices and flushes the draws to the batch target.*/
    115    class InstancedHelper {
    116    public:
    117         InstancedHelper() {}
    118         /** Returns the allocated storage for the vertices. The caller should populate the before
    119             vertices before calling issueDraws(). */
    120         void* init(GrBatchTarget* batchTarget, GrPrimitiveType, size_t vertexStride,
    121                    const GrIndexBuffer*, int verticesPerInstance, int indicesPerInstance,
    122                    int instancesToDraw);
    123 
    124         /** Call after init() to issue draws to the batch target.*/
    125         void issueDraw(GrBatchTarget* batchTarget) {
    126             SkASSERT(fVertices.instanceCount());
    127             batchTarget->draw(fVertices);
    128         }
    129     private:
    130         GrVertices  fVertices;
    131     };
    132 
    133     static const int kVerticesPerQuad = 4;
    134     static const int kIndicesPerQuad = 6;
    135 
    136     /** A specialization of InstanceHelper for quad rendering. */
    137     class QuadHelper : private InstancedHelper {
    138     public:
    139         QuadHelper() : INHERITED() {}
    140         /** Finds the cached quad index buffer and reserves vertex space. Returns NULL on failure
    141             and on sucess a pointer to the vertex data that the caller should populate before
    142             calling issueDraws(). */
    143         void* init(GrBatchTarget* batchTarget, size_t vertexStride, int quadsToDraw);
    144 
    145         using InstancedHelper::issueDraw;
    146 
    147     private:
    148         typedef InstancedHelper INHERITED;
    149     };
    150 
    151     SkRect fBounds;
    152 
    153 private:
    154     static uint32_t GenClassID() {
    155         // fCurrProcessorClassID has been initialized to kIllegalProcessorClassID. The
    156         // atomic inc returns the old value not the incremented value. So we add
    157         // 1 to the returned value.
    158         uint32_t id = static_cast<uint32_t>(sk_atomic_inc(&gCurrBatchClassID)) + 1;
    159         if (!id) {
    160             SkFAIL("This should never wrap as it should only be called once for each GrBatch "
    161                    "subclass.");
    162         }
    163         return id;
    164     }
    165 
    166     enum {
    167         kIllegalBatchClassID = 0,
    168     };
    169     static int32_t gCurrBatchClassID;
    170 
    171     SkDEBUGCODE(bool fUsed;)
    172 
    173     int fNumberOfDraws;
    174 
    175     typedef SkRefCnt INHERITED;
    176 };
    177 
    178 #endif
    179