From 0fec61d19ca9088d54f58bd0a67150171b83d66c Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Thu, 8 Dec 2011 15:53:53 +0000 Subject: [PATCH] Make GrDrawState a real class with getters and setters Review URL: http://codereview.appspot.com/5448119/ git-svn-id: http://skia.googlecode.com/svn/trunk@2830 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/gpu/GrAAHairLinePathRenderer.cpp | 6 +- src/gpu/GrContext.cpp | 78 +++-- src/gpu/GrDefaultPathRenderer.cpp | 34 +- src/gpu/GrDrawState.h | 601 ++++++++++++++++++++++++++++++++--- src/gpu/GrDrawTarget.cpp | 172 ++-------- src/gpu/GrDrawTarget.h | 432 +++++-------------------- src/gpu/GrGpu.cpp | 37 ++- src/gpu/GrGpu.h | 4 +- src/gpu/GrGpuGL.cpp | 208 ++++++------ src/gpu/GrGpuGLShaders.cpp | 190 +++++------ src/gpu/GrInOrderDrawBuffer.cpp | 16 +- src/gpu/GrTesselatedPathRenderer.cpp | 15 +- src/gpu/GrTextContext.cpp | 12 +- 13 files changed, 970 insertions(+), 835 deletions(-) diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp index e306b67..1806797 100644 --- a/src/gpu/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/GrAAHairLinePathRenderer.cpp @@ -702,7 +702,8 @@ void GrAAHairLinePathRenderer::drawPath(GrDrawState::StageMask stageMask) { int nBufLines = fLinesIndexBuffer->maxQuads(); while (lines < fLineSegmentCnt) { int n = GrMin(fLineSegmentCnt-lines, nBufLines); - fTarget->setVertexEdgeType(GrDrawState::kHairLine_EdgeType); + fTarget->drawState()->setVertexEdgeType( + GrDrawState::kHairLine_EdgeType); fTarget->drawIndexed(kTriangles_PrimitiveType, kVertsPerLineSeg*lines, // startV 0, // startI @@ -715,7 +716,8 @@ void GrAAHairLinePathRenderer::drawPath(GrDrawState::StageMask stageMask) { int quads = 0; while (quads < fQuadCnt) { int n = GrMin(fQuadCnt-quads, kNumQuadsInIdxBuffer); - fTarget->setVertexEdgeType(GrDrawState::kHairQuad_EdgeType); + fTarget->drawState()->setVertexEdgeType( + GrDrawState::kHairQuad_EdgeType); fTarget->drawIndexed(kTriangles_PrimitiveType, 4*fLineSegmentCnt + kVertsPerQuad*quads, // startV 0, // startI diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index de80f65..a792bd1 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -217,21 +217,17 @@ void gen_stencil_key_values(const GrStencilBuffer* sb, // It does not reset stage textures/samplers or per-vertex-edge-aa state since // they aren't used unless the vertex layout references them. // It also doesn't set the render target. -void reset_target_state(GrDrawTarget* target){ - target->setViewMatrix(GrMatrix::I()); - target->setColorFilter(0, SkXfermode::kDst_Mode); - target->disableState(GrDrawTarget::kDither_StateBit | - GrDrawTarget::kHWAntialias_StateBit | - GrDrawTarget::kClip_StateBit | - GrDrawTarget::kNoColorWrites_StateBit | - GrDrawTarget::kEdgeAAConcave_StateBit); - target->setEdgeAAData(NULL, 0); - target->disableStencil(); - target->setAlpha(0xFF); - target->setBlendFunc(kOne_BlendCoeff, - kZero_BlendCoeff); - target->setFirstCoverageStage(GrDrawState::kNumStages); - target->setDrawFace(GrDrawState::kBoth_DrawFace); +void reset_target_state(GrDrawState* drawState) { + drawState->setViewMatrix(GrMatrix::I()); + drawState->setColorFilter(0, SkXfermode::kDst_Mode); + drawState->resetStateFlags(); + drawState->setEdgeAAData(NULL, 0); + drawState->disableStencil(); + drawState->setAlpha(0xFF); + drawState->setBlendFunc(kOne_BlendCoeff, + kZero_BlendCoeff); + drawState->setFirstCoverageStage(GrDrawState::kNumStages); + drawState->setDrawFace(GrDrawState::kBoth_DrawFace); } } @@ -352,7 +348,7 @@ GrContext::TextureCacheEntry GrContext::createAndLockTexture(TextureKey key, if (NULL != texture) { GrDrawTarget::AutoStateRestore asr(fGpu); - reset_target_state(fGpu); + reset_target_state(fGpu->drawState()); fGpu->setRenderTarget(texture->asRenderTarget()); fGpu->setTexture(0, clampEntry.texture()); @@ -601,7 +597,7 @@ const GrClip& GrContext::getClip() const { return fGpu->getClip(); } void GrContext::setClip(const GrClip& clip) { fGpu->setClip(clip); - fGpu->enableState(GrDrawTarget::kClip_StateBit); + fGpu->drawState()->enableState(GrDrawState::kClip_StateBit); } void GrContext::setClip(const GrIRect& rect) { @@ -806,14 +802,13 @@ void GrContext::setupOffscreenAAPass1(GrDrawTarget* target, target->enableState(GrDrawTarget::kHWAntialias_StateBit); #endif - GrMatrix transM; int left = boundRect.fLeft + tileX * record->fTileSizeX; int top = boundRect.fTop + tileY * record->fTileSizeY; - transM.setTranslate(-left * GR_Scalar1, -top * GR_Scalar1); - target->postConcatViewMatrix(transM); - GrMatrix scaleM; - scaleM.setScale(record->fScale * GR_Scalar1, record->fScale * GR_Scalar1); - target->postConcatViewMatrix(scaleM); + GrDrawState* drawState = target->drawState(); + drawState->viewMatrix()->postTranslate(-left * GR_Scalar1, + -top * GR_Scalar1); + drawState->viewMatrix()->postScale(record->fScale * GR_Scalar1, + record->fScale * GR_Scalar1); int w = (tileX == record->fTileCountX-1) ? boundRect.fRight - left : record->fTileSizeX; @@ -1327,7 +1322,7 @@ void GrContext::drawRect(const GrPaint& paint, GrDrawTarget::AutoViewMatrixRestore avmr; if (NULL != matrix) { avmr.set(target); - target->preConcatViewMatrix(*matrix); + target->viewMatrix()->preConcat(*matrix); target->preConcatSamplerMatrices(stageMask, *matrix); } @@ -1351,7 +1346,7 @@ void GrContext::drawRect(const GrPaint& paint, m.postConcat(*matrix); } - target->preConcatViewMatrix(m); + target->viewMatrix()->preConcat(m); target->preConcatSamplerMatrices(stageMask, m); target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4); @@ -1378,7 +1373,8 @@ void GrContext::drawRectToRect(const GrPaint& paint, #if GR_STATIC_RECT_VB GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory); - + GrDrawState* drawState = target->drawState(); + GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL); GrDrawTarget::AutoViewMatrixRestore avmr(target); @@ -1390,13 +1386,13 @@ void GrContext::drawRectToRect(const GrPaint& paint, if (NULL != dstMatrix) { m.postConcat(*dstMatrix); } - target->preConcatViewMatrix(m); + drawState->viewMatrix()->preConcat(m); // srcRect refers to first stage int otherStageMask = paint.getActiveStageMask() & (~(1 << GrPaint::kFirstTextureStage)); if (otherStageMask) { - target->preConcatSamplerMatrices(otherStageMask, m); + drawState->preConcatSamplerMatrices(otherStageMask, m); } m.setAll(srcRect.width(), 0, srcRect.fLeft, @@ -1405,7 +1401,7 @@ void GrContext::drawRectToRect(const GrPaint& paint, if (NULL != srcMatrix) { m.postConcat(*srcMatrix); } - target->preConcatSamplerMatrix(GrPaint::kFirstTextureStage, m); + drawState->sampler(GrPaint::kFirstTextureStage)->preConcatMatrix(m); const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer(); if (NULL == sqVB) { @@ -1781,7 +1777,7 @@ bool GrContext::internalReadRenderTargetPixels(GrRenderTarget* target, GrAssert(NULL != target); GrDrawTarget::AutoStateRestore asr(fGpu); - reset_target_state(fGpu); + reset_target_state(fGpu->drawState()); fGpu->setRenderTarget(target); @@ -1819,7 +1815,7 @@ void GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst) { ASSERT_OWNED_RESOURCE(src); GrDrawTarget::AutoStateRestore asr(fGpu); - reset_target_state(fGpu); + reset_target_state(fGpu->drawState()); fGpu->setRenderTarget(dst); GrSamplerState sampler(GrSamplerState::kClamp_WrapMode, GrSamplerState::kNearest_Filter); @@ -1889,7 +1885,7 @@ void GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target, config, buffer, rowBytes, flags); GrDrawTarget::AutoStateRestore asr(fGpu); - reset_target_state(fGpu); + reset_target_state(fGpu->drawState()); GrMatrix matrix; matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top)); @@ -1920,6 +1916,8 @@ void GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target, void GrContext::setPaint(const GrPaint& paint, GrDrawTarget* target) { + GrDrawState* drawState = target->drawState(); + for (int i = 0; i < GrPaint::kMaxTextures; ++i) { int s = i + GrPaint::kFirstTextureStage; target->setTexture(s, paint.getTexture(i)); @@ -1936,20 +1934,20 @@ void GrContext::setPaint(const GrPaint& paint, GrDrawTarget* target) { target->setSamplerState(s, paint.getMaskSampler(i)); } - target->setColor(paint.fColor); + drawState->setColor(paint.fColor); if (paint.fDither) { - target->enableState(GrDrawTarget::kDither_StateBit); + drawState->enableState(GrDrawState::kDither_StateBit); } else { - target->disableState(GrDrawTarget::kDither_StateBit); + drawState->disableState(GrDrawState::kDither_StateBit); } if (paint.fAntiAlias) { - target->enableState(GrDrawTarget::kHWAntialias_StateBit); + drawState->enableState(GrDrawState::kHWAntialias_StateBit); } else { - target->disableState(GrDrawTarget::kHWAntialias_StateBit); + drawState->disableState(GrDrawState::kHWAntialias_StateBit); } - target->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff); - target->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode); + drawState->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff); + drawState->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode); if (paint.getActiveMaskStageMask() && !target->canApplyCoverage()) { GrPrintf("Partial pixel coverage will be incorrectly blended.\n"); @@ -2020,7 +2018,7 @@ void GrContext::setMatrix(const GrMatrix& m) { } void GrContext::concatMatrix(const GrMatrix& m) const { - fGpu->preConcatViewMatrix(m); + fGpu->viewMatrix()->preConcat(m); } static inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) { diff --git a/src/gpu/GrDefaultPathRenderer.cpp b/src/gpu/GrDefaultPathRenderer.cpp index 197ee06..cd4e429 100644 --- a/src/gpu/GrDefaultPathRenderer.cpp +++ b/src/gpu/GrDefaultPathRenderer.cpp @@ -190,7 +190,8 @@ static inline bool single_pass_path(const GrDrawTarget& target, return hint == kConvex_ConvexHint || hint == kNonOverlappingConvexPieces_ConvexHint || (hint == kSameWindingConvexPieces_ConvexHint && - !target.drawWillReadDst() && !target.isDitherState()); + !target.drawWillReadDst() && + !target.getDrawState().isDitherState()); } return false; @@ -388,6 +389,8 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask, GrScalar tol = GR_Scalar1; tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, fPath->getBounds()); + GrDrawState* drawState = fTarget->drawState(); + // FIXME: It's really dumb that we recreate the verts for a new vertex // layout. We only do that because the GrDrawTarget API doesn't allow // us to change the vertex layout after reserveVertexSpace(). We won't @@ -405,9 +408,9 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask, GrAssert(NULL != fTarget); GrDrawTarget::AutoStateRestore asr(fTarget); - bool colorWritesWereDisabled = fTarget->isColorWriteDisabled(); + bool colorWritesWereDisabled = drawState->isColorWriteDisabled(); // face culling doesn't make sense here - GrAssert(GrDrawState::kBoth_DrawFace == fTarget->getDrawFace()); + GrAssert(GrDrawState::kBoth_DrawFace == drawState->getDrawFace()); int passCount = 0; const GrStencilSettings* passes[3]; @@ -503,36 +506,37 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask, { for (int p = 0; p < passCount; ++p) { - fTarget->setDrawFace(drawFace[p]); + drawState->setDrawFace(drawFace[p]); if (NULL != passes[p]) { - fTarget->setStencil(*passes[p]); + drawState->setStencil(*passes[p]); } if (lastPassIsBounds && (p == passCount-1)) { if (!colorWritesWereDisabled) { - fTarget->disableState(GrDrawTarget::kNoColorWrites_StateBit); + drawState->disableState( + GrDrawState::kNoColorWrites_StateBit); } GrRect bounds; if (reverse) { - GrAssert(NULL != fTarget->getRenderTarget()); + GrAssert(NULL != drawState->getRenderTarget()); // draw over the whole world. bounds.setLTRB(0, 0, - GrIntToScalar(fTarget->getRenderTarget()->width()), - GrIntToScalar(fTarget->getRenderTarget()->height())); + GrIntToScalar(drawState->getRenderTarget()->width()), + GrIntToScalar(drawState->getRenderTarget()->height())); GrMatrix vmi; // mapRect through persp matrix may not be correct - if (!fTarget->getViewMatrix().hasPerspective() && - fTarget->getViewInverse(&vmi)) { + if (!drawState->getViewMatrix().hasPerspective() && + drawState->getViewInverse(&vmi)) { vmi.mapRect(&bounds); } else { if (stageMask) { - if (!fTarget->getViewInverse(&vmi)) { + if (!drawState->getViewInverse(&vmi)) { GrPrintf("Could not invert matrix."); return; } - fTarget->preConcatSamplerMatrices(stageMask, vmi); + drawState->preConcatSamplerMatrices(stageMask, vmi); } - fTarget->setViewMatrix(GrMatrix::I()); + drawState->setViewMatrix(GrMatrix::I()); } } else { bounds = fPath->getBounds(); @@ -542,7 +546,7 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask, fTarget->drawSimpleRect(bounds, NULL, stageMask); } else { if (passCount > 1) { - fTarget->enableState(GrDrawTarget::kNoColorWrites_StateBit); + drawState->enableState(GrDrawState::kNoColorWrites_StateBit); } if (fUseIndexedDraw) { fTarget->drawIndexed(fPrimitiveType, 0, 0, diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h index 90de1a3..8be4f3f 100644 --- a/src/gpu/GrDrawState.h +++ b/src/gpu/GrDrawState.h @@ -10,6 +10,7 @@ #include "GrColor.h" #include "GrMatrix.h" +#include "GrNoncopyable.h" #include "GrSamplerState.h" #include "GrStencil.h" @@ -45,13 +46,386 @@ struct GrDrawState { typedef uint32_t StageMask; GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages); - enum DrawFace { - kBoth_DrawFace, - kCCW_DrawFace, - kCW_DrawFace, + GrDrawState() { + // make sure any pad is zero for memcmp + // all GrDrawState members should default to something + // valid by the memset + memset(this, 0, sizeof(GrDrawState)); + + // memset exceptions + fColorFilterMode = SkXfermode::kDstIn_Mode; + fFirstCoverageStage = kNumStages; + + // pedantic assertion that our ptrs will + // be NULL (0 ptr is mem addr 0) + GrAssert((intptr_t)(void*)NULL == 0LL); + + GrAssert(fStencilSettings.isDisabled()); + fFirstCoverageStage = kNumStages; + } + + /////////////////////////////////////////////////////////////////////////// + /// @name Color + //// + + /** + * Sets color for next draw to a premultiplied-alpha color. + * + * @param color the color to set. + */ + void setColor(GrColor color) { fColor = color; } + + GrColor getColor() const { return fColor; } + + /** + * Sets the color to be used for the next draw to be + * (r,g,b,a) = (alpha, alpha, alpha, alpha). + * + * @param alpha The alpha value to set as the color. + */ + void setAlpha(uint8_t a) { + this->setColor((a << 24) | (a << 16) | (a << 8) | a); + } + + /** + * Add a color filter that can be represented by a color and a mode. Applied + * after color-computing texture stages. + */ + void setColorFilter(GrColor c, SkXfermode::Mode mode) { + fColorFilterColor = c; + fColorFilterMode = mode; + } + + GrColor getColorFilterColor() const { return fColorFilterColor; } + SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; } + + /// @} + + /////////////////////////////////////////////////////////////////////////// + /// @name Textures + //// + + /** + * Sets the texture used at the next drawing call + * + * @param stage The texture stage for which the texture will be set + * + * @param texture The texture to set. Can be NULL though there is no + * advantage to settings a NULL texture if doing non-textured drawing + */ + void setTexture(int stage, GrTexture* texture) { + GrAssert((unsigned)stage < kNumStages); + fTextures[stage] = texture; + } + + /** + * Retrieves the currently set texture. + * + * @return The currently set texture. The return value will be NULL if no + * texture has been set, NULL was most recently passed to + * setTexture, or the last setTexture was destroyed. + */ + const GrTexture* getTexture(int stage) const { + GrAssert((unsigned)stage < kNumStages); + return fTextures[stage]; + } + GrTexture* getTexture(int stage) { + GrAssert((unsigned)stage < kNumStages); + return fTextures[stage]; + } + + /// @} + + /////////////////////////////////////////////////////////////////////////// + /// @name Samplers + //// + + /** + * Returns the current sampler for a stage. + */ + const GrSamplerState& getSampler(int stage) const { + GrAssert((unsigned)stage < kNumStages); + return fSamplers[stage]; + } + + /** + * Writable pointer to a stage's sampler. + */ + GrSamplerState* sampler(int stage) { + GrAssert((unsigned)stage < kNumStages); + return fSamplers + stage; + } + + /** + * Preconcats the matrix of all samplers in the mask with the same matrix. + */ + void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) { + GrAssert(!(stageMask & kIllegalStageMaskBits)); + for (int i = 0; i < kNumStages; ++i) { + if ((1 << i) & stageMask) { + fSamplers[i].preConcatMatrix(matrix); + } + } + } + + /// @} + + /////////////////////////////////////////////////////////////////////////// + /// @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); + fFirstCoverageStage = firstCoverageStage; + } + + /** + * Gets the index of the first coverage-computing stage. + */ + int getFirstCoverageStage() const { + return fFirstCoverageStage; + } + + ///@} + + /////////////////////////////////////////////////////////////////////////// + /// @name Blending + //// + + /** + * Sets the blending function coeffecients. + * + * The blend function will be: + * D' = sat(S*srcCoef + D*dstCoef) + * + * where D is the existing destination color, S is the incoming source + * color, and D' is the new destination color that will be written. sat() + * is the saturation function. + * + * @param srcCoef coeffecient applied to the src color. + * @param dstCoef coeffecient applied to the dst color. + */ + void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { + fSrcBlend = srcCoeff; + fDstBlend = dstCoeff; + #if GR_DEBUG + switch (dstCoeff) { + case kDC_BlendCoeff: + case kIDC_BlendCoeff: + case kDA_BlendCoeff: + case kIDA_BlendCoeff: + GrPrintf("Unexpected dst blend coeff. Won't work correctly with" + "coverage stages.\n"); + break; + default: + break; + } + switch (srcCoeff) { + case kSC_BlendCoeff: + case kISC_BlendCoeff: + case kSA_BlendCoeff: + case kISA_BlendCoeff: + GrPrintf("Unexpected src blend coeff. Won't work correctly with" + "coverage stages.\n"); + break; + default: + break; + } + #endif + } + + GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; } + GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; } + + void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff, + GrBlendCoeff* dstBlendCoeff) const { + *srcBlendCoeff = fSrcBlend; + *dstBlendCoeff = fDstBlend; + } + + /** + * Sets the blending function constant referenced by the following blending + * coeffecients: + * kConstC_BlendCoeff + * kIConstC_BlendCoeff + * kConstA_BlendCoeff + * kIConstA_BlendCoeff + * + * @param constant the constant to set + */ + void setBlendConstant(GrColor constant) { fBlendConstant = constant; } + + /** + * Retrieves the last value set by setBlendConstant() + * @return the blending constant value + */ + GrColor getBlendConstant() const { return fBlendConstant; } + + /// @} + + /////////////////////////////////////////////////////////////////////////// + /// @name View Matrix + //// + + /** + * Sets the matrix applied to veretx positions. + * + * In the post-view-matrix space the rectangle [0,w]x[0,h] + * fully covers the render target. (w and h are the width and height of the + * the rendertarget.) + */ + void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; } + + /** + * Gets a writable pointer to the view matrix. + */ + GrMatrix* viewMatrix() { return &fViewMatrix; } + + /** + * Multiplies the current view matrix by a matrix + * + * After this call V' = V*m where V is the old view matrix, + * m is the parameter to this function, and V' is the new view matrix. + * (We consider positions to be column vectors so position vector p is + * transformed by matrix X as p' = X*p.) + * + * @param m the matrix used to modify the view matrix. + */ + void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); } + + /** + * Multiplies the current view matrix by a matrix + * + * After this call V' = m*V where V is the old view matrix, + * m is the parameter to this function, and V' is the new view matrix. + * (We consider positions to be column vectors so position vector p is + * transformed by matrix X as p' = X*p.) + * + * @param m the matrix used to modify the view matrix. + */ + void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); } + + /** + * Retrieves the current view matrix + * @return the current view matrix. + */ + const GrMatrix& getViewMatrix() const { return fViewMatrix; } + + /** + * Retrieves the inverse of the current view matrix. + * + * If the current view matrix is invertible, return true, and if matrix + * is non-null, copy the inverse into it. If the current view matrix is + * non-invertible, return false and ignore the matrix parameter. + * + * @param matrix if not null, will receive a copy of the current inverse. + */ + bool getViewInverse(GrMatrix* matrix) const { + // TODO: determine whether we really need to leave matrix unmodified + // at call sites when inversion fails. + GrMatrix inverse; + if (fViewMatrix.invert(&inverse)) { + if (matrix) { + *matrix = inverse; + } + return true; + } + return false; + } + + /// @} + + /////////////////////////////////////////////////////////////////////////// + /// @name Render Target + //// + + /** + * Sets the rendertarget used at the next drawing call + * + * @param target The render target to set. + */ + void setRenderTarget(GrRenderTarget* target) { fRenderTarget = target; } + + /** + * Retrieves the currently set rendertarget. + * + * @return The currently set render target. + */ + const GrRenderTarget* getRenderTarget() const { return fRenderTarget; } + GrRenderTarget* getRenderTarget() { return fRenderTarget; } + + class AutoRenderTargetRestore : public ::GrNoncopyable { + public: + AutoRenderTargetRestore() : fDrawState(NULL) {} + AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) { + this->set(ds, newTarget); + } + ~AutoRenderTargetRestore() { this->set(NULL, NULL); } + void set(GrDrawState* ds, GrRenderTarget* newTarget) { + if (NULL != fDrawState) { + fDrawState->setRenderTarget(fSavedTarget); + } + if (NULL != ds) { + fSavedTarget = ds->getRenderTarget(); + ds->setRenderTarget(newTarget); + } + fDrawState = ds; + } + private: + GrDrawState* fDrawState; + GrRenderTarget* fSavedTarget; }; - /** + /// @} + + /////////////////////////////////////////////////////////////////////////// + /// @name Stencil + //// + + /** + * Sets the stencil settings to use for the next draw. + * Changing the clip has the side-effect of possibly zeroing + * out the client settable stencil bits. So multipass algorithms + * using stencil should not change the clip between passes. + * @param settings the stencil settings to use. + */ + void setStencil(const GrStencilSettings& settings) { + fStencilSettings = settings; + } + + /** + * Shortcut to disable stencil testing and ops. + */ + void disableStencil() { + fStencilSettings.setDisabled(); + } + + const GrStencilSettings& getStencil() const { return fStencilSettings; } + + GrStencilSettings* stencil() { return &fStencilSettings; } + + /// @} + + /////////////////////////////////////////////////////////////////////////// + // @name Edge AA + // There are two ways to perform antialiasing using edge equations. One + // is to specify an (linear or quadratic) edge eq per-vertex. This requires + // splitting vertices shared by primitives. + // + // The other is via setEdgeAAData which sets a set of edges and each + // is tested against all the edges. + //// + + /** * When specifying edges as vertex data this enum specifies what type of * edges are in use. The edges are always 4 GrScalars in memory, even when * the edge type requires fewer than 4. @@ -66,6 +440,19 @@ struct GrDrawState { }; /** + * Determines the interpretation per-vertex edge data when the + * kEdge_VertexLayoutBit is set (see GrDrawTarget). When per-vertex edges + * are not specified the value of this setting has no effect. + */ + void setVertexEdgeType(VertexEdgeType type) { + fVertexEdgeType = type; + } + + VertexEdgeType getVertexEdgeType() const { + return fVertexEdgeType; + } + + /** * The absolute maximum number of edges that may be specified for * a single draw call when performing edge antialiasing. This is used for * the size of several static buffers, so implementations of getMaxEdges() @@ -91,53 +478,146 @@ struct GrDrawState { float fX, fY, fZ; }; - GrDrawState() { - // make sure any pad is zero for memcmp - // all GrDrawState members should default to something - // valid by the memset - memset(this, 0, sizeof(GrDrawState)); - - // memset exceptions - fColorFilterXfermode = SkXfermode::kDstIn_Mode; - fFirstCoverageStage = kNumStages; + /** + * Sets the edge data required for edge antialiasing. + * + * @param edges 3 * numEdges float values, representing the edge + * equations in Ax + By + C form + */ + void setEdgeAAData(const Edge* edges, int numEdges) { + GrAssert(numEdges <= GrDrawState::kMaxEdges); + memcpy(fEdgeAAEdges, edges, numEdges * sizeof(GrDrawState::Edge)); + fEdgeAANumEdges = numEdges; + } - // pedantic assertion that our ptrs will - // be NULL (0 ptr is mem addr 0) - GrAssert((intptr_t)(void*)NULL == 0LL); + int getNumAAEdges() const { return fEdgeAANumEdges; } - // default stencil setting should be disabled - GrAssert(fStencilSettings.isDisabled()); - fFirstCoverageStage = kNumStages; + const Edge* getAAEdges() const { return fEdgeAAEdges; } + + /// @} + + /////////////////////////////////////////////////////////////////////////// + /// @name State Flags + //// + + /** + * Flags that affect rendering. Controlled using enable/disableState(). All + * default to disabled. + */ + enum StateBits { + /** + * Perform dithering. TODO: Re-evaluate whether we need this bit + */ + kDither_StateBit = 0x01, + /** + * Perform HW anti-aliasing. This means either HW FSAA, if supported + * by the render target, or smooth-line rendering if a line primitive + * is drawn and line smoothing is supported by the 3D API. + */ + kHWAntialias_StateBit = 0x02, + /** + * Draws will respect the clip, otherwise the clip is ignored. + */ + kClip_StateBit = 0x04, + /** + * Disables writing to the color buffer. Useful when performing stencil + * operations. + */ + kNoColorWrites_StateBit = 0x08, + /** + * Modifies the behavior of edge AA specified by setEdgeAA. If set, + * will test edge pairs for convexity when rasterizing. Set this if the + * source polygon is non-convex. + */ + kEdgeAAConcave_StateBit = 0x10, + + // Users of the class may add additional bits to the vector + kDummyStateBit, + kLastPublicStateBit = kDummyStateBit-1, + }; + + void resetStateFlags() { + fFlagBits = 0; } - uint8_t fFlagBits; - GrBlendCoeff fSrcBlend : 8; - GrBlendCoeff fDstBlend : 8; - DrawFace fDrawFace : 8; - uint8_t fFirstCoverageStage; - SkXfermode::Mode fColorFilterXfermode : 8; - GrColor fBlendConstant; - GrTexture* fTextures[kNumStages]; - GrRenderTarget* fRenderTarget; - GrColor fColor; - GrColor fColorFilterColor; + /** + * Enable render state settings. + * + * @param flags bitfield of StateBits specifing the states to enable + */ + void enableState(uint32_t stateBits) { + fFlagBits |= stateBits; + } - GrStencilSettings fStencilSettings; - GrMatrix fViewMatrix; + /** + * Disable render state settings. + * + * @param flags bitfield of StateBits specifing the states to disable + */ + void disableState(uint32_t stateBits) { + fFlagBits &= ~(stateBits); + } - // @{ Data for GrTesselatedPathRenderer - // TODO: currently ignored in copying & comparison for performance. - // Must be considered if GrTesselatedPathRenderer is being used. + bool isDitherState() const { + return 0 != (fFlagBits & kDither_StateBit); + } - int fEdgeAANumEdges; - VertexEdgeType fVertexEdgeType; - Edge fEdgeAAEdges[kMaxEdges]; + bool isHWAntialiasState() const { + return 0 != (fFlagBits & kHWAntialias_StateBit); + } - // @} + bool isClipState() const { + return 0 != (fFlagBits & kClip_StateBit); + } - // This field must be last; it will not be copied or compared - // if the corresponding fTexture[] is NULL. - GrSamplerState fSamplerStates[kNumStages]; + bool isColorWriteDisabled() const { + return 0 != (fFlagBits & kNoColorWrites_StateBit); + } + + bool isConcaveEdgeAAState() const { + return 0 != (fFlagBits & kEdgeAAConcave_StateBit); + } + + bool isStateFlagEnabled(uint32_t stateBit) const { + return 0 != (stateBit & fFlagBits); + } + + void copyStateFlags(const GrDrawState& ds) { + fFlagBits = ds.fFlagBits; + } + + /// @} + + /////////////////////////////////////////////////////////////////////////// + /// @name Face Culling + //// + + enum DrawFace { + kBoth_DrawFace, + kCCW_DrawFace, + kCW_DrawFace, + }; + + /** + * Controls whether clockwise, counterclockwise, or both faces are drawn. + * @param face the face(s) to draw. + */ + void setDrawFace(DrawFace face) { + fDrawFace = face; + } + + /** + * Gets whether the target is drawing clockwise, counterclockwise, + * or both faces. + * @return the current draw face(s). + */ + DrawFace getDrawFace() const { + return fDrawFace; + } + + /// @} + + /////////////////////////////////////////////////////////////////////////// // Most stages are usually not used, so conditionals here // reduce the expected number of bytes touched by 50%. @@ -146,7 +626,7 @@ struct GrDrawState { for (int i = 0; i < kNumStages; i++) { if (fTextures[i] && - memcmp(&this->fSamplerStates[i], &s.fSamplerStates[i], + memcmp(&this->fSamplers[i], &s.fSamplers[i], sizeof(GrSamplerState))) { return false; } @@ -163,7 +643,7 @@ struct GrDrawState { for (int i = 0; i < kNumStages; i++) { if (s.fTextures[i]) { - memcpy(&this->fSamplerStates[i], &s.fSamplerStates[i], + memcpy(&this->fSamplers[i], &s.fSamplers[i], sizeof(GrSamplerState)); } } @@ -172,6 +652,36 @@ struct GrDrawState { } private: + static const StageMask kIllegalStageMaskBits = ~((1 << kNumStages)-1); + uint8_t fFlagBits; + GrBlendCoeff fSrcBlend : 8; + GrBlendCoeff fDstBlend : 8; + DrawFace fDrawFace : 8; + uint8_t fFirstCoverageStage; + SkXfermode::Mode fColorFilterMode : 8; + GrColor fBlendConstant; + GrTexture* fTextures[kNumStages]; + GrRenderTarget* fRenderTarget; + GrColor fColor; + GrColor fColorFilterColor; + + GrStencilSettings fStencilSettings; + GrMatrix fViewMatrix; + + // @{ Data for GrTesselatedPathRenderer + // TODO: currently ignored in copying & comparison for performance. + // Must be considered if GrTesselatedPathRenderer is being used. + + int fEdgeAANumEdges; + VertexEdgeType fVertexEdgeType; + Edge fEdgeAAEdges[kMaxEdges]; + + // @} + + // This field must be last; it will not be copied or compared + // if the corresponding fTexture[] is NULL. + GrSamplerState fSamplers[kNumStages]; + size_t leadingBytes() const { // Can't use offsetof() with non-POD types, so stuck with pointer math. // TODO: ignores GrTesselatedPathRenderer data structures. We don't @@ -184,4 +694,3 @@ private: }; #endif - diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index 7a84262..2d1563d 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -455,119 +455,6 @@ const GrClip& GrDrawTarget::getClip() const { return fClip; } -void GrDrawTarget::setTexture(int stage, GrTexture* tex) { - GrAssert(stage >= 0 && stage < GrDrawState::kNumStages); - fCurrDrawState.fTextures[stage] = tex; -} - -const GrTexture* GrDrawTarget::getTexture(int stage) const { - GrAssert(stage >= 0 && stage < GrDrawState::kNumStages); - return fCurrDrawState.fTextures[stage]; -} - -GrTexture* GrDrawTarget::getTexture(int stage) { - GrAssert(stage >= 0 && stage < GrDrawState::kNumStages); - return fCurrDrawState.fTextures[stage]; -} - -void GrDrawTarget::setRenderTarget(GrRenderTarget* target) { - fCurrDrawState.fRenderTarget = target; -} - -const GrRenderTarget* GrDrawTarget::getRenderTarget() const { - return fCurrDrawState.fRenderTarget; -} - -GrRenderTarget* GrDrawTarget::getRenderTarget() { - return fCurrDrawState.fRenderTarget; -} - -void GrDrawTarget::setViewMatrix(const GrMatrix& m) { - fCurrDrawState.fViewMatrix = m; -} - -void GrDrawTarget::preConcatViewMatrix(const GrMatrix& matrix) { - fCurrDrawState.fViewMatrix.preConcat(matrix); -} - -void GrDrawTarget::postConcatViewMatrix(const GrMatrix& matrix) { - fCurrDrawState.fViewMatrix.postConcat(matrix); -} - -const GrMatrix& GrDrawTarget::getViewMatrix() const { - return fCurrDrawState.fViewMatrix; -} - -bool GrDrawTarget::getViewInverse(GrMatrix* matrix) const { - // Mike: Can we cache this somewhere? - // Brian: Sure, do we use it often? - - GrMatrix inverse; - if (fCurrDrawState.fViewMatrix.invert(&inverse)) { - if (matrix) { - *matrix = inverse; - } - return true; - } - return false; -} - -void GrDrawTarget::setSamplerState(int stage, const GrSamplerState& state) { - GrAssert(stage >= 0 && stage < GrDrawState::kNumStages); - fCurrDrawState.fSamplerStates[stage] = state; -} - -void GrDrawTarget::enableState(uint32_t bits) { - fCurrDrawState.fFlagBits |= bits; -} - -void GrDrawTarget::disableState(uint32_t bits) { - fCurrDrawState.fFlagBits &= ~(bits); -} - -void GrDrawTarget::setBlendFunc(GrBlendCoeff srcCoeff, - GrBlendCoeff dstCoeff) { - fCurrDrawState.fSrcBlend = srcCoeff; - fCurrDrawState.fDstBlend = dstCoeff; -#if GR_DEBUG - switch (dstCoeff) { - case kDC_BlendCoeff: - case kIDC_BlendCoeff: - case kDA_BlendCoeff: - case kIDA_BlendCoeff: - GrPrintf("Unexpected dst blend coeff. Won't work correctly with" - "coverage stages.\n"); - break; - default: - break; - } - switch (srcCoeff) { - case kSC_BlendCoeff: - case kISC_BlendCoeff: - case kSA_BlendCoeff: - case kISA_BlendCoeff: - GrPrintf("Unexpected src blend coeff. Won't work correctly with" - "coverage stages.\n"); - break; - default: - break; - } -#endif -} - -void GrDrawTarget::setColor(GrColor c) { - fCurrDrawState.fColor = c; -} - -void GrDrawTarget::setColorFilter(GrColor c, SkXfermode::Mode mode) { - fCurrDrawState.fColorFilterColor = c; - fCurrDrawState.fColorFilterXfermode = mode; -} - -void GrDrawTarget::setAlpha(uint8_t a) { - this->setColor((a << 24) | (a << 16) | (a << 8) | a); -} - void GrDrawTarget::saveCurrentDrawState(SavedDrawState* state) const { state->fState = fCurrDrawState; } @@ -804,8 +691,8 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex, return false; } if (GrPixelConfigIsUnpremultiplied(this->getRenderTarget()->config())) { - if (kOne_BlendCoeff != fCurrDrawState.fSrcBlend || - kZero_BlendCoeff != fCurrDrawState.fDstBlend) { + if (kOne_BlendCoeff != getDrawState().getSrcBlendCoeff() || + kZero_BlendCoeff != getDrawState().getDstBlendCoeff()) { return false; } } @@ -817,8 +704,8 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex, // a custom bilerp in the shader. Until Skia itself supports unpremul // configs there is no pressure to implement this. if (this->isStageEnabled(s) && - GrPixelConfigIsUnpremultiplied(fCurrDrawState.fTextures[s]->config()) && - GrSamplerState::kNearest_Filter != fCurrDrawState.fSamplerStates[s].getFilter()) { + GrPixelConfigIsUnpremultiplied(this->getTexture(s)->config()) && + GrSamplerState::kNearest_Filter != this->getSampler(s).getFilter()) { return false; } } @@ -861,9 +748,10 @@ bool GrDrawTarget::canTweakAlphaForCoverage() const { * for Cd we find that only 1, ISA, and ISC produce the correct depth * coeffecient in terms of S' and D. */ - return kOne_BlendCoeff == fCurrDrawState.fDstBlend|| - kISA_BlendCoeff == fCurrDrawState.fDstBlend || - kISC_BlendCoeff == fCurrDrawState.fDstBlend; + GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff(); + return kOne_BlendCoeff == dstCoeff || + kISA_BlendCoeff == dstCoeff || + kISC_BlendCoeff == dstCoeff; } @@ -872,20 +760,21 @@ bool GrDrawTarget::srcAlphaWillBeOne() const { // Check if per-vertex or constant color may have partial alpha if ((layout & kColor_VertexLayoutBit) || - 0xff != GrColorUnpackA(fCurrDrawState.fColor)) { + 0xff != GrColorUnpackA(this->getColor())) { return false; } // Check if color filter could introduce an alpha // (TODO: Consider being more aggressive with regards to detecting 0xff // final alpha from color filter). - if (SkXfermode::kDst_Mode != fCurrDrawState.fColorFilterXfermode) { + if (SkXfermode::kDst_Mode != this->getDrawState().getColorFilterMode()) { return false; } // Check if a color stage could create a partial alpha - for (int s = 0; s < fCurrDrawState.fFirstCoverageStage; ++s) { + int firstCoverageStage = this->getFirstCoverageStage(); + for (int s = 0; s < firstCoverageStage; ++s) { if (StageWillBeUsed(s, layout, fCurrDrawState)) { - GrAssert(NULL != fCurrDrawState.fTextures[s]); - GrPixelConfig config = fCurrDrawState.fTextures[s]->config(); + GrAssert(NULL != this->getTexture(s)); + GrPixelConfig config = this->getTexture(s)->config(); if (!GrPixelConfigIsOpaque(config)) { return false; } @@ -905,12 +794,12 @@ GrDrawTarget::getBlendOpts(bool forceCoverage, if (NULL == srcCoeff) { srcCoeff = &bogusSrcCoeff; } - *srcCoeff = fCurrDrawState.fSrcBlend; + *srcCoeff = this->getDrawState().getSrcBlendCoeff(); if (NULL == dstCoeff) { dstCoeff = &bogusDstCoeff; } - *dstCoeff = fCurrDrawState.fDstBlend; + *dstCoeff = this->getDrawState().getDstBlendCoeff(); // We don't ever expect source coeffecients to reference the source GrAssert(kSA_BlendCoeff != *srcCoeff && @@ -923,7 +812,7 @@ GrDrawTarget::getBlendOpts(bool forceCoverage, kDC_BlendCoeff != *dstCoeff && kIDC_BlendCoeff != *dstCoeff); - if (SkToBool(kNoColorWrites_StateBit & fCurrDrawState.fFlagBits)) { + if (this->getDrawState().isColorWriteDisabled()) { *srcCoeff = kZero_BlendCoeff; *dstCoeff = kOne_BlendCoeff; } @@ -939,7 +828,7 @@ GrDrawTarget::getBlendOpts(bool forceCoverage, // stenciling is enabled. Having color writes disabled is effectively // (0,1). if ((kZero_BlendCoeff == *srcCoeff && dstCoeffIsOne)) { - if (fCurrDrawState.fStencilSettings.doesWrite()) { + if (this->getDrawState().getStencil().doesWrite()) { if (fCaps.fShaderSupport) { return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag; @@ -953,10 +842,10 @@ GrDrawTarget::getBlendOpts(bool forceCoverage, // check for coverage due to edge aa or coverage texture stage bool hasCoverage = forceCoverage || - fCurrDrawState.fEdgeAANumEdges > 0 || + this->getDrawState().getNumAAEdges() > 0 || (layout & kCoverage_VertexLayoutBit) || (layout & kEdge_VertexLayoutBit); - for (int s = fCurrDrawState.fFirstCoverageStage; + for (int s = this->getFirstCoverageStage(); !hasCoverage && s < GrDrawState::kNumStages; ++s) { if (StageWillBeUsed(s, layout, fCurrDrawState)) { @@ -1023,7 +912,7 @@ bool GrDrawTarget::willUseHWAALines() const { // but not in a premul-alpha way. So we only use them when our alpha // is 0xff and tweaking the color for partial coverage is OK if (!fCaps.fHWAALineSupport || - !(kHWAntialias_StateBit & fCurrDrawState.fFlagBits)) { + !(this->getDrawState().isHWAntialiasState())) { return false; } BlendOptFlags opts = this->getBlendOpts(); @@ -1043,16 +932,6 @@ bool GrDrawTarget::drawWillReadDst() const { this->getBlendOpts()); } -/////////////////////////////////////////////////////////////////////////////// - -void GrDrawTarget::setEdgeAAData(const GrDrawState::Edge* edges, int numEdges) { - GrAssert(numEdges <= GrDrawState::kMaxEdges); - memcpy(fCurrDrawState.fEdgeAAEdges, edges, - numEdges * sizeof(GrDrawState::Edge)); - fCurrDrawState.fEdgeAANumEdges = numEdges; -} - - //////////////////////////////////////////////////////////////////////////////// void GrDrawTarget::drawRect(const GrRect& rect, @@ -1068,13 +947,13 @@ void GrDrawTarget::drawRect(const GrRect& rect, return; } - SetRectVertices(rect, matrix, srcRects, + SetRectVertices(rect, matrix, srcRects, srcMatrices, layout, geo.vertices()); drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4); } -GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageMask stageMask, +GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageMask stageMask, const GrRect* srcRects[]) { GrVertexLayout layout = 0; @@ -1183,7 +1062,7 @@ GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw( if (fViewMatrix.invert(&invVM)) { for (int s = 0; s < GrDrawState::kNumStages; ++s) { if (fStageMask & (1 << s)) { - fSamplerMatrices[s] = target->getSamplerMatrix(s); + fSamplerMatrices[s] = target->getSampler(s).getMatrix(); } } target->preConcatSamplerMatrices(fStageMask, invVM); @@ -1199,7 +1078,8 @@ GrDrawTarget::AutoDeviceCoordDraw::~AutoDeviceCoordDraw() { fDrawTarget->setViewMatrix(fViewMatrix); for (int s = 0; s < GrDrawState::kNumStages; ++s) { if (fStageMask & (1 << s)) { - fDrawTarget->setSamplerMatrix(s, fSamplerMatrices[s]); + GrSamplerState* sampler = fDrawTarget->drawState()->sampler(s); + sampler->setMatrix(fSamplerMatrices[s]); } } } diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h index 4bd9eee..b72fb3a 100644 --- a/src/gpu/GrDrawTarget.h +++ b/src/gpu/GrDrawTarget.h @@ -57,62 +57,9 @@ public: int fMaxTextureSize; }; + // for convenience typedef GrDrawState::StageMask StageMask; - /** - * Flags that affect rendering. Controlled using enable/disableState(). All - * default to disabled. - */ - enum StateBits { - /** - * Perform dithering. TODO: Re-evaluate whether we need this bit - */ - kDither_StateBit = 0x01, - /** - * Perform HW anti-aliasing. This means either HW FSAA, if supported - * by the render target, or smooth-line rendering if a line primitive - * is drawn and line smoothing is supported by the 3D API. - */ - kHWAntialias_StateBit = 0x02, - /** - * Draws will respect the clip, otherwise the clip is ignored. - */ - kClip_StateBit = 0x04, - /** - * Disables writing to the color buffer. Useful when performing stencil - * operations. - */ - kNoColorWrites_StateBit = 0x08, - /** - * Modifies the behavior of edge AA specified by setEdgeAA. If set, - * will test edge pairs for convexity when rasterizing. Set this if the - * source polygon is non-convex. - */ - kEdgeAAConcave_StateBit = 0x10, - // subclass may use additional bits internally - kDummyStateBit, - kLastPublicStateBit = kDummyStateBit-1 - }; - - /** - * Sets the stencil settings to use for the next draw. - * Changing the clip has the side-effect of possibly zeroing - * out the client settable stencil bits. So multipass algorithms - * using stencil should not change the clip between passes. - * @param settings the stencil settings to use. - */ - void setStencil(const GrStencilSettings& settings) { - fCurrDrawState.fStencilSettings = settings; - } - - /** - * Shortcut to disable stencil testing and ops. - */ - void disableStencil() { - fCurrDrawState.fStencilSettings.setDisabled(); - } - -public: /////////////////////////////////////////////////////////////////////////// GrDrawTarget(); @@ -141,285 +88,6 @@ public: const GrClip& getClip() const; /** - * Sets the texture used at the next drawing call - * - * @param stage The texture stage for which the texture will be set - * - * @param texture The texture to set. Can be NULL though there is no advantage - * to settings a NULL texture if doing non-textured drawing - */ - void setTexture(int stage, GrTexture* texture); - - /** - * Retrieves the currently set texture. - * - * @return The currently set texture. The return value will be NULL if no - * texture has been set, NULL was most recently passed to - * setTexture, or the last setTexture was destroyed. - */ - const GrTexture* getTexture(int stage) const; - GrTexture* getTexture(int stage); - - /** - * Sets the rendertarget used at the next drawing call - * - * @param target The render target to set. - */ - void setRenderTarget(GrRenderTarget* target); - - /** - * Retrieves the currently set rendertarget. - * - * @return The currently set render target. - */ - const GrRenderTarget* getRenderTarget() const; - GrRenderTarget* getRenderTarget(); - - /** - * Sets the sampler state for a stage used in subsequent draws. - * - * The sampler state determines how texture coordinates are - * intepretted and used to sample the texture. - * - * @param stage the stage of the sampler to set - * @param samplerState Specifies the sampler state. - */ - void setSamplerState(int stage, const GrSamplerState& samplerState); - - /** - * Concats the matrix of a stage's sampler. - * - * @param stage the stage of the sampler to set - * @param matrix the matrix to concat - */ - void preConcatSamplerMatrix(int stage, const GrMatrix& matrix) { - GrAssert(stage >= 0 && stage < GrDrawState::kNumStages); - fCurrDrawState.fSamplerStates[stage].preConcatMatrix(matrix); - } - - /** - * Shortcut for preConcatSamplerMatrix on all stages in mask with same - * matrix - */ - void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) { - for (int i = 0; i < GrDrawState::kNumStages; ++i) { - if ((1 << i) & stageMask) { - this->preConcatSamplerMatrix(i, matrix); - } - } - } - - /** - * Shortcut for preConcatSamplerMatrix on all enabled stages in mask with - * same matrix - * - * @param stage the stage of the sampler to set - * @param matrix the matrix to concat - */ - void preConcatEnabledSamplerMatrices(const GrMatrix& matrix) { - StageMask stageMask = this->enabledStages(); - this->preConcatSamplerMatrices(stageMask, matrix); - } - - /** - * Gets the matrix of a stage's sampler - * - * @param stage the stage to of sampler to get - * @return the sampler state's matrix - */ - const GrMatrix& getSamplerMatrix(int stage) const { - return fCurrDrawState.fSamplerStates[stage].getMatrix(); - } - - /** - * Sets the matrix of a stage's sampler - * - * @param stage the stage of sampler set - * @param matrix the matrix to set - */ - void setSamplerMatrix(int stage, const GrMatrix& matrix) { - fCurrDrawState.fSamplerStates[stage].setMatrix(matrix); - } - - /** - * Sets the matrix applied to veretx positions. - * - * In the post-view-matrix space the rectangle [0,w]x[0,h] - * fully covers the render target. (w and h are the width and height of the - * the rendertarget.) - * - * @param m the matrix used to transform the vertex positions. - */ - void setViewMatrix(const GrMatrix& m); - - /** - * Multiplies the current view matrix by a matrix - * - * After this call V' = V*m where V is the old view matrix, - * m is the parameter to this function, and V' is the new view matrix. - * (We consider positions to be column vectors so position vector p is - * transformed by matrix X as p' = X*p.) - * - * @param m the matrix used to modify the view matrix. - */ - void preConcatViewMatrix(const GrMatrix& m); - - /** - * Multiplies the current view matrix by a matrix - * - * After this call V' = m*V where V is the old view matrix, - * m is the parameter to this function, and V' is the new view matrix. - * (We consider positions to be column vectors so position vector p is - * transformed by matrix X as p' = X*p.) - * - * @param m the matrix used to modify the view matrix. - */ - void postConcatViewMatrix(const GrMatrix& m); - - /** - * Retrieves the current view matrix - * @return the current view matrix. - */ - const GrMatrix& getViewMatrix() const; - - /** - * Retrieves the inverse of the current view matrix. - * - * If the current view matrix is invertible, return true, and if matrix - * is non-null, copy the inverse into it. If the current view matrix is - * non-invertible, return false and ignore the matrix parameter. - * - * @param matrix if not null, will receive a copy of the current inverse. - */ - bool getViewInverse(GrMatrix* matrix) const; - - /** - * Sets color for next draw to a premultiplied-alpha color. - * - * @param the color to set. - */ - void setColor(GrColor); - - /** - * Gets the currently set color. - * @return the current color. - */ - GrColor getColor() const { return fCurrDrawState.fColor; } - - /** - * Add a color filter that can be represented by a color and a mode. - */ - void setColorFilter(GrColor, SkXfermode::Mode); - - /** - * Sets the color to be used for the next draw to be - * (r,g,b,a) = (alpha, alpha, alpha, alpha). - * - * @param alpha The alpha value to set as the color. - */ - void setAlpha(uint8_t alpha); - - /** - * Controls whether clockwise, counterclockwise, or both faces are drawn. - * @param face the face(s) to draw. - */ - void setDrawFace(GrDrawState::DrawFace face) { - fCurrDrawState.fDrawFace = face; - } - - /** - * 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 GrDrawState::kNumStages (all stages - * are color-computing). - */ - void setFirstCoverageStage(int firstCoverageStage) { - fCurrDrawState.fFirstCoverageStage = firstCoverageStage; - } - - /** - * Gets the index of the first coverage-computing stage. - */ - int getFirstCoverageStage() const { - return fCurrDrawState.fFirstCoverageStage; - } - - /** - * Gets whether the target is drawing clockwise, counterclockwise, - * or both faces. - * @return the current draw face(s). - */ - GrDrawState::DrawFace getDrawFace() const { - return fCurrDrawState.fDrawFace; - } - - /** - * Enable render state settings. - * - * @param flags bitfield of StateBits specifing the states to enable - */ - void enableState(uint32_t stateBits); - - /** - * Disable render state settings. - * - * @param flags bitfield of StateBits specifing the states to disable - */ - void disableState(uint32_t stateBits); - - bool isDitherState() const { - return 0 != (fCurrDrawState.fFlagBits & kDither_StateBit); - } - - bool isHWAntialiasState() const { - return 0 != (fCurrDrawState.fFlagBits & kHWAntialias_StateBit); - } - - bool isClipState() const { - return 0 != (fCurrDrawState.fFlagBits & kClip_StateBit); - } - - bool isColorWriteDisabled() const { - return 0 != (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit); - } - - /** - * Sets the blending function coeffecients. - * - * The blend function will be: - * D' = sat(S*srcCoef + D*dstCoef) - * - * where D is the existing destination color, S is the incoming source - * color, and D' is the new destination color that will be written. sat() - * is the saturation function. - * - * @param srcCoef coeffecient applied to the src color. - * @param dstCoef coeffecient applied to the dst color. - */ - void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff); - - /** - * Sets the blending function constant referenced by the following blending - * coeffecients: - * kConstC_BlendCoeff - * kIConstC_BlendCoeff - * kConstA_BlendCoeff - * kIConstA_BlendCoeff - * - * @param constant the constant to set - */ - void setBlendConstant(GrColor constant) { fCurrDrawState.fBlendConstant = constant; } - - /** - * Retrieves the last value set by setBlendConstant() - * @return the blending constant value - */ - GrColor getBlendConstant() const { return fCurrDrawState.fBlendConstant; } - - /** * Determines if blending will require a read of a dst given the current * state set on the draw target * @@ -448,15 +116,6 @@ public: */ bool canTweakAlphaForCoverage() const; - /** - * Determines the interpretation per-vertex edge data when the - * kEdge_VertexLayoutBit is set (see below). When per-vertex edges are not - * specified the value of this setting has no effect. - */ - void setVertexEdgeType(GrDrawState::VertexEdgeType type) { - fCurrDrawState.fVertexEdgeType = type; - } - /** * Given the current draw state, vertex layout, and hw support, will HW AA * lines be used (if line primitive type is drawn)? (Note that lines are @@ -464,13 +123,70 @@ public: */ bool willUseHWAALines() const; - /** - * Sets the edge data required for edge antialiasing. - * - * @param edges 3 * 6 float values, representing the edge - * equations in Ax + By + C form - */ - void setEdgeAAData(const GrDrawState::Edge* edges, int numEdges); + const GrDrawState& getDrawState() const { return fCurrDrawState; } + GrDrawState* drawState() { return &fCurrDrawState; } + + // Convenience Pass-thrus to GrDrawState. These are likely candidates for + // removal. + void setViewMatrix(const GrMatrix& m) { + this->drawState()->setViewMatrix(m); + } + GrMatrix* viewMatrix() { + return this->drawState()->viewMatrix(); + } + const GrMatrix& getViewMatrix() const { + return this->getDrawState().getViewMatrix(); + } + bool getViewInverse(GrMatrix* inv) const { + return this->getDrawState().getViewInverse(inv); + } + void setRenderTarget(GrRenderTarget* renderTarget) { + this->drawState()->setRenderTarget(renderTarget); + } + const GrRenderTarget* getRenderTarget() const { + return this->getDrawState().getRenderTarget(); + } + GrRenderTarget* getRenderTarget() { + return this->drawState()->getRenderTarget(); + } + void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { + this->drawState()->setBlendFunc(srcCoeff, dstCoeff); + } + void setTexture(int stage, GrTexture* texture) { + this->drawState()->setTexture(stage, texture); + } + const GrTexture* getTexture(int stage) const { + return this->getDrawState().getTexture(stage); + } + GrTexture* getTexture(int stage) { + return this->drawState()->getTexture(stage); + } + // THIS WILL BE REMOVED AND REPLACED WITH DIRECT ACCESS TO SAMPLER + // IN A COMING REVISION. + void setSamplerState(int stage, const GrSamplerState& sampler) { + *(this->drawState()->sampler(stage)) = sampler; + } + const GrSamplerState& getSampler(int stage) const { + return this->getDrawState().getSampler(stage); + } + void preConcatSamplerMatrices(StageMask stageMask, + const GrMatrix& m) { + this->drawState()->preConcatSamplerMatrices(stageMask, m); + } + GrColor getColor() const { return this->getDrawState().getColor(); } + void setColor(GrColor color) { this->drawState()->setColor(color); } + void setFirstCoverageStage(int firstCoverageStage) { + this->drawState()->setFirstCoverageStage(firstCoverageStage); + } + int getFirstCoverageStage() const { + return this->getDrawState().getFirstCoverageStage(); + } + void setDrawFace(const GrDrawState::DrawFace face) { + this->drawState()->setDrawFace(face); + } + GrDrawState::DrawFace getDrawFace() const { + return this->getDrawState().getDrawFace(); + } /** * Used to save and restore the GrGpu's drawing state @@ -895,7 +611,7 @@ public: } AutoViewMatrixRestore(GrDrawTarget* target) - : fDrawTarget(target), fMatrix(fDrawTarget->getViewMatrix()) { + : fDrawTarget(target), fMatrix(target->getViewMatrix()) { GrAssert(NULL != target); } @@ -927,13 +643,14 @@ public: */ class AutoDeviceCoordDraw : ::GrNoncopyable { public: - AutoDeviceCoordDraw(GrDrawTarget* target, StageMask stageMask); + AutoDeviceCoordDraw(GrDrawTarget* target, + GrDrawState::StageMask stageMask); ~AutoDeviceCoordDraw(); private: - GrDrawTarget* fDrawTarget; - GrMatrix fViewMatrix; - GrMatrix fSamplerMatrices[GrDrawState::kNumStages]; - int fStageMask; + GrDrawTarget* fDrawTarget; + GrMatrix fViewMatrix; + GrMatrix fSamplerMatrices[GrDrawState::kNumStages]; + GrDrawState::StageMask fStageMask; }; //////////////////////////////////////////////////////////////////////////// @@ -1279,7 +996,8 @@ protected: // given a vertex layout and a draw state, will a stage be used? static bool StageWillBeUsed(int stage, GrVertexLayout layout, const GrDrawState& state) { - return NULL != state.fTextures[stage] && VertexUsesStage(stage, layout); + return NULL != state.getTexture(stage) && + VertexUsesStage(stage, layout); } bool isStageEnabled(int stage) const { @@ -1337,7 +1055,7 @@ protected: // Helpers for drawRect, protected so subclasses that override drawRect // can use them. - static GrVertexLayout GetRectVertexLayout(StageMask stageEnableBitfield, + static GrVertexLayout GetRectVertexLayout(StageMask stageMask, const GrRect* srcRects[]); static void SetRectVertices(const GrRect& rect, diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index 1583630..4c0594b 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -185,10 +185,10 @@ bool GrGpu::attachStencilBufferToRenderTarget(GrRenderTarget* rt) { // We used to clear down in the GL subclass using a special purpose // FBO. But iOS doesn't allow a stencil-only FBO. It reports unsupported // FBO status. - GrRenderTarget* oldRT = fCurrDrawState.fRenderTarget; - fCurrDrawState.fRenderTarget = rt; + GrRenderTarget* oldRT = this->getRenderTarget(); + this->setRenderTarget(rt); this->clearStencil(); - fCurrDrawState.fRenderTarget = oldRT; + this->setRenderTarget(oldRT); return true; } else { return false; @@ -530,16 +530,17 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { const GrIRect* r = NULL; GrIRect clipRect; + GrRenderTarget* rt = this->getRenderTarget(); + // GrDrawTarget should have filtered this for us - GrAssert(NULL != fCurrDrawState.fRenderTarget); + GrAssert(NULL != rt); - if (fCurrDrawState.fFlagBits & kClip_StateBit) { - GrRenderTarget& rt = *fCurrDrawState.fRenderTarget; + if (this->getDrawState().isClipState()) { GrRect bounds; GrRect rtRect; rtRect.setLTRB(0, 0, - GrIntToScalar(rt.width()), GrIntToScalar(rt.height())); + GrIntToScalar(rt->width()), GrIntToScalar(rt->height())); if (fClip.hasConservativeBounds()) { bounds = fClip.getConservativeBounds(); if (!bounds.intersect(rtRect)) { @@ -560,15 +561,17 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { !bounds.isEmpty(); // TODO: dynamically attach a SB when needed. - GrStencilBuffer* stencilBuffer = rt.getStencilBuffer(); + GrStencilBuffer* stencilBuffer = rt->getStencilBuffer(); if (fClipInStencil && NULL == stencilBuffer) { return false; } + GrDrawState* drawState = this->drawState(); + if (fClipInStencil && - stencilBuffer->mustRenderClip(fClip, rt.width(), rt.height())) { + stencilBuffer->mustRenderClip(fClip, rt->width(), rt->height())) { - stencilBuffer->setLastClip(fClip, rt.width(), rt.height()); + stencilBuffer->setLastClip(fClip, rt->width(), rt->height()); // we set the current clip to the bounds so that our recursive // draws are scissored to them. We use the copy of the complex clip @@ -583,9 +586,9 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { this->setViewMatrix(GrMatrix::I()); this->flushScissor(NULL); #if !VISUALIZE_COMPLEX_CLIP - this->enableState(kNoColorWrites_StateBit); + drawState->enableState(GrDrawState::kNoColorWrites_StateBit); #else - this->disableState(kNoColorWrites_StateBit); + drawState->disableState(GrDrawState::kNoColorWrites_StateBit); #endif int count = clip.getElementCount(); int clipBit = stencilBuffer->bits(); @@ -606,7 +609,7 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { GrPathFill fill; bool fillInverted; // enabled at bottom of loop - this->disableState(kModifyStencilClip_StateBit); + drawState->disableState(kModifyStencilClip_StateBit); bool canRenderDirectToStencil; // can the clip element be drawn // directly to the stencil buffer @@ -664,11 +667,11 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { }; SET_RANDOM_COLOR if (kRect_ClipType == clip.getElementType(c)) { - this->setStencil(gDrawToStencil); + drawState->setStencil(gDrawToStencil); this->drawSimpleRect(clip.getRect(c), NULL, 0); } else { if (canRenderDirectToStencil) { - this->setStencil(gDrawToStencil); + drawState->setStencil(gDrawToStencil); pr->drawPath(0); } else { pr->drawPathToStencil(); @@ -678,9 +681,9 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { // now we modify the clip bit by rendering either the clip // element directly or a bounding rect of the entire clip. - this->enableState(kModifyStencilClip_StateBit); + drawState->enableState(kModifyStencilClip_StateBit); for (int p = 0; p < passes; ++p) { - this->setStencil(stencilSettings[p]); + drawState->setStencil(stencilSettings[p]); if (canDrawDirectToClip) { if (kRect_ClipType == clip.getElementType(c)) { SET_RANDOM_COLOR diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index 11bf153..7b705e4 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -327,8 +327,8 @@ public: } protected: - enum PrivateStateBits { - kFirstBit = (kLastPublicStateBit << 1), + enum PrivateDrawStateBits { + kFirstBit = (GrDrawState::kLastPublicStateBit << 1), kModifyStencilClip_StateBit = kFirstBit, // allows draws to modify // stencil bits used for diff --git a/src/gpu/GrGpuGL.cpp b/src/gpu/GrGpuGL.cpp index 9f7e4ec..5df1ed1 100644 --- a/src/gpu/GrGpuGL.cpp +++ b/src/gpu/GrGpuGL.cpp @@ -480,7 +480,7 @@ void GrGpuGL::onResetContext() { GL_CALL(Disable(GR_GL_CULL_FACE)); GL_CALL(FrontFace(GR_GL_CCW)); - fHWDrawState.fDrawFace = GrDrawState::kBoth_DrawFace; + fHWDrawState.setDrawFace(GrDrawState::kBoth_DrawFace); GL_CALL(Disable(GR_GL_DITHER)); if (kDesktop_GrGLBinding == this->glBinding()) { @@ -492,7 +492,7 @@ void GrGpuGL::onResetContext() { } GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE)); - fHWDrawState.fFlagBits = 0; + fHWDrawState.resetStateFlags(); // we only ever use lines in hairline mode GL_CALL(LineWidth(1)); @@ -502,23 +502,22 @@ void GrGpuGL::onResetContext() { // illegal values //fHWDrawState.fSrcBlend = (GrBlendCoeff)(uint8_t)-1; - fHWDrawState.fSrcBlend = (GrBlendCoeff)0xFF; - fHWDrawState.fDstBlend = (GrBlendCoeff)(uint8_t)-1; - - fHWDrawState.fBlendConstant = 0x00000000; + fHWDrawState.setBlendFunc((GrBlendCoeff)-1, (GrBlendCoeff)-1); + fHWDrawState.setBlendConstant(0x00000000); GL_CALL(BlendColor(0,0,0,0)); - fHWDrawState.fColor = GrColor_ILLEGAL; + fHWDrawState.setColor(GrColor_ILLEGAL); - fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix(); + fHWDrawState.setViewMatrix(GrMatrix::InvalidMatrix()); for (int s = 0; s < GrDrawState::kNumStages; ++s) { - fHWDrawState.fTextures[s] = NULL; - fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax, - -GR_ScalarMax, - true); - fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix()); - fHWDrawState.fSamplerStates[s].setConvolutionParams(0, NULL, NULL); + fHWDrawState.setTexture(s, NULL); + GrSamplerState* sampler = fHWDrawState.sampler(s); + sampler->setRadial2Params(-GR_ScalarMax, + -GR_ScalarMax, + true); + sampler->setMatrix(GrMatrix::InvalidMatrix()); + sampler->setConvolutionParams(0, NULL, NULL); } fHWBounds.fScissorRect.invalidate(); @@ -526,7 +525,7 @@ void GrGpuGL::onResetContext() { GL_CALL(Disable(GR_GL_SCISSOR_TEST)); fHWBounds.fViewportRect.invalidate(); - fHWDrawState.fStencilSettings.invalidate(); + fHWDrawState.stencil()->invalidate(); fHWStencilClip = false; fClipInStencil = false; @@ -536,7 +535,7 @@ void GrGpuGL::onResetContext() { fHWGeometryState.fArrayPtrsDirty = true; GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE)); - fHWDrawState.fRenderTarget = NULL; + fHWDrawState.setRenderTarget(NULL); // we assume these values if (this->glCaps().fUnpackRowLengthSupport) { @@ -1191,7 +1190,7 @@ bool GrGpuGL::attachStencilBufferToRenderTarget(GrStencilBuffer* sb, GrGLStencilBuffer* glsb = (GrGLStencilBuffer*) sb; GrGLuint rb = glsb->renderbufferID(); - fHWDrawState.fRenderTarget = NULL; + fHWDrawState.setRenderTarget(NULL); GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fbo)); GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_STENCIL_ATTACHMENT, @@ -1276,9 +1275,9 @@ GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) { } void GrGpuGL::flushScissor(const GrIRect* rect) { - GrAssert(NULL != fCurrDrawState.fRenderTarget); + GrAssert(this->getRenderTarget() != NULL); const GrGLIRect& vp = - ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport(); + ((GrGLRenderTarget*)this->getRenderTarget())->getViewport(); GrGLIRect scissor; if (NULL != rect) { @@ -1307,15 +1306,17 @@ void GrGpuGL::flushScissor(const GrIRect* rect) { } void GrGpuGL::onClear(const GrIRect* rect, GrColor color) { + const GrRenderTarget* rt = this->getDrawState().getRenderTarget(); // parent class should never let us get here with no RT - GrAssert(NULL != fCurrDrawState.fRenderTarget); + GrAssert(rt != NULL); + GrIRect clippedRect; if (NULL != rect) { // flushScissor expects rect to be clipped to the target. clippedRect = *rect; - GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(), - fCurrDrawState.fRenderTarget->height()); + GrIRect rtRect = SkIRect::MakeWH(rt->width(), + rt->height()); if (clippedRect.intersect(rtRect)) { rect = &clippedRect; } else { @@ -1329,7 +1330,7 @@ void GrGpuGL::onClear(const GrIRect* rect, GrColor color) { static const GrGLfloat scale255 = 1.f / 255.f; a = GrColorUnpackA(color) * scale255; GrGLfloat scaleRGB = scale255; - if (GrPixelConfigIsUnpremultiplied(fCurrDrawState.fRenderTarget->config())) { + if (GrPixelConfigIsUnpremultiplied(rt->config())) { scaleRGB *= a; } r = GrColorUnpackR(color) * scaleRGB; @@ -1337,13 +1338,13 @@ void GrGpuGL::onClear(const GrIRect* rect, GrColor color) { b = GrColorUnpackB(color) * scaleRGB; GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE)); - fHWDrawState.fFlagBits &= ~kNoColorWrites_StateBit; + fHWDrawState.disableState(GrDrawState::kNoColorWrites_StateBit); GL_CALL(ClearColor(r, g, b, a)); GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT)); } void GrGpuGL::clearStencil() { - if (NULL == fCurrDrawState.fRenderTarget) { + if (NULL == this->getRenderTarget()) { return; } @@ -1356,17 +1357,17 @@ void GrGpuGL::clearStencil() { GL_CALL(StencilMask(0xffffffff)); GL_CALL(ClearStencil(0)); GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT)); - fHWDrawState.fStencilSettings.invalidate(); + fHWDrawState.stencil()->invalidate(); } void GrGpuGL::clearStencilClip(const GrIRect& rect, bool insideClip) { - GrAssert(NULL != fCurrDrawState.fRenderTarget); + GrRenderTarget* rt = this->getRenderTarget(); + GrAssert(NULL != rt); // this should only be called internally when we know we have a // stencil buffer. - GrAssert(NULL != fCurrDrawState.fRenderTarget->getStencilBuffer()); - GrGLint stencilBitCount = - fCurrDrawState.fRenderTarget->getStencilBuffer()->bits(); + GrAssert(NULL != rt->getStencilBuffer()); + GrGLint stencilBitCount = rt->getStencilBuffer()->bits(); #if 0 GrAssert(stencilBitCount > 0); GrGLint clipStencilMask = (1 << (stencilBitCount - 1)); @@ -1389,7 +1390,7 @@ void GrGpuGL::clearStencilClip(const GrIRect& rect, bool insideClip) { GL_CALL(StencilMask(clipStencilMask)); GL_CALL(ClearStencil(value)); GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT)); - fHWDrawState.fStencilSettings.invalidate(); + fHWDrawState.stencil()->invalidate(); } void GrGpuGL::onForceRenderTargetFlush() { @@ -1445,13 +1446,12 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target, // resolve the render target if necessary GrGLRenderTarget* tgt = static_cast(target); - GrAutoTPtrValueRestore autoTargetRestore; + GrDrawState::AutoRenderTargetRestore arr; switch (tgt->getResolveType()) { case GrGLRenderTarget::kCantResolve_ResolveType: return false; case GrGLRenderTarget::kAutoResolves_ResolveType: - autoTargetRestore.save(&fCurrDrawState.fRenderTarget); - fCurrDrawState.fRenderTarget = target; + arr.set(this->drawState(), target); this->flushRenderTarget(&GrIRect::EmptyIRect()); break; case GrGLRenderTarget::kCanResolve_ResolveType: @@ -1549,10 +1549,11 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target, void GrGpuGL::flushRenderTarget(const GrIRect* bound) { - GrAssert(NULL != fCurrDrawState.fRenderTarget); + GrAssert(this->getRenderTarget() != NULL); - GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget; - if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) { + GrGLRenderTarget* rt = + static_cast(this->getRenderTarget()); + if (fHWDrawState.getRenderTarget() != rt) { GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID())); #if GR_COLLECT_STATS ++fStats.fRenderTargetChngCnt; @@ -1565,7 +1566,7 @@ void GrGpuGL::flushRenderTarget(const GrIRect* bound) { } #endif fDirtyFlags.fRenderTargetChanged = true; - fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget; + fHWDrawState.setRenderTarget(rt); const GrGLIRect& vp = rt->getViewport(); if (fHWBounds.fViewportRect != vp) { vp.pushToGLViewport(this->glInterface()); @@ -1682,7 +1683,7 @@ void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) { #endif // make sure we go through flushRenderTarget() since we've modified // the bound DRAW FBO ID. - fHWDrawState.fRenderTarget = NULL; + fHWDrawState.setRenderTarget(NULL); const GrGLIRect& vp = rt->getViewport(); const GrIRect dirtyRect = rt->getResolveRect(); GrGLIRect r; @@ -1754,21 +1755,24 @@ GR_STATIC_ASSERT(6 == kZero_StencilOp); GR_STATIC_ASSERT(7 == kInvert_StencilOp); void GrGpuGL::flushStencil() { - const GrStencilSettings* settings = &fCurrDrawState.fStencilSettings; + const GrDrawState& drawState = this->getDrawState(); + const GrStencilSettings* settings = &drawState.getStencil(); // use stencil for clipping if clipping is enabled and the clip // has been written into the stencil. - bool stencilClip = fClipInStencil && - (kClip_StateBit & fCurrDrawState.fFlagBits); + bool stencilClip = fClipInStencil && drawState.isClipState(); + + bool modifyingStencilClip = drawState.isStateFlagEnabled( + kModifyStencilClip_StateBit); bool stencilChange = fHWStencilClip != stencilClip || - fHWDrawState.fStencilSettings != *settings || - ((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) != - (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit)); + fHWDrawState.getStencil() != *settings || + (fHWDrawState.isStateFlagEnabled(kModifyStencilClip_StateBit) != + modifyingStencilClip); if (stencilChange) { // we can't simultaneously perform stencil-clipping and modify the stencil clip - GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit)); + GrAssert(!stencilClip || !drawState.isStateFlagEnabled(kModifyStencilClip_StateBit)); if (settings->isDisabled()) { if (stencilClip) { @@ -1793,15 +1797,14 @@ void GrGpuGL::flushStencil() { } #endif int stencilBits = 0; - GrStencilBuffer* stencilBuffer = - fCurrDrawState.fRenderTarget->getStencilBuffer(); + GrStencilBuffer* stencilBuffer = + drawState.getRenderTarget()->getStencilBuffer(); if (NULL != stencilBuffer) { stencilBits = stencilBuffer->bits(); } // TODO: dynamically attach a stencil buffer GrAssert(stencilBits || - (GrStencilSettings::gDisabled == - fCurrDrawState.fStencilSettings)); + (GrStencilSettings::gDisabled == *settings)); GrGLuint clipStencilMask = 0; GrGLuint userStencilMask = ~0; @@ -1815,7 +1818,7 @@ void GrGpuGL::flushStencil() { unsigned int frontWriteMask = settings->fFrontWriteMask; GrGLenum frontFunc; - if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) { + if (modifyingStencilClip) { GrAssert(settings->fFrontFunc < kBasicStencilFuncCount); frontFunc = grToGLStencilFunc[settings->fFrontFunc]; @@ -1847,7 +1850,7 @@ void GrGpuGL::flushStencil() { unsigned int backWriteMask = settings->fBackWriteMask; - if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) { + if (modifyingStencilClip) { GrAssert(settings->fBackFunc < kBasicStencilFuncCount); backFunc = grToGLStencilFunc[settings->fBackFunc]; } else { @@ -1885,7 +1888,7 @@ void GrGpuGL::flushStencil() { grToGLStencilOp[settings->fFrontPassOp])); } } - fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings; + *fHWDrawState.stencil() = *settings; fHWStencilClip = stencilClip; } } @@ -1897,6 +1900,8 @@ void GrGpuGL::flushAAState(GrPrimitiveType type) { // we prefer smooth lines over multisampled lines // msaa should be disabled if drawing smooth lines. + + GrRenderTarget* rt = this->getRenderTarget(); if (GrIsPrimTypeLines(type)) { bool smooth = this->willUseHWAALines(); if (!fHWAAState.fSmoothLineEnabled && smooth) { @@ -1906,13 +1911,13 @@ void GrGpuGL::flushAAState(GrPrimitiveType type) { GL_CALL(Disable(GR_GL_LINE_SMOOTH)); fHWAAState.fSmoothLineEnabled = false; } - if (fCurrDrawState.fRenderTarget->isMultisampled() && + if (rt->isMultisampled() && fHWAAState.fMSAAEnabled) { GL_CALL(Disable(GR_GL_MULTISAMPLE)); fHWAAState.fMSAAEnabled = false; } - } else if (fCurrDrawState.fRenderTarget->isMultisampled() && - SkToBool(kHWAntialias_StateBit & fCurrDrawState.fFlagBits) != + } else if (rt->isMultisampled() && + this->getDrawState().isHWAntialiasState() != fHWAAState.fMSAAEnabled) { if (fHWAAState.fMSAAEnabled) { GL_CALL(Disable(GR_GL_MULTISAMPLE)); @@ -1933,12 +1938,11 @@ void GrGpuGL::flushBlend(GrPrimitiveType type, GL_CALL(Enable(GR_GL_BLEND)); fHWBlendDisabled = false; } - if (kSA_BlendCoeff != fHWDrawState.fSrcBlend || - kISA_BlendCoeff != fHWDrawState.fDstBlend) { + if (kSA_BlendCoeff != fHWDrawState.getSrcBlendCoeff() || + kISA_BlendCoeff != fHWDrawState.getDstBlendCoeff()) { GL_CALL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff], gXfermodeCoeff2Blend[kISA_BlendCoeff])); - fHWDrawState.fSrcBlend = kSA_BlendCoeff; - fHWDrawState.fDstBlend = kISA_BlendCoeff; + fHWDrawState.setBlendFunc(kSA_BlendCoeff, kISA_BlendCoeff); } } else { // any optimization to disable blending should @@ -1955,25 +1959,25 @@ void GrGpuGL::flushBlend(GrPrimitiveType type, fHWBlendDisabled = blendOff; } if (!blendOff) { - if (fHWDrawState.fSrcBlend != srcCoeff || - fHWDrawState.fDstBlend != dstCoeff) { + if (fHWDrawState.getSrcBlendCoeff() != srcCoeff || + fHWDrawState.getDstBlendCoeff() != dstCoeff) { GL_CALL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff], gXfermodeCoeff2Blend[dstCoeff])); - fHWDrawState.fSrcBlend = srcCoeff; - fHWDrawState.fDstBlend = dstCoeff; + fHWDrawState.setBlendFunc(srcCoeff, dstCoeff); } + GrColor blendConstant = this->getDrawState().getBlendConstant(); if ((BlendCoeffReferencesConstant(srcCoeff) || BlendCoeffReferencesConstant(dstCoeff)) && - fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) { + fHWDrawState.getBlendConstant() != blendConstant) { float c[] = { - GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f, - GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f, - GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f, - GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f + GrColorUnpackR(blendConstant) / 255.f, + GrColorUnpackG(blendConstant) / 255.f, + GrColorUnpackB(blendConstant) / 255.f, + GrColorUnpackA(blendConstant) / 255.f }; GL_CALL(BlendColor(c[0], c[1], c[2], c[3])); - fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant; + fHWDrawState.setBlendConstant(blendConstant); } } } @@ -2033,12 +2037,13 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { // GrGpu::setupClipAndFlushState should have already checked this // and bailed if not true. - GrAssert(NULL != fCurrDrawState.fRenderTarget); + GrAssert(this->getRenderTarget() != NULL); for (int s = 0; s < GrDrawState::kNumStages; ++s) { // bind texture and set sampler state if (this->isStageEnabled(s)) { - GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s]; + GrGLTexture* nextTexture = + static_cast(this->drawState()->getTexture(s)); // true for now, but maybe not with GrEffect. GrAssert(NULL != nextTexture); @@ -2052,20 +2057,20 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { resolveRenderTarget(texRT); } - if (fHWDrawState.fTextures[s] != nextTexture) { + if (fHWDrawState.getTexture(s) != nextTexture) { setTextureUnit(s); GL_CALL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID())); #if GR_COLLECT_STATS ++fStats.fTextureChngCnt; #endif //GrPrintf("---- bindtexture %d\n", nextTexture->textureID()); - fHWDrawState.fTextures[s] = nextTexture; + fHWDrawState.setTexture(s, nextTexture); // The texture matrix has to compensate for texture width/height // and NPOT-embedded-in-POT fDirtyFlags.fTextureChangedMask |= (1 << s); } - const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s]; + const GrSamplerState& sampler = this->getSampler(s); ResetTimestamp timestamp; const GrGLTexture::TexParams& oldTexParams = nextTexture->getCachedTexParams(×tamp); @@ -2117,7 +2122,7 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { GrIRect* rect = NULL; GrIRect clipBounds; - if ((fCurrDrawState.fFlagBits & kClip_StateBit) && + if (this->getDrawState().isClipState() && fClip.hasConservativeBounds()) { fClip.getConservativeBounds().roundOut(&clipBounds); rect = &clipBounds; @@ -2125,19 +2130,19 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { this->flushRenderTarget(rect); this->flushAAState(type); - if ((fCurrDrawState.fFlagBits & kDither_StateBit) != - (fHWDrawState.fFlagBits & kDither_StateBit)) { - if (fCurrDrawState.fFlagBits & kDither_StateBit) { + if (this->getDrawState().isDitherState() != + fHWDrawState.isDitherState()) { + if (this->getDrawState().isDitherState()) { GL_CALL(Enable(GR_GL_DITHER)); } else { GL_CALL(Disable(GR_GL_DITHER)); } } - if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) != - (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) { + if (this->getDrawState().isColorWriteDisabled() != + fHWDrawState.isColorWriteDisabled()) { GrGLenum mask; - if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) { + if (this->getDrawState().isColorWriteDisabled()) { mask = GR_GL_FALSE; } else { mask = GR_GL_TRUE; @@ -2145,8 +2150,8 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { GL_CALL(ColorMask(mask, mask, mask, mask)); } - if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) { - switch (fCurrDrawState.fDrawFace) { + if (fHWDrawState.getDrawFace() != this->getDrawFace()) { + switch (this->getDrawFace()) { case GrDrawState::kCCW_DrawFace: GL_CALL(Enable(GR_GL_CULL_FACE)); GL_CALL(CullFace(GR_GL_BACK)); @@ -2161,24 +2166,27 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { default: GrCrash("Unknown draw face."); } - fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace; + fHWDrawState.setDrawFace(this->getDrawFace()); } #if GR_DEBUG // check for circular rendering for (int s = 0; s < GrDrawState::kNumStages; ++s) { GrAssert(!this->isStageEnabled(s) || - NULL == fCurrDrawState.fRenderTarget || - NULL == fCurrDrawState.fTextures[s] || - fCurrDrawState.fTextures[s]->asRenderTarget() != - fCurrDrawState.fRenderTarget); + NULL == this->getRenderTarget() || + NULL == this->getTexture(s) || + this->getTexture(s)->asRenderTarget() != + this->getRenderTarget()); } #endif - flushStencil(); + this->flushStencil(); + + // the flushStencil() function called above detecs a change in the + // kModifyStencilClip_StateBit flag. Therefore this copy must happen after + // flushStencil() + fHWDrawState.copyStateFlags(this->getDrawState()); - // flushStencil may look at the private state bits, so keep it before this. - fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits; return true; } @@ -2210,22 +2218,22 @@ void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) { void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) { GrAssert(NULL != renderTarget); - if (fCurrDrawState.fRenderTarget == renderTarget) { - fCurrDrawState.fRenderTarget = NULL; + if (this->getRenderTarget() == renderTarget) { + this->setRenderTarget(NULL); } - if (fHWDrawState.fRenderTarget == renderTarget) { - fHWDrawState.fRenderTarget = NULL; + if (this->getRenderTarget() == renderTarget) { + fHWDrawState.setRenderTarget(NULL); } } void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) { for (int s = 0; s < GrDrawState::kNumStages; ++s) { - if (fCurrDrawState.fTextures[s] == texture) { - fCurrDrawState.fTextures[s] = NULL; + if (this->getTexture(s) == texture) { + this->setTexture(s, NULL); } - if (fHWDrawState.fTextures[s] == texture) { + if (fHWDrawState.getTexture(s) == texture) { // deleting bound texture does implied bind to 0 - fHWDrawState.fTextures[s] = NULL; + this->setTexture(s, NULL); } } } diff --git a/src/gpu/GrGpuGLShaders.cpp b/src/gpu/GrGpuGLShaders.cpp index 9018a4e..5109a10 100644 --- a/src/gpu/GrGpuGLShaders.cpp +++ b/src/gpu/GrGpuGLShaders.cpp @@ -343,7 +343,7 @@ const GrMatrix& GrGpuGLShaders::getHWSamplerMatrix(int stage) { if (GrGLProgram::kSetAsAttribute == fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) { - return fHWDrawState.fSamplerStates[stage].getMatrix(); + return fHWDrawState.getSampler(stage).getMatrix(); } else { return fProgramData->fTextureMatrices[stage]; } @@ -351,9 +351,9 @@ const GrMatrix& GrGpuGLShaders::getHWSamplerMatrix(int stage) { void GrGpuGLShaders::recordHWSamplerMatrix(int stage, const GrMatrix& matrix) { GrAssert(fProgramData); - if (GrGLProgram::kSetAsAttribute == + if (GrGLProgram::kSetAsAttribute == fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) { - fHWDrawState.fSamplerStates[stage].setMatrix(matrix); + fHWDrawState.sampler(stage)->setMatrix(matrix); } else { fProgramData->fTextureMatrices[stage] = matrix; } @@ -388,47 +388,68 @@ void GrGpuGLShaders::onResetContext() { } void GrGpuGLShaders::flushViewMatrix() { - GrAssert(NULL != fCurrDrawState.fRenderTarget); - GrMatrix m; - m.setAll( - GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1, - 0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1, - 0, 0, GrMatrix::I()[8]); - m.setConcat(m, fCurrDrawState.fViewMatrix); - - // ES doesn't allow you to pass true to the transpose param, - // so do our own transpose - GrGLfloat mt[] = { - GrScalarToFloat(m[GrMatrix::kMScaleX]), - GrScalarToFloat(m[GrMatrix::kMSkewY]), - GrScalarToFloat(m[GrMatrix::kMPersp0]), - GrScalarToFloat(m[GrMatrix::kMSkewX]), - GrScalarToFloat(m[GrMatrix::kMScaleY]), - GrScalarToFloat(m[GrMatrix::kMPersp1]), - GrScalarToFloat(m[GrMatrix::kMTransX]), - GrScalarToFloat(m[GrMatrix::kMTransY]), - GrScalarToFloat(m[GrMatrix::kMPersp2]) - }; - if (GrGLProgram::kSetAsAttribute == + const GrMatrix* hwViewMatrix; + // If we are using a uniform for the matrix then the cached value is + // stored with each program. If we are using an attribute than it is global + // to all programs. + if (GrGLProgram::kSetAsAttribute == fProgramData->fUniLocations.fViewMatrixUni) { - int baseIdx = GrGLProgram::ViewMatrixAttributeIdx(); - GL_CALL(VertexAttrib4fv(baseIdx + 0, mt+0)); - GL_CALL(VertexAttrib4fv(baseIdx + 1, mt+3)); - GL_CALL(VertexAttrib4fv(baseIdx + 2, mt+6)); + hwViewMatrix = &fHWDrawState.getViewMatrix(); } else { - GrAssert(GrGLProgram::kUnusedUniform != - fProgramData->fUniLocations.fViewMatrixUni); - GL_CALL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni, - 1, false, mt)); + hwViewMatrix = &fProgramData->fViewMatrix; + } + + if (*hwViewMatrix != this->getViewMatrix()) { + + GrRenderTarget* rt = this->getRenderTarget(); + GrAssert(NULL != rt); + GrMatrix m; + m.setAll( + GrIntToScalar(2) / rt->width(), 0, -GR_Scalar1, + 0,-GrIntToScalar(2) / rt->height(), GR_Scalar1, + 0, 0, GrMatrix::I()[8]); + m.setConcat(m, this->getViewMatrix()); + + // ES doesn't allow you to pass true to the transpose param, + // so do our own transpose + GrGLfloat mt[] = { + GrScalarToFloat(m[GrMatrix::kMScaleX]), + GrScalarToFloat(m[GrMatrix::kMSkewY]), + GrScalarToFloat(m[GrMatrix::kMPersp0]), + GrScalarToFloat(m[GrMatrix::kMSkewX]), + GrScalarToFloat(m[GrMatrix::kMScaleY]), + GrScalarToFloat(m[GrMatrix::kMPersp1]), + GrScalarToFloat(m[GrMatrix::kMTransX]), + GrScalarToFloat(m[GrMatrix::kMTransY]), + GrScalarToFloat(m[GrMatrix::kMPersp2]) + }; + + if (GrGLProgram::kSetAsAttribute == + fProgramData->fUniLocations.fViewMatrixUni) { + int baseIdx = GrGLProgram::ViewMatrixAttributeIdx(); + GL_CALL(VertexAttrib4fv(baseIdx + 0, mt+0)); + GL_CALL(VertexAttrib4fv(baseIdx + 1, mt+3)); + GL_CALL(VertexAttrib4fv(baseIdx + 2, mt+6)); + } else { + GrAssert(GrGLProgram::kUnusedUniform != + fProgramData->fUniLocations.fViewMatrixUni); + GL_CALL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni, + 1, false, mt)); + } + if (GrGLProgram::kSetAsAttribute == + fProgramData->fUniLocations.fViewMatrixUni) { + fHWDrawState.setViewMatrix(this->getViewMatrix()); + } else { + fProgramData->fViewMatrix = this->getViewMatrix(); + } } } void GrGpuGLShaders::flushTextureDomain(int s) { const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTexDomUni; if (GrGLProgram::kUnusedUniform != uni) { - const GrRect &texDom = - fCurrDrawState.fSamplerStates[s].getTextureDomain(); + const GrRect &texDom = this->getSampler(s).getTextureDomain(); if (((1 << s) & fDirtyFlags.fTextureChangedMask) || fProgramData->fTextureDomain[s] != texDom) { @@ -442,7 +463,7 @@ void GrGpuGLShaders::flushTextureDomain(int s) { GrScalarToFloat(texDom.bottom()) }; - GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; + GrGLTexture* texture = (GrGLTexture*) this->getTexture(s); GrGLTexture::Orientation orientation = texture->orientation(); // vertical flip if necessary @@ -461,19 +482,18 @@ void GrGpuGLShaders::flushTextureDomain(int s) { void GrGpuGLShaders::flushTextureMatrix(int s) { const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTextureMatrixUni; - GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; + GrGLTexture* texture = (GrGLTexture*) this->getTexture(s); if (NULL != texture) { + const GrMatrix& hwMat = fHWDrawState.getSampler(s).getMatrix(); + const GrMatrix& currMat = this->getSampler(s).getMatrix(); if (GrGLProgram::kUnusedUniform != uni && (((1 << s) & fDirtyFlags.fTextureChangedMask) || - getHWSamplerMatrix(s) != getSamplerMatrix(s))) { + hwMat != currMat)) { - GrAssert(NULL != fCurrDrawState.fTextures[s]); - - GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; + GrAssert(NULL != texture); - GrMatrix m = getSamplerMatrix(s); - GrSamplerState::SampleMode mode = - fCurrDrawState.fSamplerStates[s].getSampleMode(); + GrMatrix m = currMat; + GrSamplerState::SampleMode mode = this->getSampler(s).getSampleMode(); AdjustTextureMatrix(texture, mode, &m); // ES doesn't allow you to pass true to the transpose param, @@ -499,7 +519,7 @@ void GrGpuGLShaders::flushTextureMatrix(int s) { } else { GL_CALL(UniformMatrix3fv(uni, 1, false, mt)); } - recordHWSamplerMatrix(s, getSamplerMatrix(s)); + this->recordHWSamplerMatrix(s, currMat); } } } @@ -507,7 +527,7 @@ void GrGpuGLShaders::flushTextureMatrix(int s) { void GrGpuGLShaders::flushRadial2(int s) { const int &uni = fProgramData->fUniLocations.fStages[s].fRadial2Uni; - const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s]; + const GrSamplerState& sampler = fCurrDrawState.getSampler(s); if (GrGLProgram::kUnusedUniform != uni && (fProgramData->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() || fProgramData->fRadial2Radius0[s] != sampler.getRadial2Radius0() || @@ -539,7 +559,7 @@ void GrGpuGLShaders::flushRadial2(int s) { } void GrGpuGLShaders::flushConvolution(int s) { - const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s]; + const GrSamplerState& sampler = this->getSampler(s); int kernelUni = fProgramData->fUniLocations.fStages[s].fKernelUni; if (GrGLProgram::kUnusedUniform != kernelUni) { GL_CALL(Uniform1fv(kernelUni, sampler.getKernelWidth(), @@ -554,7 +574,7 @@ void GrGpuGLShaders::flushConvolution(int s) { void GrGpuGLShaders::flushTexelSize(int s) { const int& uni = fProgramData->fUniLocations.fStages[s].fNormalizedTexelSizeUni; if (GrGLProgram::kUnusedUniform != uni) { - GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; + GrGLTexture* texture = (GrGLTexture*) this->getTexture(s); if (texture->width() != fProgramData->fTextureWidth[s] || texture->height() != fProgramData->fTextureHeight[s]) { @@ -570,13 +590,14 @@ void GrGpuGLShaders::flushTexelSize(int s) { void GrGpuGLShaders::flushEdgeAAData() { const int& uni = fProgramData->fUniLocations.fEdgesUni; if (GrGLProgram::kUnusedUniform != uni) { - int count = fCurrDrawState.fEdgeAANumEdges; + + int count = this->getDrawState().getNumAAEdges(); GrDrawState::Edge edges[GrDrawState::kMaxEdges]; // Flip the edges in Y float height = - static_cast(fCurrDrawState.fRenderTarget->height()); + static_cast(this->getRenderTarget()->height()); for (int i = 0; i < count; ++i) { - edges[i] = fCurrDrawState.fEdgeAAEdges[i]; + edges[i] = this->getDrawState().getAAEdges()[i]; float b = edges[i].fY; edges[i].fY = -b; edges[i].fZ += b * height; @@ -599,16 +620,16 @@ void GrGpuGLShaders::flushColor(GrColor color) { if (this->getGeomSrc().fVertexLayout & kColor_VertexLayoutBit) { // color will be specified per-vertex as an attribute // invalidate the const vertex attrib color - fHWDrawState.fColor = GrColor_ILLEGAL; + fHWDrawState.setColor(GrColor_ILLEGAL); } else { switch (desc.fColorInput) { case ProgramDesc::kAttribute_ColorInput: - if (fHWDrawState.fColor != color) { + if (fHWDrawState.getColor() != color) { // OpenGL ES only supports the float varities of glVertexAttrib float c[] = GR_COLOR_TO_VEC4(color); GL_CALL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), c)); - fHWDrawState.fColor = color; + fHWDrawState.setColor(color); } break; case ProgramDesc::kUniform_ColorInput: @@ -629,13 +650,13 @@ void GrGpuGLShaders::flushColor(GrColor color) { GrCrash("Unknown color type."); } } - if (fProgramData->fUniLocations.fColorFilterUni - != GrGLProgram::kUnusedUniform - && fProgramData->fColorFilterColor - != fCurrDrawState.fColorFilterColor) { - float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColorFilterColor); - GL_CALL(Uniform4fv(fProgramData->fUniLocations.fColorFilterUni, 1, c)); - fProgramData->fColorFilterColor = fCurrDrawState.fColorFilterColor; + GrColor filterColor = this->getDrawState().getColorFilterColor(); + int uni = fProgramData->fUniLocations.fColorFilterUni; + if (uni != GrGLProgram::kUnusedUniform && + fProgramData->fColorFilterColor != filterColor) { + float c[] = GR_COLOR_TO_VEC4(filterColor); + GL_CALL(Uniform4fv(uni, 1, c)); + fProgramData->fColorFilterColor = filterColor; } } @@ -648,7 +669,7 @@ bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) { if (fDirtyFlags.fRenderTargetChanged) { // our coords are in pixel space and the GL matrices map to NDC // so if the viewport changed, our matrix is now wrong. - fHWDrawState.fViewMatrix = GrMatrix::InvalidMatrix(); + fHWDrawState.setViewMatrix(GrMatrix::InvalidMatrix()); // we assume all shader matrices may be wrong after viewport changes fProgramCache->invalidateViewMatrices(); } @@ -680,22 +701,11 @@ bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) { } else if (blendOpts & kEmitCoverage_BlendOptFlag) { color = 0xffffffff; } else { - color = fCurrDrawState.fColor; + color = this->getColor(); } this->flushColor(color); - GrMatrix* currViewMatrix; - if (GrGLProgram::kSetAsAttribute == - fProgramData->fUniLocations.fViewMatrixUni) { - currViewMatrix = &fHWDrawState.fViewMatrix; - } else { - currViewMatrix = &fProgramData->fViewMatrix; - } - - if (*currViewMatrix != fCurrDrawState.fViewMatrix) { - flushViewMatrix(); - *currViewMatrix = fCurrDrawState.fViewMatrix; - } + this->flushViewMatrix(); for (int s = 0; s < GrDrawState::kNumStages; ++s) { this->flushTextureMatrix(s); @@ -709,7 +719,7 @@ bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) { this->flushTextureDomain(s); } this->flushEdgeAAData(); - resetDirtyFlags(); + this->resetDirtyFlags(); return true; } @@ -856,6 +866,7 @@ void GrGpuGLShaders::setupGeometry(int* startVertex, void GrGpuGLShaders::buildProgram(GrPrimitiveType type, BlendOptFlags blendOpts, GrBlendCoeff dstCoeff) { + const GrDrawState& drawState = this->getDrawState(); ProgramDesc& desc = fCurrentProgram.fProgramDesc; // This should already have been caught @@ -885,7 +896,7 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type, desc.fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : - fCurrDrawState.fColorFilterXfermode; + drawState.getColorFilterMode(); // no reason to do edge aa or look at per-vertex coverage if coverage is // ignored @@ -897,7 +908,7 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type, bool colorIsTransBlack = SkToBool(blendOpts & kEmitTransBlack_BlendOptFlag); bool colorIsSolidWhite = (blendOpts & kEmitCoverage_BlendOptFlag) || (!requiresAttributeColors && - 0xffffffff == fCurrDrawState.fColor); + 0xffffffff == this->getColor()); if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) { desc.fColorInput = ProgramDesc::kTransBlack_ColorInput; } else if (GR_AGGRESSIVE_SHADER_OPTS && colorIsSolidWhite) { @@ -908,16 +919,15 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type, desc.fColorInput = ProgramDesc::kAttribute_ColorInput; } - desc.fEdgeAANumEdges = skipCoverage ? 0 : fCurrDrawState.fEdgeAANumEdges; + desc.fEdgeAANumEdges = skipCoverage ? 0 : drawState.getNumAAEdges(); desc.fEdgeAAConcave = desc.fEdgeAANumEdges > 0 && - SkToBool(fCurrDrawState.fFlagBits & - kEdgeAAConcave_StateBit); + drawState.isConcaveEdgeAAState(); int lastEnabledStage = -1; if (!skipCoverage && (desc.fVertexLayout & GrDrawTarget::kEdge_VertexLayoutBit)) { - desc.fVertexEdgeType = fCurrDrawState.fVertexEdgeType; + desc.fVertexEdgeType = drawState.getVertexEdgeType(); } else { // use canonical value when not set to avoid cache misses desc.fVertexEdgeType = GrDrawState::kHairLine_EdgeType; @@ -929,19 +939,19 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type, stage.fOptFlags = 0; stage.setEnabled(this->isStageEnabled(s)); - bool skip = s < fCurrDrawState.fFirstCoverageStage ? skipColor : - skipCoverage; + bool skip = s < drawState.getFirstCoverageStage() ? skipColor : + skipCoverage; if (!skip && stage.isEnabled()) { lastEnabledStage = s; - GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; + GrGLTexture* texture = (GrGLTexture*) drawState.getTexture(s); GrAssert(NULL != texture); - const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s]; + const GrSamplerState& sampler = drawState.getSampler(s); // we matrix to invert when orientation is TopDown, so make sure // we aren't in that case before flagging as identity. if (TextureMatrixIsIdentity(texture, sampler)) { stage.fOptFlags |= StageDesc::kIdentityMatrix_OptFlagBit; - } else if (!getSamplerMatrix(s).hasPerspective()) { + } else if (!drawState.getSampler(s).getMatrix().hasPerspective()) { stage.fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; } switch (sampler.getSampleMode()) { @@ -1024,7 +1034,7 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type, } } - if (GrPixelConfigIsUnpremultiplied(fCurrDrawState.fRenderTarget->config())) { + if (GrPixelConfigIsUnpremultiplied(drawState.getRenderTarget()->config())) { desc.fOutputPM = ProgramDesc::kNo_OutputPM; } else { desc.fOutputPM = ProgramDesc::kYes_OutputPM; @@ -1046,9 +1056,9 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type, // immaterial. int firstCoverageStage = GrDrawState::kNumStages; desc.fFirstCoverageStage = GrDrawState::kNumStages; - bool hasCoverage = fCurrDrawState.fFirstCoverageStage <= lastEnabledStage; + bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage; if (hasCoverage) { - firstCoverageStage = fCurrDrawState.fFirstCoverageStage; + firstCoverageStage = drawState.getFirstCoverageStage(); } // other coverage inputs diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp index 340cff1..829d9f0 100644 --- a/src/gpu/GrInOrderDrawBuffer.cpp +++ b/src/gpu/GrInOrderDrawBuffer.cpp @@ -102,7 +102,7 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect, // simply because the clip has changed if the clip doesn't affect // the rect. bool disabledClip = false; - if (this->isClipState() && fClip.isRect()) { + if (this->getDrawState().isClipState() && fClip.isRect()) { GrRect clipRect = fClip.getRect(0); // If the clip rect touches the edge of the viewport, extended it @@ -132,7 +132,7 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect, } } if (insideClip) { - this->disableState(kClip_StateBit); + this->drawState()->disableState(GrDrawState::kClip_StateBit); disabledClip = true; } } @@ -176,7 +176,7 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect, fLastRectVertexLayout = layout; } if (disabledClip) { - this->enableState(kClip_StateBit); + this->drawState()->disableState(GrDrawState::kClip_StateBit); } } else { INHERITED::drawRect(rect, matrix, stageMask, srcRects, srcMatrices); @@ -328,9 +328,9 @@ void GrInOrderDrawBuffer::reset() { for (uint32_t i = 0; i < numStates; ++i) { const GrDrawState& dstate = this->accessSavedDrawState(fStates[i]); for (int s = 0; s < GrDrawState::kNumStages; ++s) { - GrSafeUnref(dstate.fTextures[s]); + GrSafeUnref(dstate.getTexture(s)); } - GrSafeUnref(dstate.fRenderTarget); + GrSafeUnref(dstate.getRenderTarget()); } int numDraws = fDraws.count(); for (int d = 0; d < numDraws; ++d) { @@ -594,14 +594,14 @@ bool GrInOrderDrawBuffer::needsNewState() const { void GrInOrderDrawBuffer::pushState() { for (int s = 0; s < GrDrawState::kNumStages; ++s) { - GrSafeRef(fCurrDrawState.fTextures[s]); + GrSafeRef(fCurrDrawState.getTexture(s)); } - GrSafeRef(fCurrDrawState.fRenderTarget); + GrSafeRef(fCurrDrawState.getRenderTarget()); this->saveCurrentDrawState(&fStates.push_back()); } bool GrInOrderDrawBuffer::needsNewClip() const { - if (fCurrDrawState.fFlagBits & kClip_StateBit) { + if (this->getDrawState().isClipState()) { if (fClips.empty() || (fClipSet && fClips.back() != fClip)) { return true; } diff --git a/src/gpu/GrTesselatedPathRenderer.cpp b/src/gpu/GrTesselatedPathRenderer.cpp index b6612d1..5834dfd 100644 --- a/src/gpu/GrTesselatedPathRenderer.cpp +++ b/src/gpu/GrTesselatedPathRenderer.cpp @@ -471,7 +471,7 @@ FINISHED: if (count <= maxEdges) { // All edges fit; upload all edges and draw all verts as a fan fTarget->setVertexSourceToArray(layout, base, count); - fTarget->setEdgeAAData(&edges[0], count); + fTarget->drawState()->setEdgeAAData(&edges[0], count); fTarget->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count); } else { // Upload "maxEdges" edges and verts at a time, and draw as @@ -481,11 +481,11 @@ FINISHED: base[i] = base[0]; int size = GR_CT_MIN(count - i, maxEdges); fTarget->setVertexSourceToArray(layout, &base[i], size); - fTarget->setEdgeAAData(&edges[i], size); + fTarget->drawState()->setEdgeAAData(&edges[i], size); fTarget->drawNonIndexed(kTriangleFan_PrimitiveType, 0, size); } } - fTarget->setEdgeAAData(NULL, 0); + fTarget->drawState()->setEdgeAAData(NULL, 0); } else { fTarget->setVertexSourceToArray(layout, base, count); fTarget->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count); @@ -534,7 +534,7 @@ FINISHED: } // Draw the resulting polys and upload their edge data. - fTarget->enableState(GrDrawTarget::kEdgeAAConcave_StateBit); + fTarget->drawState()->enableState(GrDrawState::kEdgeAAConcave_StateBit); const GrPointArray& vertices = ptess.vertices(); const GrIndexArray& indices = ptess.indices(); const GrDrawState::Edge* edges = ptess.edges(); @@ -567,12 +567,13 @@ FINISHED: tri_edges[t++] = edge4; tri_edges[t++] = edge5; } - fTarget->setEdgeAAData(&tri_edges[0], t); + fTarget->drawState()->setEdgeAAData(&tri_edges[0], t); fTarget->setVertexSourceToArray(layout, &tri_verts[0], 3); fTarget->drawNonIndexed(kTriangles_PrimitiveType, 0, 3); } - fTarget->setEdgeAAData(NULL, 0); - fTarget->disableState(GrDrawTarget::kEdgeAAConcave_StateBit); + fTarget->drawState()->setEdgeAAData(NULL, 0); + fTarget->drawState()->disableState( + GrDrawState::kEdgeAAConcave_StateBit); return; } diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp index 4b78d4a..ef98487 100644 --- a/src/gpu/GrTextContext.cpp +++ b/src/gpu/GrTextContext.cpp @@ -25,6 +25,7 @@ enum { void GrTextContext::flushGlyphs() { if (fCurrVertex > 0) { GrDrawTarget::AutoStateRestore asr(fDrawTarget); + GrDrawState* drawState = fDrawTarget->drawState(); // setup our sampler state for our text texture/atlas GrSamplerState::Filter filter; @@ -41,6 +42,7 @@ void GrTextContext::flushGlyphs() { int nIndices = fCurrVertex + (fCurrVertex >> 1); GrAssert(fCurrTexture); fDrawTarget->setTexture(kGlyphMaskStage, fCurrTexture); + drawState->setTexture(kGlyphMaskStage, fCurrTexture); if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { if (kOne_BlendCoeff != fPaint.fSrcBlendCoeff || @@ -49,15 +51,15 @@ void GrTextContext::flushGlyphs() { GrPrintf("LCD Text will not draw correctly.\n"); } // setup blend so that we get mask * paintColor + (1-mask)*dstColor - fDrawTarget->setBlendConstant(fPaint.fColor); - fDrawTarget->setBlendFunc(kConstC_BlendCoeff, kISC_BlendCoeff); + drawState->setBlendConstant(fPaint.fColor); + drawState->setBlendFunc(kConstC_BlendCoeff, kISC_BlendCoeff); // don't modulate by the paint's color in the frag since we're // already doing it via the blend const. - fDrawTarget->setColor(0xffffffff); + drawState->setColor(0xffffffff); } else { // set back to normal in case we took LCD path previously. - fDrawTarget->setBlendFunc(fPaint.fSrcBlendCoeff, fPaint.fDstBlendCoeff); - fDrawTarget->setColor(fPaint.fColor); + drawState->setBlendFunc(fPaint.fSrcBlendCoeff, fPaint.fDstBlendCoeff); + drawState->setColor(fPaint.fColor); } fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); -- 2.7.4