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 "GrBatchAtlas.h"
     12 #include "GrBufferAllocPool.h"
     13 #include "GrPendingProgramElement.h"
     14 #include "GrPipeline.h"
     15 #include "GrTRecorder.h"
     16 #include "GrVertices.h"
     17 
     18 /*
     19  * GrBatch instances use this object to allocate space for their geometry and to issue the draws
     20  * that render their batch.
     21  */
     22 class GrBatchTarget : public SkNoncopyable {
     23 public:
     24     typedef GrBatchAtlas::BatchToken BatchToken;
     25     GrBatchTarget(GrGpu* gpu);
     26 
     27     void initDraw(const GrPrimitiveProcessor* primProc, const GrPipeline* pipeline) {
     28         GrNEW_APPEND_TO_RECORDER(fFlushBuffer, BufferedFlush, (primProc, pipeline));
     29         fNumberOfDraws++;
     30         fCurrentToken++;
     31     }
     32 
     33     class TextureUploader {
     34     public:
     35         TextureUploader(GrGpu* gpu) : fGpu(gpu) { SkASSERT(gpu); }
     36 
     37         /**
     38          * Updates the pixels in a rectangle of a texture.
     39          *
     40          * @param left          left edge of the rectangle to write (inclusive)
     41          * @param top           top edge of the rectangle to write (inclusive)
     42          * @param width         width of rectangle to write in pixels.
     43          * @param height        height of rectangle to write in pixels.
     44          * @param config        the pixel config of the source buffer
     45          * @param buffer        memory to read pixels from
     46          * @param rowBytes      number of bytes between consecutive rows. Zero
     47          *                      means rows are tightly packed.
     48          */
     49         bool writeTexturePixels(GrTexture* texture,
     50                                 int left, int top, int width, int height,
     51                                 GrPixelConfig config, const void* buffer,
     52                                 size_t rowBytes) {
     53             return fGpu->writeTexturePixels(texture, left, top, width, height, config, buffer,
     54                                             rowBytes);
     55         }
     56 
     57     private:
     58         GrGpu* fGpu;
     59     };
     60 
     61     class Uploader : public SkRefCnt {
     62     public:
     63         Uploader(BatchToken lastUploadToken) : fLastUploadToken(lastUploadToken) {}
     64         BatchToken lastUploadToken() const { return fLastUploadToken; }
     65         virtual void upload(TextureUploader)=0;
     66 
     67     private:
     68         BatchToken fLastUploadToken;
     69     };
     70 
     71     void upload(Uploader* upload) {
     72         if (this->asapToken() == upload->lastUploadToken()) {
     73             fAsapUploads.push_back().reset(SkRef(upload));
     74         } else {
     75             fInlineUploads.push_back().reset(SkRef(upload));
     76         }
     77     }
     78 
     79     void draw(const GrVertices& vertices) {
     80         fFlushBuffer.back().fVertexDraws.push_back(vertices);
     81     }
     82 
     83     bool isIssued(BatchToken token) const { return fLastFlushedToken >= token; }
     84     BatchToken currentToken() const { return fCurrentToken; }
     85     BatchToken asapToken() const { return fLastFlushedToken + 1; }
     86 
     87     // TODO much of this complexity goes away when batch is everywhere
     88     void resetNumberOfDraws() { fNumberOfDraws = 0; }
     89     int numberOfDraws() const { return fNumberOfDraws; }
     90     void preFlush() {
     91         this->unmapVertexAndIndexBuffers();
     92         int updateCount = fAsapUploads.count();
     93         for (int i = 0; i < updateCount; i++) {
     94             fAsapUploads[i]->upload(TextureUploader(fGpu));
     95         }
     96         fInlineUpdatesIndex = 0;
     97         fIter = FlushBuffer::Iter(fFlushBuffer);
     98     }
     99     void flushNext(int n);
    100     void postFlush() {
    101         SkASSERT(!fIter.next());
    102         fFlushBuffer.reset();
    103         fAsapUploads.reset();
    104         fInlineUploads.reset();
    105     }
    106 
    107     // TODO This goes away when everything uses batch
    108     GrBatchTracker* currentBatchTracker() {
    109         SkASSERT(!fFlushBuffer.empty());
    110         return &fFlushBuffer.back().fBatchTracker;
    111     }
    112 
    113     const GrDrawTargetCaps& caps() const { return *fGpu->caps(); }
    114 
    115     GrResourceProvider* resourceProvider() const { return fGpu->getContext()->resourceProvider(); }
    116 
    117     void* makeVertSpace(size_t vertexSize, int vertexCount,
    118                         const GrVertexBuffer** buffer, int* startVertex);
    119     uint16_t* makeIndexSpace(int indexCount,
    120                              const GrIndexBuffer** buffer, int* startIndex);
    121 
    122     // A helper for draws which overallocate and then return data to the pool
    123     void putBackIndices(size_t indices) { fIndexPool->putBack(indices * sizeof(uint16_t)); }
    124 
    125     void putBackVertices(size_t vertices, size_t vertexStride) {
    126         fVertexPool->putBack(vertices * vertexStride);
    127     }
    128 
    129     void reset() {
    130         fVertexPool->reset();
    131         fIndexPool->reset();
    132     }
    133 
    134 private:
    135     void unmapVertexAndIndexBuffers() {
    136         fVertexPool->unmap();
    137         fIndexPool->unmap();
    138     }
    139 
    140     GrGpu* fGpu;
    141     SkAutoTDelete<GrVertexBufferAllocPool> fVertexPool;
    142     SkAutoTDelete<GrIndexBufferAllocPool> fIndexPool;
    143 
    144     typedef void* TBufferAlign; // This wouldn't be enough align if a command used long double.
    145 
    146     struct BufferedFlush {
    147         BufferedFlush(const GrPrimitiveProcessor* primProc, const GrPipeline* pipeline)
    148             : fPrimitiveProcessor(primProc)
    149             , fPipeline(pipeline) {}
    150         typedef GrPendingProgramElement<const GrPrimitiveProcessor> ProgramPrimitiveProcessor;
    151         ProgramPrimitiveProcessor fPrimitiveProcessor;
    152         const GrPipeline* fPipeline;
    153         GrBatchTracker fBatchTracker;
    154         SkSTArray<1, GrVertices, true> fVertexDraws;
    155     };
    156 
    157     enum {
    158         kFlushBufferInitialSizeInBytes = 8 * sizeof(BufferedFlush),
    159     };
    160 
    161     typedef GrTRecorder<BufferedFlush, TBufferAlign> FlushBuffer;
    162 
    163     FlushBuffer fFlushBuffer;
    164     // TODO this is temporary
    165     FlushBuffer::Iter fIter;
    166     int fNumberOfDraws;
    167     BatchToken fCurrentToken;
    168     BatchToken fLastFlushedToken; // The next token to be flushed
    169     SkTArray<SkAutoTUnref<Uploader>, true> fAsapUploads;
    170     SkTArray<SkAutoTUnref<Uploader>, true> fInlineUploads;
    171     int fInlineUpdatesIndex;
    172 };
    173 
    174 #endif
    175