Pull xfer mode test out of generic draw-as-hairline test. Use coverage rather than alpha to draw hairlines < 1pix wide in GPU.
Review URL: http://codereview.appspot.com/5528112/ git-svn-id: http://skia.googlecode.com/svn/trunk@3070 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
376cd1f919
commit
dd1be60702
@ -36,6 +36,7 @@ public:
|
||||
bool fColorMatrixEnabled;
|
||||
|
||||
GrColor fColor;
|
||||
uint8_t fCoverage;
|
||||
|
||||
GrColor fColorFilterColor;
|
||||
SkXfermode::Mode fColorFilterXfermode;
|
||||
@ -126,6 +127,7 @@ public:
|
||||
fDither = paint.fDither;
|
||||
|
||||
fColor = paint.fColor;
|
||||
fCoverage = paint.fCoverage;
|
||||
|
||||
fColorFilterColor = paint.fColorFilterColor;
|
||||
fColorFilterXfermode = paint.fColorFilterXfermode;
|
||||
@ -161,6 +163,7 @@ public:
|
||||
this->resetBlend();
|
||||
this->resetOptions();
|
||||
this->resetColor();
|
||||
this->resetCoverage();
|
||||
this->resetTextures();
|
||||
this->resetColorFilter();
|
||||
this->resetMasks();
|
||||
@ -242,6 +245,10 @@ private:
|
||||
fColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
|
||||
}
|
||||
|
||||
void resetCoverage() {
|
||||
fCoverage = 0xff;
|
||||
}
|
||||
|
||||
void resetTextures() {
|
||||
for (int i = 0; i < kMaxTextures; ++i) {
|
||||
this->setTexture(i, NULL);
|
||||
|
@ -860,14 +860,14 @@ static bool xfermodeSupportsCoverageAsAlpha(SkXfermode* xfer) {
|
||||
}
|
||||
|
||||
bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix,
|
||||
SkAlpha* newAlpha) {
|
||||
SkASSERT(newAlpha);
|
||||
SkScalar* coverage) {
|
||||
SkASSERT(coverage);
|
||||
if (SkPaint::kStroke_Style != paint.getStyle()) {
|
||||
return false;
|
||||
}
|
||||
SkScalar strokeWidth = paint.getStrokeWidth();
|
||||
if (0 == strokeWidth) {
|
||||
*newAlpha = paint.getAlpha();
|
||||
*coverage = SK_Scalar1;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -877,9 +877,6 @@ bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix,
|
||||
if (!paint.isAntiAlias()) {
|
||||
return false;
|
||||
}
|
||||
if (!xfermodeSupportsCoverageAsAlpha(paint.getXfermode())) {
|
||||
return false;
|
||||
}
|
||||
if (matrix.hasPerspective()) {
|
||||
return false;
|
||||
}
|
||||
@ -891,16 +888,7 @@ bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix,
|
||||
SkScalar len0 = fast_len(dst[0]);
|
||||
SkScalar len1 = fast_len(dst[1]);
|
||||
if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) {
|
||||
SkScalar modulate = SkScalarAve(len0, len1);
|
||||
#if 0
|
||||
*newAlpha = SkToU8(SkScalarRoundToInt(modulate * paint.getAlpha()));
|
||||
#else
|
||||
// this is the old technique, which we preserve for now so we don't
|
||||
// change previous results (testing)
|
||||
// the new way seems fine, its just (a tiny bit) different
|
||||
int scale = (int)SkScalarMul(modulate, 256);
|
||||
*newAlpha = paint.getAlpha() * scale >> 8;
|
||||
#endif
|
||||
*coverage = SkScalarAve(len0, len1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -947,12 +935,29 @@ void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint,
|
||||
SkTLazy<SkPaint> lazyPaint;
|
||||
|
||||
{
|
||||
SkAlpha newAlpha;
|
||||
if (SkDrawTreatAsHairline(origPaint, *matrix, &newAlpha)) {
|
||||
lazyPaint.set(origPaint);
|
||||
lazyPaint.get()->setAlpha(newAlpha);
|
||||
lazyPaint.get()->setStrokeWidth(0);
|
||||
paint = lazyPaint.get();
|
||||
SkScalar coverage;
|
||||
if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) {
|
||||
if (SK_Scalar1 == coverage) {
|
||||
lazyPaint.set(origPaint);
|
||||
lazyPaint.get()->setStrokeWidth(0);
|
||||
paint = lazyPaint.get();
|
||||
} else if (xfermodeSupportsCoverageAsAlpha(origPaint.getXfermode())) {
|
||||
U8CPU newAlpha;
|
||||
#if 0
|
||||
newAlpha = SkToU8(SkScalarRoundToInt(coverage *
|
||||
origPaint.getAlpha()));
|
||||
#else
|
||||
// this is the old technique, which we preserve for now so
|
||||
// we don't change previous results (testing)
|
||||
// the new way seems fine, its just (a tiny bit) different
|
||||
int scale = (int)SkScalarMul(coverage, 256);
|
||||
newAlpha = origPaint.getAlpha() * scale >> 8;
|
||||
#endif
|
||||
lazyPaint.set(origPaint);
|
||||
lazyPaint.get()->setStrokeWidth(0);
|
||||
lazyPaint.get()->setAlpha(newAlpha);
|
||||
paint = lazyPaint.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,13 +35,12 @@ struct SkDrawProcs {
|
||||
};
|
||||
|
||||
/**
|
||||
* If the current paint is set to stroke, has a compatible xfermode, and the
|
||||
* stroke-width when applied to the matrix is <= 1.0, then this returns true,
|
||||
* and sets newAlpha (simulating a stroke by drawing a hairline + newAlpha).
|
||||
* If any of these conditions are false, then this returns false and modulate
|
||||
* is ignored.
|
||||
* 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
|
||||
* a stroke by drawing a hairline with partial coverage). If any of these
|
||||
* conditions are false, then this returns false and coverage is ignored.
|
||||
*/
|
||||
bool SkDrawTreatAsHairline(const SkPaint&, const SkMatrix&, SkAlpha* newAlpha);
|
||||
bool SkDrawTreatAsHairline(const SkPaint&, const SkMatrix&, SkScalar* coverage);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -2060,6 +2060,7 @@ void GrContext::setPaint(const GrPaint& paint, GrDrawTarget* target) {
|
||||
drawState->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
|
||||
drawState->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
|
||||
drawState->setColorMatrix(paint.fColorMatrix);
|
||||
drawState->setCoverage(paint.fCoverage);
|
||||
|
||||
if (paint.getActiveMaskStageMask() && !target->canApplyCoverage()) {
|
||||
GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
|
||||
@ -2254,6 +2255,9 @@ void GrContext::convolve(GrTexture* texture,
|
||||
|
||||
GrDrawTarget::AutoStateRestore asr(fGpu);
|
||||
GrDrawState* drawState = fGpu->drawState();
|
||||
GrRenderTarget* target = drawState->getRenderTarget();
|
||||
drawState->reset();
|
||||
drawState->setRenderTarget(target);
|
||||
GrMatrix sampleM;
|
||||
sampleM.setIDiv(texture->width(), texture->height());
|
||||
drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
|
||||
@ -2263,10 +2267,7 @@ void GrContext::convolve(GrTexture* texture,
|
||||
kernel,
|
||||
imageIncrement);
|
||||
|
||||
drawState->setViewMatrix(GrMatrix::I());
|
||||
drawState->setTexture(0, texture);
|
||||
drawState->setAlpha(0xFF);
|
||||
drawState->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff);
|
||||
fGpu->drawSimpleRect(rect, NULL, 1 << 0);
|
||||
}
|
||||
|
||||
|
@ -412,6 +412,7 @@ bool SkGpuDevice::skPaint2GrPaintNoShader(const SkPaint& skPaint,
|
||||
|
||||
grPaint->fDither = skPaint.isDither();
|
||||
grPaint->fAntiAlias = skPaint.isAntiAlias();
|
||||
grPaint->fCoverage = 0xFF;
|
||||
|
||||
SkXfermode::Coeff sm = SkXfermode::kOne_Coeff;
|
||||
SkXfermode::Coeff dm = SkXfermode::kISA_Coeff;
|
||||
@ -1061,32 +1062,22 @@ static bool drawWithMaskFilter(GrContext* context, const SkPath& path,
|
||||
}
|
||||
|
||||
void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
|
||||
const SkPaint& origPaint, const SkMatrix* prePathMatrix,
|
||||
const SkPaint& paint, const SkMatrix* prePathMatrix,
|
||||
bool pathIsMutable) {
|
||||
CHECK_SHOULD_DRAW(draw);
|
||||
|
||||
bool doFill = true;
|
||||
SkTLazy<SkPaint> lazyPaint;
|
||||
const SkPaint* paint = &origPaint;
|
||||
|
||||
// can we cheat, and threat a thin stroke as a hairline (w/ modulated alpha)
|
||||
|
||||
SkScalar coverage = SK_Scalar1;
|
||||
// can we cheat, and threat a thin stroke as a hairline w/ coverage
|
||||
// if we can, we draw lots faster (raster device does this same test)
|
||||
{
|
||||
SkAlpha newAlpha;
|
||||
if (SkDrawTreatAsHairline(*paint, *draw.fMatrix, &newAlpha)) {
|
||||
lazyPaint.set(*paint);
|
||||
lazyPaint.get()->setAlpha(newAlpha);
|
||||
lazyPaint.get()->setStrokeWidth(0);
|
||||
paint = lazyPaint.get();
|
||||
doFill = false;
|
||||
}
|
||||
if (SkDrawTreatAsHairline(paint, *draw.fMatrix, &coverage)) {
|
||||
doFill = false;
|
||||
}
|
||||
// must reference paint from here down, and not origPaint
|
||||
// since we may have change the paint (using lazyPaint for storage)
|
||||
|
||||
GrPaint grPaint;
|
||||
SkAutoCachedTexture act;
|
||||
if (!this->skPaint2GrPaintShader(*paint,
|
||||
if (!this->skPaint2GrPaintShader(paint,
|
||||
&act,
|
||||
*draw.fMatrix,
|
||||
&grPaint,
|
||||
@ -1094,6 +1085,8 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
|
||||
return;
|
||||
}
|
||||
|
||||
grPaint.fCoverage = SkScalarRoundToInt(coverage * grPaint.fCoverage);
|
||||
|
||||
// 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
|
||||
// its parameter type is const).
|
||||
@ -1115,25 +1108,25 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
|
||||
// at this point we're done with prePathMatrix
|
||||
SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
|
||||
|
||||
if (doFill && (paint->getPathEffect() ||
|
||||
paint->getStyle() != SkPaint::kFill_Style)) {
|
||||
if (doFill && (paint.getPathEffect() ||
|
||||
paint.getStyle() != SkPaint::kFill_Style)) {
|
||||
// it is safe to use tmpPath here, even if we already used it for the
|
||||
// prepathmatrix, since getFillPath can take the same object for its
|
||||
// input and output safely.
|
||||
doFill = paint->getFillPath(*pathPtr, &tmpPath);
|
||||
doFill = paint.getFillPath(*pathPtr, &tmpPath);
|
||||
pathPtr = &tmpPath;
|
||||
}
|
||||
|
||||
if (paint->getMaskFilter()) {
|
||||
if (paint.getMaskFilter()) {
|
||||
// avoid possibly allocating a new path in transform if we can
|
||||
SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
|
||||
|
||||
// transform the path into device space
|
||||
pathPtr->transform(*draw.fMatrix, devPathPtr);
|
||||
if (!drawWithGPUMaskFilter(fContext, *devPathPtr, paint->getMaskFilter(),
|
||||
if (!drawWithGPUMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
|
||||
*draw.fMatrix, *draw.fClip, draw.fBounder,
|
||||
&grPaint)) {
|
||||
drawWithMaskFilter(fContext, *devPathPtr, paint->getMaskFilter(),
|
||||
drawWithMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
|
||||
*draw.fMatrix, *draw.fClip, draw.fBounder,
|
||||
&grPaint);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user