From 8f9cbd62ec108d410b91155dcf6a4789c641246f Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Fri, 9 Dec 2011 15:55:34 +0000 Subject: [PATCH] Cleanup of r2830. git-svn-id: http://skia.googlecode.com/svn/trunk@2841 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/gpu/GrAAHairLinePathRenderer.cpp | 24 +- src/gpu/GrContext.cpp | 216 ++++----- src/gpu/GrDefaultPathRenderer.cpp | 34 +- src/gpu/GrDrawState.h | 645 +++++++++++++++++++++++++-- src/gpu/GrDrawTarget.cpp | 186 ++------ src/gpu/GrDrawTarget.h | 384 +--------------- src/gpu/GrGpu.cpp | 40 +- src/gpu/GrGpu.h | 4 +- src/gpu/GrGpuGL.cpp | 216 ++++----- src/gpu/GrGpuGLShaders.cpp | 191 ++++---- src/gpu/GrGpuGLShaders.h | 2 + src/gpu/GrInOrderDrawBuffer.cpp | 31 +- src/gpu/GrTesselatedPathRenderer.cpp | 36 +- src/gpu/GrTextContext.cpp | 12 +- 14 files changed, 1070 insertions(+), 951 deletions(-) diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp index e306b676b0..29db9aa543 100644 --- a/src/gpu/GrAAHairLinePathRenderer.cpp +++ b/src/gpu/GrAAHairLinePathRenderer.cpp @@ -602,8 +602,8 @@ void add_line(const SkPoint p[2], } bool GrAAHairLinePathRenderer::createGeom(GrDrawState::StageMask stageMask) { - - int rtHeight = fTarget->getRenderTarget()->height(); + const GrDrawState& drawState = fTarget->getDrawState(); + int rtHeight = drawState.getRenderTarget()->height(); GrIRect clip; if (fTarget->getClip().hasConservativeBounds()) { @@ -617,7 +617,7 @@ bool GrAAHairLinePathRenderer::createGeom(GrDrawState::StageMask stageMask) { // have changed since last previous path draw then we can reuse the // previous geoemtry. if (stageMask == fPreviousStages && - fPreviousViewMatrix == fTarget->getViewMatrix() && + fPreviousViewMatrix == drawState.getViewMatrix() && fPreviousTranslate == fTranslate && rtHeight == fPreviousRTHeight && fClipRect == clip) { @@ -631,7 +631,7 @@ bool GrAAHairLinePathRenderer::createGeom(GrDrawState::StageMask stageMask) { } } - GrMatrix viewM = fTarget->getViewMatrix(); + GrMatrix viewM = drawState.getViewMatrix(); PREALLOC_PTARRAY(128) lines; PREALLOC_PTARRAY(128) quads; @@ -672,7 +672,7 @@ bool GrAAHairLinePathRenderer::createGeom(GrDrawState::StageMask stageMask) { } fPreviousStages = stageMask; - fPreviousViewMatrix = fTarget->getViewMatrix(); + fPreviousViewMatrix = drawState.getViewMatrix(); fPreviousRTHeight = rtHeight; fClipRect = clip; fPreviousTranslate = fTranslate; @@ -685,14 +685,16 @@ void GrAAHairLinePathRenderer::drawPath(GrDrawState::StageMask stageMask) { return; } + GrDrawState* drawState = fTarget->drawState(); + GrDrawTarget::AutoStateRestore asr; - if (!fTarget->getViewMatrix().hasPerspective()) { + if (!drawState->getViewMatrix().hasPerspective()) { asr.set(fTarget); GrMatrix ivm; - if (fTarget->getViewInverse(&ivm)) { - fTarget->preConcatSamplerMatrices(stageMask, ivm); + if (drawState->getViewInverse(&ivm)) { + drawState->preConcatSamplerMatrices(stageMask, ivm); } - fTarget->setViewMatrix(GrMatrix::I()); + drawState->setViewMatrix(GrMatrix::I()); } // TODO: See whether rendering lines as degenerate quads improves perf @@ -702,7 +704,7 @@ void GrAAHairLinePathRenderer::drawPath(GrDrawState::StageMask stageMask) { int nBufLines = fLinesIndexBuffer->maxQuads(); while (lines < fLineSegmentCnt) { int n = GrMin(fLineSegmentCnt-lines, nBufLines); - fTarget->setVertexEdgeType(GrDrawState::kHairLine_EdgeType); + drawState->setVertexEdgeType(GrDrawState::kHairLine_EdgeType); fTarget->drawIndexed(kTriangles_PrimitiveType, kVertsPerLineSeg*lines, // startV 0, // startI @@ -715,7 +717,7 @@ void GrAAHairLinePathRenderer::drawPath(GrDrawState::StageMask stageMask) { int quads = 0; while (quads < fQuadCnt) { int n = GrMin(fQuadCnt-quads, kNumQuadsInIdxBuffer); - fTarget->setVertexEdgeType(GrDrawState::kHairQuad_EdgeType); + 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 de80f654a7..f455984313 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -218,20 +218,22 @@ void gen_stencil_key_values(const GrStencilBuffer* sb, // 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); + GrDrawState* drawState = target->drawState(); + + drawState->setViewMatrix(GrMatrix::I()); + drawState->setColorFilter(0, SkXfermode::kDst_Mode); + drawState->disableState(GrDrawState::kDither_StateBit | + GrDrawState::kHWAntialias_StateBit | + GrDrawState::kClip_StateBit | + GrDrawState::kNoColorWrites_StateBit | + GrDrawState::kEdgeAAConcave_StateBit); + drawState->setEdgeAAData(NULL, 0); + drawState->disableStencil(); + drawState->setAlpha(0xFF); target->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff); - target->setFirstCoverageStage(GrDrawState::kNumStages); - target->setDrawFace(GrDrawState::kBoth_DrawFace); + drawState->setFirstCoverageStage(GrDrawState::kNumStages); + drawState->setDrawFace(GrDrawState::kBoth_DrawFace); } } @@ -353,9 +355,9 @@ GrContext::TextureCacheEntry GrContext::createAndLockTexture(TextureKey key, if (NULL != texture) { GrDrawTarget::AutoStateRestore asr(fGpu); reset_target_state(fGpu); - - fGpu->setRenderTarget(texture->asRenderTarget()); - fGpu->setTexture(0, clampEntry.texture()); + GrDrawState* drawState = fGpu->drawState(); + drawState->setRenderTarget(texture->asRenderTarget()); + drawState->setTexture(0, clampEntry.texture()); GrSamplerState::Filter filter; // if filtering is not desired then we want to ensure all @@ -368,7 +370,7 @@ GrContext::TextureCacheEntry GrContext::createAndLockTexture(TextureKey key, } GrSamplerState stretchSampler(GrSamplerState::kClamp_WrapMode, filter); - fGpu->setSamplerState(0, stretchSampler); + drawState->setSampler(0, stretchSampler); static const GrVertexLayout layout = GrDrawTarget::StageTexCoordVertexLayoutBit(0,0); @@ -601,7 +603,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) { @@ -624,22 +626,24 @@ void GrContext::drawPaint(const GrPaint& paint) { r.setLTRB(0, 0, GrIntToScalar(getRenderTarget()->width()), GrIntToScalar(getRenderTarget()->height())); - GrAutoMatrix am; GrMatrix inverse; SkTLazy tmpPaint; const GrPaint* p = &paint; + GrDrawState* drawState = fGpu->drawState(); + GrAutoMatrix am; + // We attempt to map r by the inverse matrix and draw that. mapRect will // map the four corners and bound them with a new rect. This will not // produce a correct result for some perspective matrices. if (!this->getMatrix().hasPerspective()) { - if (!fGpu->getViewInverse(&inverse)) { + if (!drawState->getViewInverse(&inverse)) { GrPrintf("Could not invert matrix"); return; } inverse.mapRect(&r); } else { if (paint.getActiveMaskStageMask() || paint.getActiveStageMask()) { - if (!fGpu->getViewInverse(&inverse)) { + if (!drawState->getViewInverse(&inverse)) { GrPrintf("Could not invert matrix"); return; } @@ -697,7 +701,7 @@ bool GrContext::doOffscreenAA(GrDrawTarget* target, (!PREFER_MSAA_OFFSCREEN_AA || !fGpu->getCaps().fFSAASupport)) { return false; } - if (target->getRenderTarget()->isMultisampled()) { + if (target->getDrawState().getRenderTarget()->isMultisampled()) { return false; } if (disable_coverage_aa_for_blend(target)) { @@ -801,19 +805,20 @@ void GrContext::setupOffscreenAAPass1(GrDrawTarget* target, GrPaint tempPaint; tempPaint.reset(); this->setPaint(tempPaint, target); - target->setRenderTarget(offRT0); + GrDrawState* drawState = target->drawState(); + drawState->setRenderTarget(offRT0); #if PREFER_MSAA_OFFSCREEN_AA - target->enableState(GrDrawTarget::kHWAntialias_StateBit); + target->enableState(GrDrawState::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); + drawState->viewMatrix()->postConcat(transM); GrMatrix scaleM; scaleM.setScale(record->fScale * GR_Scalar1, record->fScale * GR_Scalar1); - target->postConcatViewMatrix(scaleM); + drawState->viewMatrix()->postConcat(scaleM); int w = (tileX == record->fTileCountX-1) ? boundRect.fRight - left : record->fTileSizeX; @@ -872,19 +877,21 @@ void GrContext::doOffscreenAAPass2(GrDrawTarget* target, kOffscreenStage = GrPaint::kTotalStages, }; + GrDrawState* drawState = target->drawState(); + if (OffscreenRecord::k4x4TwoPass_Downsample == record->fDownsample) { GrAssert(NULL != record->fOffscreen1.texture()); scale = 2; GrRenderTarget* dst = record->fOffscreen1.texture()->asRenderTarget(); - + // Do 2x2 downsample from first to second - target->setTexture(kOffscreenStage, src); - target->setRenderTarget(dst); - target->setViewMatrix(GrMatrix::I()); + drawState->setTexture(kOffscreenStage, src); + drawState->setRenderTarget(dst); + drawState->setViewMatrix(GrMatrix::I()); sampleM.setScale(scale * GR_Scalar1 / src->width(), scale * GR_Scalar1 / src->height()); sampler.setMatrix(sampleM); - target->setSamplerState(kOffscreenStage, sampler); + drawState->setSampler(kOffscreenStage, sampler); GrRect rect = SkRect::MakeWH(SkIntToScalar(scale * tileRect.width()), SkIntToScalar(scale * tileRect.height())); target->drawSimpleRect(rect, NULL, 1 << kOffscreenStage); @@ -911,24 +918,22 @@ void GrContext::doOffscreenAAPass2(GrDrawTarget* target, if (stageMask) { GrMatrix invVM; - if (target->getViewInverse(&invVM)) { - target->preConcatSamplerMatrices(stageMask, invVM); + if (drawState->getViewInverse(&invVM)) { + drawState->preConcatSamplerMatrices(stageMask, invVM); } } // This is important when tiling, otherwise second tile's // pass 1 view matrix will be incorrect. - GrDrawTarget::AutoViewMatrixRestore avmr(target); + GrDrawState::AutoViewMatrixRestore avmr(drawState, GrMatrix::I()); - target->setViewMatrix(GrMatrix::I()); - - target->setTexture(kOffscreenStage, src); + drawState->setTexture(kOffscreenStage, src); sampleM.setScale(scale * GR_Scalar1 / src->width(), scale * GR_Scalar1 / src->height()); sampler.setMatrix(sampleM); sampleM.setTranslate(SkIntToScalar(-tileRect.fLeft), SkIntToScalar(-tileRect.fTop)); sampler.preConcatMatrix(sampleM); - target->setSamplerState(kOffscreenStage, sampler); + drawState->setSampler(kOffscreenStage, sampler); GrRect dstRect; int stages = (1 << kOffscreenStage) | stageMask; @@ -1040,7 +1045,7 @@ static GrVertexLayout aa_rect_layout(const GrDrawTarget* target, bool useCoverage) { GrVertexLayout layout = 0; for (int s = 0; s < GrDrawState::kNumStages; ++s) { - if (NULL != target->getTexture(s)) { + if (NULL != target->getDrawState().getTexture(s)) { layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s); } } @@ -1087,7 +1092,7 @@ void GrContext::fillAARect(GrDrawTarget* target, if (useVertexCoverage) { innerColor = 0xffffffff; } else { - innerColor = target->getColor(); + innerColor = target->getDrawState().getColor(); } verts += 4 * vsize; @@ -1158,7 +1163,7 @@ void GrContext::strokeAARect(GrDrawTarget* target, if (useVertexCoverage) { innerColor = 0xffffffff; } else { - innerColor = target->getColor(); + innerColor = target->getDrawState().getColor(); } verts += 4 * vsize; for (int i = 0; i < 8; ++i) { @@ -1214,8 +1219,8 @@ static bool apply_aa_to_rect(GrDrawTarget* target, return false; } } - - if (target->getRenderTarget()->isMultisampled()) { + const GrDrawState& drawState = target->getDrawState(); + if (drawState.getRenderTarget()->isMultisampled()) { return false; } @@ -1223,7 +1228,7 @@ static bool apply_aa_to_rect(GrDrawTarget* target, return false; } - if (!target->getViewMatrix().preservesAxisAlignment()) { + if (!drawState.getViewMatrix().preservesAxisAlignment()) { return false; } @@ -1232,7 +1237,7 @@ static bool apply_aa_to_rect(GrDrawTarget* target, return false; } - *combinedMatrix = target->getViewMatrix(); + *combinedMatrix = drawState.getViewMatrix(); if (NULL != matrix) { combinedMatrix->preConcat(*matrix); GrAssert(combinedMatrix->preservesAxisAlignment()); @@ -1267,14 +1272,7 @@ void GrContext::drawRect(const GrPaint& paint, &useVertexCoverage); if (doAA) { - GrDrawTarget::AutoViewMatrixRestore avm(target); - if (stageMask) { - GrMatrix inv; - if (combinedMatrix.invert(&inv)) { - target->preConcatSamplerMatrices(stageMask, inv); - } - } - target->setViewMatrix(GrMatrix::I()); + GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask); if (width >= 0) { GrVec strokeSize;; if (width > 0) { @@ -1324,16 +1322,17 @@ void GrContext::drawRect(const GrPaint& paint, vertex[4].set(rect.fLeft, rect.fTop); } - GrDrawTarget::AutoViewMatrixRestore avmr; + GrDrawState::AutoViewMatrixRestore avmr; if (NULL != matrix) { - avmr.set(target); - target->preConcatViewMatrix(*matrix); - target->preConcatSamplerMatrices(stageMask, *matrix); + GrDrawState* drawState = target->drawState(); + avmr.set(drawState); + drawState->preConcatViewMatrix(*matrix); + drawState->preConcatSamplerMatrices(stageMask, *matrix); } target->drawNonIndexed(primType, 0, vertCount); } else { - #if GR_STATIC_RECT_VB +#if GR_STATIC_RECT_VB GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL); const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer(); if (NULL == sqVB) { @@ -1341,7 +1340,8 @@ void GrContext::drawRect(const GrPaint& paint, return; } target->setVertexSourceToBuffer(layout, sqVB); - GrDrawTarget::AutoViewMatrixRestore avmr(target); + GrDrawState* drawState = target->drawState(); + GrDrawState::AutoViewMatrixRestore avmr(drawState); GrMatrix m; m.setAll(rect.width(), 0, rect.fLeft, 0, rect.height(), rect.fTop, @@ -1350,14 +1350,13 @@ void GrContext::drawRect(const GrPaint& paint, if (NULL != matrix) { m.postConcat(*matrix); } - - target->preConcatViewMatrix(m); - target->preConcatSamplerMatrices(stageMask, m); + drawState->preConcatViewMatrix(m); + drawState->preConcatSamplerMatrices(stageMask, m); target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4); - #else +#else target->drawSimpleRect(rect, matrix, stageMask); - #endif +#endif } } @@ -1378,9 +1377,9 @@ 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); + GrDrawState::AutoViewMatrixRestore avmr(drawState); GrMatrix m; @@ -1390,13 +1389,13 @@ void GrContext::drawRectToRect(const GrPaint& paint, if (NULL != dstMatrix) { m.postConcat(*dstMatrix); } - target->preConcatViewMatrix(m); + drawState->preConcatViewMatrix(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 +1404,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) { @@ -1553,10 +1552,9 @@ void GrContext::drawPath(const GrPaint& paint, const GrPath& path, if (doOSAA) { bool needsStencil = pr->requiresStencilPass(target, path, fill); - + const GrRenderTarget* rt = target->getDrawState().getRenderTarget(); // compute bounds as intersection of rt size, clip, and path - GrIRect bound = SkIRect::MakeWH(target->getRenderTarget()->width(), - target->getRenderTarget()->height()); + GrIRect bound = SkIRect::MakeWH(rt->width(), rt->height()); GrIRect clipIBounds; if (target->getClip().hasConservativeBounds()) { target->getClip().getConservativeBounds().roundOut(&clipIBounds); @@ -1564,13 +1562,13 @@ void GrContext::drawPath(const GrPaint& paint, const GrPath& path, return; } } - GrRect pathBounds = path.getBounds(); if (!pathBounds.isEmpty()) { if (NULL != translate) { pathBounds.offset(*translate); } - target->getViewMatrix().mapRect(&pathBounds, pathBounds); + target->getDrawState().getViewMatrix().mapRect(&pathBounds, + pathBounds); GrIRect pathIBounds; pathBounds.roundOut(&pathIBounds); if (!bound.intersect(pathIBounds)) { @@ -1706,7 +1704,7 @@ bool GrContext::internalReadRenderTargetPixels(GrRenderTarget* target, ASSERT_OWNED_RESOURCE(target); if (NULL == target) { - target = fGpu->getRenderTarget(); + target = fGpu->drawState()->getRenderTarget(); if (NULL == target) { return false; } @@ -1782,8 +1780,8 @@ bool GrContext::internalReadRenderTargetPixels(GrRenderTarget* target, GrDrawTarget::AutoStateRestore asr(fGpu); reset_target_state(fGpu); - - fGpu->setRenderTarget(target); + GrDrawState* drawState = fGpu->drawState(); + drawState->setRenderTarget(target); GrMatrix matrix; if (flipY) { @@ -1799,8 +1797,8 @@ bool GrContext::internalReadRenderTargetPixels(GrRenderTarget* target, GrSamplerState::kNearest_Filter, matrix); sampler.setRAndBSwap(swapRAndB); - fGpu->setSamplerState(0, sampler); - fGpu->setTexture(0, src); + drawState->setSampler(0, sampler); + drawState->setTexture(0, src); GrRect rect; rect.setXYWH(0, 0, SK_Scalar1 * width, SK_Scalar1 * height); fGpu->drawSimpleRect(rect, NULL, 0x1); @@ -1820,14 +1818,15 @@ void GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst) { GrDrawTarget::AutoStateRestore asr(fGpu); reset_target_state(fGpu); - fGpu->setRenderTarget(dst); + GrDrawState* drawState = fGpu->drawState(); + drawState->setRenderTarget(dst); GrSamplerState sampler(GrSamplerState::kClamp_WrapMode, GrSamplerState::kNearest_Filter); GrMatrix sampleM; sampleM.setIDiv(src->width(), src->height()); sampler.setMatrix(sampleM); - fGpu->setTexture(0, src); - fGpu->setSamplerState(0, sampler); + drawState->setTexture(0, src); + drawState->setSampler(0, sampler); SkRect rect = SkRect::MakeXYWH(0, 0, src->width(), src->height()); fGpu->drawSimpleRect(rect, NULL, 1 << 0); } @@ -1843,7 +1842,7 @@ void GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target, ASSERT_OWNED_RESOURCE(target); if (NULL == target) { - target = fGpu->getRenderTarget(); + target = fGpu->drawState()->getRenderTarget(); if (NULL == target) { return; } @@ -1890,12 +1889,13 @@ void GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target, GrDrawTarget::AutoStateRestore asr(fGpu); reset_target_state(fGpu); + GrDrawState* drawState = fGpu->drawState(); GrMatrix matrix; matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top)); - fGpu->setViewMatrix(matrix); - fGpu->setRenderTarget(target); - fGpu->setTexture(0, texture); + drawState->setViewMatrix(matrix); + drawState->setRenderTarget(target); + drawState->setTexture(0, texture); matrix.setIDiv(texture->width(), texture->height()); GrSamplerState sampler; @@ -1903,7 +1903,7 @@ void GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target, GrSamplerState::kNearest_Filter, matrix); sampler.setRAndBSwap(swapRAndB); - fGpu->setSamplerState(0, sampler); + drawState->setSampler(0, sampler); GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0); static const int VCOUNT = 4; @@ -1919,37 +1919,38 @@ 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)); + drawState->setTexture(s, paint.getTexture(i)); ASSERT_OWNED_RESOURCE(paint.getTexture(i)); - target->setSamplerState(s, paint.getTextureSampler(i)); + drawState->setSampler(s, paint.getTextureSampler(i)); } - target->setFirstCoverageStage(GrPaint::kFirstMaskStage); + drawState->setFirstCoverageStage(GrPaint::kFirstMaskStage); for (int i = 0; i < GrPaint::kMaxMasks; ++i) { int s = i + GrPaint::kFirstMaskStage; - target->setTexture(s, paint.getMask(i)); + drawState->setTexture(s, paint.getMask(i)); ASSERT_OWNED_RESOURCE(paint.getMask(i)); - target->setSamplerState(s, paint.getMaskSampler(i)); + drawState->setSampler(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->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode); if (paint.getActiveMaskStageMask() && !target->canApplyCoverage()) { GrPrintf("Partial pixel coverage will be incorrectly blended.\n"); @@ -2000,27 +2001,27 @@ GrPathRenderer* GrContext::getPathRenderer(const GrPath& path, void GrContext::setRenderTarget(GrRenderTarget* target) { ASSERT_OWNED_RESOURCE(target); this->flush(false); - fGpu->setRenderTarget(target); + fGpu->drawState()->setRenderTarget(target); } GrRenderTarget* GrContext::getRenderTarget() { - return fGpu->getRenderTarget(); + return fGpu->drawState()->getRenderTarget(); } const GrRenderTarget* GrContext::getRenderTarget() const { - return fGpu->getRenderTarget(); + return fGpu->getDrawState().getRenderTarget(); } const GrMatrix& GrContext::getMatrix() const { - return fGpu->getViewMatrix(); + return fGpu->getDrawState().getViewMatrix(); } void GrContext::setMatrix(const GrMatrix& m) { - fGpu->setViewMatrix(m); + fGpu->drawState()->setViewMatrix(m); } void GrContext::concatMatrix(const GrMatrix& m) const { - fGpu->preConcatViewMatrix(m); + fGpu->drawState()->preConcatViewMatrix(m); } static inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) { @@ -2149,10 +2150,11 @@ void GrContext::convolve(GrTexture* texture, sampler.setConvolutionParams(kernelWidth, kernel, imageIncrement); sampleM.setIDiv(texture->width(), texture->height()); sampler.setMatrix(sampleM); - fGpu->setSamplerState(0, sampler); - fGpu->setViewMatrix(GrMatrix::I()); - fGpu->setTexture(0, texture); - fGpu->setColor(0xFFFFFFFF); + GrDrawState* drawState = fGpu->drawState(); + drawState->setSampler(0, sampler); + drawState->setViewMatrix(GrMatrix::I()); + drawState->setTexture(0, texture); + drawState->setAlpha(0xFF); fGpu->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff); fGpu->drawSimpleRect(rect, NULL, 1 << 0); } diff --git a/src/gpu/GrDefaultPathRenderer.cpp b/src/gpu/GrDefaultPathRenderer.cpp index 197ee061dc..ebd0cc142d 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; @@ -384,9 +385,10 @@ FINISHED: void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask, bool stencilOnly) { - GrMatrix viewM = fTarget->getViewMatrix(); + GrMatrix viewM = fTarget->getDrawState().getViewMatrix(); 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 @@ -405,9 +407,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 +505,36 @@ 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->stencil() = *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 +544,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 90de1a3f7f..7526b9fe4f 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,433 @@ 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 fSamplerStates[stage]; + } + + /** + * Sets the sampler. This will be removed soon in favor of direct access. + */ + void setSampler(int stage, const GrSamplerState& sampler) { + GrAssert((unsigned)stage < kNumStages); + fSamplerStates[stage] = sampler; + } + + /** + * Writable pointer to a stage's sampler. + */ + GrSamplerState* sampler(int stage) { + GrAssert((unsigned)stage < kNumStages); + return fSamplerStates + 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) { + fSamplerStates[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; + } + + class AutoViewMatrixRestore : public ::GrNoncopyable { + public: + AutoViewMatrixRestore() : fDrawState(NULL) {} + AutoViewMatrixRestore(GrDrawState* ds, const GrMatrix& newMatrix) { + fDrawState = NULL; + this->set(ds, newMatrix); + } + AutoViewMatrixRestore(GrDrawState* ds) { + fDrawState = NULL; + this->set(ds); + } + ~AutoViewMatrixRestore() { + this->set(NULL, GrMatrix::I()); + } + void set(GrDrawState* ds, const GrMatrix& newMatrix) { + if (NULL != fDrawState) { + fDrawState->setViewMatrix(fSavedMatrix); + } + if (NULL != ds) { + fSavedMatrix = ds->getViewMatrix(); + ds->setViewMatrix(newMatrix); + } + fDrawState = ds; + } + void set(GrDrawState* ds) { + if (NULL != fDrawState) { + fDrawState->setViewMatrix(fSavedMatrix); + } + if (NULL != ds) { + fSavedMatrix = ds->getViewMatrix(); + } + fDrawState = ds; + } + private: + GrDrawState* fDrawState; + GrMatrix fSavedMatrix; }; - /** + /// @} + + /////////////////////////////////////////////////////////////////////////// + /// @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) { + fDrawState = NULL; + 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. @@ -65,6 +486,19 @@ struct GrDrawState { kHairQuad_EdgeType }; + /** + * 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 @@ -91,53 +525,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; - - // pedantic assertion that our ptrs will - // be NULL (0 ptr is mem addr 0) - GrAssert((intptr_t)(void*)NULL == 0LL); - - // default stencil setting should be disabled - GrAssert(fStencilSettings.isDisabled()); - 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; } - 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; + int getNumAAEdges() const { return fEdgeAANumEdges; } - GrStencilSettings fStencilSettings; - GrMatrix fViewMatrix; + const Edge* getAAEdges() const { return fEdgeAAEdges; } - // @{ 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]; + /////////////////////////////////////////////////////////////////////////// + /// @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, - // This field must be last; it will not be copied or compared - // if the corresponding fTexture[] is NULL. - GrSamplerState fSamplerStates[kNumStages]; + // Users of the class may add additional bits to the vector + kDummyStateBit, + kLastPublicStateBit = kDummyStateBit-1, + }; + + void resetStateFlags() { + fFlagBits = 0; + } + + /** + * Enable render state settings. + * + * @param flags bitfield of StateBits specifing the states to enable + */ + void enableState(uint32_t stateBits) { + fFlagBits |= stateBits; + } + + /** + * Disable render state settings. + * + * @param flags bitfield of StateBits specifing the states to disable + */ + void disableState(uint32_t stateBits) { + fFlagBits &= ~(stateBits); + } + + bool isDitherState() const { + return 0 != (fFlagBits & kDither_StateBit); + } + + bool isHWAntialiasState() const { + return 0 != (fFlagBits & kHWAntialias_StateBit); + } + + bool isClipState() const { + return 0 != (fFlagBits & kClip_StateBit); + } + + 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%. @@ -172,6 +699,33 @@ 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. + + VertexEdgeType fVertexEdgeType; + int fEdgeAANumEdges; + Edge fEdgeAAEdges[kMaxEdges]; + + // @} + // This field must be last; it will not be copied or compared + // if the corresponding fTexture[] is NULL. + GrSamplerState fSamplerStates[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 +738,3 @@ private: }; #endif - diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index 7a84262d20..aa5cf201d2 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -10,9 +10,10 @@ #include "GrDrawTarget.h" #include "GrGpuVertex.h" +#include "GrIndexBuffer.h" +#include "GrRenderTarget.h" #include "GrTexture.h" #include "GrVertexBuffer.h" -#include "GrIndexBuffer.h" namespace { @@ -455,119 +456,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; } @@ -800,12 +688,13 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex, } } #endif - if (NULL == this->getRenderTarget()) { + const GrDrawState& drawState = this->getDrawState(); + if (NULL == drawState.getRenderTarget()) { return false; } - if (GrPixelConfigIsUnpremultiplied(this->getRenderTarget()->config())) { - if (kOne_BlendCoeff != fCurrDrawState.fSrcBlend || - kZero_BlendCoeff != fCurrDrawState.fDstBlend) { + if (GrPixelConfigIsUnpremultiplied(drawState.getRenderTarget()->config())) { + if (kOne_BlendCoeff != drawState.getSrcBlendCoeff() || + kZero_BlendCoeff != drawState.getDstBlendCoeff()) { return false; } } @@ -817,8 +706,9 @@ 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(drawState.getTexture(s)->config()) && + GrSamplerState::kNearest_Filter != + drawState.getSampler(s).getFilter()) { return false; } } @@ -861,31 +751,33 @@ 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; } bool GrDrawTarget::srcAlphaWillBeOne() const { const GrVertexLayout& layout = this->getGeomSrc().fVertexLayout; + const GrDrawState& drawState = this->getDrawState(); // Check if per-vertex or constant color may have partial alpha if ((layout & kColor_VertexLayoutBit) || - 0xff != GrColorUnpackA(fCurrDrawState.fColor)) { + 0xff != GrColorUnpackA(drawState.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 != drawState.getColorFilterMode()) { return false; } // Check if a color stage could create a partial alpha - for (int s = 0; s < fCurrDrawState.fFirstCoverageStage; ++s) { + for (int s = 0; s < drawState.getFirstCoverageStage(); ++s) { if (StageWillBeUsed(s, layout, fCurrDrawState)) { - GrAssert(NULL != fCurrDrawState.fTextures[s]); - GrPixelConfig config = fCurrDrawState.fTextures[s]->config(); + GrAssert(NULL != drawState.getTexture(s)); + GrPixelConfig config = drawState.getTexture(s)->config(); if (!GrPixelConfigIsOpaque(config)) { return false; } @@ -900,17 +792,18 @@ GrDrawTarget::getBlendOpts(bool forceCoverage, GrBlendCoeff* dstCoeff) const { const GrVertexLayout& layout = this->getGeomSrc().fVertexLayout; + const GrDrawState& drawState = this->getDrawState(); GrBlendCoeff bogusSrcCoeff, bogusDstCoeff; if (NULL == srcCoeff) { srcCoeff = &bogusSrcCoeff; } - *srcCoeff = fCurrDrawState.fSrcBlend; + *srcCoeff = drawState.getSrcBlendCoeff(); if (NULL == dstCoeff) { dstCoeff = &bogusDstCoeff; } - *dstCoeff = fCurrDrawState.fDstBlend; + *dstCoeff = drawState.getDstBlendCoeff(); // We don't ever expect source coeffecients to reference the source GrAssert(kSA_BlendCoeff != *srcCoeff && @@ -923,7 +816,7 @@ GrDrawTarget::getBlendOpts(bool forceCoverage, kDC_BlendCoeff != *dstCoeff && kIDC_BlendCoeff != *dstCoeff); - if (SkToBool(kNoColorWrites_StateBit & fCurrDrawState.fFlagBits)) { + if (drawState.isColorWriteDisabled()) { *srcCoeff = kZero_BlendCoeff; *dstCoeff = kOne_BlendCoeff; } @@ -939,7 +832,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 (drawState.getStencil().doesWrite()) { if (fCaps.fShaderSupport) { return kDisableBlend_BlendOptFlag | kEmitTransBlack_BlendOptFlag; @@ -953,10 +846,10 @@ GrDrawTarget::getBlendOpts(bool forceCoverage, // check for coverage due to edge aa or coverage texture stage bool hasCoverage = forceCoverage || - fCurrDrawState.fEdgeAANumEdges > 0 || + drawState.getNumAAEdges() > 0 || (layout & kCoverage_VertexLayoutBit) || (layout & kEdge_VertexLayoutBit); - for (int s = fCurrDrawState.fFirstCoverageStage; + for (int s = drawState.getFirstCoverageStage(); !hasCoverage && s < GrDrawState::kNumStages; ++s) { if (StageWillBeUsed(s, layout, fCurrDrawState)) { @@ -1023,7 +916,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,15 +936,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; -} - //////////////////////////////////////////////////////////////////////////////// @@ -1174,32 +1058,34 @@ GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw( GrDrawTarget* target, GrDrawState::StageMask stageMask) { GrAssert(NULL != target); + GrDrawState* drawState = target->drawState(); fDrawTarget = target; - fViewMatrix = target->getViewMatrix(); + fViewMatrix = drawState->getViewMatrix(); fStageMask = stageMask; if (fStageMask) { GrMatrix invVM; if (fViewMatrix.invert(&invVM)) { for (int s = 0; s < GrDrawState::kNumStages; ++s) { if (fStageMask & (1 << s)) { - fSamplerMatrices[s] = target->getSamplerMatrix(s); + fSamplerMatrices[s] = drawState->getSampler(s).getMatrix(); } } - target->preConcatSamplerMatrices(fStageMask, invVM); + drawState->preConcatSamplerMatrices(fStageMask, invVM); } else { // sad trombone sound fStageMask = 0; } } - target->setViewMatrix(GrMatrix::I()); + drawState->setViewMatrix(GrMatrix::I()); } GrDrawTarget::AutoDeviceCoordDraw::~AutoDeviceCoordDraw() { - fDrawTarget->setViewMatrix(fViewMatrix); + GrDrawState* drawState = fDrawTarget->drawState(); + drawState->setViewMatrix(fViewMatrix); for (int s = 0; s < GrDrawState::kNumStages; ++s) { if (fStageMask & (1 << s)) { - fDrawTarget->setSamplerMatrix(s, fSamplerMatrices[s]); + drawState->sampler(s)->setMatrix(fSamplerMatrices[s]); } } } diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h index 4bd9eee777..262f72cde2 100644 --- a/src/gpu/GrDrawTarget.h +++ b/src/gpu/GrDrawTarget.h @@ -16,7 +16,6 @@ #include "GrDrawState.h" #include "GrMatrix.h" #include "GrRefCnt.h" -#include "GrRenderTarget.h" #include "GrSamplerState.h" #include "GrStencil.h" #include "GrTexture.h" @@ -57,62 +56,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(); @@ -140,285 +86,24 @@ 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); + const GrDrawState& getDrawState() const { return fCurrDrawState; } + GrDrawState* drawState() { return &fCurrDrawState; } - /** - * 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); + void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) { + this->drawState()->setBlendFunc(srcCoeff, dstCoeff); } /** - * 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 + * Shortcut for drawState()->preConcatSamplerMatrices() on all enabled + * stages * - * @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); + this->drawState()->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 +133,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,14 +140,6 @@ 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); - /** * Used to save and restore the GrGpu's drawing state */ @@ -888,39 +556,6 @@ public: //////////////////////////////////////////////////////////////////////////// - class AutoViewMatrixRestore : ::GrNoncopyable { - public: - AutoViewMatrixRestore() { - fDrawTarget = NULL; - } - - AutoViewMatrixRestore(GrDrawTarget* target) - : fDrawTarget(target), fMatrix(fDrawTarget->getViewMatrix()) { - GrAssert(NULL != target); - } - - void set(GrDrawTarget* target) { - GrAssert(NULL != target); - if (NULL != fDrawTarget) { - fDrawTarget->setViewMatrix(fMatrix); - } - fDrawTarget = target; - fMatrix = target->getViewMatrix(); - } - - ~AutoViewMatrixRestore() { - if (NULL != fDrawTarget) { - fDrawTarget->setViewMatrix(fMatrix); - } - } - - private: - GrDrawTarget* fDrawTarget; - GrMatrix fMatrix; - }; - - //////////////////////////////////////////////////////////////////////////// - /** * Sets the view matrix to I and preconcats all stage matrices enabled in * mask by the view inverse. Destructor undoes these changes. @@ -1279,7 +914,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 { diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index 1583630ecd..eb96c57b43 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -185,10 +185,8 @@ 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; + GrDrawState::AutoRenderTargetRestore artr(this->drawState(), rt); this->clearStencil(); - fCurrDrawState.fRenderTarget = oldRT; return true; } else { return false; @@ -230,7 +228,7 @@ GrIndexBuffer* GrGpu::createIndexBuffer(uint32_t size, bool dynamic) { } void GrGpu::clear(const GrIRect* rect, GrColor color) { - if (NULL == this->getRenderTarget()) { + if (NULL == this->getDrawState().getRenderTarget()) { return; } this->handleDirtyContext(); @@ -530,16 +528,18 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { const GrIRect* r = NULL; GrIRect clipRect; - // GrDrawTarget should have filtered this for us - GrAssert(NULL != fCurrDrawState.fRenderTarget); + GrDrawState* drawState = this->drawState(); + const GrRenderTarget* rt = drawState->getRenderTarget(); - if (fCurrDrawState.fFlagBits & kClip_StateBit) { - GrRenderTarget& rt = *fCurrDrawState.fRenderTarget; + // GrDrawTarget should have filtered this for us + GrAssert(NULL != rt); + + if (drawState->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 +560,15 @@ 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; } 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 @@ -580,12 +580,12 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { AutoStateRestore asr(this); AutoGeometryPush agp(this); - this->setViewMatrix(GrMatrix::I()); + drawState->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 +606,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 +664,11 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) { }; SET_RANDOM_COLOR if (kRect_ClipType == clip.getElementType(c)) { - this->setStencil(gDrawToStencil); + *drawState->stencil() = gDrawToStencil; this->drawSimpleRect(clip.getRect(c), NULL, 0); } else { if (canRenderDirectToStencil) { - this->setStencil(gDrawToStencil); + *drawState->stencil() = gDrawToStencil; pr->drawPath(0); } else { pr->drawPathToStencil(); @@ -678,9 +678,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->stencil() = 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 11bf1539f1..11f50831ca 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -327,8 +327,8 @@ public: } protected: - enum PrivateStateBits { - kFirstBit = (kLastPublicStateBit << 1), + enum PrivateDrawStateStateBits { + 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 9f7e4ec0ad..2a8634f00c 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)); @@ -501,24 +501,22 @@ void GrGpuGL::onResetContext() { fActiveTextureUnitIdx = -1; // illegal values - //fHWDrawState.fSrcBlend = (GrBlendCoeff)(uint8_t)-1; - fHWDrawState.fSrcBlend = (GrBlendCoeff)0xFF; - fHWDrawState.fDstBlend = (GrBlendCoeff)(uint8_t)-1; + fHWDrawState.setBlendFunc((GrBlendCoeff)0xFF, (GrBlendCoeff)0xFF); - fHWDrawState.fBlendConstant = 0x00000000; + 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); + fHWDrawState.sampler(s)->setRadial2Params(-GR_ScalarMax, + -GR_ScalarMax, + true); + fHWDrawState.sampler(s)->setMatrix(GrMatrix::InvalidMatrix()); + fHWDrawState.sampler(s)->setConvolutionParams(0, NULL, NULL); } fHWBounds.fScissorRect.invalidate(); @@ -526,7 +524,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 +534,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 +1189,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 +1274,12 @@ GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) { } void GrGpuGL::flushScissor(const GrIRect* rect) { - GrAssert(NULL != fCurrDrawState.fRenderTarget); - const GrGLIRect& vp = - ((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport(); + const GrDrawState& drawState = this->getDrawState(); + const GrGLRenderTarget* rt = + static_cast(drawState.getRenderTarget()); + + GrAssert(NULL != rt); + const GrGLIRect& vp = rt->getViewport(); GrGLIRect scissor; if (NULL != rect) { @@ -1307,15 +1308,16 @@ void GrGpuGL::flushScissor(const GrIRect* rect) { } void GrGpuGL::onClear(const GrIRect* rect, GrColor color) { + const GrDrawState& drawState = this->getDrawState(); + const GrRenderTarget* rt = drawState.getRenderTarget(); // parent class should never let us get here with no RT - GrAssert(NULL != fCurrDrawState.fRenderTarget); + GrAssert(NULL != rt); 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 +1331,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 +1339,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->getDrawState().getRenderTarget()) { return; } @@ -1356,17 +1358,18 @@ 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); + const GrDrawState& drawState = this->getDrawState(); + const GrRenderTarget* rt = drawState.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 +1392,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 +1448,12 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target, // resolve the render target if necessary GrGLRenderTarget* tgt = static_cast(target); - GrAutoTPtrValueRestore autoTargetRestore; + GrDrawState::AutoRenderTargetRestore artr; switch (tgt->getResolveType()) { case GrGLRenderTarget::kCantResolve_ResolveType: return false; case GrGLRenderTarget::kAutoResolves_ResolveType: - autoTargetRestore.save(&fCurrDrawState.fRenderTarget); - fCurrDrawState.fRenderTarget = target; + artr.set(this->drawState(), target); this->flushRenderTarget(&GrIRect::EmptyIRect()); break; case GrGLRenderTarget::kCanResolve_ResolveType: @@ -1549,10 +1551,11 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target, void GrGpuGL::flushRenderTarget(const GrIRect* bound) { - GrAssert(NULL != fCurrDrawState.fRenderTarget); + GrGLRenderTarget* rt = + static_cast(this->drawState()->getRenderTarget()); + GrAssert(NULL != rt); - GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget; - if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) { + if (fHWDrawState.getRenderTarget() != rt) { GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID())); #if GR_COLLECT_STATS ++fStats.fRenderTargetChngCnt; @@ -1565,7 +1568,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 +1685,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 +1757,25 @@ 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 drawClipToStencil = + 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) != + drawClipToStencil); if (stencilChange) { - // we can't simultaneously perform stencil-clipping and modify the stencil clip - GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit)); + // we can't simultaneously perform stencil-clipping and + // modify the stencil clip + GrAssert(!stencilClip || !drawClipToStencil); if (settings->isDisabled()) { if (stencilClip) { @@ -1793,15 +1800,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,8 +1821,7 @@ void GrGpuGL::flushStencil() { unsigned int frontWriteMask = settings->fFrontWriteMask; GrGLenum frontFunc; - if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) { - + if (drawClipToStencil) { GrAssert(settings->fFrontFunc < kBasicStencilFuncCount); frontFunc = grToGLStencilFunc[settings->fFrontFunc]; } else { @@ -1847,7 +1852,7 @@ void GrGpuGL::flushStencil() { unsigned int backWriteMask = settings->fBackWriteMask; - if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) { + if (drawClipToStencil) { GrAssert(settings->fBackFunc < kBasicStencilFuncCount); backFunc = grToGLStencilFunc[settings->fBackFunc]; } else { @@ -1885,12 +1890,13 @@ void GrGpuGL::flushStencil() { grToGLStencilOp[settings->fFrontPassOp])); } } - fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings; + *fHWDrawState.stencil() = *settings; fHWStencilClip = stencilClip; } } void GrGpuGL::flushAAState(GrPrimitiveType type) { + const GrRenderTarget* rt = this->getDrawState().getRenderTarget(); if (kDesktop_GrGLBinding == this->glBinding()) { // ES doesn't support toggling GL_MULTISAMPLE and doesn't have // smooth lines. @@ -1906,13 +1912,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 +1939,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 +1960,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 blendConst = fCurrDrawState.getBlendConstant(); if ((BlendCoeffReferencesConstant(srcCoeff) || BlendCoeffReferencesConstant(dstCoeff)) && - fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) { + fHWDrawState.getBlendConstant() != blendConst) { float c[] = { - GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f, - GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f, - GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f, - GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f + GrColorUnpackR(blendConst) / 255.f, + GrColorUnpackG(blendConst) / 255.f, + GrColorUnpackB(blendConst) / 255.f, + GrColorUnpackA(blendConst) / 255.f }; GL_CALL(BlendColor(c[0], c[1], c[2], c[3])); - fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant; + fHWDrawState.setBlendConstant(blendConst); } } } @@ -2031,14 +2036,16 @@ void set_tex_swizzle(GrGLenum swizzle[4], const GrGLInterface* gl) { bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { + GrDrawState* drawState = this->drawState(); // GrGpu::setupClipAndFlushState should have already checked this // and bailed if not true. - GrAssert(NULL != fCurrDrawState.fRenderTarget); + GrAssert(NULL != drawState->getRenderTarget()); 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(drawState->getTexture(s)); // true for now, but maybe not with GrEffect. GrAssert(NULL != nextTexture); @@ -2052,20 +2059,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 = drawState->getSampler(s); ResetTimestamp timestamp; const GrGLTexture::TexParams& oldTexParams = nextTexture->getCachedTexParams(×tamp); @@ -2117,7 +2124,7 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { GrIRect* rect = NULL; GrIRect clipBounds; - if ((fCurrDrawState.fFlagBits & kClip_StateBit) && + if (drawState->isClipState() && fClip.hasConservativeBounds()) { fClip.getConservativeBounds().roundOut(&clipBounds); rect = &clipBounds; @@ -2125,19 +2132,18 @@ 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 (drawState->isDitherState() != fHWDrawState.isDitherState()) { + if (drawState->isDitherState()) { GL_CALL(Enable(GR_GL_DITHER)); } else { GL_CALL(Disable(GR_GL_DITHER)); } } - if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) != - (fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) { + if (drawState->isColorWriteDisabled() != + fHWDrawState.isColorWriteDisabled()) { GrGLenum mask; - if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) { + if (drawState->isColorWriteDisabled()) { mask = GR_GL_FALSE; } else { mask = GR_GL_TRUE; @@ -2145,8 +2151,8 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { GL_CALL(ColorMask(mask, mask, mask, mask)); } - if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) { - switch (fCurrDrawState.fDrawFace) { + if (fHWDrawState.getDrawFace() != drawState->getDrawFace()) { + switch (fCurrDrawState.getDrawFace()) { case GrDrawState::kCCW_DrawFace: GL_CALL(Enable(GR_GL_CULL_FACE)); GL_CALL(CullFace(GR_GL_BACK)); @@ -2161,24 +2167,26 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) { default: GrCrash("Unknown draw face."); } - fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace; + fHWDrawState.setDrawFace(drawState->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 == drawState->getRenderTarget() || + NULL == drawState->getTexture(s) || + drawState->getTexture(s)->asRenderTarget() != + drawState->getRenderTarget()); } #endif - flushStencil(); + this->flushStencil(); - // flushStencil may look at the private state bits, so keep it before this. - fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits; + // This copy must happen after flushStencil() is called. flushStencil() + // relies on detecting when the kModifyStencilClip_StateBit state has + // changed since the last draw. + fHWDrawState.copyStateFlags(*drawState); return true; } @@ -2210,22 +2218,24 @@ void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) { void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) { GrAssert(NULL != renderTarget); - if (fCurrDrawState.fRenderTarget == renderTarget) { - fCurrDrawState.fRenderTarget = NULL; + GrDrawState* drawState = this->drawState(); + if (drawState->getRenderTarget() == renderTarget) { + drawState->setRenderTarget(NULL); } - if (fHWDrawState.fRenderTarget == renderTarget) { - fHWDrawState.fRenderTarget = NULL; + if (fHWDrawState.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; + GrDrawState* drawState = this->drawState(); + if (drawState->getTexture(s) == texture) { + fCurrDrawState.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; + fHWDrawState.setTexture(s, NULL); } } } diff --git a/src/gpu/GrGpuGLShaders.cpp b/src/gpu/GrGpuGLShaders.cpp index 9018a4ee1c..5534d050bd 100644 --- a/src/gpu/GrGpuGLShaders.cpp +++ b/src/gpu/GrGpuGLShaders.cpp @@ -338,12 +338,33 @@ GrGpuGLShaders::~GrGpuGLShaders() { delete fProgramCache; } +const GrMatrix& GrGpuGLShaders::getHWViewMatrix() { + GrAssert(fProgramData); + + if (GrGLProgram::kSetAsAttribute == + fProgramData->fUniLocations.fViewMatrixUni) { + return fHWDrawState.getViewMatrix(); + } else { + return fProgramData->fViewMatrix; + } +} + +void GrGpuGLShaders::recordHWViewMatrix(const GrMatrix& matrix) { + GrAssert(fProgramData); + if (GrGLProgram::kSetAsAttribute == + fProgramData->fUniLocations.fViewMatrixUni) { + fHWDrawState.setViewMatrix(matrix); + } else { + fProgramData->fViewMatrix = matrix; + } +} + const GrMatrix& GrGpuGLShaders::getHWSamplerMatrix(int stage) { GrAssert(fProgramData); if (GrGLProgram::kSetAsAttribute == fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) { - return fHWDrawState.fSamplerStates[stage].getMatrix(); + return fHWDrawState.getSampler(stage).getMatrix(); } else { return fProgramData->fTextureMatrices[stage]; } @@ -353,7 +374,7 @@ void GrGpuGLShaders::recordHWSamplerMatrix(int stage, const GrMatrix& matrix) { GrAssert(fProgramData); 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 +409,53 @@ 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); + const GrMatrix& vm = this->getDrawState().getViewMatrix(); + if (GrGpuGLShaders::getHWViewMatrix() != vm) { - // 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]) - }; + const GrRenderTarget* rt = this->getDrawState().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, vm); - 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)); + // 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)); + } + this->recordHWViewMatrix(vm); } } void GrGpuGLShaders::flushTextureDomain(int s) { const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTexDomUni; + const GrDrawState& drawState = this->getDrawState(); if (GrGLProgram::kUnusedUniform != uni) { - const GrRect &texDom = - fCurrDrawState.fSamplerStates[s].getTextureDomain(); + const GrRect &texDom = drawState.getSampler(s).getTextureDomain(); if (((1 << s) & fDirtyFlags.fTextureChangedMask) || fProgramData->fTextureDomain[s] != texDom) { @@ -442,7 +469,8 @@ void GrGpuGLShaders::flushTextureDomain(int s) { GrScalarToFloat(texDom.bottom()) }; - GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; + const GrGLTexture* texture = + static_cast(drawState.getTexture(s)); GrGLTexture::Orientation orientation = texture->orientation(); // vertical flip if necessary @@ -461,19 +489,17 @@ void GrGpuGLShaders::flushTextureDomain(int s) { void GrGpuGLShaders::flushTextureMatrix(int s) { const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTextureMatrixUni; - GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; + const GrDrawState& drawState = this->getDrawState(); + const GrGLTexture* texture = + static_cast(drawState.getTexture(s)); if (NULL != texture) { if (GrGLProgram::kUnusedUniform != uni && (((1 << s) & fDirtyFlags.fTextureChangedMask) || - getHWSamplerMatrix(s) != getSamplerMatrix(s))) { + this->getHWSamplerMatrix(s) != drawState.getSampler(s).getMatrix())) { - GrAssert(NULL != fCurrDrawState.fTextures[s]); - - GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; - - GrMatrix m = getSamplerMatrix(s); - GrSamplerState::SampleMode mode = - fCurrDrawState.fSamplerStates[s].getSampleMode(); + GrMatrix m = drawState.getSampler(s).getMatrix(); + GrSamplerState::SampleMode mode = + drawState.getSampler(s).getSampleMode(); AdjustTextureMatrix(texture, mode, &m); // ES doesn't allow you to pass true to the transpose param, @@ -499,7 +525,7 @@ void GrGpuGLShaders::flushTextureMatrix(int s) { } else { GL_CALL(UniformMatrix3fv(uni, 1, false, mt)); } - recordHWSamplerMatrix(s, getSamplerMatrix(s)); + this->recordHWSamplerMatrix(s, drawState.getSampler(s).getMatrix()); } } } @@ -507,7 +533,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 = this->getDrawState().getSampler(s); if (GrGLProgram::kUnusedUniform != uni && (fProgramData->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() || fProgramData->fRadial2Radius0[s] != sampler.getRadial2Radius0() || @@ -539,7 +565,7 @@ void GrGpuGLShaders::flushRadial2(int s) { } void GrGpuGLShaders::flushConvolution(int s) { - const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s]; + const GrSamplerState& sampler = this->getDrawState().getSampler(s); int kernelUni = fProgramData->fUniLocations.fStages[s].fKernelUni; if (GrGLProgram::kUnusedUniform != kernelUni) { GL_CALL(Uniform1fv(kernelUni, sampler.getKernelWidth(), @@ -554,7 +580,8 @@ 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]; + const GrGLTexture* texture = + static_cast(this->getDrawState().getTexture(s)); if (texture->width() != fProgramData->fTextureWidth[s] || texture->height() != fProgramData->fTextureHeight[s]) { @@ -570,13 +597,13 @@ 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->getDrawState().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; @@ -596,19 +623,21 @@ static const float ONE_OVER_255 = 1.f / 255.f; void GrGpuGLShaders::flushColor(GrColor color) { const ProgramDesc& desc = fCurrentProgram.getDesc(); + const GrDrawState& drawState = this->getDrawState(); + 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: @@ -632,10 +661,10 @@ void GrGpuGLShaders::flushColor(GrColor color) { if (fProgramData->fUniLocations.fColorFilterUni != GrGLProgram::kUnusedUniform && fProgramData->fColorFilterColor - != fCurrDrawState.fColorFilterColor) { - float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColorFilterColor); + != drawState.getColorFilterColor()) { + float c[] = GR_COLOR_TO_VEC4(drawState.getColorFilterColor()); GL_CALL(Uniform4fv(fProgramData->fUniLocations.fColorFilterUni, 1, c)); - fProgramData->fColorFilterColor = fCurrDrawState.fColorFilterColor; + fProgramData->fColorFilterColor = drawState.getColorFilterColor(); } } @@ -645,10 +674,12 @@ bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) { return false; } + const GrDrawState& drawState = this->getDrawState(); + 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 +711,11 @@ bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) { } else if (blendOpts & kEmitCoverage_BlendOptFlag) { color = 0xffffffff; } else { - color = fCurrDrawState.fColor; + color = drawState.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); @@ -857,6 +877,7 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type, BlendOptFlags blendOpts, GrBlendCoeff dstCoeff) { ProgramDesc& desc = fCurrentProgram.fProgramDesc; + const GrDrawState& drawState = this->getDrawState(); // This should already have been caught GrAssert(!(kSkipDraw_BlendOptFlag & blendOpts)); @@ -885,7 +906,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 +918,7 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type, bool colorIsTransBlack = SkToBool(blendOpts & kEmitTransBlack_BlendOptFlag); bool colorIsSolidWhite = (blendOpts & kEmitCoverage_BlendOptFlag) || (!requiresAttributeColors && - 0xffffffff == fCurrDrawState.fColor); + 0xffffffff == drawState.getColor()); if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) { desc.fColorInput = ProgramDesc::kTransBlack_ColorInput; } else if (GR_AGGRESSIVE_SHADER_OPTS && colorIsSolidWhite) { @@ -908,16 +929,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 +949,20 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type, stage.fOptFlags = 0; stage.setEnabled(this->isStageEnabled(s)); - bool skip = s < fCurrDrawState.fFirstCoverageStage ? skipColor : + bool skip = s < drawState.getFirstCoverageStage() ? skipColor : skipCoverage; if (!skip && stage.isEnabled()) { lastEnabledStage = s; - GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; + const GrGLTexture* texture = + static_cast(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 (!sampler.getMatrix().hasPerspective()) { stage.fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; } switch (sampler.getSampleMode()) { @@ -1024,7 +1045,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 +1067,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/GrGpuGLShaders.h b/src/gpu/GrGpuGLShaders.h index baa5d9d907..36712963e8 100644 --- a/src/gpu/GrGpuGLShaders.h +++ b/src/gpu/GrGpuGLShaders.h @@ -46,6 +46,8 @@ private: class ProgramCache; // Helpers to make code more readable + const GrMatrix& getHWViewMatrix(); + void recordHWViewMatrix(const GrMatrix& matrix); const GrMatrix& getHWSamplerMatrix(int stage); void recordHWSamplerMatrix(int stage, const GrMatrix& matrix); diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp index 340cff18f3..cbe153cb7d 100644 --- a/src/gpu/GrInOrderDrawBuffer.cpp +++ b/src/gpu/GrInOrderDrawBuffer.cpp @@ -9,6 +9,7 @@ #include "GrInOrderDrawBuffer.h" +#include "GrRenderTarget.h" #include "GrTexture.h" #include "GrBufferAllocPool.h" #include "GrIndexBuffer.h" @@ -78,6 +79,8 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect, GrAssert(!(fDraws.empty() && fCurrQuad)); GrAssert(!(0 != fMaxQuads && NULL == fQuadIndexBuffer)); + GrDrawState* drawState = this->drawState(); + // if we have a quad IB then either append to the previous run of // rects or start a new run if (fMaxQuads) { @@ -89,9 +92,8 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect, GrPrintf("Failed to get space for vertices!\n"); return; } - AutoViewMatrixRestore avmr(this); - GrMatrix combinedMatrix = this->getViewMatrix(); - this->setViewMatrix(GrMatrix::I()); + GrMatrix combinedMatrix = drawState->getViewMatrix(); + GrDrawState::AutoViewMatrixRestore avmr(drawState, GrMatrix::I()); if (NULL != matrix) { combinedMatrix.preConcat(*matrix); } @@ -102,14 +104,14 @@ 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 (drawState->isClipState() && fClip.isRect()) { GrRect clipRect = fClip.getRect(0); // If the clip rect touches the edge of the viewport, extended it // out (close) to infinity to avoid bogus intersections. // We might consider a more exact clip to viewport if this // conservative test fails. - const GrRenderTarget* target = this->getRenderTarget(); + const GrRenderTarget* target = drawState->getRenderTarget(); if (0 >= clipRect.fLeft) { clipRect.fLeft = GR_ScalarMin; } @@ -132,7 +134,7 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect, } } if (insideClip) { - this->disableState(kClip_StateBit); + drawState->disableState(GrDrawState::kClip_StateBit); disabledClip = true; } } @@ -176,7 +178,7 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect, fLastRectVertexLayout = layout; } if (disabledClip) { - this->enableState(kClip_StateBit); + drawState->enableState(GrDrawState::kClip_StateBit); } } else { INHERITED::drawRect(rect, matrix, stageMask, srcRects, srcMatrices); @@ -310,8 +312,8 @@ void GrInOrderDrawBuffer::clear(const GrIRect* rect, GrColor color) { // the current render target. If we get that smart we have to make sure // those draws aren't read before this clear (render-to-texture). r.setLTRB(0, 0, - this->getRenderTarget()->width(), - this->getRenderTarget()->height()); + this->getDrawState().getRenderTarget()->width(), + this->getDrawState().getRenderTarget()->height()); rect = &r; } Clear& clr = fClears.push_back(); @@ -328,9 +330,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) { @@ -593,15 +595,16 @@ bool GrInOrderDrawBuffer::needsNewState() const { } void GrInOrderDrawBuffer::pushState() { + const GrDrawState& drawState = this->getDrawState(); for (int s = 0; s < GrDrawState::kNumStages; ++s) { - GrSafeRef(fCurrDrawState.fTextures[s]); + GrSafeRef(drawState.getTexture(s)); } - GrSafeRef(fCurrDrawState.fRenderTarget); + GrSafeRef(drawState.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 b6612d1d29..f7fd8e4039 100644 --- a/src/gpu/GrTesselatedPathRenderer.cpp +++ b/src/gpu/GrTesselatedPathRenderer.cpp @@ -12,6 +12,7 @@ #include "GrDrawState.h" #include "GrPathUtils.h" #include "GrPoint.h" +#include "GrRenderTarget.h" #include "GrTDArray.h" #include "SkTemplates.h" @@ -348,10 +349,11 @@ static size_t computeEdgesAndIntersect(const GrMatrix& matrix, void GrTesselatedPathRenderer::drawPath(GrDrawState::StageMask stageMask) { GrDrawTarget::AutoStateRestore asr(fTarget); + GrDrawState* drawState = fTarget->drawState(); // face culling doesn't make sense here - GrAssert(GrDrawState::kBoth_DrawFace == fTarget->getDrawFace()); + GrAssert(GrDrawState::kBoth_DrawFace == drawState->getDrawFace()); - GrMatrix viewM = fTarget->getViewMatrix(); + GrMatrix viewM = drawState->getViewMatrix(); GrScalar tol = GR_Scalar1; tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, fPath->getBounds()); @@ -433,12 +435,12 @@ FINISHED: if (inverted) { GrRect bounds; - GrAssert(NULL != fTarget->getRenderTarget()); + GrAssert(NULL != drawState->getRenderTarget()); bounds.setLTRB(0, 0, - GrIntToScalar(fTarget->getRenderTarget()->width()), - GrIntToScalar(fTarget->getRenderTarget()->height())); + GrIntToScalar(drawState->getRenderTarget()->width()), + GrIntToScalar(drawState->getRenderTarget()->height())); GrMatrix vmi; - if (fTarget->getViewInverse(&vmi)) { + if (drawState->getViewInverse(&vmi)) { vmi.mapRect(&bounds); } *vert++ = GrPoint::Make(bounds.fLeft, bounds.fTop); @@ -460,8 +462,8 @@ FINISHED: if (subpathCnt == 1 && !inverted && fPath->isConvex()) { if (fAntiAlias) { GrEdgeArray edges; - GrMatrix inverse, matrix = fTarget->getViewMatrix(); - fTarget->getViewInverse(&inverse); + GrMatrix inverse, matrix = drawState->getViewMatrix(); + drawState->getViewInverse(&inverse); count = computeEdgesAndIntersect(matrix, inverse, base, count, &edges, 0.0f); size_t maxEdges = fTarget->getMaxEdges(); @@ -471,7 +473,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); + 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 +483,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); + drawState->setEdgeAAData(&edges[i], size); fTarget->drawNonIndexed(kTriangleFan_PrimitiveType, 0, size); } } - fTarget->setEdgeAAData(NULL, 0); + drawState->setEdgeAAData(NULL, 0); } else { fTarget->setVertexSourceToArray(layout, base, count); fTarget->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count); @@ -498,8 +500,8 @@ FINISHED: GrBoundaryTess btess(count, fill_type_to_glu_winding_rule(fFill)); btess.addVertices(base, subpathVertCount, subpathCnt); - GrMatrix inverse, matrix = fTarget->getViewMatrix(); - if (!fTarget->getViewInverse(&inverse)) { + GrMatrix inverse, matrix = drawState->getViewMatrix(); + if (!drawState->getViewInverse(&inverse)) { return; } @@ -534,7 +536,7 @@ FINISHED: } // Draw the resulting polys and upload their edge data. - fTarget->enableState(GrDrawTarget::kEdgeAAConcave_StateBit); + drawState->enableState(GrDrawState::kEdgeAAConcave_StateBit); const GrPointArray& vertices = ptess.vertices(); const GrIndexArray& indices = ptess.indices(); const GrDrawState::Edge* edges = ptess.edges(); @@ -567,12 +569,12 @@ FINISHED: tri_edges[t++] = edge4; tri_edges[t++] = edge5; } - fTarget->setEdgeAAData(&tri_edges[0], t); + 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); + drawState->setEdgeAAData(NULL, 0); + drawState->disableState(GrDrawState::kEdgeAAConcave_StateBit); return; } diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp index 4b78d4a8c7..3b3841b293 100644 --- a/src/gpu/GrTextContext.cpp +++ b/src/gpu/GrTextContext.cpp @@ -25,7 +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; if (fExtMatrix.isIdentity()) { @@ -35,12 +35,12 @@ void GrTextContext::flushGlyphs() { } GrSamplerState sampler(GrSamplerState::kRepeat_WrapMode, filter); - fDrawTarget->setSamplerState(kGlyphMaskStage, sampler); + drawState->setSampler(kGlyphMaskStage, sampler); GrAssert(GrIsALIGN4(fCurrVertex)); 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 +49,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); + drawState->setBlendConstant(fPaint.fColor); fDrawTarget->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->setColor(fPaint.fColor); } fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());