Android初始化OpenGL ES,并且分析Renderer子线程原理
来源:互联网 发布:口袋弹弓 淘宝 编辑:程序博客网 时间:2024/05/16 05:00
Android使用OpenGL ES需要搭配GLSurfaceView、Renderer,当然也可以使用TextureView,不过TextureView没有GLSurfaceView的OpenGL ES初始化操作,所以使用起来有些麻烦,需要自定义OpenGL初始化,本文使用GLSurfaceView初始化OpenGL ES。
首先讲一下Android中View,GLSurfaceView和TextureView等的区别吧
- View:显示视图,内置画布,提供图形绘制函数、触屏事件、按键事件函数等;必须在UI主线程内更新画面,速度较慢。
- SurfaceView:基于view视图进行拓展的视图类,更适合2D游戏的开发;是view的子类,类似使用双缓机制,在新的线程中更新画面,所以刷新界面速度比view快。其缺点是不能做变形和动画,也不能随屏幕的变化而变化,另外不能在其上面覆盖其它的SurfaceView。
- GLSurfaceView:是surfaceview的子类,在其基础上封装了egl环境管理,以及render线程。专用于3D游戏开发的视图,OpenGL ES专用。
- TextureView:它也是继承自View,只能运行中硬件加速窗口。它的功能类似于SurfaceView + SurfaceTexture,它内部包含一个SurfaceTexture,它可以让Camera的数据和显示分离,比如需要做二次处理时,如Camera吧采集的数据发送给SurfaceTexture(比如做个美颜),SurfaceTexture处理后传给TextureView显示。TextureView可以做view的变形和动画。一般它是在主线程上做处理(在Android 5.0引入渲染线程后,它是在渲染线程中做的)。
初始化OpenGL
一般步骤如下:
- 创建GLSurfaceView实例
- 检查设备是否支持OpenGL ES 2.0
- 配置OpenGL ES
- 创建Renderer
前三步的代码可参考如下:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //实例化一个GLSurfaceView mGLSurfaceView = new GLSurfaceView(this); //检查设备是否支持OpenGL ES 2.0 final ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE); final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo(); final boolean supportES2 = configurationInfo.reqGlEsVersion >= 0x00020000; //配置OpenGL ES,主要是版本设置和设置Renderer,Renderer用于执行OpenGL的绘制 if (supportES2) { mGLSurfaceView.setEGLContextClientVersion(2); mGLSurfaceView.setRenderer(new MyRenderer()); renderSet = true; } else { Toast.makeText(getApplicationContext(),"不支持OpenGL ES 2.0版本",Toast.LENGTH_SHORT).show(); return; } //在屏幕上显示GLSurfaceView setContentView(mGLSurfaceView); }
创建Renderer渲染器的代码如下:
public class MyRenderer implements GLSurfaceView.Renderer { //当Surface创建后会调用此方法 @Override public void onSurfaceCreated(GL10 gl, EGLConfig config) { glClearColor(1.0f,0.0f,0.0f,0.0f);//清空屏幕的颜色,本例为红色 } //当Surface创建成功或尺寸改变时都调用此方法 @Override public void onSurfaceChanged(GL10 gl, int width, int height) { glViewport(0,0,width,height); } //每绘制一帧都会调用此方法 @Override public void onDrawFrame(GL10 gl) { //清空颜色缓冲区,然后使用glClearColor()方法设置填充屏幕的颜色 glClear(GL_COLOR_BUFFER_BIT); } }
GL10 gl这个参数是OpenGL ES 1.0遗留下来的,如果使用OpenGL ES 2.0以上版本可以忽略它
现在运行起来屏幕会显示空白的红色窗口,初始化OpenGL就是这么简单
Renderer子线程原理
之前讲了GLSurfaceView是在新的线程更新画面,也就是执行Renderer,现在通过源码来分析一下是如何做到的。
首先我们给GLSurfaceView设置Renderer渲染器是通过下面这个方法。
mGLSurfaceView.setRenderer(new MyRenderer());
我们进到此方法中,发现它会创建一个GLThread线程并启动
public void setRenderer(Renderer renderer) { ...... //将renderer赋值给GLSurfaceView的实例变量mRenderer mRenderer = renderer; mGLThread = new GLThread(mThisWeakRef); mGLThread.start(); }
mThisWeakRef是此GLSurfaceView的一个虚引用,防止内存泄露,它是GLSurfaceView的一个实例变量
private final WeakReference<GLSurfaceView> mThisWeakRef = new WeakReference<GLSurfaceView>(this);
GLThread线程的run方法会执行guardedRun()方法
@Override public void run() { ...... try { guardedRun(); } catch (InterruptedException e) { // fall thru and exit normally } finally { sGLThreadManager.threadExiting(this); } }
guardedRun方法里面首先会创建一个EglHelper实例,它是用来初始化EGL环境配置的,然后启动一个无限循环
private void guardedRun() throws InterruptedException { mEglHelper = new EglHelper(mGLSurfaceViewWeakRef); while (true) { ...... }}
这个无限循环里面东西很多,核心为一下几块:
- 初始化EGL环境配置,
mEglHelper = new EglHelper(mGLSurfaceViewWeakRef);......try { mEglHelper.start();//} catch (RuntimeException t) { sGLThreadManager.releaseEglContextLocked(this); throw t;}mHaveEglContext = true;createEglContext = true;
- 执行Renderer的onSurfaceCreated方法
//如果EGL环境配置好了,会执行onSurfaceCreated()方法,这个方法实际使用时可能会被多次调用,比如设备被唤醒或从别的Activity切换到此Activity时if (createEglContext) { //mGLSurfaceViewWeakRef就是前面的mThisWeakRef,它是GLThread构造函数里面设置的,通过mGLSurfaceViewWeakRef获取到所指的GLSurfaceView GLSurfaceView view = mGLSurfaceViewWeakRef.get(); if (view != null) { try { view.mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } } createEglContext = false;}
- 执行Renderer的onSurfaceChanged方法
当Surface的尺寸改变时就会调用onSurfaceChanged()方法
if (sizeChanged) { GLSurfaceView view = mGLSurfaceViewWeakRef.get(); if (view != null) { try { view.mRenderer.onSurfaceChanged(gl, w, h); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } } sizeChanged = false;}
- 执行Renderer的onDrawFrame方法
它是在代码块中执行的,也就是说每绘制一帧时都会执行onDrawFrame()方法
{ GLSurfaceView view = mGLSurfaceViewWeakRef.get(); if (view != null) { try { view.mRenderer.onDrawFrame(gl); } finally { Trace.traceEnd(Trace.TRACE_TAG_VIEW); } }}
- Android初始化OpenGL ES,并且分析Renderer子线程原理
- 在Android下初始化Native OpenGL ES
- Android Dev Intro - An OpenGL ES renderer based on the GLSurfaceView rendering framework
- opengl es 初始化及android切后台opengl上下文丢失
- openGl ES初始化
- android.opengl.GLSurfaceView.Renderer概述
- Android OpenGL ES 分析与实践
- Android OpenGL ES 分析与实践
- Android OpenGL ES 分析与实践(1)
- Android OpenGL ES 分析与实践(2)
- Android OpenGL ES 分析与实践(4)
- Android OpenGL ES 分析与实践 (3)
- Android OpenGL ES 分析与实践(5)
- Android OpenGL ES 分析与实践(6)
- Android OpenGL ES 分析与实践
- Android OpenGL ES 分析与实践
- OpenGL ES Tutorial - lesson 1 : 认识GLSurfaceView & Renderer
- OpenGL ES Tutorial - lesson 1 : 认识GLSurfaceView & Renderer
- 四则(栈or二叉树)
- css3:-webkit-box
- OC学习记录2:数组
- 算法分析与设计第四周:513. Find Bottom Left Tree Value
- 快速排序
- Android初始化OpenGL ES,并且分析Renderer子线程原理
- 二进制中负数的表示
- aaa
- 抽象类的应用
- POJ 1014
- HRBUST
- HDU-1584-蜘蛛牌(DFS)
- Scanner及String类总结
- php内存管理之垃圾回收机制