Merge "Print warnings when backwards timestamps are detected." into jb-mr1-dev
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 3481c6f..9e265ba 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -402,9 +402,11 @@
         Rect mCrop;
 
         // mTransform is the current transform flags for this buffer slot.
+        // (example: NATIVE_WINDOW_TRANSFORM_ROT_90)
         uint32_t mTransform;
 
         // mScalingMode is the current scaling mode for this buffer slot.
+        // (example: NATIVE_WINDOW_SCALING_MODE_FREEZE)
         uint32_t mScalingMode;
 
         // mTimestamp is the current timestamp for this buffer slot. This gets
diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp
index 2eee6f5..8594b84 100644
--- a/libs/gui/BufferQueue.cpp
+++ b/libs/gui/BufferQueue.cpp
@@ -150,6 +150,7 @@
 }
 
 status_t BufferQueue::setTransformHint(uint32_t hint) {
+    ST_LOGV("setTransformHint: %02x", hint);
     Mutex::Autolock lock(mMutex);
     mTransformHint = hint;
     return OK;
@@ -737,9 +738,10 @@
 
     snprintf(buffer, SIZE,
             "%s-BufferQueue maxBufferCount=%d, mSynchronousMode=%d, default-size=[%dx%d], "
-            "default-format=%d, FIFO(%d)={%s}\n",
+            "default-format=%d, transform-hint=%02x, FIFO(%d)={%s}\n",
             prefix, maxBufferCount, mSynchronousMode, mDefaultWidth,
-            mDefaultHeight, mDefaultBufferFormat, fifoSize, fifo.string());
+            mDefaultHeight, mDefaultBufferFormat, mTransformHint,
+            fifoSize, fifo.string());
     result.append(buffer);
 
 
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 212c6a7..d9b40cf 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -1414,6 +1414,59 @@
     EGLContext mProducerEglContext;
 };
 
+TEST_F(SurfaceTextureGLToGLTest, TransformHintGetsRespected) {
+    const uint32_t texWidth = 32;
+    const uint32_t texHeight = 64;
+
+    mST->setDefaultBufferSize(texWidth, texHeight);
+    mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
+
+    // This test requires 3 buffers to avoid deadlock because we're
+    // both producer and consumer, and only using one thread.
+    mST->setDefaultMaxBufferCount(3);
+
+    // Do the producer side of things
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+            mProducerEglSurface, mProducerEglContext));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    // Start a buffer with our chosen size and transform hint moving
+    // through the system.
+    glClear(GL_COLOR_BUFFER_BIT);  // give the driver something to do
+    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
+    mST->updateTexImage();  // consume it
+    // Swap again.
+    glClear(GL_COLOR_BUFFER_BIT);
+    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
+    mST->updateTexImage();
+
+    // The current buffer should either show the effects of the transform
+    // hint (in the form of an inverse transform), or show that the
+    // transform hint has been ignored.
+    sp<GraphicBuffer> buf = mST->getCurrentBuffer();
+    if (mST->getCurrentTransform() == NATIVE_WINDOW_TRANSFORM_ROT_270) {
+        ASSERT_EQ(texWidth, buf->getHeight());
+        ASSERT_EQ(texHeight, buf->getWidth());
+    } else {
+        ASSERT_EQ(texWidth, buf->getWidth());
+        ASSERT_EQ(texHeight, buf->getHeight());
+    }
+
+    // Reset the transform hint and confirm that it takes.
+    mST->setTransformHint(0);
+    glClear(GL_COLOR_BUFFER_BIT);
+    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
+    mST->updateTexImage();
+    glClear(GL_COLOR_BUFFER_BIT);
+    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
+    mST->updateTexImage();
+
+    buf = mST->getCurrentBuffer();
+    ASSERT_EQ((uint32_t) 0, mST->getCurrentTransform());
+    ASSERT_EQ(texWidth, buf->getWidth());
+    ASSERT_EQ(texHeight, buf->getHeight());
+}
+
 TEST_F(SurfaceTextureGLToGLTest, TexturingFromGLFilledRGBABufferPow2) {
     const int texWidth = 64;
     const int texHeight = 64;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 6a9cb3e..2c06a0b 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -309,7 +309,7 @@
 void DisplayDevice::updateGeometryTransform() {
     int w = mDisplayWidth;
     int h = mDisplayHeight;
-    Transform T, R, S;
+    Transform TL, TP, R, S;
     if (DisplayDevice::orientationToTransfrom(
             mOrientation, w, h, &R) == NO_ERROR) {
         dirtyRegion.set(bounds());
@@ -350,13 +350,12 @@
         float src_y = viewport.top;
         float dst_x = frame.left;
         float dst_y = frame.top;
-        float tx = dst_x - src_x;
-        float ty = dst_y - src_y;
-        T.set(tx, ty);
+        TL.set(-src_x, -src_y);
+        TP.set(dst_x, dst_y);
 
-        // The viewport and frame are both in the logical orientation, so the
-        // translation is also in that space. So translation must be applied
-        // before rotating from logical to physical orientation.
-        mGlobalTransform = S * R * T;
+        // The viewport and frame are both in the logical orientation.
+        // Apply the logical translation, scale to physical size, apply the
+        // physical translation and finally rotate to the physical orientation.
+        mGlobalTransform = R * TP * S * TL;
     }
 }
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 75eff9f..6785ba8 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -109,6 +109,8 @@
 #else
     mSurfaceTexture->setDefaultMaxBufferCount(3);
 #endif
+
+    updateTransformHint();
 }
 
 Layer::~Layer()
