GLSurfaceView源码解析&EGL环境

发布时间:2024-01-24 06:54:57

目录

1.GLSurfaceView源码解析

1.1??setRenderer的实现

1.2?接下来我们看下GLThread的实现

1.3??GLThread的关键方法guardedRun?(渲染的核心逻辑)重点!

1.4?EglHelper又是什么呐?

2?TextureView?+EGL+?GLThread绘制图形


1.GLSurfaceView源码解析

**查看源码的原则:以常用的API为入口,依据地图、带着问题、沿着主线来寻找答案**

比如GLSurfaceView我们在使用时调用如下两个方法

-?setEGLContextClientVersion
-?setRenderer

随后的操作都是在Render的回调中处理

void?onSurfaceCreated(GL10?gl,?EGLConfig?config);
void?onSurfaceChanged(GL10?gl,?int?width,?int?height);
void?onDrawFrame(GL10?gl);

具体使用见上一篇?[?OpenGL?ES?绘制平面图形?]

我们今天的主角是EGL和GLThread,

1.1??setRenderer的实现

public?void?setRenderer(Renderer?renderer)?{
????//?1.?检查GLThread的状态,如果不为空,则抛出异常
????//即一个GLSurfaceView只能有一个GLThread
????checkRenderThreadState();
????//2.?生成?EGLConfig?对象.用于指定OpenGL颜色、深度、模版等设置
????if?(mEGLConfigChooser?==?null)?{
????????mEGLConfigChooser?=?new?SimpleEGLConfigChooser(true);
????}
????//3.?生成?EGLContext?对象.用于提供EGLContext创建和销毁的处理
????if?(mEGLContextFactory?==?null)?{
????????mEGLContextFactory?=?new?DefaultContextFactory();
????}
????//4.?生成?EGLSurface窗口对象.?用于提供EGLSurface创建和销毁的处理
????if?(mEGLWindowSurfaceFactory?==?null)?{
????????mEGLWindowSurfaceFactory?=?new?DefaultWindowSurfaceFactory();
????}
????//5.?开启?GLThread线程?
????mRenderer?=?renderer;
????mGLThread?=?new?GLThread(mThisWeakRef);
????mGLThread.start();
}

对象的含义

**EGLDisplay**?是对实际显示设备的抽象。

?**EGLSurface**?是对用来存储图像的内存区域FrameBuffer的抽象,包括Color?Buffer,?Stencil?Buffer?,Depth?Buffer.

?**EGLContext**??存储OpenGL?ES绘图的一些状态信息。

1.2?接下来我们看下GLThread的实现

static?class?GLThread?extends?Thread?{
????GLThread(WeakReference<GLSurfaceView>?glSurfaceViewWeakRef)?{
????????super();
????????...
????}

????@Override
????public?void?run()?{
????????setName("GLThread?"?+?getId());
????????if?(LOG_THREADS)?{
????????????Log.i("GLThread",?"starting?tid="?+?getId());
????????}

????????try?{
????????????guardedRun();
????????}?catch?(InterruptedException?e)?{
????????????//?fall?thru?and?exit?normally
????????}?finally?{
????????????sGLThreadManager.threadExiting(this);
????????}
????}
}

可以看到GLTread就是是一个Thread的子类,关键的处理逻辑在guardedRun()方法中,下面我们来看它的实现,这也是本篇的重点。

在guardedRun涉及了很多状态的同步问题,这个我们下一小节在来看

1.3??GLThread的关键方法guardedRun?(渲染的核心逻辑)重点!

图片来自[GLSurfaceView渲染过程详解

private?void?guardedRun(){
    //1.?创建EGLContext上下文
    mEglHelper.start();
    //2.?创建EGLSurface,本质是申请一块内存
?   mEglHelper.createSurface()
    //3.?获取GL对象,包装OpenGL?API环境
    mEglHelper.createGL()
    ---》Render执行渲染必须在EGLContext和EGLSurface生成并绑定后才能进行。
    //?这里就是Render的回调方法
    view.mRenderer.onSurfaceCreated(gl,?mEglHelper.mEglConfig);
    view.mRenderer.onSurfaceChanged(gl,?w,?h);
    view.mRenderer.onDrawFrame(gl);
    ---》Render渲染后的数据要想在视图窗口显示,必须调用eglSwapBuffers交换Framebuffer
    //opengl使用的双内存缓冲,一个进行显示,另一个则后台进行绘制,绘制OK后,交互内存进行显示
    mEglHelper.swap();
}

1.4?EglHelper又是什么呐?

从1.3中EglHelper的几个方法调用入手

public?void?start(){
????//1.?获取EGL对象
????mEgl?=?(EGL10)?EGLContext.getEGL();

????//2.?获取EGLDisplay即显示对象
????mEglDisplay?=?mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);

????//3.?初始化
????mEgl.eglInitialize(mEglDisplay,?version)

????//4.?egl配置
????//这里的mEGLConfigChooser是在setRenderer中实现的
????mEglConfig?=?view.mEGLConfigChooser.chooseConfig(mEgl,?mEglDisplay);
????//5.?创建EGL上下文.?EGLContext是用来链接渲染和视图窗口的上下文。
????//?注意:createContext()很耗资源
????mEglContext?=?view.mEGLContextFactory.createContext(mEgl,?mEglDisplay,?mEglConfig);
}

public?boolean?createSurface()?{
????//创建EGLsurface窗口
????//这里的mEGLWindowSurfaceFactory是在setRenderer中实现的
????mEglSurface?=?view.mEGLWindowSurfaceFactory.createWindowSurface(mEgl,mEglDisplay,?mEglConfig,?view.getHolder());

????????//将EGLSurface和EGLContext进行绑定
????????mEgl.eglMakeCurrent(mEglDisplay,?mEglSurface,?mEglSurface,??mEglContext)
}

GL?createGL()?{
????//创建EGL上下文的gl对下
????//GLSurfaceView的使用方在回调函数中接受,比如:onDrawFrame(GL10?gl)
????GL?gl?=?mEglContext.getGL();
}

public?int?swap()?{
????//通过切换前后Frame,实现Surface的展示
????mEgl.eglSwapBuffers(mEglDisplay,?mEglSurface)
}

2?TextureView?+EGL+?GLThread绘制图形

????????将GLSurfaceView内容全部复制出来,然后取消其继承和接口实现,将所有报错的代码删除掉,这样就相当于剔除了GLSurfaceView的SurfaceView而保留了它的GL环境,我们可以使用GLEnvironment来进行渲染,并自由的指定渲染载体,可以是SurfaceView/TextureView.

?我原本的想法是自己把整个流程以及状态的同步等都要自己实现一遍。

?看到来自[GLSurfaceView的简单分析及巧妙借用]?的思路,觉得比较高效省事,如果一上来就自己去实现GL环境,可能会有不少收获,但是也会踩不少坑,先学会使用,在学造轮子。


?

文章来源:https://blog.csdn.net/WolfKingzyh/article/details/135795287
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。