Add SkMatrix::getPerspectiveTypeMaskOnly() and SkMatrix::isTriviallyIdentity().
Reduces profile time in setConcat() and computeTypeMask() for demos that
do a lot of matrix concatenation.
git-svn-id: http://skia.googlecode.com/svn/trunk@2191 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/GrDefaultPathRenderer.cpp b/gpu/src/GrDefaultPathRenderer.cpp
index b8b7f62..79d6e25 100644
--- a/gpu/src/GrDefaultPathRenderer.cpp
+++ b/gpu/src/GrDefaultPathRenderer.cpp
@@ -10,6 +10,7 @@
#include "GrContext.h"
#include "GrPathUtils.h"
+#include "SkString.h"
#include "SkTrace.h"
@@ -372,9 +373,6 @@
void GrDefaultPathRenderer::onDrawPath(GrDrawTarget::StageBitfield stages,
bool stencilOnly) {
- SK_TRACE_EVENT1("GrDefaultPathRenderer::onDrawPath",
- "points", SkStringPrintf("%i", path.countPoints()).c_str());
-
GrMatrix viewM = fTarget->getViewMatrix();
// In order to tesselate the path we get a bound on how much the matrix can
// stretch when mapping to screen coordinates.
@@ -502,8 +500,6 @@
}
{
- SK_TRACE_EVENT1("GrDefaultPathRenderer::onDrawPath::renderPasses",
- "verts", SkStringPrintf("%i", vert - base).c_str());
for (int p = 0; p < passCount; ++p) {
fTarget->setDrawFace(drawFace[p]);
if (NULL != passes[p]) {
diff --git a/include/core/SkMatrix.h b/include/core/SkMatrix.h
index 086aa98..7c2109c 100644
--- a/include/core/SkMatrix.h
+++ b/include/core/SkMatrix.h
@@ -67,10 +67,11 @@
bool preservesAxisAlignment() const { return this->rectStaysRect(); }
/**
- * Returns true if the perspective contains perspective elements.
+ * Returns true if the matrix contains perspective elements.
*/
bool hasPerspective() const {
- return SkToBool(this->getType() & kPerspective_Mask);
+ return SkToBool(this->getPerspectiveTypeMaskOnly() &
+ kPerspective_Mask);
}
enum {
@@ -536,6 +537,11 @@
*/
kRectStaysRect_Mask = 0x10,
+ /** Set if the perspective bit is valid even though the rest of
+ the matrix is Unknown.
+ */
+ kOnlyPerspectiveValid_Mask = 0x40,
+
kUnknown_Mask = 0x80,
kORableMasks = kTranslate_Mask |
@@ -554,10 +560,13 @@
mutable uint8_t fTypeMask;
uint8_t computeTypeMask() const;
+ uint8_t computePerspectiveTypeMask() const;
void setTypeMask(int mask) {
// allow kUnknown or a valid mask
- SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask);
+ SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask ||
+ ((kUnknown_Mask | kOnlyPerspectiveValid_Mask | kPerspective_Mask) & mask)
+ == mask);
fTypeMask = SkToU8(mask);
}
@@ -571,6 +580,24 @@
SkASSERT((mask & kAllMasks) == mask);
fTypeMask &= ~mask;
}
+
+ TypeMask getPerspectiveTypeMaskOnly() const {
+ if ((fTypeMask & kUnknown_Mask) &&
+ !(fTypeMask & kOnlyPerspectiveValid_Mask)) {
+ fTypeMask = this->computePerspectiveTypeMask();
+ }
+ return (TypeMask)(fTypeMask & 0xF);
+ }
+
+ /** Returns true if we already know that the matrix is identity;
+ false otherwise.
+ */
+ bool isTriviallyIdentity() const {
+ if (fTypeMask & kUnknown_Mask) {
+ return false;
+ }
+ return ((fTypeMask & 0xF) == 0);
+ }
static bool Poly2Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
static bool Poly3Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp
index ba8f596..3000533 100644
--- a/src/core/SkMatrix.cpp
+++ b/src/core/SkMatrix.cpp
@@ -56,6 +56,18 @@
static const int32_t kPersp1Int = (1 << 30);
#endif
+uint8_t SkMatrix::computePerspectiveTypeMask() const {
+ unsigned mask = kOnlyPerspectiveValid_Mask | kUnknown_Mask;
+
+ if (SkScalarAs2sCompliment(fMat[kMPersp0]) |
+ SkScalarAs2sCompliment(fMat[kMPersp1]) |
+ (SkScalarAs2sCompliment(fMat[kMPersp2]) - kPersp1Int)) {
+ mask |= kPerspective_Mask;
+ }
+
+ return SkToU8(mask);
+}
+
uint8_t SkMatrix::computeTypeMask() const {
unsigned mask = 0;
@@ -165,7 +177,7 @@
fMat[kMTransY] += SkScalarMul(fMat[kMSkewY], dx) +
SkScalarMul(fMat[kMScaleY], dy);
- this->setTypeMask(kUnknown_Mask);
+ this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
return true;
}
@@ -180,7 +192,7 @@
if (SkScalarToCompareType(dx) || SkScalarToCompareType(dy)) {
fMat[kMTransX] += dx;
fMat[kMTransY] += dy;
- this->setTypeMask(kUnknown_Mask);
+ this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
return true;
}
@@ -324,7 +336,7 @@
fMat[kMPersp0] = fMat[kMPersp1] = 0;
fMat[kMPersp2] = kMatrix22Elem;
- this->setTypeMask(kUnknown_Mask);
+ this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV) {
@@ -339,7 +351,7 @@
fMat[kMPersp0] = fMat[kMPersp1] = 0;
fMat[kMPersp2] = kMatrix22Elem;
- this->setTypeMask(kUnknown_Mask);
+ this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
void SkMatrix::setRotate(SkScalar degrees, SkScalar px, SkScalar py) {
@@ -392,7 +404,7 @@
fMat[kMPersp0] = fMat[kMPersp1] = 0;
fMat[kMPersp2] = kMatrix22Elem;
- this->setTypeMask(kUnknown_Mask);
+ this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
void SkMatrix::setSkew(SkScalar sx, SkScalar sy) {
@@ -407,7 +419,7 @@
fMat[kMPersp0] = fMat[kMPersp1] = 0;
fMat[kMPersp2] = kMatrix22Elem;
- this->setTypeMask(kUnknown_Mask);
+ this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
bool SkMatrix::preSkew(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
@@ -573,12 +585,12 @@
}
bool SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) {
- TypeMask aType = a.getType();
- TypeMask bType = b.getType();
+ TypeMask aType = a.getPerspectiveTypeMaskOnly();
+ TypeMask bType = b.getPerspectiveTypeMaskOnly();
- if (0 == aType) {
+ if (a.isTriviallyIdentity()) {
*this = b;
- } else if (0 == bType) {
+ } else if (b.isTriviallyIdentity()) {
*this = a;
} else {
SkMatrix tmp;
@@ -615,6 +627,7 @@
}
normalize_perspective(tmp.fMat);
+ tmp.setTypeMask(kUnknown_Mask);
} else { // not perspective
if (!fixmuladdmul(a.fMat[kMScaleX], b.fMat[kMScaleX],
a.fMat[kMSkewX], b.fMat[kMSkewY], &tmp.fMat[kMScaleX])) {
@@ -652,10 +665,12 @@
tmp.fMat[kMPersp0] = tmp.fMat[kMPersp1] = 0;
tmp.fMat[kMPersp2] = kMatrix22Elem;
+ //SkDebugf("Concat mat non-persp type: %d\n", tmp.getType());
+ //SkASSERT(!(tmp.getType() & kPerspective_Mask));
+ tmp.setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
*this = tmp;
}
- this->setTypeMask(kUnknown_Mask);
return true;
}
@@ -829,6 +844,7 @@
}
inv->fMat[kMPersp2] = SkFixedToFract(inv->fMat[kMPersp2]);
#endif
+ inv->setTypeMask(kUnknown_Mask);
} else { // not perspective
#ifdef SK_SCALAR_IS_FIXED
Sk64 tx, ty;
@@ -877,6 +893,7 @@
inv->fMat[kMPersp0] = 0;
inv->fMat[kMPersp1] = 0;
inv->fMat[kMPersp2] = kMatrix22Elem;
+ inv->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
if (inv == &tmp) {
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index a8d1942..cf94982 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1480,7 +1480,7 @@
const SkPaint& paint) {
CHECK_SHOULD_DRAW(draw);
- if (draw.fMatrix->getType() & SkMatrix::kPerspective_Mask) {
+ if (draw.fMatrix->hasPerspective()) {
// this guy will just call our drawPath()
draw.drawText((const char*)text, byteLength, x, y, paint);
} else {
@@ -1508,7 +1508,7 @@
const SkPaint& paint) {
CHECK_SHOULD_DRAW(draw);
- if (draw.fMatrix->getType() & SkMatrix::kPerspective_Mask) {
+ if (draw.fMatrix->hasPerspective()) {
// this guy will just call our drawPath()
draw.drawPosText((const char*)text, byteLength, pos, constY,
scalarsPerPos, paint);