summaryrefslogtreecommitdiffstats
path: root/libs/hwui/Matrix.cpp
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2013-01-15 18:51:42 -0800
committerRomain Guy <romainguy@google.com>2013-01-17 15:39:31 -0800
commit8ce00301a023eecaeb8891ce906f67b513ebb42a (patch)
tree3b14c80a49cbec537aad39aa4bb266cac41102f7 /libs/hwui/Matrix.cpp
parent0f8d155363c361199a9d9aa5dcdbc4088990f893 (diff)
downloadframeworks_base-8ce00301a023eecaeb8891ce906f67b513ebb42a.zip
frameworks_base-8ce00301a023eecaeb8891ce906f67b513ebb42a.tar.gz
frameworks_base-8ce00301a023eecaeb8891ce906f67b513ebb42a.tar.bz2
Implement clipRect with a transform, clipRegion & clipPath
Bug #7146141 When non-rectangular clipping occurs in a layer the render buffer used as the stencil buffer is not cached. If this happens on a View's hardware layer the render buffer will live for as long as the layer is bound to the view. When a stencil buffer is required because of a call to Canvas.saveLayer() it will be allocated on every frame. A future change will address this problem. If "show GPU overdraw" is enabled, non-rectangular clips are not supported anymore and we fall back to rectangular clips instead. This is a limitation imposed by OpenGL ES that cannot be worked around at this time. This change also improves the Matrix4 implementation to easily detect when a rect remains a rect after transform. Change-Id: I0e69fb901792d38bc0c4ca1bf9fdb02d7db415b9
Diffstat (limited to 'libs/hwui/Matrix.cpp')
-rw-r--r--libs/hwui/Matrix.cpp139
1 files changed, 107 insertions, 32 deletions
diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp
index a924362..79fae2b 100644
--- a/libs/hwui/Matrix.cpp
+++ b/libs/hwui/Matrix.cpp
@@ -30,6 +30,16 @@
namespace android {
namespace uirenderer {
+///////////////////////////////////////////////////////////////////////////////
+// Defines
+///////////////////////////////////////////////////////////////////////////////
+
+static const float EPSILON = 0.0000001f;
+
+///////////////////////////////////////////////////////////////////////////////
+// Matrix
+///////////////////////////////////////////////////////////////////////////////
+
void Matrix4::loadIdentity() {
data[kScaleX] = 1.0f;
data[kSkewY] = 0.0f;
@@ -51,44 +61,91 @@ void Matrix4::loadIdentity() {
data[kTranslateZ] = 0.0f;
data[kPerspective2] = 1.0f;
- mIsIdentity = true;
- mSimpleMatrix = true;
+ mType = kTypeIdentity | kTypeRectToRect;
+}
+
+static bool isZero(float f) {
+ return fabs(f) <= EPSILON;
+}
+
+uint32_t Matrix4::getType() const {
+ if (mType & kTypeUnknown) {
+ mType = kTypeIdentity;
+
+ if (data[kPerspective0] != 0.0f || data[kPerspective1] != 0.0f ||
+ data[kPerspective2] != 1.0f) {
+ mType |= kTypePerspective;
+ }
+
+ if (data[kTranslateX] != 0.0f || data[kTranslateY] != 0.0f) {
+ mType |= kTypeTranslate;
+ }
+
+ float m00 = data[kScaleX];
+ float m01 = data[kSkewX];
+ float m10 = data[kSkewY];
+ float m11 = data[kScaleY];
+
+ if (m01 != 0.0f || m10 != 0.0f) {
+ mType |= kTypeAffine;
+ }
+
+ if (m00 != 1.0f || m11 != 1.0f) {
+ mType |= kTypeScale;
+ }
+
+ // The following section determines whether the matrix will preserve
+ // rectangles. For instance, a rectangle transformed by a pure
+ // translation matrix will result in a rectangle. A rectangle
+ // transformed by a 45 degrees rotation matrix is not a rectangle.
+ // If the matrix has a perspective component then we already know
+ // it doesn't preserve rectangles.
+ if (!(mType & kTypePerspective)) {
+ if ((isZero(m00) && isZero(m11) && !isZero(m01) && !isZero(m10)) ||
+ (isZero(m01) && isZero(m10) && !isZero(m00) && !isZero(m11))) {
+ mType |= kTypeRectToRect;
+ }
+ }
+ }
+ return mType;
+}
+
+uint32_t Matrix4::getGeometryType() const {
+ return getType() & sGeometryMask;
+}
+
+bool Matrix4::rectToRect() const {
+ return getType() & kTypeRectToRect;
}
bool Matrix4::changesBounds() const {
- return !(data[0] == 1.0f && data[1] == 0.0f && data[2] == 0.0f && data[4] == 0.0f &&
- data[5] == 1.0f && data[6] == 0.0f && data[8] == 0.0f && data[9] == 0.0f &&
- data[10] == 1.0f);
+ return getType() & (kTypeScale | kTypeAffine | kTypePerspective);
}
bool Matrix4::isPureTranslate() const {
- return mSimpleMatrix && data[kScaleX] == 1.0f && data[kScaleY] == 1.0f;
+ return getGeometryType() == kTypeTranslate;
}
bool Matrix4::isSimple() const {
- return mSimpleMatrix;
+ return getGeometryType() <= (kTypeScale | kTypeTranslate);
}
bool Matrix4::isIdentity() const {
- return mIsIdentity;
+ return getGeometryType() == kTypeIdentity;
}
bool Matrix4::isPerspective() const {
- return data[kPerspective0] != 0.0f || data[kPerspective1] != 0.0f ||
- data[kPerspective2] != 1.0f;
+ return getType() & kTypePerspective;
}
void Matrix4::load(const float* v) {
memcpy(data, v, sizeof(data));
- // TODO: Do something smarter here
- mSimpleMatrix = false;
- mIsIdentity = false;
+ mType = kTypeUnknown;
}
void Matrix4::load(const Matrix4& v) {
memcpy(data, v.data, sizeof(data));
- mSimpleMatrix = v.mSimpleMatrix;
- mIsIdentity = v.mIsIdentity;
+ mType = v.getType();
}
void Matrix4::load(const SkMatrix& v) {
@@ -108,8 +165,14 @@ void Matrix4::load(const SkMatrix& v) {
data[kScaleZ] = 1.0f;
- mSimpleMatrix = (v.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask));
- mIsIdentity = v.isIdentity();
+ // NOTE: The flags are compatible between SkMatrix and this class.
+ // However, SkMatrix::getType() does not return the flag
+ // kRectStaysRect. The return value is masked with 0xF
+ // so we need the extra rectStaysRect() check
+ mType = v.getType();
+ if (v.rectStaysRect()) {
+ mType |= kTypeRectToRect;
+ }
}
void Matrix4::copyTo(SkMatrix& v) const {
@@ -158,8 +221,7 @@ void Matrix4::loadInverse(const Matrix4& v) {
data[kPerspective2] = (v.data[kScaleX] * v.data[kScaleY] -
v.data[kSkewX] * v.data[kSkewY]) * scale;
- mSimpleMatrix = v.mSimpleMatrix;
- mIsIdentity = v.mIsIdentity;
+ mType = kTypeUnknown;
}
void Matrix4::copyTo(float* v) const {
@@ -178,7 +240,7 @@ void Matrix4::multiply(float v) {
for (int i = 0; i < 16; i++) {
data[i] *= v;
}
- mIsIdentity = false;
+ mType = kTypeUnknown;
}
void Matrix4::loadTranslate(float x, float y, float z) {
@@ -188,7 +250,7 @@ void Matrix4::loadTranslate(float x, float y, float z) {
data[kTranslateY] = y;
data[kTranslateZ] = z;
- mIsIdentity = false;
+ mType = kTypeTranslate | kTypeRectToRect;
}
void Matrix4::loadScale(float sx, float sy, float sz) {
@@ -198,7 +260,7 @@ void Matrix4::loadScale(float sx, float sy, float sz) {
data[kScaleY] = sy;
data[kScaleZ] = sz;
- mIsIdentity = false;
+ mType = kTypeScale | kTypeRectToRect;
}
void Matrix4::loadSkew(float sx, float sy) {
@@ -216,8 +278,23 @@ void Matrix4::loadSkew(float sx, float sy) {
data[kPerspective1] = 0.0f;
data[kPerspective2] = 1.0f;
- mSimpleMatrix = false;
- mIsIdentity = false;
+ mType = kTypeUnknown;
+}
+
+void Matrix4::loadRotate(float angle) {
+ angle *= float(M_PI / 180.0f);
+ float c = cosf(angle);
+ float s = sinf(angle);
+
+ loadIdentity();
+
+ data[kScaleX] = c;
+ data[kSkewX] = -s;
+
+ data[kSkewY] = s;
+ data[kScaleY] = c;
+
+ mType = kTypeUnknown;
}
void Matrix4::loadRotate(float angle, float x, float y, float z) {
@@ -257,8 +334,7 @@ void Matrix4::loadRotate(float angle, float x, float y, float z) {
data[6] = yz * nc + xs;
data[kScaleZ] = z * z * nc + c;
- mSimpleMatrix = false;
- mIsIdentity = false;
+ mType = kTypeUnknown;
}
void Matrix4::loadMultiply(const Matrix4& u, const Matrix4& v) {
@@ -282,8 +358,7 @@ void Matrix4::loadMultiply(const Matrix4& u, const Matrix4& v) {
set(i, 3, w);
}
- mSimpleMatrix = u.mSimpleMatrix && v.mSimpleMatrix;
- mIsIdentity = false;
+ mType = kTypeUnknown;
}
void Matrix4::loadOrtho(float left, float right, float bottom, float top, float near, float far) {
@@ -296,13 +371,13 @@ void Matrix4::loadOrtho(float left, float right, float bottom, float top, float
data[kTranslateY] = -(top + bottom) / (top - bottom);
data[kTranslateZ] = -(far + near) / (far - near);
- mIsIdentity = false;
+ mType = kTypeTranslate | kTypeScale | kTypeRectToRect;
}
#define MUL_ADD_STORE(a, b, c) a = (a) * (b) + (c)
void Matrix4::mapPoint(float& x, float& y) const {
- if (mSimpleMatrix) {
+ if (isSimple()) {
MUL_ADD_STORE(x, data[kScaleX], data[kTranslateX]);
MUL_ADD_STORE(y, data[kScaleY], data[kTranslateY]);
return;
@@ -318,7 +393,7 @@ void Matrix4::mapPoint(float& x, float& y) const {
}
void Matrix4::mapRect(Rect& r) const {
- if (mSimpleMatrix) {
+ if (isSimple()) {
MUL_ADD_STORE(r.left, data[kScaleX], data[kTranslateX]);
MUL_ADD_STORE(r.right, data[kScaleX], data[kTranslateX]);
MUL_ADD_STORE(r.top, data[kScaleY], data[kTranslateY]);
@@ -376,7 +451,7 @@ void Matrix4::mapRect(Rect& r) const {
}
void Matrix4::dump() const {
- ALOGD("Matrix4[simple=%d", mSimpleMatrix);
+ ALOGD("Matrix4[simple=%d, type=0x%x", isSimple(), getType());
ALOGD(" %f %f %f %f", data[kScaleX], data[kSkewX], data[8], data[kTranslateX]);
ALOGD(" %f %f %f %f", data[kSkewY], data[kScaleY], data[9], data[kTranslateY]);
ALOGD(" %f %f %f %f", data[2], data[6], data[kScaleZ], data[kTranslateZ]);