зеркало из https://github.com/mozilla/moz-skia.git
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:
Родитель
376cd1f919
Коммит
dd1be60702
|
@ -36,6 +36,7 @@ public:
|
||||||
bool fColorMatrixEnabled;
|
bool fColorMatrixEnabled;
|
||||||
|
|
||||||
GrColor fColor;
|
GrColor fColor;
|
||||||
|
uint8_t fCoverage;
|
||||||
|
|
||||||
GrColor fColorFilterColor;
|
GrColor fColorFilterColor;
|
||||||
SkXfermode::Mode fColorFilterXfermode;
|
SkXfermode::Mode fColorFilterXfermode;
|
||||||
|
@ -126,6 +127,7 @@ public:
|
||||||
fDither = paint.fDither;
|
fDither = paint.fDither;
|
||||||
|
|
||||||
fColor = paint.fColor;
|
fColor = paint.fColor;
|
||||||
|
fCoverage = paint.fCoverage;
|
||||||
|
|
||||||
fColorFilterColor = paint.fColorFilterColor;
|
fColorFilterColor = paint.fColorFilterColor;
|
||||||
fColorFilterXfermode = paint.fColorFilterXfermode;
|
fColorFilterXfermode = paint.fColorFilterXfermode;
|
||||||
|
@ -161,6 +163,7 @@ public:
|
||||||
this->resetBlend();
|
this->resetBlend();
|
||||||
this->resetOptions();
|
this->resetOptions();
|
||||||
this->resetColor();
|
this->resetColor();
|
||||||
|
this->resetCoverage();
|
||||||
this->resetTextures();
|
this->resetTextures();
|
||||||
this->resetColorFilter();
|
this->resetColorFilter();
|
||||||
this->resetMasks();
|
this->resetMasks();
|
||||||
|
@ -242,6 +245,10 @@ private:
|
||||||
fColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
|
fColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void resetCoverage() {
|
||||||
|
fCoverage = 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
void resetTextures() {
|
void resetTextures() {
|
||||||
for (int i = 0; i < kMaxTextures; ++i) {
|
for (int i = 0; i < kMaxTextures; ++i) {
|
||||||
this->setTexture(i, NULL);
|
this->setTexture(i, NULL);
|
||||||
|
|
|
@ -860,14 +860,14 @@ static bool xfermodeSupportsCoverageAsAlpha(SkXfermode* xfer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix,
|
bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix,
|
||||||
SkAlpha* newAlpha) {
|
SkScalar* coverage) {
|
||||||
SkASSERT(newAlpha);
|
SkASSERT(coverage);
|
||||||
if (SkPaint::kStroke_Style != paint.getStyle()) {
|
if (SkPaint::kStroke_Style != paint.getStyle()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
SkScalar strokeWidth = paint.getStrokeWidth();
|
SkScalar strokeWidth = paint.getStrokeWidth();
|
||||||
if (0 == strokeWidth) {
|
if (0 == strokeWidth) {
|
||||||
*newAlpha = paint.getAlpha();
|
*coverage = SK_Scalar1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -877,9 +877,6 @@ bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix,
|
||||||
if (!paint.isAntiAlias()) {
|
if (!paint.isAntiAlias()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!xfermodeSupportsCoverageAsAlpha(paint.getXfermode())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (matrix.hasPerspective()) {
|
if (matrix.hasPerspective()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -891,16 +888,7 @@ bool SkDrawTreatAsHairline(const SkPaint& paint, const SkMatrix& matrix,
|
||||||
SkScalar len0 = fast_len(dst[0]);
|
SkScalar len0 = fast_len(dst[0]);
|
||||||
SkScalar len1 = fast_len(dst[1]);
|
SkScalar len1 = fast_len(dst[1]);
|
||||||
if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) {
|
if (len0 <= SK_Scalar1 && len1 <= SK_Scalar1) {
|
||||||
SkScalar modulate = SkScalarAve(len0, len1);
|
*coverage = 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
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -947,12 +935,29 @@ void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint,
|
||||||
SkTLazy<SkPaint> lazyPaint;
|
SkTLazy<SkPaint> lazyPaint;
|
||||||
|
|
||||||
{
|
{
|
||||||
SkAlpha newAlpha;
|
SkScalar coverage;
|
||||||
if (SkDrawTreatAsHairline(origPaint, *matrix, &newAlpha)) {
|
if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) {
|
||||||
|
if (SK_Scalar1 == coverage) {
|
||||||
lazyPaint.set(origPaint);
|
lazyPaint.set(origPaint);
|
||||||
lazyPaint.get()->setAlpha(newAlpha);
|
|
||||||
lazyPaint.get()->setStrokeWidth(0);
|
lazyPaint.get()->setStrokeWidth(0);
|
||||||
paint = lazyPaint.get();
|
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
|
* If the current paint is set to stroke and the stroke-width when applied to
|
||||||
* stroke-width when applied to the matrix is <= 1.0, then this returns true,
|
* the matrix is <= 1.0, then this returns true, and sets coverage (simulating
|
||||||
* and sets newAlpha (simulating a stroke by drawing a hairline + newAlpha).
|
* a stroke by drawing a hairline with partial coverage). If any of these
|
||||||
* If any of these conditions are false, then this returns false and modulate
|
* conditions are false, then this returns false and coverage is ignored.
|
||||||
* is ignored.
|
|
||||||
*/
|
*/
|
||||||
bool SkDrawTreatAsHairline(const SkPaint&, const SkMatrix&, SkAlpha* newAlpha);
|
bool SkDrawTreatAsHairline(const SkPaint&, const SkMatrix&, SkScalar* coverage);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -2060,6 +2060,7 @@ void GrContext::setPaint(const GrPaint& paint, GrDrawTarget* target) {
|
||||||
drawState->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
|
drawState->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
|
||||||
drawState->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
|
drawState->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
|
||||||
drawState->setColorMatrix(paint.fColorMatrix);
|
drawState->setColorMatrix(paint.fColorMatrix);
|
||||||
|
drawState->setCoverage(paint.fCoverage);
|
||||||
|
|
||||||
if (paint.getActiveMaskStageMask() && !target->canApplyCoverage()) {
|
if (paint.getActiveMaskStageMask() && !target->canApplyCoverage()) {
|
||||||
GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
|
GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
|
||||||
|
@ -2254,6 +2255,9 @@ void GrContext::convolve(GrTexture* texture,
|
||||||
|
|
||||||
GrDrawTarget::AutoStateRestore asr(fGpu);
|
GrDrawTarget::AutoStateRestore asr(fGpu);
|
||||||
GrDrawState* drawState = fGpu->drawState();
|
GrDrawState* drawState = fGpu->drawState();
|
||||||
|
GrRenderTarget* target = drawState->getRenderTarget();
|
||||||
|
drawState->reset();
|
||||||
|
drawState->setRenderTarget(target);
|
||||||
GrMatrix sampleM;
|
GrMatrix sampleM;
|
||||||
sampleM.setIDiv(texture->width(), texture->height());
|
sampleM.setIDiv(texture->width(), texture->height());
|
||||||
drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
|
drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
|
||||||
|
@ -2263,10 +2267,7 @@ void GrContext::convolve(GrTexture* texture,
|
||||||
kernel,
|
kernel,
|
||||||
imageIncrement);
|
imageIncrement);
|
||||||
|
|
||||||
drawState->setViewMatrix(GrMatrix::I());
|
|
||||||
drawState->setTexture(0, texture);
|
drawState->setTexture(0, texture);
|
||||||
drawState->setAlpha(0xFF);
|
|
||||||
drawState->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff);
|
|
||||||
fGpu->drawSimpleRect(rect, NULL, 1 << 0);
|
fGpu->drawSimpleRect(rect, NULL, 1 << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -412,6 +412,7 @@ bool SkGpuDevice::skPaint2GrPaintNoShader(const SkPaint& skPaint,
|
||||||
|
|
||||||
grPaint->fDither = skPaint.isDither();
|
grPaint->fDither = skPaint.isDither();
|
||||||
grPaint->fAntiAlias = skPaint.isAntiAlias();
|
grPaint->fAntiAlias = skPaint.isAntiAlias();
|
||||||
|
grPaint->fCoverage = 0xFF;
|
||||||
|
|
||||||
SkXfermode::Coeff sm = SkXfermode::kOne_Coeff;
|
SkXfermode::Coeff sm = SkXfermode::kOne_Coeff;
|
||||||
SkXfermode::Coeff dm = SkXfermode::kISA_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,
|
void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
|
||||||
const SkPaint& origPaint, const SkMatrix* prePathMatrix,
|
const SkPaint& paint, const SkMatrix* prePathMatrix,
|
||||||
bool pathIsMutable) {
|
bool pathIsMutable) {
|
||||||
CHECK_SHOULD_DRAW(draw);
|
CHECK_SHOULD_DRAW(draw);
|
||||||
|
|
||||||
bool doFill = true;
|
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)
|
// if we can, we draw lots faster (raster device does this same test)
|
||||||
{
|
if (SkDrawTreatAsHairline(paint, *draw.fMatrix, &coverage)) {
|
||||||
SkAlpha newAlpha;
|
|
||||||
if (SkDrawTreatAsHairline(*paint, *draw.fMatrix, &newAlpha)) {
|
|
||||||
lazyPaint.set(*paint);
|
|
||||||
lazyPaint.get()->setAlpha(newAlpha);
|
|
||||||
lazyPaint.get()->setStrokeWidth(0);
|
|
||||||
paint = lazyPaint.get();
|
|
||||||
doFill = false;
|
doFill = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// must reference paint from here down, and not origPaint
|
|
||||||
// since we may have change the paint (using lazyPaint for storage)
|
|
||||||
|
|
||||||
GrPaint grPaint;
|
GrPaint grPaint;
|
||||||
SkAutoCachedTexture act;
|
SkAutoCachedTexture act;
|
||||||
if (!this->skPaint2GrPaintShader(*paint,
|
if (!this->skPaint2GrPaintShader(paint,
|
||||||
&act,
|
&act,
|
||||||
*draw.fMatrix,
|
*draw.fMatrix,
|
||||||
&grPaint,
|
&grPaint,
|
||||||
|
@ -1094,6 +1085,8 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grPaint.fCoverage = SkScalarRoundToInt(coverage * grPaint.fCoverage);
|
||||||
|
|
||||||
// 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).
|
||||||
|
@ -1115,25 +1108,25 @@ void SkGpuDevice::drawPath(const SkDraw& draw, const SkPath& origSrcPath,
|
||||||
// at this point we're done with prePathMatrix
|
// at this point we're done with prePathMatrix
|
||||||
SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
|
SkDEBUGCODE(prePathMatrix = (const SkMatrix*)0x50FF8001;)
|
||||||
|
|
||||||
if (doFill && (paint->getPathEffect() ||
|
if (doFill && (paint.getPathEffect() ||
|
||||||
paint->getStyle() != SkPaint::kFill_Style)) {
|
paint.getStyle() != SkPaint::kFill_Style)) {
|
||||||
// it is safe to use tmpPath here, even if we already used it for the
|
// 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
|
// prepathmatrix, since getFillPath can take the same object for its
|
||||||
// input and output safely.
|
// input and output safely.
|
||||||
doFill = paint->getFillPath(*pathPtr, &tmpPath);
|
doFill = paint.getFillPath(*pathPtr, &tmpPath);
|
||||||
pathPtr = &tmpPath;
|
pathPtr = &tmpPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (paint->getMaskFilter()) {
|
if (paint.getMaskFilter()) {
|
||||||
// avoid possibly allocating a new path in transform if we can
|
// avoid possibly allocating a new path in transform if we can
|
||||||
SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
|
SkPath* devPathPtr = pathIsMutable ? pathPtr : &tmpPath;
|
||||||
|
|
||||||
// transform the path into device space
|
// transform the path into device space
|
||||||
pathPtr->transform(*draw.fMatrix, devPathPtr);
|
pathPtr->transform(*draw.fMatrix, devPathPtr);
|
||||||
if (!drawWithGPUMaskFilter(fContext, *devPathPtr, paint->getMaskFilter(),
|
if (!drawWithGPUMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
|
||||||
*draw.fMatrix, *draw.fClip, draw.fBounder,
|
*draw.fMatrix, *draw.fClip, draw.fBounder,
|
||||||
&grPaint)) {
|
&grPaint)) {
|
||||||
drawWithMaskFilter(fContext, *devPathPtr, paint->getMaskFilter(),
|
drawWithMaskFilter(fContext, *devPathPtr, paint.getMaskFilter(),
|
||||||
*draw.fMatrix, *draw.fClip, draw.fBounder,
|
*draw.fMatrix, *draw.fClip, draw.fBounder,
|
||||||
&grPaint);
|
&grPaint);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче