aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar robertphillips <robertphillips@google.com>2016-08-10 16:25:25 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-08-10 16:25:25 -0700
commit27cdd947903a4262bb483e7d35153358f4541bf8 (patch)
tree15649ca5e140b28b7dcc4831450142062b000639
parent2ab9057b31ee92060b9769ea1adfada51c11c010 (diff)
Implement GPU occluded blur mask filter
Spawned off: https://codereview.chromium.org/2214163003/ (Minor clean up related to blur mask filters) GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2201133002 Review-Url: https://codereview.chromium.org/2201133002
-rw-r--r--bench/BlurOccludedRRectBench.cpp10
-rw-r--r--gm/occludedrrectblur.cpp2
-rw-r--r--include/core/SkMaskFilter.h3
-rw-r--r--include/core/SkPicture.h3
-rw-r--r--include/effects/SkBlurMaskFilter.h16
-rw-r--r--src/core/SkMaskFilter.cpp3
-rw-r--r--src/core/SkReadBuffer.h1
-rw-r--r--src/effects/SkBlurMaskFilter.cpp88
-rw-r--r--src/gpu/SkGpuDevice.cpp1
-rw-r--r--src/gpu/SkGpuDevice_drawTexture.cpp1
10 files changed, 96 insertions, 32 deletions
diff --git a/bench/BlurOccludedRRectBench.cpp b/bench/BlurOccludedRRectBench.cpp
index a2e8276776..a3c9e193ac 100644
--- a/bench/BlurOccludedRRectBench.cpp
+++ b/bench/BlurOccludedRRectBench.cpp
@@ -35,7 +35,7 @@ public:
const SkRect r = SkRect::MakeWH(480, 230);
const SkRRect rr = SkRRect::MakeRectXY(r, 8, 8);
- //SkRect occRect = sk_tool_utils::compute_central_occluder(rr);
+ SkRect occRect = sk_tool_utils::compute_central_occluder(rr);
for (int i = 0; i < 2; ++i) {
canvas->save();
@@ -51,8 +51,8 @@ public:
firstBlur.setAntiAlias(true);
firstBlur.setColor(0x09000000);
firstBlur.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
- 2.5f));
- //, occRect));
+ 2.5f,
+ occRect));
canvas->drawRRect(rr, firstBlur);
@@ -63,8 +63,8 @@ public:
secondBlur.setAntiAlias(true);
secondBlur.setColor(0x30000000);
secondBlur.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle,
- 6.0f));
- //, occRect));
+ 6.0f,
+ occRect));
canvas->drawRRect(rr, secondBlur);
diff --git a/gm/occludedrrectblur.cpp b/gm/occludedrrectblur.cpp
index 937b1790cd..e21a0141d6 100644
--- a/gm/occludedrrectblur.cpp
+++ b/gm/occludedrrectblur.cpp
@@ -46,7 +46,7 @@ static void draw_rrect(SkCanvas* canvas, const SkRRect& rr, const SkRRect& occRR
// draw the blur
SkPaint paint;
- paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, kBlurSigma)); //, occRect));
+ paint.setMaskFilter(SkBlurMaskFilter::Make(kNormal_SkBlurStyle, kBlurSigma, occRect));
canvas->drawRRect(rr, paint);
// draw the stroked geometry of the full occluder
diff --git a/include/core/SkMaskFilter.h b/include/core/SkMaskFilter.h
index e30fc62548..95a663d56d 100644
--- a/include/core/SkMaskFilter.h
+++ b/include/core/SkMaskFilter.h
@@ -129,7 +129,8 @@ public:
const GrClip&,
const SkMatrix& viewMatrix,
const SkStrokeRec& strokeRec,
- const SkRRect& rrect) const;
+ const SkRRect& rrect,
+ const SkRRect& devRRect) const;
/**
* This function is used to implement filters that require an explicit src mask. It should only
diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h
index 75fe66d2bf..885eb59c9b 100644
--- a/include/core/SkPicture.h
+++ b/include/core/SkPicture.h
@@ -207,10 +207,11 @@ private:
// V44: Move annotations from paint to drawAnnotation
// V45: Add invNormRotation to SkLightingShader.
// V46: Add drawTextRSXform
+ // V47: Add occluder rect to SkBlurMaskFilter
// Only SKPs within the min/current picture version range (inclusive) can be read.
static const uint32_t MIN_PICTURE_VERSION = 35; // Produced by Chrome M39.
- static const uint32_t CURRENT_PICTURE_VERSION = 46;
+ static const uint32_t CURRENT_PICTURE_VERSION = 47;
static_assert(MIN_PICTURE_VERSION <= 41,
"Remove kFontFileName and related code from SkFontDescriptor.cpp.");
diff --git a/include/effects/SkBlurMaskFilter.h b/include/effects/SkBlurMaskFilter.h
index 4b037e70cd..12eec6052f 100644
--- a/include/effects/SkBlurMaskFilter.h
+++ b/include/effects/SkBlurMaskFilter.h
@@ -32,13 +32,21 @@ public:
};
/** Create a blur maskfilter.
- * @param style The SkBlurStyle to use
- * @param sigma Standard deviation of the Gaussian blur to apply. Must be > 0.
- * @param flags Flags to use - defaults to none
+ * @param style The SkBlurStyle to use
+ * @param sigma Standard deviation of the Gaussian blur to apply. Must be > 0.
+ * @param occluder The rect for which no pixels need be drawn (b.c. it will be overdrawn
+ * with some opaque object. This is just a hint which backends are free to
+ * ignore.
+ * @param flags Flags to use - defaults to none
* @return The new blur maskfilter
*/
static sk_sp<SkMaskFilter> Make(SkBlurStyle style, SkScalar sigma,
- uint32_t flags = kNone_BlurFlag);
+ const SkRect& occluder, uint32_t flags = kNone_BlurFlag);
+
+ static sk_sp<SkMaskFilter> Make(SkBlurStyle style, SkScalar sigma,
+ uint32_t flags = kNone_BlurFlag) {
+ return Make(style, sigma, SkRect::MakeEmpty(), flags);
+ }
/** Create an emboss maskfilter
@param blurSigma standard deviation of the Gaussian blur to apply
diff --git a/src/core/SkMaskFilter.cpp b/src/core/SkMaskFilter.cpp
index 352cf71db9..62cfcf9646 100644
--- a/src/core/SkMaskFilter.cpp
+++ b/src/core/SkMaskFilter.cpp
@@ -330,7 +330,8 @@ bool SkMaskFilter::directFilterRRectMaskGPU(GrContext*,
const GrClip&,
const SkMatrix& viewMatrix,
const SkStrokeRec& strokeRec,
- const SkRRect& rrect) const {
+ const SkRRect& rrect,
+ const SkRRect& devRRect) const {
return false;
}
diff --git a/src/core/SkReadBuffer.h b/src/core/SkReadBuffer.h
index c853c00036..110b2a582c 100644
--- a/src/core/SkReadBuffer.h
+++ b/src/core/SkReadBuffer.h
@@ -66,6 +66,7 @@ public:
kHasDrawImageOpCodes_Version = 43,
kAnnotationsMovedToCanvas_Version = 44,
kLightingShaderWritesInvNormRotation = 45,
+ kBlurMaskFilterWritesOccluder = 47,
};
/**
diff --git a/src/effects/SkBlurMaskFilter.cpp b/src/effects/SkBlurMaskFilter.cpp
index f66cb9c8db..e0358bfb1b 100644
--- a/src/effects/SkBlurMaskFilter.cpp
+++ b/src/effects/SkBlurMaskFilter.cpp
@@ -37,7 +37,7 @@ SkScalar SkBlurMaskFilter::ConvertRadiusToSigma(SkScalar radius) {
class SkBlurMaskFilterImpl : public SkMaskFilter {
public:
- SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle, uint32_t flags);
+ SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle, const SkRect& occluder, uint32_t flags);
// overrides from SkMaskFilter
SkMask::Format getFormat() const override;
@@ -62,7 +62,8 @@ public:
const GrClip&,
const SkMatrix& viewMatrix,
const SkStrokeRec& strokeRec,
- const SkRRect& rrect) const override;
+ const SkRRect& rrect,
+ const SkRRect& devRRect) const override;
bool filterMaskGPU(GrTexture* src,
const SkMatrix& ctm,
const SkIRect& maskRect,
@@ -101,6 +102,7 @@ private:
SkScalar fSigma;
SkBlurStyle fBlurStyle;
+ SkRect fOccluder;
uint32_t fBlurFlags;
SkBlurQuality getQuality() const {
@@ -123,7 +125,8 @@ private:
const SkScalar SkBlurMaskFilterImpl::kMAX_BLUR_SIGMA = SkIntToScalar(128);
-sk_sp<SkMaskFilter> SkBlurMaskFilter::Make(SkBlurStyle style, SkScalar sigma, uint32_t flags) {
+sk_sp<SkMaskFilter> SkBlurMaskFilter::Make(SkBlurStyle style, SkScalar sigma,
+ const SkRect& occluder, uint32_t flags) {
if (!SkScalarIsFinite(sigma) || sigma <= 0) {
return nullptr;
}
@@ -133,7 +136,7 @@ sk_sp<SkMaskFilter> SkBlurMaskFilter::Make(SkBlurStyle style, SkScalar sigma, ui
SkASSERT(flags <= SkBlurMaskFilter::kAll_BlurFlag);
flags &= SkBlurMaskFilter::kAll_BlurFlag;
- return sk_sp<SkMaskFilter>(new SkBlurMaskFilterImpl(sigma, style, flags));
+ return sk_sp<SkMaskFilter>(new SkBlurMaskFilterImpl(sigma, style, occluder, flags));
}
bool SkBlurMaskFilter::ComputeBlurredRRectParams(const SkRRect& rrect,
@@ -196,9 +199,11 @@ bool SkBlurMaskFilter::ComputeBlurredRRectParams(const SkRRect& rrect,
///////////////////////////////////////////////////////////////////////////////
-SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle style, uint32_t flags)
+SkBlurMaskFilterImpl::SkBlurMaskFilterImpl(SkScalar sigma, SkBlurStyle style,
+ const SkRect& occluder, uint32_t flags)
: fSigma(sigma)
, fBlurStyle(style)
+ , fOccluder(occluder)
, fBlurFlags(flags) {
SkASSERT(fSigma > 0);
SkASSERT((unsigned)style <= kLastEnum_SkBlurStyle);
@@ -645,8 +650,16 @@ sk_sp<SkFlattenable> SkBlurMaskFilterImpl::CreateProc(SkReadBuffer& buffer) {
const SkScalar sigma = buffer.readScalar();
const unsigned style = buffer.readUInt();
const unsigned flags = buffer.readUInt();
+
+ SkRect occluder;
+ if (buffer.isVersionLT(SkReadBuffer::kBlurMaskFilterWritesOccluder)) {
+ occluder.setEmpty();
+ } else {
+ buffer.readRect(&occluder);
+ }
+
if (style <= kLastEnum_SkBlurStyle) {
- return SkBlurMaskFilter::Make((SkBlurStyle)style, sigma, flags);
+ return SkBlurMaskFilter::Make((SkBlurStyle)style, sigma, occluder, flags);
}
return nullptr;
}
@@ -655,6 +668,7 @@ void SkBlurMaskFilterImpl::flatten(SkWriteBuffer& buffer) const {
buffer.writeScalar(fSigma);
buffer.writeUInt(fBlurStyle);
buffer.writeUInt(fBlurFlags);
+ buffer.writeRect(fOccluder);
}
@@ -1222,7 +1236,8 @@ bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context,
const GrClip& clip,
const SkMatrix& viewMatrix,
const SkStrokeRec& strokeRec,
- const SkRRect& rrect) const {
+ const SkRRect& srcRRect,
+ const SkRRect& devRRect) const {
SkASSERT(drawContext);
if (fBlurStyle != kNormal_SkBlurStyle) {
@@ -1235,7 +1250,7 @@ bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context,
SkScalar xformedSigma = this->computeXformedSigma(viewMatrix);
- sk_sp<GrFragmentProcessor> fp(GrRRectBlurEffect::Make(context, xformedSigma, rrect));
+ sk_sp<GrFragmentProcessor> fp(GrRRectBlurEffect::Make(context, xformedSigma, devRRect));
if (!fp) {
return false;
}
@@ -1244,17 +1259,54 @@ bool SkBlurMaskFilterImpl::directFilterRRectMaskGPU(GrContext* context,
newPaint.addCoverageFragmentProcessor(std::move(fp));
newPaint.setAntiAlias(false);
- SkMatrix inverse;
- if (!viewMatrix.invert(&inverse)) {
- return false;
- }
+ if (!this->ignoreXform()) {
+ SkRect srcProxyRect = srcRRect.rect();
+ srcProxyRect.outset(3.0f*fSigma, 3.0f*fSigma);
+
+ SkPoint points[8];
+ uint16_t indices[24];
+ int numPoints, numIndices;
+
+ SkRect temp = fOccluder;
+
+ if (!temp.isEmpty() && (srcProxyRect.contains(temp) || temp.intersect(srcProxyRect))) {
+ srcProxyRect.toQuad(points);
+ temp.toQuad(&points[4]);
+ numPoints = 8;
- float extra=3.f*SkScalarCeilToScalar(xformedSigma-1/6.0f);
+ static const uint16_t ringI[24] = { 0, 1, 5, 5, 4, 0,
+ 1, 2, 6, 6, 5, 1,
+ 2, 3, 7, 7, 6, 2,
+ 3, 0, 4, 4, 7, 3 };
+ memcpy(indices, ringI, sizeof(ringI));
+ numIndices = 24;
+ } else {
+ // full rect case
+ srcProxyRect.toQuad(points);
+ numPoints = 4;
+
+ static const uint16_t fullI[6] = { 0, 1, 2, 0, 2, 3 };
+ memcpy(indices, fullI, sizeof(fullI));
+ numIndices = 6;
+ }
+
+ drawContext->drawVertices(clip, newPaint, viewMatrix, kTriangles_GrPrimitiveType,
+ numPoints, points, nullptr, nullptr, indices, numIndices);
- SkRect proxyRect = rrect.rect();
- proxyRect.outset(extra, extra);
+ } else {
+ SkMatrix inverse;
+ if (!viewMatrix.invert(&inverse)) {
+ return false;
+ }
+
+ float extra=3.f*SkScalarCeilToScalar(xformedSigma-1/6.0f);
+ SkRect proxyRect = devRRect.rect();
+ proxyRect.outset(extra, extra);
+
+
+ drawContext->fillRectWithLocalMatrix(clip, newPaint, SkMatrix::I(), proxyRect, inverse);
+ }
- drawContext->fillRectWithLocalMatrix(clip, newPaint, SkMatrix::I(), proxyRect, inverse);
return true;
}
@@ -1369,9 +1421,7 @@ void SkBlurMaskFilterImpl::toString(SkString* str) const {
str->append("flags: (");
if (fBlurFlags) {
bool needSeparator = false;
- SkAddFlagToString(str,
- SkToBool(fBlurFlags & SkBlurMaskFilter::kIgnoreTransform_BlurFlag),
- "IgnoreXform", &needSeparator);
+ SkAddFlagToString(str, this->ignoreXform(), "IgnoreXform", &needSeparator);
SkAddFlagToString(str,
SkToBool(fBlurFlags & SkBlurMaskFilter::kHighQuality_BlurFlag),
"HighQuality", &needSeparator);
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index fb513f4483..dd68a407c9 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -442,6 +442,7 @@ void SkGpuDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect,
fClip,
*draw.fMatrix,
style.strokeRec(),
+ rrect,
devRRect)) {
return;
}
diff --git a/src/gpu/SkGpuDevice_drawTexture.cpp b/src/gpu/SkGpuDevice_drawTexture.cpp
index e141cc2d62..c387574719 100644
--- a/src/gpu/SkGpuDevice_drawTexture.cpp
+++ b/src/gpu/SkGpuDevice_drawTexture.cpp
@@ -232,6 +232,7 @@ void SkGpuDevice::drawTextureProducerImpl(GrTextureProducer* producer,
clip,
viewMatrix,
rec,
+ SkRRect::MakeRect(clippedSrcRect),
SkRRect::MakeRect(clippedDstRect))) {
return;
}