Merge "Add onSurfaceTextureDestroyed() callback."

This commit is contained in:
Romain Guy
2011-06-10 15:45:23 -07:00
committed by Android (Google) Code Review
3 changed files with 117 additions and 48 deletions

View File

@@ -56,14 +56,7 @@ import android.util.Log;
* setContentView(mTextureView);
* }
*
* protected void onDestroy() {
* super.onDestroy();
*
* mCamera.stopPreview();
* mCamera.release();
* }
*
* public void onSurfaceTextureAvailable(SurfaceTexture surface) {
* public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
* mCamera = Camera.open();
*
* try {
@@ -77,6 +70,11 @@ import android.util.Log;
* public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
* // Ignored, Camera does all the work for us
* }
*
* public void onSurfaceTextureDestroyed(SurfaceTexture surface) {
* mCamera.stopPreview();
* mCamera.release();
* }
* }
* </pre>
*
@@ -155,6 +153,21 @@ public class TextureView extends View {
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (isHardwareAccelerated() && mLayer != null) {
if (mListener != null) {
mListener.onSurfaceTextureDestroyed(mSurface);
}
mLayer.destroy();
mSurface = null;
mLayer = null;
}
}
/**
* The layer type of a TextureView is ignored since a TextureView is always
* considered to act as a hardware layer. The optional paint supplied to this
@@ -217,6 +230,9 @@ public class TextureView extends View {
super.onSizeChanged(w, h, oldw, oldh);
if (mSurface != null) {
nSetDefaultBufferSize(mSurface.mSurfaceTexture, getWidth(), getHeight());
if (mListener != null) {
mListener.onSurfaceTextureSizeChanged(mSurface, getWidth(), getHeight());
}
}
}
@@ -242,7 +258,7 @@ public class TextureView extends View {
mSurface.setOnFrameAvailableListener(mUpdateListener);
if (mListener != null) {
mListener.onSurfaceTextureAvailable(mSurface);
mListener.onSurfaceTextureAvailable(mSurface, getWidth(), getHeight());
}
}
@@ -316,8 +332,10 @@ public class TextureView extends View {
*
* @param surface The surface returned by
* {@link android.view.TextureView#getSurfaceTexture()}
* @param width The width of the surface
* @param height The height of the surface
*/
public void onSurfaceTextureAvailable(SurfaceTexture surface);
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height);
/**
* Invoked when the {@link SurfaceTexture}'s buffers size changed.
@@ -328,6 +346,15 @@ public class TextureView extends View {
* @param height The new height of the surface
*/
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height);
/**
* Invoked when the specified {@link SurfaceTexture} is about to be destroyed.
* After this method is invoked, no rendering should happen inside the surface
* texture.
*
* @param surface The surface about to be destroyed
*/
public void onSurfaceTextureDestroyed(SurfaceTexture surface);
}
private static native void nSetDefaultBufferSize(int surfaceTexture, int width, int height);

View File

