From eb6879f50a5564eeb981ec5616b55bf685eb76fc Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Thu, 13 Jun 2013 19:34:18 +0000 Subject: [PATCH] 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 --- include/gpu/GrContext.h | 3 +- include/gpu/GrEffectStage.h | 96 ++++---- src/gpu/GrAAConvexPathRenderer.cpp | 2 +- src/gpu/GrAAHairLinePathRenderer.cpp | 31 +-- src/gpu/GrAARectRenderer.cpp | 18 +- src/gpu/GrClipMaskManager.cpp | 15 +- src/gpu/GrClipMaskManager.h | 4 +- src/gpu/GrContext.cpp | 59 +++-- src/gpu/GrDrawState.cpp | 215 +++++++++--------- src/gpu/GrDrawState.h | 307 +++++++++++++------------- src/gpu/GrDrawTarget.cpp | 25 ++- src/gpu/GrDrawTarget.h | 2 +- src/gpu/GrGpu.cpp | 13 +- src/gpu/GrGpu.h | 4 +- src/gpu/GrOvalRenderer.cpp | 30 +-- src/gpu/GrSWMaskHelper.cpp | 5 +- src/gpu/GrTextContext.cpp | 12 +- src/gpu/gl/GrGLProgramDesc.cpp | 96 ++++---- src/gpu/gl/debug/GrFrameBufferObj.cpp | 2 +- tests/GLProgramsTest.cpp | 4 +- 20 files changed, 470 insertions(+), 473 deletions(-) diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h index 712eff60b..5c796b26c 100644 --- a/include/gpu/GrContext.h +++ b/include/gpu/GrContext.h @@ -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); diff --git a/include/gpu/GrEffectStage.h b/include/gpu/GrEffectStage.h index 0ef334e43..3f10bdcf1 100644 --- a/include/gpu/GrEffectStage.h +++ b/include/gpu/GrEffectStage.h @@ -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 fEffectRef; + int fVertexAttribIndices[2]; }; #endif diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp index 77980e468..5d461ab3e 100644 --- a/src/gpu/GrAAConvexPathRenderer.cpp +++ b/src/gpu/GrAAConvexPathRenderer.cpp @@ -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()) { diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp index bed931c03..51bff1efc 100644 --- a/src/gpu/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/GrAAHairLinePathRenderer.cpp @@ -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, diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp index f28d91456..7fe0517f7 100644 --- a/src/gpu/GrAARectRenderer.cpp +++ b/src/gpu/GrAARectRenderer.cpp @@ -542,17 +542,10 @@ void GrAARectRenderer::shaderFillAARect(GrGpu* gpu, RectVertex* verts = reinterpret_cast(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(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); diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp index 136217967..bc20c2542 100644 --- a/src/gpu/GrClipMaskManager.cpp +++ b/src/gpu/GrClipMaskManager.cpp @@ -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 diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h index 6d9d6f693..121737b89 100644 --- a/src/gpu/GrClipMaskManager.h +++ b/src/gpu/GrClipMaskManager.h @@ -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(); diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index a28f1bc69..c94c1a925 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -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(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; diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp index 2a81e2619..7c6854347 100644 --- a/src/gpu/GrDrawState.cpp +++ b/src/gpu/GrDrawState.cpp @@ -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(-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(-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(-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; } diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h index 5b1194d0c..9d1e64d1f 100644 --- a/src/gpu/GrDrawState.h +++ b/src/gpu/GrDrawState.h @@ -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 fRenderTarget; - CommonState fCommon; - GrEffectStage fStages[kNumStages]; + SkAutoTUnref 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. diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index 02bc8d740..1f3b630f0 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -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(), diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h index e87613663..f31dd6cd2 100644 --- a/src/gpu/GrDrawTarget.h +++ b/src/gpu/GrDrawTarget.h @@ -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); diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index 0c58430dd..ae98b54be 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -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 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; } diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index 5b556c5b2..3acfac270 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -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. diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp index 70b5c7720..465dd2b45 100644 --- a/src/gpu/GrOvalRenderer.cpp +++ b/src/gpu/GrOvalRenderer.cpp @@ -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(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); diff --git a/src/gpu/GrSWMaskHelper.cpp b/src/gpu/GrSWMaskHelper.cpp index fc34591fc..0fab55c36 100644 --- a/src/gpu/GrSWMaskHelper.cpp +++ b/src/gpu/GrSWMaskHelper.cpp @@ -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); } diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp index 19f18b50a..65c5c7a1f 100644 --- a/src/gpu/GrTextContext.cpp +++ b/src/gpu/GrTextContext.cpp @@ -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() || diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp index 4f0011803..6b3008b7b 100644 --- a/src/gpu/gl/GrGLProgramDesc.cpp +++ b/src/gpu/gl/GrGLProgramDesc.cpp @@ -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* 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; diff --git a/src/gpu/gl/debug/GrFrameBufferObj.cpp b/src/gpu/gl/debug/GrFrameBufferObj.cpp index 24ab12056..7dc12acaf 100644 --- a/src/gpu/gl/debug/GrFrameBufferObj.cpp +++ b/src/gpu/gl/debug/GrFrameBufferObj.cpp @@ -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; diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp index 53af43097..55c4c0919 100644 --- a/tests/GLProgramsTest.cpp +++ b/tests/GLProgramsTest.cpp @@ -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(type)); if (NULL != context) { GrGpuGL* gpu = static_cast(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) {