GLsurfaceview 源码分析

目录

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,代码如下:


    

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和状态改变。

GLsurfaceview 源码分析_第1张图片
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 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 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 mEventQueue = new ArrayList();//event queue是每个GLthread 私有
    private WeakReference mGLSurfaceViewWeakRef;
    // 构造函数
    GLThread(WeakReference 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

流程图:


GLsurfaceview 源码分析_第2张图片
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 源码分析)