Opengl ES(三)环境搭建

Opengl ES基础系列文章是音视频学习的图形图像部分,旨在通过这部分学习,能够把Opengl ES和视频结合在一起,最终形成一个完整的知识体系。       

在Android开发中使用Opengl ES进行图形、图像绘制,需要一系列的配置才可以进行,而且,在Opengl ES开发中,需要明白以下几点:

1)Opengl ES绘制是居于状态的,通过EGLContext进行状态管理;

2)Opengl ES是和当前线程相关的,一个EGLContext对象只能关联到一个线程;

3)如果需要绘制到屏幕上,需要关联屏幕的Surface;

首先我们看下在Android中进行Opengl ES开发有几种方式。

GLSurfaceView

使用GLSurfaceView,只需要实现GLSurfaceView.Render接口,我们就可以在onDrawFrame里使用Opengl ES绘制图形、图像,Opengl ES相关的环境由GLSurfaceView自动为我们建立,我们只负责绘制就可以。

另外GLSurfaceView是继承于SurfaceView的,因此,其内部实现就是单独开启一个线程来进行绘制,最终提交到SurfaceView的Surface进行显示。

自定义方式

这种方式需要对Opengl ES进行配置,自己建立环境,管理绘制线程,虽然麻烦,但是其定制的自由度很高,最终呈现的Surface也不仅仅是SurfaceView来实现,还可以呈现在TextureView上等,非常灵活,这也是本节我们重点介绍的。

首先,大家先看看下图,其描述了一个标准的EGL程序需要做的准备工作有那些。


 从上图我们总结一下,使用EGL需要的步骤以及使用中需要注意的问题。

1)获取默认的显示设备(默认显示设备一般是0号设备);
2)使用获取的显示设备初始化EGL;
3)配置我们获取的显示设备(比如颜色模式等);
4)创建EGL的上下文EGLContext(所有的绘制状态都保存在EGLContext中);
5)创建绘制内容放置的Surface(把它理解为一块连续的内存);
6)把EGL上下文关联到当前线程的TLS(就是把EGLContext存储在线程局部存储器中);

经过上述步骤后,Opengl ES的绘制环境已经准备好了,现在可以进行绘制了,上面我们说过,Opengl ES是居于状态管理的,而上图中的第四步创建的EGLContext就是管理绘制状态的,而这个EGLContext是通过eglMakeCurrent来把其设置到当前线程的TLS中,这样,每次调用Opengl ES相关API时,会通过线程的TLS来获取到EGLContext对象,进而获取到当前我们需要操作的对象(比如当前设置的纹理对象),所以,如果当前线程没有关联任何EGLContext,是不能操作绘制相关的API的,这就是为什么Opengl ES是线程相关的,而且在不共享的情况下不能跨线程操作Opengl ES的道理(关于怎么样在多线程共享Opengl ES的对象,后续章节会讲)。
    
下面总结下Opengl ES绘制环境准备阶段需要注意如下几点:

1)一定要设置使用Opengl ES版本号(否则系统不知道我们用哪个版本);

2)内容放置的Surface有两种:设备表面和离屏渲染;

3)一定要把EGLContext关联到当前线程,其实,就是把EGLContext对象设置到当前线程的TLS;

4)Opengl ES绘制是基于状态的(状态保存在EGLContext);

相关API介绍

int eglGetDisplay(int display_id);

  •   参数
一般取值EGL_DEFAULT_DISPLAY,获取默认显示设备

  •   返回值
EGL显示设备号,默认显示设备一般是0;

  •   描述
获取默认的显示设备,通常情况下返回0(0号设备);

EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint*minor);

  •   参数
dpy:通过eglGetDisplay获取的显示设备号;
 major:EGL的主版本号;
minor:EGL的副版本号;

  •   返回值
成功返回true;否则false;

  •   描述
初始化显示设备,获取系统中 EGL 的实现版本号,注意这是EGL的版本号,不是Opengl ES的版本;

EGLBoolean eglChooseConfig(EGLDisplay dpy,const EGLint *attrib_list, EGLConfig *configs, EGLint config_size,EGLint * num_config);

  •   参数
dpy:通过eglGetDisplay获取的显示设备号;
attrib_list:属性参数列表,使用其来选中符合的config;
configs:配置参数;
config_size:配置参数的大小;
num_config:配置参数的个数

  •   返回值
成功返回true;否则false;

  •   描述
使用指定的显示参数配置显示设备,比如颜色模式等,其中attr_list是以EGL_NONE结束的参数数组;

GLAPI EGLContext APIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list ) ;

  •   参数
dpy:通过eglGetDisplay获取的显示设备号;
config:配置参数;
share_context:共享上下文(share_context所在线程能访问本EGLContext关联线程的Opengl ES对象)
attrib_list:属性参数列表

  •   返回值
EGLContext ,保存绘制状态;

  •   描述
创建Opengl ES显示上下文,操作以及状态都会记录在此上下文中。
       
GLAPI EGLBoolean APIENTRY eglMakeCurrent(EGLDisplaydpy, EGLSurface draw,  EGLSurface read,EGLContext ctx);

  •   参数
dpy:通过eglGetDisplay获取的显示设备号;
draw:绘制的Surface;
read:读取的Surface;
ctx:eglCreateContext创建的上下文;

  •   返回值
成功返回true;否则false;

  •   描述
把EGLContext关联到当前线程,这里其实就是设置到当前线程的TLS中,这样,我们执行Opengl ES相关操作的时候,就会从当前线程取出EGLContext,这就是为什么一定要调用这个函数的原因。

好了,到这里就把怎么样搭建Opengl ES绘制的环境讲完了,注意,上面介绍的EGL接口是native层的接口描述,Android层是经过封装的,会有点差别,但是大体一致,主要是参数类型的转换等,另外还有一些函数没有介绍,比如查询配置参数、创建窗口相关Surface的API,后续实际项目会具体介绍。

关于Opengl ES准备工作已经完成,下一节,开始我们真正的Opengl ES的实际项目吧。

本系列文章均为原创,主要总结作者多年在软件行业的一些经验,和大家共同学习、进步,转载请注明出处,谢谢!
来源:CSDN,作者:会说话的小鱼,转载此文目的在于传递更多信息,版权归原作者所有。
原文:https://blog.csdn.net/china0851/article/details/85156157
版权声明:本文为博主原创文章,转载请附上博文链接!

最新文章