700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > SurfaceView GLSurfaceView SurfaceTexture TextureView SurfaceHolder Surface

SurfaceView GLSurfaceView SurfaceTexture TextureView SurfaceHolder Surface

时间:2021-06-21 12:50:29

相关推荐

SurfaceView GLSurfaceView SurfaceTexture TextureView SurfaceHolder Surface

SurfaceView、GLSurfaceViewe\SurfaceTexture、TextureView、SurfaceHolder、Surface

一、简介

SurfaceTexture: SurfaceTexture是从Android3.0(API 11)加入的一个新类。这个类跟SurfaceView很像,可以从video decode里面获取图像流(image stream)。但是,和SurfaceView不同的是,SurfaceTexture在接收图像流之后,不需要显示出来。SurfaceTexture不需要显示到屏幕上,因此我们可以用SurfaceTexture接收来自decode出来的图像流,然后从SurfaceTexture中取得图像帧的拷贝进行处理,处理完毕后再送给另一个SurfaceView用于显示即可

Surface: 处理被屏幕排序的原生的buffer,Android中的Surface就是一个用来画图形(graphics)或图像(image)的地方,对于View及其子类,都是画在Surface上,各Surface对象通过Surfaceflinger合成到frameBuffer,每个Surface都是双缓冲(实际上就是两个线程,一个渲染线程,一个UI更新线程),它有一个backBuffer和一个frontBuffer,Surface中创建了Canvas对象,用来管理Surface绘图操作,Canvas对应Bitmap,存储Surface中的内容(Surface可以理解成是用来管理Canvas画布的,而Canvas用来存储图像数据的)。

SurfaceView: 这个可能经常被说起,在Camera,MediaRecorder,MediaPlayer中用来显示图像的。SurfaceView是View的子类,且实现了Parcelable接口,其中内嵌了一个专门用于绘制的SurfaceSurfaceView可以控制这个Surface的格式和尺寸,以及Surface的绘制位置。可以理解为**Surface就是管理数据的地方,SurfaceView就是展示数据的地方**。

SurfaceHolder:顾名思义,一个管理Surface的容器。SurfaceHolder是一个接口,可理解为一个Surface的监听器

通过回调方法addCallback(SurfaceHolder.Callback callback )监听Surface的创建、改变、销毁等。通过获取Surface中的Canvas对象,并锁定所得到的Canvas对象,当修改Surface中的数据完成后,释放同步锁,并提交改变Surface的状态及图像,将新的图像数据进行展示。

而最后综合:SurfaceView中调用getHolder方法,可以获得当前SurfaceView中的Surface对应的SurfaceHolder,SurfaceHolder开始对Surface进行管理操作。这里其实按MVC模式理解的话,可以更好理解。M:Surface(图像数据),V:SurfaceView(图像展示),C:SurfaceHolder(图像数据管理)

1、 SurfaceView

从Android 1.0(API level 1)时就有 。它继承自类View,因此它本质上是一个View。但与普通View不同的是,它有自己的Surface。我们知道,一般的Activity包含的多个View会组成View hierachy的树形结构,只有最顶层的DecorView,也就是根结点视图,才是对WMS可见的,这个DecorView在WMS中有一个对应的WindowState。相应地,在SF中对应的Layer。SurfaceView自带一个Surface,这个Surface在WMS中有自己对应的WindowState,在SF中也会有自己的Layer。如下图所示:

也就是说, 虽然在Client端(App)它仍在View hierachy中,但在Server端(WMS和SF)中,它与宿主窗口是分离的(可以理解成其他的View在一个窗口中,SurfaceView中的Surface单独占用一个窗口)。这样的好处是**对这个Surface的渲染可以放到单独线程去做,渲染时可以有自己的GL context。这对于一些游戏、视频等性能相关的应用非常有益,因为它不会影响主线程对事件的响应。但它也有缺点,因为这个Surface不在View hierachy中,它的显示也不受View的属性控制,所以不能进行平移,缩放等变换,也不能放在其它ViewGroup中,一些View中的特性也无法使用**。

通过源码发现,SurfaceView里面其实就是创建了一个Surface,Surface主要的实现就是管理里面的Canvas的打开、关闭等,以及监听这个Surface的创建、改变、销毁、锁定里面的Canvas以及解锁等操作的SurfaceHolder,以及一些使里面的Surface占用独立窗口的一些操作。

