| 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 |