@@ -52,13 +52,7 @@ public class GLTextureViewActivity extends Activity implements TextureView.Surfa
}
@Override
protected void onDestroy() {
super.onDestroy();
mRenderThread.finish();
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface) {
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mRenderThread = new RenderThread(surface);
mRenderThread.start();
@@ -81,6 +75,16 @@ public class GLTextureViewActivity extends Activity implements TextureView.Surfa
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
}
@Override
public void onSurfaceTextureDestroyed(SurfaceTexture surface) {
mRenderThread.finish();
try {
mRenderThread.join();
} catch (InterruptedException e) {
Log.e(RenderThread.LOG_TAG, "Could not wait for render thread");
}
}
private static class RenderThread extends Thread {
private static final String LOG_TAG = "GLTextureView";
@@ -108,26 +112,23 @@ public class GLTextureViewActivity extends Activity implements TextureView.Surfa
public void run() {
initGL();
float red = 0.0f;
float red = 1.0f;
while (!mFinished) {
checkCurrent();
Log.d(LOG_TAG, "Rendering frame");
GLES20.glClearColor(red, 0.0f, 0.0f, 1.0f);
int error = GLES20.glGetError();
if (error != GLES20.GL_NO_ERROR) {
Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error));
}
checkGlError();
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
error = GLES20.glGetError();
if (error != GLES20.GL_NO_ERROR) {
Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error));
}
checkGlError();
if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
throw new RuntimeException("Cannot swap buffers");
}
checkEglError();
try {
Thread.sleep(20);
} catch (InterruptedException e) {
@@ -141,6 +142,20 @@ public class GLTextureViewActivity extends Activity implements TextureView.Surfa
finishGL();
}
private void checkEglError() {
int error = mEgl.eglGetError();
if (error != EGL10.EGL_SUCCESS) {
Log.w(LOG_TAG, "EGL error = 0x" + Integer.toHexString(error));
}
}
private void checkGlError() {
int error = GLES20.glGetError();
if (error != GLES20.GL_NO_ERROR) {
Log.w(LOG_TAG, "GL error = 0x" + Integer.toHexString(error));
}
}
private void finishGL() {
mEgl.eglDestroyContext(mEglDisplay, mEglContext);
mEgl.eglDestroySurface(mEglDisplay, mEglSurface);

View File

@@ -16,6 +16,7 @@
package com.android.test.hwui;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
@@ -25,6 +26,7 @@ import android.os.Bundle;
import android.view.Gravity;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import android.widget.FrameLayout;
import java.io.IOException;
@@ -33,27 +35,44 @@ import java.io.IOException;
public class TextureViewActivity extends Activity implements TextureView.SurfaceTextureListener {
private Camera mCamera;
private TextureView mTextureView;
private FrameLayout mContent;
private AnimatorSet mAnimatorSet;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContent = new FrameLayout(this);
mTextureView = new TextureView(this);
mTextureView.setSurfaceTextureListener(this);
setContentView(mTextureView, new FrameLayout.LayoutParams(500, 400, Gravity.CENTER));
Button button = new Button(this);
button.setText("Remove/Add");
button.setOnClickListener(new View.OnClickListener() {
private boolean mAdded = true;
@Override
public void onClick(View v) {
if (mAdded) {
mAnimatorSet.cancel();
mContent.removeView(mTextureView);
} else {
mContent.addView(mTextureView);
}
mAdded = !mAdded;
}
});
mContent.addView(mTextureView, new FrameLayout.LayoutParams(500, 400, Gravity.CENTER));
mContent.addView(button, new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT,
Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM));
setContentView(mContent);
}
@Override
protected void onDestroy() {
super.onDestroy();
mCamera.stopPreview();
mCamera.release();
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface) {
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mCamera = Camera.open();
try {
@@ -66,27 +85,35 @@ public class TextureViewActivity extends Activity implements TextureView.Surface
mTextureView.setCameraDistance(5000);
ObjectAnimator animator = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f);
animator.setRepeatMode(ObjectAnimator.REVERSE);
animator.setRepeatCount(ObjectAnimator.INFINITE);
animator.setDuration(4000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
ObjectAnimator rotationY = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f);
rotationY.setRepeatMode(ObjectAnimator.REVERSE);
rotationY.setRepeatCount(ObjectAnimator.INFINITE);
rotationY.setDuration(4000);
rotationY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
((View) mTextureView.getParent()).invalidate();
}
});
animator.start();
animator = ObjectAnimator.ofFloat(mTextureView, "alpha", 1.0f, 0.0f);
animator.setRepeatMode(ObjectAnimator.REVERSE);
animator.setRepeatCount(ObjectAnimator.INFINITE);
animator.setDuration(4000);
animator.start();
ObjectAnimator alpha = ObjectAnimator.ofFloat(mTextureView, "alpha", 1.0f, 0.0f);
alpha.setRepeatMode(ObjectAnimator.REVERSE);
alpha.setRepeatCount(ObjectAnimator.INFINITE);
alpha.setDuration(4000);
mAnimatorSet = new AnimatorSet();
mAnimatorSet.play(alpha).with(rotationY);
mAnimatorSet.start();
}
@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
// Ignored, the Camera does all the work for us
}
@Override
public void onSurfaceTextureDestroyed(SurfaceTexture surface) {
mCamera.stopPreview();
mCamera.release();
}
}