final Surface mSurface = new Surface(); // Current surface in use

/**296* Return the SurfaceHolder providing access and control over this297* SurfaceView's underlying surface.298*299* @return SurfaceHolder The holder of the surface.300*/301 public SurfaceHolder getHolder() {302 return mSurfaceHolder;303 }304

@UnsupportedAppUsage1616 private final SurfaceHolder mSurfaceHolder = new SurfaceHolder() {1617 private static final String LOG_TAG = "SurfaceHolder";16181624 @Override1625 public void addCallback(Callback callback) {1626 synchronized (mCallbacks) {1627// This is a linear search, but in practice we'll1628// have only a couple callbacks, so it doesn't matter.1629if (!mCallbacks.contains(callback)) {1630mCallbacks.add(callback);1631}1632 }1633 }16341635 @Override1636 public void removeCallback(Callback callback) {1637 synchronized (mCallbacks) {1638mCallbacks.remove(callback);1639 }1640 }164116831684 /**1685 * Gets a {@link Canvas} for drawing into the SurfaceView's Surface1686 *1687 * After drawing into the provided {@link Canvas}, the caller must1688 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.1689 *1690 * The caller must redraw the entire surface.1691 * @return A canvas for drawing into the surface.1692 */1693 @Override1694 public Canvas lockCanvas() {1695 return internalLockCanvas(null, false);1696 }16971698 /**1699 * Gets a {@link Canvas} for drawing into the SurfaceView's Surface1700 *1701 * After drawing into the provided {@link Canvas}, the caller must1702 * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.1703 *1704 * @param inOutDirty A rectangle that represents the dirty region that the caller wants1705 * to redraw. This function may choose to expand the dirty rectangle if for example1706 * the surface has been resized or if the previous contents of the surface were1707 * not available. The caller must redraw the entire dirty region as represented1708 * by the contents of the inOutDirty rectangle upon return from this function.1709 * The caller may also pass <code>null</code> instead, in the case where the1710 * entire surface should be redrawn.1711 * @return A canvas for drawing into the surface.1712 */1713 @Override1714 public Canvas lockCanvas(Rect inOutDirty) {1715 return internalLockCanvas(inOutDirty, false);1716 }17171718 @Override1719 public Canvas lockHardwareCanvas() {1720 return internalLockCanvas(null, true);1721 }

private void setWindowStopped(boolean stopped) {310 mWindowStopped = stopped;311 updateRequestedVisibility();312 updateSurface();313 }314315 @Override316 protected void onAttachedToWindow() {317 super.onAttachedToWindow();318319 getViewRootImpl().addSurfaceChangedCallback(this);320 mWindowStopped = false;321322 mViewVisibility = getVisibility() == VISIBLE;323 updateRequestedVisibility();324325 mAttachedToWindow = true;326 mParent.requestTransparentRegion(SurfaceView.this);327 if (!mGlobalListenersAdded) {328 ViewTreeObserver observer = getViewTreeObserver();329 observer.addOnScrollChangedListener(mScrollChangedListener);330 observer.addOnPreDrawListener(mDrawListener);331 mGlobalListenersAdded = true;332 }333 }334

SurfaceView总结:里面会创建一个Surface,Surface主要管理Canvas画布对象的打开、关闭等操作,同时还有一个专门监听Surface创建、销毁、改变、里面的Canvas锁定等操作的SurfaceHolder,以及让Surface能够独占一个窗口的一系列操作。

2、GLSurfaceView

从Android 1.5(API level 3)开始加入,作为SurfaceView的补充。它可以看作是SurfaceView的一种典型使用模式。在SurfaceView的基础上,它加入了EGL的管理,并自带了渲染线程。另外它定义了用户需要实现的Render接口,提供了用Strategy pattern更改具体Render行为的灵活性。作为GLSurfaceView的Client,只需要将实现了渲染 函数的Renderer的实现类设置给GLSurfaceView即可。如:

public class TriangleActivity extends Activity {protected void onCreate(Bundle savedInstanceState) {mGLView = new GLSurfaceView(this); mGLView.setRenderer(new RendererImpl(this));

相关类图如下。其中SurfaceView中的SurfaceHolder主要是提供了一坨操作Surface的接口**。GLSurfaceView中的EglHelper和GLThread分别实现了上面提到的管理EGL环境和渲染线程的工作。GLSurfaceView的使用者需要实现Renderer接口**

通过源码可知,GLSurfaceView继承至SurfaceView,同时实现了SurfaceHolder.CallBack2的接口,只是多添加了一个Renderer接口,以及GLThread渲染线程(主要执行渲染的相关工作,管理渲染器的执行操作等,比如设置渲染器的模式,请求获得Render渲染器等)和EGlHelper管理EGL环境的工作。

1921 private static final GLThreadManager sGLThreadManager = new GLThreadManager();19221923 private final WeakReference<GLSurfaceView> mThisWeakRef =1924 new WeakReference<GLSurfaceView>(this);1925 @UnsupportedAppUsage1926 private GLThread mGLThread;1927 @UnsupportedAppUsage1928 private Renderer mRenderer;1929 private boolean mDetached;1930 private EGLConfigChooser mEGLConfigChooser;1931 private EGLContextFactory mEGLContextFactory;1932 private EGLWindowSurfaceFactory mEGLWindowSurfaceFactory;1933 private GLWrapper mGLWrapper;

设置Render渲染器之后,就可以创建GLThread渲染线程管理Render中一系列的操作了

/** @param renderer the renderer to use to perform OpenGL drawing.* 设置渲染器之后,马上开启渲染线程347*/348 public void setRenderer(Renderer renderer) {349 checkRenderThreadState();350 if (mEGLConfigChooser == null) {351 mEGLConfigChooser = new SimpleEGLConfigChooser(true);352 }353 if (mEGLContextFactory == null) {354 mEGLContextFactory = new DefaultContextFactory();355 }356 if (mEGLWindowSurfaceFactory == null) {357 mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();358 }359 mRenderer = renderer;360 mGLThread = new GLThread(mThisWeakRef);361 mGLThread.start();362 }/**606* This method is used as part of the View class and is not normally607* called or subclassed by clients of GLSurfaceView.608*/609 @Override610 protected void onAttachedToWindow() {611 super.onAttachedToWindow();612 if (LOG_ATTACH_DETACH) {613 Log.d(TAG, "onAttachedToWindow reattach =" + mDetached);614 }615 if (mDetached && (mRenderer != null)) {616 int renderMode = RENDERMODE_CONTINUOUSLY;617 if (mGLThread != null) {618renderMode = mGLThread.getRenderMode();619 }620 mGLThread = new GLThread(mThisWeakRef);621 if (renderMode != RENDERMODE_CONTINUOUSLY) {622mGLThread.setRenderMode(renderMode);623 }624 mGLThread.start();625 }626 mDetached = false;627 }

管理EGL环境

public void setEGLConfigChooser(boolean needDepth) {425 setEGLConfigChooser(new SimpleEGLConfigChooser(needDepth));426 }427428 /**429* Install a config chooser which will choose a config430* with at least the specified depthSize and stencilSize,431* and exactly the specified redSize, greenSize, blueSize and alphaSize.432* <p>If this method is433* called, it must be called before {@link #setRenderer(Renderer)}434* is called.435* <p>436* If no setEGLConfigChooser method is called, then by default the437* view will choose an RGB_888 surface with a depth buffer depth of438* at least 16 bits.439*440*/441 public void setEGLConfigChooser(int redSize, int greenSize, int blueSize,442 int alphaSize, int depthSize, int stencilSize) {443 setEGLConfigChooser(new ComponentSizeChooser(redSize, greenSize,444blueSize, alphaSize, depthSize, stencilSize));445 }

可以在GLThread渲染线程里面去请求它管理的Render渲染器,也可以设置Render的各种模式等

public void setRenderMode(int renderMode) {495 mGLThread.setRenderMode(renderMode);496 }497498 /**499* Get the current rendering mode. May be called500* from any thread. Must not be called before a renderer has been set.501* @return the current rendering mode.502* @see #RENDERMODE_CONTINUOUSLY503* @see #RENDERMODE_WHEN_DIRTY504*/505 public int getRenderMode() {506 return mGLThread.getRenderMode();507 }508509 /**510* Request that the renderer render a frame.511* This method is typically used when the render mode has been set to512* {@link #RENDERMODE_WHEN_DIRTY}, so that frames are only rendered on demand.513* May be called514* from any thread. Must not be called before a renderer has been set.515*/516 public void requestRender() {517 mGLThread.requestRender();518 }519520 /**521* This method is part of the SurfaceHolder.Callback interface, and is522* not normally called or subclassed by clients of GLSurfaceView.523*/524 public void surfaceCreated(SurfaceHolder holder) {525 mGLThread.surfaceCreated();526 }527528 /**529* This method is part of the SurfaceHolder.Callback interface, and is530* not normally called or subclassed by clients of GLSurfaceView.531*/532 public void surfaceDestroyed(SurfaceHolder holder) {533 // Surface will be destroyed when we return534 mGLThread.surfaceDestroyed();535 }536537 /**538* This method is part of the SurfaceHolder.Callback interface, and is539* not normally called or subclassed by clients of GLSurfaceView.540*/541 public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {542 mGLThread.onWindowResize(w, h);543 }544

当Surface被创建、改变、绘制的时候会回调Render里面的方法

public interface Renderer {710 /**711 * Called when the surface is created or recreated.733 */734 void onSurfaceCreated(GL10 gl, EGLConfig config);735736 /**737 * Called when the surface changed size.753 * </pre>754 * @param gl the GL interface. Use <code>instanceof</code> to755 * test if the interface supports GL11 or higher interfaces.756 * @param width757 * @param height758 */759 void onSurfaceChanged(GL10 gl, int width, int height);760761 /**762 * Called to draw the current frame.763 * <p>764 * This method is responsible for drawing the current frame.765 * <p>775 */776 void onDrawFrame(GL10 gl);777 }778

EglHelper主要进行了一系列EGL环境的设置,以及创建、销毁Surface,GLThread中关于创建、销毁Surface等操作实际上就是调用了EglHelper中相应的方法等

private static class EglHelper {1016 public EglHelper(WeakReference<GLSurfaceView> glSurfaceViewWeakRef) {1017 mGLSurfaceViewWeakRef = glSurfaceViewWeakRef;1018 }10191020 /**1021 * Initialize EGL for a given configuration spec.1022 * @param configSpec1023 */1024 public void start() {1025 if (LOG_EGL) {1026Log.w("EglHelper", "start() tid=" + Thread.currentThread().getId());1027 }1028 /*1029 * Get an EGL instance1030 */1031 mEgl = (EGL10) EGLContext.getEGL();10321033 /*1034 * Get to the default display.1035 */1036 mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);10371038 if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {1039throw new RuntimeException("eglGetDisplay failed");1040 }10411042 /*1043 * We can now initialize EGL for that display1044 */1045 int[] version = new int[2];1046 if(!mEgl.eglInitialize(mEglDisplay, version)) {1047throw new RuntimeException("eglInitialize failed");1048 }1049 GLSurfaceView view = mGLSurfaceViewWeakRef.get();1050 if (view == null) {1051mEglConfig = null;1052mEglContext = null;1053 } else {1054mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);10551056/*1057* Create an EGL context. We want to do this as rarely as we can, because an1058* EGL context is a somewhat heavy object.1059*/1060mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);1061 }1062 if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) {1063mEglContext = null;1064throwEglException("createContext");1065 }1066 if (LOG_EGL) {1067Log.w("EglHelper", "createContext " + mEglContext + " tid=" + Thread.currentThread().getId());1068 }10691070 mEglSurface = null;1071 }10721073 /**1074 * Create an egl surface for the current SurfaceHolder surface. If a surface1075 * already exists, destroy it before creating the new surface.1076 *1077 * @return true if the surface was created successfully.1078 */1079 public boolean createSurface() {10951096 /*1097 * The window size has changed, so we need to create a new1098 * surface.1099 */1100 destroySurfaceImp();11011102 /*1103 * Create an EGL surface we can render into.1104 */1105 GLSurfaceView view = mGLSurfaceViewWeakRef.get();1106 if (view != null) {1107mEglSurface = view.mEGLWindowSurfaceFactory.createWindowSurface(mEgl,1108 mEglDisplay, mEglConfig, view.getHolder());1109 } else {1110mEglSurface = null;1111 }11121113 ...1135 }private WeakReference<GLSurfaceView> mGLSurfaceViewWeakRef;1235 EGL10 mEgl;1236 EGLDisplay mEglDisplay;1237 EGLSurface mEglSurface;1238 EGLConfig mEglConfig;1239 @UnsupportedAppUsage1240 EGLContext mEglContext;1163 }

GLThead渲染线程主要是管理Surface等渲染相关组件的创建与销毁,但是这个里面仅仅是进行了一些boolean值进行开关控制,真正实现具体的创建、销毁Surface等操作的实在EglHelper中,当Surface被创建等Render接口中的onSurfaceCreated()此时就能够监听得到这个事件,这也是为什么要在创建Render以后才开启GLThread线程。

static class GLThread extends Thread {1254 GLThread(WeakReference<GLSurfaceView> glSurfaceViewWeakRef) {1255 super();1256 mWidth = 0;1257 mHeight = 0;1258 mRequestRender = true;1259 mRenderMode = RENDERMODE_CONTINUOUSLY;1260 mWantRenderNotification = false;1261 mGLSurfaceViewWeakRef = glSurfaceViewWeakRef;1262 }12631264 @Override1265 public void run() {1266 setName("GLThread " + getId());1267 if (LOG_THREADS) {1268Log.i("GLThread", "starting tid=" + getId());1269 }12701271 try {1272guardedRun();1273 } catch (InterruptedException e) {1274// fall thru and exit normally1275 } finally {1276sGLThreadManager.threadExiting(this);1277 }1278 }12791280 /*1281 * This private method should only be called inside a1282 * synchronized(sGLThreadManager) block.1283 */1284 private void stopEglSurfaceLocked() {1285 if (mHaveEglSurface) {1286mHaveEglSurface = false;1287mEglHelper.destroySurface();1288 }1289 }12901291 /*1292 * This private method should only be called inside a1293 * synchronized(sGLThreadManager) block.1294 */1295 private void stopEglContextLocked() {1296 if (mHaveEglContext) {1297mEglHelper.finish();1298mHaveEglContext = false;1299sGLThreadManager.releaseEglContextLocked(this);1300 }1301 }1839 private int mRenderMode;1840 private boolean mRequestRender;1841 private boolean mWantRenderNotification;1842 private boolean mRenderComplete;1843 private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();1844 private boolean mSizeChanged = true;1845 private Runnable mFinishDrawingRunnable = null;18461847 // End of member variables protected by the sGLThreadManager monitor.18481849 @UnsupportedAppUsage1850 private EglHelper mEglHelper;18511852 /**1853 * Set once at thread construction time, nulled out when the parent view is garbage1854 * called. This weak reference allows the GLSurfaceView to be garbage collected while1855 * the GLThread is still alive.1856 */1857 private WeakReference<GLSurfaceView> mGLSurfaceViewWeakRef;

GLSurfaceView总结:继承自SurfaceView,以及实现了SurfaceHolder.CallBack2里面的方法,也就是说就是SurfaceView的升级版,但不相同的是,里面多了一个GLThread渲染线程,用于主要执行渲染的相关工作,管理渲染器的执行操作等,比如设置渲染器的模式,请求获得Render渲染器等,和EGlHelper管理EGL环境的工作(需要注意:GLThead渲染线程主要是管理Surface等渲染相关组件的创建与销毁,但是这个里面仅仅是进行了一些boolean值进行开关控制,真正实现具体的创建、销毁Surface等操作的实在EglHelper中,当Surface被创建等Render接口中的onSurfaceCreated()此时就能够监听得到这个事件,这也是为什么要在创建Render以后才开启GLThread线程)。

3、SurfaceTexture

从Android 3.0(API level 11)加入。和SurfaceView不同的是, 它对图像流的处理并不直接显示,而是转为GL外部纹理,因此可用于图像流数据的二次处理(如Camera滤镜,桌面特效等)。比如Camera的预览数据,变成纹理后可以交给GLSurfaceView直接显示,也可以通过SurfaceTexture交给TextureView作为View heirachy中的一个硬件加速层来显示。首先,SurfaceTexture从图像流(来自Camera预览,视频解码,GL绘制场景等)中获得帧数据,当调用updateTexImage()时,根据内容流中最近的图像更新SurfaceTexture对应的GL纹理对象,接下来,就可以像操作普通GL纹理一样操作它了。从下面的类图中可以看出,它**核心管理着一个BufferQueue的Consumer和Producer两端。Producer端用于内容流的源输出数据,Consumer端用于拿GraphicBuffer并生成纹理。**SurfaceTexture.OnFrameAvailableListener用于让SurfaceTexture的使用者知道有新数据到来。JNISurfaceTextureContext是OnFrameAvailableListener从Native到Java的JNI跳板。其中SurfaceTexture中的attachToGLContext()和detachToGLContext()可以让多个GL context共享同一个内容源。

Android 5.0中将BufferQueue的核心功能分离出来,放在BufferQueueCore这个类中。BufferQueueProducer和BufferQueueConsumer分别是它的生产者和消费者实现基类(分别实现了IGraphicBufferProducer和IGraphicBufferConsumer接口)。它们都是由BufferQueue的静态 函数createBufferQueue()来创建的。Surface是生产者端的实现类,提供dequeueBuffer/queueBuffer等硬件渲染接口,和lockCanvas/unlockCanvasAndPost等软件渲染接口,其实Surface中的Canvas可以理解成就是一个存储图像数据的地方,使内容流的源可以往BufferQueue中填graphic buffer。GLConsumer继承自ConsumerBase,是消费者端的实现类。它在基类的基础上添加了GL相关的操作,如将graphic buffer中的内容转为GL纹理等操作。到此,以SurfaceTexture为中心的一个pipeline大体是这样的:

4、TextureView

在4.0(API level 14)中引入。它可以将内容流直接投影到View中,可以用于实现Live preview等功能。和SurfaceView不同, 它不会在WMS中单独创建窗口,而是作为View hierachy中的一个普通View,因此可以和其它普通View一样进行移动,旋转,缩放,动画等变化。值得注意的是 TextureView**必须在硬件加速的窗口中。它显示的内容流数据可以来自App进程或是远端进程。从类图中可以看到,TextureView继承自View,它与其它的View一样在View hierachy中管理与绘制。TextureView重载了draw()方法,其中主要把SurfaceTexture中收到的图像数据作为纹理更新到对应的HardwareLayer中**。SurfaceTexture.OnFrameAvailableListener用于通知TextureView内容流有新图像到来。SurfaceTextureListener接口用于让TextureView的使用者知道SurfaceTexture已准备好,这样就可以把SurfaceTexture交给相应的内容源。Surface为BufferQueue的Producer接口实现类,使生产者可以通过它的软件或硬件渲染接口为SurfaceTexture内部的BufferQueue提供graphic buffer。

TextureView内部就有一个SurfaceTexture,以及一个SurfaceTextureListener,用来监听SurfaceTexture的状态等,SurfaceTexture.onFrameAvailableListener主要用来通知TextureView有新图像的到来,TextureView重载了draw()方法,其中主要把SurfaceTexture中收到的图像数据作为纹理更新到对应的HardwareLayer中。

@UnsupportedAppUsage115 private TextureLayer mLayer;116 @UnsupportedAppUsage117 private SurfaceTexture mSurface;118 private SurfaceTextureListener mListener;119 private boolean mHadSurface;11 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)122 private boolean mOpaque = true;123124 private final Matrix mMatrix = new Matrix();125 private boolean mMatrixChanged;126127 private final Object[] mLock = new Object[0];128 private boolean mUpdateLayer;129 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)130 private boolean mUpdateSurface;131132 private Canvas mCanvas;

public interface SurfaceTextureListener {818 /**819 * Invoked when a {@link TextureView}'s SurfaceTexture is ready for use.820 *821 * @param surface The surface returned by822 *{@link android.view.TextureView#getSurfaceTexture()}823 * @param width The width of the surface824 * @param height The height of the surface825 */826 void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height);827828 /**829 * Invoked when the {@link SurfaceTexture}'s buffers size changed.830 *831 * @param surface The surface returned by832 *{@link android.view.TextureView#getSurfaceTexture()}833 * @param width The new width of the surface834 * @param height The new height of the surface835 */836 void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height);837838 /**839 * Invoked when the specified {@link SurfaceTexture} is about to be destroyed.840 * If returns true, no rendering should happen inside the surface texture after this method841 * is invoked. If returns false, the client needs to call {@link SurfaceTexture#release()}.842 * Most applications should return true.843 *844 * @param surface The surface about to be destroyed845 */846 boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface);847848 /**849 * Invoked when the specified {@link SurfaceTexture} is updated through850 * {@link SurfaceTexture#updateTexImage()}.851 *852 * @param surface The surface just updated853 */854 void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface);855 }

