Revert "Do not apply hairline optimization for paths if nv_path_rendering is used"
This reverts commit r12185. Review URL: https://codereview.chromium.org/66813002 git-svn-id: http://skia.googlecode.com/svn/trunk@12187 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
ab7442c8d7
commit
1b20a10f02
@ -987,12 +987,24 @@ static bool xfermodeSupportsCoverageAsAlpha(SkXfermode* xfer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix& matrix,
|
bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix,
|
||||||
SkScalar* coverage) {
|
SkScalar* coverage) {
|
||||||
SkASSERT(coverage);
|
SkASSERT(coverage);
|
||||||
SkASSERT(strokeWidth > 0);
|
if (SkPaint::kStroke_Style != paint.getStyle()) {
|
||||||
// We need to try to fake a thick-stroke with a modulated hairline.
|
return false;
|
||||||
|
}
|
||||||
|
SkScalar strokeWidth = paint.getStrokeWidth();
|
||||||
|
if (0 == strokeWidth) {
|
||||||
|
*coverage = SK_Scalar1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we get here, we need to try to fake a thick-stroke with a modulated
|
||||||
|
// hairline
|
||||||
|
|
||||||
|
if (!paint.isAntiAlias()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (matrix.hasPerspective()) {
|
if (matrix.hasPerspective()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -59,32 +59,12 @@ struct SkDrawProcs {
|
|||||||
SkDraw1Glyph::Proc fD1GProc;
|
SkDraw1Glyph::Proc fD1GProc;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool SkDrawTreatAAStrokeAsHairline(SkScalar strokeWidth, const SkMatrix&,
|
|
||||||
SkScalar* coverage);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the current paint is set to stroke and the stroke-width when applied to
|
* If the current paint is set to stroke and the stroke-width when applied to
|
||||||
* the matrix is <= 1.0, then this returns true, and sets coverage (simulating
|
* the matrix is <= 1.0, then this returns true, and sets coverage (simulating
|
||||||
* a stroke by drawing a hairline with partial coverage). If any of these
|
* a stroke by drawing a hairline with partial coverage). If any of these
|
||||||
* conditions are false, then this returns false and coverage is ignored.
|
* conditions are false, then this returns false and coverage is ignored.
|
||||||
*/
|
*/
|
||||||
inline bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix,
|
bool SkDrawTreatAsHairline(const SkPaint&, const SkMatrix&, SkScalar* coverage);
|
||||||
SkScalar* coverage) {
|
|
||||||
if (SkPaint::kStroke_Style != paint.getStyle()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SkScalar strokeWidth = paint.getStrokeWidth();
|
|
||||||
if (0 == strokeWidth) {
|
|
||||||
*coverage = SK_Scalar1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!paint.isAntiAlias()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SkDrawTreatAAStrokeAsHairline(strokeWidth, matrix, coverage);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -759,7 +759,7 @@ bool GrAAHairLinePathRenderer::createLineGeom(const SkPath& path,
|
|||||||
}
|
}
|
||||||
devBounds->set(lines.begin(), lines.count());
|
devBounds->set(lines.begin(), lines.count());
|
||||||
for (int i = 0; i < lineCnt; ++i) {
|
for (int i = 0; i < lineCnt; ++i) {
|
||||||
add_line(&lines[2*i], toSrc, drawState->getCoverageColor(), &verts);
|
add_line(&lines[2*i], toSrc, drawState->getCoverage(), &verts);
|
||||||
}
|
}
|
||||||
// All the verts computed by add_line are within sqrt(1^2 + 0.5^2) of the end points.
|
// All the verts computed by add_line are within sqrt(1^2 + 0.5^2) of the end points.
|
||||||
static const SkScalar kSqrtOfOneAndAQuarter = SkFloatToScalar(1.118f);
|
static const SkScalar kSqrtOfOneAndAQuarter = SkFloatToScalar(1.118f);
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
#include "GrSoftwarePathRenderer.h"
|
#include "GrSoftwarePathRenderer.h"
|
||||||
#include "GrStencilBuffer.h"
|
#include "GrStencilBuffer.h"
|
||||||
#include "GrTextStrike.h"
|
#include "GrTextStrike.h"
|
||||||
#include "SkDrawProcs.h"
|
|
||||||
#include "SkRTConf.h"
|
#include "SkRTConf.h"
|
||||||
#include "SkRRect.h"
|
#include "SkRRect.h"
|
||||||
#include "SkStrokeRec.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)
|
#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
|
#ifdef SK_DEBUG
|
||||||
// change this to a 1 to see notifications when partial coverage fails
|
// change this to a 1 to see notifications when partial coverage fails
|
||||||
#define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
|
#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
|
/* 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
|
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
|
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
|
// TODO: remove this ugliness when we drop the fixed-pipe impl
|
||||||
*useVertexCoverage = false;
|
*useVertexCoverage = false;
|
||||||
if (!target->getDrawState().canTweakAlphaForCoverage()) {
|
if (!target->getDrawState().canTweakAlphaForCoverage()) {
|
||||||
if (target->shouldDisableCoverageAAForBlend()) {
|
if (disable_coverage_aa_for_blend(target)) {
|
||||||
#ifdef SK_DEBUG
|
#ifdef SK_DEBUG
|
||||||
//GrPrintf("Turning off AA to correctly apply blend.\n");
|
//GrPrintf("Turning off AA to correctly apply blend.\n");
|
||||||
#endif
|
#endif
|
||||||
@ -1023,10 +1034,14 @@ void GrContext::drawRRect(const GrPaint& paint,
|
|||||||
AutoCheckFlush acf(this);
|
AutoCheckFlush acf(this);
|
||||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
|
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;
|
SkPath path;
|
||||||
path.addRRect(rect);
|
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);
|
AutoCheckFlush acf(this);
|
||||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
|
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;
|
SkPath path;
|
||||||
path.addOval(oval);
|
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;
|
*useVertexCoverage = false;
|
||||||
if (!target->getDrawState().canTweakAlphaForCoverage()) {
|
if (!target->getDrawState().canTweakAlphaForCoverage()) {
|
||||||
if (target->shouldDisableCoverageAAForBlend()) {
|
if (disable_coverage_aa_for_blend(target)) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
*useVertexCoverage = true;
|
*useVertexCoverage = true;
|
||||||
@ -1122,17 +1141,15 @@ void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrok
|
|||||||
AutoRestoreEffects are;
|
AutoRestoreEffects are;
|
||||||
AutoCheckFlush acf(this);
|
AutoCheckFlush acf(this);
|
||||||
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
|
GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
|
||||||
GrDrawState* drawState = target->drawState();
|
|
||||||
|
|
||||||
bool useCoverageAA = paint.isAntiAlias() && !drawState->getRenderTarget()->isMultisampled();
|
bool useAA = paint.isAntiAlias() && !target->getDrawState().getRenderTarget()->isMultisampled();
|
||||||
|
if (useAA && stroke.getWidth() < 0 && !path.isConvex()) {
|
||||||
if (useCoverageAA && stroke.getWidth() < 0 && !path.isConvex()) {
|
|
||||||
// Concave AA paths are expensive - try to avoid them for special cases
|
// Concave AA paths are expensive - try to avoid them for special cases
|
||||||
bool useVertexCoverage;
|
bool useVertexCoverage;
|
||||||
SkRect rects[2];
|
SkRect rects[2];
|
||||||
|
|
||||||
if (is_nested_rects(target, path, stroke, rects, &useVertexCoverage)) {
|
if (is_nested_rects(target, path, stroke, rects, &useVertexCoverage)) {
|
||||||
SkMatrix origViewMatrix = drawState->getViewMatrix();
|
SkMatrix origViewMatrix = target->getDrawState().getViewMatrix();
|
||||||
GrDrawState::AutoViewMatrixRestore avmr;
|
GrDrawState::AutoViewMatrixRestore avmr;
|
||||||
if (!avmr.setIdentity(target->drawState())) {
|
if (!avmr.setIdentity(target->drawState())) {
|
||||||
return;
|
return;
|
||||||
@ -1150,73 +1167,42 @@ void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrok
|
|||||||
bool isOval = path.isOval(&ovalRect);
|
bool isOval = path.isOval(&ovalRect);
|
||||||
|
|
||||||
if (!isOval || path.isInverseFillType()
|
if (!isOval || path.isInverseFillType()
|
||||||
|| !fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), ovalRect, stroke)) {
|
|| !fOvalRenderer->drawOval(target, this, useAA, ovalRect, stroke)) {
|
||||||
this->internalDrawPath(target, paint.isAntiAlias(), path, stroke);
|
this->internalDrawPath(target, useAA, path, stroke);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& path,
|
||||||
// See also: SkDrawTreatAsHairline.
|
const SkStrokeRec& stroke) {
|
||||||
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) {
|
|
||||||
SkASSERT(!path.isEmpty());
|
SkASSERT(!path.isEmpty());
|
||||||
|
|
||||||
// An Assumption here is that path renderer would use some form of tweaking
|
// 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
|
// 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
|
// 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.
|
// thing WRT to the blend then we'll need some query on the PR.
|
||||||
bool useCoverageAA = useAA &&
|
if (disable_coverage_aa_for_blend(target)) {
|
||||||
!target->getDrawState().getRenderTarget()->isMultisampled() &&
|
#ifdef SK_DEBUG
|
||||||
!target->shouldDisableCoverageAAForBlend();
|
//GrPrintf("Turning off AA to correctly apply blend.\n");
|
||||||
|
#endif
|
||||||
SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke);
|
useAA = false;
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GrPathRendererChain::DrawType type =
|
GrPathRendererChain::DrawType type = useAA ? GrPathRendererChain::kColorAntiAlias_DrawType :
|
||||||
useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType :
|
GrPathRendererChain::kColor_DrawType;
|
||||||
GrPathRendererChain::kColor_DrawType;
|
|
||||||
|
|
||||||
const SkPath* pathPtr = &path;
|
const SkPath* pathPtr = &path;
|
||||||
SkPath tmpPath;
|
SkPath tmpPath;
|
||||||
|
SkStrokeRec strokeRec(stroke);
|
||||||
|
|
||||||
// Try a 1st time without stroking the path and without allowing the SW renderer
|
// 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 (NULL == pr) {
|
||||||
if (!stroke->isHairlineStyle()) {
|
if (!strokeRec.isHairlineStyle()) {
|
||||||
// It didn't work the 1st time, so try again with the stroked path
|
// 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;
|
pathPtr = &tmpPath;
|
||||||
stroke.writable()->setFillStyle();
|
strokeRec.setFillStyle();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pathPtr->isEmpty()) {
|
if (pathPtr->isEmpty()) {
|
||||||
@ -1224,7 +1210,7 @@ void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This time, allow SW renderer
|
// This time, allow SW renderer
|
||||||
pr = this->getPathRenderer(*pathPtr, *stroke, target, true, type);
|
pr = this->getPathRenderer(*pathPtr, strokeRec, target, true, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NULL == pr) {
|
if (NULL == pr) {
|
||||||
@ -1234,7 +1220,7 @@ void GrContext::internalDrawPath(GrDrawTarget* target, bool useAA,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pr->drawPath(*pathPtr, *stroke, target, useCoverageAA);
|
pr->drawPath(*pathPtr, strokeRec, target, useAA);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -54,6 +54,7 @@ void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRende
|
|||||||
this->enableState(GrDrawState::kClip_StateBit);
|
this->enableState(GrDrawState::kClip_StateBit);
|
||||||
|
|
||||||
this->setColor(paint.getColor());
|
this->setColor(paint.getColor());
|
||||||
|
this->setCoverage4(paint.getCoverage());
|
||||||
this->setState(GrDrawState::kDither_StateBit, paint.isDither());
|
this->setState(GrDrawState::kDither_StateBit, paint.isDither());
|
||||||
this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
|
this->setState(GrDrawState::kHWAntialias_StateBit, paint.isAntiAlias());
|
||||||
|
|
||||||
@ -219,7 +220,7 @@ bool GrDrawState::srcAlphaWillBeOne() const {
|
|||||||
|
|
||||||
// Check whether coverage is treated as color. If so we run through the coverage computation.
|
// Check whether coverage is treated as color. If so we run through the coverage computation.
|
||||||
if (this->isCoverageDrawing()) {
|
if (this->isCoverageDrawing()) {
|
||||||
GrColor coverageColor = this->getCoverageColor();
|
GrColor coverageColor = this->getCoverage();
|
||||||
GrColor oldColor = color;
|
GrColor oldColor = color;
|
||||||
color = 0;
|
color = 0;
|
||||||
for (int c = 0; c < 4; ++c) {
|
for (int c = 0; c < 4; ++c) {
|
||||||
@ -311,7 +312,7 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
|
|||||||
|
|
||||||
bool covIsZero = !this->isCoverageDrawing() &&
|
bool covIsZero = !this->isCoverageDrawing() &&
|
||||||
!this->hasCoverageVertexAttribute() &&
|
!this->hasCoverageVertexAttribute() &&
|
||||||
0 == this->getCoverageColor();
|
0 == this->getCoverage();
|
||||||
// When coeffs are (0,1) there is no reason to draw at all, unless
|
// When coeffs are (0,1) there is no reason to draw at all, unless
|
||||||
// stenciling is enabled. Having color writes disabled is effectively
|
// stenciling is enabled. Having color writes disabled is effectively
|
||||||
// (0,1). The same applies when coverage is known to be 0.
|
// (0,1). The same applies when coverage is known to be 0.
|
||||||
@ -326,7 +327,7 @@ GrDrawState::BlendOptFlags GrDrawState::getBlendOpts(bool forceCoverage,
|
|||||||
|
|
||||||
// check for coverage due to constant coverage, per-vertex coverage, or coverage stage
|
// check for coverage due to constant coverage, per-vertex coverage, or coverage stage
|
||||||
bool hasCoverage = forceCoverage ||
|
bool hasCoverage = forceCoverage ||
|
||||||
0xffffffff != this->getCoverageColor() ||
|
0xffffffff != this->getCoverage() ||
|
||||||
this->hasCoverageVertexAttribute() ||
|
this->hasCoverageVertexAttribute() ||
|
||||||
fCoverageStages.count() > 0;
|
fCoverageStages.count() > 0;
|
||||||
|
|
||||||
|
@ -311,11 +311,15 @@ public:
|
|||||||
fCommon.fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
|
fCommon.fCoverage = GrColorPackRGBA(coverage, coverage, coverage, coverage);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t getCoverage() const {
|
/**
|
||||||
return GrColorUnpackR(fCommon.fCoverage);
|
* Version of above that specifies 4 channel per-vertex color. The value
|
||||||
|
* should be premultiplied.
|
||||||
|
*/
|
||||||
|
void setCoverage4(GrColor coverage) {
|
||||||
|
fCommon.fCoverage = coverage;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrColor getCoverageColor() const {
|
GrColor getCoverage() const {
|
||||||
return fCommon.fCoverage;
|
return fCommon.fCoverage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,15 +100,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool canApplyCoverage() const;
|
bool canApplyCoverage() const;
|
||||||
|
|
||||||
/** When we're using coverage AA but the blend is incompatible (given gpu
|
|
||||||
* limitations) we should disable AA. */
|
|
||||||
bool shouldDisableCoverageAAForBlend() {
|
|
||||||
// Enable below if we should draw with AA even when it produces
|
|
||||||
// incorrect blending.
|
|
||||||
// return false;
|
|
||||||
return !this->canApplyCoverage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given the current draw state and hw support, will HW AA lines be used (if
|
* Given the current draw state and hw support, will HW AA lines be used (if
|
||||||
* a line primitive type is drawn)?
|
* a line primitive type is drawn)?
|
||||||
|
@ -460,11 +460,7 @@ void GrOvalRenderer::reset() {
|
|||||||
bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, bool useAA,
|
bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, bool useAA,
|
||||||
const SkRect& oval, const SkStrokeRec& stroke)
|
const SkRect& oval, const SkStrokeRec& stroke)
|
||||||
{
|
{
|
||||||
bool useCoverageAA = useAA &&
|
if (!useAA) {
|
||||||
!target->getDrawState().getRenderTarget()->isMultisampled() &&
|
|
||||||
!target->shouldDisableCoverageAAForBlend();
|
|
||||||
|
|
||||||
if (!useCoverageAA) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,13 +469,13 @@ bool GrOvalRenderer::drawOval(GrDrawTarget* target, const GrContext* context, bo
|
|||||||
// we can draw circles
|
// we can draw circles
|
||||||
if (SkScalarNearlyEqual(oval.width(), oval.height())
|
if (SkScalarNearlyEqual(oval.width(), oval.height())
|
||||||
&& circle_stays_circle(vm)) {
|
&& circle_stays_circle(vm)) {
|
||||||
this->drawCircle(target, useCoverageAA, oval, stroke);
|
this->drawCircle(target, useAA, oval, stroke);
|
||||||
// if we have shader derivative support, render as device-independent
|
// if we have shader derivative support, render as device-independent
|
||||||
} else if (target->caps()->shaderDerivativeSupport()) {
|
} else if (target->caps()->shaderDerivativeSupport()) {
|
||||||
return this->drawDIEllipse(target, useCoverageAA, oval, stroke);
|
return this->drawDIEllipse(target, useAA, oval, stroke);
|
||||||
// otherwise axis-aligned ellipses only
|
// otherwise axis-aligned ellipses only
|
||||||
} else if (vm.rectStaysRect()) {
|
} else if (vm.rectStaysRect()) {
|
||||||
return this->drawEllipse(target, useCoverageAA, oval, stroke);
|
return this->drawEllipse(target, useAA, oval, stroke);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -496,7 +492,7 @@ extern const GrVertexAttrib gCircleVertexAttribs[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void GrOvalRenderer::drawCircle(GrDrawTarget* target,
|
void GrOvalRenderer::drawCircle(GrDrawTarget* target,
|
||||||
bool useCoverageAA,
|
bool useAA,
|
||||||
const SkRect& circle,
|
const SkRect& circle,
|
||||||
const SkStrokeRec& stroke)
|
const SkStrokeRec& stroke)
|
||||||
{
|
{
|
||||||
@ -601,7 +597,7 @@ extern const GrVertexAttrib gDIEllipseVertexAttribs[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
|
bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
|
||||||
bool useCoverageAA,
|
bool useAA,
|
||||||
const SkRect& ellipse,
|
const SkRect& ellipse,
|
||||||
const SkStrokeRec& stroke)
|
const SkStrokeRec& stroke)
|
||||||
{
|
{
|
||||||
@ -610,7 +606,7 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
|
|||||||
{
|
{
|
||||||
// we should have checked for this previously
|
// we should have checked for this previously
|
||||||
bool isAxisAlignedEllipse = drawState->getViewMatrix().rectStaysRect();
|
bool isAxisAlignedEllipse = drawState->getViewMatrix().rectStaysRect();
|
||||||
SkASSERT(useCoverageAA && isAxisAlignedEllipse);
|
SkASSERT(useAA && isAxisAlignedEllipse);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -733,7 +729,7 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target,
|
bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target,
|
||||||
bool useCoverageAA,
|
bool useAA,
|
||||||
const SkRect& ellipse,
|
const SkRect& ellipse,
|
||||||
const SkStrokeRec& stroke)
|
const SkStrokeRec& stroke)
|
||||||
{
|
{
|
||||||
@ -886,12 +882,8 @@ GrIndexBuffer* GrOvalRenderer::rRectIndexBuffer(GrGpu* gpu) {
|
|||||||
bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, bool useAA,
|
bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, bool useAA,
|
||||||
const SkRRect& rrect, const SkStrokeRec& stroke)
|
const SkRRect& rrect, const SkStrokeRec& stroke)
|
||||||
{
|
{
|
||||||
bool useCoverageAA = useAA &&
|
|
||||||
!target->getDrawState().getRenderTarget()->isMultisampled() &&
|
|
||||||
!target->shouldDisableCoverageAAForBlend();
|
|
||||||
|
|
||||||
// only anti-aliased rrects for now
|
// only anti-aliased rrects for now
|
||||||
if (!useCoverageAA) {
|
if (!useAA) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -899,7 +891,7 @@ bool GrOvalRenderer::drawSimpleRRect(GrDrawTarget* target, GrContext* context, b
|
|||||||
#ifdef SK_DEBUG
|
#ifdef SK_DEBUG
|
||||||
{
|
{
|
||||||
// we should have checked for this previously
|
// we should have checked for this previously
|
||||||
SkASSERT(useCoverageAA && vm.rectStaysRect() && rrect.isSimple());
|
SkASSERT(useAA && vm.rectStaysRect() && rrect.isSimple());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -37,13 +37,13 @@ public:
|
|||||||
const SkRRect& rrect, const SkStrokeRec& stroke);
|
const SkRRect& rrect, const SkStrokeRec& stroke);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool drawEllipse(GrDrawTarget* target, bool useCoverageAA,
|
bool drawEllipse(GrDrawTarget* target, bool useAA,
|
||||||
const SkRect& ellipse,
|
const SkRect& ellipse,
|
||||||
const SkStrokeRec& stroke);
|
const SkStrokeRec& stroke);
|
||||||
bool drawDIEllipse(GrDrawTarget* target, bool useCoverageAA,
|
bool drawDIEllipse(GrDrawTarget* target, bool useAA,
|
||||||
const SkRect& ellipse,
|
const SkRect& ellipse,
|
||||||
const SkStrokeRec& stroke);
|
const SkStrokeRec& stroke);
|
||||||
void drawCircle(GrDrawTarget* target, bool useCoverageAA,
|
void drawCircle(GrDrawTarget* target, bool useAA,
|
||||||
const SkRect& circle,
|
const SkRect& circle,
|
||||||
const SkStrokeRec& stroke);
|
const SkStrokeRec& stroke);
|
||||||
|
|
||||||
|
@ -12,8 +12,7 @@
|
|||||||
|
|
||||||
#include "GrContext.h"
|
#include "GrContext.h"
|
||||||
#include "GrBitmapTextContext.h"
|
#include "GrBitmapTextContext.h"
|
||||||
#include "GrGpu.h"
|
|
||||||
#include "GrDrawTargetCaps.h"
|
|
||||||
#include "SkGrTexturePixelRef.h"
|
#include "SkGrTexturePixelRef.h"
|
||||||
|
|
||||||
#include "SkColorFilter.h"
|
#include "SkColorFilter.h"
|
||||||
@ -851,6 +850,14 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// can we cheat, and treat a thin stroke as a hairline w/ coverage
|
||||||
|
// if we can, we draw lots faster (raster device does this same test)
|
||||||
|
SkScalar hairlineCoverage;
|
||||||
|
bool doHairLine = SkDrawTreatAsHairline(paint, fContext->getMatrix(), &hairlineCoverage);
|
||||||
|
if (doHairLine) {
|
||||||
|
grPaint.setCoverage(SkScalarRoundToInt(hairlineCoverage * grPaint.getCoverage()));
|
||||||
|
}
|
||||||
|
|
||||||
// If we have a prematrix, apply it to the path, optimizing for the case
|
// If we have a prematrix, apply it to the path, optimizing for the case
|
||||||
// where the original path can in fact be modified in place (even though
|
// where the original path can in fact be modified in place (even though
|
||||||
// its parameter type is const).
|
// its parameter type is const).
|
||||||
@ -880,6 +887,10 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
|
|||||||
pathPtr = &effectPath;
|
pathPtr = &effectPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!pathEffect && doHairLine) {
|
||||||
|
stroke.setHairlineStyle();
|
||||||
|
}
|
||||||
|
|
||||||
if (paint.getMaskFilter()) {
|
if (paint.getMaskFilter()) {
|
||||||
if (!stroke.isHairlineStyle()) {
|
if (!stroke.isHairlineStyle()) {
|
||||||
if (stroke.applyToPath(&tmpPath, *pathPtr)) {
|
if (stroke.applyToPath(&tmpPath, *pathPtr)) {
|
||||||
|
@ -207,10 +207,10 @@ void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
|
|||||||
coverage = 0;
|
coverage = 0;
|
||||||
} else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) {
|
} else if (blendOpts & GrDrawState::kEmitCoverage_BlendOptFlag) {
|
||||||
color = 0xffffffff;
|
color = 0xffffffff;
|
||||||
coverage = drawState.getCoverageColor();
|
coverage = drawState.getCoverage();
|
||||||
} else {
|
} else {
|
||||||
color = drawState.getColor();
|
color = drawState.getColor();
|
||||||
coverage = drawState.getCoverageColor();
|
coverage = drawState.getCoverage();
|
||||||
}
|
}
|
||||||
|
|
||||||
this->setColor(drawState, color, sharedState);
|
this->setColor(drawState, color, sharedState);
|
||||||
|
@ -156,7 +156,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState,
|
|||||||
header->fHasVertexCode = true;
|
header->fHasVertexCode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverageColor();
|
bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverage();
|
||||||
|
|
||||||
if (skipCoverage) {
|
if (skipCoverage) {
|
||||||
header->fCoverageInput = kTransBlack_ColorInput;
|
header->fCoverageInput = kTransBlack_ColorInput;
|
||||||
|
Loading…
Reference in New Issue
Block a user