diff options
author | Romain Guy <romainguy@google.com> | 2013-01-15 18:51:42 -0800 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2013-01-17 15:39:31 -0800 |
commit | 8ce00301a023eecaeb8891ce906f67b513ebb42a (patch) | |
tree | 3b14c80a49cbec537aad39aa4bb266cac41102f7 /libs/hwui/Matrix.cpp | |
parent | 0f8d155363c361199a9d9aa5dcdbc4088990f893 (diff) | |
download | frameworks_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.cpp | 139 |
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]); |