diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt index bf3a81ea75..a8ba0245bb 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 c53e4b219d..4ab709b4f1 100644 --- a/include/gpu/GrColor.h +++ b/include/gpu/GrColor.h @@ -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. diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp index 44c16a18d6..be82d5b88f 100644 --- a/src/gpu/GrAARectRenderer.cpp +++ b/src/gpu/GrAARectRenderer.cpp @@ -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(SK_ARRAY_COUNT(gAARectCoverageAttribs)); - } else { - drawState->setVertexAttribs(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(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(geo.vertices()); size_t vsize = drawState->getVertexSize(); - SkASSERT(sizeof(SkPoint) + sizeof(GrColor) == vsize); + SkASSERT(sizeof(SkPoint) + 2 * sizeof(GrColor) == vsize); SkPoint* fan0Pos = reinterpret_cast(verts); SkPoint* fan1Pos = reinterpret_cast(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(verts + i * vsize) = 0; + *reinterpret_cast(verts + i * vsize) = color; + *reinterpret_cast(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(verts + i * vsize) = innerColor; + *reinterpret_cast(verts + i * vsize) = color; + *reinterpret_cast(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(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(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(verts + i * vsize) = 0; + *reinterpret_cast(verts + i * vsize) = color; + *reinterpret_cast(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(verts + i * vsize) = innerColor; + *reinterpret_cast(verts + i * vsize) = color; + *reinterpret_cast(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(verts + i * vsize) = 0; + *reinterpret_cast(verts + i * vsize) = color; + *reinterpret_cast(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); } diff --git a/src/gpu/GrAARectRenderer.h b/src/gpu/GrAARectRenderer.h index faaf7e20be..bfa295bb13 100644 --- a/src/gpu/GrAARectRenderer.h +++ b/src/gpu/GrAARectRenderer.h @@ -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; diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp index edd44540c5..0f79402a4f 100644 --- a/src/gpu/GrClipMaskManager.cpp +++ b/src/gpu/GrClipMaskManager.cpp @@ -404,8 +404,7 @@ bool GrClipMaskManager::drawElement(GrTexture* target, 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 96380bdfe6..282d6c4acc 100755 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -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()); diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h index fa4d5b03f5..249eeebe25 100644 --- a/src/gpu/GrDrawState.h +++ b/src/gpu/GrDrawState.h @@ -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*);