Use fast path for circular shadows.

Also cleans up some of the MaskFilter code to make it
more correct.

BUG=skia:6119

Change-Id: I93016bcdd9c55fcb2d1dc8776428a72eb563d67a
Reviewed-on: https://skia-review.googlesource.com/9116
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Jim Van Verth 2017-03-02 11:28:43 -05:00 committed by Skia Commit-Bot
parent e7e5499c78
commit cf40e307cd
4 changed files with 31 additions and 30 deletions

View File

@ -469,7 +469,7 @@ protected:
canvas->translate(-250, 110);
lightPos.fX -= 250;
lightPos.fY += 110;
this->drawShadowedPath(canvas, fCirclePath, SkTMax(1.0f, 8+fZDelta), paint, 0,
this->drawShadowedPath(canvas, fCirclePath, SkTMax(1.0f, 8+fZDelta), paint, kAmbientAlpha,
lightPos, kLightWidth, 0.5f);
paint.setColor(SK_ColorGREEN);

View File

@ -220,12 +220,12 @@ bool SkAmbientShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
if (fAmbientAlpha > 0.0f) {
SkScalar srcSpaceAmbientRadius = fOccluderHeight * kHeightFactor * kGeomFactor;
const float umbraAlpha = (1.0f + SkTMax(fOccluderHeight * kHeightFactor, 0.0f));
const SkScalar ambientOffset = srcSpaceAmbientRadius / umbraAlpha;
const SkScalar strokeWidth = srcSpaceAmbientRadius * umbraAlpha;
// For the ambient rrect, we inset the offset rect by half the srcSpaceAmbientRadius
// to get our stroke shape.
SkScalar ambientPathOutset = SkTMax(ambientOffset - srcSpaceAmbientRadius * 0.5f,
minRadius);
// For the ambient rrect, we outset the offset rect by srcSpaceAmbientRadius
// minus half the strokeWidth to get our stroke shape.
SkScalar ambientPathOutset = SkTMax(srcSpaceAmbientRadius - strokeWidth * 0.5f,
minRadius);
SkRRect ambientRRect;
if (isRect) {
@ -235,14 +235,14 @@ bool SkAmbientShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
rrect.outset(ambientPathOutset, ambientPathOutset, &ambientRRect);
}
const SkScalar devSpaceAmbientRadius = srcSpaceAmbientRadius * scaleFactor;
const SkScalar devSpaceAmbientRadius = strokeWidth * scaleFactor;
GrPaint newPaint(paint);
GrColor4f color = newPaint.getColor4f();
color.fRGBA[3] *= fAmbientAlpha;
newPaint.setColor4f(color);
SkStrokeRec ambientStrokeRec(SkStrokeRec::kHairline_InitStyle);
ambientStrokeRec.setStrokeStyle(srcSpaceAmbientRadius, false);
ambientStrokeRec.setStrokeStyle(strokeWidth, false);
rtContext->drawShadowRRect(clip, std::move(newPaint), viewMatrix, ambientRRect,
devSpaceAmbientRadius,

View File

@ -101,13 +101,6 @@ public:
}
}
// TODO: still needed?
// The radii are outset for two reasons. First, it allows the shader to simply perform
// simpler computation because the computed alpha is zero, rather than 50%, at the radius.
// Second, the outer radius is used to compute the verts of the bounding box that is
// rendered and the outset ensures the box will cover all partially covered by the circle.
outerRadius += SK_ScalarHalf;
innerRadius -= SK_ScalarHalf;
bool stroked = isStrokeOnly && innerRadius > 0.0f;
std::unique_ptr<ShadowCircleOp> op(new ShadowCircleOp());
op->fViewMatrixIfUsingLocalCoords = viewMatrix;
@ -533,8 +526,6 @@ public:
}
if (strokeOnly) {
// Outset stroke by 1/4 pixel
devStrokeWidth += 0.25f;
// If stroke is greater than width or height, this is still a fill
// Otherwise we compute stroke params
if (devStrokeWidth <= devRect.width() && devStrokeWidth <= devRect.height()) {
@ -546,19 +537,7 @@ public:
bounds.outset(halfWidth, halfWidth);
}
// TODO: still needed?
// The radii are outset for two reasons. First, it allows the shader to simply perform
// simpler computation because the computed alpha is zero, rather than 50%, at the radius.
// Second, the outer radius is used to compute the verts of the bounding box that is
// rendered and the outset ensures the box will cover all partially covered by the rrect
// corners.
outerRadius += SK_ScalarHalf;
innerRadius -= SK_ScalarHalf;
this->setBounds(bounds, HasAABloat::kYes, IsZeroArea::kNo);
// Expand the rect for aa to generate correct vertices.
bounds.outset(SK_ScalarHalf, SK_ScalarHalf);
this->setBounds(bounds, HasAABloat::kNo, IsZeroArea::kNo);
fGeoData.emplace_back(Geometry{color, outerRadius, innerRadius, blurRadius, bounds, type});
fVertCount = rrect_type_to_vert_count(type);

View File

@ -18,6 +18,8 @@
#include "GrShape.h"
#include "effects/GrBlurredEdgeFragmentProcessor.h"
#endif
#include "../../src/effects/shadows/SkAmbientShadowMaskFilter.h"
#include "../../src/effects/shadows/SkSpotShadowMaskFilter.h"
/**
* Gaussian color filter -- produces a Gaussian ramp based on the color's B value,
@ -457,6 +459,26 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, SkScalar oc
uint32_t flags, SkResourceCache* cache) {
SkAutoCanvasRestore acr(canvas, true);
SkMatrix viewMatrix = canvas->getTotalMatrix();
// try circular fast path
SkRect rect;
if (viewMatrix.isSimilarity() &&
path.isOval(&rect) && rect.width() == rect.height()) {
SkPaint newPaint;
newPaint.setColor(color);
if (ambientAlpha > 0) {
newPaint.setMaskFilter(SkAmbientShadowMaskFilter::Make(occluderHeight, ambientAlpha,
flags));
canvas->drawPath(path, newPaint);
}
if (spotAlpha > 0) {
newPaint.setMaskFilter(SkSpotShadowMaskFilter::Make(occluderHeight, devLightPos,
lightRadius, spotAlpha, flags));
canvas->drawPath(path, newPaint);
}
return;
}
canvas->resetMatrix();
ShadowedPath shadowedPath(&path, &viewMatrix);