aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/effects/SkShadowMaskFilter.cpp
diff options
context:
space:
mode:
authorGravatar Jim Van Verth <jvanverth@google.com>2016-11-17 15:27:09 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2016-11-21 21:44:20 +0000
commitc59034145862bf6dc0c503cb1e47eecd321ffa8c (patch)
tree2e9be313f7221dfe66c9777280be809d75c5a025 /src/effects/SkShadowMaskFilter.cpp
parent71de072f99a0a0e83d4c06420d870af2824a9d2d (diff)
Add shadowrrect geometry processor
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4233 Change-Id: I637099709cfe30f7d3c1883e23840a47a7a25c10 Reviewed-on: https://skia-review.googlesource.com/4233 Commit-Queue: Jim Van Verth <jvanverth@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
Diffstat (limited to 'src/effects/SkShadowMaskFilter.cpp')
-rwxr-xr-xsrc/effects/SkShadowMaskFilter.cpp196
1 files changed, 18 insertions, 178 deletions
diff --git a/src/effects/SkShadowMaskFilter.cpp b/src/effects/SkShadowMaskFilter.cpp
index 3894d749f1..958ab170a7 100755
--- a/src/effects/SkShadowMaskFilter.cpp
+++ b/src/effects/SkShadowMaskFilter.cpp
@@ -154,125 +154,6 @@ void SkShadowMaskFilterImpl::flatten(SkWriteBuffer& buffer) const {
///////////////////////////////////////////////////////////////////////////////////////////////////
-class GrShadowEdgeEffect : public GrFragmentProcessor {
-public:
- enum Type {
- kGaussian_Type,
- kSmoothStep_Type,
- kGeometric_Type
- };
-
- static sk_sp<GrFragmentProcessor> Make(Type type);
-
- ~GrShadowEdgeEffect() override {}
- const char* name() const override { return "GrShadowEdge"; }
-
-private:
- GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
-
- GrShadowEdgeEffect(Type type);
-
- void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
- GrProcessorKeyBuilder* b) const override;
-
- bool onIsEqual(const GrFragmentProcessor& other) const override;
-
- void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
-
- Type fType;
-
- GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
-
- typedef GrFragmentProcessor INHERITED;
-};
-
-sk_sp<GrFragmentProcessor> GrShadowEdgeEffect::Make(Type type) {
- return sk_sp<GrFragmentProcessor>(new GrShadowEdgeEffect(type));
-}
-
-void GrShadowEdgeEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
- inout->mulByUnknownSingleComponent();
-}
-
-GrShadowEdgeEffect::GrShadowEdgeEffect(Type type)
- : fType(type) {
- this->initClassID<GrShadowEdgeEffect>();
- // TODO: remove this when we switch to a non-distance based approach
- // enable output of distance information for shape
- fUsesDistanceVectorField = true;
-}
-
-bool GrShadowEdgeEffect::onIsEqual(const GrFragmentProcessor& other) const {
- const GrShadowEdgeEffect& see = other.cast<GrShadowEdgeEffect>();
- return fType == see.fType;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrShadowEdgeEffect);
-
-sk_sp<GrFragmentProcessor> GrShadowEdgeEffect::TestCreate(GrProcessorTestData* d) {
- int t = d->fRandom->nextRangeU(0, 2);
- GrShadowEdgeEffect::Type type = kGaussian_Type;
- if (1 == t) {
- type = kSmoothStep_Type;
- } else if (2 == t) {
- type = kGeometric_Type;
- }
- return GrShadowEdgeEffect::Make(type);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-class GrGLShadowEdgeEffect : public GrGLSLFragmentProcessor {
-public:
- void emitCode(EmitArgs&) override;
-
-protected:
- void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
-
-private:
- typedef GrGLSLFragmentProcessor INHERITED;
-};
-
-void GrGLShadowEdgeEffect::emitCode(EmitArgs& args) {
-
- GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
-
- // TODO: handle smoothstep and geometric cases
- if (!args.fGpImplementsDistanceVector) {
- fragBuilder->codeAppendf("// GP does not implement fsDistanceVector - "
- " returning semi-transparent black in GrGLShadowEdgeEffect\n");
- fragBuilder->codeAppendf("vec4 color = %s;", args.fInputColor);
- fragBuilder->codeAppendf("%s = vec4(0.0, 0.0, 0.0, color.r);", args.fOutputColor);
- } else {
- fragBuilder->codeAppendf("vec4 color = %s;", args.fInputColor);
- fragBuilder->codeAppend("float radius = color.r*256.0*64.0 + color.g*64.0;");
- fragBuilder->codeAppend("float pad = color.b*64.0;");
-
- fragBuilder->codeAppendf("float factor = 1.0 - clamp((%s.z - pad)/radius, 0.0, 1.0);",
- fragBuilder->distanceVectorName());
- fragBuilder->codeAppend("factor = exp(-factor * factor * 4.0) - 0.018;");
- fragBuilder->codeAppendf("%s = factor*vec4(0.0, 0.0, 0.0, color.a);",
- args.fOutputColor);
- }
-}
-
-void GrGLShadowEdgeEffect::onSetData(const GrGLSLProgramDataManager& pdman,
- const GrProcessor& proc) {
-}
-
-void GrShadowEdgeEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
- GrProcessorKeyBuilder* b) const {
- GrGLShadowEdgeEffect::GenKey(*this, caps, b);
-}
-
-GrGLSLFragmentProcessor* GrShadowEdgeEffect::onCreateGLSLInstance() const {
- return new GrGLShadowEdgeEffect;
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
bool SkShadowMaskFilterImpl::canFilterMaskGPU(const SkRRect& devRRect,
const SkIRect& clipBounds,
const SkMatrix& ctm,
@@ -309,11 +190,8 @@ bool SkShadowMaskFilterImpl::directFilterMaskGPU(GrTextureProvider* texProvider,
return false;
}
-#define MAX_BLUR_RADIUS 16383.75f
-#define MAX_PAD 64
-
bool SkShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
- GrRenderTargetContext* drawContext,
+ GrRenderTargetContext* renderTargetContext,
GrPaint* grp,
const GrClip& clip,
const SkMatrix& viewMatrix,
@@ -355,10 +233,6 @@ bool SkShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
static const float kGeomFactor = 64.0f;
SkScalar srcSpaceAmbientRadius = fOccluderHeight * kHeightFactor * kGeomFactor;
- // the device-space radius sent to the blur shader must fit in 14.2 fixed point
- if (srcSpaceAmbientRadius*scaleFactor > MAX_BLUR_RADIUS) {
- srcSpaceAmbientRadius = MAX_BLUR_RADIUS / scaleFactor;
- }
const float umbraAlpha = 1.0f / (1.0f + SkTMax(fOccluderHeight * kHeightFactor, 0.0f));
const SkScalar ambientOffset = srcSpaceAmbientRadius * umbraAlpha;
@@ -375,44 +249,25 @@ bool SkShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
rrect.outset(ambientPathOutset, ambientPathOutset, &ambientRRect);
}
- // we outset the stroke a little to cover up AA on the interior edge
- float pad = 0.5f;
- // handle scale of radius and pad due to CTM
- pad *= scaleFactor;
const SkScalar devSpaceAmbientRadius = srcSpaceAmbientRadius * scaleFactor;
- SkASSERT(devSpaceAmbientRadius <= MAX_BLUR_RADIUS);
- SkASSERT(pad < MAX_PAD);
- // convert devSpaceAmbientRadius to 14.2 fixed point and place in the R & G components
- // convert pad to 6.2 fixed point and place in the B component
- // TODO: replace this with separate vertex attributes passed by a new GeoProc.
- // For now we can't easily pass attributes to the fragment shader, so we're overriding
- // the paint color.
- uint16_t iDevSpaceAmbientRadius = (uint16_t)(4.0f * devSpaceAmbientRadius);
GrPaint newPaint(*grp);
newPaint.setAntiAlias(true);
+ GrColor4f color = newPaint.getColor4f();
+ color.fRGBA[3] *= fAmbientAlpha;
+ newPaint.setColor4f(color);
SkStrokeRec ambientStrokeRec(SkStrokeRec::kHairline_InitStyle);
- ambientStrokeRec.setStrokeStyle(srcSpaceAmbientRadius + 2.0f * pad, false);
- newPaint.setColor4f(GrColor4f((iDevSpaceAmbientRadius >> 8)/255.f,
- (iDevSpaceAmbientRadius & 0xff)/255.f,
- 4.0f * pad/255.f,
- fAmbientAlpha));
-
- sk_sp<GrFragmentProcessor> fp(GrShadowEdgeEffect::Make(GrShadowEdgeEffect::kGaussian_Type));
- // TODO: switch to coverage FP
- newPaint.addColorFragmentProcessor(std::move(fp));
- drawContext->drawRRect(clip, newPaint, viewMatrix, ambientRRect,
- GrStyle(ambientStrokeRec, nullptr));
+ ambientStrokeRec.setStrokeStyle(srcSpaceAmbientRadius, false);
+
+ renderTargetContext->drawShadowRRect(clip, newPaint, viewMatrix, ambientRRect,
+ devSpaceAmbientRadius,
+ GrStyle(ambientStrokeRec, nullptr));
}
if (fSpotAlpha > 0.0f) {
float zRatio = SkTPin(fOccluderHeight / (fLightPos.fZ - fOccluderHeight), 0.0f, 0.95f);
SkScalar srcSpaceSpotRadius = 2.0f * fLightRadius * zRatio;
- // the device-space radius sent to the blur shader must fit in 14.2 fixed point
- if (srcSpaceSpotRadius > MAX_BLUR_RADIUS) {
- srcSpaceSpotRadius = MAX_BLUR_RADIUS;
- }
SkRRect spotRRect;
if (isRect) {
@@ -442,13 +297,11 @@ bool SkShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
// We want to extend the stroked area in so that it meets up with the caster
// geometry. The stroked geometry will, by definition already be inset half the
// stroke width but we also have to account for the scaling.
- // We also add 1/2 to cover up AA on the interior edge.
SkScalar scaleOffset = (scale - 1.0f) * SkTMax(SkTMax(SkTAbs(rrect.rect().fLeft),
SkTAbs(rrect.rect().fRight)),
SkTMax(SkTAbs(rrect.rect().fTop),
SkTAbs(rrect.rect().fBottom)));
- SkScalar insetAmount = spotOffset.length() - (0.5f * srcSpaceSpotRadius) +
- scaleOffset + 0.5f;
+ SkScalar insetAmount = spotOffset.length() - (0.5f * srcSpaceSpotRadius) + scaleOffset;
// Compute area
SkScalar strokeWidth = srcSpaceSpotRadius + insetAmount;
@@ -459,6 +312,10 @@ bool SkShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
GrPaint newPaint(*grp);
newPaint.setAntiAlias(true);
+ GrColor4f color = newPaint.getColor4f();
+ color.fRGBA[3] *= fSpotAlpha;
+ newPaint.setColor4f(color);
+
SkStrokeRec spotStrokeRec(SkStrokeRec::kFill_InitStyle);
// If the area of the stroked geometry is larger than the fill geometry,
// or if the caster is transparent, just fill it.
@@ -478,29 +335,12 @@ bool SkShadowMaskFilterImpl::directFilterRRectMaskGPU(GrContext*,
// handle scale of radius and pad due to CTM
const SkScalar devSpaceSpotRadius = srcSpaceSpotRadius * scaleFactor;
- SkASSERT(devSpaceSpotRadius <= MAX_BLUR_RADIUS);
-
- const SkScalar devSpaceSpotPad = 0;
- SkASSERT(devSpaceSpotPad < MAX_PAD);
-
- // convert devSpaceSpotRadius to 14.2 fixed point and place in the R & G
- // components convert devSpaceSpotPad to 6.2 fixed point and place in the B component
- // TODO: replace this with separate vertex attributes passed by a new GeoProc.
- // For now we can't easily pass attributes to the fragment shader, so we're overriding
- // the paint color.
- uint16_t iDevSpaceSpotRadius = (uint16_t)(4.0f * devSpaceSpotRadius);
- newPaint.setColor4f(GrColor4f((iDevSpaceSpotRadius >> 8) / 255.f,
- (iDevSpaceSpotRadius & 0xff) / 255.f,
- devSpaceSpotPad,
- fSpotAlpha));
- spotShadowRRect.offset(spotOffset.fX, spotOffset.fY);
- sk_sp<GrFragmentProcessor> fp(GrShadowEdgeEffect::Make(GrShadowEdgeEffect::kGaussian_Type));
- // TODO: switch to coverage FP
- newPaint.addColorFragmentProcessor(std::move(fp));
+ spotShadowRRect.offset(spotOffset.fX, spotOffset.fY);
- drawContext->drawRRect(clip, newPaint, viewMatrix, spotShadowRRect,
- GrStyle(spotStrokeRec, nullptr));
+ renderTargetContext->drawShadowRRect(clip, newPaint, viewMatrix, spotShadowRRect,
+ devSpaceSpotRadius,
+ GrStyle(spotStrokeRec, nullptr));
}
return true;