4.OpenglES——自定义GLSurfaceView

参考:自定义GLSurfaceView
GLSurfaceView的简单分析及巧妙借用

书写本文的初衷是为了自我学习

关于GLSurfaceView

GLSurfaceView继承了SurfaceView,实现了SurfaceHolder.Callback2接口。
SurfaceView在View的基础上是创建了独立的Surface,拥有SurfaceHolder来管理它的Surface,渲染的工作可以不再在主线程中做了。可以通过SurfaceHolder得到Canvas,在单独的线程中,利用Canvas绘制需要显示的内容,然后更新到Surface上。
而GLSurfaceView,它主要是在SurfaceView的基础上实现了一个GLThread(EGLContext创建GL环境所在线程即为GL线程),绘制的工作直接通过OpenGL来进行,绘制的内容默认情况下依旧是绘制到SurfaceView所提供的Surface上。
参照GLSurfaceView的实现,我们可以自行创建GL环境,来进行GL渲染。实现自行制定指定载体、后台渲染等功能。

自定义GLSurfaceView

因此我们只需要实现GLSurfaceView实现的功能就完成了自定义的GLSurfaceView.

1、继成SurfaceView,并实现其CallBack回调。

2、自定义GLThread线程类,主要用于OpenGL的绘制操作,调用Render渲染器。

3、添加设置Surface和EglContext的方法。

4、提供和系统GLSurfaceView相同的调用方法。
6、Render渲染器接口。

代码分析

实现原理:
1.EglSurfaceView继承了SurfaceView,实现了SurfaceHolder.Callback,创建GLThread线程,Render接口
2.EGLRender实现了EglSurfaceView中的Render接口
3.EGLActivity入口activity
代码查看顺序:
EGLActivity->.EglSurfaceView->EGLRender
然后看一下该类的内容 4.OpenglES——自定义GLSurfaceView_第1张图片

可以看到,该类创建了EGLThread线程,Render接口,并持有一个Surface。
这是因为EGLThread线程调用实现了Render接口的渲染器对象,这个渲染器对象绘制的内容,通过Surface呈现出来。

以下展示代码:

public class EglSurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    private Render mRenderer;
    private EGLThread mEGLThread;
    private Surface mSurface;
    private EGLContext mEglContext;


    public final static int RENDERMODE_WHEN_DIRTY = 0;
    public final static int RENDERMODE_CONTINUOUSLY = 1;
    private int mRenderMode = RENDERMODE_WHEN_DIRTY;


    public EglSurfaceView(Context context) {
        this(context, null);
    }

    public EglSurfaceView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public EglSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        SurfaceHolder holder = getHolder();
        holder.addCallback(this);
    }


    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if (mSurface == null) {
            mSurface = holder.getSurface();
        }
        mEGLThread = new EGLThread(new WeakReference<>(this));
        mEGLThread.isCreate = true;
        mEGLThread.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        mEGLThread.width = width;
        mEGLThread.height = height;
        mEGLThread.isChange = true;
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mEGLThread.onDestroy();
        mEGLThread = null;
        mSurface = null;
        mEglContext = null;
    }

    public void setRender(Render mRenderer) {
        this.mRenderer = mRenderer;
    }

    public void setRenderMode(int renderMode) {
        this.mRenderMode = renderMode;
    }

    public void requestRender() {
        if (mEGLThread != null) {
            mEGLThread.requestRender();
        }
    }

    public void setSurfaceAndEglContext(Surface surface, EGLContext eglContext) {
        this.mSurface = surface;
        this.mEglContext = eglContext;
    }

    public EGLContext getEglContext() {
        if (mEGLThread != null) {
            return mEGLThread.getEglContext();
        }
        return null;
    }


    private static class EGLThread extends Thread {


        EGLThread(WeakReference<EglSurfaceView> eGLSurfaceViewWeakRef) {
            this.mEGLSurfaceViewWeakRef = eGLSurfaceViewWeakRef;
        }

        @Override
        public void run() {
            super.run();
            try {
                guardedRun();
            } catch (Exception e) {
                // fall thru and exit normally
            }
        }

        private void guardedRun() throws InterruptedException {
            isExit = false;
            isStart = false;
            object = new Object();
            mEglHelper = new EglHelper();
            mEglHelper.initEgl(mEGLSurfaceViewWeakRef.get().mSurface, mEGLSurfaceViewWeakRef.get().mEglContext);

            while (true) {
                if (isExit) {
                    //释放资源
                    release();
                    break;
                }

                if (isStart) {
                    if (mEGLSurfaceViewWeakRef.get().mRenderMode == RENDERMODE_WHEN_DIRTY) {
                        synchronized (object) {
                            object.wait();
                        }
                    } else if (mEGLSurfaceViewWeakRef.get().mRenderMode == RENDERMODE_CONTINUOUSLY) {
                        Thread.sleep(1000 / 60);
                    } else {
                        throw new IllegalArgumentException("renderMode");
                    }
                }

                onCreate();
                onChange(width, height);
                onDraw();
                isStart = true;
            }

        }

        private void onCreate() {
            if (!isCreate || mEGLSurfaceViewWeakRef.get().mRenderer == null)
                return;

            isCreate = false;
            mEGLSurfaceViewWeakRef.get().mRenderer.onSurfaceCreated();
        }

        private void onChange(int width, int height) {
            if (!isChange || mEGLSurfaceViewWeakRef.get().mRenderer == null)
                return;

            isChange = false;
            mEGLSurfaceViewWeakRef.get().mRenderer.onSurfaceChanged(width, height);
        }

        private void onDraw() {
            if (mEGLSurfaceViewWeakRef.get().mRenderer == null)
                return;

            mEGLSurfaceViewWeakRef.get().mRenderer.onDrawFrame();
            //第一次的时候手动调用一次 不然不会显示ui
            if (!isStart) {
                mEGLSurfaceViewWeakRef.get().mRenderer.onDrawFrame();
            }

            mEglHelper.swapBuffers();
        }

        void requestRender() {
            if (object != null) {
                synchronized (object) {
                    object.notifyAll();
                }
            }
        }

        void release() {
            isExit = true;
            //释放锁
            requestRender();
        }

        void onDestroy() {
            if (mEglHelper != null) {
                mEglHelper.destoryEgl();
                mEglHelper = null;
                object = null;
                mEGLSurfaceViewWeakRef = null;
            }
        }

        EGLContext getEglContext() {
            if (mEglHelper != null) {
                return mEglHelper.getEglContext();
            }
            return null;
        }

        private WeakReference<EglSurfaceView> mEGLSurfaceViewWeakRef;
        private EglHelper mEglHelper;

        private int width;
        private int height;

        private boolean isCreate;
        private boolean isChange;
        private boolean isStart;
        private boolean isExit;

        private Object object;
    }


    public interface Render {
        void onSurfaceCreated();

        void onSurfaceChanged(int width, int height);

        void onDrawFrame();

    }
}

项目地址,欢迎点星

你可能感兴趣的:(OpenGLES系列)