int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info) { SkASSERT(info.isInstanced()); const GeometrySrcState& geomSrc = this->getGeomSrc(); const GrDrawState& drawState = this->getDrawState(); // we only attempt to concat the case when reserved verts are used with a client-specified index // buffer. To make this work with client-specified VBs we'd need to know if the VB was updated // between draws. if (kReserved_GeometrySrcType != geomSrc.fVertexSrc || kBuffer_GeometrySrcType != geomSrc.fIndexSrc) { return 0; } // Check if there is a draw info that is compatible that uses the same VB from the pool and // the same IB if (kDraw_Cmd != strip_trace_bit(fCmds.back())) { return 0; } DrawRecord* draw = &fDraws.back(); GeometryPoolState& poolState = fGeoPoolStateStack.back(); const GrVertexBuffer* vertexBuffer = poolState.fPoolVertexBuffer; if (!draw->isInstanced() || draw->verticesPerInstance() != info.verticesPerInstance() || draw->indicesPerInstance() != info.indicesPerInstance() || draw->fVertexBuffer != vertexBuffer || draw->fIndexBuffer != geomSrc.fIndexBuffer) { return 0; } // info does not yet account for the offset from the start of the pool's VB while the previous // draw record does. int adjustedStartVertex = poolState.fPoolStartVertex + info.startVertex(); if (draw->startVertex() + draw->vertexCount() != adjustedStartVertex) { return 0; } SkASSERT(poolState.fPoolStartVertex == draw->startVertex() + draw->vertexCount()); // how many instances can be concat'ed onto draw given the size of the index buffer int instancesToConcat = this->indexCountInCurrentSource() / info.indicesPerInstance(); instancesToConcat -= draw->instanceCount(); instancesToConcat = SkTMin(instancesToConcat, info.instanceCount()); // update the amount of reserved vertex data actually referenced in draws size_t vertexBytes = instancesToConcat * info.verticesPerInstance() * drawState.getVertexSize(); poolState.fUsedPoolVertexBytes = SkTMax(poolState.fUsedPoolVertexBytes, vertexBytes); draw->adjustInstanceCount(instancesToConcat); // update last fGpuCmdMarkers to include any additional trace markers that have been added if (this->getActiveTraceMarkers().count() > 0) { if (cmd_has_trace_marker(fCmds.back())) { fGpuCmdMarkers.back().addSet(this->getActiveTraceMarkers()); } else { fGpuCmdMarkers.push_back(this->getActiveTraceMarkers()); fCmds.back() = add_trace_bit(fCmds.back()); } } return instancesToConcat; }
void GrInOrderDrawBuffer::flush() { if (fFlushing) { return; } SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc); SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc); int numCmds = fCmds.count(); if (0 == numCmds) { return; } GrAutoTRestore<bool> flushRestore(&fFlushing); fFlushing = true; fVertexPool.unmap(); fIndexPool.unmap(); GrDrawTarget::AutoClipRestore acr(fDstGpu); AutoGeometryAndStatePush agasp(fDstGpu, kPreserve_ASRInit); GrDrawState playbackState; GrDrawState* prevDrawState = fDstGpu->drawState(); prevDrawState->ref(); fDstGpu->setDrawState(&playbackState); GrClipData clipData; int currState = 0; int currClip = 0; int currClear = 0; int currDraw = 0; int currStencilPath = 0; int currDrawPath = 0; int currDrawPaths = 0; int currCopySurface = 0; int currCmdMarker = 0; for (int c = 0; c < numCmds; ++c) { GrGpuTraceMarker newMarker("", -1); if (cmd_has_trace_marker(fCmds[c])) { SkString traceString = fGpuCmdMarkers[currCmdMarker].toString(); newMarker.fMarker = traceString.c_str(); fDstGpu->addGpuTraceMarker(&newMarker); ++currCmdMarker; } switch (strip_trace_bit(fCmds[c])) { case kDraw_Cmd: { const DrawRecord& draw = fDraws[currDraw]; fDstGpu->setVertexSourceToBuffer(draw.fVertexBuffer); if (draw.isIndexed()) { fDstGpu->setIndexSourceToBuffer(draw.fIndexBuffer); } fDstGpu->executeDraw(draw); ++currDraw; break; } case kStencilPath_Cmd: { const StencilPath& sp = fStencilPaths[currStencilPath]; fDstGpu->stencilPath(sp.fPath.get(), sp.fFill); ++currStencilPath; break; } case kDrawPath_Cmd: { const DrawPath& cp = fDrawPath[currDrawPath]; fDstGpu->executeDrawPath(cp.fPath.get(), cp.fFill, NULL != cp.fDstCopy.texture() ? &cp.fDstCopy : NULL); ++currDrawPath; break; } case kDrawPaths_Cmd: { DrawPaths& dp = fDrawPaths[currDrawPaths]; const GrDeviceCoordTexture* dstCopy = NULL != dp.fDstCopy.texture() ? &dp.fDstCopy : NULL; fDstGpu->executeDrawPaths(dp.fPathCount, dp.fPaths, dp.fTransforms, dp.fFill, dp.fStroke, dstCopy); ++currDrawPaths; break; } case kSetState_Cmd: fStates[currState].restoreTo(&playbackState); ++currState; break; case kSetClip_Cmd: clipData.fClipStack = &fClips[currClip]; clipData.fOrigin = fClipOrigins[currClip]; fDstGpu->setClip(&clipData); ++currClip; break; case kClear_Cmd: if (GrColor_ILLEGAL == fClears[currClear].fColor) { fDstGpu->discard(fClears[currClear].fRenderTarget); } else { fDstGpu->clear(&fClears[currClear].fRect, fClears[currClear].fColor, fClears[currClear].fCanIgnoreRect, fClears[currClear].fRenderTarget); } ++currClear; break; case kCopySurface_Cmd: fDstGpu->copySurface(fCopySurfaces[currCopySurface].fDst.get(), fCopySurfaces[currCopySurface].fSrc.get(), fCopySurfaces[currCopySurface].fSrcRect, fCopySurfaces[currCopySurface].fDstPoint); ++currCopySurface; break; } if (cmd_has_trace_marker(fCmds[c])) { fDstGpu->removeGpuTraceMarker(&newMarker); } } // we should have consumed all the states, clips, etc. SkASSERT(fStates.count() == currState); SkASSERT(fClips.count() == currClip); SkASSERT(fClipOrigins.count() == currClip); SkASSERT(fClears.count() == currClear); SkASSERT(fDraws.count() == currDraw); SkASSERT(fCopySurfaces.count() == currCopySurface); SkASSERT(fGpuCmdMarkers.count() == currCmdMarker); fDstGpu->setDrawState(prevDrawState); prevDrawState->unref(); this->reset(); ++fDrawID; }
void GrInOrderDrawBuffer::flush() { if (fFlushing) { return; } this->getContext()->getFontCache()->updateTextures(); SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc); SkASSERT(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc); if (fCmdBuffer.empty()) { return; } GrAutoTRestore<bool> flushRestore(&fFlushing); fFlushing = true; fVertexPool.unmap(); fIndexPool.unmap(); GrDrawTarget::AutoClipRestore acr(fDstGpu); AutoGeometryAndStatePush agasp(fDstGpu, kPreserve_ASRInit); GrDrawState* prevDrawState = SkRef(fDstGpu->drawState()); CmdBuffer::Iter iter(fCmdBuffer); int currCmdMarker = 0; fDstGpu->saveActiveTraceMarkers(); while (iter.next()) { GrGpuTraceMarker newMarker("", -1); SkString traceString; if (cmd_has_trace_marker(iter->fType)) { traceString = fGpuCmdMarkers[currCmdMarker].toString(); newMarker.fMarker = traceString.c_str(); fDstGpu->addGpuTraceMarker(&newMarker); ++currCmdMarker; } SkDEBUGCODE(bool isDraw = kDraw_Cmd == strip_trace_bit(iter->fType) || kStencilPath_Cmd == strip_trace_bit(iter->fType) || kDrawPath_Cmd == strip_trace_bit(iter->fType) || kDrawPaths_Cmd == strip_trace_bit(iter->fType)); SkASSERT(!isDraw || fDstGpu->drawState() != prevDrawState); iter->execute(fDstGpu); if (cmd_has_trace_marker(iter->fType)) { fDstGpu->removeGpuTraceMarker(&newMarker); } } fDstGpu->restoreActiveTraceMarkers(); SkASSERT(fGpuCmdMarkers.count() == currCmdMarker); fDstGpu->setDrawState(prevDrawState); prevDrawState->unref(); this->reset(); ++fDrawID; }