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 GrBatchBuffer_DEFINED
      9 #define GrBatchBuffer_DEFINED
     10 
     11 #include "GrBufferAllocPool.h"
     12 #include "batches/GrVertexBatch.h"
     13 
     14 class GrResourceProvider;
     15 
     16 /** Simple class that performs the upload on behalf of a GrBatchUploader. */
     17 class GrBatchUploader::TextureUploader {
     18 public:
     19     TextureUploader(GrGpu* gpu) : fGpu(gpu) { SkASSERT(gpu); }
     20 
     21     /**
     22         * Updates the pixels in a rectangle of a texture.
     23         *
     24         * @param left          left edge of the rectangle to write (inclusive)
     25         * @param top           top edge of the rectangle to write (inclusive)
     26         * @param width         width of rectangle to write in pixels.
     27         * @param height        height of rectangle to write in pixels.
     28         * @param config        the pixel config of the source buffer
     29         * @param buffer        memory to read pixels from
     30         * @param rowBytes      number of bytes between consecutive rows. Zero
     31         *                      means rows are tightly packed.
     32         */
     33     bool writeTexturePixels(GrTexture* texture,
     34                             int left, int top, int width, int height,
     35                             GrPixelConfig config, const void* buffer,
     36                             size_t rowBytes) {
     37         return fGpu->writePixels(texture, left, top, width, height, config, buffer, rowBytes);
     38     }
     39 
     40 private:
     41     GrGpu* fGpu;
     42 };
     43 
     44 /** Tracks the state across all the GrBatches in a GrDrawTarget flush. */
     45 class GrBatchFlushState {
     46 public:
     47     GrBatchFlushState(GrGpu*, GrResourceProvider*);
     48 
     49     ~GrBatchFlushState() { this->reset(); }
     50 
     51     void advanceToken() { ++fCurrentToken; }
     52 
     53     void advanceLastFlushedToken() { ++fLastFlushedToken; }
     54 
     55     /** Inserts an upload to be executred after all batches in the flush prepared their draws
     56         but before the draws are executed to the backend 3D API. */
     57     void addASAPUpload(GrBatchUploader* upload) {
     58         fAsapUploads.push_back().reset(SkRef(upload));
     59     }
     60 
     61     const GrCaps& caps() const { return *fGpu->caps(); }
     62     GrResourceProvider* resourceProvider() const { return fResourceProvider; }
     63 
     64     /** Has the token been flushed to the backend 3D API. */
     65     bool hasTokenBeenFlushed(GrBatchToken token) const { return fLastFlushedToken >= token; }
     66 
     67     /** The current token advances once for every contiguous set of uninterrupted draws prepared
     68         by a batch. */
     69     GrBatchToken currentToken() const { return fCurrentToken; }
     70 
     71     /** The last token flushed to all the way to the backend API. */
     72     GrBatchToken lastFlushedToken() const { return fLastFlushedToken; }
     73 
     74     /** This is a magic token that can be used to indicate that an upload should occur before
     75         any draws for any batch in the current flush execute. */
     76     GrBatchToken asapToken() const { return fLastFlushedToken + 1; }
     77 
     78     void* makeVertexSpace(size_t vertexSize, int vertexCount,
     79                           const GrVertexBuffer** buffer, int* startVertex);
     80     uint16_t* makeIndexSpace(int indexCount, const GrIndexBuffer** buffer, int* startIndex);
     81 
     82     /** This is called after each batch has a chance to prepare its draws and before the draws
     83         are issued. */
     84     void preIssueDraws() {
     85         fVertexPool.unmap();
     86         fIndexPool.unmap();
     87         int uploadCount = fAsapUploads.count();
     88         for (int i = 0; i < uploadCount; i++) {
     89             fAsapUploads[i]->upload(&fUploader);
     90         }
     91         fAsapUploads.reset();
     92     }
     93 
     94     void putBackIndices(size_t indices) { fIndexPool.putBack(indices * sizeof(uint16_t)); }
     95 
     96     void putBackVertexSpace(size_t sizeInBytes) { fVertexPool.putBack(sizeInBytes); }
     97 
     98     GrBatchUploader::TextureUploader* uploader() { return &fUploader; }
     99 
    100     GrGpu* gpu() { return fGpu; }
    101 
    102     void reset() {
    103         fVertexPool.reset();
    104         fIndexPool.reset();
    105     }
    106 
    107 private:
    108     GrGpu*                                          fGpu;
    109     GrBatchUploader::TextureUploader                fUploader;
    110 
    111     GrResourceProvider*                             fResourceProvider;
    112 
    113     GrVertexBufferAllocPool                         fVertexPool;
    114     GrIndexBufferAllocPool                          fIndexPool;
    115 
    116     SkTArray<SkAutoTUnref<GrBatchUploader>, true>   fAsapUploads;
    117 
    118     GrBatchToken                                    fCurrentToken;
    119 
    120     GrBatchToken                                    fLastFlushedToken;
    121 };
    122 
    123 /**
    124  * GrDrawBatch instances use this object to allocate space for their geometry and to issue the draws
    125  * that render their batch.
    126  */
    127 class GrDrawBatch::Target {
    128 public:
    129     Target(GrBatchFlushState* state, GrDrawBatch* batch) : fState(state), fBatch(batch) {}
    130 
    131     void upload(GrBatchUploader* upload) {
    132         if (this->asapToken() == upload->lastUploadToken()) {
    133             fState->addASAPUpload(upload);
    134         } else {
    135             fBatch->fInlineUploads.push_back().reset(SkRef(upload));
    136         }
    137     }
    138 
    139     bool hasTokenBeenFlushed(GrBatchToken token) const {
    140         return fState->hasTokenBeenFlushed(token);
    141     }
    142     GrBatchToken currentToken() const { return fState->currentToken(); }
    143     GrBatchToken asapToken() const { return fState->asapToken(); }
    144 
    145     const GrCaps& caps() const { return fState->caps(); }
    146 
    147     GrResourceProvider* resourceProvider() const { return fState->resourceProvider(); }
    148 
    149 protected:
    150     GrDrawBatch* batch() { return fBatch; }
    151     GrBatchFlushState* state() { return fState; }
    152 
    153 private:
    154     GrBatchFlushState*  fState;
    155     GrDrawBatch*        fBatch;
    156 };
    157 
    158 /** Extension of GrDrawBatch::Target for use by GrVertexBatch. Adds the ability to create vertex
    159     draws. */
    160 class GrVertexBatch::Target : public GrDrawBatch::Target {
    161 public:
    162     Target(GrBatchFlushState* state, GrVertexBatch* batch) : INHERITED(state, batch) {}
    163 
    164     void initDraw(const GrPrimitiveProcessor* primProc, const GrPipeline* pipeline) {
    165         GrVertexBatch::DrawArray* draws = this->vertexBatch()->fDrawArrays.addToTail();
    166         draws->fPrimitiveProcessor.reset(primProc);
    167         this->state()->advanceToken();
    168     }
    169 
    170     void draw(const GrVertices& vertices) {
    171         this->vertexBatch()->fDrawArrays.tail()->fDraws.push_back(vertices);
    172     }
    173 
    174     void* makeVertexSpace(size_t vertexSize, int vertexCount,
    175                           const GrVertexBuffer** buffer, int* startVertex) {
    176         return this->state()->makeVertexSpace(vertexSize, vertexCount, buffer, startVertex);
    177     }
    178 
    179     uint16_t* makeIndexSpace(int indexCount, const GrIndexBuffer** buffer, int* startIndex) {
    180         return this->state()->makeIndexSpace(indexCount, buffer, startIndex);
    181     }
    182 
    183     /** Helpers for batches which over-allocate and then return data to the pool. */
    184     void putBackIndices(int indices) { this->state()->putBackIndices(indices); }
    185     void putBackVertices(int vertices, size_t vertexStride) {
    186         this->state()->putBackVertexSpace(vertices * vertexStride);
    187     }
    188 
    189 private:
    190     GrVertexBatch* vertexBatch() { return static_cast<GrVertexBatch*>(this->batch()); }
    191     typedef GrDrawBatch::Target INHERITED;
    192 };
    193 
    194 #endif
    195