aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2017-12-05 10:35:15 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-12-05 15:56:01 +0000
commit1447177005fcbac83acd501766a46c751a49ae73 (patch)
treeed20f7b0984a3a0f01e0d46465c4fda98bb49802 /src
parentbb4b20a265a78b561c005aaf80920d4bc9c2e7d0 (diff)
Avoid GrEllipseEffect for small radii on devices without 32 bit float.
Also limit small radius bail in GrCircleEffect to clip out cases. Change-Id: I14ce736969b05203219d68f30283c36c84f78f3a Reviewed-on: https://skia-review.googlesource.com/80621 Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrClipStackClip.cpp5
-rw-r--r--src/gpu/GrReducedClip.cpp18
-rw-r--r--src/gpu/GrReducedClip.h3
-rw-r--r--src/gpu/GrRenderTargetContext.cpp5
-rw-r--r--src/gpu/effects/GrCircleEffect.fp2
-rw-r--r--src/gpu/effects/GrCircleEffect.h2
-rw-r--r--src/gpu/effects/GrEllipseEffect.cpp3
-rw-r--r--src/gpu/effects/GrEllipseEffect.fp18
-rw-r--r--src/gpu/effects/GrEllipseEffect.h9
-rw-r--r--src/gpu/effects/GrOvalEffect.cpp6
-rw-r--r--src/gpu/effects/GrOvalEffect.h4
-rw-r--r--src/gpu/effects/GrRRectEffect.cpp9
-rw-r--r--src/gpu/effects/GrRRectEffect.h4
13 files changed, 59 insertions, 29 deletions
diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp
index 684a52d216..bd6ed9afed 100644
--- a/src/gpu/GrClipStackClip.cpp
+++ b/src/gpu/GrClipStackClip.cpp
@@ -201,8 +201,9 @@ bool GrClipStackClip::apply(GrContext* context, GrRenderTargetContext* renderTar
SkASSERT(!context->caps()->avoidStencilBuffers()); // We disable MSAA when avoiding stencil.
}
- GrReducedClip reducedClip(*fStack, devBounds, renderTargetContext->priv().maxWindowRectangles(),
- maxAnalyticFPs);
+ const auto* caps = context->caps()->shaderCaps();
+ GrReducedClip reducedClip(*fStack, devBounds, caps,
+ renderTargetContext->priv().maxWindowRectangles(), maxAnalyticFPs);
if (reducedClip.hasScissor() && !GrClip::IsInsideClip(reducedClip.scissor(), devBounds)) {
out->hardClip().addScissor(reducedClip.scissor(), bounds);
diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp
index 883ed5d956..f481a10b1c 100644
--- a/src/gpu/GrReducedClip.cpp
+++ b/src/gpu/GrReducedClip.cpp
@@ -32,9 +32,8 @@
* take a rect in case the caller knows a bound on what is to be drawn through this clip.
*/
GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds,
- int maxWindowRectangles, int maxAnalyticFPs)
- : fMaxWindowRectangles(maxWindowRectangles)
- , fMaxAnalyticFPs(maxAnalyticFPs) {
+ const GrShaderCaps* caps, int maxWindowRectangles, int maxAnalyticFPs)
+ : fCaps(caps), fMaxWindowRectangles(maxWindowRectangles), fMaxAnalyticFPs(maxAnalyticFPs) {
SkASSERT(!queryBounds.isEmpty());
SkASSERT(fMaxWindowRectangles <= GrWindowRectangles::kMaxWindows);
fHasScissor = false;
@@ -588,7 +587,7 @@ inline GrReducedClip::ClipResult GrReducedClip::addAnalyticFP(const T& deviceSpa
: GrClipEdgeType::kInverseFillBW;
}
- if (auto fp = make_analytic_clip_fp(edgeType, deviceSpaceShape)) {
+ if (auto fp = make_analytic_clip_fp(edgeType, deviceSpaceShape, *fCaps)) {
fAnalyticFPs.push_back(std::move(fp));
return ClipResult::kClipped;
}
@@ -597,17 +596,20 @@ inline GrReducedClip::ClipResult GrReducedClip::addAnalyticFP(const T& deviceSpa
}
std::unique_ptr<GrFragmentProcessor> make_analytic_clip_fp(GrClipEdgeType edgeType,
- const SkRect& deviceSpaceRect) {
+ const SkRect& deviceSpaceRect,
+ const GrShaderCaps&) {
return GrConvexPolyEffect::Make(edgeType, deviceSpaceRect);
}
std::unique_ptr<GrFragmentProcessor> make_analytic_clip_fp(GrClipEdgeType edgeType,
- const SkRRect& deviceSpaceRRect) {
- return GrRRectEffect::Make(edgeType, deviceSpaceRRect);
+ const SkRRect& deviceSpaceRRect,
+ const GrShaderCaps& caps) {
+ return GrRRectEffect::Make(edgeType, deviceSpaceRRect, caps);
}
std::unique_ptr<GrFragmentProcessor> make_analytic_clip_fp(GrClipEdgeType edgeType,
- const SkPath& deviceSpacePath) {
+ const SkPath& deviceSpacePath,
+ const GrShaderCaps&) {
return GrConvexPolyEffect::Make(edgeType, deviceSpacePath);
}
diff --git a/src/gpu/GrReducedClip.h b/src/gpu/GrReducedClip.h
index 22387d7962..0922d9126f 100644
--- a/src/gpu/GrReducedClip.h
+++ b/src/gpu/GrReducedClip.h
@@ -25,7 +25,7 @@ public:
using Element = SkClipStack::Element;
using ElementList = SkTLList<SkClipStack::Element, 16>;
- GrReducedClip(const SkClipStack&, const SkRect& queryBounds,
+ GrReducedClip(const SkClipStack&, const SkRect& queryBounds, const GrShaderCaps* caps,
int maxWindowRectangles = 0, int maxAnalyticFPs = 0);
/**
@@ -117,6 +117,7 @@ private:
void makeEmpty();
+ const GrShaderCaps* fCaps;
const int fMaxWindowRectangles;
const int fMaxAnalyticFPs;
SkIRect fScissor;
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index c9cc3957a4..1f7f6458ae 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -1276,13 +1276,14 @@ bool GrRenderTargetContext::drawFilledDRRect(const GrClip& clip,
inverseVM.reset();
}
+ const auto& caps = *this->caps()->shaderCaps();
// TODO these need to be a geometry processors
- std::unique_ptr<GrFragmentProcessor> innerEffect(GrRRectEffect::Make(innerEdgeType, *inner));
+ auto innerEffect = GrRRectEffect::Make(innerEdgeType, *inner, caps);
if (!innerEffect) {
return false;
}
- std::unique_ptr<GrFragmentProcessor> outerEffect(GrRRectEffect::Make(outerEdgeType, *outer));
+ auto outerEffect = GrRRectEffect::Make(outerEdgeType, *outer, caps);
if (!outerEffect) {
return false;
}
diff --git a/src/gpu/effects/GrCircleEffect.fp b/src/gpu/effects/GrCircleEffect.fp
index 352e824b54..0faf7d74bc 100644
--- a/src/gpu/effects/GrCircleEffect.fp
+++ b/src/gpu/effects/GrCircleEffect.fp
@@ -20,7 +20,7 @@ uniform half4 circle;
float radius) {
// A radius below half causes the implicit insetting done by this processor to become
// inverted. We could handle this case by making the processor code more complicated.
- if (radius < .5f) {
+ if (radius < .5f && GrProcessorEdgeTypeIsInverseFill(edgeType)) {
return nullptr;
}
return std::unique_ptr<GrFragmentProcessor>(new GrCircleEffect(edgeType, center, radius));
diff --git a/src/gpu/effects/GrCircleEffect.h b/src/gpu/effects/GrCircleEffect.h
index d721a78241..cfc5aaf411 100644
--- a/src/gpu/effects/GrCircleEffect.h
+++ b/src/gpu/effects/GrCircleEffect.h
@@ -24,7 +24,7 @@ public:
float radius) {
// A radius below half causes the implicit insetting done by this processor to become
// inverted. We could handle this case by making the processor code more complicated.
- if (radius < .5f) {
+ if (radius < .5f && GrProcessorEdgeTypeIsInverseFill(edgeType)) {
return nullptr;
}
return std::unique_ptr<GrFragmentProcessor>(new GrCircleEffect(edgeType, center, radius));
diff --git a/src/gpu/effects/GrEllipseEffect.cpp b/src/gpu/effects/GrEllipseEffect.cpp
index b41af395d4..88a07f9bed 100644
--- a/src/gpu/effects/GrEllipseEffect.cpp
+++ b/src/gpu/effects/GrEllipseEffect.cpp
@@ -139,7 +139,8 @@ std::unique_ptr<GrFragmentProcessor> GrEllipseEffect::TestCreate(GrProcessorTest
do {
et = (GrClipEdgeType)testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
} while (GrClipEdgeType::kHairlineAA == et);
- return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry));
+ return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry),
+ *testData->caps()->shaderCaps());
}
#endif
#endif
diff --git a/src/gpu/effects/GrEllipseEffect.fp b/src/gpu/effects/GrEllipseEffect.fp
index 27beb85d2f..24cbec2c72 100644
--- a/src/gpu/effects/GrEllipseEffect.fp
+++ b/src/gpu/effects/GrEllipseEffect.fp
@@ -5,6 +5,10 @@
* found in the LICENSE file.
*/
+@header {
+ #include "GrShaderCaps.h"
+}
+
layout(key) in GrClipEdgeType edgeType;
in float2 center;
in float2 radii;
@@ -18,6 +22,17 @@ uniform float4 ellipse;
bool useScale = !sk_Caps.floatIs32Bits;
layout(when=useScale) uniform float2 scale;
+@make {
+ static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, SkPoint center,
+ SkPoint radii, const GrShaderCaps& caps) {
+ // Small radii produce bad results on devices without full float.
+ if (!caps.floatIs32Bits() && (radii.fX < 0.5f || radii.fY < 0.5f)) {
+ return nullptr;
+ }
+ return std::unique_ptr<GrFragmentProcessor>(new GrEllipseEffect(edgeType, center, radii));
+ }
+}
+
@optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag }
@setData(pdman) {
@@ -101,5 +116,6 @@ void main() {
do {
et = (GrClipEdgeType) testData->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
} while (GrClipEdgeType::kHairlineAA == et);
- return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry));
+ return GrEllipseEffect::Make(et, center, SkPoint::Make(rx, ry),
+ *testData->caps()->shaderCaps());
}
diff --git a/src/gpu/effects/GrEllipseEffect.h b/src/gpu/effects/GrEllipseEffect.h
index 8769295ef0..b892f98a56 100644
--- a/src/gpu/effects/GrEllipseEffect.h
+++ b/src/gpu/effects/GrEllipseEffect.h
@@ -12,6 +12,8 @@
#define GrEllipseEffect_DEFINED
#include "SkTypes.h"
#if SK_SUPPORT_GPU
+
+#include "GrShaderCaps.h"
#include "GrFragmentProcessor.h"
#include "GrCoordTransform.h"
class GrEllipseEffect : public GrFragmentProcessor {
@@ -19,8 +21,13 @@ public:
GrClipEdgeType edgeType() const { return fEdgeType; }
SkPoint center() const { return fCenter; }
SkPoint radii() const { return fRadii; }
+
static std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType edgeType, SkPoint center,
- SkPoint radii) {
+ SkPoint radii, const GrShaderCaps& caps) {
+ // Small radii produce bad results on devices without full float.
+ if (!caps.floatIs32Bits() && (radii.fX < 0.5f || radii.fY < 0.5f)) {
+ return nullptr;
+ }
return std::unique_ptr<GrFragmentProcessor>(new GrEllipseEffect(edgeType, center, radii));
}
GrEllipseEffect(const GrEllipseEffect& src);
diff --git a/src/gpu/effects/GrOvalEffect.cpp b/src/gpu/effects/GrOvalEffect.cpp
index 0c0f3bde5c..a475ec02df 100644
--- a/src/gpu/effects/GrOvalEffect.cpp
+++ b/src/gpu/effects/GrOvalEffect.cpp
@@ -11,8 +11,8 @@
#include "GrEllipseEffect.h"
#include "SkRect.h"
-std::unique_ptr<GrFragmentProcessor> GrOvalEffect::Make(GrClipEdgeType edgeType,
- const SkRect& oval) {
+std::unique_ptr<GrFragmentProcessor> GrOvalEffect::Make(GrClipEdgeType edgeType, const SkRect& oval,
+ const GrShaderCaps& caps) {
if (GrClipEdgeType::kHairlineAA == edgeType) {
return nullptr;
}
@@ -26,7 +26,7 @@ std::unique_ptr<GrFragmentProcessor> GrOvalEffect::Make(GrClipEdgeType edgeType,
w /= 2;
h /= 2;
return GrEllipseEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + h),
- SkPoint::Make(w, h));
+ SkPoint::Make(w, h), caps);
}
return nullptr;
diff --git a/src/gpu/effects/GrOvalEffect.h b/src/gpu/effects/GrOvalEffect.h
index f85df89459..c102a0bca2 100644
--- a/src/gpu/effects/GrOvalEffect.h
+++ b/src/gpu/effects/GrOvalEffect.h
@@ -13,6 +13,7 @@
#include "SkRefCnt.h"
class GrFragmentProcessor;
+class GrShaderCaps;
struct SkRect;
namespace GrOvalEffect {
@@ -20,8 +21,7 @@ namespace GrOvalEffect {
/**
* Creates an effect that performs clipping against an oval.
*/
-std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkRect&);
-
+std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkRect&, const GrShaderCaps&);
};
#endif
diff --git a/src/gpu/effects/GrRRectEffect.cpp b/src/gpu/effects/GrRRectEffect.cpp
index 510a26b425..871578f924 100644
--- a/src/gpu/effects/GrRRectEffect.cpp
+++ b/src/gpu/effects/GrRRectEffect.cpp
@@ -122,7 +122,7 @@ std::unique_ptr<GrFragmentProcessor> CircularRRectEffect::TestCreate(GrProcessor
do {
GrClipEdgeType et =
(GrClipEdgeType)d->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
- fp = GrRRectEffect::Make(et, rrect);
+ fp = GrRRectEffect::Make(et, rrect, *d->caps()->shaderCaps());
} while (nullptr == fp);
return fp;
}
@@ -473,7 +473,7 @@ std::unique_ptr<GrFragmentProcessor> EllipticalRRectEffect::TestCreate(GrProcess
std::unique_ptr<GrFragmentProcessor> fp;
do {
GrClipEdgeType et = (GrClipEdgeType)d->fRandom->nextULessThan(kGrClipEdgeTypeCnt);
- fp = GrRRectEffect::Make(et, rrect);
+ fp = GrRRectEffect::Make(et, rrect, *d->caps()->shaderCaps());
} while (nullptr == fp);
return fp;
}
@@ -673,13 +673,14 @@ GrGLSLFragmentProcessor* EllipticalRRectEffect::onCreateGLSLInstance() const {
//////////////////////////////////////////////////////////////////////////////
std::unique_ptr<GrFragmentProcessor> GrRRectEffect::Make(GrClipEdgeType edgeType,
- const SkRRect& rrect) {
+ const SkRRect& rrect,
+ const GrShaderCaps& caps) {
if (rrect.isRect()) {
return GrConvexPolyEffect::Make(edgeType, rrect.getBounds());
}
if (rrect.isOval()) {
- return GrOvalEffect::Make(edgeType, rrect.getBounds());
+ return GrOvalEffect::Make(edgeType, rrect.getBounds(), caps);
}
if (rrect.isSimple()) {
diff --git a/src/gpu/effects/GrRRectEffect.h b/src/gpu/effects/GrRRectEffect.h
index e9c593c53e..55ef5353b4 100644
--- a/src/gpu/effects/GrRRectEffect.h
+++ b/src/gpu/effects/GrRRectEffect.h
@@ -13,6 +13,7 @@
#include "SkRefCnt.h"
class GrFragmentProcessor;
+class GrShaderCaps;
class GrProcessor;
class SkRRect;
@@ -22,8 +23,7 @@ namespace GrRRectEffect {
* Creates an effect that performs anti-aliased clipping against a SkRRect. It doesn't support
* all varieties of SkRRect so the caller must check for a nullptr return.
*/
-std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkRRect&);
-
+std::unique_ptr<GrFragmentProcessor> Make(GrClipEdgeType, const SkRRect&, const GrShaderCaps&);
};
#endif