blob: 19cfb09cb7278633457991910c1c3a8633ba0282 [file] [log] [blame]
joshualitt4d8da812015-01-28 12:53:54 -08001/*
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
joshualitt5bf99f12015-03-13 11:47:42 -070011#include "GrBatchAtlas.h"
joshualitt6065b882015-02-24 13:20:59 -080012#include "GrBufferAllocPool.h"
kkinnunencabe20c2015-06-01 01:37:26 -070013#include "GrContext.h"
joshualitt4d8da812015-01-28 12:53:54 -080014#include "GrPendingProgramElement.h"
joshualitt7bc18b72015-02-03 16:41:41 -080015#include "GrPipeline.h"
joshualitt4d8da812015-01-28 12:53:54 -080016#include "GrTRecorder.h"
bsalomoncb8979d2015-05-05 09:51:38 -070017#include "GrVertices.h"
joshualitt4d8da812015-01-28 12:53:54 -080018
19/*
20 * GrBatch instances use this object to allocate space for their geometry and to issue the draws
21 * that render their batch.
22 */
joshualitt4d8da812015-01-28 12:53:54 -080023class GrBatchTarget : public SkNoncopyable {
24public:
joshualitt5bf99f12015-03-13 11:47:42 -070025 typedef GrBatchAtlas::BatchToken BatchToken;
robertphillipse40d3972015-05-07 09:51:43 -070026 GrBatchTarget(GrGpu* gpu);
joshualitt4d8da812015-01-28 12:53:54 -080027
joshualitt4d8da812015-01-28 12:53:54 -080028 void initDraw(const GrPrimitiveProcessor* primProc, const GrPipeline* pipeline) {
29 GrNEW_APPEND_TO_RECORDER(fFlushBuffer, BufferedFlush, (primProc, pipeline));
joshualitt7bc18b72015-02-03 16:41:41 -080030 fNumberOfDraws++;
joshualitt5bf99f12015-03-13 11:47:42 -070031 fCurrentToken++;
32 }
33
34 class TextureUploader {
35 public:
36 TextureUploader(GrGpu* gpu) : fGpu(gpu) { SkASSERT(gpu); }
37
38 /**
39 * Updates the pixels in a rectangle of a texture.
40 *
41 * @param left left edge of the rectangle to write (inclusive)
42 * @param top top edge of the rectangle to write (inclusive)
43 * @param width width of rectangle to write in pixels.
44 * @param height height of rectangle to write in pixels.
45 * @param config the pixel config of the source buffer
46 * @param buffer memory to read pixels from
47 * @param rowBytes number of bytes between consecutive rows. Zero
48 * means rows are tightly packed.
49 */
50 bool writeTexturePixels(GrTexture* texture,
51 int left, int top, int width, int height,
52 GrPixelConfig config, const void* buffer,
53 size_t rowBytes) {
54 return fGpu->writeTexturePixels(texture, left, top, width, height, config, buffer,
55 rowBytes);
56 }
57
58 private:
59 GrGpu* fGpu;
60 };
61
62 class Uploader : public SkRefCnt {
63 public:
64 Uploader(BatchToken lastUploadToken) : fLastUploadToken(lastUploadToken) {}
65 BatchToken lastUploadToken() const { return fLastUploadToken; }
66 virtual void upload(TextureUploader)=0;
67
68 private:
69 BatchToken fLastUploadToken;
70 };
71
72 void upload(Uploader* upload) {
73 if (this->asapToken() == upload->lastUploadToken()) {
74 fAsapUploads.push_back().reset(SkRef(upload));
75 } else {
76 fInlineUploads.push_back().reset(SkRef(upload));
77 }
joshualitt4d8da812015-01-28 12:53:54 -080078 }
79
bsalomoncb8979d2015-05-05 09:51:38 -070080 void draw(const GrVertices& vertices) {
81 fFlushBuffer.back().fVertexDraws.push_back(vertices);
joshualitt4d8da812015-01-28 12:53:54 -080082 }
83
joshualitt5bf99f12015-03-13 11:47:42 -070084 bool isIssued(BatchToken token) const { return fLastFlushedToken >= token; }
85 BatchToken currentToken() const { return fCurrentToken; }
86 BatchToken asapToken() const { return fLastFlushedToken + 1; }
87
88 // TODO much of this complexity goes away when batch is everywhere
joshualitt7bc18b72015-02-03 16:41:41 -080089 void resetNumberOfDraws() { fNumberOfDraws = 0; }
90 int numberOfDraws() const { return fNumberOfDraws; }
joshualitt5bf99f12015-03-13 11:47:42 -070091 void preFlush() {
robertphillipse40d3972015-05-07 09:51:43 -070092 this->unmapVertexAndIndexBuffers();
joshualitt5bf99f12015-03-13 11:47:42 -070093 int updateCount = fAsapUploads.count();
94 for (int i = 0; i < updateCount; i++) {
95 fAsapUploads[i]->upload(TextureUploader(fGpu));
joshualitt7bc18b72015-02-03 16:41:41 -080096 }
joshualitt5bf99f12015-03-13 11:47:42 -070097 fInlineUpdatesIndex = 0;
98 fIter = FlushBuffer::Iter(fFlushBuffer);
joshualitt7bc18b72015-02-03 16:41:41 -080099 }
joshualitt5bf99f12015-03-13 11:47:42 -0700100 void flushNext(int n);
101 void postFlush() {
102 SkASSERT(!fIter.next());
103 fFlushBuffer.reset();
104 fAsapUploads.reset();
105 fInlineUploads.reset();
106 }
joshualitt4d8da812015-01-28 12:53:54 -0800107
bsalomon4b91f762015-05-19 09:29:46 -0700108 const GrCaps& caps() const { return *fGpu->caps(); }
joshualitt7bc18b72015-02-03 16:41:41 -0800109
bsalomoned0bcad2015-05-04 10:36:42 -0700110 GrResourceProvider* resourceProvider() const { return fGpu->getContext()->resourceProvider(); }
joshualitt76e7fb62015-02-11 08:52:27 -0800111
robertphillipse40d3972015-05-07 09:51:43 -0700112 void* makeVertSpace(size_t vertexSize, int vertexCount,
113 const GrVertexBuffer** buffer, int* startVertex);
114 uint16_t* makeIndexSpace(int indexCount,
115 const GrIndexBuffer** buffer, int* startIndex);
116
joshualitt6065b882015-02-24 13:20:59 -0800117 // A helper for draws which overallocate and then return data to the pool
robertphillips1b8e1b52015-06-24 06:54:10 -0700118 void putBackIndices(size_t indices) { fIndexPool.putBack(indices * sizeof(uint16_t)); }
joshualitt6065b882015-02-24 13:20:59 -0800119
120 void putBackVertices(size_t vertices, size_t vertexStride) {
robertphillips1b8e1b52015-06-24 06:54:10 -0700121 fVertexPool.putBack(vertices * vertexStride);
joshualitt6065b882015-02-24 13:20:59 -0800122 }
123
robertphillipse40d3972015-05-07 09:51:43 -0700124 void reset() {
robertphillips1b8e1b52015-06-24 06:54:10 -0700125 fVertexPool.reset();
126 fIndexPool.reset();
robertphillipse40d3972015-05-07 09:51:43 -0700127 }
128
joshualitt4d8da812015-01-28 12:53:54 -0800129private:
robertphillipse40d3972015-05-07 09:51:43 -0700130 void unmapVertexAndIndexBuffers() {
robertphillips1b8e1b52015-06-24 06:54:10 -0700131 fVertexPool.unmap();
132 fIndexPool.unmap();
robertphillipse40d3972015-05-07 09:51:43 -0700133 }
134
joshualitt4d8da812015-01-28 12:53:54 -0800135 GrGpu* fGpu;
robertphillips1b8e1b52015-06-24 06:54:10 -0700136 GrVertexBufferAllocPool fVertexPool;
137 GrIndexBufferAllocPool fIndexPool;
joshualitt4d8da812015-01-28 12:53:54 -0800138
139 typedef void* TBufferAlign; // This wouldn't be enough align if a command used long double.
140
141 struct BufferedFlush {
142 BufferedFlush(const GrPrimitiveProcessor* primProc, const GrPipeline* pipeline)
143 : fPrimitiveProcessor(primProc)
joshualitt7bc18b72015-02-03 16:41:41 -0800144 , fPipeline(pipeline) {}
joshualitt4d8da812015-01-28 12:53:54 -0800145 typedef GrPendingProgramElement<const GrPrimitiveProcessor> ProgramPrimitiveProcessor;
146 ProgramPrimitiveProcessor fPrimitiveProcessor;
147 const GrPipeline* fPipeline;
148 GrBatchTracker fBatchTracker;
bsalomoncb8979d2015-05-05 09:51:38 -0700149 SkSTArray<1, GrVertices, true> fVertexDraws;
joshualitt4d8da812015-01-28 12:53:54 -0800150 };
151
152 enum {
153 kFlushBufferInitialSizeInBytes = 8 * sizeof(BufferedFlush),
joshualitt4d8da812015-01-28 12:53:54 -0800154 };
155
156 typedef GrTRecorder<BufferedFlush, TBufferAlign> FlushBuffer;
157
158 FlushBuffer fFlushBuffer;
159 // TODO this is temporary
160 FlushBuffer::Iter fIter;
joshualitt7bc18b72015-02-03 16:41:41 -0800161 int fNumberOfDraws;
joshualitt5bf99f12015-03-13 11:47:42 -0700162 BatchToken fCurrentToken;
163 BatchToken fLastFlushedToken; // The next token to be flushed
164 SkTArray<SkAutoTUnref<Uploader>, true> fAsapUploads;
165 SkTArray<SkAutoTUnref<Uploader>, true> fInlineUploads;
166 int fInlineUpdatesIndex;
joshualitt4d8da812015-01-28 12:53:54 -0800167};
168
169#endif