Always use both a color and coverage attribute in GrAARectRenderer.

R=robertphillips@google.com

Author: bsalomon@google.com

Review URL: https://codereview.chromium.org/435743002
This commit is contained in:
bsalomon 2014-08-11 11:07:48 -07:00 committed by Commit bot
parent 3e30af2dca
commit 9c0822a415
7 changed files with 88 additions and 129 deletions

View File

@ -32,3 +32,20 @@
## http://skbug.com/123456 : ignoring failures on gradtext GM test
## epoger will rebaseline by 25 Dec 2013
#gradtext
#bsalomon: https://codereview.chromium.org/435743002
thinstrokedrects
thinrects
drawlooper
aarectmodes
mixed_xfermodes
convex_poly_effect
rects
twopointconical
gradients_2pt_conical_inside
gradients_local_perspective
gradient_dirty_laundry
gradients
gradients_2pt_conical_edge
gradients_2pt_conical_outside
gradients_no_texture

View File

@ -88,6 +88,11 @@ static inline void GrColorToRGBAFloat(GrColor color, float rgba[4]) {
rgba[3] = GrColorUnpackA(color) * ONE_OVER_255;
}
/** Determines whether the color is opaque or not. */
static inline bool GrColorIsOpaque(GrColor color) {
return (color & (0xFFU << GrColor_SHIFT_A)) == (0xFFU << GrColor_SHIFT_A);
}
/**
* Flags used for bitfields of color components. They are defined so that the bit order reflects the
* GrColor shift order.

View File

@ -256,24 +256,12 @@ GrEffect* GrRectEffect::TestCreate(SkRandom* random,
namespace {
extern const GrVertexAttrib gAARectCoverageAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec4ub_GrVertexAttribType, sizeof(SkPoint), kCoverage_GrVertexAttribBinding},
extern const GrVertexAttrib gAARectAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
{kVec4ub_GrVertexAttribType, sizeof(SkPoint) + sizeof(SkColor), kCoverage_GrVertexAttribBinding},
};
extern const GrVertexAttrib gAARectColorAttribs[] = {
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
{kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
};
static void set_aa_rect_vertex_attributes(GrDrawState* drawState, bool useCoverage) {
if (useCoverage) {
drawState->setVertexAttribs<gAARectCoverageAttribs>(SK_ARRAY_COUNT(gAARectCoverageAttribs));
} else {
drawState->setVertexAttribs<gAARectColorAttribs>(SK_ARRAY_COUNT(gAARectColorAttribs));
}
}
static void set_inset_fan(SkPoint* pts, size_t stride,
const SkRect& r, SkScalar dx, SkScalar dy) {
pts->setRectFan(r.fLeft + dx, r.fTop + dy,
@ -451,11 +439,15 @@ void GrAARectRenderer::geometryFillAARect(GrGpu* gpu,
GrDrawTarget* target,
const SkRect& rect,
const SkMatrix& combinedMatrix,
const SkRect& devRect,
bool useVertexCoverage) {
const SkRect& devRect) {
GrDrawState* drawState = target->drawState();
set_aa_rect_vertex_attributes(drawState, useVertexCoverage);
GrColor color = drawState->getColor();
drawState->setVertexAttribs<gAARectAttribs>(SK_ARRAY_COUNT(gAARectAttribs));
if (GrColorIsOpaque(color)) {
drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
}
GrDrawTarget::AutoReleaseGeometry geo(target, 8, 0);
if (!geo.succeeded()) {
@ -471,7 +463,7 @@ void GrAARectRenderer::geometryFillAARect(GrGpu* gpu,
intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
size_t vsize = drawState->getVertexSize();
SkASSERT(sizeof(SkPoint) + sizeof(GrColor) == vsize);
SkASSERT(sizeof(SkPoint) + 2 * sizeof(GrColor) == vsize);
SkPoint* fan0Pos = reinterpret_cast<SkPoint*>(verts);
SkPoint* fan1Pos = reinterpret_cast<SkPoint*>(verts + 4 * vsize);
@ -528,9 +520,11 @@ void GrAARectRenderer::geometryFillAARect(GrGpu* gpu,
*((SkPoint*)((intptr_t)fan0Pos + 3 * vsize)) += vec[0] - vec[1];
}
// Make verts point to vertex color and then set all the color and coverage vertex attrs values.
verts += sizeof(SkPoint);
for (int i = 0; i < 4; ++i) {
*reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
*reinterpret_cast<GrColor*>(verts + i * vsize) = color;
*reinterpret_cast<GrColor*>(verts + i * vsize + sizeof(GrColor)) = 0;
}
int scale;
@ -541,20 +535,11 @@ void GrAARectRenderer::geometryFillAARect(GrGpu* gpu,
scale = 0xff;
}
GrColor innerColor;
if (useVertexCoverage) {
innerColor = GrColorPackRGBA(scale, scale, scale, scale);
} else {
if (0xff == scale) {
innerColor = target->getDrawState().getColor();
} else {
innerColor = SkAlphaMulQ(target->getDrawState().getColor(), scale);
}
}
verts += 4 * vsize;
GrColor innerCoverage;
innerCoverage = GrColorPackRGBA(scale, scale, scale, scale); verts += 4 * vsize;
for (int i = 0; i < 4; ++i) {
*reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
*reinterpret_cast<GrColor*>(verts + i * vsize) = color;
*reinterpret_cast<GrColor*>(verts + i * vsize + sizeof(GrColor)) = innerCoverage;
}
target->setIndexSourceToBuffer(indexBuffer);
@ -723,8 +708,7 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu,
const SkRect& rect,
const SkMatrix& combinedMatrix,
const SkRect& devRect,
const SkStrokeRec& stroke,
bool useVertexCoverage) {
const SkStrokeRec& stroke) {
SkVector devStrokeSize;
SkScalar width = stroke.getWidth();
if (width > 0) {
@ -767,8 +751,7 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu,
}
if (spare <= 0 && miterStroke) {
this->fillAARect(gpu, target, devOutside, SkMatrix::I(),
devOutside, useVertexCoverage);
this->fillAARect(gpu, target, devOutside, SkMatrix::I(), devOutside);
return;
}
@ -785,8 +768,7 @@ void GrAARectRenderer::strokeAARect(GrGpu* gpu,
devOutsideAssist.outset(0, ry);
}
this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist,
devInside, useVertexCoverage, miterStroke);
this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist, devInside, miterStroke);
}
void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu,
@ -794,11 +776,15 @@ void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu,
const SkRect& devOutside,
const SkRect& devOutsideAssist,
const SkRect& devInside,
bool useVertexCoverage,
bool miterStroke) {
GrDrawState* drawState = target->drawState();
set_aa_rect_vertex_attributes(drawState, useVertexCoverage);
drawState->setVertexAttribs<gAARectAttribs>(SK_ARRAY_COUNT(gAARectAttribs));
GrColor color = drawState->getColor();
if (GrColorIsOpaque(color)) {
drawState->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
}
int innerVertexNum = 4;
int outerVertexNum = miterStroke ? 4 : 8;
@ -817,7 +803,6 @@ void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu,
intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
size_t vsize = drawState->getVertexSize();
SkASSERT(sizeof(SkPoint) + sizeof(GrColor) == vsize);
// We create vertices for four nested rectangles. There are two ramps from 0 to full
// coverage, one on the exterior of the stroke and the other on the interior.
@ -866,12 +851,15 @@ void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu,
set_inset_fan(fan3Pos, vsize, devInside, SK_ScalarHalf, SK_ScalarHalf);
}
// Make verts point to vertex color and then set all the color and coverage vertex attrs values.
// The outermost rect has 0 coverage
verts += sizeof(SkPoint);
for (int i = 0; i < outerVertexNum; ++i) {
*reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
*reinterpret_cast<GrColor*>(verts + i * vsize) = color;
*reinterpret_cast<GrColor*>(verts + i * vsize + sizeof(GrColor)) = 0;
}
// scale is the coverage for the the inner two rects.
int scale;
if (inset < SK_ScalarHalf) {
scale = SkScalarFloorToInt(512.0f * inset / (inset + SK_ScalarHalf));
@ -880,27 +868,18 @@ void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu,
scale = 0xff;
}
// The inner two rects have full coverage
GrColor innerColor;
if (useVertexCoverage) {
innerColor = GrColorPackRGBA(scale, scale, scale, scale);
} else {
if (0xff == scale) {
innerColor = target->getDrawState().getColor();
} else {
innerColor = SkAlphaMulQ(target->getDrawState().getColor(), scale);
}
}
verts += outerVertexNum * vsize;
GrColor innerCoverage = GrColorPackRGBA(scale, scale, scale, scale);
for (int i = 0; i < outerVertexNum + innerVertexNum; ++i) {
*reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
*reinterpret_cast<GrColor*>(verts + i * vsize) = color;
*reinterpret_cast<GrColor*>(verts + i * vsize + sizeof(GrColor)) = innerCoverage;
}
// The innermost rect has 0 coverage
verts += (outerVertexNum + innerVertexNum) * vsize;
for (int i = 0; i < innerVertexNum; ++i) {
*reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
*reinterpret_cast<GrColor*>(verts + i * vsize) = color;
*reinterpret_cast<GrColor*>(verts + i * vsize + sizeof(GrColor)) = 0;
}
target->setIndexSourceToBuffer(indexBuffer);
@ -911,8 +890,7 @@ void GrAARectRenderer::geometryStrokeAARect(GrGpu* gpu,
void GrAARectRenderer::fillAANestedRects(GrGpu* gpu,
GrDrawTarget* target,
const SkRect rects[2],
const SkMatrix& combinedMatrix,
bool useVertexCoverage) {
const SkMatrix& combinedMatrix) {
SkASSERT(combinedMatrix.rectStaysRect());
SkASSERT(!rects[1].isEmpty());
@ -922,10 +900,9 @@ void GrAARectRenderer::fillAANestedRects(GrGpu* gpu,
combinedMatrix.mapPoints((SkPoint*)&devInside, (const SkPoint*)&rects[1], 2);
if (devInside.isEmpty()) {
this->fillAARect(gpu, target, devOutside, SkMatrix::I(), devOutside, useVertexCoverage);
this->fillAARect(gpu, target, devOutside, SkMatrix::I(), devOutside);
return;
}
this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist,
devInside, useVertexCoverage, true);
this->geometryStrokeAARect(gpu, target, devOutside, devOutsideAssist, devInside, true);
}

View File

@ -43,8 +43,7 @@ public:
GrDrawTarget* target,
const SkRect& rect,
const SkMatrix& combinedMatrix,
const SkRect& devRect,
bool useVertexCoverage) {
const SkRect& devRect) {
#ifdef SHADER_AA_FILL_RECT
if (combinedMatrix.rectStaysRect()) {
this->shaderFillAlignedAARect(gpu, target,
@ -54,9 +53,7 @@ public:
rect, combinedMatrix);
}
#else
this->geometryFillAARect(gpu, target,
rect, combinedMatrix,
devRect, useVertexCoverage);
this->geometryFillAARect(gpu, target, rect, combinedMatrix, devRect);
#endif
}
@ -65,15 +62,13 @@ public:
const SkRect& rect,
const SkMatrix& combinedMatrix,
const SkRect& devRect,
const SkStrokeRec& stroke,
bool useVertexCoverage);
const SkStrokeRec& stroke);
// First rect is outer; second rect is inner
void fillAANestedRects(GrGpu* gpu,
GrDrawTarget* target,
const SkRect rects[2],
const SkMatrix& combinedMatrix,
bool useVertexCoverage);
const SkMatrix& combinedMatrix);
private:
GrIndexBuffer* fAAFillRectIndexBuffer;
@ -85,14 +80,11 @@ private:
static int aaStrokeRectIndexCount(bool miterStroke);
GrIndexBuffer* aaStrokeRectIndexBuffer(GrGpu* gpu, bool miterStroke);
// TODO: Remove the useVertexCoverage boolean. Just use it all the time
// since we now have a coverage vertex attribute
void geometryFillAARect(GrGpu* gpu,
GrDrawTarget* target,
const SkRect& rect,
const SkMatrix& combinedMatrix,
const SkRect& devRect,
bool useVertexCoverage);
const SkRect& devRect);
void shaderFillAARect(GrGpu* gpu,
GrDrawTarget* target,
@ -109,7 +101,6 @@ private:
const SkRect& devOutside,
const SkRect& devOutsideAssist,
const SkRect& devInside,
bool useVertexCoverage,
bool miterStroke);
typedef SkRefCnt INHERITED;

View File

@ -404,8 +404,7 @@ bool GrClipMaskManager::drawElement(GrTexture* target,
fGpu,
element->getRect(),
SkMatrix::I(),
element->getRect(),
false);
element->getRect());
} else {
fGpu->drawSimpleRect(element->getRect());
}

View File

@ -719,35 +719,17 @@ static void setStrokeRectStrip(SkPoint verts[10], SkRect rect,
verts[9] = verts[1];
}
static bool isIRect(const SkRect& r) {
return SkScalarIsInt(r.fLeft) && SkScalarIsInt(r.fTop) &&
SkScalarIsInt(r.fRight) && SkScalarIsInt(r.fBottom);
}
static bool apply_aa_to_rect(GrDrawTarget* target,
const SkRect& rect,
SkScalar strokeWidth,
const SkMatrix& combinedMatrix,
SkRect* devBoundRect,
bool* useVertexCoverage) {
// we use a simple coverage ramp to do aa on axis-aligned rects
// we check if the rect will be axis-aligned, and the rect won't land on
// integer coords.
// we are keeping around the "tweak the alpha" trick because
// it is our only hope for the fixed-pipe implementation.
// In a shader implementation we can give a separate coverage input
// TODO: remove this ugliness when we drop the fixed-pipe impl
*useVertexCoverage = false;
if (!target->getDrawState().canTweakAlphaForCoverage()) {
if (target->shouldDisableCoverageAAForBlend()) {
SkRect* devBoundRect) {
if (!target->getDrawState().canTweakAlphaForCoverage() &&
target->shouldDisableCoverageAAForBlend()) {
#ifdef SK_DEBUG
//GrPrintf("Turning off AA to correctly apply blend.\n");
//GrPrintf("Turning off AA to correctly apply blend.\n");
#endif
return false;
} else {
*useVertexCoverage = true;
}
return false;
}
const GrDrawState& drawState = target->getDrawState();
if (drawState.getRenderTarget()->isMultisampled()) {
@ -771,11 +753,7 @@ static bool apply_aa_to_rect(GrDrawTarget* target,
combinedMatrix.mapRect(devBoundRect, rect);
if (strokeWidth < 0) {
return !isIRect(*devBoundRect);
} else {
return true;
}
return true;
}
static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
@ -840,11 +818,9 @@ void GrContext::drawRect(const GrPaint& paint,
}
SkRect devBoundRect;
bool useVertexCoverage;
bool needAA = paint.isAntiAlias() &&
!target->getDrawState().getRenderTarget()->isMultisampled();
bool doAA = needAA && apply_aa_to_rect(target, rect, width, matrix, &devBoundRect,
&useVertexCoverage);
bool doAA = needAA && apply_aa_to_rect(target, rect, width, matrix, &devBoundRect);
const SkStrokeRec& strokeRec = strokeInfo->getStrokeRec();
@ -856,12 +832,11 @@ void GrContext::drawRect(const GrPaint& paint,
if (width >= 0) {
fAARectRenderer->strokeAARect(this->getGpu(), target, rect,
matrix, devBoundRect,
strokeRec, useVertexCoverage);
strokeRec);
} else {
// filled AA rect
fAARectRenderer->fillAARect(this->getGpu(), target,
rect, matrix, devBoundRect,
useVertexCoverage);
rect, matrix, devBoundRect);
}
return;
}
@ -1117,8 +1092,7 @@ void GrContext::drawOval(const GrPaint& paint,
static bool is_nested_rects(GrDrawTarget* target,
const SkPath& path,
const SkStrokeRec& stroke,
SkRect rects[2],
bool* useVertexCoverage) {
SkRect rects[2]) {
SkASSERT(stroke.isFillStyle());
if (path.isInverseFillType()) {
@ -1133,13 +1107,9 @@ static bool is_nested_rects(GrDrawTarget* target,
return false;
}
*useVertexCoverage = false;
if (!target->getDrawState().canTweakAlphaForCoverage()) {
if (target->shouldDisableCoverageAAForBlend()) {
return false;
} else {
*useVertexCoverage = true;
}
if (!target->getDrawState().canTweakAlphaForCoverage() &&
target->shouldDisableCoverageAAForBlend()) {
return false;
}
SkPath::Direction dirs[2];
@ -1233,20 +1203,16 @@ void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const GrStrok
if (useCoverageAA && strokeRec.getWidth() < 0 && !path.isConvex()) {
// Concave AA paths are expensive - try to avoid them for special cases
bool useVertexCoverage;
SkRect rects[2];
if (is_nested_rects(target, path, strokeRec, rects, &useVertexCoverage)) {
if (is_nested_rects(target, path, strokeRec, rects)) {
SkMatrix origViewMatrix = drawState->getViewMatrix();
GrDrawState::AutoViewMatrixRestore avmr;
if (!avmr.setIdentity(target->drawState())) {
return;
}
fAARectRenderer->fillAANestedRects(this->getGpu(), target,
rects,
origViewMatrix,
useVertexCoverage);
fAARectRenderer->fillAANestedRects(this->getGpu(), target, rects, origViewMatrix);
return;
}
}
@ -1761,6 +1727,9 @@ GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint,
are->set(NULL);
return NULL;
}
// Clear any vertex attributes configured for the previous use of the
// GrDrawState which can effect which blend optimizations are in effect.
fDrawState->setDefaultVertexAttribs();
} else {
fDrawState->reset(fViewMatrix);
fDrawState->setRenderTarget(fRenderTarget.get());

View File

@ -60,7 +60,8 @@ public:
/**
* Initializes the GrDrawState based on a GrPaint, view matrix and render target. Note that
* GrDrawState encompasses more than GrPaint. Aspects of GrDrawState that have no GrPaint
* equivalents are set to default values. Clipping will be enabled.
* equivalents are set to default values with the exception of vertex attribute state which
* is unmodified by this function and clipping which will be enabled.
*/
void setFromPaint(const GrPaint& , const SkMatrix& viewMatrix, GrRenderTarget*);