Pass in ProcOptInfos into willNeedDstCopy on XPs

BUG=skia:

Review URL: https://codereview.chromium.org/912413002
This commit is contained in:
egdaniel 2015-02-13 09:00:33 -08:00 committed by Commit bot
parent f89f60f697
commit e36914cb20
19 changed files with 248 additions and 195 deletions

View File

@ -233,7 +233,8 @@ public:
*/
virtual bool canTweakAlphaForCoverage() const = 0;
bool willNeedDstCopy(const GrDrawTargetCaps& caps) const;
bool willNeedDstCopy(const GrDrawTargetCaps& caps, const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI) const;
bool isEqual(const GrXPFactory& that) const {
if (this->classID() != that.classID()) {
@ -267,7 +268,8 @@ private:
* Returns true if the XP generated by this factory will explicitly read dst in the fragment
* shader.
*/
virtual bool willReadDstColor() const = 0;
virtual bool willReadDstColor(const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI) const = 0;
virtual bool onIsEqual(const GrXPFactory&) const = 0;

View File

@ -43,7 +43,8 @@ private:
const GrProcOptInfo& coveragePOI,
const GrDeviceCoordTexture* dstCopy) const SK_OVERRIDE;
bool willReadDstColor() const SK_OVERRIDE;
bool willReadDstColor(const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI) const SK_OVERRIDE;
bool onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE {
const GrPorterDuffXPFactory& xpf = xpfBase.cast<GrPorterDuffXPFactory>();

View File

@ -308,7 +308,7 @@ GrArithmeticXPFactory::onCreateXferProcessor(const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI,
const GrDeviceCoordTexture* dstCopy) const {
return ArithmeticXP::Create(fK1, fK2, fK3, fK4, fEnforcePMColor, dstCopy,
this->willReadDstColor());
this->willReadDstColor(colorPOI, coveragePOI));
}

View File

@ -100,7 +100,10 @@ private:
const GrProcOptInfo& coveragePOI,
const GrDeviceCoordTexture* dstCopy) const SK_OVERRIDE;
bool willReadDstColor() const SK_OVERRIDE { return true; }
bool willReadDstColor(const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI) const SK_OVERRIDE {
return true;
}
bool onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE {
const GrArithmeticXPFactory& xpf = xpfBase.cast<GrArithmeticXPFactory>();

View File

@ -12,6 +12,7 @@
#include "GrContext.h"
#include "GrDrawTargetCaps.h"
#include "GrPath.h"
#include "GrPipeline.h"
#include "GrRenderTarget.h"
#include "GrSurfacePriv.h"
#include "GrTemplates.h"
@ -385,9 +386,11 @@ bool GrDrawTarget::checkDraw(const GrPipelineBuilder& pipelineBuilder,
}
bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder,
const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI,
GrDeviceCoordTexture* dstCopy,
const SkRect* drawBounds) {
if (!pipelineBuilder.willXPNeedDstCopy(*this->caps())) {
if (!pipelineBuilder.willXPNeedDstCopy(*this->caps(), colorPOI, coveragePOI)) {
return true;
}
SkIRect copyRect;
@ -470,9 +473,15 @@ void GrDrawTarget::drawIndexed(GrPipelineBuilder* pipelineBuilder,
info.setDevBounds(*devBounds);
}
GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, gp, devBounds,
this);
if (pipelineInfo.mustSkipDraw()) {
return;
}
this->setDrawBuffers(&info, gp->getVertexStride());
this->onDraw(*pipelineBuilder, gp, info, scissorState);
this->onDraw(gp, info, pipelineInfo);
}
}
@ -509,9 +518,15 @@ void GrDrawTarget::drawNonIndexed(GrPipelineBuilder* pipelineBuilder,
info.setDevBounds(*devBounds);
}
GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, gp, devBounds,
this);
if (pipelineInfo.mustSkipDraw()) {
return;
}
this->setDrawBuffers(&info, gp->getVertexStride());
this->onDraw(*pipelineBuilder, gp, info, scissorState);
this->onDraw(gp, info, pipelineInfo);
}
}
@ -530,7 +545,17 @@ void GrDrawTarget::drawBatch(GrPipelineBuilder* pipelineBuilder,
return;
}
this->onDrawBatch(batch, *pipelineBuilder, scissorState, devBounds);
// init batch and my other crap
GrBatchOpt batchOpt;
batchOpt.fCanTweakAlphaForCoverage = pipelineBuilder->canTweakAlphaForCoverage();
batch->initBatchOpt(batchOpt);
GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, batch, devBounds, this);
if (pipelineInfo.mustSkipDraw()) {
return;
}
this->onDrawBatch(batch, pipelineInfo);
}
static const GrStencilSettings& winding_path_stencil_settings() {
@ -620,8 +645,13 @@ void GrDrawTarget::drawPath(GrPipelineBuilder* pipelineBuilder,
pipelineBuilder->getRenderTarget()->getStencilBuffer(),
&stencilSettings);
this->onDrawPath(*pipelineBuilder, pathProc, path, scissorState, stencilSettings,
&devBounds);
GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, pathProc, &devBounds,
this);
if (pipelineInfo.mustSkipDraw()) {
return;
}
this->onDrawPath(pathProc, path, stencilSettings, pipelineInfo);
}
void GrDrawTarget::drawPaths(GrPipelineBuilder* pipelineBuilder,
@ -659,8 +689,13 @@ void GrDrawTarget::drawPaths(GrPipelineBuilder* pipelineBuilder,
// instead for it to just copy the entire dst. Realistically this is a moot
// point, because any context that supports NV_path_rendering will also
// support NV_blend_equation_advanced.
this->onDrawPaths(*pipelineBuilder, pathProc, pathRange, indices, indexType, transformValues,
transformType, count, scissorState, stencilSettings, NULL);
GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, pathProc, NULL, this);
if (pipelineInfo.mustSkipDraw()) {
return;
}
this->onDrawPaths(pathProc, pathRange, indices, indexType, transformValues,
transformType, count, stencilSettings, pipelineInfo);
}
void GrDrawTarget::clear(const SkIRect* rect,
@ -778,8 +813,15 @@ void GrDrawTarget::drawIndexedInstances(GrPipelineBuilder* pipelineBuilder,
info.fStartIndex,
info.fVertexCount,
info.fIndexCount)) {
GrDrawTarget::PipelineInfo pipelineInfo(pipelineBuilder, &scissorState, gp, devBounds,
this);
if (pipelineInfo.mustSkipDraw()) {
return;
}
this->setDrawBuffers(&info, gp->getVertexStride());
this->onDraw(*pipelineBuilder, gp, info, scissorState);
this->onDraw(gp, info, pipelineInfo);
}
info.fStartVertex += info.fVertexCount;
instanceCount -= info.fInstanceCount;
@ -985,6 +1027,47 @@ bool GrDrawTarget::internalCanCopySurface(const GrSurface* dst,
this->onCanCopySurface(dst, src, clippedSrcRect, clippedDstPoint);
}
void GrDrawTarget::setupPipeline(const PipelineInfo& pipelineInfo,
GrPipeline* pipeline) {
SkNEW_PLACEMENT_ARGS(pipeline, GrPipeline, (*pipelineInfo.fPipelineBuilder,
pipelineInfo.fColorPOI,
pipelineInfo.fCoveragePOI,
*this->caps(),
*pipelineInfo.fScissor,
&pipelineInfo.fDstCopy));
}
///////////////////////////////////////////////////////////////////////////////
GrDrawTarget::PipelineInfo::PipelineInfo(GrPipelineBuilder* pipelineBuilder,
GrScissorState* scissor,
const GrPrimitiveProcessor* primProc,
const SkRect* devBounds,
GrDrawTarget* target)
: fPipelineBuilder(pipelineBuilder)
, fScissor(scissor) {
fColorPOI = fPipelineBuilder->colorProcInfo(primProc);
fCoveragePOI = fPipelineBuilder->coverageProcInfo(primProc);
if (!target->setupDstReadIfNecessary(*fPipelineBuilder, fColorPOI, fCoveragePOI,
&fDstCopy, devBounds)) {
fPipelineBuilder = NULL;
}
}
GrDrawTarget::PipelineInfo::PipelineInfo(GrPipelineBuilder* pipelineBuilder,
GrScissorState* scissor,
const GrBatch* batch,
const SkRect* devBounds,
GrDrawTarget* target)
: fPipelineBuilder(pipelineBuilder)
, fScissor(scissor) {
fColorPOI = fPipelineBuilder->colorProcInfo(batch);
fCoveragePOI = fPipelineBuilder->coverageProcInfo(batch);
if (!target->setupDstReadIfNecessary(*fPipelineBuilder, fColorPOI, fCoveragePOI,
&fDstCopy, devBounds)) {
fPipelineBuilder = NULL;
}
}
///////////////////////////////////////////////////////////////////////////////
void GrDrawTargetCaps::reset() {

View File

@ -33,6 +33,7 @@ class GrClipData;
class GrDrawTargetCaps;
class GrPath;
class GrPathRange;
class GrPipeline;
class GrDrawTarget : public SkRefCnt {
public:
@ -680,9 +681,36 @@ protected:
// but couldn't be made. Otherwise, returns true. This method needs to be protected because it
// needs to be accessed by GLPrograms to setup a correct drawstate
bool setupDstReadIfNecessary(const GrPipelineBuilder&,
const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI,
GrDeviceCoordTexture* dstCopy,
const SkRect* drawBounds);
struct PipelineInfo {
PipelineInfo(GrPipelineBuilder* pipelineBuilder, GrScissorState* scissor,
const GrPrimitiveProcessor* primProc, const SkRect* devBounds,
GrDrawTarget* target);
PipelineInfo(GrPipelineBuilder* pipelineBuilder, GrScissorState* scissor,
const GrBatch* batch, const SkRect* devBounds, GrDrawTarget* target);
bool willBlendWithDst(const GrPrimitiveProcessor* primProc) const {
return fPipelineBuilder->willBlendWithDst(primProc);
}
private:
friend class GrDrawTarget;
bool mustSkipDraw() const { return (NULL == fPipelineBuilder); }
GrPipelineBuilder* fPipelineBuilder;
GrScissorState* fScissor;
GrProcOptInfo fColorPOI;
GrProcOptInfo fCoveragePOI;
GrDeviceCoordTexture fDstCopy;
};
void setupPipeline(const PipelineInfo& pipelineInfo, GrPipeline* pipeline);
private:
/**
* This will be called before allocating a texture as a dst for copySurface. This function
@ -719,14 +747,8 @@ private:
virtual void geometrySourceWillPush() = 0;
virtual void geometrySourceWillPop(const GeometrySrcState& restoredState) = 0;
// subclass called to perform drawing
virtual void onDraw(const GrPipelineBuilder&,
const GrGeometryProcessor*,
const DrawInfo&,
const GrScissorState&) = 0;
virtual void onDrawBatch(GrBatch*,
const GrPipelineBuilder&,
const GrScissorState&,
const SkRect* devBounds) = 0;
virtual void onDraw(const GrGeometryProcessor*, const DrawInfo&, const PipelineInfo&) = 0;
virtual void onDrawBatch(GrBatch*, const PipelineInfo&) = 0;
// TODO copy in order drawbuffer onDrawRect to here
virtual void onDrawRect(GrPipelineBuilder*,
GrColor color,
@ -740,23 +762,19 @@ private:
const GrPath*,
const GrScissorState&,
const GrStencilSettings&) = 0;
virtual void onDrawPath(const GrPipelineBuilder&,
const GrPathProcessor*,
virtual void onDrawPath(const GrPathProcessor*,
const GrPath*,
const GrScissorState&,
const GrStencilSettings&,
const SkRect* devBounds) = 0;
virtual void onDrawPaths(const GrPipelineBuilder&,
const GrPathProcessor*,
const PipelineInfo&) = 0;
virtual void onDrawPaths(const GrPathProcessor*,
const GrPathRange*,
const void* indices,
PathIndexType,
const float transformValues[],
PathTransformType,
int count,
const GrScissorState&,
const GrStencilSettings&,
const SkRect* devBounds) = 0;
const PipelineInfo&) = 0;
virtual void onClear(const SkIRect* rect, GrColor color, bool canIgnoreRect,
GrRenderTarget* renderTarget) = 0;

View File

@ -190,8 +190,7 @@ void GrInOrderDrawBuffer::onDrawRect(GrPipelineBuilder* pipelineBuilder,
&devBounds);
}
int GrInOrderDrawBuffer::concatInstancedDraw(const GrPipelineBuilder& pipelineBuilder,
const DrawInfo& info) {
int GrInOrderDrawBuffer::concatInstancedDraw(const DrawInfo& info) {
SkASSERT(!fCmdBuffer.empty());
SkASSERT(info.isInstanced());
@ -244,20 +243,19 @@ int GrInOrderDrawBuffer::concatInstancedDraw(const GrPipelineBuilder& pipelineBu
return instancesToConcat;
}
void GrInOrderDrawBuffer::onDraw(const GrPipelineBuilder& pipelineBuilder,
const GrGeometryProcessor* gp,
void GrInOrderDrawBuffer::onDraw(const GrGeometryProcessor* gp,
const DrawInfo& info,
const GrScissorState& scissorState) {
const PipelineInfo& pipelineInfo) {
SkASSERT(info.vertexBuffer() && (!info.isIndexed() || info.indexBuffer()));
this->closeBatch();
if (!this->recordStateAndShouldDraw(pipelineBuilder, gp, scissorState, info.getDevBounds())) {
if (!this->setupPipelineAndShouldDraw(gp, pipelineInfo)) {
return;
}
Draw* draw;
if (info.isInstanced()) {
int instancesConcated = this->concatInstancedDraw(pipelineBuilder, info);
int instancesConcated = this->concatInstancedDraw(info);
if (info.instanceCount() > instancesConcated) {
draw = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Draw, (info));
draw->fInfo.adjustInstanceCount(-instancesConcated);
@ -271,10 +269,8 @@ void GrInOrderDrawBuffer::onDraw(const GrPipelineBuilder& pipelineBuilder,
}
void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch,
const GrPipelineBuilder& pipelineBuilder,
const GrScissorState& scissorState,
const SkRect* devBounds) {
if (!this->recordStateAndShouldDraw(batch, pipelineBuilder, scissorState, devBounds)) {
const PipelineInfo& pipelineInfo) {
if (!this->setupPipelineAndShouldDraw(batch, pipelineInfo)) {
return;
}
@ -310,16 +306,14 @@ void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder
this->recordTraceMarkersIfNecessary();
}
void GrInOrderDrawBuffer::onDrawPath(const GrPipelineBuilder& pipelineBuilder,
const GrPathProcessor* pathProc,
void GrInOrderDrawBuffer::onDrawPath(const GrPathProcessor* pathProc,
const GrPath* path,
const GrScissorState& scissorState,
const GrStencilSettings& stencilSettings,
const SkRect* devBounds) {
const PipelineInfo& pipelineInfo) {
this->closeBatch();
// TODO: Only compare the subset of GrPipelineBuilder relevant to path covering?
if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, devBounds)) {
if (!this->setupPipelineAndShouldDraw(pathProc, pipelineInfo)) {
return;
}
DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (path));
@ -327,23 +321,21 @@ void GrInOrderDrawBuffer::onDrawPath(const GrPipelineBuilder& pipelineBuilder,
this->recordTraceMarkersIfNecessary();
}
void GrInOrderDrawBuffer::onDrawPaths(const GrPipelineBuilder& pipelineBuilder,
const GrPathProcessor* pathProc,
void GrInOrderDrawBuffer::onDrawPaths(const GrPathProcessor* pathProc,
const GrPathRange* pathRange,
const void* indices,
PathIndexType indexType,
const float transformValues[],
PathTransformType transformType,
int count,
const GrScissorState& scissorState,
const GrStencilSettings& stencilSettings,
const SkRect* devBounds) {
const PipelineInfo& pipelineInfo) {
SkASSERT(pathRange);
SkASSERT(indices);
SkASSERT(transformValues);
this->closeBatch();
if (!this->recordStateAndShouldDraw(pipelineBuilder, pathProc, scissorState, devBounds)) {
if (!this->setupPipelineAndShouldDraw(pathProc, pipelineInfo)) {
return;
}
@ -373,7 +365,7 @@ void GrInOrderDrawBuffer::onDrawPaths(const GrPipelineBuilder& pipelineBuilder,
transformType == previous->fTransformType &&
stencilSettings == previous->fStencilSettings &&
path_fill_type_is_winding(stencilSettings) &&
!pipelineBuilder.willBlendWithDst(pathProc)) {
!pipelineInfo.willBlendWithDst(pathProc)) {
// Fold this DrawPaths call into the one previous.
previous->fCount += count;
return;
@ -492,7 +484,7 @@ void GrInOrderDrawBuffer::onFlush() {
// only have GrBatch and we can delete this
if (ss->fPrimitiveProcessor) {
this->getGpu()->buildProgramDesc(&ss->fDesc, *ss->fPrimitiveProcessor,
ss->fPipeline,
*ss->getPipeline(),
ss->fBatchTracker);
}
currentState = ss;
@ -514,7 +506,7 @@ void GrInOrderDrawBuffer::onFlush() {
void GrInOrderDrawBuffer::Draw::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
SkASSERT(state);
DrawArgs args(state->fPrimitiveProcessor.get(), &state->fPipeline, &state->fDesc,
DrawArgs args(state->fPrimitiveProcessor.get(), state->getPipeline(), &state->fDesc,
&state->fBatchTracker);
buf->getGpu()->draw(args, fInfo);
}
@ -532,14 +524,14 @@ void GrInOrderDrawBuffer::StencilPath::execute(GrInOrderDrawBuffer* buf, const S
void GrInOrderDrawBuffer::DrawPath::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
SkASSERT(state);
DrawArgs args(state->fPrimitiveProcessor.get(), &state->fPipeline, &state->fDesc,
DrawArgs args(state->fPrimitiveProcessor.get(), state->getPipeline(), &state->fDesc,
&state->fBatchTracker);
buf->getGpu()->drawPath(args, this->path(), fStencilSettings);
}
void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
SkASSERT(state);
DrawArgs args(state->fPrimitiveProcessor.get(), &state->fPipeline, &state->fDesc,
DrawArgs args(state->fPrimitiveProcessor.get(), state->getPipeline(), &state->fDesc,
&state->fBatchTracker);
buf->getGpu()->drawPaths(args, this->pathRange(),
&buf->fPathIndexBuffer[fIndicesLocation], fIndexType,
@ -549,7 +541,7 @@ void GrInOrderDrawBuffer::DrawPaths::execute(GrInOrderDrawBuffer* buf, const Set
void GrInOrderDrawBuffer::DrawBatch::execute(GrInOrderDrawBuffer* buf, const SetState* state) {
SkASSERT(state);
fBatch->generateGeometry(buf->getBatchTarget(), &state->fPipeline);
fBatch->generateGeometry(buf->getBatchTarget(), state->getPipeline());
}
void GrInOrderDrawBuffer::SetState::execute(GrInOrderDrawBuffer*, const SetState*) {}
@ -585,30 +577,24 @@ bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
return false;
}
bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrPipelineBuilder& pipelineBuilder,
const GrPrimitiveProcessor* primProc,
const GrScissorState& scissor,
const SkRect* devBounds) {
GrDeviceCoordTexture dstCopy;
if (!this->setupDstReadIfNecessary(pipelineBuilder, &dstCopy, devBounds)) {
return false;
}
SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
(pipelineBuilder, primProc, *this->getGpu()->caps(),
scissor, &dstCopy));
if (ss->fPipeline.mustSkip()) {
bool GrInOrderDrawBuffer::setupPipelineAndShouldDraw(const GrPrimitiveProcessor* primProc,
const PipelineInfo& pipelineInfo) {
SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, (primProc));
this->setupPipeline(pipelineInfo, ss->pipelineLocation());
if (ss->getPipeline()->mustSkip()) {
fCmdBuffer.pop_back();
return false;
}
ss->fPrimitiveProcessor->initBatchTracker(&ss->fBatchTracker,
ss->fPipeline.getInitBatchTracker());
ss->getPipeline()->getInitBatchTracker());
if (fPrevState && fPrevState->fPrimitiveProcessor.get() &&
fPrevState->fPrimitiveProcessor->canMakeEqual(fPrevState->fBatchTracker,
*ss->fPrimitiveProcessor,
ss->fBatchTracker) &&
fPrevState->fPipeline.isEqual(ss->fPipeline)) {
fPrevState->getPipeline()->isEqual(*ss->getPipeline())) {
fCmdBuffer.pop_back();
} else {
fPrevState = ss;
@ -617,29 +603,20 @@ bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrPipelineBuilder& pipe
return true;
}
bool GrInOrderDrawBuffer::recordStateAndShouldDraw(GrBatch* batch,
const GrPipelineBuilder& pipelineBuilder,
const GrScissorState& scissor,
const SkRect* devBounds) {
GrDeviceCoordTexture dstCopy;
if (!this->setupDstReadIfNecessary(pipelineBuilder, &dstCopy, devBounds)) {
return false;
}
// TODO this gets much simpler when we have batches everywhere.
// If the previous command is also a set state, then we check to see if it has a Batch. If so,
// and we can make the two batches equal, and we can combine the states, then we make them equal
SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState,
(batch, pipelineBuilder, *this->getGpu()->caps(), scissor,
&dstCopy));
if (ss->fPipeline.mustSkip()) {
bool GrInOrderDrawBuffer::setupPipelineAndShouldDraw(GrBatch* batch,
const PipelineInfo& pipelineInfo) {
SetState* ss = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, SetState, ());
this->setupPipeline(pipelineInfo, ss->pipelineLocation());
if (ss->getPipeline()->mustSkip()) {
fCmdBuffer.pop_back();
return false;
}
batch->initBatchTracker(ss->fPipeline.getInitBatchTracker());
batch->initBatchTracker(ss->getPipeline()->getInitBatchTracker());
if (fPrevState && !fPrevState->fPrimitiveProcessor.get() &&
fPrevState->fPipeline.isEqual(ss->fPipeline)) {
fPrevState->getPipeline()->isEqual(*ss->getPipeline())) {
fCmdBuffer.pop_back();
} else {
this->closeBatch();

View File

@ -188,28 +188,28 @@ private:
// TODO: rename to SetPipeline once pp, batch tracker, and desc are removed
struct SetState : public Cmd {
// TODO get rid of the prim proc version of this when we use batch everywhere
SetState(const GrPipelineBuilder& pipelineBuilder, const GrPrimitiveProcessor* primProc,
const GrDrawTargetCaps& caps,
const GrScissorState& scissor, const GrDeviceCoordTexture* dstCopy)
// TODO get rid of the prim proc parameter when we use batch everywhere
SetState(const GrPrimitiveProcessor* primProc = NULL)
: Cmd(kSetState_Cmd)
, fPrimitiveProcessor(primProc)
, fPipeline(pipelineBuilder, primProc, caps, scissor, dstCopy) {}
, fPrimitiveProcessor(primProc) {}
SetState(GrBatch* batch,
const GrPipelineBuilder& pipelineBuilder,
const GrDrawTargetCaps& caps,
const GrScissorState& scissor, const GrDeviceCoordTexture* dstCopy)
: Cmd(kSetState_Cmd)
, fPipeline(batch, pipelineBuilder, caps, scissor, dstCopy) {}
~SetState() { reinterpret_cast<GrPipeline*>(fPipeline.get())->~GrPipeline(); }
// This function is only for getting the location in memory where we will create our
// pipeline object.
GrPipeline* pipelineLocation() { return reinterpret_cast<GrPipeline*>(fPipeline.get()); }
const GrPipeline* getPipeline() const {
return reinterpret_cast<const GrPipeline*>(fPipeline.get());
}
void execute(GrInOrderDrawBuffer*, const SetState*) SK_OVERRIDE;
typedef GrPendingProgramElement<const GrPrimitiveProcessor> ProgramPrimitiveProcessor;
ProgramPrimitiveProcessor fPrimitiveProcessor;
const GrPipeline fPipeline;
GrProgramDesc fDesc;
GrBatchTracker fBatchTracker;
ProgramPrimitiveProcessor fPrimitiveProcessor;
SkAlignedSStorage<sizeof(GrPipeline)> fPipeline;
GrProgramDesc fDesc;
GrBatchTracker fBatchTracker;
};
struct DrawBatch : public Cmd {
@ -230,14 +230,8 @@ private:
void onFlush() SK_OVERRIDE;
// overrides from GrDrawTarget
void onDraw(const GrPipelineBuilder&,
const GrGeometryProcessor*,
const DrawInfo&,
const GrScissorState&) SK_OVERRIDE;
void onDrawBatch(GrBatch*,
const GrPipelineBuilder&,
const GrScissorState&,
const SkRect* devBounds) SK_OVERRIDE;
void onDraw(const GrGeometryProcessor*, const DrawInfo&, const PipelineInfo&) SK_OVERRIDE;
void onDrawBatch(GrBatch*, const PipelineInfo&) SK_OVERRIDE;
void onDrawRect(GrPipelineBuilder*,
GrColor,
const SkMatrix& viewMatrix,
@ -250,23 +244,19 @@ private:
const GrPath*,
const GrScissorState&,
const GrStencilSettings&) SK_OVERRIDE;
void onDrawPath(const GrPipelineBuilder&,
const GrPathProcessor*,
void onDrawPath(const GrPathProcessor*,
const GrPath*,
const GrScissorState&,
const GrStencilSettings&,
const SkRect* devBounds) SK_OVERRIDE;
void onDrawPaths(const GrPipelineBuilder&,
const GrPathProcessor*,
const PipelineInfo&) SK_OVERRIDE;
void onDrawPaths(const GrPathProcessor*,
const GrPathRange*,
const void* indices,
PathIndexType,
const float transformValues[],
PathTransformType,
int count,
const GrScissorState&,
const GrStencilSettings&,
const SkRect* devBounds) SK_OVERRIDE;
const PipelineInfo&) SK_OVERRIDE;
void onClear(const SkIRect* rect,
GrColor color,
bool canIgnoreRect,
@ -278,20 +268,15 @@ private:
// Attempts to concat instances from info onto the previous draw. info must represent an
// instanced draw. The caller must have already recorded a new draw state and clip if necessary.
int concatInstancedDraw(const GrPipelineBuilder&, const DrawInfo&);
int concatInstancedDraw(const DrawInfo&);
// Determines whether the current draw operation requires a new GrPipeline and if so
// records it. If the draw can be skipped false is returned and no new GrPipeline is
// recorded.
// TODO delete the primproc variant when we have batches everywhere
bool SK_WARN_UNUSED_RESULT recordStateAndShouldDraw(const GrPipelineBuilder&,
const GrPrimitiveProcessor*,
const GrScissorState&,
const SkRect*);
bool SK_WARN_UNUSED_RESULT recordStateAndShouldDraw(GrBatch*,
const GrPipelineBuilder&,
const GrScissorState&,
const SkRect*);
bool SK_WARN_UNUSED_RESULT setupPipelineAndShouldDraw(const GrPrimitiveProcessor*,
const PipelineInfo&);
bool SK_WARN_UNUSED_RESULT setupPipelineAndShouldDraw(GrBatch*, const PipelineInfo&);
// We lazily record clip changes in order to skip clips that have no effect.
void recordClipIfNecessary();

View File

@ -15,37 +15,11 @@
#include "GrXferProcessor.h"
GrPipeline::GrPipeline(const GrPipelineBuilder& pipelineBuilder,
const GrPrimitiveProcessor* primProc,
const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI,
const GrDrawTargetCaps& caps,
const GrScissorState& scissorState,
const GrDeviceCoordTexture* dstCopy) {
const GrProcOptInfo& colorPOI = pipelineBuilder.colorProcInfo(primProc);
const GrProcOptInfo& coveragePOI = pipelineBuilder.coverageProcInfo(primProc);
this->internalConstructor(pipelineBuilder, colorPOI, coveragePOI, caps, scissorState, dstCopy);
}
GrPipeline::GrPipeline(GrBatch* batch,
const GrPipelineBuilder& pipelineBuilder,
const GrDrawTargetCaps& caps,
const GrScissorState& scissorState,
const GrDeviceCoordTexture* dstCopy) {
GrBatchOpt batchOpt;
batchOpt.fCanTweakAlphaForCoverage = pipelineBuilder.canTweakAlphaForCoverage();
batch->initBatchOpt(batchOpt);
const GrProcOptInfo& colorPOI = pipelineBuilder.colorProcInfo(batch);
const GrProcOptInfo& coveragePOI = pipelineBuilder.coverageProcInfo(batch);
this->internalConstructor(pipelineBuilder, colorPOI, coveragePOI, caps, scissorState, dstCopy);
}
void GrPipeline::internalConstructor(const GrPipelineBuilder& pipelineBuilder,
const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI,
const GrDrawTargetCaps& caps,
const GrScissorState& scissorState,
const GrDeviceCoordTexture* dstCopy) {
// Create XferProcessor from DS's XPFactory
SkAutoTUnref<GrXferProcessor> xferProcessor(
pipelineBuilder.getXPFactory()->createXferProcessor(colorPOI, coveragePOI, dstCopy, caps));

View File

@ -29,14 +29,13 @@ class GrPipeline {
public:
SK_DECLARE_INST_COUNT(GrPipeline)
// TODO get rid of this version of the constructor when we use batch everywhere
GrPipeline(const GrPipelineBuilder& pipelineBuilder, const GrPrimitiveProcessor*,
const GrDrawTargetCaps&, const GrScissorState&,
GrPipeline(const GrPipelineBuilder&,
const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI,
const GrDrawTargetCaps&,
const GrScissorState&,
const GrDeviceCoordTexture* dstCopy);
GrPipeline(GrBatch*, const GrPipelineBuilder&, const GrDrawTargetCaps&,
const GrScissorState&, const GrDeviceCoordTexture* dstCopy);
/*
* Returns true if it is possible to combine the two GrPipelines and it will update 'this'
* to subsume 'that''s draw.
@ -137,14 +136,6 @@ public:
const GrPipelineInfo& getInitBatchTracker() const { return fInitBT; }
private:
// TODO we can have one constructor once GrBatch is complete
void internalConstructor(const GrPipelineBuilder&,
const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI,
const GrDrawTargetCaps&,
const GrScissorState&,
const GrDeviceCoordTexture* dstCopy);
/**
* Alter the program desc and inputs (attribs and processors) based on the blend optimization.
*/

View File

@ -101,8 +101,10 @@ bool GrPipelineBuilder::canUseFracCoveragePrimProc(GrColor color,
//////////////////////////////////////////////////////////////////////////////s
bool GrPipelineBuilder::willXPNeedDstCopy(const GrDrawTargetCaps& caps) const {
return this->getXPFactory()->willNeedDstCopy(caps);
bool GrPipelineBuilder::willXPNeedDstCopy(const GrDrawTargetCaps& caps,
const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI) const {
return this->getXPFactory()->willNeedDstCopy(caps, colorPOI, coveragePOI);
}
void GrPipelineBuilder::AutoRestoreEffects::set(GrPipelineBuilder* pipelineBuilder) {

View File

@ -103,7 +103,8 @@ public:
/**
* Checks whether the xp will need a copy of the destination to correctly blend.
*/
bool willXPNeedDstCopy(const GrDrawTargetCaps& caps) const;
bool willXPNeedDstCopy(const GrDrawTargetCaps& caps, const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI) const;
/**
* The xfer processor factory.
@ -388,15 +389,6 @@ public:
GrPipelineBuilder& operator= (const GrPipelineBuilder& that);
private:
// Calculating invariant color / coverage information is expensive, so we partially cache the
// results.
//
// canUseFracCoveragePrimProc() - Called in regular skia draw, caches results but only for a
// specific color and coverage. May be called multiple times
// willBlendWithDst() - only called by Nvpr, does not cache results
// GrOptDrawState constructor - never caches results
// TODO delete when we have Batch
const GrProcOptInfo& colorProcInfo(const GrPrimitiveProcessor* pp) const {
this->calcColorInvariantOutput(pp);
@ -417,6 +409,14 @@ private:
this->calcCoverageInvariantOutput(batch);
return fCoverageProcInfo;
}
private:
// Calculating invariant color / coverage information is expensive, so we partially cache the
// results.
//
// canUseFracCoveragePrimProc() - Called in regular skia draw, caches results but only for a
// specific color and coverage. May be called multiple times
// willBlendWithDst() - only called by Nvpr, does not cache results
// GrOptDrawState constructor - never caches results
/**
* Primproc variants of the calc functions

View File

@ -38,7 +38,7 @@ GrXferProcessor* GrXPFactory::createXferProcessor(const GrProcOptInfo& colorPOI,
const GrDeviceCoordTexture* dstCopy,
const GrDrawTargetCaps& caps) const {
#ifdef SK_DEBUG
if (this->willReadDstColor()) {
if (this->willReadDstColor(colorPOI, coveragePOI)) {
if (!caps.dstReadInShaderSupport()) {
SkASSERT(dstCopy && dstCopy->texture());
} else {
@ -52,7 +52,8 @@ GrXferProcessor* GrXPFactory::createXferProcessor(const GrProcOptInfo& colorPOI,
return this->onCreateXferProcessor(colorPOI, coveragePOI, dstCopy);
}
bool GrXPFactory::willNeedDstCopy(const GrDrawTargetCaps& caps) const {
return (this->willReadDstColor() && !caps.dstReadInShaderSupport());
bool GrXPFactory::willNeedDstCopy(const GrDrawTargetCaps& caps, const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI) const {
return (this->willReadDstColor(colorPOI, coveragePOI) && !caps.dstReadInShaderSupport());
}

View File

@ -39,7 +39,10 @@ private:
const GrProcOptInfo& coveragePOI,
const GrDeviceCoordTexture* dstCopy) const SK_OVERRIDE;
bool willReadDstColor() const SK_OVERRIDE { return false; }
bool willReadDstColor(const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI) const SK_OVERRIDE {
return false;
}
bool onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE {
const GrCoverageSetOpXPFactory& xpf = xpfBase.cast<GrCoverageSetOpXPFactory>();

View File

@ -611,7 +611,7 @@ GrXferProcessor*
GrCustomXPFactory::onCreateXferProcessor(const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI,
const GrDeviceCoordTexture* dstCopy) const {
return CustomXP::Create(fMode, dstCopy, this->willReadDstColor());
return CustomXP::Create(fMode, dstCopy, this->willReadDstColor(colorPOI, coveragePOI));
}

View File

@ -81,7 +81,10 @@ private:
const GrProcOptInfo& coveragePOI,
const GrDeviceCoordTexture* dstCopy) const SK_OVERRIDE;
bool willReadDstColor() const SK_OVERRIDE { return true; }
bool willReadDstColor(const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI) const SK_OVERRIDE {
return true;
}
bool onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE {
const GrCustomXPFactory& xpf = xpfBase.cast<GrCustomXPFactory>();

View File

@ -43,7 +43,10 @@ private:
const GrProcOptInfo& coveragePOI,
const GrDeviceCoordTexture* dstCopy) const SK_OVERRIDE;
bool willReadDstColor() const SK_OVERRIDE { return false; }
bool willReadDstColor(const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI) const SK_OVERRIDE {
return false;
}
bool onIsEqual(const GrXPFactory& xpfBase) const SK_OVERRIDE {
return true;

View File

@ -458,14 +458,14 @@ GrPorterDuffXPFactory::onCreateXferProcessor(const GrProcOptInfo& colorPOI,
const GrDeviceCoordTexture* dstCopy) const {
if (!covPOI.isFourChannelOutput()) {
return PorterDuffXferProcessor::Create(fSrcCoeff, fDstCoeff, 0, dstCopy,
this->willReadDstColor());
this->willReadDstColor(colorPOI, covPOI));
} else {
if (this->supportsRGBCoverage(colorPOI.color(), colorPOI.validFlags())) {
SkASSERT(kRGBA_GrColorComponentFlags == colorPOI.validFlags());
GrColor blendConstant = GrUnPreMulColor(colorPOI.color());
return PorterDuffXferProcessor::Create(kConstC_GrBlendCoeff, kISC_GrBlendCoeff,
blendConstant, dstCopy,
this->willReadDstColor());
this->willReadDstColor(colorPOI, covPOI));
} else {
return NULL;
}
@ -587,7 +587,8 @@ void GrPorterDuffXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI,
output->fWillBlendWithDst = false;
}
bool GrPorterDuffXPFactory::willReadDstColor() const {
bool GrPorterDuffXPFactory::willReadDstColor(const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI) const {
return false;
}

View File

@ -298,14 +298,20 @@ bool GrDrawTarget::programUnitTest(int maxStages) {
} else {
primProc = pathProc.get();
}
if (!this->setupDstReadIfNecessary(pipelineBuilder, &dstCopy, NULL)) {
const GrProcOptInfo& colorPOI = pipelineBuilder.colorProcInfo(primProc);
const GrProcOptInfo& coveragePOI = pipelineBuilder.coverageProcInfo(primProc);
if (!this->setupDstReadIfNecessary(pipelineBuilder, colorPOI, coveragePOI, &dstCopy,
NULL)) {
SkDebugf("Couldn't setup dst read texture");
return false;
}
// create optimized draw state, setup readDst texture if required, and build a descriptor
// and program. ODS creation can fail, so we have to check
GrPipeline pipeline(pipelineBuilder, primProc, *gpu->caps(), scissor, &dstCopy);
GrPipeline pipeline(pipelineBuilder, colorPOI, coveragePOI,
*gpu->caps(), scissor, &dstCopy);
if (pipeline.mustSkip()) {
continue;
}