blob: 8d83d2cbd602dc5ceab3895e360142a36c975a96 [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"
joshualitt4d8da812015-01-28 12:53:54 -080013#include "GrPendingProgramElement.h"
joshualitt7bc18b72015-02-03 16:41:41 -080014#include "GrPipeline.h"
joshualitt4d8da812015-01-28 12:53:54 -080015#include "GrTRecorder.h"
bsalomoncb8979d2015-05-05 09:51:38 -070016#include "GrVertices.h"
joshualitt4d8da812015-01-28 12:53:54 -080017
18/*
19 * GrBatch instances use this object to allocate space for their geometry and to issue the draws
20 * that render their batch.
21 */
joshualitt4d8da812015-01-28 12:53:54 -080022class GrBatchTarget : public SkNoncopyable {
23public:
joshualitt5bf99f12015-03-13 11:47:42 -070024 typedef GrBatchAtlas::BatchToken BatchToken;
robertphillipse40d3972015-05-07 09:51:43 -070025 GrBatchTarget(GrGpu* gpu);
joshualitt4d8da812015-01-28 12:53:54 -080026
joshualitt4d8da812015-01-28 12:53:54 -080027 void initDraw(const GrPrimitiveProcessor* primProc, const GrPipeline* pipeline) {
28 GrNEW_APPEND_TO_RECORDER(fFlushBuffer, BufferedFlush, (primProc, pipeline));
joshualitt7bc18b72015-02-03 16:41:41 -080029 fNumberOfDraws++;
joshualitt5bf99f12015-03-13 11:47:42 -070030 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 }
joshualitt4d8da812015-01-28 12:53:54 -080077 }
78
bsalomoncb8979d2015-05-05 09:51:38 -070079 void draw(const GrVertices& vertices) {
80 fFlushBuffer.back().fVertexDraws.push_back(vertices);
joshualitt4d8da812015-01-28 12:53:54 -080081 }
82
joshualitt5bf99f12015-03-13 11:47:42 -070083 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
joshualitt7bc18b72015-02-03 16:41:41 -080088 void resetNumberOfDraws() { fNumberOfDraws = 0; }
89 int numberOfDraws() const { return fNumberOfDraws; }
joshualitt5bf99f12015-03-13 11:47:42 -070090 void preFlush() {
robertphillipse40d3972015-05-07 09:51:43 -070091 this->unmapVertexAndIndexBuffers();
joshualitt5bf99f12015-03-13 11:47:42 -070092 int updateCount = fAsapUploads.count();
93 for (int i = 0; i < updateCount; i++) {
94 fAsapUploads[i]->upload(TextureUploader(fGpu));
joshualitt7bc18b72015-02-03 16:41:41 -080095 }
joshualitt5bf99f12015-03-13 11:47:42 -070096 fInlineUpdatesIndex = 0;
97 fIter = FlushBuffer::Iter(fFlushBuffer);
joshualitt7bc18b72015-02-03 16:41:41 -080098 }
joshualitt5bf99f12015-03-13 11:47:42 -070099 void flushNext(int n);
100 void postFlush() {
101 SkASSERT(!fIter.next());
102 fFlushBuffer.reset();
103 fAsapUploads.reset();
104 fInlineUploads.reset();
105 }
joshualitt4d8da812015-01-28 12:53:54 -0800106
bsalomon4b91f762015-05-19 09:29:46 -0700107 const GrCaps& caps() const { return *fGpu->caps(); }
joshualitt7bc18b72015-02-03 16:41:41 -0800108
bsalomoned0bcad2015-05-04 10:36:42 -0700109 GrResourceProvider* resourceProvider() const { return fGpu->getContext()->resourceProvider(); }
joshualitt76e7fb62015-02-11 08:52:27 -0800110
robertphillipse40d3972015-05-07 09:51:43 -0700111 void* makeVertSpace(size_t vertexSize, int vertexCount,
112 const GrVertexBuffer** buffer, int* startVertex);
113 uint16_t* makeIndexSpace(int indexCount,
114 const GrIndexBuffer** buffer, int* startIndex);
115
joshualitt6065b882015-02-24 13:20:59 -0800116 // A helper for draws which overallocate and then return data to the pool
robertphillipseea2ff72015-05-14 05:24:53 -0700117 void putBackIndices(size_t indices) { fIndexPool->putBack(indices * sizeof(uint16_t)); }
joshualitt6065b882015-02-24 13:20:59 -0800118
119 void putBackVertices(size_t vertices, size_t vertexStride) {
robertphillipseea2ff72015-05-14 05:24:53 -0700120 fVertexPool->putBack(vertices * vertexStride);
joshualitt6065b882015-02-24 13:20:59 -0800121 }
122
robertphillipse40d3972015-05-07 09:51:43 -0700123 void reset() {
robertphillipseea2ff72015-05-14 05:24:53 -0700124 fVertexPool->reset();
125 fIndexPool->reset();
robertphillipse40d3972015-05-07 09:51:43 -0700126 }
127
joshualitt4d8da812015-01-28 12:53:54 -0800128private:
robertphillipse40d3972015-05-07 09:51:43 -0700129 void unmapVertexAndIndexBuffers() {
robertphillipseea2ff72015-05-14 05:24:53 -0700130 fVertexPool->unmap();
131 fIndexPool->unmap();
robertphillipse40d3972015-05-07 09:51:43 -0700132 }
133
joshualitt4d8da812015-01-28 12:53:54 -0800134 GrGpu* fGpu;
robertphillipseea2ff72015-05-14 05:24:53 -0700135 SkAutoTDelete<GrVertexBufferAllocPool> fVertexPool;
136 SkAutoTDelete<GrIndexBufferAllocPool> fIndexPool;
joshualitt4d8da812015-01-28 12:53:54 -0800137
138 typedef void* TBufferAlign; // This wouldn't be enough align if a command used long double.
139
140 struct BufferedFlush {
141 BufferedFlush(const GrPrimitiveProcessor* primProc, const GrPipeline* pipeline)
142 : fPrimitiveProcessor(primProc)
joshualitt7bc18b72015-02-03 16:41:41 -0800143 , fPipeline(pipeline) {}
joshualitt4d8da812015-01-28 12:53:54 -0800144 typedef GrPendingProgramElement<const GrPrimitiveProcessor> ProgramPrimitiveProcessor;
145 ProgramPrimitiveProcessor fPrimitiveProcessor;
146 const GrPipeline* fPipeline;
147 GrBatchTracker fBatchTracker;
bsalomoncb8979d2015-05-05 09:51:38 -0700148 SkSTArray<1, GrVertices, true> fVertexDraws;
joshualitt4d8da812015-01-28 12:53:54 -0800149 };
150
151 enum {
152 kFlushBufferInitialSizeInBytes = 8 * sizeof(BufferedFlush),
joshualitt4d8da812015-01-28 12:53:54 -0800153 };
154
155 typedef GrTRecorder<BufferedFlush, TBufferAlign> FlushBuffer;
156
157 FlushBuffer fFlushBuffer;
158 // TODO this is temporary
159 FlushBuffer::Iter fIter;
joshualitt7bc18b72015-02-03 16:41:41 -0800160 int fNumberOfDraws;
joshualitt5bf99f12015-03-13 11:47:42 -0700161 BatchToken fCurrentToken;
162 BatchToken fLastFlushedToken; // The next token to be flushed
163 SkTArray<SkAutoTUnref<Uploader>, true> fAsapUploads;
164 SkTArray<SkAutoTUnref<Uploader>, true> fInlineUploads;
165 int fInlineUpdatesIndex;
joshualitt4d8da812015-01-28 12:53:54 -0800166};
167
168#endif