Merge "Revert "handle surfaces posts independently from composition""
diff --git a/include/gui/SurfaceTextureClient.h b/include/gui/SurfaceTextureClient.h
index 8c1e505..c0e90b3 100644
--- a/include/gui/SurfaceTextureClient.h
+++ b/include/gui/SurfaceTextureClient.h
@@ -73,6 +73,7 @@
     int dispatchSetBufferCount(va_list args);
     int dispatchSetBuffersGeometry(va_list args);
     int dispatchSetBuffersDimensions(va_list args);
+    int dispatchSetBuffersUserDimensions(va_list args);
     int dispatchSetBuffersFormat(va_list args);
     int dispatchSetScalingMode(va_list args);
     int dispatchSetBuffersTransform(va_list args);
@@ -95,6 +96,7 @@
     virtual int disconnect(int api);
     virtual int setBufferCount(int bufferCount);
     virtual int setBuffersDimensions(int w, int h);
+    virtual int setBuffersUserDimensions(int w, int h);
     virtual int setBuffersFormat(int format);
     virtual int setScalingMode(int mode);
     virtual int setBuffersTransform(int transform);
@@ -157,13 +159,23 @@
     // buffer that gets queued. It is set by calling setTransform.
     uint32_t mTransform;
 
-    // mDefaultWidth is default width of the window, regardless of the
-    // native_window_set_buffers_dimensions call
-    uint32_t mDefaultWidth;
+     // mDefaultWidth is default width of the buffers, regardless of the
+     // native_window_set_buffers_dimensions call.
+     uint32_t mDefaultWidth;
 
-    // mDefaultHeight is default width of the window, regardless of the
-    // native_window_set_buffers_dimensions call
-    uint32_t mDefaultHeight;
+     // mDefaultHeight is default height of the buffers, regardless of the
+     // native_window_set_buffers_dimensions call.
+     uint32_t mDefaultHeight;
+
+     // mUserWidth, if non-zero, is an application-specified override
+     // of mDefaultWidth.  This is lower priority than the width set by
+     // native_window_set_buffers_dimensions.
+     uint32_t mUserWidth;
+
+     // mUserHeight, if non-zero, is an application-specified override
+     // of mDefaultHeight.  This is lower priority than the height set
+     // by native_window_set_buffers_dimensions.
+     uint32_t mUserHeight;
 
     // mTransformHint is the transform probably applied to buffers of this
     // window. this is only a hint, actual transform may differ.
diff --git a/libs/gui/SurfaceTextureClient.cpp b/libs/gui/SurfaceTextureClient.cpp
index 592658b..aa114ed 100644
--- a/libs/gui/SurfaceTextureClient.cpp
+++ b/libs/gui/SurfaceTextureClient.cpp
@@ -80,6 +80,8 @@
     mTransform = 0;
     mDefaultWidth = 0;
     mDefaultHeight = 0;
+    mUserWidth = 0;
+    mUserHeight = 0;
     mTransformHint = 0;
     mConnectedToCpu = false;
 }
@@ -159,7 +161,9 @@
     ALOGV("SurfaceTextureClient::dequeueBuffer");
     Mutex::Autolock lock(mMutex);
     int buf = -1;
