aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/utils/SkShadowUtils.cpp
diff options
context:
space:
mode:
authorGravatar Mike Reed <reed@google.com>2017-05-17 08:53:36 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-05-17 13:40:42 +0000
commit4204da25aa4c6e0b321314aa32fd9affb4865563 (patch)
tree87ef273357fda474b96cc672d9247b216159b4fb /src/utils/SkShadowUtils.cpp
parent63e7973d1f01bd03216659b9d2267f83a752c8fb (diff)
move shadows to device virtual
This CL keeps the impl for each device backend in the utils file for simplicity (shared helpers). Future CLs may move into their respective impl as they become more specialized. Bug: skia: Change-Id: I97ce6cdcc5106ebf4c84778f943cc32d0b7613c1 Reviewed-on: https://skia-review.googlesource.com/15893 Reviewed-by: Mike Klein <mtklein@chromium.org> Commit-Queue: Mike Reed <reed@google.com>
Diffstat (limited to 'src/utils/SkShadowUtils.cpp')
-rw-r--r--src/utils/SkShadowUtils.cpp181
1 files changed, 104 insertions, 77 deletions
diff --git a/src/utils/SkShadowUtils.cpp b/src/utils/SkShadowUtils.cpp
index 806c98e68b..f0ab230acc 100644
--- a/src/utils/SkShadowUtils.cpp
+++ b/src/utils/SkShadowUtils.cpp
@@ -9,6 +9,8 @@
#include "SkCanvas.h"
#include "SkColorFilter.h"
#include "SkColorPriv.h"
+#include "SkDevice.h"
+#include "SkDrawShadowRec.h"
#include "SkPath.h"
#include "SkPM4f.h"
#include "SkRandom.h"
@@ -20,9 +22,9 @@
#if SK_SUPPORT_GPU
#include "GrShape.h"
#include "effects/GrBlurredEdgeFragmentProcessor.h"
-#endif
#include "../../src/effects/shadows/SkAmbientShadowMaskFilter.h"
#include "../../src/effects/shadows/SkSpotShadowMaskFilter.h"
+#endif
/**
* Gaussian color filter -- produces a Gaussian ramp based on the color's B value,
@@ -444,7 +446,9 @@ static void* kNamespace;
* they are first found in SkResourceCache.
*/
template <typename FACTORY>
-void draw_shadow(const FACTORY& factory, SkCanvas* canvas, ShadowedPath& path, SkColor color) {
+ void draw_shadow(const FACTORY& factory,
+ std::function<void(const SkVertices*, SkBlendMode, const SkPaint&,
+ SkScalar tx, SkScalar ty)> drawProc, ShadowedPath& path, SkColor color) {
FindContext<FACTORY> context(&path.viewMatrix(), &factory);
SkResourceCache::Key* key = nullptr;
@@ -496,82 +500,83 @@ void draw_shadow(const FACTORY& factory, SkCanvas* canvas, ShadowedPath& path, S
paint.setColorFilter(SkColorFilter::MakeComposeFilter(
SkColorFilter::MakeModeFilter(color, SkBlendMode::kModulate),
SkGaussianColorFilter::Make()));
- if (translate->fX || translate->fY) {
- canvas->save();
- canvas->translate(translate->fX, translate->fY);
- }
- canvas->drawVertices(vertices, SkBlendMode::kModulate, paint);
- if (translate->fX || translate->fY) {
- canvas->restore();
- }
+
+ drawProc(vertices.get(), SkBlendMode::kModulate, paint, translate->fX, translate->fY);
}
}
-static bool draw_analytic_shadows(SkCanvas* canvas, const SkPath& path, SkScalar occluderZ,
- const SkPoint3& devLightPos, SkScalar lightRadius,
- SkScalar ambientAlpha, SkScalar spotAlpha, SkColor color,
- uint32_t flags) {
- // only supported in GPU code
- if (!canvas->getGrContext()) {
- return false;
- }
+static bool tilted(const SkPoint3& zPlaneParams) {
+ return !SkScalarNearlyZero(zPlaneParams.fX) || !SkScalarNearlyZero(zPlaneParams.fY);
+}
+
+static SkPoint3 map(const SkMatrix& m, const SkPoint3& pt) {
+ SkPoint3 result;
+ m.mapXY(pt.fX, pt.fY, (SkPoint*)&result.fX);
+ result.fZ = pt.fZ;
+ return result;
+}
+
+#if SK_SUPPORT_GPU
+#include "SkGpuDevice.h"
+void SkGpuDevice::drawShadow(const SkPath& path, const SkDrawShadowRec& rec) {
+ // check z plane
+ bool tiltZPlane = tilted(rec.fZPlaneParams);
+ bool skipAnalytic = SkToBool(rec.fFlags & SkShadowFlags::kGeometricOnly_ShadowFlag);
+
+ const SkMatrix& ctm = this->ctm();
- SkRect rect;
- SkRRect rrect;
- const SkMatrix& ctm = canvas->getTotalMatrix();
- if (ctm.rectStaysRect() && ctm.isSimilarity()) {
+ if (!tiltZPlane && !skipAnalytic && ctm.rectStaysRect() && ctm.isSimilarity()) {
+ SkPoint3 devLightPos = map(ctm, rec.fLightPos);
+
+ const SkScalar occluderZ = rec.fZPlaneParams.fZ;
+ SkPaint ambientPaint, spotPaint;
+ ambientPaint.setColor(rec.fColor);
+ spotPaint.setColor(rec.fColor);
+ if (rec.fAmbientAlpha > 0) {
+ ambientPaint.setMaskFilter(SkAmbientShadowMaskFilter::Make(occluderZ, rec.fAmbientAlpha,
+ rec.fFlags));
+ }
+ if (rec.fSpotAlpha > 0) {
+ spotPaint.setMaskFilter(SkSpotShadowMaskFilter::Make(occluderZ, devLightPos,
+ rec.fLightRadius, rec.fSpotAlpha,
+ rec.fFlags));
+ }
+
+ SkRect rect;
+ SkRRect rrect;
if (path.isRect(&rect)) {
- SkPaint newPaint;
- newPaint.setColor(color);
- if (ambientAlpha > 0) {
- newPaint.setMaskFilter(SkAmbientShadowMaskFilter::Make(occluderZ,
- ambientAlpha, flags));
- canvas->drawRect(rect, newPaint);
+ if (rec.fAmbientAlpha > 0) {
+ this->drawRect(rect, ambientPaint);
}
- if (spotAlpha > 0) {
- newPaint.setMaskFilter(SkSpotShadowMaskFilter::Make(occluderZ, devLightPos,
- lightRadius, spotAlpha,
- flags));
- canvas->drawRect(rect, newPaint);
+ if (rec.fSpotAlpha > 0) {
+ this->drawRect(rect, spotPaint);
}
- return true;
+ return;
} else if (path.isRRect(&rrect) && rrect.isSimpleCircular() &&
rrect.radii(SkRRect::kUpperLeft_Corner).fX > SK_ScalarNearlyZero) {
- SkPaint newPaint;
- newPaint.setColor(color);
- if (ambientAlpha > 0) {
- newPaint.setMaskFilter(SkAmbientShadowMaskFilter::Make(occluderZ,
- ambientAlpha, flags));
- canvas->drawRRect(rrect, newPaint);
+ if (rec.fAmbientAlpha > 0) {
+ this->drawRRect(rrect, ambientPaint);
}
- if (spotAlpha > 0) {
- newPaint.setMaskFilter(SkSpotShadowMaskFilter::Make(occluderZ, devLightPos,
- lightRadius, spotAlpha,
- flags));
- canvas->drawRRect(rrect, newPaint);
+ if (rec.fSpotAlpha > 0) {
+ this->drawRRect(rrect, spotPaint);
}
- return true;
+ return;
} else if (path.isOval(&rect) && SkScalarNearlyEqual(rect.width(), rect.height()) &&
rect.width() > SK_ScalarNearlyZero) {
- SkPaint newPaint;
- newPaint.setColor(color);
- if (ambientAlpha > 0) {
- newPaint.setMaskFilter(SkAmbientShadowMaskFilter::Make(occluderZ,
- ambientAlpha, flags));
- canvas->drawOval(rect, newPaint);
+ if (rec.fAmbientAlpha > 0) {
+ this->drawOval(rect, ambientPaint);
}
- if (spotAlpha > 0) {
- newPaint.setMaskFilter(SkSpotShadowMaskFilter::Make(occluderZ, devLightPos,
- lightRadius, spotAlpha,
- flags));
- canvas->drawOval(rect, newPaint);
+ if (rec.fSpotAlpha > 0) {
+ this->drawOval(rect, spotPaint);
}
- return true;
+ return;
}
}
- return false;
+ // failed to find an accelerated case
+ this->INHERITED::drawShadow(path, rec);
}
+#endif
static SkColor compute_render_color(SkColor color, float alpha) {
return SkColorSetARGB(alpha*SkColorGetA(color), SkColorGetR(color),
@@ -583,26 +588,47 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, const SkPoi
const SkPoint3& devLightPos, SkScalar lightRadius,
SkScalar ambientAlpha, SkScalar spotAlpha, SkColor color,
uint32_t flags) {
- // check z plane
- bool tiltZPlane = !SkScalarNearlyZero(zPlaneParams.fX) || !SkScalarNearlyZero(zPlaneParams.fY);
-
- // try fast paths
- bool skipAnalytic = SkToBool(flags & SkShadowFlags::kGeometricOnly_ShadowFlag) || tiltZPlane;
- if (!skipAnalytic && draw_analytic_shadows(canvas, path, zPlaneParams.fZ, devLightPos,
- lightRadius, ambientAlpha, spotAlpha, color,
- flags)) {
+ SkMatrix inverse;
+ if (!canvas->getTotalMatrix().invert(&inverse)) {
return;
}
+ SkPoint pt = inverse.mapXY(devLightPos.fX, devLightPos.fY);
+
+ SkDrawShadowRec rec;
+ rec.fZPlaneParams = zPlaneParams;
+ rec.fLightPos = { pt.fX, pt.fY, devLightPos.fZ };
+ rec.fLightRadius = lightRadius;
+ rec.fAmbientAlpha = SkScalarToFloat(ambientAlpha);
+ rec.fSpotAlpha = SkScalarToFloat(spotAlpha);
+ rec.fColor = color;
+ rec.fFlags = flags;
+
+ canvas->private_draw_shadow_rec(path, rec);
+}
+
+void SkBaseDevice::drawShadow(const SkPath& path, const SkDrawShadowRec& rec) {
+ auto drawVertsProc = [this](const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint,
+ SkScalar tx, SkScalar ty) {
+ SkAutoDeviceCTMRestore adr(this, SkMatrix::Concat(this->ctm(),
+ SkMatrix::MakeTrans(tx, ty)));
+ this->drawVertices(vertices, mode, paint);
+ };
- SkAutoCanvasRestore acr(canvas, true);
- SkMatrix viewMatrix = canvas->getTotalMatrix();
- canvas->resetMatrix();
+ SkMatrix viewMatrix = this->ctm();
+ SkAutoDeviceCTMRestore adr(this, SkMatrix::I());
ShadowedPath shadowedPath(&path, &viewMatrix);
- bool transparent = SkToBool(flags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
+ bool tiltZPlane = tilted(rec.fZPlaneParams);
+ bool transparent = SkToBool(rec.fFlags & SkShadowFlags::kTransparentOccluder_ShadowFlag);
bool uncached = tiltZPlane || path.isVolatile();
+ SkColor color = rec.fColor;
+ SkPoint3 zPlaneParams = rec.fZPlaneParams;
+ SkPoint3 devLightPos = map(viewMatrix, rec.fLightPos);
+ float lightRadius = rec.fLightRadius;
+
+ float ambientAlpha = rec.fAmbientAlpha;
if (ambientAlpha > 0) {
ambientAlpha = SkTMin(ambientAlpha, 1.f);
if (uncached) {
@@ -614,19 +640,20 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, const SkPoi
// Run the vertex color through a GaussianColorFilter and then modulate the grayscale
// result of that against our 'color' param.
paint.setColorFilter(SkColorFilter::MakeComposeFilter(
- SkColorFilter::MakeModeFilter(renderColor, SkBlendMode::kModulate),
- SkGaussianColorFilter::Make()));
- canvas->drawVertices(vertices, SkBlendMode::kModulate, paint);
+ SkColorFilter::MakeModeFilter(renderColor, SkBlendMode::kModulate),
+ SkGaussianColorFilter::Make()));
+ this->drawVertices(vertices.get(), SkBlendMode::kModulate, paint);
} else {
AmbientVerticesFactory factory;
factory.fOccluderHeight = zPlaneParams.fZ;
factory.fTransparent = transparent;
SkColor renderColor = compute_render_color(color, ambientAlpha);
- draw_shadow(factory, canvas, shadowedPath, renderColor);
+ draw_shadow(factory, drawVertsProc, shadowedPath, renderColor);
}
}
+ float spotAlpha = rec.fSpotAlpha;
if (spotAlpha > 0) {
spotAlpha = SkTMin(spotAlpha, 1.f);
if (uncached) {
@@ -641,7 +668,7 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, const SkPoi
paint.setColorFilter(SkColorFilter::MakeComposeFilter(
SkColorFilter::MakeModeFilter(renderColor, SkBlendMode::kModulate),
SkGaussianColorFilter::Make()));
- canvas->drawVertices(vertices, SkBlendMode::kModulate, paint);
+ this->drawVertices(vertices.get(), SkBlendMode::kModulate, paint);
} else {
SpotVerticesFactory factory;
SkScalar occluderHeight = zPlaneParams.fZ;
@@ -690,7 +717,7 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, const SkPoi
}
#endif
SkColor renderColor = compute_render_color(color, spotAlpha);
- draw_shadow(factory, canvas, shadowedPath, renderColor);
+ draw_shadow(factory, drawVertsProc, shadowedPath, renderColor);
}
}
}