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