Skip to content

Commit 2af3524

Browse files
author
Jamie Gennis
committed
TextureView: add setSurfaceTexture method
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
1 parent c6d9930 commit 2af3524

File tree

3 files changed

+75
-5
lines changed

3 files changed

+75
-5
lines changed

core/java/android/view/GLES20TextureLayer.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ class GLES20TextureLayer extends GLES20Layer {
4242
}
4343
}
4444

45+
GLES20TextureLayer(SurfaceTexture surface, boolean isOpaque) {
46+
this(isOpaque);
47+
mSurface = surface;
48+
mSurface.attachToGLContext(mTexture);
49+
}
50+
4551
@Override
4652
boolean isValid() {
4753
return mLayer != 0 && mTexture != 0;
@@ -72,6 +78,14 @@ SurfaceTexture getSurfaceTexture() {
7278
return mSurface;
7379
}
7480

81+
void setSurfaceTexture(SurfaceTexture surfaceTexture) {
82+
if (mSurface != null) {
83+
mSurface.release();
84+
}
85+
mSurface = surfaceTexture;
86+
mSurface.attachToGLContext(mTexture);
87+
}
88+
7589
@Override
7690
void update(int width, int height, boolean isOpaque) {
7791
super.update(width, height, isOpaque);

core/java/android/view/HardwareRenderer.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,9 +391,9 @@ abstract boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbac
391391
* @param isOpaque Whether the layer should be opaque or not
392392
*
393393
* @return A hardware layer
394-
*/
394+
*/
395395
abstract HardwareLayer createHardwareLayer(boolean isOpaque);
396-
396+
397397
/**
398398
* Creates a new hardware layer.
399399
*
@@ -416,6 +416,15 @@ abstract boolean draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbac
416416
*/
417417
abstract SurfaceTexture createSurfaceTexture(HardwareLayer layer);
418418

419+
/**
420+
* Sets the {@link android.graphics.SurfaceTexture} that will be used to
421+
* render into the specified hardware layer.
422+
*
423+
* @param layer The layer to render into using a {@link android.graphics.SurfaceTexture}
424+
* @param surfaceTexture The {@link android.graphics.SurfaceTexture} to use for the layer
425+
*/
426+
abstract void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture);
427+
419428
/**
420429
* Initializes the hardware renderer for the specified surface and setup the
421430
* renderer for drawing, if needed. This is invoked when the ViewAncestor has
@@ -1344,6 +1353,11 @@ SurfaceTexture createSurfaceTexture(HardwareLayer layer) {
13441353
return ((GLES20TextureLayer) layer).getSurfaceTexture();
13451354
}
13461355

1356+
@Override
1357+
void setSurfaceTexture(HardwareLayer layer, SurfaceTexture surfaceTexture) {
1358+
((GLES20TextureLayer) layer).setSurfaceTexture(surfaceTexture);
1359+
}
1360+
13471361
@Override
13481362
void destroyLayers(View view) {
13491363
if (view != null && isEnabled() && checkCurrent() != SURFACE_STATE_ERROR) {

core/java/android/view/TextureView.java

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ public class TextureView extends View {
115115

116116
private final Object[] mLock = new Object[0];
117117
private boolean mUpdateLayer;
118+
private boolean mUpdateSurface;
118119

119120
private SurfaceTexture.OnFrameAvailableListener mUpdateListener;
120121

@@ -208,6 +209,8 @@ protected void onDetachedFromWindow() {
208209

209210
private void destroySurface() {
210211
if (mLayer != null) {
212+
mSurface.detachFromGLContext();
213+
211214
boolean shouldRelease = true;
212215
if (mListener != null) {
213216
shouldRelease = mListener.onSurfaceTextureDestroyed(mSurface);
@@ -322,9 +325,13 @@ HardwareLayer getHardwareLayer() {
322325
}
323326

324327
mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(mOpaque);
325-
mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer);
328+
if (!mUpdateSurface) {
329+
// We already have a SurfaceTexture to use, and we will pass it
330+
// to mLayer below.
331+
mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer);
332+
}
326333
nSetDefaultBufferSize(mSurface, getWidth(), getHeight());
327-
nCreateNativeWindow(mSurface);
334+
nCreateNativeWindow(mSurface);
328335

329336
mUpdateListener = new SurfaceTexture.OnFrameAvailableListener() {
330337
@Override
@@ -344,6 +351,15 @@ public void onFrameAvailable(SurfaceTexture surfaceTexture) {
344351
}
345352
}
346353

354+
if (mUpdateSurface) {
355+
// Someone has requested that we use a specific SurfaceTexture, so
356+
// tell mLayer about it and set the SurfaceTexture to use the
357+
// current view size.
358+
mUpdateSurface = false;
359+
mAttachInfo.mHardwareRenderer.setSurfaceTexture(mLayer, mSurface);
360+
nSetDefaultBufferSize(mSurface, getWidth(), getHeight());
361+
}
362+
347363
applyUpdate();
348364
applyTransformMatrix();
349365

@@ -371,7 +387,7 @@ private void updateLayer() {
371387
mUpdateLayer = true;
372388
invalidate();
373389
}
374-
390+
375391
private void applyUpdate() {
376392
if (mLayer == null) {
377393
return;
@@ -635,6 +651,32 @@ public SurfaceTexture getSurfaceTexture() {
635651
return mSurface;
636652
}
637653

654+
/**
655+
* Set the {@link SurfaceTexture} for this view to use. If a {@link
656+
* SurfaceTexture} is already being used by this view, it is immediately
657+
* released and not be usable any more. The {@link
658+
* SurfaceTextureListener#onSurfaceTextureDestroyed} callback is <b>not</b>
659+
* called.
660+
*
661+
* The {@link SurfaceTexture} object must be detached from all OpenGL ES
662+
* contexts prior to calling this method.
663+
*
664+
* @param surfaceTexture The {@link SurfaceTexture} that the view should use.
665+
* @see SurfaceTexture#detachFromGLContext()
666+
* @hide
667+
*/
668+
public void setSurfaceTexture(SurfaceTexture surfaceTexture) {
669+
if (surfaceTexture == null) {
670+
throw new NullPointerException("surfaceTexture must not be null");
671+
}
672+
if (mSurface != null) {
673+
mSurface.release();
674+
}
675+
mSurface = surfaceTexture;
676+
mUpdateSurface = true;
677+
invalidateParentIfNeeded();
678+
}
679+
638680
/**
639681
* Returns the {@link SurfaceTextureListener} currently associated with this
640682
* texture view.

0 commit comments

Comments
 (0)