Create GrCommandBuilder
BUG=skia: Review URL: https://codereview.chromium.org/1113313003
This commit is contained in:
parent
f4e0857fe9
commit
e46760e8b2
@ -86,6 +86,8 @@
|
||||
'<(skia_src_path)/gpu/GrClipMaskManager.h',
|
||||
'<(skia_src_path)/gpu/GrClipMaskManager.cpp',
|
||||
'<(skia_src_path)/gpu/GrContext.cpp',
|
||||
'<(skia_src_path)/gpu/GrCommandBuilder.h',
|
||||
'<(skia_src_path)/gpu/GrCommandBuilder.cpp',
|
||||
'<(skia_src_path)/gpu/GrCoordTransform.cpp',
|
||||
'<(skia_src_path)/gpu/GrDashLinePathRenderer.cpp',
|
||||
'<(skia_src_path)/gpu/GrDashLinePathRenderer.h',
|
||||
|
197
src/gpu/GrCommandBuilder.cpp
Normal file
197
src/gpu/GrCommandBuilder.cpp
Normal file
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright 2015 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "GrCommandBuilder.h"
|
||||
|
||||
#include "GrColor.h"
|
||||
#include "GrInOrderDrawBuffer.h"
|
||||
#include "GrTemplates.h"
|
||||
#include "SkPoint.h"
|
||||
|
||||
static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
|
||||
static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
|
||||
bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
|
||||
if (isWinding) {
|
||||
// Double check that it is in fact winding.
|
||||
SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
|
||||
SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
|
||||
SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
|
||||
SkASSERT(!pathStencilSettings.isTwoSided());
|
||||
}
|
||||
return isWinding;
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd* GrCommandBuilder::recordDrawBatch(State* state, GrBatch* batch) {
|
||||
// Check if there is a Batch Draw we can batch with
|
||||
if (!this->cmdBuffer()->empty() &&
|
||||
Cmd::kDrawBatch_CmdType == this->cmdBuffer()->back().type()) {
|
||||
DrawBatch* previous = static_cast<DrawBatch*>(&this->cmdBuffer()->back());
|
||||
if (previous->fState == state && previous->fBatch->combineIfPossible(batch)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), DrawBatch, (state, batch,
|
||||
this->batchTarget()));
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd*
|
||||
GrCommandBuilder::recordStencilPath(const GrPipelineBuilder& pipelineBuilder,
|
||||
const GrPathProcessor* pathProc,
|
||||
const GrPath* path,
|
||||
const GrScissorState& scissorState,
|
||||
const GrStencilSettings& stencilSettings) {
|
||||
StencilPath* sp = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), StencilPath,
|
||||
(path, pipelineBuilder.getRenderTarget()));
|
||||
|
||||
sp->fScissor = scissorState;
|
||||
sp->fUseHWAA = pipelineBuilder.isHWAntialias();
|
||||
sp->fViewMatrix = pathProc->viewMatrix();
|
||||
sp->fStencil = stencilSettings;
|
||||
return sp;
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd*
|
||||
GrCommandBuilder::recordDrawPath(State* state,
|
||||
const GrPathProcessor* pathProc,
|
||||
const GrPath* path,
|
||||
const GrStencilSettings& stencilSettings) {
|
||||
DrawPath* dp = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), DrawPath, (state, path));
|
||||
dp->fStencilSettings = stencilSettings;
|
||||
return dp;
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd*
|
||||
GrCommandBuilder::recordDrawPaths(State* state,
|
||||
GrInOrderDrawBuffer* iodb,
|
||||
const GrPathProcessor* pathProc,
|
||||
const GrPathRange* pathRange,
|
||||
const void* indexValues,
|
||||
GrDrawTarget::PathIndexType indexType,
|
||||
const float transformValues[],
|
||||
GrDrawTarget::PathTransformType transformType,
|
||||
int count,
|
||||
const GrStencilSettings& stencilSettings,
|
||||
const GrDrawTarget::PipelineInfo& pipelineInfo) {
|
||||
SkASSERT(pathRange);
|
||||
SkASSERT(indexValues);
|
||||
SkASSERT(transformValues);
|
||||
|
||||
char* savedIndices;
|
||||
float* savedTransforms;
|
||||
|
||||
iodb->appendIndicesAndTransforms(indexValues, indexType,
|
||||
transformValues, transformType,
|
||||
count, &savedIndices, &savedTransforms);
|
||||
|
||||
if (!this->cmdBuffer()->empty() &&
|
||||
Cmd::kDrawPaths_CmdType == this->cmdBuffer()->back().type()) {
|
||||
// The previous command was also DrawPaths. Try to collapse this call into the one
|
||||
// before. Note that stenciling all the paths at once, then covering, may not be
|
||||
// equivalent to two separate draw calls if there is overlap. Blending won't work,
|
||||
// and the combined calls may also cancel each other's winding numbers in some
|
||||
// places. For now the winding numbers are only an issue if the fill is even/odd,
|
||||
// because DrawPaths is currently only used for glyphs, and glyphs in the same
|
||||
// font tend to all wind in the same direction.
|
||||
DrawPaths* previous = static_cast<DrawPaths*>(&this->cmdBuffer()->back());
|
||||
if (pathRange == previous->pathRange() &&
|
||||
indexType == previous->fIndexType &&
|
||||
transformType == previous->fTransformType &&
|
||||
stencilSettings == previous->fStencilSettings &&
|
||||
path_fill_type_is_winding(stencilSettings) &&
|
||||
!pipelineInfo.willBlendWithDst(pathProc) &&
|
||||
previous->fState == state) {
|
||||
const int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
|
||||
const int xformSize = GrPathRendering::PathTransformSize(transformType);
|
||||
if (&previous->fIndices[previous->fCount*indexBytes] == savedIndices &&
|
||||
(0 == xformSize ||
|
||||
&previous->fTransforms[previous->fCount*xformSize] == savedTransforms)) {
|
||||
// Fold this DrawPaths call into the one previous.
|
||||
previous->fCount += count;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), DrawPaths, (state, pathRange));
|
||||
dp->fIndices = savedIndices;
|
||||
dp->fIndexType = indexType;
|
||||
dp->fTransforms = savedTransforms;
|
||||
dp->fTransformType = transformType;
|
||||
dp->fCount = count;
|
||||
dp->fStencilSettings = stencilSettings;
|
||||
return dp;
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd* GrCommandBuilder::recordClear(const SkIRect* rect,
|
||||
GrColor color,
|
||||
bool canIgnoreRect,
|
||||
GrRenderTarget* renderTarget) {
|
||||
SkASSERT(renderTarget);
|
||||
|
||||
SkIRect r;
|
||||
if (NULL == rect) {
|
||||
// We could do something smart and remove previous draws and clears to
|
||||
// the current render target. If we get that smart we have to make sure
|
||||
// those draws aren't read before this clear (render-to-texture).
|
||||
r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
|
||||
rect = &r;
|
||||
}
|
||||
Clear* clr = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), Clear, (renderTarget));
|
||||
GrColorIsPMAssert(color);
|
||||
clr->fColor = color;
|
||||
clr->fRect = *rect;
|
||||
clr->fCanIgnoreRect = canIgnoreRect;
|
||||
return clr;
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd* GrCommandBuilder::recordClearStencilClip(const SkIRect& rect,
|
||||
bool insideClip,
|
||||
GrRenderTarget* renderTarget) {
|
||||
SkASSERT(renderTarget);
|
||||
|
||||
ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(),
|
||||
ClearStencilClip,
|
||||
(renderTarget));
|
||||
clr->fRect = rect;
|
||||
clr->fInsideClip = insideClip;
|
||||
return clr;
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd* GrCommandBuilder::recordDiscard(GrRenderTarget* renderTarget) {
|
||||
SkASSERT(renderTarget);
|
||||
|
||||
Clear* clr = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), Clear, (renderTarget));
|
||||
clr->fColor = GrColor_ILLEGAL;
|
||||
return clr;
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd* GrCommandBuilder::recordCopySurface(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
CopySurface* cs = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), CopySurface, (dst, src));
|
||||
cs->fSrcRect = srcRect;
|
||||
cs->fDstPoint = dstPoint;
|
||||
return cs;
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd*
|
||||
GrCommandBuilder::recordXferBarrierIfNecessary(const GrPipeline& pipeline,
|
||||
const GrDrawTargetCaps& caps) {
|
||||
const GrXferProcessor& xp = *pipeline.getXferProcessor();
|
||||
GrRenderTarget* rt = pipeline.getRenderTarget();
|
||||
|
||||
GrXferBarrierType barrierType;
|
||||
if (!xp.willNeedXferBarrier(rt, caps, &barrierType)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
XferBarrier* xb = GrNEW_APPEND_TO_RECORDER(*this->cmdBuffer(), XferBarrier, ());
|
||||
xb->fBarrierType = barrierType;
|
||||
return xb;
|
||||
}
|
85
src/gpu/GrCommandBuilder.h
Normal file
85
src/gpu/GrCommandBuilder.h
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2015 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrCommandBuilder_DEFINED
|
||||
#define GrCommandBuilder_DEFINED
|
||||
|
||||
#include "GrTargetCommands.h"
|
||||
|
||||
class GrInOrderDrawBuffer;
|
||||
class GrVertexBufferAllocPool;
|
||||
class GrIndexBufferAllocPool;
|
||||
|
||||
class GrCommandBuilder : ::SkNoncopyable {
|
||||
public:
|
||||
typedef GrTargetCommands::Cmd Cmd;
|
||||
typedef GrTargetCommands::State State;
|
||||
|
||||
GrCommandBuilder(GrGpu* gpu,
|
||||
GrVertexBufferAllocPool* vertexPool,
|
||||
GrIndexBufferAllocPool* indexPool)
|
||||
: fCommands(gpu, vertexPool, indexPool) {
|
||||
}
|
||||
|
||||
virtual ~GrCommandBuilder() {}
|
||||
|
||||
void reset() { fCommands.reset(); }
|
||||
void flush(GrInOrderDrawBuffer* iodb) { fCommands.flush(iodb); }
|
||||
|
||||
virtual Cmd* recordClearStencilClip(const SkIRect& rect,
|
||||
bool insideClip,
|
||||
GrRenderTarget* renderTarget);
|
||||
virtual Cmd* recordDiscard(GrRenderTarget*);
|
||||
virtual Cmd* recordDrawBatch(State*, GrBatch*);
|
||||
virtual Cmd* recordStencilPath(const GrPipelineBuilder&,
|
||||
const GrPathProcessor*,
|
||||
const GrPath*,
|
||||
const GrScissorState&,
|
||||
const GrStencilSettings&);
|
||||
virtual Cmd* recordDrawPath(State*,
|
||||
const GrPathProcessor*,
|
||||
const GrPath*,
|
||||
const GrStencilSettings&);
|
||||
virtual Cmd* recordDrawPaths(State*,
|
||||
GrInOrderDrawBuffer*,
|
||||
const GrPathProcessor*,
|
||||
const GrPathRange*,
|
||||
const void*,
|
||||
GrDrawTarget::PathIndexType,
|
||||
const float transformValues[],
|
||||
GrDrawTarget::PathTransformType ,
|
||||
int,
|
||||
const GrStencilSettings&,
|
||||
const GrDrawTarget::PipelineInfo&);
|
||||
virtual Cmd* recordClear(const SkIRect* rect,
|
||||
GrColor,
|
||||
bool canIgnoreRect,
|
||||
GrRenderTarget*);
|
||||
virtual Cmd* recordCopySurface(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint);
|
||||
virtual Cmd* recordXferBarrierIfNecessary(const GrPipeline&, const GrDrawTargetCaps&);
|
||||
|
||||
private:
|
||||
typedef GrTargetCommands::DrawBatch DrawBatch;
|
||||
typedef GrTargetCommands::StencilPath StencilPath;
|
||||
typedef GrTargetCommands::DrawPath DrawPath;
|
||||
typedef GrTargetCommands::DrawPaths DrawPaths;
|
||||
typedef GrTargetCommands::Clear Clear;
|
||||
typedef GrTargetCommands::ClearStencilClip ClearStencilClip;
|
||||
typedef GrTargetCommands::CopySurface CopySurface;
|
||||
typedef GrTargetCommands::XferBarrier XferBarrier;
|
||||
|
||||
GrTargetCommands::CmdBuffer* cmdBuffer() { return fCommands.cmdBuffer(); }
|
||||
GrBatchTarget* batchTarget() { return fCommands.batchTarget(); }
|
||||
|
||||
GrTargetCommands fCommands;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
@ -373,6 +373,7 @@ public:
|
||||
bool programUnitTest(int maxStages);
|
||||
|
||||
protected:
|
||||
friend class GrCommandBuilder; // for PipelineInfo
|
||||
friend class GrTargetCommands; // for PipelineInfo
|
||||
|
||||
GrContext* getContext() { return fContext; }
|
||||
|
@ -14,7 +14,7 @@ GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrContext* context,
|
||||
GrVertexBufferAllocPool* vertexPool,
|
||||
GrIndexBufferAllocPool* indexPool)
|
||||
: INHERITED(context, vertexPool, indexPool)
|
||||
, fCommands(context->getGpu(), vertexPool, indexPool)
|
||||
, fCommands(SkNEW_ARGS(GrCommandBuilder, (context->getGpu(), vertexPool, indexPool)))
|
||||
, fPathIndexBuffer(kPathIdxBufferMinReserve * sizeof(char)/4)
|
||||
, fPathTransformBuffer(kPathXformBufferMinReserve * sizeof(float)/4)
|
||||
, fPipelineBuffer(kPipelineBufferMinReserve)
|
||||
@ -272,7 +272,7 @@ void GrInOrderDrawBuffer::onDrawBatch(GrBatch* batch,
|
||||
return;
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd* cmd = fCommands.recordDrawBatch(state, batch);
|
||||
GrTargetCommands::Cmd* cmd = fCommands->recordDrawBatch(state, batch);
|
||||
this->recordTraceMarkersIfNecessary(cmd);
|
||||
}
|
||||
|
||||
@ -281,9 +281,9 @@ void GrInOrderDrawBuffer::onStencilPath(const GrPipelineBuilder& pipelineBuilder
|
||||
const GrPath* path,
|
||||
const GrScissorState& scissorState,
|
||||
const GrStencilSettings& stencilSettings) {
|
||||
GrTargetCommands::Cmd* cmd = fCommands.recordStencilPath(pipelineBuilder,
|
||||
pathProc, path, scissorState,
|
||||
stencilSettings);
|
||||
GrTargetCommands::Cmd* cmd = fCommands->recordStencilPath(pipelineBuilder,
|
||||
pathProc, path, scissorState,
|
||||
stencilSettings);
|
||||
this->recordTraceMarkersIfNecessary(cmd);
|
||||
}
|
||||
|
||||
@ -295,7 +295,7 @@ void GrInOrderDrawBuffer::onDrawPath(const GrPathProcessor* pathProc,
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
GrTargetCommands::Cmd* cmd = fCommands.recordDrawPath(state, pathProc, path, stencilSettings);
|
||||
GrTargetCommands::Cmd* cmd = fCommands->recordDrawPath(state, pathProc, path, stencilSettings);
|
||||
this->recordTraceMarkersIfNecessary(cmd);
|
||||
}
|
||||
|
||||
@ -312,23 +312,23 @@ void GrInOrderDrawBuffer::onDrawPaths(const GrPathProcessor* pathProc,
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
GrTargetCommands::Cmd* cmd = fCommands.recordDrawPaths(state, this, pathProc, pathRange,
|
||||
indices, indexType, transformValues,
|
||||
transformType, count,
|
||||
stencilSettings, pipelineInfo);
|
||||
GrTargetCommands::Cmd* cmd = fCommands->recordDrawPaths(state, this, pathProc, pathRange,
|
||||
indices, indexType, transformValues,
|
||||
transformType, count,
|
||||
stencilSettings, pipelineInfo);
|
||||
this->recordTraceMarkersIfNecessary(cmd);
|
||||
}
|
||||
|
||||
void GrInOrderDrawBuffer::onClear(const SkIRect* rect, GrColor color,
|
||||
bool canIgnoreRect, GrRenderTarget* renderTarget) {
|
||||
GrTargetCommands::Cmd* cmd = fCommands.recordClear(rect, color, canIgnoreRect, renderTarget);
|
||||
GrTargetCommands::Cmd* cmd = fCommands->recordClear(rect, color, canIgnoreRect, renderTarget);
|
||||
this->recordTraceMarkersIfNecessary(cmd);
|
||||
}
|
||||
|
||||
void GrInOrderDrawBuffer::clearStencilClip(const SkIRect& rect,
|
||||
bool insideClip,
|
||||
GrRenderTarget* renderTarget) {
|
||||
GrTargetCommands::Cmd* cmd = fCommands.recordClearStencilClip(rect, insideClip, renderTarget);
|
||||
GrTargetCommands::Cmd* cmd = fCommands->recordClearStencilClip(rect, insideClip, renderTarget);
|
||||
this->recordTraceMarkersIfNecessary(cmd);
|
||||
}
|
||||
|
||||
@ -337,12 +337,12 @@ void GrInOrderDrawBuffer::discard(GrRenderTarget* renderTarget) {
|
||||
return;
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd* cmd = fCommands.recordDiscard(renderTarget);
|
||||
GrTargetCommands::Cmd* cmd = fCommands->recordDiscard(renderTarget);
|
||||
this->recordTraceMarkersIfNecessary(cmd);
|
||||
}
|
||||
|
||||
void GrInOrderDrawBuffer::onReset() {
|
||||
fCommands.reset();
|
||||
fCommands->reset();
|
||||
fPathIndexBuffer.rewind();
|
||||
fPathTransformBuffer.rewind();
|
||||
fGpuCmdMarkers.reset();
|
||||
@ -358,7 +358,7 @@ void GrInOrderDrawBuffer::onReset() {
|
||||
}
|
||||
|
||||
void GrInOrderDrawBuffer::onFlush() {
|
||||
fCommands.flush(this);
|
||||
fCommands->flush(this);
|
||||
++fDrawID;
|
||||
}
|
||||
|
||||
@ -367,7 +367,7 @@ void GrInOrderDrawBuffer::onCopySurface(GrSurface* dst,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
SkASSERT(this->getGpu()->canCopySurface(dst, src, srcRect, dstPoint));
|
||||
GrTargetCommands::Cmd* cmd = fCommands.recordCopySurface(dst, src, srcRect, dstPoint);
|
||||
GrTargetCommands::Cmd* cmd = fCommands->recordCopySurface(dst, src, srcRect, dstPoint);
|
||||
this->recordTraceMarkersIfNecessary(cmd);
|
||||
}
|
||||
|
||||
@ -410,7 +410,8 @@ GrInOrderDrawBuffer::setupPipelineAndShouldDraw(const GrPrimitiveProcessor* prim
|
||||
fPrevState.reset(state);
|
||||
}
|
||||
|
||||
fCommands.recordXferBarrierIfNecessary(*fPrevState->getPipeline(), this);
|
||||
this->recordTraceMarkersIfNecessary(
|
||||
fCommands->recordXferBarrierIfNecessary(*fPrevState->getPipeline(), *this->caps()));
|
||||
return fPrevState;
|
||||
}
|
||||
|
||||
@ -434,6 +435,7 @@ GrInOrderDrawBuffer::setupPipelineAndShouldDraw(GrBatch* batch,
|
||||
fPrevState.reset(state);
|
||||
}
|
||||
|
||||
fCommands.recordXferBarrierIfNecessary(*fPrevState->getPipeline(), this);
|
||||
this->recordTraceMarkersIfNecessary(
|
||||
fCommands->recordXferBarrierIfNecessary(*fPrevState->getPipeline(), *this->caps()));
|
||||
return fPrevState;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
#define GrInOrderDrawBuffer_DEFINED
|
||||
|
||||
#include "GrDrawTarget.h"
|
||||
#include "GrTargetCommands.h"
|
||||
#include "GrCommandBuilder.h"
|
||||
#include "SkChunkAlloc.h"
|
||||
|
||||
/**
|
||||
@ -71,6 +71,7 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
friend class GrCommandBuilder;
|
||||
friend class GrTargetCommands;
|
||||
typedef GrTargetCommands::State State;
|
||||
|
||||
@ -148,7 +149,7 @@ private:
|
||||
// highwater mark
|
||||
static const int kPipelineBufferHighWaterMark = 100;
|
||||
|
||||
GrTargetCommands fCommands;
|
||||
SkAutoTDelete<GrCommandBuilder> fCommands;
|
||||
SkTArray<GrTraceMarkerSet, false> fGpuCmdMarkers;
|
||||
SkChunkAlloc fPathIndexBuffer;
|
||||
SkChunkAlloc fPathTransformBuffer;
|
||||
|
@ -7,164 +7,7 @@
|
||||
|
||||
#include "GrTargetCommands.h"
|
||||
|
||||
#include "GrColor.h"
|
||||
#include "GrDefaultGeoProcFactory.h"
|
||||
#include "GrInOrderDrawBuffer.h"
|
||||
#include "GrTemplates.h"
|
||||
#include "SkPoint.h"
|
||||
|
||||
static bool path_fill_type_is_winding(const GrStencilSettings& pathStencilSettings) {
|
||||
static const GrStencilSettings::Face pathFace = GrStencilSettings::kFront_Face;
|
||||
bool isWinding = kInvert_StencilOp != pathStencilSettings.passOp(pathFace);
|
||||
if (isWinding) {
|
||||
// Double check that it is in fact winding.
|
||||
SkASSERT(kIncClamp_StencilOp == pathStencilSettings.passOp(pathFace));
|
||||
SkASSERT(kIncClamp_StencilOp == pathStencilSettings.failOp(pathFace));
|
||||
SkASSERT(0x1 != pathStencilSettings.writeMask(pathFace));
|
||||
SkASSERT(!pathStencilSettings.isTwoSided());
|
||||
}
|
||||
return isWinding;
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd* GrTargetCommands::recordDrawBatch(State* state, GrBatch* batch) {
|
||||
// Check if there is a Batch Draw we can batch with
|
||||
if (!fCmdBuffer.empty() && Cmd::kDrawBatch_CmdType == fCmdBuffer.back().type()) {
|
||||
DrawBatch* previous = static_cast<DrawBatch*>(&fCmdBuffer.back());
|
||||
if (previous->fState == state && previous->fBatch->combineIfPossible(batch)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawBatch, (state, batch, &fBatchTarget));
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd* GrTargetCommands::recordStencilPath(
|
||||
const GrPipelineBuilder& pipelineBuilder,
|
||||
const GrPathProcessor* pathProc,
|
||||
const GrPath* path,
|
||||
const GrScissorState& scissorState,
|
||||
const GrStencilSettings& stencilSettings) {
|
||||
StencilPath* sp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, StencilPath,
|
||||
(path, pipelineBuilder.getRenderTarget()));
|
||||
|
||||
sp->fScissor = scissorState;
|
||||
sp->fUseHWAA = pipelineBuilder.isHWAntialias();
|
||||
sp->fViewMatrix = pathProc->viewMatrix();
|
||||
sp->fStencil = stencilSettings;
|
||||
return sp;
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd* GrTargetCommands::recordDrawPath(
|
||||
State* state,
|
||||
const GrPathProcessor* pathProc,
|
||||
const GrPath* path,
|
||||
const GrStencilSettings& stencilSettings) {
|
||||
DrawPath* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPath, (state, path));
|
||||
dp->fStencilSettings = stencilSettings;
|
||||
return dp;
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd* GrTargetCommands::recordDrawPaths(
|
||||
State* state,
|
||||
GrInOrderDrawBuffer* iodb,
|
||||
const GrPathProcessor* pathProc,
|
||||
const GrPathRange* pathRange,
|
||||
const void* indexValues,
|
||||
GrDrawTarget::PathIndexType indexType,
|
||||
const float transformValues[],
|
||||
GrDrawTarget::PathTransformType transformType,
|
||||
int count,
|
||||
const GrStencilSettings& stencilSettings,
|
||||
const GrDrawTarget::PipelineInfo& pipelineInfo) {
|
||||
SkASSERT(pathRange);
|
||||
SkASSERT(indexValues);
|
||||
SkASSERT(transformValues);
|
||||
|
||||
char* savedIndices;
|
||||
float* savedTransforms;
|
||||
|
||||
iodb->appendIndicesAndTransforms(indexValues, indexType,
|
||||
transformValues, transformType,
|
||||
count, &savedIndices, &savedTransforms);
|
||||
|
||||
if (!fCmdBuffer.empty() && Cmd::kDrawPaths_CmdType == fCmdBuffer.back().type()) {
|
||||
// The previous command was also DrawPaths. Try to collapse this call into the one
|
||||
// before. Note that stenciling all the paths at once, then covering, may not be
|
||||
// equivalent to two separate draw calls if there is overlap. Blending won't work,
|
||||
// and the combined calls may also cancel each other's winding numbers in some
|
||||
// places. For now the winding numbers are only an issue if the fill is even/odd,
|
||||
// because DrawPaths is currently only used for glyphs, and glyphs in the same
|
||||
// font tend to all wind in the same direction.
|
||||
DrawPaths* previous = static_cast<DrawPaths*>(&fCmdBuffer.back());
|
||||
if (pathRange == previous->pathRange() &&
|
||||
indexType == previous->fIndexType &&
|
||||
transformType == previous->fTransformType &&
|
||||
stencilSettings == previous->fStencilSettings &&
|
||||
path_fill_type_is_winding(stencilSettings) &&
|
||||
!pipelineInfo.willBlendWithDst(pathProc) &&
|
||||
previous->fState == state) {
|
||||
const int indexBytes = GrPathRange::PathIndexSizeInBytes(indexType);
|
||||
const int xformSize = GrPathRendering::PathTransformSize(transformType);
|
||||
if (&previous->fIndices[previous->fCount*indexBytes] == savedIndices &&
|
||||
(0 == xformSize ||
|
||||
&previous->fTransforms[previous->fCount*xformSize] == savedTransforms)) {
|
||||
// Fold this DrawPaths call into the one previous.
|
||||
previous->fCount += count;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DrawPaths* dp = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, DrawPaths, (state, pathRange));
|
||||
dp->fIndices = savedIndices;
|
||||
dp->fIndexType = indexType;
|
||||
dp->fTransforms = savedTransforms;
|
||||
dp->fTransformType = transformType;
|
||||
dp->fCount = count;
|
||||
dp->fStencilSettings = stencilSettings;
|
||||
return dp;
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd* GrTargetCommands::recordClear(const SkIRect* rect,
|
||||
GrColor color,
|
||||
bool canIgnoreRect,
|
||||
GrRenderTarget* renderTarget) {
|
||||
SkASSERT(renderTarget);
|
||||
|
||||
SkIRect r;
|
||||
if (NULL == rect) {
|
||||
// We could do something smart and remove previous draws and clears to
|
||||
// the current render target. If we get that smart we have to make sure
|
||||
// those draws aren't read before this clear (render-to-texture).
|
||||
r.setLTRB(0, 0, renderTarget->width(), renderTarget->height());
|
||||
rect = &r;
|
||||
}
|
||||
Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
|
||||
GrColorIsPMAssert(color);
|
||||
clr->fColor = color;
|
||||
clr->fRect = *rect;
|
||||
clr->fCanIgnoreRect = canIgnoreRect;
|
||||
return clr;
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd* GrTargetCommands::recordClearStencilClip(const SkIRect& rect,
|
||||
bool insideClip,
|
||||
GrRenderTarget* renderTarget) {
|
||||
SkASSERT(renderTarget);
|
||||
|
||||
ClearStencilClip* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, ClearStencilClip, (renderTarget));
|
||||
clr->fRect = rect;
|
||||
clr->fInsideClip = insideClip;
|
||||
return clr;
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd* GrTargetCommands::recordDiscard(GrRenderTarget* renderTarget) {
|
||||
SkASSERT(renderTarget);
|
||||
|
||||
Clear* clr = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, Clear, (renderTarget));
|
||||
clr->fColor = GrColor_ILLEGAL;
|
||||
return clr;
|
||||
}
|
||||
|
||||
void GrTargetCommands::reset() {
|
||||
fCmdBuffer.reset();
|
||||
@ -271,30 +114,3 @@ void GrTargetCommands::CopySurface::execute(GrGpu* gpu) {
|
||||
void GrTargetCommands::XferBarrier::execute(GrGpu* gpu) {
|
||||
gpu->xferBarrier(fBarrierType);
|
||||
}
|
||||
|
||||
GrTargetCommands::Cmd* GrTargetCommands::recordCopySurface(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint) {
|
||||
CopySurface* cs = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, CopySurface, (dst, src));
|
||||
cs->fSrcRect = srcRect;
|
||||
cs->fDstPoint = dstPoint;
|
||||
return cs;
|
||||
}
|
||||
|
||||
void GrTargetCommands::recordXferBarrierIfNecessary(const GrPipeline& pipeline,
|
||||
GrInOrderDrawBuffer* iodb) {
|
||||
const GrXferProcessor& xp = *pipeline.getXferProcessor();
|
||||
GrRenderTarget* rt = pipeline.getRenderTarget();
|
||||
|
||||
GrXferBarrierType barrierType;
|
||||
if (!xp.willNeedXferBarrier(rt, *iodb->caps(), &barrierType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
XferBarrier* xb = GrNEW_APPEND_TO_RECORDER(fCmdBuffer, XferBarrier, ());
|
||||
xb->fBarrierType = barrierType;
|
||||
|
||||
iodb->recordTraceMarkersIfNecessary(xb);
|
||||
}
|
||||
|
||||
|
@ -24,9 +24,6 @@ class GrVertexBufferAllocPool;
|
||||
class GrIndexBufferAllocPool;
|
||||
|
||||
class GrTargetCommands : ::SkNoncopyable {
|
||||
struct State;
|
||||
struct SetState;
|
||||
|
||||
public:
|
||||
GrTargetCommands(GrGpu* gpu,
|
||||
GrVertexBufferAllocPool* vertexPool,
|
||||
@ -68,43 +65,9 @@ public:
|
||||
void reset();
|
||||
void flush(GrInOrderDrawBuffer*);
|
||||
|
||||
Cmd* recordClearStencilClip(const SkIRect& rect,
|
||||
bool insideClip,
|
||||
GrRenderTarget* renderTarget);
|
||||
|
||||
Cmd* recordDiscard(GrRenderTarget*);
|
||||
Cmd* recordDrawBatch(State*, GrBatch*);
|
||||
Cmd* recordStencilPath(const GrPipelineBuilder&,
|
||||
const GrPathProcessor*,
|
||||
const GrPath*,
|
||||
const GrScissorState&,
|
||||
const GrStencilSettings&);
|
||||
Cmd* recordDrawPath(State*,
|
||||
const GrPathProcessor*,
|
||||
const GrPath*,
|
||||
const GrStencilSettings&);
|
||||
Cmd* recordDrawPaths(State*,
|
||||
GrInOrderDrawBuffer*,
|
||||
const GrPathProcessor*,
|
||||
const GrPathRange*,
|
||||
const void*,
|
||||
GrDrawTarget::PathIndexType,
|
||||
const float transformValues[],
|
||||
GrDrawTarget::PathTransformType ,
|
||||
int,
|
||||
const GrStencilSettings&,
|
||||
const GrDrawTarget::PipelineInfo&);
|
||||
Cmd* recordClear(const SkIRect* rect,
|
||||
GrColor,
|
||||
bool canIgnoreRect,
|
||||
GrRenderTarget*);
|
||||
Cmd* recordCopySurface(GrSurface* dst,
|
||||
GrSurface* src,
|
||||
const SkIRect& srcRect,
|
||||
const SkIPoint& dstPoint);
|
||||
|
||||
private:
|
||||
friend class GrInOrderDrawBuffer;
|
||||
friend class GrCommandBuilder;
|
||||
friend class GrInOrderDrawBuffer; // This goes away when State becomes just a pipeline
|
||||
|
||||
typedef GrGpu::DrawArgs DrawArgs;
|
||||
|
||||
@ -293,6 +256,9 @@ private:
|
||||
typedef void* TCmdAlign; // This wouldn't be enough align if a command used long double.
|
||||
typedef GrTRecorder<Cmd, TCmdAlign> CmdBuffer;
|
||||
|
||||
CmdBuffer* cmdBuffer() { return &fCmdBuffer; }
|
||||
GrBatchTarget* batchTarget() { return &fBatchTarget; }
|
||||
|
||||
CmdBuffer fCmdBuffer;
|
||||
GrBatchTarget fBatchTarget;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user