blob: 2008fa69ebfc44fd014943f5292ae9a01f4f324a [file] [log] [blame]
bsalomon75398562015-08-17 12:55:38 -07001/*
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
14class GrResourceProvider;
15
16/** Simple class that performs the upload on behalf of a GrBatchUploader. */
17class GrBatchUploader::TextureUploader {
18public:
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
40private:
41 GrGpu* fGpu;
42};
43
44/** Tracks the state across all the GrBatches in a GrDrawTarget flush. */
45class GrBatchFlushState {
46public:
robertphillips1f0e3502015-11-10 10:19:50 -080047 GrBatchFlushState(GrGpu*, GrResourceProvider*);
bsalomon75398562015-08-17 12:55:38 -070048
joshualittf6d259b2015-10-02 11:27:14 -070049 ~GrBatchFlushState() { this->reset(); }
bsalomon75398562015-08-17 12:55:38 -070050
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
joshualittf6d259b2015-10-02 11:27:14 -0700102 void reset() {
103 fVertexPool.reset();
104 fIndexPool.reset();
105 }
106
bsalomon75398562015-08-17 12:55:38 -0700107private:
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 */
127class GrDrawBatch::Target {
128public:
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
149protected:
150 GrDrawBatch* batch() { return fBatch; }
151 GrBatchFlushState* state() { return fState; }
152
153private:
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. */
160class GrVertexBatch::Target : public GrDrawBatch::Target {
161public:
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
189private:
190 GrVertexBatch* vertexBatch() { return static_cast<GrVertexBatch*>(this->batch()); }
191 typedef GrDrawBatch::Target INHERITED;
192};
193
194#endif