GLSurfaceView源码解析&EGL环境

目录

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环境,可能会有不少收获,但是也会踩不少坑,先学会使用,在学造轮子。


 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

新视图

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值