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
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt
index bf3a81e..a8ba024 100644
--- a/expectations/gm/ignored-tests.txt
+++ b/expectations/gm/ignored-tests.txt
@@ -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
diff --git a/include/gpu/GrColor.h b/include/gpu/GrColor.h
index c53e4b2..4ab709b 100644
--- a/include/gpu/GrColor.h
+++ b/include/gpu/GrColor.h
@@ -88,6 +88,11 @@
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.
diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp
index 44c16a1..be82d5b 100644
--- a/src/gpu/GrAARectRenderer.cpp
+++ b/src/gpu/GrAARectRenderer.cpp
@@ -256,24 +256,12 @@
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 @@
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 @@
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 @@
*((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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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::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 @@
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);
}
diff --git a/src/gpu/GrAARectRenderer.h b/src/gpu/GrAARectRenderer.h
index faaf7e2..bfa295b 100644
--- a/src/gpu/GrAARectRenderer.h
+++ b/src/gpu/GrAARectRenderer.h
@@ -43,8 +43,7 @@
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 @@
rect, combinedMatrix);
}
#else
- this->geometryFillAARect(gpu, target,
- rect, combinedMatrix,
- devRect, useVertexCoverage);
+ this->geometryFillAARect(gpu, target, rect, combinedMatrix, devRect);
#endif
}
@@ -65,15 +62,13 @@
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 @@
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 @@
const SkRect& devOutside,
const SkRect& devOutsideAssist,
const SkRect& devInside,
- bool useVertexCoverage,
bool miterStroke);
typedef SkRefCnt INHERITED;
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index edd4454..0f79402 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -404,8 +404,7 @@
fGpu,
element->getRect(),
SkMatrix::I(),
- element->getRect(),
- false);
+ element->getRect());
} else {
fGpu->drawSimpleRect(element->getRect());
}
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 96380bd..282d6c4 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -719,35 +719,17 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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());
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index fa4d5b0..249eeeb 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -60,7 +60,8 @@
/**
* 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*);