写在前面的话
最近在弄framework层的注入,又是学习Android系统的启动流程,IPC,还有Android的整个GUI渲染机制,看源码看了一礼拜,眼睛疼,擦。。总感觉没有成功的打通整个环节,从Android系统的启动,到执行开机通话这个环节,又得研究游戏Apk是怎么调用OpenGL的渲染,为什么不走eglSwapBuffer这个方法,我hook了又不调,烦得很哎。。还是找个简单的来做一做,先研究在Android应用上面openGL的使用吧哎。。想到这一个礼拜来一直沉迷源码,赶紧停下来写写java,我就顺手把OpenGL在安卓的应用这一块理一理吧。。唉。。
SurfaceView
先简略的说一下SurfaceFlinger,这就是一个系统服务,负责系统底层GUI这一块的管理,后面我会详细的把这一块理一理。
通常来说,我们一个Activity(或者说一个Window)都在SurfaceFlinger中,对应这一个Layer(见下图),像一般我们在Activity的布局中,需要显示Button啊、TextView这种的,都是往这个对应的Layer填充数据,然后由SurfaceFlinger来对各种各样的Layer进行合成渲染,最后控制底层显示在屏幕上。然后像Button这种的控件的绘制,都是在UI主线程中进行的,如果需要频繁的刷新界面,比如直播啊拍照的摄像头预览,那肯定就比较耗时嘛,耗时你主线程就没办法对用户的输入进行响应,容易ANR,所以就有了SurfaceView这个东西,他在SurfaceFlinger中单独对应一个Layer(LayerBuffer),通过子线程来对它进行更新。
SurfaceView继承View,有两个子类GLSurfaceView和VideoView
使用
创建一个自定义的MySurfaceView,继承自SurfaceView,并实现两个接口SurfaceHolder.CallBack和Runnable(都是为了方便,如果代码复杂的应该要分别实现MySurfaceHolder已经DrawingThread来分别对应周期控制与子线程绘制)。
SurfaceHolder.CallBack的三个方法分别对应着SurfaceView的三个生命周期
1 | public interface Callback { |
由此我们可以猜测这个Holder可能是Surface的主要控制类,看看这个类的部分方法,不难知道SurfaceHolder控制着SurfaceView的大小,格式,可以监控或者改变SurfaceView。
1 | void setFixedSize(int var1, int var2); |
需要绘制的话,还需要一个画布类Canvas,在对应的生命周期中开始绘制并且提交,Holder也提供了相应的方法
1 | mCanvas = mHolder.lockCanvas(); //lock |
完整代码
1 | public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable{ |
GLSurfaceView 和 Renderer
SurfaceView的子类,功能和SurfaceView相似。我们可以创建一个GLSurfaceView类的实例,实现GLSurfaceView.Renderer接口添加自定义渲染。GLSurfaceView没什么好说的,主要还是他的这个渲染器接口Renderer
1 | public interface Renderer { |
这个接口有3个方法
- onSurfaceCreated() surface被创建或者重新创建的时候调用。当线程开始渲染时或者EGL Context丢失时也会调用(EGL是Android系统对OpenGL的上层封装扩展,EGL Context通常在系统屏幕黑掉的时候丢失)。
- onSurfaceChanged()- 如果View的几和形状发生变化了就调用
- onDrawFrame()- 绘制当前的帧,每次View被重绘时被调用。
完整代码
根据以上3个方法的介绍,基本可以确定是onSurfaceCreated里面做一些配置任务,官网也推荐我们在这个方法里创建一些资源等。然后在onDrawFrame里面实现每一帧的绘制任务。
具体的位置就是要参考openGL的API了,先写上吧,以后有需要再进一步学习
1 |
|
在MainActivity中直接调用setRenderer即可
1 | mGLSurfaceView = (GLSurfaceView) findViewById(R.id.glsv_main); |