Make GrDrawState a real class with getters and setters

Review URL: http://codereview.appspot.com/5448119/



git-svn-id: http://skia.googlecode.com/svn/trunk@2830 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
bsalomon@google.com 2011-12-08 15:53:53 +00:00
parent 590e798617
commit 0fec61d19c
13 changed files with 984 additions and 849 deletions

View File

@ -702,7 +702,8 @@ void GrAAHairLinePathRenderer::drawPath(GrDrawState::StageMask stageMask) {
int nBufLines = fLinesIndexBuffer->maxQuads(); int nBufLines = fLinesIndexBuffer->maxQuads();
while (lines < fLineSegmentCnt) { while (lines < fLineSegmentCnt) {
int n = GrMin(fLineSegmentCnt-lines, nBufLines); int n = GrMin(fLineSegmentCnt-lines, nBufLines);
fTarget->setVertexEdgeType(GrDrawState::kHairLine_EdgeType); fTarget->drawState()->setVertexEdgeType(
GrDrawState::kHairLine_EdgeType);
fTarget->drawIndexed(kTriangles_PrimitiveType, fTarget->drawIndexed(kTriangles_PrimitiveType,
kVertsPerLineSeg*lines, // startV kVertsPerLineSeg*lines, // startV
0, // startI 0, // startI
@ -715,7 +716,8 @@ void GrAAHairLinePathRenderer::drawPath(GrDrawState::StageMask stageMask) {
int quads = 0; int quads = 0;
while (quads < fQuadCnt) { while (quads < fQuadCnt) {
int n = GrMin(fQuadCnt-quads, kNumQuadsInIdxBuffer); int n = GrMin(fQuadCnt-quads, kNumQuadsInIdxBuffer);
fTarget->setVertexEdgeType(GrDrawState::kHairQuad_EdgeType); fTarget->drawState()->setVertexEdgeType(
GrDrawState::kHairQuad_EdgeType);
fTarget->drawIndexed(kTriangles_PrimitiveType, fTarget->drawIndexed(kTriangles_PrimitiveType,
4*fLineSegmentCnt + kVertsPerQuad*quads, // startV 4*fLineSegmentCnt + kVertsPerQuad*quads, // startV
0, // startI 0, // startI

View File

@ -217,21 +217,17 @@ void gen_stencil_key_values(const GrStencilBuffer* sb,
// It does not reset stage textures/samplers or per-vertex-edge-aa state since // It does not reset stage textures/samplers or per-vertex-edge-aa state since
// they aren't used unless the vertex layout references them. // they aren't used unless the vertex layout references them.
// It also doesn't set the render target. // It also doesn't set the render target.
void reset_target_state(GrDrawTarget* target){ void reset_target_state(GrDrawState* drawState) {
target->setViewMatrix(GrMatrix::I()); drawState->setViewMatrix(GrMatrix::I());
target->setColorFilter(0, SkXfermode::kDst_Mode); drawState->setColorFilter(0, SkXfermode::kDst_Mode);
target->disableState(GrDrawTarget::kDither_StateBit | drawState->resetStateFlags();
GrDrawTarget::kHWAntialias_StateBit | drawState->setEdgeAAData(NULL, 0);
GrDrawTarget::kClip_StateBit | drawState->disableStencil();
GrDrawTarget::kNoColorWrites_StateBit | drawState->setAlpha(0xFF);
GrDrawTarget::kEdgeAAConcave_StateBit); drawState->setBlendFunc(kOne_BlendCoeff,
target->setEdgeAAData(NULL, 0); kZero_BlendCoeff);
target->disableStencil(); drawState->setFirstCoverageStage(GrDrawState::kNumStages);
target->setAlpha(0xFF); drawState->setDrawFace(GrDrawState::kBoth_DrawFace);
target->setBlendFunc(kOne_BlendCoeff,
kZero_BlendCoeff);
target->setFirstCoverageStage(GrDrawState::kNumStages);
target->setDrawFace(GrDrawState::kBoth_DrawFace);
} }
} }
@ -352,7 +348,7 @@ GrContext::TextureCacheEntry GrContext::createAndLockTexture(TextureKey key,
if (NULL != texture) { if (NULL != texture) {
GrDrawTarget::AutoStateRestore asr(fGpu); GrDrawTarget::AutoStateRestore asr(fGpu);
reset_target_state(fGpu); reset_target_state(fGpu->drawState());
fGpu->setRenderTarget(texture->asRenderTarget()); fGpu->setRenderTarget(texture->asRenderTarget());
fGpu->setTexture(0, clampEntry.texture()); fGpu->setTexture(0, clampEntry.texture());
@ -601,7 +597,7 @@ const GrClip& GrContext::getClip() const { return fGpu->getClip(); }
void GrContext::setClip(const GrClip& clip) { void GrContext::setClip(const GrClip& clip) {
fGpu->setClip(clip); fGpu->setClip(clip);
fGpu->enableState(GrDrawTarget::kClip_StateBit); fGpu->drawState()->enableState(GrDrawState::kClip_StateBit);
} }
void GrContext::setClip(const GrIRect& rect) { void GrContext::setClip(const GrIRect& rect) {
@ -806,14 +802,13 @@ void GrContext::setupOffscreenAAPass1(GrDrawTarget* target,
target->enableState(GrDrawTarget::kHWAntialias_StateBit); target->enableState(GrDrawTarget::kHWAntialias_StateBit);
#endif #endif
GrMatrix transM;
int left = boundRect.fLeft + tileX * record->fTileSizeX; int left = boundRect.fLeft + tileX * record->fTileSizeX;
int top = boundRect.fTop + tileY * record->fTileSizeY; int top = boundRect.fTop + tileY * record->fTileSizeY;
transM.setTranslate(-left * GR_Scalar1, -top * GR_Scalar1); GrDrawState* drawState = target->drawState();
target->postConcatViewMatrix(transM); drawState->viewMatrix()->postTranslate(-left * GR_Scalar1,
GrMatrix scaleM; -top * GR_Scalar1);
scaleM.setScale(record->fScale * GR_Scalar1, record->fScale * GR_Scalar1); drawState->viewMatrix()->postScale(record->fScale * GR_Scalar1,
target->postConcatViewMatrix(scaleM); record->fScale * GR_Scalar1);
int w = (tileX == record->fTileCountX-1) ? boundRect.fRight - left : int w = (tileX == record->fTileCountX-1) ? boundRect.fRight - left :
record->fTileSizeX; record->fTileSizeX;
@ -1327,7 +1322,7 @@ void GrContext::drawRect(const GrPaint& paint,
GrDrawTarget::AutoViewMatrixRestore avmr; GrDrawTarget::AutoViewMatrixRestore avmr;
if (NULL != matrix) { if (NULL != matrix) {
avmr.set(target); avmr.set(target);
target->preConcatViewMatrix(*matrix); target->viewMatrix()->preConcat(*matrix);
target->preConcatSamplerMatrices(stageMask, *matrix); target->preConcatSamplerMatrices(stageMask, *matrix);
} }
@ -1351,7 +1346,7 @@ void GrContext::drawRect(const GrPaint& paint,
m.postConcat(*matrix); m.postConcat(*matrix);
} }
target->preConcatViewMatrix(m); target->viewMatrix()->preConcat(m);
target->preConcatSamplerMatrices(stageMask, m); target->preConcatSamplerMatrices(stageMask, m);
target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4); target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
@ -1378,7 +1373,8 @@ void GrContext::drawRectToRect(const GrPaint& paint,
#if GR_STATIC_RECT_VB #if GR_STATIC_RECT_VB
GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory); GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
GrDrawState* drawState = target->drawState();
GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL); GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
GrDrawTarget::AutoViewMatrixRestore avmr(target); GrDrawTarget::AutoViewMatrixRestore avmr(target);
@ -1390,13 +1386,13 @@ void GrContext::drawRectToRect(const GrPaint& paint,
if (NULL != dstMatrix) { if (NULL != dstMatrix) {
m.postConcat(*dstMatrix); m.postConcat(*dstMatrix);
} }
target->preConcatViewMatrix(m); drawState->viewMatrix()->preConcat(m);
// srcRect refers to first stage // srcRect refers to first stage
int otherStageMask = paint.getActiveStageMask() & int otherStageMask = paint.getActiveStageMask() &
(~(1 << GrPaint::kFirstTextureStage)); (~(1 << GrPaint::kFirstTextureStage));
if (otherStageMask) { if (otherStageMask) {
target->preConcatSamplerMatrices(otherStageMask, m); drawState->preConcatSamplerMatrices(otherStageMask, m);
} }
m.setAll(srcRect.width(), 0, srcRect.fLeft, m.setAll(srcRect.width(), 0, srcRect.fLeft,
@ -1405,7 +1401,7 @@ void GrContext::drawRectToRect(const GrPaint& paint,
if (NULL != srcMatrix) { if (NULL != srcMatrix) {
m.postConcat(*srcMatrix); m.postConcat(*srcMatrix);
} }
target->preConcatSamplerMatrix(GrPaint::kFirstTextureStage, m); drawState->sampler(GrPaint::kFirstTextureStage)->preConcatMatrix(m);
const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer(); const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
if (NULL == sqVB) { if (NULL == sqVB) {
@ -1781,7 +1777,7 @@ bool GrContext::internalReadRenderTargetPixels(GrRenderTarget* target,
GrAssert(NULL != target); GrAssert(NULL != target);
GrDrawTarget::AutoStateRestore asr(fGpu); GrDrawTarget::AutoStateRestore asr(fGpu);
reset_target_state(fGpu); reset_target_state(fGpu->drawState());
fGpu->setRenderTarget(target); fGpu->setRenderTarget(target);
@ -1819,7 +1815,7 @@ void GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst) {
ASSERT_OWNED_RESOURCE(src); ASSERT_OWNED_RESOURCE(src);
GrDrawTarget::AutoStateRestore asr(fGpu); GrDrawTarget::AutoStateRestore asr(fGpu);
reset_target_state(fGpu); reset_target_state(fGpu->drawState());
fGpu->setRenderTarget(dst); fGpu->setRenderTarget(dst);
GrSamplerState sampler(GrSamplerState::kClamp_WrapMode, GrSamplerState sampler(GrSamplerState::kClamp_WrapMode,
GrSamplerState::kNearest_Filter); GrSamplerState::kNearest_Filter);
@ -1889,7 +1885,7 @@ void GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target,
config, buffer, rowBytes, flags); config, buffer, rowBytes, flags);
GrDrawTarget::AutoStateRestore asr(fGpu); GrDrawTarget::AutoStateRestore asr(fGpu);
reset_target_state(fGpu); reset_target_state(fGpu->drawState());
GrMatrix matrix; GrMatrix matrix;
matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top)); matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
@ -1920,6 +1916,8 @@ void GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target,
void GrContext::setPaint(const GrPaint& paint, GrDrawTarget* target) { void GrContext::setPaint(const GrPaint& paint, GrDrawTarget* target) {
GrDrawState* drawState = target->drawState();
for (int i = 0; i < GrPaint::kMaxTextures; ++i) { for (int i = 0; i < GrPaint::kMaxTextures; ++i) {
int s = i + GrPaint::kFirstTextureStage; int s = i + GrPaint::kFirstTextureStage;
target->setTexture(s, paint.getTexture(i)); target->setTexture(s, paint.getTexture(i));
@ -1936,20 +1934,20 @@ void GrContext::setPaint(const GrPaint& paint, GrDrawTarget* target) {
target->setSamplerState(s, paint.getMaskSampler(i)); target->setSamplerState(s, paint.getMaskSampler(i));
} }
target->setColor(paint.fColor); drawState->setColor(paint.fColor);
if (paint.fDither) { if (paint.fDither) {
target->enableState(GrDrawTarget::kDither_StateBit); drawState->enableState(GrDrawState::kDither_StateBit);
} else { } else {
target->disableState(GrDrawTarget::kDither_StateBit); drawState->disableState(GrDrawState::kDither_StateBit);
} }
if (paint.fAntiAlias) { if (paint.fAntiAlias) {
target->enableState(GrDrawTarget::kHWAntialias_StateBit); drawState->enableState(GrDrawState::kHWAntialias_StateBit);
} else { } else {
target->disableState(GrDrawTarget::kHWAntialias_StateBit); drawState->disableState(GrDrawState::kHWAntialias_StateBit);
} }
target->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff); drawState->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
target->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode); drawState->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
if (paint.getActiveMaskStageMask() && !target->canApplyCoverage()) { if (paint.getActiveMaskStageMask() && !target->canApplyCoverage()) {
GrPrintf("Partial pixel coverage will be incorrectly blended.\n"); GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
@ -2020,7 +2018,7 @@ void GrContext::setMatrix(const GrMatrix& m) {
} }
void GrContext::concatMatrix(const GrMatrix& m) const { void GrContext::concatMatrix(const GrMatrix& m) const {
fGpu->preConcatViewMatrix(m); fGpu->viewMatrix()->preConcat(m);
} }
static inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) { static inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {

View File

@ -190,7 +190,8 @@ static inline bool single_pass_path(const GrDrawTarget& target,
return hint == kConvex_ConvexHint || return hint == kConvex_ConvexHint ||
hint == kNonOverlappingConvexPieces_ConvexHint || hint == kNonOverlappingConvexPieces_ConvexHint ||
(hint == kSameWindingConvexPieces_ConvexHint && (hint == kSameWindingConvexPieces_ConvexHint &&
!target.drawWillReadDst() && !target.isDitherState()); !target.drawWillReadDst() &&
!target.getDrawState().isDitherState());
} }
return false; return false;
@ -388,6 +389,8 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask,
GrScalar tol = GR_Scalar1; GrScalar tol = GR_Scalar1;
tol = GrPathUtils::scaleToleranceToSrc(tol, viewM, fPath->getBounds()); 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 // 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 // layout. We only do that because the GrDrawTarget API doesn't allow
// us to change the vertex layout after reserveVertexSpace(). We won't // us to change the vertex layout after reserveVertexSpace(). We won't
@ -405,9 +408,9 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask,
GrAssert(NULL != fTarget); GrAssert(NULL != fTarget);
GrDrawTarget::AutoStateRestore asr(fTarget); GrDrawTarget::AutoStateRestore asr(fTarget);
bool colorWritesWereDisabled = fTarget->isColorWriteDisabled(); bool colorWritesWereDisabled = drawState->isColorWriteDisabled();
// face culling doesn't make sense here // face culling doesn't make sense here
GrAssert(GrDrawState::kBoth_DrawFace == fTarget->getDrawFace()); GrAssert(GrDrawState::kBoth_DrawFace == drawState->getDrawFace());
int passCount = 0; int passCount = 0;
const GrStencilSettings* passes[3]; const GrStencilSettings* passes[3];
@ -503,36 +506,37 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask,
{ {
for (int p = 0; p < passCount; ++p) { for (int p = 0; p < passCount; ++p) {
fTarget->setDrawFace(drawFace[p]); drawState->setDrawFace(drawFace[p]);
if (NULL != passes[p]) { if (NULL != passes[p]) {
fTarget->setStencil(*passes[p]); drawState->setStencil(*passes[p]);
} }
if (lastPassIsBounds && (p == passCount-1)) { if (lastPassIsBounds && (p == passCount-1)) {
if (!colorWritesWereDisabled) { if (!colorWritesWereDisabled) {
fTarget->disableState(GrDrawTarget::kNoColorWrites_StateBit); drawState->disableState(
GrDrawState::kNoColorWrites_StateBit);
} }
GrRect bounds; GrRect bounds;
if (reverse) { if (reverse) {
GrAssert(NULL != fTarget->getRenderTarget()); GrAssert(NULL != drawState->getRenderTarget());
// draw over the whole world. // draw over the whole world.
bounds.setLTRB(0, 0, bounds.setLTRB(0, 0,
GrIntToScalar(fTarget->getRenderTarget()->width()), GrIntToScalar(drawState->getRenderTarget()->width()),
GrIntToScalar(fTarget->getRenderTarget()->height())); GrIntToScalar(drawState->getRenderTarget()->height()));
GrMatrix vmi; GrMatrix vmi;
// mapRect through persp matrix may not be correct // mapRect through persp matrix may not be correct
if (!fTarget->getViewMatrix().hasPerspective() && if (!drawState->getViewMatrix().hasPerspective() &&
fTarget->getViewInverse(&vmi)) { drawState->getViewInverse(&vmi)) {
vmi.mapRect(&bounds); vmi.mapRect(&bounds);
} else { } else {
if (stageMask) { if (stageMask) {
if (!fTarget->getViewInverse(&vmi)) { if (!drawState->getViewInverse(&vmi)) {
GrPrintf("Could not invert matrix."); GrPrintf("Could not invert matrix.");
return; return;
} }
fTarget->preConcatSamplerMatrices(stageMask, vmi); drawState->preConcatSamplerMatrices(stageMask, vmi);
} }
fTarget->setViewMatrix(GrMatrix::I()); drawState->setViewMatrix(GrMatrix::I());
} }
} else { } else {
bounds = fPath->getBounds(); bounds = fPath->getBounds();
@ -542,7 +546,7 @@ void GrDefaultPathRenderer::onDrawPath(GrDrawState::StageMask stageMask,
fTarget->drawSimpleRect(bounds, NULL, stageMask); fTarget->drawSimpleRect(bounds, NULL, stageMask);
} else { } else {
if (passCount > 1) { if (passCount > 1) {
fTarget->enableState(GrDrawTarget::kNoColorWrites_StateBit); drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
} }
if (fUseIndexedDraw) { if (fUseIndexedDraw) {
fTarget->drawIndexed(fPrimitiveType, 0, 0, fTarget->drawIndexed(fPrimitiveType, 0, 0,

View File

@ -10,6 +10,7 @@
#include "GrColor.h" #include "GrColor.h"
#include "GrMatrix.h" #include "GrMatrix.h"
#include "GrNoncopyable.h"
#include "GrSamplerState.h" #include "GrSamplerState.h"
#include "GrStencil.h" #include "GrStencil.h"
@ -45,13 +46,386 @@ struct GrDrawState {
typedef uint32_t StageMask; typedef uint32_t StageMask;
GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages); GR_STATIC_ASSERT(sizeof(StageMask)*8 >= GrDrawState::kNumStages);
enum DrawFace { GrDrawState() {
kBoth_DrawFace, // make sure any pad is zero for memcmp
kCCW_DrawFace, // all GrDrawState members should default to something
kCW_DrawFace, // valid by the memset
memset(this, 0, sizeof(GrDrawState));
// memset exceptions
fColorFilterMode = SkXfermode::kDstIn_Mode;
fFirstCoverageStage = kNumStages;
// pedantic assertion that our ptrs will
// be NULL (0 ptr is mem addr 0)
GrAssert((intptr_t)(void*)NULL == 0LL);
GrAssert(fStencilSettings.isDisabled());
fFirstCoverageStage = kNumStages;
}
///////////////////////////////////////////////////////////////////////////
/// @name Color
////
/**
* Sets color for next draw to a premultiplied-alpha color.
*
* @param color the color to set.
*/
void setColor(GrColor color) { fColor = color; }
GrColor getColor() const { return fColor; }
/**
* Sets the color to be used for the next draw to be
* (r,g,b,a) = (alpha, alpha, alpha, alpha).
*
* @param alpha The alpha value to set as the color.
*/
void setAlpha(uint8_t a) {
this->setColor((a << 24) | (a << 16) | (a << 8) | a);
}
/**
* Add a color filter that can be represented by a color and a mode. Applied
* after color-computing texture stages.
*/
void setColorFilter(GrColor c, SkXfermode::Mode mode) {
fColorFilterColor = c;
fColorFilterMode = mode;
}
GrColor getColorFilterColor() const { return fColorFilterColor; }
SkXfermode::Mode getColorFilterMode() const { return fColorFilterMode; }
/// @}
///////////////////////////////////////////////////////////////////////////
/// @name Textures
////
/**
* Sets the texture used at the next drawing call
*
* @param stage The texture stage for which the texture will be set
*
* @param texture The texture to set. Can be NULL though there is no
* advantage to settings a NULL texture if doing non-textured drawing
*/
void setTexture(int stage, GrTexture* texture) {
GrAssert((unsigned)stage < kNumStages);
fTextures[stage] = texture;
}
/**
* Retrieves the currently set texture.
*
* @return The currently set texture. The return value will be NULL if no
* texture has been set, NULL was most recently passed to
* setTexture, or the last setTexture was destroyed.
*/
const GrTexture* getTexture(int stage) const {
GrAssert((unsigned)stage < kNumStages);
return fTextures[stage];
}
GrTexture* getTexture(int stage) {
GrAssert((unsigned)stage < kNumStages);
return fTextures[stage];
}
/// @}
///////////////////////////////////////////////////////////////////////////
/// @name Samplers
////
/**
* Returns the current sampler for a stage.
*/
const GrSamplerState& getSampler(int stage) const {
GrAssert((unsigned)stage < kNumStages);
return fSamplers[stage];
}
/**
* Writable pointer to a stage's sampler.
*/
GrSamplerState* sampler(int stage) {
GrAssert((unsigned)stage < kNumStages);
return fSamplers + stage;
}
/**
* Preconcats the matrix of all samplers in the mask with the same matrix.
*/
void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
GrAssert(!(stageMask & kIllegalStageMaskBits));
for (int i = 0; i < kNumStages; ++i) {
if ((1 << i) & stageMask) {
fSamplers[i].preConcatMatrix(matrix);
}
}
}
/// @}
///////////////////////////////////////////////////////////////////////////
/// @name Coverage / Color Stages
////
/**
* A common pattern is to compute a color with the initial stages and then
* modulate that color by a coverage value in later stage(s) (AA, mask-
* filters, glyph mask, etc). Color-filters, xfermodes, etc should be
* computed based on the pre-coverage-modulated color. The division of
* stages between color-computing and coverage-computing is specified by
* this method. Initially this is kNumStages (all stages
* are color-computing).
*/
void setFirstCoverageStage(int firstCoverageStage) {
GrAssert((unsigned)firstCoverageStage < kNumStages);
fFirstCoverageStage = firstCoverageStage;
}
/**
* Gets the index of the first coverage-computing stage.
*/
int getFirstCoverageStage() const {
return fFirstCoverageStage;
}
///@}
///////////////////////////////////////////////////////////////////////////
/// @name Blending
////
/**
* Sets the blending function coeffecients.
*
* The blend function will be:
* D' = sat(S*srcCoef + D*dstCoef)
*
* where D is the existing destination color, S is the incoming source
* color, and D' is the new destination color that will be written. sat()
* is the saturation function.
*
* @param srcCoef coeffecient applied to the src color.
* @param dstCoef coeffecient applied to the dst color.
*/
void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
fSrcBlend = srcCoeff;
fDstBlend = dstCoeff;
#if GR_DEBUG
switch (dstCoeff) {
case kDC_BlendCoeff:
case kIDC_BlendCoeff:
case kDA_BlendCoeff:
case kIDA_BlendCoeff:
GrPrintf("Unexpected dst blend coeff. Won't work correctly with"
"coverage stages.\n");
break;
default:
break;
}
switch (srcCoeff) {
case kSC_BlendCoeff:
case kISC_BlendCoeff:
case kSA_BlendCoeff:
case kISA_BlendCoeff:
GrPrintf("Unexpected src blend coeff. Won't work correctly with"
"coverage stages.\n");
break;
default:
break;
}
#endif
}
GrBlendCoeff getSrcBlendCoeff() const { return fSrcBlend; }
GrBlendCoeff getDstBlendCoeff() const { return fDstBlend; }
void getDstBlendCoeff(GrBlendCoeff* srcBlendCoeff,
GrBlendCoeff* dstBlendCoeff) const {
*srcBlendCoeff = fSrcBlend;
*dstBlendCoeff = fDstBlend;
}
/**
* Sets the blending function constant referenced by the following blending
* coeffecients:
* kConstC_BlendCoeff
* kIConstC_BlendCoeff
* kConstA_BlendCoeff
* kIConstA_BlendCoeff
*
* @param constant the constant to set
*/
void setBlendConstant(GrColor constant) { fBlendConstant = constant; }
/**
* Retrieves the last value set by setBlendConstant()
* @return the blending constant value
*/
GrColor getBlendConstant() const { return fBlendConstant; }
/// @}
///////////////////////////////////////////////////////////////////////////
/// @name View Matrix
////
/**
* Sets the matrix applied to veretx positions.
*
* In the post-view-matrix space the rectangle [0,w]x[0,h]
* fully covers the render target. (w and h are the width and height of the
* the rendertarget.)
*/
void setViewMatrix(const GrMatrix& m) { fViewMatrix = m; }
/**
* Gets a writable pointer to the view matrix.
*/
GrMatrix* viewMatrix() { return &fViewMatrix; }
/**
* Multiplies the current view matrix by a matrix
*
* After this call V' = V*m where V is the old view matrix,
* m is the parameter to this function, and V' is the new view matrix.
* (We consider positions to be column vectors so position vector p is
* transformed by matrix X as p' = X*p.)
*
* @param m the matrix used to modify the view matrix.
*/
void preConcatViewMatrix(const GrMatrix& m) { fViewMatrix.preConcat(m); }
/**
* Multiplies the current view matrix by a matrix
*
* After this call V' = m*V where V is the old view matrix,
* m is the parameter to this function, and V' is the new view matrix.
* (We consider positions to be column vectors so position vector p is
* transformed by matrix X as p' = X*p.)
*
* @param m the matrix used to modify the view matrix.
*/
void postConcatViewMatrix(const GrMatrix& m) { fViewMatrix.postConcat(m); }
/**
* Retrieves the current view matrix
* @return the current view matrix.
*/
const GrMatrix& getViewMatrix() const { return fViewMatrix; }
/**
* Retrieves the inverse of the current view matrix.
*
* If the current view matrix is invertible, return true, and if matrix
* is non-null, copy the inverse into it. If the current view matrix is
* non-invertible, return false and ignore the matrix parameter.
*
* @param matrix if not null, will receive a copy of the current inverse.
*/
bool getViewInverse(GrMatrix* matrix) const {
// TODO: determine whether we really need to leave matrix unmodified
// at call sites when inversion fails.
GrMatrix inverse;
if (fViewMatrix.invert(&inverse)) {
if (matrix) {
*matrix = inverse;
}
return true;
}
return false;
}
/// @}
///////////////////////////////////////////////////////////////////////////
/// @name Render Target
////
/**
* Sets the rendertarget used at the next drawing call
*
* @param target The render target to set.
*/
void setRenderTarget(GrRenderTarget* target) { fRenderTarget = target; }
/**
* Retrieves the currently set rendertarget.
*
* @return The currently set render target.
*/
const GrRenderTarget* getRenderTarget() const { return fRenderTarget; }
GrRenderTarget* getRenderTarget() { return fRenderTarget; }
class AutoRenderTargetRestore : public ::GrNoncopyable {
public:
AutoRenderTargetRestore() : fDrawState(NULL) {}
AutoRenderTargetRestore(GrDrawState* ds, GrRenderTarget* newTarget) {
this->set(ds, newTarget);
}
~AutoRenderTargetRestore() { this->set(NULL, NULL); }
void set(GrDrawState* ds, GrRenderTarget* newTarget) {
if (NULL != fDrawState) {
fDrawState->setRenderTarget(fSavedTarget);
}
if (NULL != ds) {
fSavedTarget = ds->getRenderTarget();
ds->setRenderTarget(newTarget);
}
fDrawState = ds;
}
private:
GrDrawState* fDrawState;
GrRenderTarget* fSavedTarget;
}; };
/** /// @}
///////////////////////////////////////////////////////////////////////////
/// @name Stencil
////
/**
* Sets the stencil settings to use for the next draw.
* Changing the clip has the side-effect of possibly zeroing
* out the client settable stencil bits. So multipass algorithms
* using stencil should not change the clip between passes.
* @param settings the stencil settings to use.
*/
void setStencil(const GrStencilSettings& settings) {
fStencilSettings = settings;
}
/**
* Shortcut to disable stencil testing and ops.
*/
void disableStencil() {
fStencilSettings.setDisabled();
}
const GrStencilSettings& getStencil() const { return fStencilSettings; }
GrStencilSettings* stencil() { return &fStencilSettings; }
/// @}
///////////////////////////////////////////////////////////////////////////
// @name Edge AA
// There are two ways to perform antialiasing using edge equations. One
// is to specify an (linear or quadratic) edge eq per-vertex. This requires
// splitting vertices shared by primitives.
//
// The other is via setEdgeAAData which sets a set of edges and each
// is tested against all the edges.
////
/**
* When specifying edges as vertex data this enum specifies what type of * 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 * edges are in use. The edges are always 4 GrScalars in memory, even when
* the edge type requires fewer than 4. * the edge type requires fewer than 4.
@ -65,6 +439,19 @@ struct GrDrawState {
kHairQuad_EdgeType 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 * The absolute maximum number of edges that may be specified for
* a single draw call when performing edge antialiasing. This is used for * a single draw call when performing edge antialiasing. This is used for
@ -91,31 +478,187 @@ struct GrDrawState {
float fX, fY, fZ; float fX, fY, fZ;
}; };
GrDrawState() { /**
// make sure any pad is zero for memcmp * Sets the edge data required for edge antialiasing.
// all GrDrawState members should default to something *
// valid by the memset * @param edges 3 * numEdges float values, representing the edge
memset(this, 0, sizeof(GrDrawState)); * equations in Ax + By + C form
*/
// memset exceptions void setEdgeAAData(const Edge* edges, int numEdges) {
fColorFilterXfermode = SkXfermode::kDstIn_Mode; GrAssert(numEdges <= GrDrawState::kMaxEdges);
fFirstCoverageStage = kNumStages; memcpy(fEdgeAAEdges, edges, numEdges * sizeof(GrDrawState::Edge));
fEdgeAANumEdges = numEdges;
// pedantic assertion that our ptrs will
// be NULL (0 ptr is mem addr 0)
GrAssert((intptr_t)(void*)NULL == 0LL);
// default stencil setting should be disabled
GrAssert(fStencilSettings.isDisabled());
fFirstCoverageStage = kNumStages;
} }
int getNumAAEdges() const { return fEdgeAANumEdges; }
const Edge* getAAEdges() const { return fEdgeAAEdges; }
/// @}
///////////////////////////////////////////////////////////////////////////
/// @name State Flags
////
/**
* Flags that affect rendering. Controlled using enable/disableState(). All
* default to disabled.
*/
enum StateBits {
/**
* Perform dithering. TODO: Re-evaluate whether we need this bit
*/
kDither_StateBit = 0x01,
/**
* Perform HW anti-aliasing. This means either HW FSAA, if supported
* by the render target, or smooth-line rendering if a line primitive
* is drawn and line smoothing is supported by the 3D API.
*/
kHWAntialias_StateBit = 0x02,
/**
* Draws will respect the clip, otherwise the clip is ignored.
*/
kClip_StateBit = 0x04,
/**
* Disables writing to the color buffer. Useful when performing stencil
* operations.
*/
kNoColorWrites_StateBit = 0x08,
/**
* Modifies the behavior of edge AA specified by setEdgeAA. If set,
* will test edge pairs for convexity when rasterizing. Set this if the
* source polygon is non-convex.
*/
kEdgeAAConcave_StateBit = 0x10,
// Users of the class may add additional bits to the vector
kDummyStateBit,
kLastPublicStateBit = kDummyStateBit-1,
};
void resetStateFlags() {
fFlagBits = 0;
}
/**
* 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%.
bool operator ==(const GrDrawState& s) const {
if (memcmp(this, &s, this->leadingBytes())) return false;
for (int i = 0; i < kNumStages; i++) {
if (fTextures[i] &&
memcmp(&this->fSamplers[i], &s.fSamplers[i],
sizeof(GrSamplerState))) {
return false;
}
}
return true;
}
bool operator !=(const GrDrawState& s) const { return !(*this == s); }
// Most stages are usually not used, so conditionals here
// reduce the expected number of bytes touched by 50%.
GrDrawState& operator =(const GrDrawState& s) {
memcpy(this, &s, this->leadingBytes());
for (int i = 0; i < kNumStages; i++) {
if (s.fTextures[i]) {
memcpy(&this->fSamplers[i], &s.fSamplers[i],
sizeof(GrSamplerState));
}
}
return *this;
}
private:
static const StageMask kIllegalStageMaskBits = ~((1 << kNumStages)-1);
uint8_t fFlagBits; uint8_t fFlagBits;
GrBlendCoeff fSrcBlend : 8; GrBlendCoeff fSrcBlend : 8;
GrBlendCoeff fDstBlend : 8; GrBlendCoeff fDstBlend : 8;
DrawFace fDrawFace : 8; DrawFace fDrawFace : 8;
uint8_t fFirstCoverageStage; uint8_t fFirstCoverageStage;
SkXfermode::Mode fColorFilterXfermode : 8; SkXfermode::Mode fColorFilterMode : 8;
GrColor fBlendConstant; GrColor fBlendConstant;
GrTexture* fTextures[kNumStages]; GrTexture* fTextures[kNumStages];
GrRenderTarget* fRenderTarget; GrRenderTarget* fRenderTarget;
@ -137,41 +680,8 @@ struct GrDrawState {
// This field must be last; it will not be copied or compared // This field must be last; it will not be copied or compared
// if the corresponding fTexture[] is NULL. // if the corresponding fTexture[] is NULL.
GrSamplerState fSamplerStates[kNumStages]; GrSamplerState fSamplers[kNumStages];
// Most stages are usually not used, so conditionals here
// reduce the expected number of bytes touched by 50%.
bool operator ==(const GrDrawState& s) const {
if (memcmp(this, &s, this->leadingBytes())) return false;
for (int i = 0; i < kNumStages; i++) {
if (fTextures[i] &&
memcmp(&this->fSamplerStates[i], &s.fSamplerStates[i],
sizeof(GrSamplerState))) {
return false;
}
}
return true;
}
bool operator !=(const GrDrawState& s) const { return !(*this == s); }
// Most stages are usually not used, so conditionals here
// reduce the expected number of bytes touched by 50%.
GrDrawState& operator =(const GrDrawState& s) {
memcpy(this, &s, this->leadingBytes());
for (int i = 0; i < kNumStages; i++) {
if (s.fTextures[i]) {
memcpy(&this->fSamplerStates[i], &s.fSamplerStates[i],
sizeof(GrSamplerState));
}
}
return *this;
}
private:
size_t leadingBytes() const { size_t leadingBytes() const {
// Can't use offsetof() with non-POD types, so stuck with pointer math. // Can't use offsetof() with non-POD types, so stuck with pointer math.
// TODO: ignores GrTesselatedPathRenderer data structures. We don't // TODO: ignores GrTesselatedPathRenderer data structures. We don't
@ -184,4 +694,3 @@ private:
}; };
#endif #endif

View File

@ -455,119 +455,6 @@ const GrClip& GrDrawTarget::getClip() const {
return fClip; 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 { void GrDrawTarget::saveCurrentDrawState(SavedDrawState* state) const {
state->fState = fCurrDrawState; state->fState = fCurrDrawState;
} }
@ -804,8 +691,8 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
return false; return false;
} }
if (GrPixelConfigIsUnpremultiplied(this->getRenderTarget()->config())) { if (GrPixelConfigIsUnpremultiplied(this->getRenderTarget()->config())) {
if (kOne_BlendCoeff != fCurrDrawState.fSrcBlend || if (kOne_BlendCoeff != getDrawState().getSrcBlendCoeff() ||
kZero_BlendCoeff != fCurrDrawState.fDstBlend) { kZero_BlendCoeff != getDrawState().getDstBlendCoeff()) {
return false; return false;
} }
} }
@ -817,8 +704,8 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
// a custom bilerp in the shader. Until Skia itself supports unpremul // a custom bilerp in the shader. Until Skia itself supports unpremul
// configs there is no pressure to implement this. // configs there is no pressure to implement this.
if (this->isStageEnabled(s) && if (this->isStageEnabled(s) &&
GrPixelConfigIsUnpremultiplied(fCurrDrawState.fTextures[s]->config()) && GrPixelConfigIsUnpremultiplied(this->getTexture(s)->config()) &&
GrSamplerState::kNearest_Filter != fCurrDrawState.fSamplerStates[s].getFilter()) { GrSamplerState::kNearest_Filter != this->getSampler(s).getFilter()) {
return false; return false;
} }
} }
@ -861,9 +748,10 @@ bool GrDrawTarget::canTweakAlphaForCoverage() const {
* for Cd we find that only 1, ISA, and ISC produce the correct depth * for Cd we find that only 1, ISA, and ISC produce the correct depth
* coeffecient in terms of S' and D. * coeffecient in terms of S' and D.
*/ */
return kOne_BlendCoeff == fCurrDrawState.fDstBlend|| GrBlendCoeff dstCoeff = this->getDrawState().getDstBlendCoeff();
kISA_BlendCoeff == fCurrDrawState.fDstBlend || return kOne_BlendCoeff == dstCoeff ||
kISC_BlendCoeff == fCurrDrawState.fDstBlend; kISA_BlendCoeff == dstCoeff ||
kISC_BlendCoeff == dstCoeff;
} }
@ -872,20 +760,21 @@ bool GrDrawTarget::srcAlphaWillBeOne() const {
// Check if per-vertex or constant color may have partial alpha // Check if per-vertex or constant color may have partial alpha
if ((layout & kColor_VertexLayoutBit) || if ((layout & kColor_VertexLayoutBit) ||
0xff != GrColorUnpackA(fCurrDrawState.fColor)) { 0xff != GrColorUnpackA(this->getColor())) {
return false; return false;
} }
// Check if color filter could introduce an alpha // Check if color filter could introduce an alpha
// (TODO: Consider being more aggressive with regards to detecting 0xff // (TODO: Consider being more aggressive with regards to detecting 0xff
// final alpha from color filter). // final alpha from color filter).
if (SkXfermode::kDst_Mode != fCurrDrawState.fColorFilterXfermode) { if (SkXfermode::kDst_Mode != this->getDrawState().getColorFilterMode()) {
return false; return false;
} }
// Check if a color stage could create a partial alpha // Check if a color stage could create a partial alpha
for (int s = 0; s < fCurrDrawState.fFirstCoverageStage; ++s) { int firstCoverageStage = this->getFirstCoverageStage();
for (int s = 0; s < firstCoverageStage; ++s) {
if (StageWillBeUsed(s, layout, fCurrDrawState)) { if (StageWillBeUsed(s, layout, fCurrDrawState)) {
GrAssert(NULL != fCurrDrawState.fTextures[s]); GrAssert(NULL != this->getTexture(s));
GrPixelConfig config = fCurrDrawState.fTextures[s]->config(); GrPixelConfig config = this->getTexture(s)->config();
if (!GrPixelConfigIsOpaque(config)) { if (!GrPixelConfigIsOpaque(config)) {
return false; return false;
} }
@ -905,12 +794,12 @@ GrDrawTarget::getBlendOpts(bool forceCoverage,
if (NULL == srcCoeff) { if (NULL == srcCoeff) {
srcCoeff = &bogusSrcCoeff; srcCoeff = &bogusSrcCoeff;
} }
*srcCoeff = fCurrDrawState.fSrcBlend; *srcCoeff = this->getDrawState().getSrcBlendCoeff();
if (NULL == dstCoeff) { if (NULL == dstCoeff) {
dstCoeff = &bogusDstCoeff; dstCoeff = &bogusDstCoeff;
} }
*dstCoeff = fCurrDrawState.fDstBlend; *dstCoeff = this->getDrawState().getDstBlendCoeff();
// We don't ever expect source coeffecients to reference the source // We don't ever expect source coeffecients to reference the source
GrAssert(kSA_BlendCoeff != *srcCoeff && GrAssert(kSA_BlendCoeff != *srcCoeff &&
@ -923,7 +812,7 @@ GrDrawTarget::getBlendOpts(bool forceCoverage,
kDC_BlendCoeff != *dstCoeff && kDC_BlendCoeff != *dstCoeff &&
kIDC_BlendCoeff != *dstCoeff); kIDC_BlendCoeff != *dstCoeff);
if (SkToBool(kNoColorWrites_StateBit & fCurrDrawState.fFlagBits)) { if (this->getDrawState().isColorWriteDisabled()) {
*srcCoeff = kZero_BlendCoeff; *srcCoeff = kZero_BlendCoeff;
*dstCoeff = kOne_BlendCoeff; *dstCoeff = kOne_BlendCoeff;
} }
@ -939,7 +828,7 @@ GrDrawTarget::getBlendOpts(bool forceCoverage,
// stenciling is enabled. Having color writes disabled is effectively // stenciling is enabled. Having color writes disabled is effectively
// (0,1). // (0,1).
if ((kZero_BlendCoeff == *srcCoeff && dstCoeffIsOne)) { if ((kZero_BlendCoeff == *srcCoeff && dstCoeffIsOne)) {
if (fCurrDrawState.fStencilSettings.doesWrite()) { if (this->getDrawState().getStencil().doesWrite()) {
if (fCaps.fShaderSupport) { if (fCaps.fShaderSupport) {
return kDisableBlend_BlendOptFlag | return kDisableBlend_BlendOptFlag |
kEmitTransBlack_BlendOptFlag; kEmitTransBlack_BlendOptFlag;
@ -953,10 +842,10 @@ GrDrawTarget::getBlendOpts(bool forceCoverage,
// check for coverage due to edge aa or coverage texture stage // check for coverage due to edge aa or coverage texture stage
bool hasCoverage = forceCoverage || bool hasCoverage = forceCoverage ||
fCurrDrawState.fEdgeAANumEdges > 0 || this->getDrawState().getNumAAEdges() > 0 ||
(layout & kCoverage_VertexLayoutBit) || (layout & kCoverage_VertexLayoutBit) ||
(layout & kEdge_VertexLayoutBit); (layout & kEdge_VertexLayoutBit);
for (int s = fCurrDrawState.fFirstCoverageStage; for (int s = this->getFirstCoverageStage();
!hasCoverage && s < GrDrawState::kNumStages; !hasCoverage && s < GrDrawState::kNumStages;
++s) { ++s) {
if (StageWillBeUsed(s, layout, fCurrDrawState)) { if (StageWillBeUsed(s, layout, fCurrDrawState)) {
@ -1023,7 +912,7 @@ bool GrDrawTarget::willUseHWAALines() const {
// but not in a premul-alpha way. So we only use them when our alpha // 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 // is 0xff and tweaking the color for partial coverage is OK
if (!fCaps.fHWAALineSupport || if (!fCaps.fHWAALineSupport ||
!(kHWAntialias_StateBit & fCurrDrawState.fFlagBits)) { !(this->getDrawState().isHWAntialiasState())) {
return false; return false;
} }
BlendOptFlags opts = this->getBlendOpts(); BlendOptFlags opts = this->getBlendOpts();
@ -1043,16 +932,6 @@ bool GrDrawTarget::drawWillReadDst() const {
this->getBlendOpts()); this->getBlendOpts());
} }
///////////////////////////////////////////////////////////////////////////////
void GrDrawTarget::setEdgeAAData(const GrDrawState::Edge* edges, int numEdges) {
GrAssert(numEdges <= GrDrawState::kMaxEdges);
memcpy(fCurrDrawState.fEdgeAAEdges, edges,
numEdges * sizeof(GrDrawState::Edge));
fCurrDrawState.fEdgeAANumEdges = numEdges;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void GrDrawTarget::drawRect(const GrRect& rect, void GrDrawTarget::drawRect(const GrRect& rect,
@ -1068,13 +947,13 @@ void GrDrawTarget::drawRect(const GrRect& rect,
return; return;
} }
SetRectVertices(rect, matrix, srcRects, SetRectVertices(rect, matrix, srcRects,
srcMatrices, layout, geo.vertices()); srcMatrices, layout, geo.vertices());
drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4); drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
} }
GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageMask stageMask, GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageMask stageMask,
const GrRect* srcRects[]) { const GrRect* srcRects[]) {
GrVertexLayout layout = 0; GrVertexLayout layout = 0;
@ -1183,7 +1062,7 @@ GrDrawTarget::AutoDeviceCoordDraw::AutoDeviceCoordDraw(
if (fViewMatrix.invert(&invVM)) { if (fViewMatrix.invert(&invVM)) {
for (int s = 0; s < GrDrawState::kNumStages; ++s) { for (int s = 0; s < GrDrawState::kNumStages; ++s) {
if (fStageMask & (1 << s)) { if (fStageMask & (1 << s)) {
fSamplerMatrices[s] = target->getSamplerMatrix(s); fSamplerMatrices[s] = target->getSampler(s).getMatrix();
} }
} }
target->preConcatSamplerMatrices(fStageMask, invVM); target->preConcatSamplerMatrices(fStageMask, invVM);
@ -1199,7 +1078,8 @@ GrDrawTarget::AutoDeviceCoordDraw::~AutoDeviceCoordDraw() {
fDrawTarget->setViewMatrix(fViewMatrix); fDrawTarget->setViewMatrix(fViewMatrix);
for (int s = 0; s < GrDrawState::kNumStages; ++s) { for (int s = 0; s < GrDrawState::kNumStages; ++s) {
if (fStageMask & (1 << s)) { if (fStageMask & (1 << s)) {
fDrawTarget->setSamplerMatrix(s, fSamplerMatrices[s]); GrSamplerState* sampler = fDrawTarget->drawState()->sampler(s);
sampler->setMatrix(fSamplerMatrices[s]);
} }
} }
} }

View File

@ -57,62 +57,9 @@ public:
int fMaxTextureSize; int fMaxTextureSize;
}; };
// for convenience
typedef GrDrawState::StageMask StageMask; 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(); GrDrawTarget();
@ -140,285 +87,6 @@ public:
*/ */
const GrClip& getClip() const; const GrClip& getClip() const;
/**
* Sets the texture used at the next drawing call
*
* @param stage The texture stage for which the texture will be set
*
* @param texture The texture to set. Can be NULL though there is no advantage
* to settings a NULL texture if doing non-textured drawing
*/
void setTexture(int stage, GrTexture* texture);
/**
* Retrieves the currently set texture.
*
* @return The currently set texture. The return value will be NULL if no
* texture has been set, NULL was most recently passed to
* setTexture, or the last setTexture was destroyed.
*/
const GrTexture* getTexture(int stage) const;
GrTexture* getTexture(int stage);
/**
* Sets the rendertarget used at the next drawing call
*
* @param target The render target to set.
*/
void setRenderTarget(GrRenderTarget* target);
/**
* Retrieves the currently set rendertarget.
*
* @return The currently set render target.
*/
const GrRenderTarget* getRenderTarget() const;
GrRenderTarget* getRenderTarget();
/**
* Sets the sampler state for a stage used in subsequent draws.
*
* The sampler state determines how texture coordinates are
* intepretted and used to sample the texture.
*
* @param stage the stage of the sampler to set
* @param samplerState Specifies the sampler state.
*/
void setSamplerState(int stage, const GrSamplerState& samplerState);
/**
* Concats the matrix of a stage's sampler.
*
* @param stage the stage of the sampler to set
* @param matrix the matrix to concat
*/
void preConcatSamplerMatrix(int stage, const GrMatrix& matrix) {
GrAssert(stage >= 0 && stage < GrDrawState::kNumStages);
fCurrDrawState.fSamplerStates[stage].preConcatMatrix(matrix);
}
/**
* Shortcut for preConcatSamplerMatrix on all stages in mask with same
* matrix
*/
void preConcatSamplerMatrices(StageMask stageMask, const GrMatrix& matrix) {
for (int i = 0; i < GrDrawState::kNumStages; ++i) {
if ((1 << i) & stageMask) {
this->preConcatSamplerMatrix(i, matrix);
}
}
}
/**
* Shortcut for preConcatSamplerMatrix on all enabled stages in mask with
* same matrix
*
* @param stage the stage of the sampler to set
* @param matrix the matrix to concat
*/
void preConcatEnabledSamplerMatrices(const GrMatrix& matrix) {
StageMask stageMask = this->enabledStages();
this->preConcatSamplerMatrices(stageMask, matrix);
}
/**
* Gets the matrix of a stage's sampler
*
* @param stage the stage to of sampler to get
* @return the sampler state's matrix
*/
const GrMatrix& getSamplerMatrix(int stage) const {
return fCurrDrawState.fSamplerStates[stage].getMatrix();
}
/**
* Sets the matrix of a stage's sampler
*
* @param stage the stage of sampler set
* @param matrix the matrix to set
*/
void setSamplerMatrix(int stage, const GrMatrix& matrix) {
fCurrDrawState.fSamplerStates[stage].setMatrix(matrix);
}
/**
* Sets the matrix applied to veretx positions.
*
* In the post-view-matrix space the rectangle [0,w]x[0,h]
* fully covers the render target. (w and h are the width and height of the
* the rendertarget.)
*
* @param m the matrix used to transform the vertex positions.
*/
void setViewMatrix(const GrMatrix& m);
/**
* Multiplies the current view matrix by a matrix
*
* After this call V' = V*m where V is the old view matrix,
* m is the parameter to this function, and V' is the new view matrix.
* (We consider positions to be column vectors so position vector p is
* transformed by matrix X as p' = X*p.)
*
* @param m the matrix used to modify the view matrix.
*/
void preConcatViewMatrix(const GrMatrix& m);
/**
* Multiplies the current view matrix by a matrix
*
* After this call V' = m*V where V is the old view matrix,
* m is the parameter to this function, and V' is the new view matrix.
* (We consider positions to be column vectors so position vector p is
* transformed by matrix X as p' = X*p.)
*
* @param m the matrix used to modify the view matrix.
*/
void postConcatViewMatrix(const GrMatrix& m);
/**
* Retrieves the current view matrix
* @return the current view matrix.
*/
const GrMatrix& getViewMatrix() const;
/**
* Retrieves the inverse of the current view matrix.
*
* If the current view matrix is invertible, return true, and if matrix
* is non-null, copy the inverse into it. If the current view matrix is
* non-invertible, return false and ignore the matrix parameter.
*
* @param matrix if not null, will receive a copy of the current inverse.
*/
bool getViewInverse(GrMatrix* matrix) const;
/**
* Sets color for next draw to a premultiplied-alpha color.
*
* @param the color to set.
*/
void setColor(GrColor);
/**
* Gets the currently set color.
* @return the current color.
*/
GrColor getColor() const { return fCurrDrawState.fColor; }
/**
* Add a color filter that can be represented by a color and a mode.
*/
void setColorFilter(GrColor, SkXfermode::Mode);
/**
* Sets the color to be used for the next draw to be
* (r,g,b,a) = (alpha, alpha, alpha, alpha).
*
* @param alpha The alpha value to set as the color.
*/
void setAlpha(uint8_t alpha);
/**
* Controls whether clockwise, counterclockwise, or both faces are drawn.
* @param face the face(s) to draw.
*/
void setDrawFace(GrDrawState::DrawFace face) {
fCurrDrawState.fDrawFace = face;
}
/**
* A common pattern is to compute a color with the initial stages and then
* modulate that color by a coverage value in later stage(s) (AA, mask-
* filters, glyph mask, etc). Color-filters, xfermodes, etc should be
* computed based on the pre-coverage-modulated color. The division of
* stages between color-computing and coverage-computing is specified by
* this method. Initially this is GrDrawState::kNumStages (all stages
* are color-computing).
*/
void setFirstCoverageStage(int firstCoverageStage) {
fCurrDrawState.fFirstCoverageStage = firstCoverageStage;
}
/**
* Gets the index of the first coverage-computing stage.
*/
int getFirstCoverageStage() const {
return fCurrDrawState.fFirstCoverageStage;
}
/**
* Gets whether the target is drawing clockwise, counterclockwise,
* or both faces.
* @return the current draw face(s).
*/
GrDrawState::DrawFace getDrawFace() const {
return fCurrDrawState.fDrawFace;
}
/**
* Enable render state settings.
*
* @param flags bitfield of StateBits specifing the states to enable
*/
void enableState(uint32_t stateBits);
/**
* Disable render state settings.
*
* @param flags bitfield of StateBits specifing the states to disable
*/
void disableState(uint32_t stateBits);
bool isDitherState() const {
return 0 != (fCurrDrawState.fFlagBits & kDither_StateBit);
}
bool isHWAntialiasState() const {
return 0 != (fCurrDrawState.fFlagBits & kHWAntialias_StateBit);
}
bool isClipState() const {
return 0 != (fCurrDrawState.fFlagBits & kClip_StateBit);
}
bool isColorWriteDisabled() const {
return 0 != (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit);
}
/**
* Sets the blending function coeffecients.
*
* The blend function will be:
* D' = sat(S*srcCoef + D*dstCoef)
*
* where D is the existing destination color, S is the incoming source
* color, and D' is the new destination color that will be written. sat()
* is the saturation function.
*
* @param srcCoef coeffecient applied to the src color.
* @param dstCoef coeffecient applied to the dst color.
*/
void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff);
/**
* Sets the blending function constant referenced by the following blending
* coeffecients:
* kConstC_BlendCoeff
* kIConstC_BlendCoeff
* kConstA_BlendCoeff
* kIConstA_BlendCoeff
*
* @param constant the constant to set
*/
void setBlendConstant(GrColor constant) { fCurrDrawState.fBlendConstant = constant; }
/**
* Retrieves the last value set by setBlendConstant()
* @return the blending constant value
*/
GrColor getBlendConstant() const { return fCurrDrawState.fBlendConstant; }
/** /**
* Determines if blending will require a read of a dst given the current * Determines if blending will require a read of a dst given the current
* state set on the draw target * state set on the draw target
@ -448,15 +116,6 @@ public:
*/ */
bool canTweakAlphaForCoverage() const; 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 * 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 * lines be used (if line primitive type is drawn)? (Note that lines are
@ -464,13 +123,70 @@ public:
*/ */
bool willUseHWAALines() const; bool willUseHWAALines() const;
/** const GrDrawState& getDrawState() const { return fCurrDrawState; }
* Sets the edge data required for edge antialiasing. GrDrawState* drawState() { return &fCurrDrawState; }
*
* @param edges 3 * 6 float values, representing the edge // Convenience Pass-thrus to GrDrawState. These are likely candidates for
* equations in Ax + By + C form // removal.
*/ void setViewMatrix(const GrMatrix& m) {
void setEdgeAAData(const GrDrawState::Edge* edges, int numEdges); this->drawState()->setViewMatrix(m);
}
GrMatrix* viewMatrix() {
return this->drawState()->viewMatrix();
}
const GrMatrix& getViewMatrix() const {
return this->getDrawState().getViewMatrix();
}
bool getViewInverse(GrMatrix* inv) const {
return this->getDrawState().getViewInverse(inv);
}
void setRenderTarget(GrRenderTarget* renderTarget) {
this->drawState()->setRenderTarget(renderTarget);
}
const GrRenderTarget* getRenderTarget() const {
return this->getDrawState().getRenderTarget();
}
GrRenderTarget* getRenderTarget() {
return this->drawState()->getRenderTarget();
}
void setBlendFunc(GrBlendCoeff srcCoeff, GrBlendCoeff dstCoeff) {
this->drawState()->setBlendFunc(srcCoeff, dstCoeff);
}
void setTexture(int stage, GrTexture* texture) {
this->drawState()->setTexture(stage, texture);
}
const GrTexture* getTexture(int stage) const {
return this->getDrawState().getTexture(stage);
}
GrTexture* getTexture(int stage) {
return this->drawState()->getTexture(stage);
}
// THIS WILL BE REMOVED AND REPLACED WITH DIRECT ACCESS TO SAMPLER
// IN A COMING REVISION.
void setSamplerState(int stage, const GrSamplerState& sampler) {
*(this->drawState()->sampler(stage)) = sampler;
}
const GrSamplerState& getSampler(int stage) const {
return this->getDrawState().getSampler(stage);
}
void preConcatSamplerMatrices(StageMask stageMask,
const GrMatrix& m) {
this->drawState()->preConcatSamplerMatrices(stageMask, m);
}
GrColor getColor() const { return this->getDrawState().getColor(); }
void setColor(GrColor color) { this->drawState()->setColor(color); }
void setFirstCoverageStage(int firstCoverageStage) {
this->drawState()->setFirstCoverageStage(firstCoverageStage);
}
int getFirstCoverageStage() const {
return this->getDrawState().getFirstCoverageStage();
}
void setDrawFace(const GrDrawState::DrawFace face) {
this->drawState()->setDrawFace(face);
}
GrDrawState::DrawFace getDrawFace() const {
return this->getDrawState().getDrawFace();
}
/** /**
* Used to save and restore the GrGpu's drawing state * Used to save and restore the GrGpu's drawing state
@ -895,7 +611,7 @@ public:
} }
AutoViewMatrixRestore(GrDrawTarget* target) AutoViewMatrixRestore(GrDrawTarget* target)
: fDrawTarget(target), fMatrix(fDrawTarget->getViewMatrix()) { : fDrawTarget(target), fMatrix(target->getViewMatrix()) {
GrAssert(NULL != target); GrAssert(NULL != target);
} }
@ -927,13 +643,14 @@ public:
*/ */
class AutoDeviceCoordDraw : ::GrNoncopyable { class AutoDeviceCoordDraw : ::GrNoncopyable {
public: public:
AutoDeviceCoordDraw(GrDrawTarget* target, StageMask stageMask); AutoDeviceCoordDraw(GrDrawTarget* target,
GrDrawState::StageMask stageMask);
~AutoDeviceCoordDraw(); ~AutoDeviceCoordDraw();
private: private:
GrDrawTarget* fDrawTarget; GrDrawTarget* fDrawTarget;
GrMatrix fViewMatrix; GrMatrix fViewMatrix;
GrMatrix fSamplerMatrices[GrDrawState::kNumStages]; GrMatrix fSamplerMatrices[GrDrawState::kNumStages];
int fStageMask; GrDrawState::StageMask fStageMask;
}; };
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
@ -1279,7 +996,8 @@ protected:
// given a vertex layout and a draw state, will a stage be used? // given a vertex layout and a draw state, will a stage be used?
static bool StageWillBeUsed(int stage, GrVertexLayout layout, static bool StageWillBeUsed(int stage, GrVertexLayout layout,
const GrDrawState& state) { const GrDrawState& state) {
return NULL != state.fTextures[stage] && VertexUsesStage(stage, layout); return NULL != state.getTexture(stage) &&
VertexUsesStage(stage, layout);
} }
bool isStageEnabled(int stage) const { bool isStageEnabled(int stage) const {
@ -1337,7 +1055,7 @@ protected:
// Helpers for drawRect, protected so subclasses that override drawRect // Helpers for drawRect, protected so subclasses that override drawRect
// can use them. // can use them.
static GrVertexLayout GetRectVertexLayout(StageMask stageEnableBitfield, static GrVertexLayout GetRectVertexLayout(StageMask stageMask,
const GrRect* srcRects[]); const GrRect* srcRects[]);
static void SetRectVertices(const GrRect& rect, static void SetRectVertices(const GrRect& rect,

View File

@ -185,10 +185,10 @@ bool GrGpu::attachStencilBufferToRenderTarget(GrRenderTarget* rt) {
// We used to clear down in the GL subclass using a special purpose // 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. But iOS doesn't allow a stencil-only FBO. It reports unsupported
// FBO status. // FBO status.
GrRenderTarget* oldRT = fCurrDrawState.fRenderTarget; GrRenderTarget* oldRT = this->getRenderTarget();
fCurrDrawState.fRenderTarget = rt; this->setRenderTarget(rt);
this->clearStencil(); this->clearStencil();
fCurrDrawState.fRenderTarget = oldRT; this->setRenderTarget(oldRT);
return true; return true;
} else { } else {
return false; return false;
@ -530,16 +530,17 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
const GrIRect* r = NULL; const GrIRect* r = NULL;
GrIRect clipRect; GrIRect clipRect;
// GrDrawTarget should have filtered this for us GrRenderTarget* rt = this->getRenderTarget();
GrAssert(NULL != fCurrDrawState.fRenderTarget);
if (fCurrDrawState.fFlagBits & kClip_StateBit) { // GrDrawTarget should have filtered this for us
GrRenderTarget& rt = *fCurrDrawState.fRenderTarget; GrAssert(NULL != rt);
if (this->getDrawState().isClipState()) {
GrRect bounds; GrRect bounds;
GrRect rtRect; GrRect rtRect;
rtRect.setLTRB(0, 0, rtRect.setLTRB(0, 0,
GrIntToScalar(rt.width()), GrIntToScalar(rt.height())); GrIntToScalar(rt->width()), GrIntToScalar(rt->height()));
if (fClip.hasConservativeBounds()) { if (fClip.hasConservativeBounds()) {
bounds = fClip.getConservativeBounds(); bounds = fClip.getConservativeBounds();
if (!bounds.intersect(rtRect)) { if (!bounds.intersect(rtRect)) {
@ -560,15 +561,17 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
!bounds.isEmpty(); !bounds.isEmpty();
// TODO: dynamically attach a SB when needed. // TODO: dynamically attach a SB when needed.
GrStencilBuffer* stencilBuffer = rt.getStencilBuffer(); GrStencilBuffer* stencilBuffer = rt->getStencilBuffer();
if (fClipInStencil && NULL == stencilBuffer) { if (fClipInStencil && NULL == stencilBuffer) {
return false; return false;
} }
if (fClipInStencil && GrDrawState* drawState = this->drawState();
stencilBuffer->mustRenderClip(fClip, rt.width(), rt.height())) {
stencilBuffer->setLastClip(fClip, rt.width(), rt.height()); if (fClipInStencil &&
stencilBuffer->mustRenderClip(fClip, rt->width(), rt->height())) {
stencilBuffer->setLastClip(fClip, rt->width(), rt->height());
// we set the current clip to the bounds so that our recursive // 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 // draws are scissored to them. We use the copy of the complex clip
@ -583,9 +586,9 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
this->setViewMatrix(GrMatrix::I()); this->setViewMatrix(GrMatrix::I());
this->flushScissor(NULL); this->flushScissor(NULL);
#if !VISUALIZE_COMPLEX_CLIP #if !VISUALIZE_COMPLEX_CLIP
this->enableState(kNoColorWrites_StateBit); drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
#else #else
this->disableState(kNoColorWrites_StateBit); drawState->disableState(GrDrawState::kNoColorWrites_StateBit);
#endif #endif
int count = clip.getElementCount(); int count = clip.getElementCount();
int clipBit = stencilBuffer->bits(); int clipBit = stencilBuffer->bits();
@ -606,7 +609,7 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
GrPathFill fill; GrPathFill fill;
bool fillInverted; bool fillInverted;
// enabled at bottom of loop // enabled at bottom of loop
this->disableState(kModifyStencilClip_StateBit); drawState->disableState(kModifyStencilClip_StateBit);
bool canRenderDirectToStencil; // can the clip element be drawn bool canRenderDirectToStencil; // can the clip element be drawn
// directly to the stencil buffer // directly to the stencil buffer
@ -664,11 +667,11 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
}; };
SET_RANDOM_COLOR SET_RANDOM_COLOR
if (kRect_ClipType == clip.getElementType(c)) { if (kRect_ClipType == clip.getElementType(c)) {
this->setStencil(gDrawToStencil); drawState->setStencil(gDrawToStencil);
this->drawSimpleRect(clip.getRect(c), NULL, 0); this->drawSimpleRect(clip.getRect(c), NULL, 0);
} else { } else {
if (canRenderDirectToStencil) { if (canRenderDirectToStencil) {
this->setStencil(gDrawToStencil); drawState->setStencil(gDrawToStencil);
pr->drawPath(0); pr->drawPath(0);
} else { } else {
pr->drawPathToStencil(); pr->drawPathToStencil();
@ -678,9 +681,9 @@ bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
// now we modify the clip bit by rendering either the clip // now we modify the clip bit by rendering either the clip
// element directly or a bounding rect of the entire 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) { for (int p = 0; p < passes; ++p) {
this->setStencil(stencilSettings[p]); drawState->setStencil(stencilSettings[p]);
if (canDrawDirectToClip) { if (canDrawDirectToClip) {
if (kRect_ClipType == clip.getElementType(c)) { if (kRect_ClipType == clip.getElementType(c)) {
SET_RANDOM_COLOR SET_RANDOM_COLOR

View File

@ -327,8 +327,8 @@ public:
} }
protected: protected:
enum PrivateStateBits { enum PrivateDrawStateBits {
kFirstBit = (kLastPublicStateBit << 1), kFirstBit = (GrDrawState::kLastPublicStateBit << 1),
kModifyStencilClip_StateBit = kFirstBit, // allows draws to modify kModifyStencilClip_StateBit = kFirstBit, // allows draws to modify
// stencil bits used for // stencil bits used for

View File

@ -480,7 +480,7 @@ void GrGpuGL::onResetContext() {
GL_CALL(Disable(GR_GL_CULL_FACE)); GL_CALL(Disable(GR_GL_CULL_FACE));
GL_CALL(FrontFace(GR_GL_CCW)); GL_CALL(FrontFace(GR_GL_CCW));
fHWDrawState.fDrawFace = GrDrawState::kBoth_DrawFace; fHWDrawState.setDrawFace(GrDrawState::kBoth_DrawFace);
GL_CALL(Disable(GR_GL_DITHER)); GL_CALL(Disable(GR_GL_DITHER));
if (kDesktop_GrGLBinding == this->glBinding()) { 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)); 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 // we only ever use lines in hairline mode
GL_CALL(LineWidth(1)); GL_CALL(LineWidth(1));
@ -502,23 +502,22 @@ void GrGpuGL::onResetContext() {
// illegal values // illegal values
//fHWDrawState.fSrcBlend = (GrBlendCoeff)(uint8_t)-1; //fHWDrawState.fSrcBlend = (GrBlendCoeff)(uint8_t)-1;
fHWDrawState.fSrcBlend = (GrBlendCoeff)0xFF; fHWDrawState.setBlendFunc((GrBlendCoeff)-1, (GrBlendCoeff)-1);
fHWDrawState.fDstBlend = (GrBlendCoeff)(uint8_t)-1; fHWDrawState.setBlendConstant(0x00000000);
fHWDrawState.fBlendConstant = 0x00000000;
GL_CALL(BlendColor(0,0,0,0)); 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) { for (int s = 0; s < GrDrawState::kNumStages; ++s) {
fHWDrawState.fTextures[s] = NULL; fHWDrawState.setTexture(s, NULL);
fHWDrawState.fSamplerStates[s].setRadial2Params(-GR_ScalarMax, GrSamplerState* sampler = fHWDrawState.sampler(s);
-GR_ScalarMax, sampler->setRadial2Params(-GR_ScalarMax,
true); -GR_ScalarMax,
fHWDrawState.fSamplerStates[s].setMatrix(GrMatrix::InvalidMatrix()); true);
fHWDrawState.fSamplerStates[s].setConvolutionParams(0, NULL, NULL); sampler->setMatrix(GrMatrix::InvalidMatrix());
sampler->setConvolutionParams(0, NULL, NULL);
} }
fHWBounds.fScissorRect.invalidate(); fHWBounds.fScissorRect.invalidate();
@ -526,7 +525,7 @@ void GrGpuGL::onResetContext() {
GL_CALL(Disable(GR_GL_SCISSOR_TEST)); GL_CALL(Disable(GR_GL_SCISSOR_TEST));
fHWBounds.fViewportRect.invalidate(); fHWBounds.fViewportRect.invalidate();
fHWDrawState.fStencilSettings.invalidate(); fHWDrawState.stencil()->invalidate();
fHWStencilClip = false; fHWStencilClip = false;
fClipInStencil = false; fClipInStencil = false;
@ -536,7 +535,7 @@ void GrGpuGL::onResetContext() {
fHWGeometryState.fArrayPtrsDirty = true; fHWGeometryState.fArrayPtrsDirty = true;
GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_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 // we assume these values
if (this->glCaps().fUnpackRowLengthSupport) { if (this->glCaps().fUnpackRowLengthSupport) {
@ -1191,7 +1190,7 @@ bool GrGpuGL::attachStencilBufferToRenderTarget(GrStencilBuffer* sb,
GrGLStencilBuffer* glsb = (GrGLStencilBuffer*) sb; GrGLStencilBuffer* glsb = (GrGLStencilBuffer*) sb;
GrGLuint rb = glsb->renderbufferID(); GrGLuint rb = glsb->renderbufferID();
fHWDrawState.fRenderTarget = NULL; fHWDrawState.setRenderTarget(NULL);
GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fbo)); GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, fbo));
GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
GR_GL_STENCIL_ATTACHMENT, GR_GL_STENCIL_ATTACHMENT,
@ -1276,9 +1275,9 @@ GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
} }
void GrGpuGL::flushScissor(const GrIRect* rect) { void GrGpuGL::flushScissor(const GrIRect* rect) {
GrAssert(NULL != fCurrDrawState.fRenderTarget); GrAssert(this->getRenderTarget() != NULL);
const GrGLIRect& vp = const GrGLIRect& vp =
((GrGLRenderTarget*)fCurrDrawState.fRenderTarget)->getViewport(); ((GrGLRenderTarget*)this->getRenderTarget())->getViewport();
GrGLIRect scissor; GrGLIRect scissor;
if (NULL != rect) { if (NULL != rect) {
@ -1307,15 +1306,17 @@ void GrGpuGL::flushScissor(const GrIRect* rect) {
} }
void GrGpuGL::onClear(const GrIRect* rect, GrColor color) { void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
// parent class should never let us get here with no RT // parent class should never let us get here with no RT
GrAssert(NULL != fCurrDrawState.fRenderTarget); GrAssert(rt != NULL);
GrIRect clippedRect; GrIRect clippedRect;
if (NULL != rect) { if (NULL != rect) {
// flushScissor expects rect to be clipped to the target. // flushScissor expects rect to be clipped to the target.
clippedRect = *rect; clippedRect = *rect;
GrIRect rtRect = SkIRect::MakeWH(fCurrDrawState.fRenderTarget->width(), GrIRect rtRect = SkIRect::MakeWH(rt->width(),
fCurrDrawState.fRenderTarget->height()); rt->height());
if (clippedRect.intersect(rtRect)) { if (clippedRect.intersect(rtRect)) {
rect = &clippedRect; rect = &clippedRect;
} else { } else {
@ -1329,7 +1330,7 @@ void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
static const GrGLfloat scale255 = 1.f / 255.f; static const GrGLfloat scale255 = 1.f / 255.f;
a = GrColorUnpackA(color) * scale255; a = GrColorUnpackA(color) * scale255;
GrGLfloat scaleRGB = scale255; GrGLfloat scaleRGB = scale255;
if (GrPixelConfigIsUnpremultiplied(fCurrDrawState.fRenderTarget->config())) { if (GrPixelConfigIsUnpremultiplied(rt->config())) {
scaleRGB *= a; scaleRGB *= a;
} }
r = GrColorUnpackR(color) * scaleRGB; r = GrColorUnpackR(color) * scaleRGB;
@ -1337,13 +1338,13 @@ void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
b = GrColorUnpackB(color) * scaleRGB; b = GrColorUnpackB(color) * scaleRGB;
GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE)); 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(ClearColor(r, g, b, a));
GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT)); GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT));
} }
void GrGpuGL::clearStencil() { void GrGpuGL::clearStencil() {
if (NULL == fCurrDrawState.fRenderTarget) { if (NULL == this->getRenderTarget()) {
return; return;
} }
@ -1356,17 +1357,17 @@ void GrGpuGL::clearStencil() {
GL_CALL(StencilMask(0xffffffff)); GL_CALL(StencilMask(0xffffffff));
GL_CALL(ClearStencil(0)); GL_CALL(ClearStencil(0));
GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT)); GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
fHWDrawState.fStencilSettings.invalidate(); fHWDrawState.stencil()->invalidate();
} }
void GrGpuGL::clearStencilClip(const GrIRect& rect, bool insideClip) { void GrGpuGL::clearStencilClip(const GrIRect& rect, bool insideClip) {
GrAssert(NULL != fCurrDrawState.fRenderTarget); GrRenderTarget* rt = this->getRenderTarget();
GrAssert(NULL != rt);
// this should only be called internally when we know we have a // this should only be called internally when we know we have a
// stencil buffer. // stencil buffer.
GrAssert(NULL != fCurrDrawState.fRenderTarget->getStencilBuffer()); GrAssert(NULL != rt->getStencilBuffer());
GrGLint stencilBitCount = GrGLint stencilBitCount = rt->getStencilBuffer()->bits();
fCurrDrawState.fRenderTarget->getStencilBuffer()->bits();
#if 0 #if 0
GrAssert(stencilBitCount > 0); GrAssert(stencilBitCount > 0);
GrGLint clipStencilMask = (1 << (stencilBitCount - 1)); GrGLint clipStencilMask = (1 << (stencilBitCount - 1));
@ -1389,7 +1390,7 @@ void GrGpuGL::clearStencilClip(const GrIRect& rect, bool insideClip) {
GL_CALL(StencilMask(clipStencilMask)); GL_CALL(StencilMask(clipStencilMask));
GL_CALL(ClearStencil(value)); GL_CALL(ClearStencil(value));
GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT)); GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
fHWDrawState.fStencilSettings.invalidate(); fHWDrawState.stencil()->invalidate();
} }
void GrGpuGL::onForceRenderTargetFlush() { void GrGpuGL::onForceRenderTargetFlush() {
@ -1445,13 +1446,12 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target,
// resolve the render target if necessary // resolve the render target if necessary
GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target); GrGLRenderTarget* tgt = static_cast<GrGLRenderTarget*>(target);
GrAutoTPtrValueRestore<GrRenderTarget*> autoTargetRestore; GrDrawState::AutoRenderTargetRestore arr;
switch (tgt->getResolveType()) { switch (tgt->getResolveType()) {
case GrGLRenderTarget::kCantResolve_ResolveType: case GrGLRenderTarget::kCantResolve_ResolveType:
return false; return false;
case GrGLRenderTarget::kAutoResolves_ResolveType: case GrGLRenderTarget::kAutoResolves_ResolveType:
autoTargetRestore.save(&fCurrDrawState.fRenderTarget); arr.set(this->drawState(), target);
fCurrDrawState.fRenderTarget = target;
this->flushRenderTarget(&GrIRect::EmptyIRect()); this->flushRenderTarget(&GrIRect::EmptyIRect());
break; break;
case GrGLRenderTarget::kCanResolve_ResolveType: case GrGLRenderTarget::kCanResolve_ResolveType:
@ -1549,10 +1549,11 @@ bool GrGpuGL::onReadPixels(GrRenderTarget* target,
void GrGpuGL::flushRenderTarget(const GrIRect* bound) { void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
GrAssert(NULL != fCurrDrawState.fRenderTarget); GrAssert(this->getRenderTarget() != NULL);
GrGLRenderTarget* rt = (GrGLRenderTarget*)fCurrDrawState.fRenderTarget; GrGLRenderTarget* rt =
if (fHWDrawState.fRenderTarget != fCurrDrawState.fRenderTarget) { static_cast<GrGLRenderTarget*>(this->getRenderTarget());
if (fHWDrawState.getRenderTarget() != rt) {
GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID())); GL_CALL(BindFramebuffer(GR_GL_FRAMEBUFFER, rt->renderFBOID()));
#if GR_COLLECT_STATS #if GR_COLLECT_STATS
++fStats.fRenderTargetChngCnt; ++fStats.fRenderTargetChngCnt;
@ -1565,7 +1566,7 @@ void GrGpuGL::flushRenderTarget(const GrIRect* bound) {
} }
#endif #endif
fDirtyFlags.fRenderTargetChanged = true; fDirtyFlags.fRenderTargetChanged = true;
fHWDrawState.fRenderTarget = fCurrDrawState.fRenderTarget; fHWDrawState.setRenderTarget(rt);
const GrGLIRect& vp = rt->getViewport(); const GrGLIRect& vp = rt->getViewport();
if (fHWBounds.fViewportRect != vp) { if (fHWBounds.fViewportRect != vp) {
vp.pushToGLViewport(this->glInterface()); vp.pushToGLViewport(this->glInterface());
@ -1682,7 +1683,7 @@ void GrGpuGL::resolveRenderTarget(GrGLRenderTarget* rt) {
#endif #endif
// make sure we go through flushRenderTarget() since we've modified // make sure we go through flushRenderTarget() since we've modified
// the bound DRAW FBO ID. // the bound DRAW FBO ID.
fHWDrawState.fRenderTarget = NULL; fHWDrawState.setRenderTarget(NULL);
const GrGLIRect& vp = rt->getViewport(); const GrGLIRect& vp = rt->getViewport();
const GrIRect dirtyRect = rt->getResolveRect(); const GrIRect dirtyRect = rt->getResolveRect();
GrGLIRect r; GrGLIRect r;
@ -1754,21 +1755,24 @@ GR_STATIC_ASSERT(6 == kZero_StencilOp);
GR_STATIC_ASSERT(7 == kInvert_StencilOp); GR_STATIC_ASSERT(7 == kInvert_StencilOp);
void GrGpuGL::flushStencil() { 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 // use stencil for clipping if clipping is enabled and the clip
// has been written into the stencil. // has been written into the stencil.
bool stencilClip = fClipInStencil && bool stencilClip = fClipInStencil && drawState.isClipState();
(kClip_StateBit & fCurrDrawState.fFlagBits);
bool modifyingStencilClip = drawState.isStateFlagEnabled(
kModifyStencilClip_StateBit);
bool stencilChange = fHWStencilClip != stencilClip || bool stencilChange = fHWStencilClip != stencilClip ||
fHWDrawState.fStencilSettings != *settings || fHWDrawState.getStencil() != *settings ||
((fHWDrawState.fFlagBits & kModifyStencilClip_StateBit) != (fHWDrawState.isStateFlagEnabled(kModifyStencilClip_StateBit) !=
(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit)); modifyingStencilClip);
if (stencilChange) { if (stencilChange) {
// we can't simultaneously perform stencil-clipping and modify the stencil clip // we can't simultaneously perform stencil-clipping and modify the stencil clip
GrAssert(!stencilClip || !(fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit)); GrAssert(!stencilClip || !drawState.isStateFlagEnabled(kModifyStencilClip_StateBit));
if (settings->isDisabled()) { if (settings->isDisabled()) {
if (stencilClip) { if (stencilClip) {
@ -1793,15 +1797,14 @@ void GrGpuGL::flushStencil() {
} }
#endif #endif
int stencilBits = 0; int stencilBits = 0;
GrStencilBuffer* stencilBuffer = GrStencilBuffer* stencilBuffer =
fCurrDrawState.fRenderTarget->getStencilBuffer(); drawState.getRenderTarget()->getStencilBuffer();
if (NULL != stencilBuffer) { if (NULL != stencilBuffer) {
stencilBits = stencilBuffer->bits(); stencilBits = stencilBuffer->bits();
} }
// TODO: dynamically attach a stencil buffer // TODO: dynamically attach a stencil buffer
GrAssert(stencilBits || GrAssert(stencilBits ||
(GrStencilSettings::gDisabled == (GrStencilSettings::gDisabled == *settings));
fCurrDrawState.fStencilSettings));
GrGLuint clipStencilMask = 0; GrGLuint clipStencilMask = 0;
GrGLuint userStencilMask = ~0; GrGLuint userStencilMask = ~0;
@ -1815,7 +1818,7 @@ void GrGpuGL::flushStencil() {
unsigned int frontWriteMask = settings->fFrontWriteMask; unsigned int frontWriteMask = settings->fFrontWriteMask;
GrGLenum frontFunc; GrGLenum frontFunc;
if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) { if (modifyingStencilClip) {
GrAssert(settings->fFrontFunc < kBasicStencilFuncCount); GrAssert(settings->fFrontFunc < kBasicStencilFuncCount);
frontFunc = grToGLStencilFunc[settings->fFrontFunc]; frontFunc = grToGLStencilFunc[settings->fFrontFunc];
@ -1847,7 +1850,7 @@ void GrGpuGL::flushStencil() {
unsigned int backWriteMask = settings->fBackWriteMask; unsigned int backWriteMask = settings->fBackWriteMask;
if (fCurrDrawState.fFlagBits & kModifyStencilClip_StateBit) { if (modifyingStencilClip) {
GrAssert(settings->fBackFunc < kBasicStencilFuncCount); GrAssert(settings->fBackFunc < kBasicStencilFuncCount);
backFunc = grToGLStencilFunc[settings->fBackFunc]; backFunc = grToGLStencilFunc[settings->fBackFunc];
} else { } else {
@ -1885,7 +1888,7 @@ void GrGpuGL::flushStencil() {
grToGLStencilOp[settings->fFrontPassOp])); grToGLStencilOp[settings->fFrontPassOp]));
} }
} }
fHWDrawState.fStencilSettings = fCurrDrawState.fStencilSettings; *fHWDrawState.stencil() = *settings;
fHWStencilClip = stencilClip; fHWStencilClip = stencilClip;
} }
} }
@ -1897,6 +1900,8 @@ void GrGpuGL::flushAAState(GrPrimitiveType type) {
// we prefer smooth lines over multisampled lines // we prefer smooth lines over multisampled lines
// msaa should be disabled if drawing smooth lines. // msaa should be disabled if drawing smooth lines.
GrRenderTarget* rt = this->getRenderTarget();
if (GrIsPrimTypeLines(type)) { if (GrIsPrimTypeLines(type)) {
bool smooth = this->willUseHWAALines(); bool smooth = this->willUseHWAALines();
if (!fHWAAState.fSmoothLineEnabled && smooth) { if (!fHWAAState.fSmoothLineEnabled && smooth) {
@ -1906,13 +1911,13 @@ void GrGpuGL::flushAAState(GrPrimitiveType type) {
GL_CALL(Disable(GR_GL_LINE_SMOOTH)); GL_CALL(Disable(GR_GL_LINE_SMOOTH));
fHWAAState.fSmoothLineEnabled = false; fHWAAState.fSmoothLineEnabled = false;
} }
if (fCurrDrawState.fRenderTarget->isMultisampled() && if (rt->isMultisampled() &&
fHWAAState.fMSAAEnabled) { fHWAAState.fMSAAEnabled) {
GL_CALL(Disable(GR_GL_MULTISAMPLE)); GL_CALL(Disable(GR_GL_MULTISAMPLE));
fHWAAState.fMSAAEnabled = false; fHWAAState.fMSAAEnabled = false;
} }
} else if (fCurrDrawState.fRenderTarget->isMultisampled() && } else if (rt->isMultisampled() &&
SkToBool(kHWAntialias_StateBit & fCurrDrawState.fFlagBits) != this->getDrawState().isHWAntialiasState() !=
fHWAAState.fMSAAEnabled) { fHWAAState.fMSAAEnabled) {
if (fHWAAState.fMSAAEnabled) { if (fHWAAState.fMSAAEnabled) {
GL_CALL(Disable(GR_GL_MULTISAMPLE)); GL_CALL(Disable(GR_GL_MULTISAMPLE));
@ -1933,12 +1938,11 @@ void GrGpuGL::flushBlend(GrPrimitiveType type,
GL_CALL(Enable(GR_GL_BLEND)); GL_CALL(Enable(GR_GL_BLEND));
fHWBlendDisabled = false; fHWBlendDisabled = false;
} }
if (kSA_BlendCoeff != fHWDrawState.fSrcBlend || if (kSA_BlendCoeff != fHWDrawState.getSrcBlendCoeff() ||
kISA_BlendCoeff != fHWDrawState.fDstBlend) { kISA_BlendCoeff != fHWDrawState.getDstBlendCoeff()) {
GL_CALL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff], GL_CALL(BlendFunc(gXfermodeCoeff2Blend[kSA_BlendCoeff],
gXfermodeCoeff2Blend[kISA_BlendCoeff])); gXfermodeCoeff2Blend[kISA_BlendCoeff]));
fHWDrawState.fSrcBlend = kSA_BlendCoeff; fHWDrawState.setBlendFunc(kSA_BlendCoeff, kISA_BlendCoeff);
fHWDrawState.fDstBlend = kISA_BlendCoeff;
} }
} else { } else {
// any optimization to disable blending should // any optimization to disable blending should
@ -1955,25 +1959,25 @@ void GrGpuGL::flushBlend(GrPrimitiveType type,
fHWBlendDisabled = blendOff; fHWBlendDisabled = blendOff;
} }
if (!blendOff) { if (!blendOff) {
if (fHWDrawState.fSrcBlend != srcCoeff || if (fHWDrawState.getSrcBlendCoeff() != srcCoeff ||
fHWDrawState.fDstBlend != dstCoeff) { fHWDrawState.getDstBlendCoeff() != dstCoeff) {
GL_CALL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff], GL_CALL(BlendFunc(gXfermodeCoeff2Blend[srcCoeff],
gXfermodeCoeff2Blend[dstCoeff])); gXfermodeCoeff2Blend[dstCoeff]));
fHWDrawState.fSrcBlend = srcCoeff; fHWDrawState.setBlendFunc(srcCoeff, dstCoeff);
fHWDrawState.fDstBlend = dstCoeff;
} }
GrColor blendConstant = this->getDrawState().getBlendConstant();
if ((BlendCoeffReferencesConstant(srcCoeff) || if ((BlendCoeffReferencesConstant(srcCoeff) ||
BlendCoeffReferencesConstant(dstCoeff)) && BlendCoeffReferencesConstant(dstCoeff)) &&
fHWDrawState.fBlendConstant != fCurrDrawState.fBlendConstant) { fHWDrawState.getBlendConstant() != blendConstant) {
float c[] = { float c[] = {
GrColorUnpackR(fCurrDrawState.fBlendConstant) / 255.f, GrColorUnpackR(blendConstant) / 255.f,
GrColorUnpackG(fCurrDrawState.fBlendConstant) / 255.f, GrColorUnpackG(blendConstant) / 255.f,
GrColorUnpackB(fCurrDrawState.fBlendConstant) / 255.f, GrColorUnpackB(blendConstant) / 255.f,
GrColorUnpackA(fCurrDrawState.fBlendConstant) / 255.f GrColorUnpackA(blendConstant) / 255.f
}; };
GL_CALL(BlendColor(c[0], c[1], c[2], c[3])); GL_CALL(BlendColor(c[0], c[1], c[2], c[3]));
fHWDrawState.fBlendConstant = fCurrDrawState.fBlendConstant; fHWDrawState.setBlendConstant(blendConstant);
} }
} }
} }
@ -2033,12 +2037,13 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
// GrGpu::setupClipAndFlushState should have already checked this // GrGpu::setupClipAndFlushState should have already checked this
// and bailed if not true. // and bailed if not true.
GrAssert(NULL != fCurrDrawState.fRenderTarget); GrAssert(this->getRenderTarget() != NULL);
for (int s = 0; s < GrDrawState::kNumStages; ++s) { for (int s = 0; s < GrDrawState::kNumStages; ++s) {
// bind texture and set sampler state // bind texture and set sampler state
if (this->isStageEnabled(s)) { if (this->isStageEnabled(s)) {
GrGLTexture* nextTexture = (GrGLTexture*)fCurrDrawState.fTextures[s]; GrGLTexture* nextTexture =
static_cast<GrGLTexture*>(this->drawState()->getTexture(s));
// true for now, but maybe not with GrEffect. // true for now, but maybe not with GrEffect.
GrAssert(NULL != nextTexture); GrAssert(NULL != nextTexture);
@ -2052,20 +2057,20 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
resolveRenderTarget(texRT); resolveRenderTarget(texRT);
} }
if (fHWDrawState.fTextures[s] != nextTexture) { if (fHWDrawState.getTexture(s) != nextTexture) {
setTextureUnit(s); setTextureUnit(s);
GL_CALL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID())); GL_CALL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID()));
#if GR_COLLECT_STATS #if GR_COLLECT_STATS
++fStats.fTextureChngCnt; ++fStats.fTextureChngCnt;
#endif #endif
//GrPrintf("---- bindtexture %d\n", nextTexture->textureID()); //GrPrintf("---- bindtexture %d\n", nextTexture->textureID());
fHWDrawState.fTextures[s] = nextTexture; fHWDrawState.setTexture(s, nextTexture);
// The texture matrix has to compensate for texture width/height // The texture matrix has to compensate for texture width/height
// and NPOT-embedded-in-POT // and NPOT-embedded-in-POT
fDirtyFlags.fTextureChangedMask |= (1 << s); fDirtyFlags.fTextureChangedMask |= (1 << s);
} }
const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s]; const GrSamplerState& sampler = this->getSampler(s);
ResetTimestamp timestamp; ResetTimestamp timestamp;
const GrGLTexture::TexParams& oldTexParams = const GrGLTexture::TexParams& oldTexParams =
nextTexture->getCachedTexParams(&timestamp); nextTexture->getCachedTexParams(&timestamp);
@ -2117,7 +2122,7 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
GrIRect* rect = NULL; GrIRect* rect = NULL;
GrIRect clipBounds; GrIRect clipBounds;
if ((fCurrDrawState.fFlagBits & kClip_StateBit) && if (this->getDrawState().isClipState() &&
fClip.hasConservativeBounds()) { fClip.hasConservativeBounds()) {
fClip.getConservativeBounds().roundOut(&clipBounds); fClip.getConservativeBounds().roundOut(&clipBounds);
rect = &clipBounds; rect = &clipBounds;
@ -2125,19 +2130,19 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
this->flushRenderTarget(rect); this->flushRenderTarget(rect);
this->flushAAState(type); this->flushAAState(type);
if ((fCurrDrawState.fFlagBits & kDither_StateBit) != if (this->getDrawState().isDitherState() !=
(fHWDrawState.fFlagBits & kDither_StateBit)) { fHWDrawState.isDitherState()) {
if (fCurrDrawState.fFlagBits & kDither_StateBit) { if (this->getDrawState().isDitherState()) {
GL_CALL(Enable(GR_GL_DITHER)); GL_CALL(Enable(GR_GL_DITHER));
} else { } else {
GL_CALL(Disable(GR_GL_DITHER)); GL_CALL(Disable(GR_GL_DITHER));
} }
} }
if ((fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) != if (this->getDrawState().isColorWriteDisabled() !=
(fHWDrawState.fFlagBits & kNoColorWrites_StateBit)) { fHWDrawState.isColorWriteDisabled()) {
GrGLenum mask; GrGLenum mask;
if (fCurrDrawState.fFlagBits & kNoColorWrites_StateBit) { if (this->getDrawState().isColorWriteDisabled()) {
mask = GR_GL_FALSE; mask = GR_GL_FALSE;
} else { } else {
mask = GR_GL_TRUE; mask = GR_GL_TRUE;
@ -2145,8 +2150,8 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
GL_CALL(ColorMask(mask, mask, mask, mask)); GL_CALL(ColorMask(mask, mask, mask, mask));
} }
if (fHWDrawState.fDrawFace != fCurrDrawState.fDrawFace) { if (fHWDrawState.getDrawFace() != this->getDrawFace()) {
switch (fCurrDrawState.fDrawFace) { switch (this->getDrawFace()) {
case GrDrawState::kCCW_DrawFace: case GrDrawState::kCCW_DrawFace:
GL_CALL(Enable(GR_GL_CULL_FACE)); GL_CALL(Enable(GR_GL_CULL_FACE));
GL_CALL(CullFace(GR_GL_BACK)); GL_CALL(CullFace(GR_GL_BACK));
@ -2161,24 +2166,27 @@ bool GrGpuGL::flushGLStateCommon(GrPrimitiveType type) {
default: default:
GrCrash("Unknown draw face."); GrCrash("Unknown draw face.");
} }
fHWDrawState.fDrawFace = fCurrDrawState.fDrawFace; fHWDrawState.setDrawFace(this->getDrawFace());
} }
#if GR_DEBUG #if GR_DEBUG
// check for circular rendering // check for circular rendering
for (int s = 0; s < GrDrawState::kNumStages; ++s) { for (int s = 0; s < GrDrawState::kNumStages; ++s) {
GrAssert(!this->isStageEnabled(s) || GrAssert(!this->isStageEnabled(s) ||
NULL == fCurrDrawState.fRenderTarget || NULL == this->getRenderTarget() ||
NULL == fCurrDrawState.fTextures[s] || NULL == this->getTexture(s) ||
fCurrDrawState.fTextures[s]->asRenderTarget() != this->getTexture(s)->asRenderTarget() !=
fCurrDrawState.fRenderTarget); this->getRenderTarget());
} }
#endif #endif
flushStencil(); this->flushStencil();
// the flushStencil() function called above detecs a change in the
// kModifyStencilClip_StateBit flag. Therefore this copy must happen after
// flushStencil()
fHWDrawState.copyStateFlags(this->getDrawState());
// flushStencil may look at the private state bits, so keep it before this.
fHWDrawState.fFlagBits = fCurrDrawState.fFlagBits;
return true; return true;
} }
@ -2210,22 +2218,22 @@ void GrGpuGL::notifyIndexBufferDelete(const GrGLIndexBuffer* buffer) {
void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) { void GrGpuGL::notifyRenderTargetDelete(GrRenderTarget* renderTarget) {
GrAssert(NULL != renderTarget); GrAssert(NULL != renderTarget);
if (fCurrDrawState.fRenderTarget == renderTarget) { if (this->getRenderTarget() == renderTarget) {
fCurrDrawState.fRenderTarget = NULL; this->setRenderTarget(NULL);
} }
if (fHWDrawState.fRenderTarget == renderTarget) { if (this->getRenderTarget() == renderTarget) {
fHWDrawState.fRenderTarget = NULL; fHWDrawState.setRenderTarget(NULL);
} }
} }
void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) { void GrGpuGL::notifyTextureDelete(GrGLTexture* texture) {
for (int s = 0; s < GrDrawState::kNumStages; ++s) { for (int s = 0; s < GrDrawState::kNumStages; ++s) {
if (fCurrDrawState.fTextures[s] == texture) { if (this->getTexture(s) == texture) {
fCurrDrawState.fTextures[s] = NULL; this->setTexture(s, NULL);
} }
if (fHWDrawState.fTextures[s] == texture) { if (fHWDrawState.getTexture(s) == texture) {
// deleting bound texture does implied bind to 0 // deleting bound texture does implied bind to 0
fHWDrawState.fTextures[s] = NULL; this->setTexture(s, NULL);
} }
} }
} }

View File

@ -343,7 +343,7 @@ const GrMatrix& GrGpuGLShaders::getHWSamplerMatrix(int stage) {
if (GrGLProgram::kSetAsAttribute == if (GrGLProgram::kSetAsAttribute ==
fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) { fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) {
return fHWDrawState.fSamplerStates[stage].getMatrix(); return fHWDrawState.getSampler(stage).getMatrix();
} else { } else {
return fProgramData->fTextureMatrices[stage]; return fProgramData->fTextureMatrices[stage];
} }
@ -351,9 +351,9 @@ const GrMatrix& GrGpuGLShaders::getHWSamplerMatrix(int stage) {
void GrGpuGLShaders::recordHWSamplerMatrix(int stage, const GrMatrix& matrix) { void GrGpuGLShaders::recordHWSamplerMatrix(int stage, const GrMatrix& matrix) {
GrAssert(fProgramData); GrAssert(fProgramData);
if (GrGLProgram::kSetAsAttribute == if (GrGLProgram::kSetAsAttribute ==
fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) { fProgramData->fUniLocations.fStages[stage].fTextureMatrixUni) {
fHWDrawState.fSamplerStates[stage].setMatrix(matrix); fHWDrawState.sampler(stage)->setMatrix(matrix);
} else { } else {
fProgramData->fTextureMatrices[stage] = matrix; fProgramData->fTextureMatrices[stage] = matrix;
} }
@ -388,47 +388,68 @@ void GrGpuGLShaders::onResetContext() {
} }
void GrGpuGLShaders::flushViewMatrix() { void GrGpuGLShaders::flushViewMatrix() {
GrAssert(NULL != fCurrDrawState.fRenderTarget);
GrMatrix m;
m.setAll(
GrIntToScalar(2) / fCurrDrawState.fRenderTarget->width(), 0, -GR_Scalar1,
0,-GrIntToScalar(2) / fCurrDrawState.fRenderTarget->height(), GR_Scalar1,
0, 0, GrMatrix::I()[8]);
m.setConcat(m, fCurrDrawState.fViewMatrix);
// ES doesn't allow you to pass true to the transpose param, const GrMatrix* hwViewMatrix;
// so do our own transpose // If we are using a uniform for the matrix then the cached value is
GrGLfloat mt[] = { // stored with each program. If we are using an attribute than it is global
GrScalarToFloat(m[GrMatrix::kMScaleX]), // to all programs.
GrScalarToFloat(m[GrMatrix::kMSkewY]), if (GrGLProgram::kSetAsAttribute ==
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) { fProgramData->fUniLocations.fViewMatrixUni) {
int baseIdx = GrGLProgram::ViewMatrixAttributeIdx(); hwViewMatrix = &fHWDrawState.getViewMatrix();
GL_CALL(VertexAttrib4fv(baseIdx + 0, mt+0));
GL_CALL(VertexAttrib4fv(baseIdx + 1, mt+3));
GL_CALL(VertexAttrib4fv(baseIdx + 2, mt+6));
} else { } else {
GrAssert(GrGLProgram::kUnusedUniform != hwViewMatrix = &fProgramData->fViewMatrix;
fProgramData->fUniLocations.fViewMatrixUni); }
GL_CALL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni,
1, false, mt)); if (*hwViewMatrix != this->getViewMatrix()) {
GrRenderTarget* rt = this->getRenderTarget();
GrAssert(NULL != rt);
GrMatrix m;
m.setAll(
GrIntToScalar(2) / rt->width(), 0, -GR_Scalar1,
0,-GrIntToScalar(2) / rt->height(), GR_Scalar1,
0, 0, GrMatrix::I()[8]);
m.setConcat(m, this->getViewMatrix());
// ES doesn't allow you to pass true to the transpose param,
// so do our own transpose
GrGLfloat mt[] = {
GrScalarToFloat(m[GrMatrix::kMScaleX]),
GrScalarToFloat(m[GrMatrix::kMSkewY]),
GrScalarToFloat(m[GrMatrix::kMPersp0]),
GrScalarToFloat(m[GrMatrix::kMSkewX]),
GrScalarToFloat(m[GrMatrix::kMScaleY]),
GrScalarToFloat(m[GrMatrix::kMPersp1]),
GrScalarToFloat(m[GrMatrix::kMTransX]),
GrScalarToFloat(m[GrMatrix::kMTransY]),
GrScalarToFloat(m[GrMatrix::kMPersp2])
};
if (GrGLProgram::kSetAsAttribute ==
fProgramData->fUniLocations.fViewMatrixUni) {
int baseIdx = GrGLProgram::ViewMatrixAttributeIdx();
GL_CALL(VertexAttrib4fv(baseIdx + 0, mt+0));
GL_CALL(VertexAttrib4fv(baseIdx + 1, mt+3));
GL_CALL(VertexAttrib4fv(baseIdx + 2, mt+6));
} else {
GrAssert(GrGLProgram::kUnusedUniform !=
fProgramData->fUniLocations.fViewMatrixUni);
GL_CALL(UniformMatrix3fv(fProgramData->fUniLocations.fViewMatrixUni,
1, false, mt));
}
if (GrGLProgram::kSetAsAttribute ==
fProgramData->fUniLocations.fViewMatrixUni) {
fHWDrawState.setViewMatrix(this->getViewMatrix());
} else {
fProgramData->fViewMatrix = this->getViewMatrix();
}
} }
} }
void GrGpuGLShaders::flushTextureDomain(int s) { void GrGpuGLShaders::flushTextureDomain(int s) {
const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTexDomUni; const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTexDomUni;
if (GrGLProgram::kUnusedUniform != uni) { if (GrGLProgram::kUnusedUniform != uni) {
const GrRect &texDom = const GrRect &texDom = this->getSampler(s).getTextureDomain();
fCurrDrawState.fSamplerStates[s].getTextureDomain();
if (((1 << s) & fDirtyFlags.fTextureChangedMask) || if (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
fProgramData->fTextureDomain[s] != texDom) { fProgramData->fTextureDomain[s] != texDom) {
@ -442,7 +463,7 @@ void GrGpuGLShaders::flushTextureDomain(int s) {
GrScalarToFloat(texDom.bottom()) GrScalarToFloat(texDom.bottom())
}; };
GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; GrGLTexture* texture = (GrGLTexture*) this->getTexture(s);
GrGLTexture::Orientation orientation = texture->orientation(); GrGLTexture::Orientation orientation = texture->orientation();
// vertical flip if necessary // vertical flip if necessary
@ -461,19 +482,18 @@ void GrGpuGLShaders::flushTextureDomain(int s) {
void GrGpuGLShaders::flushTextureMatrix(int s) { void GrGpuGLShaders::flushTextureMatrix(int s) {
const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTextureMatrixUni; const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTextureMatrixUni;
GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; GrGLTexture* texture = (GrGLTexture*) this->getTexture(s);
if (NULL != texture) { if (NULL != texture) {
const GrMatrix& hwMat = fHWDrawState.getSampler(s).getMatrix();
const GrMatrix& currMat = this->getSampler(s).getMatrix();
if (GrGLProgram::kUnusedUniform != uni && if (GrGLProgram::kUnusedUniform != uni &&
(((1 << s) & fDirtyFlags.fTextureChangedMask) || (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
getHWSamplerMatrix(s) != getSamplerMatrix(s))) { hwMat != currMat)) {
GrAssert(NULL != fCurrDrawState.fTextures[s]); GrAssert(NULL != texture);
GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; GrMatrix m = currMat;
GrSamplerState::SampleMode mode = this->getSampler(s).getSampleMode();
GrMatrix m = getSamplerMatrix(s);
GrSamplerState::SampleMode mode =
fCurrDrawState.fSamplerStates[s].getSampleMode();
AdjustTextureMatrix(texture, mode, &m); AdjustTextureMatrix(texture, mode, &m);
// ES doesn't allow you to pass true to the transpose param, // ES doesn't allow you to pass true to the transpose param,
@ -499,7 +519,7 @@ void GrGpuGLShaders::flushTextureMatrix(int s) {
} else { } else {
GL_CALL(UniformMatrix3fv(uni, 1, false, mt)); GL_CALL(UniformMatrix3fv(uni, 1, false, mt));
} }
recordHWSamplerMatrix(s, getSamplerMatrix(s)); this->recordHWSamplerMatrix(s, currMat);
} }
} }
} }
@ -507,7 +527,7 @@ void GrGpuGLShaders::flushTextureMatrix(int s) {
void GrGpuGLShaders::flushRadial2(int s) { void GrGpuGLShaders::flushRadial2(int s) {
const int &uni = fProgramData->fUniLocations.fStages[s].fRadial2Uni; const int &uni = fProgramData->fUniLocations.fStages[s].fRadial2Uni;
const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s]; const GrSamplerState& sampler = fCurrDrawState.getSampler(s);
if (GrGLProgram::kUnusedUniform != uni && if (GrGLProgram::kUnusedUniform != uni &&
(fProgramData->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() || (fProgramData->fRadial2CenterX1[s] != sampler.getRadial2CenterX1() ||
fProgramData->fRadial2Radius0[s] != sampler.getRadial2Radius0() || fProgramData->fRadial2Radius0[s] != sampler.getRadial2Radius0() ||
@ -539,7 +559,7 @@ void GrGpuGLShaders::flushRadial2(int s) {
} }
void GrGpuGLShaders::flushConvolution(int s) { void GrGpuGLShaders::flushConvolution(int s) {
const GrSamplerState& sampler = fCurrDrawState.fSamplerStates[s]; const GrSamplerState& sampler = this->getSampler(s);
int kernelUni = fProgramData->fUniLocations.fStages[s].fKernelUni; int kernelUni = fProgramData->fUniLocations.fStages[s].fKernelUni;
if (GrGLProgram::kUnusedUniform != kernelUni) { if (GrGLProgram::kUnusedUniform != kernelUni) {
GL_CALL(Uniform1fv(kernelUni, sampler.getKernelWidth(), GL_CALL(Uniform1fv(kernelUni, sampler.getKernelWidth(),
@ -554,7 +574,7 @@ void GrGpuGLShaders::flushConvolution(int s) {
void GrGpuGLShaders::flushTexelSize(int s) { void GrGpuGLShaders::flushTexelSize(int s) {
const int& uni = fProgramData->fUniLocations.fStages[s].fNormalizedTexelSizeUni; const int& uni = fProgramData->fUniLocations.fStages[s].fNormalizedTexelSizeUni;
if (GrGLProgram::kUnusedUniform != uni) { if (GrGLProgram::kUnusedUniform != uni) {
GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; GrGLTexture* texture = (GrGLTexture*) this->getTexture(s);
if (texture->width() != fProgramData->fTextureWidth[s] || if (texture->width() != fProgramData->fTextureWidth[s] ||
texture->height() != fProgramData->fTextureHeight[s]) { texture->height() != fProgramData->fTextureHeight[s]) {
@ -570,13 +590,14 @@ void GrGpuGLShaders::flushTexelSize(int s) {
void GrGpuGLShaders::flushEdgeAAData() { void GrGpuGLShaders::flushEdgeAAData() {
const int& uni = fProgramData->fUniLocations.fEdgesUni; const int& uni = fProgramData->fUniLocations.fEdgesUni;
if (GrGLProgram::kUnusedUniform != uni) { if (GrGLProgram::kUnusedUniform != uni) {
int count = fCurrDrawState.fEdgeAANumEdges;
int count = this->getDrawState().getNumAAEdges();
GrDrawState::Edge edges[GrDrawState::kMaxEdges]; GrDrawState::Edge edges[GrDrawState::kMaxEdges];
// Flip the edges in Y // Flip the edges in Y
float height = float height =
static_cast<float>(fCurrDrawState.fRenderTarget->height()); static_cast<float>(this->getRenderTarget()->height());
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
edges[i] = fCurrDrawState.fEdgeAAEdges[i]; edges[i] = this->getDrawState().getAAEdges()[i];
float b = edges[i].fY; float b = edges[i].fY;
edges[i].fY = -b; edges[i].fY = -b;
edges[i].fZ += b * height; edges[i].fZ += b * height;
@ -599,16 +620,16 @@ void GrGpuGLShaders::flushColor(GrColor color) {
if (this->getGeomSrc().fVertexLayout & kColor_VertexLayoutBit) { if (this->getGeomSrc().fVertexLayout & kColor_VertexLayoutBit) {
// color will be specified per-vertex as an attribute // color will be specified per-vertex as an attribute
// invalidate the const vertex attrib color // invalidate the const vertex attrib color
fHWDrawState.fColor = GrColor_ILLEGAL; fHWDrawState.setColor(GrColor_ILLEGAL);
} else { } else {
switch (desc.fColorInput) { switch (desc.fColorInput) {
case ProgramDesc::kAttribute_ColorInput: case ProgramDesc::kAttribute_ColorInput:
if (fHWDrawState.fColor != color) { if (fHWDrawState.getColor() != color) {
// OpenGL ES only supports the float varities of glVertexAttrib // OpenGL ES only supports the float varities of glVertexAttrib
float c[] = GR_COLOR_TO_VEC4(color); float c[] = GR_COLOR_TO_VEC4(color);
GL_CALL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(), GL_CALL(VertexAttrib4fv(GrGLProgram::ColorAttributeIdx(),
c)); c));
fHWDrawState.fColor = color; fHWDrawState.setColor(color);
} }
break; break;
case ProgramDesc::kUniform_ColorInput: case ProgramDesc::kUniform_ColorInput:
@ -629,13 +650,13 @@ void GrGpuGLShaders::flushColor(GrColor color) {
GrCrash("Unknown color type."); GrCrash("Unknown color type.");
} }
} }
if (fProgramData->fUniLocations.fColorFilterUni GrColor filterColor = this->getDrawState().getColorFilterColor();
!= GrGLProgram::kUnusedUniform int uni = fProgramData->fUniLocations.fColorFilterUni;
&& fProgramData->fColorFilterColor if (uni != GrGLProgram::kUnusedUniform &&
!= fCurrDrawState.fColorFilterColor) { fProgramData->fColorFilterColor != filterColor) {
float c[] = GR_COLOR_TO_VEC4(fCurrDrawState.fColorFilterColor); float c[] = GR_COLOR_TO_VEC4(filterColor);
GL_CALL(Uniform4fv(fProgramData->fUniLocations.fColorFilterUni, 1, c)); GL_CALL(Uniform4fv(uni, 1, c));
fProgramData->fColorFilterColor = fCurrDrawState.fColorFilterColor; fProgramData->fColorFilterColor = filterColor;
} }
} }
@ -648,7 +669,7 @@ bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) {
if (fDirtyFlags.fRenderTargetChanged) { if (fDirtyFlags.fRenderTargetChanged) {
// our coords are in pixel space and the GL matrices map to NDC // our coords are in pixel space and the GL matrices map to NDC
// so if the viewport changed, our matrix is now wrong. // 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 // we assume all shader matrices may be wrong after viewport changes
fProgramCache->invalidateViewMatrices(); fProgramCache->invalidateViewMatrices();
} }
@ -680,22 +701,11 @@ bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) {
} else if (blendOpts & kEmitCoverage_BlendOptFlag) { } else if (blendOpts & kEmitCoverage_BlendOptFlag) {
color = 0xffffffff; color = 0xffffffff;
} else { } else {
color = fCurrDrawState.fColor; color = this->getColor();
} }
this->flushColor(color); this->flushColor(color);
GrMatrix* currViewMatrix; this->flushViewMatrix();
if (GrGLProgram::kSetAsAttribute ==
fProgramData->fUniLocations.fViewMatrixUni) {
currViewMatrix = &fHWDrawState.fViewMatrix;
} else {
currViewMatrix = &fProgramData->fViewMatrix;
}
if (*currViewMatrix != fCurrDrawState.fViewMatrix) {
flushViewMatrix();
*currViewMatrix = fCurrDrawState.fViewMatrix;
}
for (int s = 0; s < GrDrawState::kNumStages; ++s) { for (int s = 0; s < GrDrawState::kNumStages; ++s) {
this->flushTextureMatrix(s); this->flushTextureMatrix(s);
@ -709,7 +719,7 @@ bool GrGpuGLShaders::flushGraphicsState(GrPrimitiveType type) {
this->flushTextureDomain(s); this->flushTextureDomain(s);
} }
this->flushEdgeAAData(); this->flushEdgeAAData();
resetDirtyFlags(); this->resetDirtyFlags();
return true; return true;
} }
@ -856,6 +866,7 @@ void GrGpuGLShaders::setupGeometry(int* startVertex,
void GrGpuGLShaders::buildProgram(GrPrimitiveType type, void GrGpuGLShaders::buildProgram(GrPrimitiveType type,
BlendOptFlags blendOpts, BlendOptFlags blendOpts,
GrBlendCoeff dstCoeff) { GrBlendCoeff dstCoeff) {
const GrDrawState& drawState = this->getDrawState();
ProgramDesc& desc = fCurrentProgram.fProgramDesc; ProgramDesc& desc = fCurrentProgram.fProgramDesc;
// This should already have been caught // This should already have been caught
@ -885,7 +896,7 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type,
desc.fColorFilterXfermode = skipColor ? desc.fColorFilterXfermode = skipColor ?
SkXfermode::kDst_Mode : SkXfermode::kDst_Mode :
fCurrDrawState.fColorFilterXfermode; drawState.getColorFilterMode();
// no reason to do edge aa or look at per-vertex coverage if coverage is // no reason to do edge aa or look at per-vertex coverage if coverage is
// ignored // ignored
@ -897,7 +908,7 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type,
bool colorIsTransBlack = SkToBool(blendOpts & kEmitTransBlack_BlendOptFlag); bool colorIsTransBlack = SkToBool(blendOpts & kEmitTransBlack_BlendOptFlag);
bool colorIsSolidWhite = (blendOpts & kEmitCoverage_BlendOptFlag) || bool colorIsSolidWhite = (blendOpts & kEmitCoverage_BlendOptFlag) ||
(!requiresAttributeColors && (!requiresAttributeColors &&
0xffffffff == fCurrDrawState.fColor); 0xffffffff == this->getColor());
if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) { if (GR_AGGRESSIVE_SHADER_OPTS && colorIsTransBlack) {
desc.fColorInput = ProgramDesc::kTransBlack_ColorInput; desc.fColorInput = ProgramDesc::kTransBlack_ColorInput;
} else if (GR_AGGRESSIVE_SHADER_OPTS && colorIsSolidWhite) { } else if (GR_AGGRESSIVE_SHADER_OPTS && colorIsSolidWhite) {
@ -908,16 +919,15 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type,
desc.fColorInput = ProgramDesc::kAttribute_ColorInput; desc.fColorInput = ProgramDesc::kAttribute_ColorInput;
} }
desc.fEdgeAANumEdges = skipCoverage ? 0 : fCurrDrawState.fEdgeAANumEdges; desc.fEdgeAANumEdges = skipCoverage ? 0 : drawState.getNumAAEdges();
desc.fEdgeAAConcave = desc.fEdgeAANumEdges > 0 && desc.fEdgeAAConcave = desc.fEdgeAANumEdges > 0 &&
SkToBool(fCurrDrawState.fFlagBits & drawState.isConcaveEdgeAAState();
kEdgeAAConcave_StateBit);
int lastEnabledStage = -1; int lastEnabledStage = -1;
if (!skipCoverage && (desc.fVertexLayout & if (!skipCoverage && (desc.fVertexLayout &
GrDrawTarget::kEdge_VertexLayoutBit)) { GrDrawTarget::kEdge_VertexLayoutBit)) {
desc.fVertexEdgeType = fCurrDrawState.fVertexEdgeType; desc.fVertexEdgeType = drawState.getVertexEdgeType();
} else { } else {
// use canonical value when not set to avoid cache misses // use canonical value when not set to avoid cache misses
desc.fVertexEdgeType = GrDrawState::kHairLine_EdgeType; desc.fVertexEdgeType = GrDrawState::kHairLine_EdgeType;
@ -929,19 +939,19 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type,
stage.fOptFlags = 0; stage.fOptFlags = 0;
stage.setEnabled(this->isStageEnabled(s)); stage.setEnabled(this->isStageEnabled(s));
bool skip = s < fCurrDrawState.fFirstCoverageStage ? skipColor : bool skip = s < drawState.getFirstCoverageStage() ? skipColor :
skipCoverage; skipCoverage;
if (!skip && stage.isEnabled()) { if (!skip && stage.isEnabled()) {
lastEnabledStage = s; lastEnabledStage = s;
GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s]; GrGLTexture* texture = (GrGLTexture*) drawState.getTexture(s);
GrAssert(NULL != texture); 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 matrix to invert when orientation is TopDown, so make sure
// we aren't in that case before flagging as identity. // we aren't in that case before flagging as identity.
if (TextureMatrixIsIdentity(texture, sampler)) { if (TextureMatrixIsIdentity(texture, sampler)) {
stage.fOptFlags |= StageDesc::kIdentityMatrix_OptFlagBit; stage.fOptFlags |= StageDesc::kIdentityMatrix_OptFlagBit;
} else if (!getSamplerMatrix(s).hasPerspective()) { } else if (!drawState.getSampler(s).getMatrix().hasPerspective()) {
stage.fOptFlags |= StageDesc::kNoPerspective_OptFlagBit; stage.fOptFlags |= StageDesc::kNoPerspective_OptFlagBit;
} }
switch (sampler.getSampleMode()) { switch (sampler.getSampleMode()) {
@ -1024,7 +1034,7 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type,
} }
} }
if (GrPixelConfigIsUnpremultiplied(fCurrDrawState.fRenderTarget->config())) { if (GrPixelConfigIsUnpremultiplied(drawState.getRenderTarget()->config())) {
desc.fOutputPM = ProgramDesc::kNo_OutputPM; desc.fOutputPM = ProgramDesc::kNo_OutputPM;
} else { } else {
desc.fOutputPM = ProgramDesc::kYes_OutputPM; desc.fOutputPM = ProgramDesc::kYes_OutputPM;
@ -1046,9 +1056,9 @@ void GrGpuGLShaders::buildProgram(GrPrimitiveType type,
// immaterial. // immaterial.
int firstCoverageStage = GrDrawState::kNumStages; int firstCoverageStage = GrDrawState::kNumStages;
desc.fFirstCoverageStage = GrDrawState::kNumStages; desc.fFirstCoverageStage = GrDrawState::kNumStages;
bool hasCoverage = fCurrDrawState.fFirstCoverageStage <= lastEnabledStage; bool hasCoverage = drawState.getFirstCoverageStage() <= lastEnabledStage;
if (hasCoverage) { if (hasCoverage) {
firstCoverageStage = fCurrDrawState.fFirstCoverageStage; firstCoverageStage = drawState.getFirstCoverageStage();
} }
// other coverage inputs // other coverage inputs

View File

@ -102,7 +102,7 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
// simply because the clip has changed if the clip doesn't affect // simply because the clip has changed if the clip doesn't affect
// the rect. // the rect.
bool disabledClip = false; bool disabledClip = false;
if (this->isClipState() && fClip.isRect()) { if (this->getDrawState().isClipState() && fClip.isRect()) {
GrRect clipRect = fClip.getRect(0); GrRect clipRect = fClip.getRect(0);
// If the clip rect touches the edge of the viewport, extended it // If the clip rect touches the edge of the viewport, extended it
@ -132,7 +132,7 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
} }
} }
if (insideClip) { if (insideClip) {
this->disableState(kClip_StateBit); this->drawState()->disableState(GrDrawState::kClip_StateBit);
disabledClip = true; disabledClip = true;
} }
} }
@ -176,7 +176,7 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
fLastRectVertexLayout = layout; fLastRectVertexLayout = layout;
} }
if (disabledClip) { if (disabledClip) {
this->enableState(kClip_StateBit); this->drawState()->disableState(GrDrawState::kClip_StateBit);
} }
} else { } else {
INHERITED::drawRect(rect, matrix, stageMask, srcRects, srcMatrices); INHERITED::drawRect(rect, matrix, stageMask, srcRects, srcMatrices);
@ -328,9 +328,9 @@ void GrInOrderDrawBuffer::reset() {
for (uint32_t i = 0; i < numStates; ++i) { for (uint32_t i = 0; i < numStates; ++i) {
const GrDrawState& dstate = this->accessSavedDrawState(fStates[i]); const GrDrawState& dstate = this->accessSavedDrawState(fStates[i]);
for (int s = 0; s < GrDrawState::kNumStages; ++s) { 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(); int numDraws = fDraws.count();
for (int d = 0; d < numDraws; ++d) { for (int d = 0; d < numDraws; ++d) {
@ -594,14 +594,14 @@ bool GrInOrderDrawBuffer::needsNewState() const {
void GrInOrderDrawBuffer::pushState() { void GrInOrderDrawBuffer::pushState() {
for (int s = 0; s < GrDrawState::kNumStages; ++s) { for (int s = 0; s < GrDrawState::kNumStages; ++s) {
GrSafeRef(fCurrDrawState.fTextures[s]); GrSafeRef(fCurrDrawState.getTexture(s));
} }
GrSafeRef(fCurrDrawState.fRenderTarget); GrSafeRef(fCurrDrawState.getRenderTarget());
this->saveCurrentDrawState(&fStates.push_back()); this->saveCurrentDrawState(&fStates.push_back());
} }
bool GrInOrderDrawBuffer::needsNewClip() const { bool GrInOrderDrawBuffer::needsNewClip() const {
if (fCurrDrawState.fFlagBits & kClip_StateBit) { if (this->getDrawState().isClipState()) {
if (fClips.empty() || (fClipSet && fClips.back() != fClip)) { if (fClips.empty() || (fClipSet && fClips.back() != fClip)) {
return true; return true;
} }

View File

@ -471,7 +471,7 @@ FINISHED:
if (count <= maxEdges) { if (count <= maxEdges) {
// All edges fit; upload all edges and draw all verts as a fan // All edges fit; upload all edges and draw all verts as a fan
fTarget->setVertexSourceToArray(layout, base, count); fTarget->setVertexSourceToArray(layout, base, count);
fTarget->setEdgeAAData(&edges[0], count); fTarget->drawState()->setEdgeAAData(&edges[0], count);
fTarget->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count); fTarget->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count);
} else { } else {
// Upload "maxEdges" edges and verts at a time, and draw as // Upload "maxEdges" edges and verts at a time, and draw as
@ -481,11 +481,11 @@ FINISHED:
base[i] = base[0]; base[i] = base[0];
int size = GR_CT_MIN(count - i, maxEdges); int size = GR_CT_MIN(count - i, maxEdges);
fTarget->setVertexSourceToArray(layout, &base[i], size); fTarget->setVertexSourceToArray(layout, &base[i], size);
fTarget->setEdgeAAData(&edges[i], size); fTarget->drawState()->setEdgeAAData(&edges[i], size);
fTarget->drawNonIndexed(kTriangleFan_PrimitiveType, 0, size); fTarget->drawNonIndexed(kTriangleFan_PrimitiveType, 0, size);
} }
} }
fTarget->setEdgeAAData(NULL, 0); fTarget->drawState()->setEdgeAAData(NULL, 0);
} else { } else {
fTarget->setVertexSourceToArray(layout, base, count); fTarget->setVertexSourceToArray(layout, base, count);
fTarget->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count); fTarget->drawNonIndexed(kTriangleFan_PrimitiveType, 0, count);
@ -534,7 +534,7 @@ FINISHED:
} }
// Draw the resulting polys and upload their edge data. // Draw the resulting polys and upload their edge data.
fTarget->enableState(GrDrawTarget::kEdgeAAConcave_StateBit); fTarget->drawState()->enableState(GrDrawState::kEdgeAAConcave_StateBit);
const GrPointArray& vertices = ptess.vertices(); const GrPointArray& vertices = ptess.vertices();
const GrIndexArray& indices = ptess.indices(); const GrIndexArray& indices = ptess.indices();
const GrDrawState::Edge* edges = ptess.edges(); const GrDrawState::Edge* edges = ptess.edges();
@ -567,12 +567,13 @@ FINISHED:
tri_edges[t++] = edge4; tri_edges[t++] = edge4;
tri_edges[t++] = edge5; tri_edges[t++] = edge5;
} }
fTarget->setEdgeAAData(&tri_edges[0], t); fTarget->drawState()->setEdgeAAData(&tri_edges[0], t);
fTarget->setVertexSourceToArray(layout, &tri_verts[0], 3); fTarget->setVertexSourceToArray(layout, &tri_verts[0], 3);
fTarget->drawNonIndexed(kTriangles_PrimitiveType, 0, 3); fTarget->drawNonIndexed(kTriangles_PrimitiveType, 0, 3);
} }
fTarget->setEdgeAAData(NULL, 0); fTarget->drawState()->setEdgeAAData(NULL, 0);
fTarget->disableState(GrDrawTarget::kEdgeAAConcave_StateBit); fTarget->drawState()->disableState(
GrDrawState::kEdgeAAConcave_StateBit);
return; return;
} }

View File

@ -25,6 +25,7 @@ enum {
void GrTextContext::flushGlyphs() { void GrTextContext::flushGlyphs() {
if (fCurrVertex > 0) { if (fCurrVertex > 0) {
GrDrawTarget::AutoStateRestore asr(fDrawTarget); GrDrawTarget::AutoStateRestore asr(fDrawTarget);
GrDrawState* drawState = fDrawTarget->drawState();
// setup our sampler state for our text texture/atlas // setup our sampler state for our text texture/atlas
GrSamplerState::Filter filter; GrSamplerState::Filter filter;
@ -41,6 +42,7 @@ void GrTextContext::flushGlyphs() {
int nIndices = fCurrVertex + (fCurrVertex >> 1); int nIndices = fCurrVertex + (fCurrVertex >> 1);
GrAssert(fCurrTexture); GrAssert(fCurrTexture);
fDrawTarget->setTexture(kGlyphMaskStage, fCurrTexture); fDrawTarget->setTexture(kGlyphMaskStage, fCurrTexture);
drawState->setTexture(kGlyphMaskStage, fCurrTexture);
if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) {
if (kOne_BlendCoeff != fPaint.fSrcBlendCoeff || if (kOne_BlendCoeff != fPaint.fSrcBlendCoeff ||
@ -49,15 +51,15 @@ void GrTextContext::flushGlyphs() {
GrPrintf("LCD Text will not draw correctly.\n"); GrPrintf("LCD Text will not draw correctly.\n");
} }
// setup blend so that we get mask * paintColor + (1-mask)*dstColor // 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); drawState->setBlendFunc(kConstC_BlendCoeff, kISC_BlendCoeff);
// don't modulate by the paint's color in the frag since we're // don't modulate by the paint's color in the frag since we're
// already doing it via the blend const. // already doing it via the blend const.
fDrawTarget->setColor(0xffffffff); drawState->setColor(0xffffffff);
} else { } else {
// set back to normal in case we took LCD path previously. // set back to normal in case we took LCD path previously.
fDrawTarget->setBlendFunc(fPaint.fSrcBlendCoeff, fPaint.fDstBlendCoeff); drawState->setBlendFunc(fPaint.fSrcBlendCoeff, fPaint.fDstBlendCoeff);
fDrawTarget->setColor(fPaint.fColor); drawState->setColor(fPaint.fColor);
} }
fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());