aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar bsalomon <bsalomon@google.com>2016-05-09 13:02:01 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-05-09 13:02:01 -0700
commit97fd2d42b97104fa32a58d7e7a5b7255913f9c9d (patch)
treef1984297182430bf5b706e6514d21c20b37d4db7 /src/gpu
parent1b4c01c66081cd163535eab21b29a3996b01a6cf (diff)
Incorporate scale into GrStyle and GrShape
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/GrShape.cpp32
-rw-r--r--src/gpu/GrShape.h15
-rw-r--r--src/gpu/GrStyle.cpp26
-rw-r--r--src/gpu/GrStyle.h24
4 files changed, 66 insertions, 31 deletions
diff --git a/src/gpu/GrShape.cpp b/src/gpu/GrShape.cpp
index 84e14e8925..8462d4d41d 100644
--- a/src/gpu/GrShape.cpp
+++ b/src/gpu/GrShape.cpp
@@ -83,7 +83,7 @@ void GrShape::writeUnstyledKey(uint32_t* key) const {
SkASSERT(key - origKey == this->unstyledKeySize());
}
-void GrShape::setInheritedKey(const GrShape &parent, GrStyle::Apply apply) {
+void GrShape::setInheritedKey(const GrShape &parent, GrStyle::Apply apply, SkScalar scale) {
SkASSERT(!fInheritedKey.count());
// If the output shape turns out to be simple, then we will just use its geometric key
if (Type::kPath == fType) {
@@ -124,7 +124,8 @@ void GrShape::setInheritedKey(const GrShape &parent, GrStyle::Apply apply) {
parentCnt * sizeof(uint32_t));
}
// Now turn (geo,path_effect) or (geo) into (geo,path_effect,stroke)
- GrStyle::WriteKey(fInheritedKey.get() + parentCnt, parent.fStyle, apply, styleKeyFlags);
+ GrStyle::WriteKey(fInheritedKey.get() + parentCnt, parent.fStyle, apply, scale,
+ styleKeyFlags);
}
}
@@ -144,7 +145,11 @@ GrShape::GrShape(const GrShape& that) : fType(that.fType), fStyle(that.fStyle) {
sizeof(uint32_t) * fInheritedKey.count());
}
-GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply) {
+GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply, SkScalar scale) {
+ // TODO: Add some quantization of scale for better cache performance here or leave that up
+ // to caller?
+ // TODO: For certain shapes and stroke params we could ignore the scale. (e.g. miter or bevel
+ // stroke of a rect).
if (!parent.style().applies() ||
(GrStyle::Apply::kPathEffectOnly == apply && !parent.style().pathEffect())) {
fType = Type::kEmpty;
@@ -169,6 +174,7 @@ GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply) {
// Should we consider bounds? Would have to include in key, but it'd be nice to know
// if the bounds actually modified anything before including in key.
SkStrokeRec strokeRec = parent.fStyle.strokeRec();
+ strokeRec.setResScale(scale);
if (!pe->filterPath(fPath.get(), *srcForPathEffect, &strokeRec, nullptr)) {
// Make an empty unstyled shape if filtering fails.
fType = Type::kEmpty;
@@ -176,6 +182,9 @@ GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply) {
fPath.reset();
return;
}
+ // A path effect has access to change the res scale but we aren't expecting it to and it
+ // would mess up our key computation.
+ SkASSERT(scale == strokeRec.getResScale());
if (GrStyle::Apply::kPathEffectAndStrokeRec == apply) {
if (strokeRec.needToApply()) {
// The intermediate shape may not be a general path. If we we're just applying
@@ -207,17 +216,20 @@ GrShape::GrShape(const GrShape& parent, GrStyle::Apply apply) {
fStyle = GrStyle(strokeRec, nullptr);
}
} else {
- const SkPath* srcForStrokeRec;
+ const SkPath* srcForParentStyle;
if (parent.fType == Type::kPath) {
- srcForStrokeRec = parent.fPath.get();
+ srcForParentStyle = parent.fPath.get();
} else {
- srcForStrokeRec = tmpPath.init();
+ srcForParentStyle = tmpPath.init();
parent.asPath(tmpPath.get());
}
- SkASSERT(parent.fStyle.strokeRec().needToApply());
- SkAssertResult(parent.fStyle.strokeRec().applyToPath(fPath.get(), *srcForStrokeRec));
- fStyle.resetToInitStyle(SkStrokeRec::kFill_InitStyle);
+ SkStrokeRec::InitStyle fillOrHairline;
+ SkASSERT(parent.fStyle.applies());
+ SkASSERT(!parent.fStyle.pathEffect());
+ SkAssertResult(parent.fStyle.applyToPath(fPath.get(), &fillOrHairline, *srcForParentStyle,
+ scale));
+ fStyle.resetToInitStyle(fillOrHairline);
}
this->attemptToReduceFromPath();
- this->setInheritedKey(*parentForKey, apply);
+ this->setInheritedKey(*parentForKey, apply, scale);
}
diff --git a/src/gpu/GrShape.h b/src/gpu/GrShape.h
index f4bd7e581a..d72b17965c 100644
--- a/src/gpu/GrShape.h
+++ b/src/gpu/GrShape.h
@@ -106,7 +106,14 @@ public:
const GrStyle& style() const { return fStyle; }
- GrShape applyStyle(GrStyle::Apply apply) { return GrShape(*this, apply); }
+ /**
+ * Returns a shape that has either applied the path effect or path effect and stroking
+ * information from this shape's style to its geometry. Scale is used when approximating the
+ * output geometry and typically is computed from the view matrix
+ */
+ GrShape applyStyle(GrStyle::Apply apply, SkScalar scale) {
+ return GrShape(*this, apply, scale);
+ }
bool asRRect(SkRRect* rrect) const {
if (Type::kRRect != fType) {
@@ -170,14 +177,14 @@ private:
};
- /** Constructor used by Apply* functions */
- GrShape(const GrShape& parentShape, GrStyle::Apply);
+ /** Constructor used by the applyStyle() function */
+ GrShape(const GrShape& parentShape, GrStyle::Apply, SkScalar scale);
/**
* Determines the key we should inherit from the input shape's geometry and style when
* we are applying the style to create a new shape.
*/
- void setInheritedKey(const GrShape& parentShape, GrStyle::Apply);
+ void setInheritedKey(const GrShape& parentShape, GrStyle::Apply, SkScalar scale);
void attemptToReduceFromPath() {
SkASSERT(Type::kPath == fType);
diff --git a/src/gpu/GrStyle.cpp b/src/gpu/GrStyle.cpp
index 68238dded9..3698c31ff8 100644
--- a/src/gpu/GrStyle.cpp
+++ b/src/gpu/GrStyle.cpp
@@ -11,8 +11,8 @@ int GrStyle::KeySize(const GrStyle &style, Apply apply, uint32_t flags) {
GR_STATIC_ASSERT(sizeof(uint32_t) == sizeof(SkScalar));
int size = 0;
if (style.isDashed()) {
- // One scalar for dash phase and one for each dash value.
- size += 1 + style.dashIntervalCnt();
+ // One scalar for scale, one for dash phase, and one for each dash value.
+ size += 2 + style.dashIntervalCnt();
} else if (style.pathEffect()) {
// No key for a generic path effect.
return -1;
@@ -23,21 +23,29 @@ int GrStyle::KeySize(const GrStyle &style, Apply apply, uint32_t flags) {
}
if (style.strokeRec().needToApply()) {
- // One for style/cap/join, 2 for miter and width.
- size += 3;
+ // One for res scale, one for style/cap/join, one for miter limit, and one for width.
+ size += 4;
}
return size;
}
-void GrStyle::WriteKey(uint32_t *key, const GrStyle &style, Apply apply, uint32_t flags) {
+void GrStyle::WriteKey(uint32_t *key, const GrStyle &style, Apply apply, SkScalar scale,
+ uint32_t flags) {
SkASSERT(key);
SkASSERT(KeySize(style, apply) >= 0);
GR_STATIC_ASSERT(sizeof(uint32_t) == sizeof(SkScalar));
int i = 0;
+ // The scale can influence both the path effect and stroking. We want to preserve the
+ // property that the following two are equal:
+ // 1. WriteKey with apply == kPathEffectAndStrokeRec
+ // 2. WriteKey with apply == kPathEffectOnly followed by WriteKey of a GrStyle made
+ // from SkStrokeRec output by the the path effect (and no additional path effect).
+ // Since the scale can affect both parts of 2 we write it into the key twice.
if (style.isDashed()) {
GR_STATIC_ASSERT(sizeof(style.dashPhase()) == sizeof(uint32_t));
SkScalar phase = style.dashPhase();
+ memcpy(&key[i++], &scale, sizeof(SkScalar));
memcpy(&key[i++], &phase, sizeof(SkScalar));
int32_t count = style.dashIntervalCnt();
@@ -52,6 +60,7 @@ void GrStyle::WriteKey(uint32_t *key, const GrStyle &style, Apply apply, uint32_
}
if (Apply::kPathEffectAndStrokeRec == apply && style.strokeRec().needToApply()) {
+ memcpy(&key[i++], &scale, sizeof(SkScalar));
enum {
kStyleBits = 2,
kJoinBits = 2,
@@ -123,9 +132,10 @@ static inline bool apply_path_effect(SkPath* dst, SkStrokeRec* strokeRec,
}
bool GrStyle::applyPathEffectToPath(SkPath *dst, SkStrokeRec *remainingStroke,
- const SkPath &src) const {
+ const SkPath &src, SkScalar resScale) const {
SkASSERT(dst);
SkStrokeRec strokeRec = fStrokeRec;
+ strokeRec.setResScale(resScale);
if (!apply_path_effect(dst, &strokeRec, fPathEffect, src)) {
return false;
}
@@ -133,10 +143,12 @@ bool GrStyle::applyPathEffectToPath(SkPath *dst, SkStrokeRec *remainingStroke,
return true;
}
-bool GrStyle::applyToPath(SkPath* dst, SkStrokeRec::InitStyle* style, const SkPath& src) const {
+bool GrStyle::applyToPath(SkPath* dst, SkStrokeRec::InitStyle* style, const SkPath& src,
+ SkScalar resScale) const {
SkASSERT(style);
SkASSERT(dst);
SkStrokeRec strokeRec = fStrokeRec;
+ strokeRec.setResScale(resScale);
const SkPath* pathForStrokeRec = &src;
if (apply_path_effect(dst, &strokeRec, fPathEffect, src)) {
pathForStrokeRec = dst;
diff --git a/src/gpu/GrStyle.h b/src/gpu/GrStyle.h
index 2ca037a463..6166b56fb7 100644
--- a/src/gpu/GrStyle.h
+++ b/src/gpu/GrStyle.h
@@ -60,7 +60,7 @@ public:
* either reflect just the path effect (if one) or the path effect and the strokerec. Note
* that a simple fill has a zero sized key.
*/
- static int KeySize(const GrStyle& , Apply, uint32_t flags = 0);
+ static int KeySize(const GrStyle&, Apply, uint32_t flags = 0);
/**
* Writes a unique key for the style into the provided buffer. This function assumes the buffer
@@ -69,7 +69,7 @@ public:
* for just dash application followed by the key for the remaining SkStrokeRec is the same as
* the key for applying dashing and SkStrokeRec all at once.
*/
- static void WriteKey(uint32_t*, const GrStyle&, Apply, uint32_t flags = 0);
+ static void WriteKey(uint32_t*, const GrStyle&, Apply, SkScalar scale, uint32_t flags = 0);
GrStyle() : GrStyle(SkStrokeRec::kFill_InitStyle) {}
@@ -135,18 +135,22 @@ public:
/**
* Applies just the path effect and returns remaining stroke information. This will fail if
- * there is no path effect. dst may or may not have been overwritten on failure.
+ * there is no path effect. dst may or may not have been overwritten on failure. Scale controls
+ * geometric approximations made by the path effect. It is typically computed from the view
+ * matrix.
*/
bool SK_WARN_UNUSED_RESULT applyPathEffectToPath(SkPath* dst, SkStrokeRec* remainingStoke,
- const SkPath& src) const;
+ const SkPath& src, SkScalar scale) const;
- /** If this succeeds then the result path should be filled or hairlined as indicated by the
- returned SkStrokeRec::InitStyle value. Will fail if there is no path effect and the
- strokerec doesn't change the geometry. When this fails the outputs may or may not have
- been overwritten.
- */
+ /**
+ * If this succeeds then the result path should be filled or hairlined as indicated by the
+ * returned SkStrokeRec::InitStyle value. Will fail if there is no path effect and the
+ * strokerec doesn't change the geometry. When this fails the outputs may or may not have
+ * been overwritten. Scale controls geometric approximations made by the path effect and
+ * stroker. It is typically computed from the view matrix.
+ */
bool SK_WARN_UNUSED_RESULT applyToPath(SkPath* dst, SkStrokeRec::InitStyle* fillOrHairline,
- const SkPath& src) const;
+ const SkPath& src, SkScalar scale) const;
/** Given bounds of a path compute the bounds of path with the style applied. */
void adjustBounds(SkRect* dst, const SkRect& src) const {