@@ -429,12 +431,12 @@
     if (sizeChanged) {
         // the size changed, we need to ask our client to request a new buffer
         ALOGD_IF(DEBUG_RESIZE,
-                "doTransaction: geometry (layer=%p), scalingMode=%d\n"
+                "doTransaction: geometry (layer=%p '%s'), tr=%02x, scalingMode=%d\n"
                 "  current={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
                 "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n"
                 "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
                 "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
-                this, mCurrentScalingMode,
+                this, (const char*) getName(), mCurrentTransform, mCurrentScalingMode,
                 temp.active.w, temp.active.h,
                 temp.active.crop.left,
                 temp.active.crop.top,
@@ -597,10 +599,10 @@
                     }
 
                     ALOGD_IF(DEBUG_RESIZE,
-                            "lockPageFlip: (layer=%p), buffer (%ux%u, tr=%02x), scalingMode=%d\n"
+                            "latchBuffer/reject: buffer (%ux%u, tr=%02x), scalingMode=%d\n"
                             "  drawing={ active   ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n"
                             "            requested={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }}\n",
-                            this, bufWidth, bufHeight, item.mTransform, item.mScalingMode,
+                            bufWidth, bufHeight, item.mTransform, item.mScalingMode,
                             front.active.w, front.active.h,
                             front.active.crop.left,
                             front.active.crop.top,
@@ -631,10 +633,6 @@
 
         Reject r(mDrawingState, currentState(), recomputeVisibleRegions);
 
-        // XXX: not sure if setTransformHint belongs here
-        // it should only be needed when the main screen orientation changes
-        mSurfaceTexture->setTransformHint(getTransformHint());
-
         if (mSurfaceTexture->updateTexImage(&r) < NO_ERROR) {
             // something happened!
             recomputeVisibleRegions = true;
@@ -711,9 +709,9 @@
     snprintf(buffer, SIZE,
             "      "
             "format=%2d, activeBuffer=[%4ux%4u:%4u,%3X],"
-            " transform-hint=0x%02x, queued-frames=%d, mRefreshPending=%d\n",
+            " queued-frames=%d, mRefreshPending=%d\n",
             mFormat, w0, h0, s0,f0,
-            getTransformHint(), mQueuedFrames, mRefreshPending);
+            mQueuedFrames, mRefreshPending);
 
     result.append(buffer);
 
@@ -759,7 +757,7 @@
     return usage;
 }
 
-uint32_t Layer::getTransformHint() const {
+void Layer::updateTransformHint() const {
     uint32_t orientation = 0;
     if (!mFlinger->mDebugDisableTransformHint) {
         // The transform hint is used to improve performance on the main
@@ -774,7 +772,7 @@
             orientation = 0;
         }
     }
-    return orientation;
+    mSurfaceTexture->setTransformHint(orientation);
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 78fe321..b839f8c 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -89,6 +89,10 @@
     // only for debugging
     inline const sp<GraphicBuffer>& getActiveBuffer() const { return mActiveBuffer; }
 
+    // Updates the transform hint in our SurfaceTexture to match
+    // the current orientation of the default display device.
+    virtual void updateTransformHint() const;
+
 protected:
     virtual void onFirstRef();
     virtual void dump(String8& result, char* scratch, size_t size) const;
@@ -100,7 +104,6 @@
     void onFrameQueued();
     virtual sp<ISurface> createSurface();
     uint32_t getEffectiveUsage(uint32_t usage) const;
-    uint32_t getTransformHint() const;
     bool isCropped() const;
     Rect computeBufferCrop() const;
     static bool getOpacityForFormat(uint32_t format);
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 4651517..7326f53 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -229,6 +229,12 @@
      */
     virtual void onPostComposition() { }
 
+    /**
+     * Updates the SurfaceTexture's transform hint, for layers that have
+     * a SurfaceTexture.
+     */
+    virtual void updateTransformHint() const { }
+
     /** always call base class first */
     virtual void dump(String8& result, char* scratch, size_t size) const;
     virtual void shortDump(String8& result, char* scratch, size_t size) const;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 6542acd..f1d790d 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -988,6 +988,18 @@
                             disp->setProjection(state.orientation,
                                     state.viewport, state.frame);
                         }
+
+                        // Walk through all the layers in currentLayers,
+                        // and update their transform hint.
+                        //
+                        // TODO: we could be much more clever about which
+                        // layers we touch and how often we do these updates
+                        // (e.g. only touch the layers associated with this
+                        // display, and only on a rotation).
+                        for (size_t i = 0; i < count; i++) {
+                            const sp<LayerBase>& layerBase = currentLayers[i];
+                            layerBase->updateTransformHint();
+                        }
                     }
                 }
             }
