| Index: src/gpu/GrContext.cpp
|
| diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
|
| index 5eee2433c78a0db443d292785acc11aa3158e94e..b0d34fd03933af6e531ca3b4ae78fbd723477cc7 100644
|
| --- a/src/gpu/GrContext.cpp
|
| +++ b/src/gpu/GrContext.cpp
|
| @@ -25,7 +25,6 @@
|
| #include "GrSoftwarePathRenderer.h"
|
| #include "GrStencilBuffer.h"
|
| #include "GrTextStrike.h"
|
| -#include "SkDrawProcs.h"
|
| #include "SkRTConf.h"
|
| #include "SkRRect.h"
|
| #include "SkStrokeRec.h"
|
| @@ -44,6 +43,10 @@ SK_CONF_DECLARE(bool, c_Defer, "gpu.deferContext", true,
|
|
|
| #define BUFFERED_DRAW (c_Defer ? kYes_BufferedDraw : kNo_BufferedDraw)
|
|
|
| +// When we're using coverage AA but the blend is incompatible (given gpu
|
| +// limitations) should we disable AA or draw wrong?
|
| +#define DISABLE_COVERAGE_AA_FOR_BLEND 1
|
| +
|
| #ifdef SK_DEBUG
|
| // change this to a 1 to see notifications when partial coverage fails
|
| #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
|
| @@ -692,6 +695,14 @@ void GrContext::dumpFontCache() const {
|
|
|
| ////////////////////////////////////////////////////////////////////////////////
|
|
|
| +namespace {
|
| +inline bool disable_coverage_aa_for_blend(GrDrawTarget* target) {
|
| + return DISABLE_COVERAGE_AA_FOR_BLEND && !target->canApplyCoverage();
|
| +}
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +
|
| /* create a triangle strip that strokes the specified triangle. There are 8
|
| unique vertices, but we repreat the last 2 to close up. Alternatively we
|
| could use an indices array, and then only send 8 verts, but not sure that
|
| @@ -735,7 +746,7 @@ static bool apply_aa_to_rect(GrDrawTarget* target,
|
| // TODO: remove this ugliness when we drop the fixed-pipe impl
|
| *useVertexCoverage = false;
|
| if (!target->getDrawState().canTweakAlphaForCoverage()) {
|
| - if (target->shouldDisableCoverageAAForBlend()) {
|
| + if (disable_coverage_aa_for_blend(target)) {
|
| #ifdef SK_DEBUG
|
| //GrPrintf("Turning off AA to correctly apply blend.\n");
|
| #endif
|
| @@ -1023,10 +1034,14 @@ void GrContext::drawRRect(const GrPaint& paint,
|
| AutoCheckFlush acf(this);
|
| GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
|
|
|
| - if (!fOvalRenderer->drawSimpleRRect(target, this, paint.isAntiAlias(), rect, stroke)) {
|
| + bool useAA = paint.isAntiAlias() &&
|
| + !target->getDrawState().getRenderTarget()->isMultisampled() &&
|
| + !disable_coverage_aa_for_blend(target);
|
| +
|
| + if (!fOvalRenderer->drawSimpleRRect(target, this, useAA, rect, stroke)) {
|
| SkPath path;
|
| path.addRRect(rect);
|
| - this->internalDrawPath(target, paint.isAntiAlias(), path, stroke);
|
| + this->internalDrawPath(target, useAA, path, stroke);
|
| }
|
| }
|
|
|
| @@ -1043,10 +1058,14 @@ void GrContext::drawOval(const GrPaint& paint,
|
| AutoCheckFlush acf(this);
|
| GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
|
|
|
| - if (!fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), oval, stroke)) {
|
| + bool useAA = paint.isAntiAlias() &&
|
| + !target->getDrawState().getRenderTarget()->isMultisampled() &&
|
| + !disable_coverage_aa_for_blend(target);
|
| +
|
| + if (!fOvalRenderer->drawOval(target, this, useAA, oval, stroke)) {
|
| SkPath path;
|
| path.addOval(oval);
|
| - this->internalDrawPath(target, paint.isAntiAlias(), path, stroke);
|
| + this->internalDrawPath(target, useAA, path, stroke);
|
| }
|
| }
|
|
|
| @@ -1072,7 +1091,7 @@ static bool is_nested_rects(GrDrawTarget* target,
|
|
|
| *useVertexCoverage = false;
|
| if (!target->getDrawState().canTweakAlphaForCoverage()) {
|
| - if (target->shouldDisableCoverageAAForBlend()) {
|
| + if (disable_coverage_aa_for_blend(target)) {
|
| return false;
|
| } else {
|
| *useVertexCoverage = true;
|
| @@ -1122,17 +1141,15 @@ void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrok
|
| AutoRestoreEffects are;
|
| AutoCheckFlush acf(this);
|
| GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
|
| - GrDrawState* drawState = target->drawState();
|
| -
|
| - bool useCoverageAA = paint.isAntiAlias() && !drawState->getRenderTarget()->isMultisampled();
|
|
|
| - if (useCoverageAA && stroke.getWidth() < 0 && !path.isConvex()) {
|
| + bool useAA = paint.isAntiAlias() && !target->getDrawState().getRenderTarget()->isMultisampled();
|
| + if (useAA && stroke.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, stroke, rects, &useVertexCoverage)) {
|
| - SkMatrix origViewMatrix = drawState->getViewMatrix();
|
| + SkMatrix origViewMatrix = target->getDrawState().getViewMatrix();
|
| GrDrawState::AutoViewMatrixRestore avmr;
|
| if (!avmr.setIdentity(target->drawState())) {
|
| return;
|
| @@ -1150,73 +1167,42 @@ void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrok
|
| bool isOval = path.isOval(&ovalRect);
|
|
|
| if (!isOval || path.isInverseFillType()
|
| - || !fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), ovalRect, stroke)) {
|
| - this->internalDrawPath(target, paint.isAntiAlias(), path, stroke);
|
| + || !fOvalRenderer->drawOval(target, this, useAA, ovalRect, stroke)) {
|
| + this->internalDrawPath(target, useAA, path, stroke);
|
| }
|
| }
|
|
|
| -namespace {
|
| -// See also: SkDrawTreatAsHairline.
|
| -static inline bool should_convert_to_hairline(bool useAA, const SkStrokeRec& stroke,
|
| - const SkMatrix& matrix, SkScalar* coverage) {
|
| -
|
| - if (stroke.getStyle() != SkStrokeRec::kStroke_Style) {
|
| - return false;
|
| - }
|
| -
|
| - SkASSERT(0 != stroke.getWidth());
|
| -
|
| - if (!useAA) {
|
| - return false;
|
| - }
|
| -
|
| - return SkDrawTreatAAStrokeAsHairline(stroke.getWidth(), matrix, coverage);
|
| -}
|
| -}
|
| -
|
| -
|
| -void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA,
|
| - const SkPath& path, const SkStrokeRec& origStroke) {
|
| +void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& path,
|
| + const SkStrokeRec& stroke) {
|
| SkASSERT(!path.isEmpty());
|
|
|
| // An Assumption here is that path renderer would use some form of tweaking
|
| // the src color (either the input alpha or in the frag shader) to implement
|
| // aa. If we have some future driver-mojo path AA that can do the right
|
| // thing WRT to the blend then we'll need some query on the PR.
|
| - bool useCoverageAA = useAA &&
|
| - !target->getDrawState().getRenderTarget()->isMultisampled() &&
|
| - !target->shouldDisableCoverageAAForBlend();
|
| -
|
| - SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke);
|
| - // Can we treat a thin stroke as a hairline w/ coverage? If we can, we draw lots faster (raster
|
| - // device does this same test).
|
| -
|
| - // Do not do this if gpu supports path rendering natively and we might be using the support
|
| - // (useCoverageAA == false). Hairline renderer is likely to be slow due to program switches.
|
| - if (!useCoverageAA || !fGpu->caps()->pathRenderingSupport()) {
|
| - SkScalar hairlineCoverage;
|
| - if (should_convert_to_hairline(useAA, *stroke, this->getMatrix(), &hairlineCoverage)) {
|
| - target->drawState()->setCoverage(SkScalarRoundToInt(hairlineCoverage * target->getDrawState().getCoverage()));
|
| - stroke.writable()->setHairlineStyle();
|
| - }
|
| + if (disable_coverage_aa_for_blend(target)) {
|
| +#ifdef SK_DEBUG
|
| + //GrPrintf("Turning off AA to correctly apply blend.\n");
|
| +#endif
|
| + useAA = false;
|
| }
|
|
|
| - GrPathRendererChain::DrawType type =
|
| - useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType :
|
| - GrPathRendererChain::kColor_DrawType;
|
| + GrPathRendererChain::DrawType type = useAA ? GrPathRendererChain::kColorAntiAlias_DrawType :
|
| + GrPathRendererChain::kColor_DrawType;
|
|
|
| const SkPath* pathPtr = &path;
|
| SkPath tmpPath;
|
| + SkStrokeRec strokeRec(stroke);
|
|
|
| // Try a 1st time without stroking the path and without allowing the SW renderer
|
| - GrPathRenderer* pr = this->getPathRenderer(*pathPtr, *stroke, target, false, type);
|
| + GrPathRenderer* pr = this->getPathRenderer(*pathPtr, strokeRec, target, false, type);
|
|
|
| if (NULL == pr) {
|
| - if (!stroke->isHairlineStyle()) {
|
| + if (!strokeRec.isHairlineStyle()) {
|
| // It didn't work the 1st time, so try again with the stroked path
|
| - if (stroke->applyToPath(&tmpPath, *pathPtr)) {
|
| + if (strokeRec.applyToPath(&tmpPath, *pathPtr)) {
|
| pathPtr = &tmpPath;
|
| - stroke.writable()->setFillStyle();
|
| + strokeRec.setFillStyle();
|
| }
|
| }
|
| if (pathPtr->isEmpty()) {
|
| @@ -1224,7 +1210,7 @@ void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA,
|
| }
|
|
|
| // This time, allow SW renderer
|
| - pr = this->getPathRenderer(*pathPtr, *stroke, target, true, type);
|
| + pr = this->getPathRenderer(*pathPtr, strokeRec, target, true, type);
|
| }
|
|
|
| if (NULL == pr) {
|
| @@ -1234,7 +1220,7 @@ void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA,
|
| return;
|
| }
|
|
|
| - pr->drawPath(*pathPtr, *stroke, target, useCoverageAA);
|
| + pr->drawPath(*pathPtr, strokeRec, target, useAA);
|
| }
|
|
|
| ////////////////////////////////////////////////////////////////////////////////
|
|
|