美文网首页
GLsurfaceview 源码分析

GLsurfaceview 源码分析

作者: mfdalf | 来源:发表于2021-03-27 21:40 被阅读0次

    目录

    1 GLsurfaceview 的定义和作用

    2 GLsurfaceview 使用

    3 GLsurfaceview 源码分析

    正文

    1 GLsurfaceview定义&作用:

    GLSurfaceView继承于SurfaceView,主要用于配合OpenGL ES的接口执行渲染窗口的任务。
    GLsurfaceview=surfaceview+surfaceTexture+opengl+eglhelper.
    (surface,surfaceview,surfaceTexture说明请点这里).

    2 GLsurfaceview 使用:

    下面是标准使用流程,引用自:https://blog.csdn.net/MarRn/article/details/100897530

    1)、在layout文件中使用android.opengl.GLSurfaceView,代码如下:

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <android.opengl.GLSurfaceView
            android:id="@+id/surfaceview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </RelativeLayout>
    

    2)、自定义Renderer
    其中onDrawframe 编写glsl脚本(shader)

    public class TestRenderer implements GLSurfaceView.Renderer{
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
                    ...
        }
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            //设置窗口大小
            GLES20.glViewport(0, 0, width, height);
        }
        public void onDrawFrame(GL10 gl) {
            //执行清屏
            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
            GLES20.glClearColor(0.0f, 0.1f, 0.0f, 1.0f);
        }
    }
    

    3)、给GLSurfaceView设置Renderer

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_activity);
        glSurfaceView = (GLSurfaceView)findViewById(R.id.surfaceview);
        TestRenderer renderer = new TestRenderer();
        glSurfaceView.setRenderer(renderer);
    }
    

    小结:camera 采集-->回调到surface(buffer)-->render渲染输出到屏幕(surfaceview在xml中config的.)

    3 GLsurfaceview类的组成 :

    GLThread内部类:OpenGL ES的运行线程。包含创建EGL环境、调用GLRender的onSurfaceCreated、onSurfaceChanged和onDrawFrame方法以及生命周期的管理。
    EglHelper内部类:负责创建EGL环境。包括start,createSurface,swap等.
    GLSurfaceView:负责提供Surface和状态改变。

    image

    4 源码分析

    4.1 Init

    public class GLSurfaceView extends SurfaceView implements SurfaceHolder.Callback2 {
        //1=================================
      private static final GLThreadManager sGLThreadManager = new GLThreadManager();//多个GLthread共享
        private GLThread mGLThread; // GL 线程
        private Renderer mRenderer; // GLSurfaceView 的回调接口
        public void setRenderer(Renderer renderer) { // 设置渲染接口
        mEGLConfigChooser = new SimpleEGLConfigChooser(true);
        mEGLContextFactory = new DefaultContextFactory();
        mEGLWindowSurfaceFactory = new DefaultWindowSurfaceFactory();
            mRenderer = renderer;
            mGLThread = new GLThread(mThisWeakRef);
            mGLThread.start();
        }
       //2===GLsurfaceview接口仅仅是个wrapper,真正执行的是GLthread对应函数=================
        //set mHasSurface=true
       public void surfaceCreated(SurfaceHolder holder) {
            mGLThread.surfaceCreated();
        }
        //set width&height
       public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
            mGLThread.onWindowResize(w, h);
        }   
        public void requestRender() {
            mGLThread.requestRender();
        }
        public void queueEvent(Runnable r) {
            mGLThread.queueEvent(r);
        }
        //3=========================
        private static class DefaultWindowSurfaceFactory implements EGLWindowSurfaceFactory {
            public EGLSurface createWindowSurface(EGL10 egl, EGLDisplay display,EGLConfig config, Object nativeWindow) {
                EGLSurface result = null;
                result = egl.eglCreateWindowSurface(display, config, nativeWindow, null);
                return result;
            }
        }
    }
    
    

    4.2 EglHelper内部类: wrapper egl 操作,负责创建EGL环境

     /*An EGL helper class.*///egl=display+context+surface  
    //create egl surface&context&opengl,swap surface to target
        private static class EglHelper {
            public EglHelper(WeakReference<GLSurfaceView> glSurfaceViewWeakRef) {
                mGLSurfaceViewWeakRef = glSurfaceViewWeakRef;
            }
            //1===========
            public void start() {
                /*Get an EGL instance */
                mEgl = (EGL10) EGLContext.getEGL();
                /*Get to the default display.*/
                mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
                /*We can now initialize EGL for that display   */
                int[] version = new int[2];
                mEgl.eglInitialize(mEglDisplay, version)
                GLSurfaceView view = mGLSurfaceViewWeakRef.get();
                mEglConfig = view.mEGLConfigChooser.chooseConfig(mEgl, mEglDisplay);//颜色、深度、模板等等设置
                mEglContext = view.mEGLContextFactory.createContext(mEgl, mEglDisplay, mEglConfig);
                mEglSurface = null;
            }
            //2=============
            public boolean createSurface() {
                /*Create an EGL surface we can render into.   */
                GLSurfaceView view = mGLSurfaceViewWeakRef.get();
    mEglSurface=view.mEGLWindowSurfaceFactory.createWindowSurface(mEgl,mEglDisplay, mEglConfig,view.getHolder());
                //绑定context和surface
                mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)
            }
            //3============
            GL createGL() {
                GL gl = mEglContext.getGL();
                GLSurfaceView view = mGLSurfaceViewWeakRef.get();
                return gl;
            }
            //4 /*Display the current render surface.*/
            public int swap() {
               mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)
            }
            private WeakReference<GLSurfaceView> mGLSurfaceViewWeakRef;
        }
    

    4.3 GLthread

    Render框架:onSurfaceCreated(),onSurfaceChanged(),onDrawFrame()。
    onSurfaceCreated() :在开始渲染的时候被调用,无论什么时候OpenGL ES 渲染不得不重新被创建.
    onSurfaceChanged():该方法在surface大小改变时被调用。
    onDrawFrame():每帧的时候该方法都会被调用.

    1 ) 调用guardedRun

    static class GLThread extends Thread {
        private EglHelper mEglHelper; // EGL环境的帮助类
        private ArrayList<Runnable> mEventQueue = new ArrayList<Runnable>();//event queue是每个GLthread 私有
        private WeakReference<GLSurfaceView> mGLSurfaceViewWeakRef;
        // 构造函数
        GLThread(WeakReference<GLSurfaceView> glSurfaceViewWeakRef) {
              ......
             mGLSurfaceViewWeakRef = glSurfaceViewWeakRef;
        }
        public void run() {
            //最最最重要的逻辑
            guardedRun();
    }
    

    2 ) guardedRun() 函数

    处理两种情况:
    scenario1: camera 采集自动回调.frameAvailale新来一帧: GLsurfaceview.requestrender--- onDrawFrame.
    scenario2: GLsurfaceView手动执行opengl(filter)操作: GLsurfaceview.queueEvent.add(r)--- GLsurfaceview.queueEvent.remove(r)&r.run

    流程图:


    image

    a) ReadyToDraw: 当发送GLsurfaceview.requestRender的时候,mRequestRender=true,

    // 判断是否准备好开始 draw
    private boolean readyToDraw() {
                return (!mPaused) && mHasSurface && (!mSurfaceIsBad)
                    && (mWidth > 0) && (mHeight > 0)
                    // 如果是 RENDERMODE_CONTINUOUSLY 渲染模式,则不需要调用 requestRender() 也会一直调用onDrawFrame() 进行渲染
                    && (mRequestRender || (mRenderMode == RENDERMODE_CONTINUOUSLY));
            }
    

    b) 两个线程同步实现 (重点)

    发送端:
    requestRender:收到camera采集数据,设置画图开关&唤醒线程。

        /*Request that the renderer render a frame. *///设置开关&唤醒线程
         public void requestRender() {
                synchronized(sGLThreadManager) {
                    mRequestRender = true;
                    sGLThreadManager.notifyAll();
                }
            }
    

    QueueEvent: 由于操作 OpenGL 环境只能通过 GL线程,所以GLSurfaceView 提供了 queueEvent() 函数,将待执行的 runnable 添加到 GLThread 中的队列中。

        /*Queue a runnable to be run on GL rendering thread.Renderer communicate with it on the rendering thread*/
    //入参就是一个runnable 线程实体
            //向queue添加runnable task&唤醒线程
            public void queueEvent(Runnable r) {
                synchronized(sGLThreadManager) {
                    mEventQueue.add(r);
                    sGLThreadManager.notifyAll();
                }
            }
    

    UI线程运行上面两个函数之后,任务完成。后面画图工作是另一个线程GLthread处理.

    接收端:
    核心内容: 双循环

            private void guardedRun() throws InterruptedException { 
                mEglHelper = new EglHelper(mGLSurfaceViewWeakRef);//创建Eglhelper类
                    while (true) {//外循环处理业务逻辑event.run和ondrawframe
                        synchronized (sGLThreadManager) {
                            while (true) {//内循环两种消息路由
                                //scenario1: step1 读取GLsurfaceview.queueevent发送的task,然后退出内循环
                                if (! mEventQueue.isEmpty()) {
                                    event = mEventQueue.remove(0);
                                    break;
                                }
                                if (readyToDraw()) {//requestRender
                                    // If we don't have an EGL context, try to acquire one.
                                    if (! mHaveEglContext) {//只第一次执行
                                            mEglHelper.start();//
                                            mHaveEglContext = true;
                                            createEglContext = true;
                                            sGLThreadManager.notifyAll();
                                    }
                                    if (mHaveEglContext && !mHaveEglSurface) {//只第一次执行
                                        mHaveEglSurface = true;
                                        createEglSurface = true;
                                        createGlInterface = true;
                                        sizeChanged = true;
                                    }
                                    //scenario2的情况每次都会执行
                                    if (mHaveEglSurface) {
                                        ......          
                                        //===scenario2:requestRender--onDrawFrame.
                                        //==step1  退出内循环&唤醒GLsurfaceView所有GLthread
                                        mRequestRender = false;
                                        sGLThreadManager.notifyAll();
                                        break;
                                    }
                                } 
                                //==scenario1: step3  阻塞,线程同步:等待queueevent;==
                                sGLThreadManager.wait();
                            }//内循环end
                        } // end of synchronized(sGLThreadManager)
                        //===scenario1: step2 运行GLsurfaceview.queueevent (runnable)===
                        if (event != null) {
                            event.run();
                            event = null;
                            continue;
                        }
                        if (createEglSurface) {//只第一次执行
                           mEglHelper.createSurface()
                           createEglSurface = false;
                        }
                        if (createGlInterface) {//只第一次执行
                            gl = (GL10) mEglHelper.createGL();
                            createGlInterface = false;
                        }
                        if (createEglContext) {//只第一次执行
                            GLSurfaceView view = mGLSurfaceViewWeakRef.get();
                            view.mRenderer.onSurfaceCreated(gl, mEglHelper.mEglConfig);
                            createEglContext = false;
                        }
                    //==scenario2: step2 外循环的时候每次都执行。
                    GLSurfaceView view = mGLSurfaceViewWeakRef.get();
                    view.mRenderer.onDrawFrame(gl);
                    //scenario2: step3 onDrawFrame中opengl将数据画到suface,这句是将surface上数据画到display(双缓冲surface,是前后surface交换,前端surface即是display)
                    int swapError = mEglHelper.swap();
                    switch (swapError) {
                        case EGL10.EGL_SUCCESS:
                            break;
                        ......
                    }
                } 
    

    附录:GLsurfaceview 源码
    参考:
    Android Camera开发:使用GLSurfaceView预览Camera 基础拍照https://blog.csdn.net/yanzi1225627/article/details/33339965
    Android Camera使用OpenGL ES 2.0和GLSurfaceView对预览进行实时二次处理(黑白滤镜):https://blog.csdn.net/lb377463323/article/details/77071054
    [-综合篇-] 相机、OpenGL、视频、Flutter和SurfaceView:https://www.imooc.com/article/293406
    Android: Camera相机开发详解(中) ——实现预览、拍照、保存照片等功能 https://www.jianshu.com/p/e20a2ad6ad9a
    GLSurfaceView 源码分析 & EGL 创建过程 https://www.pianshen.com/article/8421310032/

    相关文章

      网友评论

          本文标题:GLsurfaceview 源码分析

          本文链接:https://www.haomeiwen.com/subject/rgayhltx.html