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 initDraw(const GrPrimitiveProcessor * primProc,const GrPipeline * pipeline)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: TextureUploader(GrGpu * gpu)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 */ writeTexturePixels(GrTexture * texture,int left,int top,int width,int height,GrPixelConfig config,const void * buffer,size_t rowBytes)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: Uploader(BatchToken lastUploadToken)63 Uploader(BatchToken lastUploadToken) : fLastUploadToken(lastUploadToken) {} lastUploadToken()64 BatchToken lastUploadToken() const { return fLastUploadToken; } 65 virtual void upload(TextureUploader)=0; 66 67 private: 68 BatchToken fLastUploadToken; 69 }; 70 upload(Uploader * upload)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 draw(const GrVertices & vertices)79 void draw(const GrVertices& vertices) { 80 fFlushBuffer.back().fVertexDraws.push_back(vertices); 81 } 82 isIssued(BatchToken token)83 bool isIssued(BatchToken token) const { return fLastFlushedToken >= token; } currentToken()84 BatchToken currentToken() const { return fCurrentToken; } asapToken()85 BatchToken asapToken() const { return fLastFlushedToken + 1; } 86 87 // TODO much of this complexity goes away when batch is everywhere resetNumberOfDraws()88 void resetNumberOfDraws() { fNumberOfDraws = 0; } numberOfDraws()89 int numberOfDraws() const { return fNumberOfDraws; } preFlush()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); postFlush()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 currentBatchTracker()108 GrBatchTracker* currentBatchTracker() { 109 SkASSERT(!fFlushBuffer.empty()); 110 return &fFlushBuffer.back().fBatchTracker; 111 } 112 caps()113 const GrDrawTargetCaps& caps() const { return *fGpu->caps(); } 114 resourceProvider()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 putBackIndices(size_t indices)123 void putBackIndices(size_t indices) { fIndexPool->putBack(indices * sizeof(uint16_t)); } 124 putBackVertices(size_t vertices,size_t vertexStride)125 void putBackVertices(size_t vertices, size_t vertexStride) { 126 fVertexPool->putBack(vertices * vertexStride); 127 } 128 reset()129 void reset() { 130 fVertexPool->reset(); 131 fIndexPool->reset(); 132 } 133 134 private: unmapVertexAndIndexBuffers()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 { BufferedFlushBufferedFlush147 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