OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrFlushToGpuDrawTarget.h" | 8 #include "GrFlushToGpuDrawTarget.h" |
9 #include "GrContext.h" | 9 #include "GrContext.h" |
10 #include "GrGpu.h" | 10 #include "GrGpu.h" |
11 #include "GrBufferAllocPool.h" | 11 #include "GrBufferAllocPool.h" |
12 | 12 |
13 GrFlushToGpuDrawTarget::GrFlushToGpuDrawTarget(GrGpu* gpu, | 13 GrFlushToGpuDrawTarget::GrFlushToGpuDrawTarget(GrGpu* gpu, |
14 GrVertexBufferAllocPool* vertexPo
ol, | 14 GrVertexBufferAllocPool* vertexPo
ol, |
15 GrIndexBufferAllocPool* indexPool
) | 15 GrIndexBufferAllocPool* indexPool
) |
16 : INHERITED(gpu->getContext()) | 16 : INHERITED(gpu->getContext()) |
17 , fGpu(SkRef(gpu)) | 17 , fGpu(SkRef(gpu)) |
18 , fVertexPool(vertexPool) | 18 , fVertexPool(vertexPool) |
19 , fIndexPool(indexPool) | 19 , fIndexPool(indexPool) |
20 , fFlushing(false) { | 20 , fFlushing(false) { |
21 | 21 |
22 fCaps.reset(SkRef(fGpu->caps())); | 22 fCaps.reset(SkRef(fGpu->caps())); |
23 | 23 |
24 SkASSERT(vertexPool); | 24 SkASSERT(vertexPool); |
25 SkASSERT(indexPool); | 25 SkASSERT(indexPool); |
26 | 26 |
27 GeometryPoolState& poolState = fGeoPoolStateStack.push_back(); | |
28 poolState.fUsedPoolVertexBytes = 0; | |
29 poolState.fUsedPoolIndexBytes = 0; | |
30 #ifdef SK_DEBUG | |
31 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0; | |
32 poolState.fPoolStartVertex = ~0; | |
33 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0; | |
34 poolState.fPoolStartIndex = ~0; | |
35 #endif | |
36 } | |
37 | |
38 GrFlushToGpuDrawTarget::~GrFlushToGpuDrawTarget() { | |
39 // This must be called by before the GrDrawTarget destructor | |
40 this->releaseGeometry(); | |
41 } | |
42 | |
43 void GrFlushToGpuDrawTarget::setDrawBuffers(DrawInfo* info, size_t vertexStride)
{ | |
44 GeometryPoolState& poolState = fGeoPoolStateStack.back(); | |
45 if (kBuffer_GeometrySrcType == this->getGeomSrc().fVertexSrc) { | |
46 info->setVertexBuffer(this->getGeomSrc().fVertexBuffer); | |
47 } else { | |
48 // Update the bytes used since the last reserve-geom request. | |
49 size_t bytes = (info->vertexCount() + info->startVertex()) * vertexStrid
e; | |
50 poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes,
bytes); | |
51 info->setVertexBuffer(poolState.fPoolVertexBuffer); | |
52 info->adjustStartVertex(poolState.fPoolStartVertex); | |
53 } | |
54 | |
55 if (info->isIndexed()) { | |
56 if (kBuffer_GeometrySrcType == this->getGeomSrc().fIndexSrc) { | |
57 info->setIndexBuffer(this->getGeomSrc().fIndexBuffer); | |
58 } else { | |
59 // Update the bytes used since the last reserve-geom request. | |
60 size_t bytes = (info->indexCount() + info->startIndex()) * sizeof(ui
nt16_t); | |
61 poolState.fUsedPoolIndexBytes = SkTMax(poolState.fUsedPoolIndexBytes
, bytes); | |
62 info->setIndexBuffer(poolState.fPoolIndexBuffer); | |
63 info->adjustStartIndex(poolState.fPoolStartIndex); | |
64 } | |
65 } | |
66 } | 27 } |
67 | 28 |
68 void GrFlushToGpuDrawTarget::reset() { | 29 void GrFlushToGpuDrawTarget::reset() { |
69 SkASSERT(1 == fGeoPoolStateStack.count()); | |
70 this->resetVertexSource(); | |
71 this->resetIndexSource(); | |
72 | |
73 fVertexPool->reset(); | 30 fVertexPool->reset(); |
74 fIndexPool->reset(); | 31 fIndexPool->reset(); |
75 | 32 |
76 this->onReset(); | 33 this->onReset(); |
77 } | 34 } |
78 | 35 |
79 void GrFlushToGpuDrawTarget::flush() { | 36 void GrFlushToGpuDrawTarget::flush() { |
80 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc); | |
81 SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc); | |
82 | |
83 if (fFlushing) { | 37 if (fFlushing) { |
84 return; | 38 return; |
85 } | 39 } |
86 fFlushing = true; | 40 fFlushing = true; |
87 | 41 |
88 fGpu->saveActiveTraceMarkers(); | 42 fGpu->saveActiveTraceMarkers(); |
89 | 43 |
90 this->onFlush(); | 44 this->onFlush(); |
91 | 45 |
92 fGpu->restoreActiveTraceMarkers(); | 46 fGpu->restoreActiveTraceMarkers(); |
93 | 47 |
94 fFlushing = false; | 48 fFlushing = false; |
95 this->reset(); | 49 this->reset(); |
96 } | 50 } |
97 | 51 |
98 void GrFlushToGpuDrawTarget::willReserveVertexAndIndexSpace(int vertexCount, | |
99 size_t vertexStride, | |
100 int indexCount) { | |
101 // We use geometryHints() to know whether to flush the draw buffer. We | |
102 // can't flush if we are inside an unbalanced pushGeometrySource. | |
103 // Moreover, flushing blows away vertex and index data that was | |
104 // previously reserved. So if the vertex or index data is pulled from | |
105 // reserved space and won't be released by this request then we can't | |
106 // flush. | |
107 bool insideGeoPush = fGeoPoolStateStack.count() > 1; | |
108 | |
109 bool unreleasedVertexSpace = | |
110 !vertexCount && | |
111 kReserved_GeometrySrcType == this->getGeomSrc().fVertexSrc; | |
112 | |
113 bool unreleasedIndexSpace = | |
114 !indexCount && | |
115 kReserved_GeometrySrcType == this->getGeomSrc().fIndexSrc; | |
116 | |
117 int vcount = vertexCount; | |
118 int icount = indexCount; | |
119 | |
120 if (!insideGeoPush && | |
121 !unreleasedVertexSpace && | |
122 !unreleasedIndexSpace && | |
123 this->geometryHints(vertexStride, &vcount, &icount)) { | |
124 this->flush(); | |
125 } | |
126 } | |
127 | |
128 bool GrFlushToGpuDrawTarget::geometryHints(size_t vertexStride, | |
129 int* vertexCount, | |
130 int* indexCount) const { | |
131 // we will recommend a flush if the data could fit in a single | |
132 // preallocated buffer but none are left and it can't fit | |
133 // in the current buffer (which may not be prealloced). | |
134 bool flush = false; | |
135 if (indexCount) { | |
136 int32_t currIndices = fIndexPool->currentBufferIndices(); | |
137 if (*indexCount > currIndices && | |
138 (!fIndexPool->preallocatedBuffersRemaining() && | |
139 *indexCount <= fIndexPool->preallocatedBufferIndices())) { | |
140 | |
141 flush = true; | |
142 } | |
143 *indexCount = currIndices; | |
144 } | |
145 if (vertexCount) { | |
146 int32_t currVertices = fVertexPool->currentBufferVertices(vertexStride); | |
147 if (*vertexCount > currVertices && | |
148 (!fVertexPool->preallocatedBuffersRemaining() && | |
149 *vertexCount <= fVertexPool->preallocatedBufferVertices(vertexStrid
e))) { | |
150 | |
151 flush = true; | |
152 } | |
153 *vertexCount = currVertices; | |
154 } | |
155 return flush; | |
156 } | |
157 | |
158 bool GrFlushToGpuDrawTarget::onReserveVertexSpace(size_t vertexSize, | |
159 int vertexCount, | |
160 void** vertices) { | |
161 GeometryPoolState& poolState = fGeoPoolStateStack.back(); | |
162 SkASSERT(vertexCount > 0); | |
163 SkASSERT(vertices); | |
164 SkASSERT(0 == poolState.fUsedPoolVertexBytes); | |
165 | |
166 *vertices = fVertexPool->makeSpace(vertexSize, | |
167 vertexCount, | |
168 &poolState.fPoolVertexBuffer, | |
169 &poolState.fPoolStartVertex); | |
170 return SkToBool(*vertices); | |
171 } | |
172 | |
173 bool GrFlushToGpuDrawTarget::onReserveIndexSpace(int indexCount, void** indices)
{ | |
174 GeometryPoolState& poolState = fGeoPoolStateStack.back(); | |
175 SkASSERT(indexCount > 0); | |
176 SkASSERT(indices); | |
177 SkASSERT(0 == poolState.fUsedPoolIndexBytes); | |
178 | |
179 *indices = fIndexPool->makeSpace(indexCount, | |
180 &poolState.fPoolIndexBuffer, | |
181 &poolState.fPoolStartIndex); | |
182 return SkToBool(*indices); | |
183 } | |
184 | |
185 void GrFlushToGpuDrawTarget::releaseReservedVertexSpace() { | |
186 GeometryPoolState& poolState = fGeoPoolStateStack.back(); | |
187 const GeometrySrcState& geoSrc = this->getGeomSrc(); | |
188 | |
189 // If we get a release vertex space call then our current source should eith
er be reserved | |
190 // or array (which we copied into reserved space). | |
191 SkASSERT(kReserved_GeometrySrcType == geoSrc.fVertexSrc); | |
192 | |
193 // When the caller reserved vertex buffer space we gave it back a pointer | |
194 // provided by the vertex buffer pool. At each draw we tracked the largest | |
195 // offset into the pool's pointer that was referenced. Now we return to the | |
196 // pool any portion at the tail of the allocation that no draw referenced. | |
197 size_t reservedVertexBytes = geoSrc.fVertexSize * geoSrc.fVertexCount; | |
198 fVertexPool->putBack(reservedVertexBytes - poolState.fUsedPoolVertexBytes); | |
199 poolState.fUsedPoolVertexBytes = 0; | |
200 poolState.fPoolVertexBuffer = NULL; | |
201 poolState.fPoolStartVertex = 0; | |
202 } | |
203 | |
204 void GrFlushToGpuDrawTarget::releaseReservedIndexSpace() { | |
205 GeometryPoolState& poolState = fGeoPoolStateStack.back(); | |
206 const GeometrySrcState& geoSrc = this->getGeomSrc(); | |
207 | |
208 // If we get a release index space call then our current source should eithe
r be reserved | |
209 // or array (which we copied into reserved space). | |
210 SkASSERT(kReserved_GeometrySrcType == geoSrc.fIndexSrc); | |
211 | |
212 // Similar to releaseReservedVertexSpace we return any unused portion at | |
213 // the tail | |
214 size_t reservedIndexBytes = sizeof(uint16_t) * geoSrc.fIndexCount; | |
215 fIndexPool->putBack(reservedIndexBytes - poolState.fUsedPoolIndexBytes); | |
216 poolState.fUsedPoolIndexBytes = 0; | |
217 poolState.fPoolIndexBuffer = NULL; | |
218 poolState.fPoolStartIndex = 0; | |
219 } | |
220 | |
221 void GrFlushToGpuDrawTarget::geometrySourceWillPush() { | |
222 GeometryPoolState& poolState = fGeoPoolStateStack.push_back(); | |
223 poolState.fUsedPoolVertexBytes = 0; | |
224 poolState.fUsedPoolIndexBytes = 0; | |
225 #ifdef SK_DEBUG | |
226 poolState.fPoolVertexBuffer = (GrVertexBuffer*)~0; | |
227 poolState.fPoolStartVertex = ~0; | |
228 poolState.fPoolIndexBuffer = (GrIndexBuffer*)~0; | |
229 poolState.fPoolStartIndex = ~0; | |
230 #endif | |
231 } | |
232 | |
233 void GrFlushToGpuDrawTarget::geometrySourceWillPop(const GeometrySrcState& resto
redState) { | |
234 SkASSERT(fGeoPoolStateStack.count() > 1); | |
235 fGeoPoolStateStack.pop_back(); | |
236 GeometryPoolState& poolState = fGeoPoolStateStack.back(); | |
237 // we have to assume that any slack we had in our vertex/index data | |
238 // is now unreleasable because data may have been appended later in the | |
239 // pool. | |
240 if (kReserved_GeometrySrcType == restoredState.fVertexSrc) { | |
241 poolState.fUsedPoolVertexBytes = restoredState.fVertexSize * restoredSta
te.fVertexCount; | |
242 } | |
243 if (kReserved_GeometrySrcType == restoredState.fIndexSrc) { | |
244 poolState.fUsedPoolIndexBytes = sizeof(uint16_t) * restoredState.fIndexC
ount; | |
245 } | |
246 } | |
247 | |
248 bool GrFlushToGpuDrawTarget::onCanCopySurface(const GrSurface* dst, | 52 bool GrFlushToGpuDrawTarget::onCanCopySurface(const GrSurface* dst, |
249 const GrSurface* src, | 53 const GrSurface* src, |
250 const SkIRect& srcRect, | 54 const SkIRect& srcRect, |
251 const SkIPoint& dstPoint) { | 55 const SkIPoint& dstPoint) { |
252 return getGpu()->canCopySurface(dst, src, srcRect, dstPoint); | 56 return getGpu()->canCopySurface(dst, src, srcRect, dstPoint); |
253 } | 57 } |
254 | 58 |
255 bool GrFlushToGpuDrawTarget::onInitCopySurfaceDstDesc(const GrSurface* src, GrSu
rfaceDesc* desc) { | 59 bool GrFlushToGpuDrawTarget::onInitCopySurfaceDstDesc(const GrSurface* src, GrSu
rfaceDesc* desc) { |
256 return getGpu()->initCopySurfaceDstDesc(src, desc); | 60 return getGpu()->initCopySurfaceDstDesc(src, desc); |
257 } | 61 } |
OLD | NEW |