Replace fixed-size array of effect stages in GrDrawState with two appendable arrays, one for color, one for coverage.
R=robertphillips@google.com Review URL: https://codereview.chromium.org/16952006 git-svn-id: http://skia.googlecode.com/svn/trunk@9592 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
74feb1593a
commit
eb6879f50a
@ -903,9 +903,10 @@ private:
|
||||
|
||||
void flushDrawBuffer();
|
||||
|
||||
class AutoRestoreEffects;
|
||||
/// Sets the paint and returns the target to draw into. The paint can be NULL in which case the
|
||||
/// draw state is left unmodified.
|
||||
GrDrawTarget* prepareToDraw(const GrPaint*, BufferedDraw);
|
||||
GrDrawTarget* prepareToDraw(const GrPaint*, BufferedDraw, AutoRestoreEffects*);
|
||||
|
||||
void internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& path,
|
||||
const SkStrokeRec& stroke);
|
||||
|
@ -20,21 +20,38 @@
|
||||
|
||||
class GrEffectStage {
|
||||
public:
|
||||
GrEffectStage()
|
||||
: fEffectRef (NULL) {
|
||||
GR_DEBUGCODE(fSavedCoordChangeCnt = 0;)
|
||||
GrEffectStage() {
|
||||
fCoordChangeMatrixSet = false;
|
||||
fVertexAttribIndices[0] = -1;
|
||||
fVertexAttribIndices[1] = -1;
|
||||
}
|
||||
|
||||
~GrEffectStage() {
|
||||
GrSafeUnref(fEffectRef);
|
||||
GrAssert(0 == fSavedCoordChangeCnt);
|
||||
explicit GrEffectStage(const GrEffectRef* effectRef, int attrIndex0 = -1, int attrIndex1 = -1)
|
||||
: fEffectRef(SkSafeRef(effectRef)) {
|
||||
fCoordChangeMatrixSet = false;
|
||||
fVertexAttribIndices[0] = attrIndex0;
|
||||
fVertexAttribIndices[1] = attrIndex1;
|
||||
}
|
||||
|
||||
bool operator ==(const GrEffectStage& other) const {
|
||||
GrEffectStage(const GrEffectStage& other) {
|
||||
*this = other;
|
||||
}
|
||||
|
||||
GrEffectStage& operator= (const GrEffectStage& other) {
|
||||
fCoordChangeMatrixSet = other.fCoordChangeMatrixSet;
|
||||
if (other.fCoordChangeMatrixSet) {
|
||||
fCoordChangeMatrix = other.fCoordChangeMatrix;
|
||||
}
|
||||
fEffectRef.reset(SkSafeRef(other.fEffectRef.get()));
|
||||
memcpy(fVertexAttribIndices, other.fVertexAttribIndices, sizeof(fVertexAttribIndices));
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator== (const GrEffectStage& other) const {
|
||||
// first handle cases where one or the other has no effect
|
||||
if (NULL == fEffectRef) {
|
||||
return NULL == other.fEffectRef;
|
||||
} else if (NULL == other.fEffectRef) {
|
||||
if (NULL == fEffectRef.get()) {
|
||||
return NULL == other.fEffectRef.get();
|
||||
} else if (NULL == other.fEffectRef.get()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -55,15 +72,6 @@ public:
|
||||
|
||||
bool operator!= (const GrEffectStage& s) const { return !(*this == s); }
|
||||
|
||||
GrEffectStage& operator= (const GrEffectStage& other) {
|
||||
GrSafeAssign(fEffectRef, other.fEffectRef);
|
||||
fCoordChangeMatrixSet = other.fCoordChangeMatrixSet;
|
||||
if (NULL != fEffectRef && fCoordChangeMatrixSet) {
|
||||
fCoordChangeMatrix = other.fCoordChangeMatrix;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is called when the coordinate system in which the geometry is specified will change.
|
||||
*
|
||||
@ -100,9 +108,8 @@ public:
|
||||
savedCoordChange->fCoordChangeMatrix = fCoordChangeMatrix;
|
||||
}
|
||||
GrAssert(NULL == savedCoordChange->fEffectRef.get());
|
||||
GR_DEBUGCODE(GrSafeRef(fEffectRef);)
|
||||
GR_DEBUGCODE(savedCoordChange->fEffectRef.reset(fEffectRef);)
|
||||
GR_DEBUGCODE(++fSavedCoordChangeCnt);
|
||||
GR_DEBUGCODE(GrSafeRef(fEffectRef.get());)
|
||||
GR_DEBUGCODE(savedCoordChange->fEffectRef.reset(fEffectRef.get());)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -114,7 +121,6 @@ public:
|
||||
fCoordChangeMatrix = savedCoordChange.fCoordChangeMatrix;
|
||||
}
|
||||
GrAssert(savedCoordChange.fEffectRef.get() == fEffectRef);
|
||||
GR_DEBUGCODE(--fSavedCoordChangeCnt);
|
||||
GR_DEBUGCODE(savedCoordChange.fEffectRef.reset(NULL);)
|
||||
}
|
||||
|
||||
@ -136,7 +142,7 @@ public:
|
||||
|
||||
void saveFrom(const GrEffectStage& stage) {
|
||||
GrAssert(!fInitialized);
|
||||
if (NULL != stage.fEffectRef) {
|
||||
if (NULL != stage.fEffectRef.get()) {
|
||||
stage.fEffectRef->get()->incDeferredRefCounts();
|
||||
fEffect = stage.fEffectRef->get();
|
||||
fCoordChangeMatrixSet = stage.fCoordChangeMatrixSet;
|
||||
@ -151,9 +157,8 @@ public:
|
||||
|
||||
void restoreTo(GrEffectStage* stage) {
|
||||
GrAssert(fInitialized);
|
||||
const GrEffectRef* oldEffectRef = stage->fEffectRef;
|
||||
if (NULL != fEffect) {
|
||||
stage->fEffectRef = GrEffect::CreateEffectRef(fEffect);
|
||||
stage->fEffectRef.reset(GrEffect::CreateEffectRef(fEffect));
|
||||
stage->fCoordChangeMatrixSet = fCoordChangeMatrixSet;
|
||||
if (fCoordChangeMatrixSet) {
|
||||
stage->fCoordChangeMatrix = fCoordChangeMatrix;
|
||||
@ -161,13 +166,12 @@ public:
|
||||
stage->fVertexAttribIndices[0] = fVertexAttribIndices[0];
|
||||
stage->fVertexAttribIndices[1] = fVertexAttribIndices[1];
|
||||
} else {
|
||||
stage->fEffectRef = NULL;
|
||||
stage->fEffectRef.reset(NULL);
|
||||
}
|
||||
SkSafeUnref(oldEffectRef);
|
||||
}
|
||||
|
||||
bool isEqual(const GrEffectStage& stage, bool ignoreCoordChange) const {
|
||||
if (NULL == stage.fEffectRef) {
|
||||
if (NULL == stage.fEffectRef.get()) {
|
||||
return NULL == fEffect;
|
||||
} else if (NULL == fEffect) {
|
||||
return false;
|
||||
@ -219,44 +223,28 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void reset() {
|
||||
GrSafeSetNull(fEffectRef);
|
||||
}
|
||||
void reset() { fEffectRef.reset(NULL); }
|
||||
|
||||
const GrEffectRef* setEffect(const GrEffectRef* EffectRef) {
|
||||
GrAssert(0 == fSavedCoordChangeCnt);
|
||||
GrSafeAssign(fEffectRef, EffectRef);
|
||||
fCoordChangeMatrixSet = false;
|
||||
|
||||
fVertexAttribIndices[0] = -1;
|
||||
fVertexAttribIndices[1] = -1;
|
||||
|
||||
return EffectRef;
|
||||
}
|
||||
|
||||
const GrEffectRef* setEffect(const GrEffectRef* EffectRef, int attr0, int attr1 = -1) {
|
||||
GrAssert(0 == fSavedCoordChangeCnt);
|
||||
GrSafeAssign(fEffectRef, EffectRef);
|
||||
const GrEffectRef* setEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) {
|
||||
fEffectRef.reset(SkSafeRef(effect));
|
||||
fCoordChangeMatrixSet = false;
|
||||
|
||||
fVertexAttribIndices[0] = attr0;
|
||||
fVertexAttribIndices[1] = attr1;
|
||||
|
||||
return EffectRef;
|
||||
return effect;
|
||||
}
|
||||
|
||||
const GrEffectRef* getEffect() const { return fEffectRef; }
|
||||
const GrEffectRef* getEffect() const { return fEffectRef.get(); }
|
||||
|
||||
const int* getVertexAttribIndices() const { return fVertexAttribIndices; }
|
||||
int getVertexAttribIndexCount() const { return fEffectRef->get()->numVertexAttribs(); }
|
||||
|
||||
private:
|
||||
bool fCoordChangeMatrixSet;
|
||||
SkMatrix fCoordChangeMatrix;
|
||||
const GrEffectRef* fEffectRef;
|
||||
int fVertexAttribIndices[2];
|
||||
|
||||
GR_DEBUGCODE(mutable int fSavedCoordChangeCnt;)
|
||||
bool fCoordChangeMatrixSet;
|
||||
SkMatrix fCoordChangeMatrix;
|
||||
SkAutoTUnref<const GrEffectRef> fEffectRef;
|
||||
int fVertexAttribIndices[2];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -645,7 +645,7 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath,
|
||||
};
|
||||
static const int kEdgeAttrIndex = 1;
|
||||
GrEffectRef* quadEffect = QuadEdgeEffect::Create();
|
||||
drawState->setEffect(kEdgeEffectStage, quadEffect, kEdgeAttrIndex)->unref();
|
||||
drawState->addCoverageEffect(quadEffect, kEdgeAttrIndex)->unref();
|
||||
|
||||
GrDrawTarget::AutoReleaseGeometry arg(target, vCount, iCount);
|
||||
if (!arg.succeeded()) {
|
||||
|
@ -871,24 +871,27 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
|
||||
}
|
||||
#endif
|
||||
|
||||
target->setIndexSourceToBuffer(fLinesIndexBuffer);
|
||||
int lines = 0;
|
||||
int nBufLines = fLinesIndexBuffer->maxQuads();
|
||||
drawState->setEffect(kEdgeEffectStage, hairLineEffect, kEdgeAttrIndex)->unref();
|
||||
while (lines < lineCnt) {
|
||||
int n = GrMin(lineCnt - lines, nBufLines);
|
||||
target->drawIndexed(kTriangles_GrPrimitiveType,
|
||||
kVertsPerLineSeg*lines, // startV
|
||||
0, // startI
|
||||
kVertsPerLineSeg*n, // vCount
|
||||
kIdxsPerLineSeg*n,
|
||||
&devBounds); // iCount
|
||||
lines += n;
|
||||
{
|
||||
GrDrawState::AutoRestoreEffects are(drawState);
|
||||
target->setIndexSourceToBuffer(fLinesIndexBuffer);
|
||||
int lines = 0;
|
||||
int nBufLines = fLinesIndexBuffer->maxQuads();
|
||||
drawState->addCoverageEffect(hairLineEffect, kEdgeAttrIndex)->unref();
|
||||
while (lines < lineCnt) {
|
||||
int n = GrMin(lineCnt - lines, nBufLines);
|
||||
target->drawIndexed(kTriangles_GrPrimitiveType,
|
||||
kVertsPerLineSeg*lines, // startV
|
||||
0, // startI
|
||||
kVertsPerLineSeg*n, // vCount
|
||||
kIdxsPerLineSeg*n,
|
||||
&devBounds); // iCount
|
||||
lines += n;
|
||||
}
|
||||
}
|
||||
|
||||
target->setIndexSourceToBuffer(fQuadsIndexBuffer);
|
||||
int quads = 0;
|
||||
drawState->setEffect(kEdgeEffectStage, hairQuadEffect, kEdgeAttrIndex)->unref();
|
||||
drawState->addCoverageEffect(hairQuadEffect, kEdgeAttrIndex)->unref();
|
||||
while (quads < quadCnt) {
|
||||
int n = GrMin(quadCnt - quads, kNumQuadsInIdxBuffer);
|
||||
target->drawIndexed(kTriangles_GrPrimitiveType,
|
||||
|
@ -542,17 +542,10 @@ void GrAARectRenderer::shaderFillAARect(GrGpu* gpu,
|
||||
|
||||
RectVertex* verts = reinterpret_cast<RectVertex*>(geo.vertices());
|
||||
|
||||
enum {
|
||||
// the edge effects share this stage with glyph rendering
|
||||
// (kGlyphMaskStage in GrTextContext) && SW path rendering
|
||||
// (kPathMaskStage in GrSWMaskHelper)
|
||||
kEdgeEffectStage = GrPaint::kTotalStages,
|
||||
};
|
||||
|
||||
GrEffectRef* effect = GrRectEffect::Create();
|
||||
static const int kRectAttrIndex = 1;
|
||||
static const int kWidthIndex = 2;
|
||||
drawState->setEffect(kEdgeEffectStage, effect, kRectAttrIndex, kWidthIndex)->unref();
|
||||
drawState->addCoverageEffect(effect, kRectAttrIndex, kWidthIndex)->unref();
|
||||
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
verts[i].fCenter = center;
|
||||
@ -599,16 +592,9 @@ void GrAARectRenderer::shaderFillAlignedAARect(GrGpu* gpu,
|
||||
|
||||
AARectVertex* verts = reinterpret_cast<AARectVertex*>(geo.vertices());
|
||||
|
||||
enum {
|
||||
// the edge effects share this stage with glyph rendering
|
||||
// (kGlyphMaskStage in GrTextContext) && SW path rendering
|
||||
// (kPathMaskStage in GrSWMaskHelper)
|
||||
kEdgeEffectStage = GrPaint::kTotalStages,
|
||||
};
|
||||
|
||||
GrEffectRef* effect = GrAlignedRectEffect::Create();
|
||||
static const int kOffsetIndex = 1;
|
||||
drawState->setEffect(kEdgeEffectStage, effect, kOffsetIndex)->unref();
|
||||
drawState->addCoverageEffect(effect, kOffsetIndex)->unref();
|
||||
|
||||
SkRect devRect;
|
||||
combinedMatrix.mapRect(&devRect, rect);
|
||||
|
@ -37,8 +37,6 @@ void setup_drawstate_aaclip(GrGpu* gpu,
|
||||
GrDrawState* drawState = gpu->drawState();
|
||||
GrAssert(drawState);
|
||||
|
||||
static const int kMaskStage = GrPaint::kTotalStages+1;
|
||||
|
||||
SkMatrix mat;
|
||||
// We want to use device coords to compute the texture coordinates. We set our matrix to be
|
||||
// equal to the view matrix followed by an offset to the devBound, and then a scaling matrix to
|
||||
@ -50,8 +48,8 @@ void setup_drawstate_aaclip(GrGpu* gpu,
|
||||
|
||||
SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height());
|
||||
// This could be a long-lived effect that is cached with the alpha-mask.
|
||||
drawState->setEffect(kMaskStage,
|
||||
GrTextureDomainEffect::Create(result,
|
||||
drawState->addCoverageEffect(
|
||||
GrTextureDomainEffect::Create(result,
|
||||
mat,
|
||||
GrTextureDomainEffect::MakeTexelDomain(result, domainTexels),
|
||||
GrTextureDomainEffect::kDecal_WrapMode,
|
||||
@ -109,7 +107,8 @@ bool GrClipMaskManager::useSWOnlyPath(const ElementList& elements) {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// sort out what kind of clip mask needs to be created: alpha, stencil,
|
||||
// scissor, or entirely software
|
||||
bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn) {
|
||||
bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn,
|
||||
GrDrawState::AutoRestoreEffects* are) {
|
||||
fCurrClipMaskType = kNone_ClipMaskType;
|
||||
|
||||
ElementList elements(16);
|
||||
@ -178,6 +177,7 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn) {
|
||||
// clipSpace bounds. We determine the mask's position WRT to the render target here.
|
||||
SkIRect rtSpaceMaskBounds = clipSpaceIBounds;
|
||||
rtSpaceMaskBounds.offset(-clipDataIn->fOrigin);
|
||||
are->set(fGpu->drawState());
|
||||
setup_drawstate_aaclip(fGpu, result, rtSpaceMaskBounds);
|
||||
fGpu->disableScissor();
|
||||
this->setGpuStencil();
|
||||
@ -350,6 +350,7 @@ void GrClipMaskManager::mergeMask(GrTexture* dstMask,
|
||||
GrDrawState::AutoViewMatrixRestore avmr;
|
||||
GrDrawState* drawState = fGpu->drawState();
|
||||
SkAssertResult(avmr.setIdentity(drawState));
|
||||
GrDrawState::AutoRestoreEffects are(drawState);
|
||||
|
||||
drawState->setRenderTarget(dstMask->asRenderTarget());
|
||||
|
||||
@ -357,15 +358,13 @@ void GrClipMaskManager::mergeMask(GrTexture* dstMask,
|
||||
|
||||
SkMatrix sampleM;
|
||||
sampleM.setIDiv(srcMask->width(), srcMask->height());
|
||||
drawState->setEffect(0,
|
||||
drawState->addColorEffect(
|
||||
GrTextureDomainEffect::Create(srcMask,
|
||||
sampleM,
|
||||
GrTextureDomainEffect::MakeTexelDomain(srcMask, srcBound),
|
||||
GrTextureDomainEffect::kDecal_WrapMode,
|
||||
false))->unref();
|
||||
fGpu->drawSimpleRect(SkRect::MakeFromIRect(dstBound), NULL);
|
||||
|
||||
drawState->disableStage(0);
|
||||
}
|
||||
|
||||
// get a texture to act as a temporary buffer for AA clip boolean operations
|
||||
|
@ -10,6 +10,7 @@
|
||||
#define GrClipMaskManager_DEFINED
|
||||
|
||||
#include "GrContext.h"
|
||||
#include "GrDrawState.h"
|
||||
#include "GrNoncopyable.h"
|
||||
#include "GrRect.h"
|
||||
#include "GrReducedClip.h"
|
||||
@ -29,7 +30,6 @@ class GrPathRenderer;
|
||||
class GrPathRendererChain;
|
||||
class SkPath;
|
||||
class GrTexture;
|
||||
class GrDrawState;
|
||||
|
||||
/**
|
||||
* The clip mask creator handles the generation of the clip mask. If anti
|
||||
@ -51,7 +51,7 @@ public:
|
||||
* and sets the GrGpu's scissor and stencil state. If the return is false
|
||||
* then the draw can be skipped.
|
||||
*/
|
||||
bool setupClipping(const GrClipData* clipDataIn);
|
||||
bool setupClipping(const GrClipData* clipDataIn, GrDrawState::AutoRestoreEffects*);
|
||||
|
||||
void releaseResources();
|
||||
|
||||
|
@ -66,6 +66,9 @@ static const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 4;
|
||||
|
||||
#define ASSERT_OWNED_RESOURCE(R) GrAssert(!(R) || (R)->getContext() == this)
|
||||
|
||||
// Glorified typedef to avoid including GrDrawState.h in GrContext.h
|
||||
class GrContext::AutoRestoreEffects : public GrDrawState::AutoRestoreEffects {};
|
||||
|
||||
GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) {
|
||||
GrContext* context = SkNEW(GrContext);
|
||||
if (context->init(backend, backendContext)) {
|
||||
@ -259,7 +262,7 @@ void convolve_gaussian(GrDrawTarget* target,
|
||||
direction,
|
||||
radius,
|
||||
sigma));
|
||||
drawState->setEffect(0, conv);
|
||||
drawState->addColorEffect(conv);
|
||||
target->drawSimpleRect(rect, NULL);
|
||||
}
|
||||
|
||||
@ -372,7 +375,7 @@ GrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc,
|
||||
// texels in the resampled image are copies of texels from
|
||||
// the original.
|
||||
GrTextureParams params(SkShader::kClamp_TileMode, needsFiltering);
|
||||
drawState->createTextureEffect(0, clampedTexture, SkMatrix::I(), params);
|
||||
drawState->addColorTextureEffect(clampedTexture, SkMatrix::I(), params);
|
||||
|
||||
drawState->setVertexAttribs<gVertexAttribs>(SK_ARRAY_COUNT(gVertexAttribs));
|
||||
|
||||
@ -602,7 +605,8 @@ bool GrContext::supportsIndex8PixelConfig(const GrTextureParams* params,
|
||||
void GrContext::clear(const GrIRect* rect,
|
||||
const GrColor color,
|
||||
GrRenderTarget* target) {
|
||||
this->prepareToDraw(NULL, BUFFERED_DRAW)->clear(rect, color, target);
|
||||
AutoRestoreEffects are;
|
||||
this->prepareToDraw(NULL, BUFFERED_DRAW, &are)->clear(rect, color, target);
|
||||
}
|
||||
|
||||
void GrContext::drawPaint(const GrPaint& origPaint) {
|
||||
@ -765,8 +769,8 @@ void GrContext::drawRect(const GrPaint& paint,
|
||||
const SkMatrix* matrix) {
|
||||
SK_TRACE_EVENT0("GrContext::drawRect");
|
||||
|
||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW);
|
||||
GrDrawState::AutoStageDisable atr(fDrawState);
|
||||
AutoRestoreEffects are;
|
||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are);
|
||||
|
||||
GrRect devRect;
|
||||
SkMatrix combinedMatrix;
|
||||
@ -846,8 +850,8 @@ void GrContext::drawRectToRect(const GrPaint& paint,
|
||||
const SkMatrix* dstMatrix,
|
||||
const SkMatrix* localMatrix) {
|
||||
SK_TRACE_EVENT0("GrContext::drawRectToRect");
|
||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW);
|
||||
GrDrawState::AutoStageDisable atr(fDrawState);
|
||||
AutoRestoreEffects are;
|
||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are);
|
||||
|
||||
target->drawRect(dstRect, dstMatrix, &localRect, localMatrix);
|
||||
}
|
||||
@ -902,8 +906,8 @@ void GrContext::drawVertices(const GrPaint& paint,
|
||||
|
||||
GrDrawTarget::AutoReleaseGeometry geo;
|
||||
|
||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW);
|
||||
GrDrawState::AutoStageDisable atr(fDrawState);
|
||||
AutoRestoreEffects are;
|
||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are);
|
||||
|
||||
GrDrawState* drawState = target->drawState();
|
||||
|
||||
@ -951,8 +955,8 @@ void GrContext::drawRRect(const GrPaint& paint,
|
||||
const SkRRect& rect,
|
||||
const SkStrokeRec& stroke) {
|
||||
|
||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW);
|
||||
GrDrawState::AutoStageDisable atr(fDrawState);
|
||||
AutoRestoreEffects are;
|
||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are);
|
||||
|
||||
bool useAA = paint.isAntiAlias() &&
|
||||
!target->getDrawState().getRenderTarget()->isMultisampled() &&
|
||||
@ -971,8 +975,8 @@ void GrContext::drawOval(const GrPaint& paint,
|
||||
const GrRect& oval,
|
||||
const SkStrokeRec& stroke) {
|
||||
|
||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW);
|
||||
GrDrawState::AutoStageDisable atr(fDrawState);
|
||||
AutoRestoreEffects are;
|
||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are);
|
||||
|
||||
bool useAA = paint.isAntiAlias() &&
|
||||
!target->getDrawState().getRenderTarget()->isMultisampled() &&
|
||||
@ -1045,8 +1049,8 @@ void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrok
|
||||
// cache. This presents a potential hazard for buffered drawing. However,
|
||||
// the writePixels that uploads to the scratch will perform a flush so we're
|
||||
// OK.
|
||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW);
|
||||
GrDrawState::AutoStageDisable atr(fDrawState);
|
||||
AutoRestoreEffects are;
|
||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are);
|
||||
|
||||
bool useAA = paint.isAntiAlias() && !target->getDrawState().getRenderTarget()->isMultisampled();
|
||||
if (useAA && stroke.getWidth() < 0 && !path.isConvex()) {
|
||||
@ -1346,7 +1350,7 @@ bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
|
||||
GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit);
|
||||
GrDrawState* drawState = fGpu->drawState();
|
||||
GrAssert(effect);
|
||||
drawState->setEffect(0, effect);
|
||||
drawState->addColorEffect(effect);
|
||||
|
||||
drawState->setRenderTarget(texture->asRenderTarget());
|
||||
GrRect rect = GrRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
|
||||
@ -1421,7 +1425,7 @@ void GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst, const SkIPoint*
|
||||
return;
|
||||
}
|
||||
sampleM.preTranslate(SkIntToScalar(srcRect.fLeft), SkIntToScalar(srcRect.fTop));
|
||||
drawState->createTextureEffect(0, src, sampleM);
|
||||
drawState->addColorTextureEffect(src, sampleM);
|
||||
SkRect dstR = SkRect::MakeWH(SkIntToScalar(srcRect.width()), SkIntToScalar(srcRect.height()));
|
||||
fGpu->drawSimpleRect(dstR, NULL);
|
||||
}
|
||||
@ -1539,7 +1543,7 @@ bool GrContext::writeRenderTargetPixels(GrRenderTarget* target,
|
||||
GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit, &matrix);
|
||||
GrDrawState* drawState = fGpu->drawState();
|
||||
GrAssert(effect);
|
||||
drawState->setEffect(0, effect);
|
||||
drawState->addColorEffect(effect);
|
||||
|
||||
drawState->setRenderTarget(target);
|
||||
|
||||
@ -1548,14 +1552,21 @@ bool GrContext::writeRenderTargetPixels(GrRenderTarget* target,
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint, BufferedDraw buffered) {
|
||||
GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint,
|
||||
BufferedDraw buffered,
|
||||
AutoRestoreEffects* are) {
|
||||
// All users of this draw state should be freeing up all effects when they're done.
|
||||
// Otherwise effects that own resources may keep those resources alive indefinitely.
|
||||
GrAssert(0 == fDrawState->numColorStages() && 0 == fDrawState->numCoverageStages());
|
||||
|
||||
if (kNo_BufferedDraw == buffered && kYes_BufferedDraw == fLastDrawWasBuffered) {
|
||||
this->flushDrawBuffer();
|
||||
fLastDrawWasBuffered = kNo_BufferedDraw;
|
||||
}
|
||||
ASSERT_OWNED_RESOURCE(fRenderTarget.get());
|
||||
if (NULL != paint) {
|
||||
GrAssert(fDrawState->stagesDisabled());
|
||||
GrAssert(NULL != are);
|
||||
are->set(fDrawState);
|
||||
fDrawState->setFromPaint(*paint, fViewMatrix, fRenderTarget.get());
|
||||
#if GR_DEBUG_PARTIAL_COVERAGE_CHECK
|
||||
if ((paint->hasMask() || 0xff != paint->fCoverage) &&
|
||||
@ -1655,7 +1666,7 @@ void GrContext::setupDrawBuffer() {
|
||||
}
|
||||
|
||||
GrDrawTarget* GrContext::getTextTarget() {
|
||||
return this->prepareToDraw(NULL, BUFFERED_DRAW);
|
||||
return this->prepareToDraw(NULL, BUFFERED_DRAW, NULL);
|
||||
}
|
||||
|
||||
const GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
|
||||
@ -1779,7 +1790,8 @@ GrTexture* GrContext::gaussianBlur(GrTexture* srcTexture,
|
||||
}
|
||||
|
||||
this->setRenderTarget(dstTexture->asRenderTarget());
|
||||
GrDrawTarget* target = this->prepareToDraw(NULL, BUFFERED_DRAW);
|
||||
AutoRestoreEffects are;
|
||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are);
|
||||
convolve_gaussian(target, srcTexture, srcRect, sigmaX, radiusX,
|
||||
Gr1DKernelEffect::kX_Direction);
|
||||
srcTexture = dstTexture;
|
||||
@ -1796,7 +1808,8 @@ GrTexture* GrContext::gaussianBlur(GrTexture* srcTexture,
|
||||
}
|
||||
|
||||
this->setRenderTarget(dstTexture->asRenderTarget());
|
||||
GrDrawTarget* target = this->prepareToDraw(NULL, BUFFERED_DRAW);
|
||||
AutoRestoreEffects are;
|
||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are);
|
||||
convolve_gaussian(target, srcTexture, srcRect, sigmaY, radiusY,
|
||||
Gr1DKernelEffect::kY_Direction);
|
||||
srcTexture = dstTexture;
|
||||
|
@ -9,18 +9,17 @@
|
||||
#include "GrPaint.h"
|
||||
|
||||
bool GrDrawState::setIdentityViewMatrix() {
|
||||
SkMatrix invVM;
|
||||
bool inverted = false;
|
||||
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
||||
if (this->isStageEnabled(s)) {
|
||||
if (!inverted) {
|
||||
if (!fCommon.fViewMatrix.invert(&invVM)) {
|
||||
// sad trombone sound
|
||||
return false;
|
||||
}
|
||||
inverted = true;
|
||||
}
|
||||
fStages[s].localCoordChange(invVM);
|
||||
if (fColorStages.count() || fCoverageStages.count()) {
|
||||
SkMatrix invVM;
|
||||
if (!fCommon.fViewMatrix.invert(&invVM)) {
|
||||
// sad trombone sound
|
||||
return false;
|
||||
}
|
||||
for (int s = 0; s < fColorStages.count(); ++s) {
|
||||
fColorStages[s].localCoordChange(invVM);
|
||||
}
|
||||
for (int s = 0; s < fCoverageStages.count(); ++s) {
|
||||
fCoverageStages[s].localCoordChange(invVM);
|
||||
}
|
||||
}
|
||||
fCommon.fViewMatrix.reset();
|
||||
@ -28,31 +27,23 @@ bool GrDrawState::setIdentityViewMatrix() {
|
||||
}
|
||||
|
||||
void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
|
||||
GrAssert(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
|
||||
|
||||
fColorStages.reset();
|
||||
fCoverageStages.reset();
|
||||
|
||||
for (int i = 0; i < GrPaint::kMaxColorStages; ++i) {
|
||||
int s = i + GrPaint::kFirstColorStage;
|
||||
if (paint.isColorStageEnabled(i)) {
|
||||
fStages[s] = paint.getColorStage(i);
|
||||
} else {
|
||||
fStages[s].setEffect(NULL);
|
||||
fColorStages.push_back(paint.getColorStage(i));
|
||||
}
|
||||
}
|
||||
|
||||
this->setFirstCoverageStage(GrPaint::kFirstCoverageStage);
|
||||
|
||||
for (int i = 0; i < GrPaint::kMaxCoverageStages; ++i) {
|
||||
int s = i + GrPaint::kFirstCoverageStage;
|
||||
if (paint.isCoverageStageEnabled(i)) {
|
||||
fStages[s] = paint.getCoverageStage(i);
|
||||
} else {
|
||||
fStages[s].setEffect(NULL);
|
||||
fCoverageStages.push_back(paint.getCoverageStage(i));
|
||||
}
|
||||
}
|
||||
|
||||
// disable all stages not accessible via the paint
|
||||
for (int s = GrPaint::kTotalStages; s < GrDrawState::kNumStages; ++s) {
|
||||
this->disableStage(s);
|
||||
}
|
||||
|
||||
this->setRenderTarget(rt);
|
||||
|
||||
fCommon.fViewMatrix = vm;
|
||||
@ -162,33 +153,34 @@ bool GrDrawState::validateVertexAttribs() const {
|
||||
for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
|
||||
slTypes[i] = static_cast<GrSLType>(-1);
|
||||
}
|
||||
for (int s = 0; s < kNumStages; ++s) {
|
||||
if (this->isStageEnabled(s)) {
|
||||
const GrEffectStage& stage = fStages[s];
|
||||
const GrEffectRef* effect = stage.getEffect();
|
||||
// make sure that any attribute indices have the correct binding type, that the attrib
|
||||
// type and effect's shader lang type are compatible, and that attributes shared by
|
||||
// multiple effects use the same shader lang type.
|
||||
const int* attributeIndices = stage.getVertexAttribIndices();
|
||||
int numAttributes = stage.getVertexAttribIndexCount();
|
||||
for (int i = 0; i < numAttributes; ++i) {
|
||||
int attribIndex = attributeIndices[i];
|
||||
if (attribIndex >= fCommon.fVACount ||
|
||||
kEffect_GrVertexAttribBinding != fCommon.fVAPtr[attribIndex].fBinding) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GrSLType effectSLType = (*effect)->vertexAttribType(i);
|
||||
GrVertexAttribType attribType = fCommon.fVAPtr[attribIndex].fType;
|
||||
int slVecCount = GrSLTypeVectorCount(effectSLType);
|
||||
int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
|
||||
if (slVecCount != attribVecCount ||
|
||||
(static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
|
||||
slTypes[attribIndex] != effectSLType)) {
|
||||
return false;
|
||||
}
|
||||
slTypes[attribIndex] = effectSLType;
|
||||
int totalStages = fColorStages.count() + fCoverageStages.count();
|
||||
for (int s = 0; s < totalStages; ++s) {
|
||||
int covIdx = s - fColorStages.count();
|
||||
const GrEffectStage& stage = covIdx < 0 ? fColorStages[s] : fCoverageStages[covIdx];
|
||||
const GrEffectRef* effect = stage.getEffect();
|
||||
GrAssert(NULL != effect);
|
||||
// make sure that any attribute indices have the correct binding type, that the attrib
|
||||
// type and effect's shader lang type are compatible, and that attributes shared by
|
||||
// multiple effects use the same shader lang type.
|
||||
const int* attributeIndices = stage.getVertexAttribIndices();
|
||||
int numAttributes = stage.getVertexAttribIndexCount();
|
||||
for (int i = 0; i < numAttributes; ++i) {
|
||||
int attribIndex = attributeIndices[i];
|
||||
if (attribIndex >= fCommon.fVACount ||
|
||||
kEffect_GrVertexAttribBinding != fCommon.fVAPtr[attribIndex].fBinding) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GrSLType effectSLType = (*effect)->vertexAttribType(i);
|
||||
GrVertexAttribType attribType = fCommon.fVAPtr[attribIndex].fType;
|
||||
int slVecCount = GrSLTypeVectorCount(effectSLType);
|
||||
int attribVecCount = GrVertexAttribTypeVectorCount(attribType);
|
||||
if (slVecCount != attribVecCount ||
|
||||
(static_cast<GrSLType>(-1) != slTypes[attribIndex] &&
|
||||
slTypes[attribIndex] != effectSLType)) {
|
||||
return false;
|
||||
}
|
||||
slTypes[attribIndex] = effectSLType;
|
||||
}
|
||||
}
|
||||
|
||||
@ -196,9 +188,15 @@ bool GrDrawState::validateVertexAttribs() const {
|
||||
}
|
||||
|
||||
bool GrDrawState::willEffectReadDstColor() const {
|
||||
int startStage = this->isColorWriteDisabled() ? this->getFirstCoverageStage() : 0;
|
||||
for (int s = startStage; s < kNumStages; ++s) {
|
||||
if (this->isStageEnabled(s) && (*this->getStage(s).getEffect())->willReadDstColor()) {
|
||||
if (!this->isColorWriteDisabled()) {
|
||||
for (int s = 0; s < fColorStages.count(); ++s) {
|
||||
if ((*fColorStages[s].getEffect())->willReadDstColor()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int s = 0; s < fCoverageStages.count(); ++s) {
|
||||
if ((*fCoverageStages[s].getEffect())->willReadDstColor()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -220,12 +218,9 @@ bool GrDrawState::srcAlphaWillBeOne() const {
|
||||
}
|
||||
|
||||
// Run through the color stages
|
||||
int stageCnt = getFirstCoverageStage();
|
||||
for (int s = 0; s < stageCnt; ++s) {
|
||||
const GrEffectRef* effect = this->getStage(s).getEffect();
|
||||
if (NULL != effect) {
|
||||
(*effect)->getConstantColorComponents(&color, &validComponentFlags);
|
||||
}
|
||||
for (int s = 0; s < fColorStages.count(); ++s) {
|
||||
const GrEffectRef* effect = fColorStages[s].getEffect();
|
||||
(*effect)->getConstantColorComponents(&color, &validComponentFlags);
|
||||
}
|
||||
|
||||
// Check if the color filter could introduce an alpha.
|
||||
@ -247,11 +242,9 @@ bool GrDrawState::srcAlphaWillBeOne() const {
|
||||
color |= (SkMulDiv255Round(a, b) << (c * 8));
|
||||
}
|
||||
}
|
||||
for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
|
||||
const GrEffectRef* effect = this->getStage(s).getEffect();
|
||||
if (NULL != effect) {
|
||||
(*effect)->getConstantColorComponents(&color, &validComponentFlags);
|
||||
}
|
||||
for (int s = 0; s < fCoverageStages.count(); ++s) {
|
||||
const GrEffectRef* effect = fCoverageStages[s].getEffect();
|
||||
(*effect)->getConstantColorComponents(&color, &validComponentFlags);
|
||||
}
|
||||
}
|
||||
return (kA_GrColorComponentFlag & validComponentFlags) && 0xff == GrColorUnpackA(color);
|
||||
@ -274,13 +267,11 @@ bool GrDrawState::hasSolidCoverage() const {
|
||||
}
|
||||
|
||||
// Run through the coverage stages and see if the coverage will be all ones at the end.
|
||||
for (int s = this->getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
|
||||
const GrEffectRef* effect = this->getStage(s).getEffect();
|
||||
if (NULL != effect) {
|
||||
(*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
|
||||
}
|
||||
for (int s = 0; s < fCoverageStages.count(); ++s) {
|
||||
const GrEffectRef* effect = fCoverageStages[s].getEffect();
|
||||
(*effect)->getConstantColorComponents(&coverage, &validComponentFlags);
|
||||
}
|
||||
return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
|
||||
return (kRGBA_GrColorComponentFlags == validComponentFlags) && (0xffffffff == coverage);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -349,12 +340,8 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
|
||||
// check for coverage due to constant coverage, per-vertex coverage, or coverage stage
|
||||
bool hasCoverage = forceCoverage ||
|
||||
0xffffffff != this->getCoverage() ||
|
||||
this->hasCoverageVertexAttribute();
|
||||
for (int s = this->getFirstCoverageStage(); !hasCoverage && s < GrDrawState::kNumStages; ++s) {
|
||||
if (this->isStageEnabled(s)) {
|
||||
hasCoverage = true;
|
||||
}
|
||||
}
|
||||
this->hasCoverageVertexAttribute() ||
|
||||
fCoverageStages.count() > 0;
|
||||
|
||||
// if we don't have coverage we can check whether the dst
|
||||
// has to read at all. If not, we'll disable blending.
|
||||
@ -417,11 +404,18 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
|
||||
|
||||
void GrDrawState::AutoViewMatrixRestore::restore() {
|
||||
if (NULL != fDrawState) {
|
||||
GR_DEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
|
||||
fDrawState->fCommon.fViewMatrix = fViewMatrix;
|
||||
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
||||
if (fRestoreMask & (1 << s)) {
|
||||
fDrawState->fStages[s].restoreCoordChange(fSavedCoordChanges[s]);
|
||||
}
|
||||
GrAssert(fDrawState->numColorStages() >= fNumColorStages);
|
||||
int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
|
||||
GrAssert(fDrawState->numCoverageStages() >= numCoverageStages);
|
||||
|
||||
int i = 0;
|
||||
for (int s = 0; s < fNumColorStages; ++s, ++i) {
|
||||
fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
|
||||
}
|
||||
for (int s = 0; s < numCoverageStages; ++s, ++i) {
|
||||
fDrawState->fCoverageStages[s].restoreCoordChange(fSavedCoordChanges[i]);
|
||||
}
|
||||
fDrawState = NULL;
|
||||
}
|
||||
@ -431,21 +425,17 @@ void GrDrawState::AutoViewMatrixRestore::set(GrDrawState* drawState,
|
||||
const SkMatrix& preconcatMatrix) {
|
||||
this->restore();
|
||||
|
||||
GrAssert(NULL == fDrawState);
|
||||
if (NULL == drawState || preconcatMatrix.isIdentity()) {
|
||||
return;
|
||||
}
|
||||
fDrawState = drawState;
|
||||
|
||||
fRestoreMask = 0;
|
||||
fViewMatrix = drawState->getViewMatrix();
|
||||
drawState->fCommon.fViewMatrix.preConcat(preconcatMatrix);
|
||||
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
||||
if (drawState->isStageEnabled(s)) {
|
||||
fRestoreMask |= (1 << s);
|
||||
drawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
|
||||
drawState->fStages[s].localCoordChange(preconcatMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
this->doEffectCoordChanges(preconcatMatrix);
|
||||
GR_DEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
|
||||
}
|
||||
|
||||
bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
|
||||
@ -460,16 +450,39 @@ bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
|
||||
}
|
||||
|
||||
fViewMatrix = drawState->getViewMatrix();
|
||||
fRestoreMask = 0;
|
||||
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
||||
if (drawState->isStageEnabled(s)) {
|
||||
fRestoreMask |= (1 << s);
|
||||
drawState->fStages[s].saveCoordChange(&fSavedCoordChanges[s]);
|
||||
if (0 == drawState->numTotalStages()) {
|
||||
drawState->fCommon.fViewMatrix.reset();
|
||||
fDrawState = drawState;
|
||||
fNumColorStages = 0;
|
||||
fSavedCoordChanges.reset(0);
|
||||
GR_DEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
|
||||
return true;
|
||||
} else {
|
||||
SkMatrix inv;
|
||||
if (!fViewMatrix.invert(&inv)) {
|
||||
return false;
|
||||
}
|
||||
drawState->fCommon.fViewMatrix.reset();
|
||||
fDrawState = drawState;
|
||||
this->doEffectCoordChanges(inv);
|
||||
GR_DEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& coordChangeMatrix) {
|
||||
fSavedCoordChanges.reset(fDrawState->numTotalStages());
|
||||
int i = 0;
|
||||
|
||||
fNumColorStages = fDrawState->numColorStages();
|
||||
for (int s = 0; s < fNumColorStages; ++s, ++i) {
|
||||
fDrawState->fColorStages[s].saveCoordChange(&fSavedCoordChanges[i]);
|
||||
fDrawState->fColorStages[s].localCoordChange(coordChangeMatrix);
|
||||
}
|
||||
|
||||
int numCoverageStages = fDrawState->numCoverageStages();
|
||||
for (int s = 0; s < numCoverageStages; ++s, ++i) {
|
||||
fDrawState->fCoverageStages[s].saveCoordChange(&fSavedCoordChanges[i]);
|
||||
fDrawState->fCoverageStages[s].localCoordChange(coordChangeMatrix);
|
||||
}
|
||||
if (!drawState->setIdentityViewMatrix()) {
|
||||
return false;
|
||||
}
|
||||
fDrawState = drawState;
|
||||
return true;
|
||||
}
|
||||
|
@ -27,43 +27,21 @@ class GrDrawState : public GrRefCnt {
|
||||
public:
|
||||
SK_DECLARE_INST_COUNT(GrDrawState)
|
||||
|
||||
/**
|
||||
* Total number of effect stages. Each stage can host a GrEffect. A stage is enabled if it has a
|
||||
* GrEffect. The effect produces an output color in the fragment shader. It's inputs are the
|
||||
* output from the previous enabled stage and a position. The position is either derived from
|
||||
* the interpolated vertex positions or explicit per-vertex coords, depending upon the
|
||||
* GrAttribBindings used to draw.
|
||||
*
|
||||
* The stages are divided into two sets, color-computing and coverage-computing. The final color
|
||||
* stage produces the final pixel color. The coverage-computing stages function exactly as the
|
||||
* color-computing but the output of the final coverage stage is treated as a fractional pixel
|
||||
* coverage rather than as input to the src/dst color blend step.
|
||||
*
|
||||
* The input color to the first enabled color-stage is either the constant color or interpolated
|
||||
* per-vertex colors. The input to the first coverage stage is either a constant coverage
|
||||
* (usually full-coverage) or interpolated per-vertex coverage.
|
||||
*
|
||||
* See the documentation of kCoverageDrawing_StateBit for information about disabling the
|
||||
* the color / coverage distinction.
|
||||
*
|
||||
* Stages 0 through GrPaint::kTotalStages-1 are reserved for stages copied from the client's
|
||||
* GrPaint. Stage GrPaint::kTotalStages is earmarked for use by GrTextContext, GrPathRenderer-
|
||||
* derived classes, and the rect/oval helper classes. GrPaint::kTotalStages+1 is earmarked for
|
||||
* clipping by GrClipMaskManager. TODO: replace fixed size array of stages with variable size
|
||||
* arrays of color and coverage stages.
|
||||
*/
|
||||
enum {
|
||||
kNumStages = GrPaint::kTotalStages + 2,
|
||||
};
|
||||
GrDrawState() {
|
||||
GR_DEBUGCODE(fBlockEffectRemovalCnt = 0;)
|
||||
this->reset();
|
||||
}
|
||||
|
||||
GrDrawState() { this->reset(); }
|
||||
|
||||
GrDrawState(const SkMatrix& initialViewMatrix) { this->reset(initialViewMatrix); }
|
||||
GrDrawState(const SkMatrix& initialViewMatrix) {
|
||||
GR_DEBUGCODE(fBlockEffectRemovalCnt = 0;)
|
||||
this->reset(initialViewMatrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies another draw state.
|
||||
**/
|
||||
GrDrawState(const GrDrawState& state) {
|
||||
GR_DEBUGCODE(fBlockEffectRemovalCnt = 0;)
|
||||
*this = state;
|
||||
}
|
||||
|
||||
@ -71,17 +49,19 @@ public:
|
||||
* Copies another draw state with a preconcat to the view matrix.
|
||||
**/
|
||||
GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatrix) {
|
||||
GR_DEBUGCODE(fBlockEffectRemovalCnt = 0;)
|
||||
*this = state;
|
||||
if (!preConcatMatrix.isIdentity()) {
|
||||
for (int i = 0; i < kNumStages; ++i) {
|
||||
if (this->isStageEnabled(i)) {
|
||||
fStages[i].localCoordChange(preConcatMatrix);
|
||||
}
|
||||
for (int i = 0; i < fColorStages.count(); ++i) {
|
||||
fColorStages[i].localCoordChange(preConcatMatrix);
|
||||
}
|
||||
for (int i = 0; i < fCoverageStages.count(); ++i) {
|
||||
fCoverageStages[i].localCoordChange(preConcatMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~GrDrawState() { this->disableStages(); }
|
||||
virtual ~GrDrawState() { GrAssert(0 == fBlockEffectRemovalCnt); }
|
||||
|
||||
/**
|
||||
* Resets to the default state. GrEffects will be removed from all stages.
|
||||
@ -93,8 +73,7 @@ public:
|
||||
/**
|
||||
* Initializes the GrDrawState based on a GrPaint, view matrix and render target. Note that
|
||||
* GrDrawState encompasses more than GrPaint. Aspects of GrDrawState that have no GrPaint
|
||||
* equivalents are set to default values. GrPaint has fewer stages than GrDrawState. The extra
|
||||
* GrDrawState stages are disabled. Clipping will be enabled.
|
||||
* equivalents are set to default values. Clipping will be enabled.
|
||||
*/
|
||||
void setFromPaint(const GrPaint& , const SkMatrix& viewMatrix, GrRenderTarget*);
|
||||
|
||||
@ -359,90 +338,105 @@ public:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/// @name Effect Stages
|
||||
/// Each stage hosts a GrEffect. The effect produces an output color or coverage in the fragment
|
||||
/// shader. Its inputs are the output from the previous stage as well as some variables
|
||||
/// available to it in the fragment and vertex shader (e.g. the vertex position, the dst color,
|
||||
/// the fragment position, local coordinates).
|
||||
///
|
||||
/// The stages are divided into two sets, color-computing and coverage-computing. The final
|
||||
/// color stage produces the final pixel color. The coverage-computing stages function exactly
|
||||
/// as the color-computing but the output of the final coverage stage is treated as a fractional
|
||||
/// pixel coverage rather than as input to the src/dst color blend step.
|
||||
///
|
||||
/// The input color to the first color-stage is either the constant color or interpolated
|
||||
/// per-vertex colors. The input to the first coverage stage is either a constant coverage
|
||||
/// (usually full-coverage) or interpolated per-vertex coverage.
|
||||
///
|
||||
/// See the documentation of kCoverageDrawing_StateBit for information about disabling the
|
||||
/// the color / coverage distinction.
|
||||
////
|
||||
|
||||
const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect) {
|
||||
fStages[stageIdx].setEffect(effect);
|
||||
const GrEffectRef* addColorEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) {
|
||||
GrAssert(NULL != effect);
|
||||
SkNEW_APPEND_TO_TARRAY(&fColorStages, GrEffectStage, (effect, attr0, attr1));
|
||||
return effect;
|
||||
}
|
||||
|
||||
const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect,
|
||||
int attr0, int attr1 = -1) {
|
||||
fStages[stageIdx].setEffect(effect, attr0, attr1);
|
||||
const GrEffectRef* addCoverageEffect(const GrEffectRef* effect, int attr0 = -1, int attr1 = -1) {
|
||||
GrAssert(NULL != effect);
|
||||
SkNEW_APPEND_TO_TARRAY(&fCoverageStages, GrEffectStage, (effect, attr0, attr1));
|
||||
return effect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a GrSimpleTextureEffect that uses local coords as texture coordinates.
|
||||
*/
|
||||
void createTextureEffect(int stageIdx, GrTexture* texture, const SkMatrix& matrix) {
|
||||
GrAssert(!this->getStage(stageIdx).getEffect());
|
||||
void addColorTextureEffect(GrTexture* texture, const SkMatrix& matrix) {
|
||||
GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix);
|
||||
this->setEffect(stageIdx, effect)->unref();
|
||||
this->addColorEffect(effect)->unref();
|
||||
}
|
||||
void createTextureEffect(int stageIdx,
|
||||
GrTexture* texture,
|
||||
const SkMatrix& matrix,
|
||||
const GrTextureParams& params) {
|
||||
GrAssert(!this->getStage(stageIdx).getEffect());
|
||||
|
||||
void addCoverageTextureEffect(GrTexture* texture, const SkMatrix& matrix) {
|
||||
GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix);
|
||||
this->addCoverageEffect(effect)->unref();
|
||||
}
|
||||
|
||||
void addColorTextureEffect(GrTexture* texture,
|
||||
const SkMatrix& matrix,
|
||||
const GrTextureParams& params) {
|
||||
GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
|
||||
this->setEffect(stageIdx, effect)->unref();
|
||||
this->addColorEffect(effect)->unref();
|
||||
}
|
||||
|
||||
bool stagesDisabled() {
|
||||
for (int i = 0; i < kNumStages; ++i) {
|
||||
if (NULL != fStages[i].getEffect()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void disableStage(int stageIdx) {
|
||||
this->setEffect(stageIdx, NULL);
|
||||
void addCoverageTextureEffect(GrTexture* texture,
|
||||
const SkMatrix& matrix,
|
||||
const GrTextureParams& params) {
|
||||
GrEffectRef* effect = GrSimpleTextureEffect::Create(texture, matrix, params);
|
||||
this->addCoverageEffect(effect)->unref();
|
||||
}
|
||||
|
||||
/**
|
||||
* Release all the GrEffects referred to by this draw state.
|
||||
* When this object is destroyed it will remove any effects from the draw state that were added
|
||||
* after its constructor.
|
||||
*/
|
||||
void disableStages() {
|
||||
for (int i = 0; i < kNumStages; ++i) {
|
||||
this->disableStage(i);
|
||||
}
|
||||
}
|
||||
|
||||
class AutoStageDisable : public ::GrNoncopyable {
|
||||
class AutoRestoreEffects : public ::GrNoncopyable {
|
||||
public:
|
||||
AutoStageDisable(GrDrawState* ds) : fDrawState(ds) {}
|
||||
~AutoStageDisable() {
|
||||
AutoRestoreEffects() : fDrawState(NULL) {}
|
||||
|
||||
AutoRestoreEffects(GrDrawState* ds) : fDrawState(NULL) { this->set(ds); }
|
||||
|
||||
~AutoRestoreEffects() { this->set(NULL); }
|
||||
|
||||
void set(GrDrawState* ds) {
|
||||
if (NULL != fDrawState) {
|
||||
fDrawState->disableStages();
|
||||
int n = fDrawState->fColorStages.count() - fColorEffectCnt;
|
||||
GrAssert(n >= 0);
|
||||
fDrawState->fColorStages.pop_back_n(n);
|
||||
n = fDrawState->fCoverageStages.count() - fCoverageEffectCnt;
|
||||
GrAssert(n >= 0);
|
||||
fDrawState->fCoverageStages.pop_back_n(n);
|
||||
GR_DEBUGCODE(--fDrawState->fBlockEffectRemovalCnt;)
|
||||
}
|
||||
fDrawState = ds;
|
||||
if (NULL != ds) {
|
||||
fColorEffectCnt = ds->fColorStages.count();
|
||||
fCoverageEffectCnt = ds->fCoverageStages.count();
|
||||
GR_DEBUGCODE(++ds->fBlockEffectRemovalCnt;)
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
GrDrawState* fDrawState;
|
||||
int fColorEffectCnt;
|
||||
int fCoverageEffectCnt;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the current stage by index.
|
||||
*/
|
||||
const GrEffectStage& getStage(int stageIdx) const {
|
||||
GrAssert((unsigned)stageIdx < kNumStages);
|
||||
return fStages[stageIdx];
|
||||
}
|
||||
int numColorStages() const { return fColorStages.count(); }
|
||||
int numCoverageStages() const { return fCoverageStages.count(); }
|
||||
int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); }
|
||||
|
||||
/**
|
||||
* Called when the source coord system is changing. This ensures that effects will see the
|
||||
* correct local coordinates. oldToNew gives the transformation from the old coord system in
|
||||
* which the geometry was specified to the new coordinate system from which it will be rendered.
|
||||
*/
|
||||
void localCoordChange(const SkMatrix& oldToNew) {
|
||||
for (int i = 0; i < kNumStages; ++i) {
|
||||
if (this->isStageEnabled(i)) {
|
||||
fStages[i].localCoordChange(oldToNew);
|
||||
}
|
||||
}
|
||||
}
|
||||
const GrEffectStage& getColorStage(int stageIdx) const { return fColorStages[stageIdx]; }
|
||||
const GrEffectStage& getCoverageStage(int stageIdx) const { return fCoverageStages[stageIdx]; }
|
||||
|
||||
/**
|
||||
* Checks whether any of the effects will read the dst pixel color.
|
||||
@ -451,33 +445,6 @@ public:
|
||||
|
||||
/// @}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/// @name Coverage / Color Stages
|
||||
////
|
||||
|
||||
/**
|
||||
* A common pattern is to compute a color with the initial stages and then
|
||||
* modulate that color by a coverage value in later stage(s) (AA, mask-
|
||||
* filters, glyph mask, etc). Color-filters, xfermodes, etc should be
|
||||
* computed based on the pre-coverage-modulated color. The division of
|
||||
* stages between color-computing and coverage-computing is specified by
|
||||
* this method. Initially this is kNumStages (all stages
|
||||
* are color-computing).
|
||||
*/
|
||||
void setFirstCoverageStage(int firstCoverageStage) {
|
||||
GrAssert((unsigned)firstCoverageStage <= kNumStages);
|
||||
fCommon.fFirstCoverageStage = firstCoverageStage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the index of the first coverage-computing stage.
|
||||
*/
|
||||
int getFirstCoverageStage() const {
|
||||
return fCommon.fFirstCoverageStage;
|
||||
}
|
||||
|
||||
///@}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/// @name Blending
|
||||
////
|
||||
@ -674,10 +641,12 @@ public:
|
||||
bool setIdentity(GrDrawState* drawState);
|
||||
|
||||
private:
|
||||
GrDrawState* fDrawState;
|
||||
SkMatrix fViewMatrix;
|
||||
GrEffectStage::SavedCoordChange fSavedCoordChanges[GrDrawState::kNumStages];
|
||||
uint32_t fRestoreMask;
|
||||
void doEffectCoordChanges(const SkMatrix& coordChangeMatrix);
|
||||
|
||||
GrDrawState* fDrawState;
|
||||
SkMatrix fViewMatrix;
|
||||
int fNumColorStages;
|
||||
SkAutoSTArray<8, GrEffectStage::SavedCoordChange> fSavedCoordChanges;
|
||||
};
|
||||
|
||||
/// @}
|
||||
@ -905,21 +874,20 @@ public:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool isStageEnabled(int s) const {
|
||||
GrAssert((unsigned)s < kNumStages);
|
||||
return (NULL != fStages[s].getEffect());
|
||||
}
|
||||
|
||||
bool operator ==(const GrDrawState& s) const {
|
||||
if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) {
|
||||
if (fRenderTarget.get() != s.fRenderTarget.get() ||
|
||||
fColorStages.count() != s.fColorStages.count() ||
|
||||
fCoverageStages.count() != s.fCoverageStages.count() ||
|
||||
fCommon != s.fCommon) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < kNumStages; i++) {
|
||||
bool enabled = this->isStageEnabled(i);
|
||||
if (enabled != s.isStageEnabled(i)) {
|
||||
for (int i = 0; i < fColorStages.count(); i++) {
|
||||
if (fColorStages[i] != s.fColorStages[i]) {
|
||||
return false;
|
||||
}
|
||||
if (enabled && this->fStages[i] != s.fStages[i]) {
|
||||
}
|
||||
for (int i = 0; i < fCoverageStages.count(); i++) {
|
||||
if (fCoverageStages[i] != s.fCoverageStages[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -928,21 +896,20 @@ public:
|
||||
bool operator !=(const GrDrawState& s) const { return !(*this == s); }
|
||||
|
||||
GrDrawState& operator= (const GrDrawState& s) {
|
||||
GrAssert(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
|
||||
this->setRenderTarget(s.fRenderTarget.get());
|
||||
fCommon = s.fCommon;
|
||||
for (int i = 0; i < kNumStages; i++) {
|
||||
if (s.isStageEnabled(i)) {
|
||||
this->fStages[i] = s.fStages[i];
|
||||
}
|
||||
}
|
||||
fColorStages = s.fColorStages;
|
||||
fCoverageStages = s.fCoverageStages;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void onReset(const SkMatrix* initialViewMatrix) {
|
||||
|
||||
this->disableStages();
|
||||
GrAssert(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
|
||||
fColorStages.reset();
|
||||
fCoverageStages.reset();
|
||||
|
||||
fRenderTarget.reset(NULL);
|
||||
|
||||
@ -959,7 +926,6 @@ private:
|
||||
fCommon.fBlendConstant = 0x0;
|
||||
fCommon.fFlagBits = 0x0;
|
||||
fCommon.fStencilSettings.setDisabled();
|
||||
fCommon.fFirstCoverageStage = kNumStages;
|
||||
fCommon.fCoverage = 0xffffffff;
|
||||
fCommon.fColorFilterMode = SkXfermode::kDst_Mode;
|
||||
fCommon.fColorFilterColor = 0x0;
|
||||
@ -978,7 +944,6 @@ private:
|
||||
const GrVertexAttrib* fVAPtr;
|
||||
int fVACount;
|
||||
GrStencilSettings fStencilSettings;
|
||||
int fFirstCoverageStage;
|
||||
GrColor fCoverage;
|
||||
SkXfermode::Mode fColorFilterMode;
|
||||
GrColor fColorFilterColor;
|
||||
@ -998,7 +963,6 @@ private:
|
||||
fVACount == other.fVACount &&
|
||||
!memcmp(fVAPtr, other.fVAPtr, fVACount * sizeof(GrVertexAttrib)) &&
|
||||
fStencilSettings == other.fStencilSettings &&
|
||||
fFirstCoverageStage == other.fFirstCoverageStage &&
|
||||
fCoverage == other.fCoverage &&
|
||||
fColorFilterMode == other.fColorFilterMode &&
|
||||
fColorFilterColor == other.fColorFilterColor &&
|
||||
@ -1042,8 +1006,13 @@ public:
|
||||
// Here we ref the effects directly rather than the effect-refs. TODO: When the effect-
|
||||
// ref gets fully unref'ed it will cause the underlying effect to unref its resources
|
||||
// and recycle them to the cache (if no one else is holding a ref to the resources).
|
||||
for (int i = 0; i < kNumStages; ++i) {
|
||||
fStages[i].saveFrom(drawState.fStages[i]);
|
||||
fStages.reset(drawState.fColorStages.count() + drawState.fCoverageStages.count());
|
||||
fColorStageCnt = drawState.fColorStages.count();
|
||||
for (int i = 0; i < fColorStageCnt; ++i) {
|
||||
fStages[i].saveFrom(drawState.fColorStages[i]);
|
||||
}
|
||||
for (int i = 0; i < drawState.fCoverageStages.count(); ++i) {
|
||||
fStages[i + fColorStageCnt].saveFrom(drawState.fCoverageStages[i]);
|
||||
}
|
||||
GR_DEBUGCODE(fInitialized = true;)
|
||||
}
|
||||
@ -1052,17 +1021,35 @@ public:
|
||||
GrAssert(fInitialized);
|
||||
drawState->fCommon = fCommon;
|
||||
drawState->setRenderTarget(fRenderTarget);
|
||||
for (int i = 0; i < kNumStages; ++i) {
|
||||
fStages[i].restoreTo(&drawState->fStages[i]);
|
||||
// reinflate color/cov stage arrays.
|
||||
drawState->fColorStages.reset(fColorStageCnt);
|
||||
for (int i = 0; i < fColorStageCnt; ++i) {
|
||||
fStages[i].restoreTo(&drawState->fColorStages[i]);
|
||||
}
|
||||
int coverageStageCnt = fStages.count() - fColorStageCnt;
|
||||
drawState->fCoverageStages.reset(coverageStageCnt);
|
||||
for (int i = 0; i < coverageStageCnt; ++i) {
|
||||
fStages[fColorStageCnt + i].restoreTo(&drawState->fCoverageStages[i]);
|
||||
}
|
||||
}
|
||||
|
||||
bool isEqual(const GrDrawState& state) const {
|
||||
if (fRenderTarget != state.fRenderTarget.get() || fCommon != state.fCommon) {
|
||||
int numCoverageStages = fStages.count() - fColorStageCnt;
|
||||
if (fRenderTarget != state.fRenderTarget.get() ||
|
||||
fColorStageCnt != state.fColorStages.count() ||
|
||||
numCoverageStages != state.fCoverageStages.count() ||
|
||||
fCommon != state.fCommon) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < kNumStages; ++i) {
|
||||
if (!fStages[i].isEqual(state.fStages[i], state.hasLocalCoordAttribute())) {
|
||||
bool explicitLocalCoords = state.hasLocalCoordAttribute();
|
||||
for (int i = 0; i < fColorStageCnt; ++i) {
|
||||
if (!fStages[i].isEqual(state.fColorStages[i], explicitLocalCoords)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < numCoverageStages; ++i) {
|
||||
int s = fColorStageCnt + i;
|
||||
if (!fStages[s].isEqual(state.fCoverageStages[i], explicitLocalCoords)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -1070,18 +1057,28 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
typedef SkAutoSTArray<8, GrEffectStage::DeferredStage> DeferredStageArray;
|
||||
|
||||
GrRenderTarget* fRenderTarget;
|
||||
CommonState fCommon;
|
||||
GrEffectStage::DeferredStage fStages[kNumStages];
|
||||
int fColorStageCnt;
|
||||
DeferredStageArray fStages;
|
||||
|
||||
GR_DEBUGCODE(bool fInitialized;)
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
SkAutoTUnref<GrRenderTarget> fRenderTarget;
|
||||
CommonState fCommon;
|
||||
GrEffectStage fStages[kNumStages];
|
||||
SkAutoTUnref<GrRenderTarget> fRenderTarget;
|
||||
CommonState fCommon;
|
||||
|
||||
typedef SkSTArray<4, GrEffectStage> EffectStageArray;
|
||||
EffectStageArray fColorStages;
|
||||
EffectStageArray fCoverageStages;
|
||||
|
||||
// Some of the auto restore objects assume that no effects are removed during their lifetime.
|
||||
// This is used to assert that this condition holds.
|
||||
GR_DEBUGCODE(int fBlockEffectRemovalCnt;)
|
||||
|
||||
/**
|
||||
* Sets vertex attributes for next draw.
|
||||
|
@ -387,14 +387,21 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
|
||||
}
|
||||
|
||||
GrAssert(NULL != drawState.getRenderTarget());
|
||||
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
||||
if (drawState.isStageEnabled(s)) {
|
||||
const GrEffectRef& effect = *drawState.getStage(s).getEffect();
|
||||
int numTextures = effect->numTextures();
|
||||
for (int t = 0; t < numTextures; ++t) {
|
||||
GrTexture* texture = effect->texture(t);
|
||||
GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
|
||||
}
|
||||
|
||||
for (int s = 0; s < drawState.numColorStages(); ++s) {
|
||||
const GrEffectRef& effect = *drawState.getColorStage(s).getEffect();
|
||||
int numTextures = effect->numTextures();
|
||||
for (int t = 0; t < numTextures; ++t) {
|
||||
GrTexture* texture = effect->texture(t);
|
||||
GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
|
||||
}
|
||||
}
|
||||
for (int s = 0; s < drawState.numCoverageStages(); ++s) {
|
||||
const GrEffectRef& effect = *drawState.getCoverageStage(s).getEffect();
|
||||
int numTextures = effect->numTextures();
|
||||
for (int t = 0; t < numTextures; ++t) {
|
||||
GrTexture* texture = effect->texture(t);
|
||||
GrAssert(texture->asRenderTarget() != drawState.getRenderTarget());
|
||||
}
|
||||
}
|
||||
|
||||
@ -912,7 +919,7 @@ bool GrDrawTarget::onCopySurface(GrSurface* dst,
|
||||
matrix.setTranslate(SkIntToScalar(srcRect.fLeft - dstPoint.fX),
|
||||
SkIntToScalar(srcRect.fTop - dstPoint.fY));
|
||||
matrix.postIDiv(tex->width(), tex->height());
|
||||
this->drawState()->createTextureEffect(0, tex, matrix);
|
||||
this->drawState()->addColorTextureEffect(tex, matrix);
|
||||
SkIRect dstRect = SkIRect::MakeXYWH(dstPoint.fX,
|
||||
dstPoint.fY,
|
||||
srcRect.width(),
|
||||
|
@ -355,7 +355,7 @@ public:
|
||||
* Helper for drawRect when the caller doesn't need separate local rects or matrices.
|
||||
*/
|
||||
void drawSimpleRect(const GrRect& rect, const SkMatrix* matrix = NULL) {
|
||||
drawRect(rect, matrix, NULL, NULL);
|
||||
this->drawRect(rect, matrix, NULL, NULL);
|
||||
}
|
||||
void drawSimpleRect(const GrIRect& irect, const SkMatrix* matrix = NULL) {
|
||||
SkRect rect = SkRect::MakeFromIRect(irect);
|
||||
|
@ -292,9 +292,9 @@ const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool GrGpu::setupClipAndFlushState(DrawType type, const GrDeviceCoordTexture* dstCopy) {
|
||||
|
||||
if (!fClipMaskManager.setupClipping(this->getClip())) {
|
||||
bool GrGpu::setupClipAndFlushState(DrawType type, const GrDeviceCoordTexture* dstCopy,
|
||||
GrDrawState::AutoRestoreEffects* are) {
|
||||
if (!fClipMaskManager.setupClipping(this->getClip(), are)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -336,8 +336,10 @@ void GrGpu::geometrySourceWillPop(const GeometrySrcState& restoredState) {
|
||||
|
||||
void GrGpu::onDraw(const DrawInfo& info) {
|
||||
this->handleDirtyContext();
|
||||
GrDrawState::AutoRestoreEffects are;
|
||||
if (!this->setupClipAndFlushState(PrimTypeToDrawType(info.primitiveType()),
|
||||
info.getDstCopy())) {
|
||||
info.getDstCopy(),
|
||||
&are)) {
|
||||
return;
|
||||
}
|
||||
this->onGpuDraw(info);
|
||||
@ -350,7 +352,8 @@ void GrGpu::onStencilPath(const GrPath* path, const SkStrokeRec&, SkPath::FillTy
|
||||
GrAutoTRestore<GrStencilSettings> asr(this->drawState()->stencil());
|
||||
|
||||
this->setStencilPathSettings(*path, fill, this->drawState()->stencil());
|
||||
if (!this->setupClipAndFlushState(kStencilPath_DrawType, NULL)) {
|
||||
GrDrawState::AutoRestoreEffects are;
|
||||
if (!this->setupClipAndFlushState(kStencilPath_DrawType, NULL, &are)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -365,7 +365,9 @@ protected:
|
||||
}
|
||||
|
||||
// prepares clip flushes gpu state before a draw
|
||||
bool setupClipAndFlushState(DrawType, const GrDeviceCoordTexture* dstCopy);
|
||||
bool setupClipAndFlushState(DrawType,
|
||||
const GrDeviceCoordTexture* dstCopy,
|
||||
GrDrawState::AutoRestoreEffects* are);
|
||||
|
||||
// Functions used to map clip-respecting stencil tests into normal
|
||||
// stencil funcs supported by GPUs.
|
||||
|
@ -349,16 +349,10 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
|
||||
|
||||
SkStrokeRec::Style style = stroke.getStyle();
|
||||
bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style);
|
||||
enum {
|
||||
// the edge effects share this stage with glyph rendering
|
||||
// (kGlyphMaskStage in GrTextContext) && SW path rendering
|
||||
// (kPathMaskStage in GrSWMaskHelper)
|
||||
kEdgeEffectStage = GrPaint::kTotalStages,
|
||||
};
|
||||
|
||||
GrEffectRef* effect = CircleEdgeEffect::Create(isStroked);
|
||||
static const int kCircleEdgeAttrIndex = 1;
|
||||
drawState->setEffect(kEdgeEffectStage, effect, kCircleEdgeAttrIndex)->unref();
|
||||
drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref();
|
||||
|
||||
SkScalar innerRadius = 0.0f;
|
||||
SkScalar outerRadius = radius;
|
||||
@ -509,18 +503,11 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
|
||||
|
||||
EllipseVertex* verts = reinterpret_cast<EllipseVertex*>(geo.vertices());
|
||||
|
||||
enum {
|
||||
// the edge effects share this stage with glyph rendering
|
||||
// (kGlyphMaskStage in GrTextContext) && SW path rendering
|
||||
// (kPathMaskStage in GrSWMaskHelper)
|
||||
kEdgeEffectStage = GrPaint::kTotalStages,
|
||||
};
|
||||
GrEffectRef* effect = EllipseEdgeEffect::Create(isStroked);
|
||||
|
||||
static const int kEllipseCenterAttrIndex = 1;
|
||||
static const int kEllipseEdgeAttrIndex = 2;
|
||||
drawState->setEffect(kEdgeEffectStage, effect,
|
||||
kEllipseCenterAttrIndex, kEllipseEdgeAttrIndex)->unref();
|
||||
drawState->addCoverageEffect(effect, kEllipseCenterAttrIndex, kEllipseEdgeAttrIndex)->unref();
|
||||
|
||||
// Compute the reciprocals of the radii here to save time in the shader
|
||||
SkScalar xRadRecip = SkScalarInvert(xRadius);
|
||||
@ -657,13 +644,6 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
|
||||
|
||||
bool isStroked = (SkStrokeRec::kStroke_Style == style || SkStrokeRec::kHairline_Style == style);
|
||||
|
||||
enum {
|
||||
// the edge effects share this stage with glyph rendering
|
||||
// (kGlyphMaskStage in GrTextContext) && SW path rendering
|
||||
// (kPathMaskStage in GrSWMaskHelper)
|
||||
kEdgeEffectStage = GrPaint::kTotalStages,
|
||||
};
|
||||
|
||||
GrIndexBuffer* indexBuffer = this->rRectIndexBuffer(context->getGpu());
|
||||
if (NULL == indexBuffer) {
|
||||
GrPrintf("Failed to create index buffer!\n");
|
||||
@ -702,7 +682,7 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
|
||||
|
||||
GrEffectRef* effect = CircleEdgeEffect::Create(isStroked);
|
||||
static const int kCircleEdgeAttrIndex = 1;
|
||||
drawState->setEffect(kEdgeEffectStage, effect, kCircleEdgeAttrIndex)->unref();
|
||||
drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref();
|
||||
|
||||
// The radii are outset for two reasons. First, it allows the shader to simply perform
|
||||
// clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the
|
||||
@ -805,8 +785,8 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
|
||||
GrEffectRef* effect = EllipseEdgeEffect::Create(isStroked);
|
||||
static const int kEllipseOffsetAttrIndex = 1;
|
||||
static const int kEllipseRadiiAttrIndex = 2;
|
||||
drawState->setEffect(kEdgeEffectStage, effect,
|
||||
kEllipseOffsetAttrIndex, kEllipseRadiiAttrIndex)->unref();
|
||||
drawState->addCoverageEffect(effect,
|
||||
kEllipseOffsetAttrIndex, kEllipseRadiiAttrIndex)->unref();
|
||||
|
||||
// Compute the reciprocals of the radii here to save time in the shader
|
||||
SkScalar xRadRecip = SkScalarInvert(xRadius);
|
||||
|
@ -191,6 +191,7 @@ void GrSWMaskHelper::DrawToTargetWithPathMask(GrTexture* texture,
|
||||
if (!avmr.setIdentity(drawState)) {
|
||||
return;
|
||||
}
|
||||
GrDrawState::AutoRestoreEffects are(drawState);
|
||||
enum {
|
||||
// the SW path renderer shares this stage with glyph
|
||||
// rendering (kGlyphMaskStage in GrTextContext)
|
||||
@ -213,13 +214,11 @@ void GrSWMaskHelper::DrawToTargetWithPathMask(GrTexture* texture,
|
||||
maskMatrix.preTranslate(SkIntToScalar(-rect.fLeft), SkIntToScalar(-rect.fTop));
|
||||
maskMatrix.preConcat(drawState->getViewMatrix());
|
||||
|
||||
GrAssert(!drawState->isStageEnabled(kPathMaskStage));
|
||||
drawState->setEffect(kPathMaskStage,
|
||||
drawState->addCoverageEffect(
|
||||
GrSimpleTextureEffect::Create(texture,
|
||||
maskMatrix,
|
||||
false,
|
||||
GrEffect::kPosition_CoordsType))->unref();
|
||||
|
||||
target->drawSimpleRect(dstRect);
|
||||
drawState->disableStage(kPathMaskStage);
|
||||
}
|
||||
|
@ -18,17 +18,15 @@
|
||||
#include "SkPath.h"
|
||||
#include "SkStrokeRec.h"
|
||||
|
||||
// glyph rendering shares this stage with edge rendering (kEdgeEffectStage in GrContext) && SW path
|
||||
// rendering (kPathMaskStage in GrSWMaskHelper)
|
||||
static const int kGlyphMaskStage = GrPaint::kTotalStages;
|
||||
static const int kGlyphCoordsAttributeIndex = 1;
|
||||
|
||||
void GrTextContext::flushGlyphs() {
|
||||
if (NULL == fDrawTarget) {
|
||||
return;
|
||||
}
|
||||
GrDrawTarget::AutoStateRestore asr(fDrawTarget, GrDrawTarget::kPreserve_ASRInit);
|
||||
|
||||
GrDrawState* drawState = fDrawTarget->drawState();
|
||||
GrDrawState::AutoRestoreEffects are(drawState);
|
||||
drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget());
|
||||
|
||||
if (fCurrVertex > 0) {
|
||||
@ -38,9 +36,9 @@ void GrTextContext::flushGlyphs() {
|
||||
GrTextureParams params(SkShader::kRepeat_TileMode, false);
|
||||
|
||||
// This effect could be stored with one of the cache objects (atlas?)
|
||||
drawState->setEffect(kGlyphMaskStage,
|
||||
GrSimpleTextureEffect::CreateWithCustomCoords(fCurrTexture, params),
|
||||
kGlyphCoordsAttributeIndex)->unref();
|
||||
drawState->addCoverageEffect(
|
||||
GrSimpleTextureEffect::CreateWithCustomCoords(fCurrTexture, params),
|
||||
kGlyphCoordsAttributeIndex)->unref();
|
||||
|
||||
if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) {
|
||||
if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() ||
|
||||
|
@ -14,6 +14,24 @@
|
||||
|
||||
#include "SkChecksum.h"
|
||||
|
||||
namespace {
|
||||
inline GrGLEffect::EffectKey get_key_and_update_stats(const GrEffectStage& stage,
|
||||
const GrGLCaps& caps,
|
||||
bool useExplicitLocalCoords,
|
||||
bool* setTrueIfReadsDst,
|
||||
bool* setTrueIfReadsPos) {
|
||||
const GrEffectRef& effect = *stage.getEffect();
|
||||
const GrBackendEffectFactory& factory = effect->getFactory();
|
||||
GrDrawEffect drawEffect(stage, useExplicitLocalCoords);
|
||||
if (effect->willReadDstColor()) {
|
||||
*setTrueIfReadsDst = true;
|
||||
}
|
||||
if (effect->willReadFragmentPosition()) {
|
||||
*setTrueIfReadsPos = true;
|
||||
}
|
||||
return factory.glEffectKey(drawEffect, caps);
|
||||
}
|
||||
}
|
||||
void GrGLProgramDesc::Build(const GrDrawState& drawState,
|
||||
bool isPoints,
|
||||
GrDrawState::BlendOptFlags blendOpts,
|
||||
@ -50,27 +68,10 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
|
||||
bool colorIsSolidWhite = (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) ||
|
||||
(!requiresColorAttrib && 0xffffffff == drawState.getColor());
|
||||
|
||||
// Do an initial loop over the stages to count them. We count the color and coverage effects
|
||||
// separately here. Later we may decide the distinction doesn't matter and will count all
|
||||
// effects as color in desc. Two things will allow simplication of this mess: GrDrawState will
|
||||
// have tight lists of color and coverage stages rather than a fixed size array with NULLS and
|
||||
// the xfermode-color filter will be removed.
|
||||
if (!skipColor) {
|
||||
for (int s = 0; s < drawState.getFirstCoverageStage(); ++s) {
|
||||
if (drawState.isStageEnabled(s)) {
|
||||
colorStages->push_back(&drawState.getStage(s));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!skipCoverage) {
|
||||
for (int s = drawState.getFirstCoverageStage(); s < GrDrawState::kNumStages; ++s) {
|
||||
if (drawState.isStageEnabled(s)) {
|
||||
coverageStages->push_back(&drawState.getStage(s));
|
||||
}
|
||||
}
|
||||
}
|
||||
int numEffects = (skipColor ? 0 : drawState.numColorStages()) +
|
||||
(skipCoverage ? 0 : drawState.numCoverageStages());
|
||||
|
||||
size_t newKeyLength = KeyLength(colorStages->count() + coverageStages->count());
|
||||
size_t newKeyLength = KeyLength(numEffects);
|
||||
bool allocChanged;
|
||||
desc->fKey.reset(newKeyLength, SkAutoMalloc::kAlloc_OnShrink, &allocChanged);
|
||||
if (allocChanged || !desc->fInitialized) {
|
||||
@ -86,20 +87,18 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
|
||||
int currEffectKey = 0;
|
||||
bool readsDst = false;
|
||||
bool readFragPosition = false;
|
||||
for (int s = 0; s < GrDrawState::kNumStages; ++s) {
|
||||
bool skip = s < drawState.getFirstCoverageStage() ? skipColor : skipCoverage;
|
||||
if (!skip && drawState.isStageEnabled(s)) {
|
||||
const GrEffectRef& effect = *drawState.getStage(s).getEffect();
|
||||
const GrBackendEffectFactory& factory = effect->getFactory();
|
||||
GrDrawEffect drawEffect(drawState.getStage(s), requiresLocalCoordAttrib);
|
||||
effectKeys[currEffectKey] = factory.glEffectKey(drawEffect, gpu->glCaps());
|
||||
++currEffectKey;
|
||||
if (effect->willReadDstColor()) {
|
||||
readsDst = true;
|
||||
}
|
||||
if (effect->willReadFragmentPosition()) {
|
||||
readFragPosition = true;
|
||||
}
|
||||
if (!skipColor) {
|
||||
for (int s = 0; s < drawState.numColorStages(); ++s) {
|
||||
effectKeys[currEffectKey++] =
|
||||
get_key_and_update_stats(drawState.getColorStage(s), gpu->glCaps(),
|
||||
requiresLocalCoordAttrib, &readsDst, &readFragPosition);
|
||||
}
|
||||
}
|
||||
if (!skipCoverage) {
|
||||
for (int s = 0; s < drawState.numCoverageStages(); ++s) {
|
||||
effectKeys[currEffectKey++] =
|
||||
get_key_and_update_stats(drawState.getCoverageStage(s), gpu->glCaps(),
|
||||
requiresLocalCoordAttrib, &readsDst, &readFragPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,7 +188,8 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
|
||||
|
||||
// If we do have coverage determine whether it matters.
|
||||
bool separateCoverageFromColor = false;
|
||||
if (!drawState.isCoverageDrawing() && (coverageStages->count() > 0 || requiresCoverageAttrib)) {
|
||||
if (!drawState.isCoverageDrawing() && !skipCoverage &&
|
||||
(drawState.numCoverageStages() > 0 || requiresCoverageAttrib)) {
|
||||
// color filter is applied between color/coverage computation
|
||||
if (SkXfermode::kDst_Mode != header->fColorFilterXfermode) {
|
||||
separateCoverageFromColor = true;
|
||||
@ -224,14 +224,24 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
|
||||
separateCoverageFromColor = true;
|
||||
}
|
||||
}
|
||||
if (separateCoverageFromColor) {
|
||||
header->fColorEffectCnt = colorStages->count();
|
||||
header->fCoverageEffectCnt = coverageStages->count();
|
||||
} else {
|
||||
header->fColorEffectCnt = colorStages->count() + coverageStages->count();
|
||||
header->fCoverageEffectCnt = 0;
|
||||
colorStages->push_back_n(coverageStages->count(), coverageStages->begin());
|
||||
coverageStages->reset();
|
||||
if (!skipColor) {
|
||||
for (int s = 0; s < drawState.numColorStages(); ++s) {
|
||||
colorStages->push_back(&drawState.getColorStage(s));
|
||||
}
|
||||
header->fColorEffectCnt = drawState.numColorStages();
|
||||
}
|
||||
if (!skipCoverage) {
|
||||
SkTArray<const GrEffectStage*, true>* array;
|
||||
if (separateCoverageFromColor) {
|
||||
array = coverageStages;
|
||||
header->fCoverageEffectCnt = drawState.numCoverageStages();
|
||||
} else {
|
||||
array = colorStages;
|
||||
header->fColorEffectCnt += drawState.numCoverageStages();
|
||||
}
|
||||
for (int s = 0; s < drawState.numCoverageStages(); ++s) {
|
||||
array->push_back(&drawState.getCoverageStage(s));
|
||||
}
|
||||
}
|
||||
|
||||
*desc->checksum() = 0;
|
||||
|
@ -53,7 +53,7 @@ void GrFrameBufferObj::setStencil(GrFBBindableObj *buffer) {
|
||||
GrAlwaysAssert(fStencilBuffer->getStencilBound(this));
|
||||
fStencilBuffer->resetStencilBound(this);
|
||||
|
||||
GrAlwaysAssert(!fStencilBuffer->getDeleted());
|
||||
//GrAlwaysAssert(!fStencilBuffer->getDeleted());
|
||||
fStencilBuffer->unref();
|
||||
}
|
||||
fStencilBuffer = buffer;
|
||||
|
@ -118,8 +118,6 @@ void GrGLProgramDesc::setRandom(SkMWCRandom* random,
|
||||
|
||||
bool GrGpuGL::programUnitTest(int maxStages) {
|
||||
|
||||
maxStages = GrMin(maxStages, (int)GrDrawState::kNumStages);
|
||||
|
||||
GrTextureDesc dummyDesc;
|
||||
dummyDesc.fFlags = kRenderTarget_GrTextureFlagBit;
|
||||
dummyDesc.fConfig = kSkia8888_GrPixelConfig;
|
||||
@ -207,7 +205,7 @@ static void GLProgramsTest(skiatest::Reporter* reporter, GrContextFactory* facto
|
||||
GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(type));
|
||||
if (NULL != context) {
|
||||
GrGpuGL* gpu = static_cast<GrGpuGL*>(context->getGpu());
|
||||
int maxStages = GrDrawState::kNumStages;
|
||||
int maxStages = 6;
|
||||
#if SK_ANGLE
|
||||
// Some long shaders run out of temporary registers in the D3D compiler on ANGLE.
|
||||
if (type == GrContextFactory::kANGLE_GLContextType) {
|
||||
|
Loading…
Reference in New Issue
Block a user