@@ -1976,7 +1988,8 @@
         snprintf(buffer, SIZE,
                 "+ DisplayDevice[%u]\n"
                 "   type=%x, layerStack=%u, (%4dx%4d), orient=%2d (type=%08x), "
-                "flips=%u, secure=%d, numLayers=%u, v:[%d,%d,%d,%d], f:[%d,%d,%d,%d]\n",
+                "flips=%u, secure=%d, numLayers=%u, v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], "
+                "transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
                 dpy,
                 hw->getDisplayType(), hw->getLayerStack(),
                 hw->getWidth(), hw->getHeight(),
@@ -1985,7 +1998,10 @@
                 hw->getSecureLayerVisible(),
                 hw->getVisibleLayersSortedByZ().size(),
                 hw->getViewport().left, hw->getViewport().top, hw->getViewport().right, hw->getViewport().bottom,
-                hw->getFrame().left, hw->getFrame().top, hw->getFrame().right, hw->getFrame().bottom);
+                hw->getFrame().left, hw->getFrame().top, hw->getFrame().right, hw->getFrame().bottom,
+                hw->getTransform()[0][0], hw->getTransform()[1][0], hw->getTransform()[2][0],
+                hw->getTransform()[0][1], hw->getTransform()[1][1], hw->getTransform()[2][1],
+                hw->getTransform()[0][2], hw->getTransform()[1][2], hw->getTransform()[2][2]);
 
         result.append(buffer);
     }