OSDN Git Service

TextureView: add setSurfaceTexture method
authorJamie Gennis <jgennis@google.com>
Thu, 5 Apr 2012 18:44:30 +0000 (11:44 -0700)
committerJamie Gennis <jgennis@google.com>
Thu, 5 Apr 2012 23:11:43 +0000 (16:11 -0700)
This change adds support for transferring control of a TextureView's
SurfaceTexture between the UI framework and the application.  It makes the
TextureView detach the SurfaceTexture from the UI framework's GLES context
before calling the surfaceTextureDestroyed callback, allowing the app to use
the SurfaceTexture in its own GLES context if it so chooses.  This change also
adds the TextureView#setSurfaceTexture method, allowing an app have the
TextureView use a SurfaceTexture that already exists rather than creating a new
one.

Change-Id: Iac9cc917687e4239dd1c24eae553709aa37512da

core/java/android/view/GLES20TextureLayer.java
core/java/android/view/HardwareRenderer.java
core/java/android/view/TextureView.java

index cbb908b..16a13cf 100644 (file)
@@ -42,6 +42,12 @@ class GLES20TextureLayer extends GLES20Layer {
         }        
     }
 
+    GLES20TextureLayer(SurfaceTexture surface, boolean isOpaque) {
+        this(isOpaque);
+        mSurface = surface;
+        mSurface.attachToGLContext(mTexture);
+    }
+
     @Override
     boolean isValid() {
         return mLayer != 0 && mTexture != 0;
@@ -72,6 +78,14 @@ class GLES20TextureLayer extends GLES20Layer {
         return mSurface;
     }
 
+    void setSurfaceTexture(SurfaceTexture surfaceTexture) {
+        if (mSurface != null) {
+            mSurface.release();
+        }
+        mSurface = surfaceTexture;
+        mSurface.attachToGLContext(mTexture);
+    }
+
     @Override
     void update(int width, int height, boolean isOpaque) {
         super.update(width, height, isOpaque);
index b8c692a..d1af397 100644 (file)
@@ -391,9 +391,9 @@ public abstract class HardwareRenderer {
      * @param isOpaque Whether the layer should be opaque or not
      * 
      * @return A hardware layer
-     */    
+     */
     abstract HardwareLayer createHardwareLayer(boolean isOpaque);
-    
+
     /**
      * Creates a new hardware layer.
      * 
@@ -417,6 +417,15 @@ public abstract class HardwareRenderer {
     abstract SurfaceTexture createSurfaceTexture(HardwareLayer layer);
 
     /**
+     * Sets the {@link android.graphics.SurfaceTexture} that will be used to
+     * render into the specified hardware layer.
+     *
+     * @param layer The layer to render into using a {@link android.graphics.SurfaceTexture}
+     * @param surfaceTexture The {@link android.graphics.SurfaceTexture} to use for the layer
+     */
+    abstract void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture);
+
+    /**
      * Initializes the hardware renderer for the specified surface and setup the
      * renderer for drawing, if needed. This is invoked when the ViewAncestor has
      * potentially lost the hardware renderer. The hardware renderer should be
@@ -1345,6 +1354,11 @@ public abstract class HardwareRenderer {
         }
 
         @Override
+        void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture) {
+            ((GLES20TextureLayer) layer).setSurfaceTexture(surfaceTexture);
+        }
+
+        @Override
         void destroyLayers(View view) {
             if (view != null && isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) {
                 destroyHardwareLayer(view);
index 83999a1..3cd8b71 100644 (file)
@@ -115,6 +115,7 @@ public class TextureView extends View {
 
     private final Object[] mLock = new Object[0];
     private boolean mUpdateLayer;
+    private boolean mUpdateSurface;
 
     private SurfaceTexture.OnFrameAvailableListener mUpdateListener;
 
@@ -208,6 +209,8 @@ public class TextureView extends View {
 
     private void destroySurface() {
         if (mLayer != null) {
+            mSurface.detachFromGLContext();
+
             boolean shouldRelease = true;
             if (mListener != null) {
                 shouldRelease = mListener.onSurfaceTextureDestroyed(mSurface);
@@ -322,9 +325,13 @@ public class TextureView extends View {
             }
 
             mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(mOpaque);
-            mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer);
+            if (!mUpdateSurface) {
+                // We already have a SurfaceTexture to use, and we will pass it
+                // to mLayer below.
+                mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer);
+            }
             nSetDefaultBufferSize(mSurface, getWidth(), getHeight());
-            nCreateNativeWindow(mSurface);            
+            nCreateNativeWindow(mSurface);
 
             mUpdateListener = new SurfaceTexture.OnFrameAvailableListener() {
                 @Override
@@ -344,6 +351,15 @@ public class TextureView extends View {
             }
         }
 
+        if (mUpdateSurface) {
+            // Someone has requested that we use a specific SurfaceTexture, so
+            // tell mLayer about it and set the SurfaceTexture to use the
+            // current view size.
+            mUpdateSurface = false;
+            mAttachInfo.mHardwareRenderer.setSurfaceTexture(mLayer, mSurface);
+            nSetDefaultBufferSize(mSurface, getWidth(), getHeight());
+        }
+
         applyUpdate();
         applyTransformMatrix();
 
@@ -371,7 +387,7 @@ public class TextureView extends View {
         mUpdateLayer = true;
         invalidate();
     }
-    
+
     private void applyUpdate() {
         if (mLayer == null) {
             return;
@@ -636,6 +652,32 @@ public class TextureView extends View {
     }
 
     /**
+     * Set the {@link SurfaceTexture} for this view to use. If a {@link
+     * SurfaceTexture} is already being used by this view, it is immediately
+     * released and not be usable any more.  The {@link
+     * SurfaceTextureListener#onSurfaceTextureDestroyed} callback is <b>not</b>
+     * called.
+     *
+     * The {@link SurfaceTexture} object must be detached from all OpenGL ES
+     * contexts prior to calling this method.
+     *
+     * @param surfaceTexture The {@link SurfaceTexture} that the view should use.
+     * @see SurfaceTexture#detachFromGLContext()
+     * @hide
+     */
+    public void setSurfaceTexture(SurfaceTexture surfaceTexture) {
+        if (surfaceTexture == null) {
+            throw new NullPointerException("surfaceTexture must not be null");
+        }
+        if (mSurface != null) {
+            mSurface.release();
+        }
+        mSurface = surfaceTexture;
+        mUpdateSurface = true;
+        invalidateParentIfNeeded();
+    }
+
+    /**
      * Returns the {@link SurfaceTextureListener} currently associated with this
      * texture view.
      *