-    status_t result = mSurfaceTexture->dequeueBuffer(&buf, mReqWidth, mReqHeight,
+    int reqW = mReqWidth ? mReqWidth : mUserWidth;
+    int reqH = mReqHeight ? mReqHeight : mUserHeight;
+    status_t result = mSurfaceTexture->dequeueBuffer(&buf, reqW, reqH,
             mReqFormat, mReqUsage);
     if (result < 0) {
         ALOGV("dequeueBuffer: ISurfaceTexture::dequeueBuffer(%d, %d, %d, %d)"
@@ -269,10 +273,10 @@
                 *value = NATIVE_WINDOW_SURFACE_TEXTURE_CLIENT;
                 return NO_ERROR;
             case NATIVE_WINDOW_DEFAULT_WIDTH:
-                *value = mDefaultWidth;
+                *value = mUserWidth ? mUserWidth : mDefaultWidth;
                 return NO_ERROR;
             case NATIVE_WINDOW_DEFAULT_HEIGHT:
-                *value = mDefaultHeight;
+                *value = mUserHeight ? mUserHeight : mDefaultHeight;
                 return NO_ERROR;
             case NATIVE_WINDOW_TRANSFORM_HINT:
                 *value = mTransformHint;
@@ -313,6 +317,9 @@
     case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS:
         res = dispatchSetBuffersDimensions(args);
         break;
+    case NATIVE_WINDOW_SET_BUFFERS_USER_DIMENSIONS:
+        res = dispatchSetBuffersUserDimensions(args);
+        break;
     case NATIVE_WINDOW_SET_BUFFERS_FORMAT:
         res = dispatchSetBuffersFormat(args);
         break;
@@ -380,6 +387,12 @@
     return setBuffersDimensions(w, h);
 }
 
+int SurfaceTextureClient::dispatchSetBuffersUserDimensions(va_list args) {
+    int w = va_arg(args, int);
+    int h = va_arg(args, int);
+    return setBuffersUserDimensions(w, h);
+}
+
 int SurfaceTextureClient::dispatchSetBuffersFormat(va_list args) {
     int f = va_arg(args, int);
     return setBuffersFormat(f);
@@ -504,6 +517,24 @@
     return NO_ERROR;
 }
 
+int SurfaceTextureClient::setBuffersUserDimensions(int w, int h)
+{
+    ATRACE_CALL();
+    ALOGV("SurfaceTextureClient::setBuffersUserDimensions");
+
+    if (w<0 || h<0)
+        return BAD_VALUE;
+
+    if ((w && !h) || (!w && h))
+        return BAD_VALUE;
+
+    Mutex::Autolock lock(mMutex);
+    mUserWidth = w;
+    mUserHeight = h;
+    mCrop.clear();
+    return NO_ERROR;
+}
+
 int SurfaceTextureClient::setBuffersFormat(int format)
 {
     ALOGV("SurfaceTextureClient::setBuffersFormat");
diff --git a/libs/gui/tests/SurfaceTexture_test.cpp b/libs/gui/tests/SurfaceTexture_test.cpp
index 3009093..ec4f8a4 100644
--- a/libs/gui/tests/SurfaceTexture_test.cpp
+++ b/libs/gui/tests/SurfaceTexture_test.cpp
@@ -409,7 +409,7 @@
 
         // drawTexture draws the SurfaceTexture over the entire GL viewport.
         void drawTexture() {
-            const GLfloat triangleVertices[] = {
+            static const GLfloat triangleVertices[] = {
                 -1.0f, 1.0f,
                 -1.0f, -1.0f,
                 1.0f, -1.0f,
@@ -1476,6 +1476,173 @@
     ASSERT_TRUE(mST->isSynchronousMode());
 }
 
+TEST_F(SurfaceTextureGLToGLTest, TexturingFromUserSizedGLFilledBuffer) {
+    enum { texWidth = 64 };
+    enum { texHeight = 64 };
+
+    // Set the user buffer size.
+    native_window_set_buffers_user_dimensions(mANW.get(), texWidth, texHeight);
+
+    // Do the producer side of things
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+            mProducerEglSurface, mProducerEglContext));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    // This is needed to ensure we pick up a buffer of the correct size.
+    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
+
+    glClearColor(0.6, 0.6, 0.6, 0.6);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glEnable(GL_SCISSOR_TEST);
+    glScissor(4, 4, 1, 1);
+    glClearColor(1.0, 0.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
+
+    // Do the consumer side of things
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+            mEglContext));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    glDisable(GL_SCISSOR_TEST);
+
+    mST->updateTexImage(); // Skip the first frame, which was empty
+    mST->updateTexImage();
+
+    glClearColor(0.2, 0.2, 0.2, 0.2);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glViewport(0, 0, texWidth, texHeight);
+    drawTexture();
+
+    EXPECT_TRUE(checkPixel( 0,  0, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(63,  0, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(63, 63, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel( 0, 63, 153, 153, 153, 153));
+
+    EXPECT_TRUE(checkPixel( 4,  4, 255,   0,   0, 255));
+    EXPECT_TRUE(checkPixel( 5,  5, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel( 3,  3, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(45, 52, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(12, 36, 153, 153, 153, 153));
+}
+
+TEST_F(SurfaceTextureGLToGLTest, TexturingFromPreRotatedUserSizedGLFilledBuffer) {
+    enum { texWidth = 64 };
+    enum { texHeight = 16 };
+
+    // Set the transform hint.
+    mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
+
+    // Set the user buffer size.
+    native_window_set_buffers_user_dimensions(mANW.get(), texWidth, texHeight);
+
+    // Do the producer side of things
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+            mProducerEglSurface, mProducerEglContext));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    // This is needed to ensure we pick up a buffer of the correct size and the
+    // new rotation hint.
+    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
+
+    glClearColor(0.6, 0.6, 0.6, 0.6);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glEnable(GL_SCISSOR_TEST);
+    glScissor(24, 4, 1, 1);
+    glClearColor(1.0, 0.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
+
+    // Do the consumer side of things
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+            mEglContext));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    glDisable(GL_SCISSOR_TEST);
+
+    mST->updateTexImage(); // Skip the first frame, which was empty
+    mST->updateTexImage();
+
+    glClearColor(0.2, 0.2, 0.2, 0.2);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glViewport(0, 0, texWidth, texHeight);
+    drawTexture();
+
+    EXPECT_TRUE(checkPixel( 0,  0, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(63,  0, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(63, 15, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel( 0, 15, 153, 153, 153, 153));
+
+    EXPECT_TRUE(checkPixel(24,  4, 255,   0,   0, 255));
+    EXPECT_TRUE(checkPixel(25,  5, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(23,  3, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(45, 13, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(12,  8, 153, 153, 153, 153));
+}
+
+TEST_F(SurfaceTextureGLToGLTest, TexturingFromPreRotatedGLFilledBuffer) {
+    enum { texWidth = 64 };
+    enum { texHeight = 16 };
+
+    // Set the transform hint.
+    mST->setTransformHint(NATIVE_WINDOW_TRANSFORM_ROT_90);
+
+    // Set the default buffer size.
+    mST->setDefaultBufferSize(texWidth, texHeight);
+
+    // Do the producer side of things
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mProducerEglSurface,
+            mProducerEglSurface, mProducerEglContext));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    // This is needed to ensure we pick up a buffer of the correct size and the
+    // new rotation hint.
+    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
+
+    glClearColor(0.6, 0.6, 0.6, 0.6);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glEnable(GL_SCISSOR_TEST);
+    glScissor(24, 4, 1, 1);
+    glClearColor(1.0, 0.0, 0.0, 1.0);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    eglSwapBuffers(mEglDisplay, mProducerEglSurface);
+
+    // Do the consumer side of things
+    EXPECT_TRUE(eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface,
+            mEglContext));
+    ASSERT_EQ(EGL_SUCCESS, eglGetError());
+
+    glDisable(GL_SCISSOR_TEST);
+
+    mST->updateTexImage(); // Skip the first frame, which was empty
+    mST->updateTexImage();
+
+    glClearColor(0.2, 0.2, 0.2, 0.2);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    glViewport(0, 0, texWidth, texHeight);
+    drawTexture();
+
+    EXPECT_TRUE(checkPixel( 0,  0, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(63,  0, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(63, 15, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel( 0, 15, 153, 153, 153, 153));
+
+    EXPECT_TRUE(checkPixel(24,  4, 255,   0,   0, 255));
+    EXPECT_TRUE(checkPixel(25,  5, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(23,  3, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(45, 13, 153, 153, 153, 153));
+    EXPECT_TRUE(checkPixel(12,  8, 153, 153, 153, 153));
+}
+
 /*
  * This test fixture is for testing GL -> GL texture streaming from one thread
  * to another.  It contains functionality to create a producer thread that will