OpenGL ES 自定義MyGlSurfaceView

一、自定義GLSurfaceView

  • 繼成SurfaceView,並實現其CallBack回調
  • 自定義GLThread線程類,主要用於OpenGL的繪製操作
  • 添加設置Surface和EglContext的方法
  • 提供和系統GLSurfaceView相同的調用方法
    在這裏插入圖片描述
    二、代碼使用
    1、自定義MyEGLSurfaceView
public class MyEGLSurfaceView extends SurfaceView implements SurfaceHolder.Callback{
    private Surface surface;
    private EGLContext eglContext;

    private MyEGLThread mEGLThread;
    private MyGLRender mGLRender;

    public final static int RENDERMODE_WHEN_DIRTY = 0;
    //自動模式:GL線程以一 定的時間間隔自動的循環調用用戶實現的onDrawFrame()方法進行一幀一幀的繪製
    public final static int RENDERMODE_CONTINUOUSLY = 1;
    //"髒"模式 也就是說當用戶需要重繪的時候,主動 “拉”這個重繪過程,有點類似於Canvas中的invalidate(),一般情況下使用髒模式,這樣可以有效降低cpu負載
    private int mRenderMode = RENDERMODE_CONTINUOUSLY;


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

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

    public MyEGLSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        getHolder().addCallback(this);
    }

    public void setRender(MyGLRender mGLRender) {
        this.mGLRender = mGLRender;
    }
    //設置模式
    public void setRenderMode(int mRenderMode) {

        if(mGLRender == null)
        {
            throw  new RuntimeException("must set render before");
        }
        this.mRenderMode = mRenderMode;
    }

    public void setSurfaceAndEglContext(Surface surface, EGLContext eglContext)
    {
        this.surface = surface;
        this.eglContext = eglContext;
    }
    //獲取EglContext上下文
    public EGLContext getEglContext()
    {
        if(mEGLThread != null)
        {
            return mEGLThread.getEglContext();
        }
        return null;
    }
    //當需要重繪時,調用requestRender()方法
    public void requestRender()
    {
        if(mEGLThread != null)
        {
            mEGLThread.requestRender();
        }
    }


    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if(surface == null)
        {
            surface = holder.getSurface();
        }
        //開啓一個線程處理EGL
        mEGLThread = new MyEGLThread(new WeakReference<MyEGLSurfaceView>(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.onDestory();
        mEGLThread = null;
        surface = null;
        eglContext = null;
    }

    public interface MyGLRender
    {
        void onSurfaceCreated();
        void onSurfaceChanged(int width, int height);
        void onDrawFrame();
    }

    //自定義MyEGLThread線程類,主要用於OpenGL的繪製操作
    static class MyEGLThread extends Thread{

        private WeakReference<MyEGLSurfaceView> meglSurfaceViewWeakReference;
        private EglHelper eglHelper = null;
        private Object object = null;

        private boolean isExit = false;
        private boolean isCreate = false;
        private boolean isChange = false;
        private boolean isStart = false;

        private int width;
        private int height;

        public MyEGLThread(WeakReference<MyEGLSurfaceView> meglSurfaceViewWeakReference) {
            this.meglSurfaceViewWeakReference = meglSurfaceViewWeakReference;
        }

        @Override
        public void run() {
            super.run();
            isExit = false;
            isStart = false;
            object = new Object();
            eglHelper = new EglHelper();
            eglHelper.initEgl(meglSurfaceViewWeakReference.get().surface, meglSurfaceViewWeakReference.get().eglContext);

            while (true)
            {
                if(isExit)
                {
                    //釋放資源
                    release();
                    break;
                }

                if(isStart)
                {
                    if(meglSurfaceViewWeakReference.get().mRenderMode == RENDERMODE_WHEN_DIRTY)
                    {
                        synchronized (object)
                        {
                            try {
                                object.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                    else if(meglSurfaceViewWeakReference.get().mRenderMode == RENDERMODE_CONTINUOUSLY)
                    {
                        try {
                            Thread.sleep(1000 / 60);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    else
                    {
                        throw  new RuntimeException("mRenderMode is wrong value");
                    }
                }


                onCreate();
                onChange(width, height);
                onDraw();

                isStart = true;


            }


        }

        private void onCreate()
        {
            if(isCreate && meglSurfaceViewWeakReference.get().mGLRender != null)
            {
                isCreate = false;
                meglSurfaceViewWeakReference.get().mGLRender.onSurfaceCreated();
            }
        }

        private void onChange(int width, int height)
        {
            if(isChange && meglSurfaceViewWeakReference.get().mGLRender != null)
            {
                isChange = false;
                meglSurfaceViewWeakReference.get().mGLRender.onSurfaceChanged(width, height);
            }
        }

        private void onDraw()
        {
            if(meglSurfaceViewWeakReference.get().mGLRender != null && eglHelper != null)
            {
                meglSurfaceViewWeakReference.get().mGLRender.onDrawFrame();
                if(!isStart)
                {
                    meglSurfaceViewWeakReference.get().mGLRender.onDrawFrame();
                }
                eglHelper.swapBuffers();

            }
        }

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

        public void onDestory()
        {
            isExit = true;
            requestRender();
        }


        public void release()
        {
            if(eglHelper != null)
            {
                eglHelper.destoryEgl();
                eglHelper = null;
                object = null;
                meglSurfaceViewWeakReference = null;
            }
        }

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

    }

}

2、創建一個MyRender類實現MyEGLSurfaceView.MyGLRender

public class MyRender  implements MyEGLSurfaceView.MyGLRender{

    private static final String TAG = "wq892373445";
    public MyRender(){}

    @Override
    public void onSurfaceCreated() {
        Log.d(TAG, "onSurfaceCreated");
    }

    @Override
    public void onSurfaceChanged(int width, int height) {
        GLES20.glViewport(0, 0, width, height);
        Log.d(TAG, "onSurfaceChanged");
    }

    @Override
    public void onDrawFrame() {
        Log.d(TAG, "onDrawFrame");
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
        GLES20.glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
    }
}

3、繼承MyGlSurfaceView

public class MyGlSurfaceView extends MyEGLSurfaceView{

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

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

    public MyGlSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setRender(new MyRender());
        setRenderMode(MyEGLSurfaceView.RENDERMODE_WHEN_DIRTY);
    }
}

4、佈局文件中使用

 <com.wq.myglsurfaceview.MyGlSurfaceView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

最後效果如下:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章