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: TextureUploader(GrGpu * gpu)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 */ writeTexturePixels(GrTexture * texture,int left,int top,int width,int height,GrPixelConfig config,const void * buffer,size_t rowBytes)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 ~GrBatchFlushState()49 ~GrBatchFlushState() { this->reset(); } 50 advanceToken()51 void advanceToken() { ++fCurrentToken; } 52 advanceLastFlushedToken()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. */ addASAPUpload(GrBatchUploader * upload)57 void addASAPUpload(GrBatchUploader* upload) { 58 fAsapUploads.push_back().reset(SkRef(upload)); 59 } 60 caps()61 const GrCaps& caps() const { return *fGpu->caps(); } resourceProvider()62 GrResourceProvider* resourceProvider() const { return fResourceProvider; } 63 64 /** Has the token been flushed to the backend 3D API. */ hasTokenBeenFlushed(GrBatchToken token)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. */ currentToken()69 GrBatchToken currentToken() const { return fCurrentToken; } 70 71 /** The last token flushed to all the way to the backend API. */ lastFlushedToken()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. */ asapToken()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. */ preIssueDraws()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 putBackIndices(size_t indices)94 void putBackIndices(size_t indices) { fIndexPool.putBack(indices * sizeof(uint16_t)); } 95 putBackVertexSpace(size_t sizeInBytes)96 void putBackVertexSpace(size_t sizeInBytes) { fVertexPool.putBack(sizeInBytes); } 97 uploader()98 GrBatchUploader::TextureUploader* uploader() { return &fUploader; } 99 gpu()100 GrGpu* gpu() { return fGpu; } 101 reset()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: Target(GrBatchFlushState * state,GrDrawBatch * batch)129 Target(GrBatchFlushState* state, GrDrawBatch* batch) : fState(state), fBatch(batch) {} 130 upload(GrBatchUploader * upload)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 hasTokenBeenFlushed(GrBatchToken token)139 bool hasTokenBeenFlushed(GrBatchToken token) const { 140 return fState->hasTokenBeenFlushed(token); 141 } currentToken()142 GrBatchToken currentToken() const { return fState->currentToken(); } asapToken()143 GrBatchToken asapToken() const { return fState->asapToken(); } 144 caps()145 const GrCaps& caps() const { return fState->caps(); } 146 resourceProvider()147 GrResourceProvider* resourceProvider() const { return fState->resourceProvider(); } 148 149 protected: batch()150 GrDrawBatch* batch() { return fBatch; } state()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: Target(GrBatchFlushState * state,GrVertexBatch * batch)162 Target(GrBatchFlushState* state, GrVertexBatch* batch) : INHERITED(state, batch) {} 163 initDraw(const GrPrimitiveProcessor * primProc,const GrPipeline * pipeline)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 draw(const GrVertices & vertices)170 void draw(const GrVertices& vertices) { 171 this->vertexBatch()->fDrawArrays.tail()->fDraws.push_back(vertices); 172 } 173 makeVertexSpace(size_t vertexSize,int vertexCount,const GrVertexBuffer ** buffer,int * startVertex)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 makeIndexSpace(int indexCount,const GrIndexBuffer ** buffer,int * startIndex)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. */ putBackIndices(int indices)184 void putBackIndices(int indices) { this->state()->putBackIndices(indices); } putBackVertices(int vertices,size_t vertexStride)185 void putBackVertices(int vertices, size_t vertexStride) { 186 this->state()->putBackVertexSpace(vertices * vertexStride); 187 } 188 189 private: vertexBatch()190 GrVertexBatch* vertexBatch() { return static_cast<GrVertexBatch*>(this->batch()); } 191 typedef GrDrawBatch::Target INHERITED; 192 }; 193 194 #endif 195