OpenGL ES是是一个开源图形库,那么与之相关的需要一个东西去显示画面,在android里,opengl包里提供了一个View叫GLSurfaceView,它的定义如下:
An implementation of SurfaceView that uses the dedicated surface fordisplaying OpenGL rendering.
它的特性如下:
Manages a surface, which is a special piece of memory that can be composited into the Android view system. Manages an EGL display, which enables OpenGL to render into a surface. Accepts a user-provided Renderer object that does the actual rendering. Renders on a dedicated thread to decouple rendering performance from the UI thread. Supports both on-demand and continuous rendering. Optionally wraps, traces, and/or error-checks the renderer’s OpenGL calls.可见系统已封装好一个View用于渲染画面并能进行相应设置。
使用步骤如下:1.创建定义一个GLSurfaceView2.调用GLSurfaceView的setEGLContextClientVersion设置版本号,可设为23.onResume 和 onPause分别调用GLSurfaceView相应的生命周期方法4.调用GLSurfaceView的setRender设置自己实现GLSurfaceView.Render接口的类5.Render接口有3个方法,分别是SurfaceCreated时候进行相应的初始化工作,SurfaceChange时候高宽的适配以及具体的DrawFrame方法
onSurfaceCreated(GL10 gl, EGLConfig config); onSurfaceChanged(GL10 gl, int width, int height); onDrawFrame(GL10 gl);GLSurfaceView详细分析:1.GLSurfaceView在构造函数中调用init()设置如上3个回掉函数
private void init() { SurfaceHolder holder = getHolder(); holder.addCallback(this); }
2.setRender会进行一些默认的设置,并生成一个GLThread的线程进行渲染绘制相关操作,绘制的内容默认情况下依旧是绘制到SurfaceView所提供的Surface上
public void setRenderer(Renderer renderer) { checkRenderThreadState(); if (mEGLConfigChooser == null) { mEGLConfigChooser = new SimpleEGLConfigChooser(true); } if (mEGLContextFactory == null) { mEGLContextFactory = new DefaultContextFactory(); } if (mEGLWindowSurfaceFactory == null) { mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory(); } mRenderer = renderer; mGLThread = new GLThread(mThisWeakRef); mGLThread.start(); }
3.GLThread的run()方法里调用了guardedRun()方法,在guardedRun方法里new 了一个EglHelper类,并在一段逻辑判断后调用了EglHelper的start方法。
4.EglHelper.start()方法里
public void start() { mEgl = (EGL10) EGLContext.getEGL(); mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { throw new RuntimeException('eglGetDisplay failed'); } int[] version = new int[2]; if(!mEgl.eglInitialize(mEglDisplay, version)) { throw new RuntimeException('eglInitialize failed'); } GLSurfaceView view = mGLSurfaceViewWeakRef.get(); if (view == null) { mEglConfig = null; mEglContext = null; } else { mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay); mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig); } ...}
这里有如下几个重要方法,最终会调用到C++层去初始化相关的渲染界面
EGLContext.getEGL() eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY) eglInitialize(mEglDisplay, version) createContext()5.在guardedRun() start()调用后会调用EglHelper.createSurface()方法,最终也会调用到C++层。
public boolean createSurface() {//Check preconditions.//window size has changed, create a new surface.destroySurfaceImp();//Create an EGL surface we can render into. GLSurfaceView view = mGLSurfaceViewWeakRef.get(); if (view != null) { mEglSurface = view.mEGLWindowSurfaceFactory.createWindowSurface(mEgl, mEglDisplay, mEglConfig, view.getHolder()); } else {mEglSurface = null;} ... int error = mEgl.eglGetError();... if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { logEglErrorAsWarning('EGLHelper', 'eglMakeCurrent', mEgl.eglGetError()); return false; } return true;} createWindowSurface eglGetError eglMakeCurrentEGL相关知识
EGL用于管理绘图表面,有如下机制
与设备的原生窗口系统通信 查询绘图表面的可用类型和配置 创建绘图表面 在OpenGL ES 3.0和其他图形渲染API之间同步渲染 管理纹理贴图等渲染资源EGLDisplay:由于每个窗口系统都有不同的语义,所以EGL提供基本的不透明类型EGLDisplay,封装了所有系统相关性,用于和原生窗口系统接口
EGL有如下一些方法:
EGLDisplay eglGetDisplay(Object native_display);1.打开与EGL显示服务器的链接打开与EGL显示服务器的链接2.native_display是一个displayId,指定显示链接,默认链接为EGL_DEFAULT_DISPLAY
boolean eglInitialize(EGLDisplay display, int[] major_minor)1.打开链接后,需要初始化EGL2.display:getDisplay返回的值3.主次版本号
boolean eglChooseConfig(EGLDisplay display, int[] attrib_list, EGLConfig[] configs, int config_size, int[] num_config);1.让EGL选择匹配的EGLConfig2.具体就是调用选择配置,配置细节暂不叙述
EGLContext eglCreateContext(EGLDisplay display, EGLConfig config, EGLContext share_context, int[] attrib_list);1.创建渲染上下文2.display:指定的显示链接3.config:指定的配置4.share_context:允许多个EGL上下文共享特定类型的数据;使用EGL_NO_CONTEXT表示没有共享5.attrib_list:指定创建上下文使用的属性列表;只有一个可接受的属性:EGL_CONTEXT_CLIENT_VERSION表示指定与你所使用的OpenGL ES版本6.eglCreateContext成功时,它返回一个指向新创建上下文的句柄。
EGLSurface eglCreateWindowSurface(EGLDisplay display, EGLConfig config, Object native_window, int[] attrib_list);1.有了符合渲染要求的EGLConfig,就可调用此函数创建一个窗口2.属性同上
int eglGetError();1.EGL函数成功时返回EGL_TRUE,否则返回EGL_FALSE。如果需要查询故障原因,调用eglGetError()得到返回错误码。
boolean eglMakeCurrent(EGLDisplay display, EGLSurface draw, EGLSurface read, EGLContext context);1.因一个应用程序可能创建多个EGLContext用于不同的用途,所以需要关联特定的EGLContext和渲染表面即:指定当前上下文
整个大概流程就如上所述调用下来。
以上就是Android OpenGL入门之GLSurfaceView的详细内容,更多关于Android GLSurfaceView的资料请关注乐呵呵网其它相关文章!