@Override342 public final void draw(Canvas canvas) {343 // NOTE: Maintain this carefully (see View#draw)344 mPrivateFlags = (mPrivateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;345346 /* Simplify drawing to guarantee the layer is the only thing drawn - so e.g. no background,347 scrolling, or fading edges. This guarantees all drawing is in the layer, so drawing348 properties (alpha, layer paint) affect all of the content of a TextureView. */349350 if (canvas.isHardwareAccelerated()) {351 RecordingCanvas recordingCanvas = (RecordingCanvas) canvas;352353 TextureLayer layer = getTextureLayer();354 if (layer != null) {355applyUpdate();356applyTransformMatrix();357358mLayer.setLayerPaint(mLayerPaint); // ensure layer paint is up to date359recordingCanvas.drawTextureLayer(layer);360 }361 }362 }TextureLayer getTextureLayer() {387 if (mLayer == null) {388 if (mAttachInfo == null || mAttachInfo.mThreadedRenderer == null) {389return null;390 }391392 mLayer = mAttachInfo.mThreadedRenderer.createTextureLayer();393 boolean createNewSurface = (mSurface == null);394 if (createNewSurface) {395// Create a new SurfaceTexture for the layer.396mSurface = new SurfaceTexture(false);397nCreateNativeWindow(mSurface);398 }399 mLayer.setSurfaceTexture(mSurface);400 mSurface.setDefaultBufferSize(getWidth(), getHeight());401 mSurface.setOnFrameAvailableListener(mUpdateListener, mAttachInfo.mHandler);402403 if (mListener != null && createNewSurface) {404mListener.onSurfaceTextureAvailable(mSurface, getWidth(), getHeight());405 }406 mLayer.setLayerPaint(mLayerPaint);407 }408409 if (mUpdateSurface) {410 // Someone has requested that we use a specific SurfaceTexture, so411 // tell mLayer about it and set the SurfaceTexture to use the412 // current view size.413 mUpdateSurface = false;414415 // Since we are updating the layer, force an update to ensure its416 // parameters are correct (width, height, transform, etc.)417 updateLayer();418 mMatrixChanged = true;419420 mLayer.setSurfaceTexture(mSurface);421 mSurface.setDefaultBufferSize(getWidth(), getHeight());422 }423424 return mLayer;425 }

public @Nullable Canvas lockCanvas(@Nullable Rect dirty) {688 if (!isAvailable()) return null;689690 if (mCanvas == null) {691 mCanvas = new Canvas();692 }693694 synchronized (mNativeWindowLock) {695 if (!nLockCanvas(mNativeWindow, mCanvas, dirty)) {696return null;697 }698 }699 mSaveCount = mCanvas.save();700701 return mCanvas;702 }

二、总结

SurfaceView是一个有自己独立Surface的View, 它的渲染可以放在单独线程而不是主线程中, 其缺点是不能做变形和动画。

SurfaceTexture可以用作非直接输出的内容流,这样就提供二次处理的机会。与SurfaceView直接输出相比,这样会有若干帧的延迟。同时,由于它本身管理BufferQueue,因此 内存消耗也会稍微大一些。

TextureView是一个可以把内容流作为外部纹理输出在上面的View, 它本身需要是一个硬件加速层。

事实上TextureView本身也包含了SurfaceTexture, 它与SurfaceView+SurfaceTexture组合相比可以完成类似的功能(即把内容流上的图像转成纹理,然后输出), 区别在于TextureView是在View hierachy中做绘制,因此一般它是在主线程上做的(在Android 5.0引入渲染线程后,它是在渲染线程中做的)。而SurfaceView+SurfaceTexture在单独的Surface上做绘制,可以是用户提供的线程,而不是系统的主线程或是渲染线程。另外,与SurfaceView相比,它还有个好处是可以用Hardware overlay进行显示。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。