diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp index 069b85a59..64eed4b55 100644 --- a/services/surfaceflinger/LayerBase.cpp +++ b/services/surfaceflinger/LayerBase.cpp @@ -415,6 +415,20 @@ void LayerBase::drawWithOpenGL(const Region& clip, const Texture& texture) const cb = (texture.NPOTAdjust ? texture.hScale : 1.0f); } + /* + * For the buffer transformation, we apply the rotation last. + * Since we're transforming the texture-coordinates, we need + * to apply the inverse of the buffer transformation: + * inverse( FLIP_V -> FLIP_H -> ROT_90 ) + * <=> inverse( ROT_90 * FLIP_H * FLIP_V ) + * = inverse(FLIP_V) * inverse(FLIP_H) * inverse(ROT_90) + * = FLIP_V * FLIP_H * ROT_270 + * <=> ROT_270 -> FLIP_H -> FLIP_V + * + * The rotation is performed first, in the texture coordinate space. + * + */ + struct TexCoords { GLfloat u; GLfloat v; diff --git a/services/surfaceflinger/LayerBuffer.cpp b/services/surfaceflinger/LayerBuffer.cpp index ccaad519c..edc00f1d3 100644 --- a/services/surfaceflinger/LayerBuffer.cpp +++ b/services/surfaceflinger/LayerBuffer.cpp @@ -676,8 +676,8 @@ void LayerBuffer::OverlaySource::onVisibilityResolved( overlay_dev->setPosition(overlay_dev, mOverlay, x,y,w,h); // we need to combine the layer orientation and the // user-requested orientation. - Transform finalTransform = Transform(mOrientation) * - Transform(mLayer.getOrientation()); + Transform finalTransform(Transform(mLayer.getOrientation()) * + Transform(mOrientation)); overlay_dev->setParameter(overlay_dev, mOverlay, OVERLAY_TRANSFORM, finalTransform.getOrientation()); overlay_dev->commit(overlay_dev, mOverlay); diff --git a/services/surfaceflinger/Transform.cpp b/services/surfaceflinger/Transform.cpp index f1284295b..0467a1460 100644 --- a/services/surfaceflinger/Transform.cpp +++ b/services/surfaceflinger/Transform.cpp @@ -28,26 +28,40 @@ namespace android { // --------------------------------------------------------------------------- -template inline T min(T a, T b) { +template +static inline T min(T a, T b) { return a inline T min(T a, T b, T c) { +template +static inline T min(T a, T b, T c) { return min(a, min(b, c)); } -template inline T min(T a, T b, T c, T d) { +template +static inline T min(T a, T b, T c, T d) { return min(a, b, min(c, d)); } -template inline T max(T a, T b) { +template +static inline T max(T a, T b) { return a>b ? a : b; } -template inline T max(T a, T b, T c) { +template +static inline T max(T a, T b, T c) { return max(a, max(b, c)); } -template inline T max(T a, T b, T c, T d) { +template +static inline T max(T a, T b, T c, T d) { return max(a, b, max(c, d)); } +template +static inline +void swap(T& a, T& b) { + T t(a); + a = b; + b = t; +} + // --------------------------------------------------------------------------- Transform::Transform() { @@ -160,6 +174,11 @@ status_t Transform::set(uint32_t flags, float w, float h) } Transform H, V, R; + if (flags & ROT_90) { + // w & h are inverted when rotating by 90 degrees + swap(w, h); + } + if (flags & FLIP_H) { H.mType = (FLIP_H << 8) | SCALE; H.mType |= isZero(w) ? IDENTITY : TRANSLATE; @@ -177,14 +196,15 @@ status_t Transform::set(uint32_t flags, float w, float h) } if (flags & ROT_90) { + const float original_w = h; R.mType = (ROT_90 << 8) | ROTATE; - R.mType |= isZero(w) ? IDENTITY : TRANSLATE; + R.mType |= isZero(original_w) ? IDENTITY : TRANSLATE; mat33& M(R.mMatrix); - M[0][0] = 0; M[1][0] =-1; M[2][0] = w; + M[0][0] = 0; M[1][0] =-1; M[2][0] = original_w; M[0][1] = 1; M[1][1] = 0; } - *this = ((H*V)*R); + *this = (R*(H*V)); return NO_ERROR; } @@ -282,8 +302,8 @@ uint32_t Transform::type() const } } else if (isZero(a) && isZero(d)) { flags |= ROT_90; - if (b>0) flags |= FLIP_H; - if (c<0) flags |= FLIP_V; + if (b>0) flags |= FLIP_V; + if (c<0) flags |= FLIP_H; if (!absIsOne(b) || !absIsOne(c)) { scale = true; }