diff options
-rw-r--r-- | api/current.txt | 2 | ||||
-rw-r--r-- | core/java/android/view/GLES20Canvas.java | 1 | ||||
-rw-r--r-- | core/java/android/view/GLES20RenderLayer.java | 8 | ||||
-rw-r--r-- | core/java/android/view/GLES20TextureLayer.java | 6 | ||||
-rw-r--r-- | core/java/android/view/HardwareLayer.java | 8 | ||||
-rw-r--r-- | core/java/android/view/TextureView.java | 53 | ||||
-rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 7 | ||||
-rw-r--r-- | libs/hwui/Layer.h | 9 | ||||
-rw-r--r-- | libs/hwui/Matrix.cpp | 23 | ||||
-rw-r--r-- | libs/hwui/Matrix.h | 2 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 10 | ||||
-rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java | 4 |
12 files changed, 131 insertions, 2 deletions
diff --git a/api/current.txt b/api/current.txt index c70cea85bfd0..e64e1424ad0d 100644 --- a/api/current.txt +++ b/api/current.txt @@ -22478,12 +22478,14 @@ package android.view { method public android.graphics.Bitmap getBitmap(android.graphics.Bitmap); method public android.graphics.SurfaceTexture getSurfaceTexture(); method public android.view.TextureView.SurfaceTextureListener getSurfaceTextureListener(); + method public android.graphics.Matrix getTransform(android.graphics.Matrix); method public boolean isAvailable(); method public android.graphics.Canvas lockCanvas(); method public android.graphics.Canvas lockCanvas(android.graphics.Rect); method protected final void onDraw(android.graphics.Canvas); method public void setOpaque(boolean); method public void setSurfaceTextureListener(android.view.TextureView.SurfaceTextureListener); + method public void setTransform(android.graphics.Matrix); method public void unlockCanvasAndPost(android.graphics.Canvas); } diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index e586370b4830..cfbb47c30d55 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -151,6 +151,7 @@ class GLES20Canvas extends HardwareCanvas { static native void nResizeLayer(int layerId, int width, int height, int[] layerInfo); static native void nUpdateTextureLayer(int layerId, int width, int height, boolean opaque, SurfaceTexture surface); + static native void nSetTextureLayerTransform(int layerId, int matrix); static native void nDestroyLayer(int layerId); static native void nDestroyLayerDeferred(int layerId); static native boolean nCopyLayer(int layerId, int bitmap); diff --git a/core/java/android/view/GLES20RenderLayer.java b/core/java/android/view/GLES20RenderLayer.java index 41f16e27da8a..23a716621589 100644 --- a/core/java/android/view/GLES20RenderLayer.java +++ b/core/java/android/view/GLES20RenderLayer.java @@ -17,6 +17,7 @@ package android.view; import android.graphics.Canvas; +import android.graphics.Matrix; /** * An OpenGL ES 2.0 implementation of {@link HardwareLayer}. This @@ -87,4 +88,11 @@ class GLES20RenderLayer extends GLES20Layer { } return getCanvas(); } + + /** + * Ignored + */ + @Override + void setTransform(Matrix matrix) { + } } diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java index 391d9f465994..6c41023c98bb 100644 --- a/core/java/android/view/GLES20TextureLayer.java +++ b/core/java/android/view/GLES20TextureLayer.java @@ -17,6 +17,7 @@ package android.view; import android.graphics.Canvas; +import android.graphics.Matrix; import android.graphics.SurfaceTexture; /** @@ -75,4 +76,9 @@ class GLES20TextureLayer extends GLES20Layer { super.update(width, height, isOpaque); GLES20Canvas.nUpdateTextureLayer(mLayer, width, height, isOpaque, mSurface); } + + @Override + void setTransform(Matrix matrix) { + GLES20Canvas.nSetTextureLayerTransform(mLayer, matrix.native_instance); + } } diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java index dfb39ae04543..28389abc3421 100644 --- a/core/java/android/view/HardwareLayer.java +++ b/core/java/android/view/HardwareLayer.java @@ -18,6 +18,7 @@ package android.view; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Matrix; /** * A hardware layer can be used to render graphics operations into a hardware @@ -150,4 +151,11 @@ abstract class HardwareLayer { mHeight = height; mOpaque = isOpaque; } + + /** + * Sets an optional transform on this layer. + * + * @param matrix The transform to apply to the layer. + */ + abstract void setTransform(Matrix matrix); } diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index 53a6bcba98c8..b72222ee9f99 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -19,6 +19,7 @@ package android.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; +import android.graphics.Matrix; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.SurfaceTexture; @@ -104,6 +105,9 @@ public class TextureView extends View { private boolean mOpaque = true; + private final Matrix mMatrix = new Matrix(); + private boolean mMatrixChanged; + private final Object[] mLock = new Object[0]; private boolean mUpdateLayer; @@ -312,6 +316,11 @@ public class TextureView extends View { applyUpdate(); + if (mMatrixChanged) { + mLayer.setTransform(mMatrix); + mMatrixChanged = false; + } + return mLayer; } @@ -358,6 +367,50 @@ public class TextureView extends View { } /** + * <p>Sets the transform to associate with this texture view. + * The specified transform applies to the underlying surface + * texture and does not affect the size or position of the view + * itself, only of its content.</p> + * + * <p>Some transforms might prevent the content from drawing + * all the pixels contained within this view's bounds. In such + * situations, make sure this texture view is not marked opaque.</p> + * + * @param transform The transform to apply to the content of + * this view. + * + * @see #getTransform(android.graphics.Matrix) + * @see #isOpaque() + * @see #setOpaque(boolean) + */ + public void setTransform(Matrix transform) { + mMatrix.set(transform); + mMatrixChanged = true; + invalidate(); + } + + /** + * Returns the transform associated with this texture view. + * + * @param transform The {@link Matrix} in which to copy the current + * transform. Can be null. + * + * @return The specified matrix if not null or a new {@link Matrix} + * instance otherwise. + * + * @see #setTransform(android.graphics.Matrix) + */ + public Matrix getTransform(Matrix transform) { + if (transform == null) { + transform = new Matrix(); + } + + transform.set(mMatrix); + + return transform; + } + + /** * <p>Returns a {@link android.graphics.Bitmap} representation of the content * of the associated surface texture. If the surface texture is not available, * this method returns null.</p> diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 039c5ba32ce1..80c79fd9dbdc 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -683,6 +683,12 @@ static void android_view_GLES20Canvas_updateTextureLayer(JNIEnv* env, jobject cl LayerRenderer::updateTextureLayer(layer, width, height, isOpaque, renderTarget, transform); } +static void android_view_GLES20Canvas_setTextureLayerTransform(JNIEnv* env, jobject clazz, + Layer* layer, SkMatrix* matrix) { + + layer->getTransform().load(*matrix); +} + static void android_view_GLES20Canvas_destroyLayer(JNIEnv* env, jobject clazz, Layer* layer) { LayerRenderer::destroyLayer(layer); } @@ -827,6 +833,7 @@ static JNINativeMethod gMethods[] = { { "nCreateTextureLayer", "(Z[I)I", (void*) android_view_GLES20Canvas_createTextureLayer }, { "nUpdateTextureLayer", "(IIIZLandroid/graphics/SurfaceTexture;)V", (void*) android_view_GLES20Canvas_updateTextureLayer }, + { "nSetTextureLayerTransform", "(II)V", (void*) android_view_GLES20Canvas_setTextureLayerTransform }, { "nDestroyLayer", "(I)V", (void*) android_view_GLES20Canvas_destroyLayer }, { "nDestroyLayerDeferred", "(I)V", (void*) android_view_GLES20Canvas_destroyLayerDeferred }, { "nDrawLayer", "(IIFFI)V", (void*) android_view_GLES20Canvas_drawLayer }, diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index dd75497c19a9..a8ae5c6eebd9 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -203,6 +203,10 @@ struct Layer { return texTransform; } + inline mat4& getTransform() { + return transform; + } + /** * Bounds of the layer. */ @@ -282,6 +286,11 @@ private: */ mat4 texTransform; + /** + * Optional transform. + */ + mat4 transform; + }; // struct Layer }; // namespace uirenderer diff --git a/libs/hwui/Matrix.cpp b/libs/hwui/Matrix.cpp index 9fc5131ee931..769c99cf293a 100644 --- a/libs/hwui/Matrix.cpp +++ b/libs/hwui/Matrix.cpp @@ -51,6 +51,7 @@ void Matrix4::loadIdentity() { data[kTranslateZ] = 0.0f; data[kPerspective2] = 1.0f; + mIsIdentity = true; mSimpleMatrix = true; } @@ -71,14 +72,21 @@ bool Matrix4::isSimple() { return mSimpleMatrix; } +bool Matrix4::isIdentity() { + return mIsIdentity; +} + void Matrix4::load(const float* v) { memcpy(data, v, sizeof(data)); + // TODO: Do something smarter here mSimpleMatrix = false; + mIsIdentity = false; } void Matrix4::load(const Matrix4& v) { memcpy(data, v.data, sizeof(data)); mSimpleMatrix = v.mSimpleMatrix; + mIsIdentity = v.mIsIdentity; } void Matrix4::load(const SkMatrix& v) { @@ -99,6 +107,7 @@ void Matrix4::load(const SkMatrix& v) { data[kScaleZ] = 1.0f; mSimpleMatrix = (v.getType() <= (SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask)); + mIsIdentity = v.isIdentity(); } void Matrix4::copyTo(SkMatrix& v) const { @@ -148,6 +157,7 @@ void Matrix4::loadInverse(const Matrix4& v) { v.data[kSkewX] * v.data[kSkewY]) * scale; mSimpleMatrix = v.mSimpleMatrix; + mIsIdentity = v.mIsIdentity; } void Matrix4::copyTo(float* v) const { @@ -166,20 +176,27 @@ void Matrix4::multiply(float v) { for (int i = 0; i < 16; i++) { data[i] *= v; } + mIsIdentity = false; } void Matrix4::loadTranslate(float x, float y, float z) { loadIdentity(); + data[kTranslateX] = x; data[kTranslateY] = y; data[kTranslateZ] = z; + + mIsIdentity = false; } void Matrix4::loadScale(float sx, float sy, float sz) { loadIdentity(); + data[kScaleX] = sx; data[kScaleY] = sy; data[kScaleZ] = sz; + + mIsIdentity = false; } void Matrix4::loadSkew(float sx, float sy) { @@ -198,6 +215,7 @@ void Matrix4::loadSkew(float sx, float sy) { data[kPerspective2] = 1.0f; mSimpleMatrix = false; + mIsIdentity = false; } void Matrix4::loadRotate(float angle, float x, float y, float z) { @@ -238,6 +256,7 @@ void Matrix4::loadRotate(float angle, float x, float y, float z) { data[kScaleZ] = z * z * nc + c; mSimpleMatrix = false; + mIsIdentity = false; } void Matrix4::loadMultiply(const Matrix4& u, const Matrix4& v) { @@ -262,16 +281,20 @@ void Matrix4::loadMultiply(const Matrix4& u, const Matrix4& v) { } mSimpleMatrix = u.mSimpleMatrix && v.mSimpleMatrix; + mIsIdentity = false; } void Matrix4::loadOrtho(float left, float right, float bottom, float top, float near, float far) { loadIdentity(); + data[kScaleX] = 2.0f / (right - left); data[kScaleY] = 2.0f / (top - bottom); data[kScaleZ] = -2.0f / (far - near); data[kTranslateX] = -(right + left) / (right - left); data[kTranslateY] = -(top + bottom) / (top - bottom); data[kTranslateZ] = -(far + near) / (far - near); + + mIsIdentity = false; } #define MUL_ADD_STORE(a, b, c) a = (a) * (b) + (c) diff --git a/libs/hwui/Matrix.h b/libs/hwui/Matrix.h index 2fa6ab7757a7..56fd37de813b 100644 --- a/libs/hwui/Matrix.h +++ b/libs/hwui/Matrix.h @@ -112,6 +112,7 @@ public: bool isPureTranslate(); bool isSimple(); + bool isIdentity(); bool changesBounds(); @@ -128,6 +129,7 @@ public: private: bool mSimpleMatrix; + bool mIsIdentity; inline float get(int i, int j) const { return data[i * 4 + j]; diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 4864cff6931d..a0f806a209ba 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -627,6 +627,12 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) { float alpha = layer->getAlpha() / 255.0f; + mat4& transform = layer->getTransform(); + if (!transform.isIdentity()) { + save(0); + mSnapshot->transform->multiply(transform); + } + setupDraw(); if (layer->getRenderTarget() == GL_TEXTURE_2D) { setupDrawWithTexture(); @@ -663,6 +669,10 @@ void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) { glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); finishDrawTexture(); + + if (!transform.isIdentity()) { + restore(); + } } void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) { diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java index 97e21089428c..fcb57d96b3f1 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java @@ -17,6 +17,7 @@ package com.android.test.hwui; import android.app.Activity; +import android.graphics.Matrix; import android.graphics.SurfaceTexture; import android.hardware.Camera; import android.os.Bundle; @@ -33,6 +34,7 @@ public class TextureViewActivity extends Activity implements TextureView.Surface private Camera mCamera; private TextureView mTextureView; private FrameLayout mContent; + private Matrix mMatrix = new Matrix(); @Override protected void onCreate(Bundle savedInstanceState) { @@ -82,8 +84,6 @@ public class TextureViewActivity extends Activity implements TextureView.Surface } mCamera.startPreview(); - - mTextureView.setCameraDistance(5000); } @Override |