• 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏吧

[OpenGL ES] 自定义GLSurfaceView

互联网 diligentman 4天前 3次浏览

MyGLSurfaceView

package com.example.opengldemo;

import android.content.Context;
import android.util.AttributeSet;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import androidx.annotation.NonNull;

import java.lang.ref.WeakReference;

import javax.microedition.khronos.egl.EGLContext;

public abstract class MyGLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {

    private Surface surface;
    private EGLContext eglContext;
    private MyGLThread myGLThread;
    private MyGLRender myGLRender;

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

    public int mRenderMode = RENDERMODE_CONTINUOUSLY;

    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);
        getHolder().addCallback(this);
    }

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

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {
        myGLThread.onDestory();
        myGLThread = null;
        surface = null;
        eglContext = null;
    }

    @Override
    public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
        if(surface == null){
            surface = surfaceHolder.getSurface();
        }
        myGLThread = new MyGLThread(new WeakReference<MyGLSurfaceView>(this));
        myGLThread.isCreate = true;
        myGLThread.start();
    }

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

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

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

    public void setMyGLRender(MyGLRender myGLRender) {
        this.myGLRender = myGLRender;
    }

    public void setmRenderMode(int mRenderMode) {
        if(myGLRender ==null){
            throw new RuntimeException("must set render before");
        }
        this.mRenderMode = mRenderMode;
    }

    public interface MyGLRender{
        void onSufaceCreated();
        void onSufaceChanged(int width,int height);
        void onDrawFrame();
    }


    static class MyGLThread extends Thread{

        private WeakReference<MyGLSurfaceView> myGLSurfaceViewWeakReference;
        private MyEglHelper myEglHelper = null;
        private boolean isExit = false;
        private boolean isCreate = false;
        private boolean isChange = false;
        private boolean isStart = false;
        private Object object = null;

        private int width;
        private int height;

        public MyGLThread(WeakReference<MyGLSurfaceView> myGLSurfaceViewWeakReference) {
            this.myGLSurfaceViewWeakReference = myGLSurfaceViewWeakReference;
        }

        @Override
        public void run() {
            super.run();
            isExit = false;
            isStart = false;
            object = new Object();
            myEglHelper = new MyEglHelper();
            myEglHelper.initEgl(myGLSurfaceViewWeakReference.get().surface,
                    myGLSurfaceViewWeakReference.get().eglContext);

            while (true){
                if(isExit){
                    release();
                    break;
                }

                if(isStart){
                    if(myGLSurfaceViewWeakReference.get().mRenderMode == RENDERMODE_WHEN_DIRTY){
                        synchronized (object){
                            try {
                                object.wait();
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }else if (myGLSurfaceViewWeakReference.get().mRenderMode == RENDERMODE_CONTINUOUSLY){
                        try {
                            Thread.sleep(1000/60);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }else {
                        throw new RuntimeException("mRenderMode is error value");
                    }
                }
                onCreate();
                onChange(width, height);
                onDraw();
                isStart = true;
            }
        }

        private void onCreate(){
            if (isCreate &&myGLSurfaceViewWeakReference.get().myGLRender != null){
                isCreate = false;
                myGLSurfaceViewWeakReference.get().myGLRender.onSufaceCreated();
            }
        }

        private void onChange(int width,int height){
            if(isChange && myGLSurfaceViewWeakReference.get().myGLRender != null){
                isChange = false;
                myGLSurfaceViewWeakReference.get().myGLRender.onSufaceChanged(width, height);
            }
        }

        private void onDraw(){
            if(myGLSurfaceViewWeakReference.get().myGLRender != null &&myEglHelper != null){
                myGLSurfaceViewWeakReference.get().myGLRender.onDrawFrame();
                if(!isStart){
                    myGLSurfaceViewWeakReference.get().myGLRender.onDrawFrame();
                }
                myEglHelper.swapBuffers();
            }
        }

        private void requestRnder(){
            if(object != null){
                synchronized (object){
                    notifyAll();
                }
            }
        }
        public void release(){
            if(myEglHelper != null){
                myEglHelper.destoryEgl();
                myEglHelper = null;
                object = null;
                myGLSurfaceViewWeakReference = null;
            }
        }

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

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

编写GGlSurfaceView继承上面这个类

package com.example.opengldemo;

import android.content.Context;
import android.util.AttributeSet;

public class GGlSurfaceView extends MyGLSurfaceView{
    public GGlSurfaceView(Context context) {
        this(context,null);
    }

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

    public GGlSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        setMyGLRender(new MyRender());
    }
}

写Render

package com.example.opengldemo;

import android.opengl.GLES20;

public class MyRender implements MyGLSurfaceView.MyGLRender {

    public MyRender() {
    }

    @Override
    public void onSufaceCreated() {

    }

    @Override
    public void onSufaceChanged(int width, int height) {
        GLES20.glViewport(0,0,width,height);

    }

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

activity EglSurfaceActivity

package com.example.opengldemo;

import android.os.Bundle;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

public class EglSurfaceActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_egl);
    }
}

 


喜欢 (0)