Correctly apply transforms when getting a TextureView's bitmap
Bug #5439406

Change-Id: I271a9a2e38f5b3600dc158f8f442a6b0893f472b
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 349b9e3..07995085 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -264,7 +264,7 @@
     layer->setFbo(0);
     layer->setAlpha(255, SkXfermode::kSrcOver_Mode);
     layer->layer.set(0.0f, 0.0f, 0.0f, 0.0f);
-    layer->texCoords.set(0.0f, 1.0f, 0.0f, 1.0f);
+    layer->texCoords.set(0.0f, 1.0f, 1.0f, 0.0f);
     layer->region.clear();
     layer->setRenderTarget(GL_NONE); // see ::updateTextureLayer()
 
@@ -400,6 +400,18 @@
             renderer.setViewport(bitmap->width(), bitmap->height());
             renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f,
                     bitmap->width(), bitmap->height(), !layer->isBlend());
+
+            glDisable(GL_SCISSOR_TEST);
+            renderer.translate(0.0f, bitmap->height());
+            renderer.scale(1.0f, -1.0f);
+
+            mat4 texTransform(layer->getTexTransform());
+
+            mat4 invert;
+            invert.translate(0.0f, 1.0f, 0.0f);
+            invert.scale(1.0f, -1.0f, 1.0f);
+            layer->getTexTransform().multiply(invert);
+
             if ((error = glGetError()) != GL_NO_ERROR) goto error;
 
             {
@@ -413,6 +425,7 @@
                 if ((error = glGetError()) != GL_NO_ERROR) goto error;
             }
 
+            layer->getTexTransform().load(texTransform);
             status = true;
         }
 
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
index 3232eedc..414ae0d 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/GLTextureViewActivity.java
@@ -22,9 +22,11 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.graphics.Matrix;
 import android.graphics.SurfaceTexture;
 import android.opengl.GLUtils;
 import android.os.Bundle;
+import android.os.Environment;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.TextureView;
@@ -39,6 +41,7 @@
 import javax.microedition.khronos.egl.EGLSurface;
 import javax.microedition.khronos.opengles.GL;
 import java.io.BufferedOutputStream;
+import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -65,7 +68,8 @@
                 Bitmap b = mTextureView.getBitmap(800, 800);
                 BufferedOutputStream out = null;
                 try {
-                    out = new BufferedOutputStream(new FileOutputStream("/sdcard/out.png"));
+                    File dump = new File(Environment.getExternalStorageDirectory(), "out.png");
+                    out = new BufferedOutputStream(new FileOutputStream(dump));
                     b.compress(Bitmap.CompressFormat.PNG, 100, out);
                 } catch (FileNotFoundException e) {
                     e.printStackTrace();
@@ -168,10 +172,10 @@
         private static final int TRIANGLE_VERTICES_DATA_UV_OFFSET = 3;
         private final float[] mTriangleVerticesData = {
                 // X, Y, Z, U, V
-                -1.0f, -1.0f, 0, 0.f, 0.f,
-                1.0f, -1.0f, 0, 1.f, 0.f,
-                -1.0f,  1.0f, 0, 0.f, 1.f,
-                1.0f,   1.0f, 0, 1.f, 1.f,
+                -1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
+                 1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
+                -1.0f,  1.0f, 0.0f, 0.0f, 1.0f,
+                 1.0f,  1.0f, 0.0f, 1.0f, 1.0f,
         };
 
         @Override
@@ -212,8 +216,6 @@
             while (!mFinished) {
                 checkCurrent();
 
-                Log.d(LOG_TAG, "Rendering frame");
-
                 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
                 checkGlError();
 
@@ -237,7 +239,7 @@
                 checkEglError();
 
                 try {
-                    Thread.sleep(20);
+                    Thread.sleep(2000);
                 } catch (InterruptedException e) {
                     // Ignore
                 }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
index fcb57d9..0f4c668 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
@@ -17,16 +17,23 @@
 package com.android.test.hwui;
 
 import android.app.Activity;
+import android.graphics.Bitmap;
 import android.graphics.Matrix;
 import android.graphics.SurfaceTexture;
 import android.hardware.Camera;
 import android.os.Bundle;
+import android.os.Environment;
 import android.view.Gravity;
+import android.view.Surface;
 import android.view.TextureView;
 import android.view.View;
 import android.widget.Button;
 import android.widget.FrameLayout;
 
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.IOException;
 
 @SuppressWarnings({"UnusedDeclaration"})
@@ -44,6 +51,26 @@
 
         mTextureView = new TextureView(this);
         mTextureView.setSurfaceTextureListener(this);
+        mTextureView.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Bitmap b = mTextureView.getBitmap(800, 800);
+                BufferedOutputStream out = null;
+                try {
+                    File dump = new File(Environment.getExternalStorageDirectory(), "out.png");
+                    out = new BufferedOutputStream(new FileOutputStream(dump));
+                    b.compress(Bitmap.CompressFormat.PNG, 100, out);
+                } catch (FileNotFoundException e) {
+                    e.printStackTrace();
+                } finally {
+                    if (out != null) try {
+                        out.close();
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        });
 
         Button button = new Button(this);
         button.setText("Remove/Add");
@@ -73,6 +100,8 @@
     @Override
     public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
         mCamera = Camera.open();
+        mCamera.setDisplayOrientation(getCameraOrientation());
+
         Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
         mTextureView.setLayoutParams(new FrameLayout.LayoutParams(
                 previewSize.width, previewSize.height, Gravity.CENTER));
@@ -86,6 +115,34 @@
         mCamera.startPreview();
     }
 
+    private int getCameraOrientation() {
+        Camera.CameraInfo info = new Camera.CameraInfo();
+        for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
+            Camera.getCameraInfo(i, info);
+            if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) break;
+        }
+        
+        int rotation = getWindowManager().getDefaultDisplay().getRotation();
+        int degrees = 0;
+
+        switch (rotation) {
+            case Surface.ROTATION_0:
+                degrees = 0;
+                break;
+            case Surface.ROTATION_90:
+                degrees = 90;
+                break;
+            case Surface.ROTATION_180:
+                degrees = 180;
+                break;
+            case Surface.ROTATION_270:
+                degrees = 270;
+                break;
+        }
+
+        return (info.orientation - degrees + 360) % 360;
+    }
+
     @Override
     public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
         // Ignored, the Camera does all the work for us