bool GrInOrderDrawBuffer::flush() { GrAssert(kReserved_GeometrySrcType != this->getGeomSrc().fVertexSrc); GrAssert(kReserved_GeometrySrcType != this->getGeomSrc().fIndexSrc); int numCmds = fCmds.count(); if (0 == numCmds) { return false; } GrAssert(!fFlushing); GrAutoTRestore<bool> flushRestore(&fFlushing); fFlushing = true; fVertexPool.unlock(); fIndexPool.unlock(); 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 currCopySurface = 0; for (int c = 0; c < numCmds; ++c) { switch (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.fStroke, sp.fFill); ++currStencilPath; 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: fDstGpu->clear(&fClears[currClear].fRect, fClears[currClear].fColor, 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; } } // we should have consumed all the states, clips, etc. GrAssert(fStates.count() == currState); GrAssert(fClips.count() == currClip); GrAssert(fClipOrigins.count() == currClip); GrAssert(fClears.count() == currClear); GrAssert(fDraws.count() == currDraw); GrAssert(fCopySurfaces.count() == currCopySurface); fDstGpu->setDrawState(prevDrawState); prevDrawState->unref(); this->reset(); return true; }
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; }
bool GrDefaultPathRenderer::internalDrawPath(const SkPath& path, const SkStrokeRec& origStroke, GrDrawTarget* target, bool stencilOnly) { SkMatrix viewM = target->getDrawState().getViewMatrix(); SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke); SkScalar hairlineCoverage; if (IsStrokeHairlineOrEquivalent(*stroke, target->getDrawState().getViewMatrix(), &hairlineCoverage)) { uint8_t newCoverage = SkScalarRoundToInt(hairlineCoverage * target->getDrawState().getCoverage()); target->drawState()->setCoverage(newCoverage); if (!stroke->isHairlineStyle()) { stroke.writable()->setHairlineStyle(); } } SkScalar tol = SK_Scalar1; tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, path.getBounds()); int vertexCnt; int indexCnt; GrPrimitiveType primType; GrDrawTarget::AutoReleaseGeometry arg; if (!this->createGeom(path, *stroke, tol, target, &primType, &vertexCnt, &indexCnt, &arg)) { return false; } SkASSERT(NULL != target); GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kPreserve_ASRInit); GrDrawState* drawState = target->drawState(); bool colorWritesWereDisabled = drawState->isColorWriteDisabled(); // face culling doesn't make sense here SkASSERT(GrDrawState::kBoth_DrawFace == drawState->getDrawFace()); int passCount = 0; const GrStencilSettings* passes[3]; GrDrawState::DrawFace drawFace[3]; bool reverse = false; bool lastPassIsBounds; if (stroke->isHairlineStyle()) { passCount = 1; if (stencilOnly) { passes[0] = &gDirectToStencil; } else { passes[0] = NULL; } lastPassIsBounds = false; drawFace[0] = GrDrawState::kBoth_DrawFace; } else { if (single_pass_path(path, *stroke)) { passCount = 1; if (stencilOnly) { passes[0] = &gDirectToStencil; } else { passes[0] = NULL; } drawFace[0] = GrDrawState::kBoth_DrawFace; lastPassIsBounds = false; } else { switch (path.getFillType()) { case SkPath::kInverseEvenOdd_FillType: reverse = true; // fallthrough case SkPath::kEvenOdd_FillType: passes[0] = &gEOStencilPass; if (stencilOnly) { passCount = 1; lastPassIsBounds = false; } else { passCount = 2; lastPassIsBounds = true; if (reverse) { passes[1] = &gInvEOColorPass; } else { passes[1] = &gEOColorPass; } } drawFace[0] = drawFace[1] = GrDrawState::kBoth_DrawFace; break; case SkPath::kInverseWinding_FillType: reverse = true; // fallthrough case SkPath::kWinding_FillType: if (fSeparateStencil) { if (fStencilWrapOps) { passes[0] = &gWindStencilSeparateWithWrap; } else { passes[0] = &gWindStencilSeparateNoWrap; } passCount = 2; drawFace[0] = GrDrawState::kBoth_DrawFace; } else { if (fStencilWrapOps) { passes[0] = &gWindSingleStencilWithWrapInc; passes[1] = &gWindSingleStencilWithWrapDec; } else { passes[0] = &gWindSingleStencilNoWrapInc; passes[1] = &gWindSingleStencilNoWrapDec; } // which is cw and which is ccw is arbitrary. drawFace[0] = GrDrawState::kCW_DrawFace; drawFace[1] = GrDrawState::kCCW_DrawFace; passCount = 3; } if (stencilOnly) { lastPassIsBounds = false; --passCount; } else { lastPassIsBounds = true; drawFace[passCount-1] = GrDrawState::kBoth_DrawFace; if (reverse) { passes[passCount-1] = &gInvWindColorPass; } else { passes[passCount-1] = &gWindColorPass; } } break; default: SkDEBUGFAIL("Unknown path fFill!"); return false; } } } SkRect devBounds; GetPathDevBounds(path, drawState->getRenderTarget(), viewM, &devBounds); for (int p = 0; p < passCount; ++p) { drawState->setDrawFace(drawFace[p]); if (NULL != passes[p]) { *drawState->stencil() = *passes[p]; } if (lastPassIsBounds && (p == passCount-1)) { if (!colorWritesWereDisabled) { drawState->disableState(GrDrawState::kNoColorWrites_StateBit); } SkRect bounds; GrDrawState::AutoViewMatrixRestore avmr; if (reverse) { SkASSERT(NULL != drawState->getRenderTarget()); // draw over the dev bounds (which will be the whole dst surface for inv fill). bounds = devBounds; SkMatrix vmi; // mapRect through persp matrix may not be correct if (!drawState->getViewMatrix().hasPerspective() && drawState->getViewInverse(&vmi)) { vmi.mapRect(&bounds); } else { avmr.setIdentity(drawState); } } else { bounds = path.getBounds(); } GrDrawTarget::AutoGeometryAndStatePush agasp(target, GrDrawTarget::kPreserve_ASRInit); target->drawSimpleRect(bounds, NULL); } else { if (passCount > 1) { drawState->enableState(GrDrawState::kNoColorWrites_StateBit); } if (indexCnt) { target->drawIndexed(primType, 0, 0, vertexCnt, indexCnt, &devBounds); } else { target->drawNonIndexed(primType, 0, vertexCnt, &devBounds); } } } return true; }
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; }