EGL环境创建

EGL

EGL是OpenGL ES和本地窗口系统的接口,不同平台上EGL配置是不一样的,而OpenGL的调用方式是一致的,就是说:OpenGL跨平台就是依赖于EGL接口。

为什么要自己创建EGL环境?
当我们需要把同一个场景渲染到不同的Surface上时,此时系统GLSurfaceView就不能满足需求了,所以我们需要自己创建EGL环境来实现渲染操作。

注意:OpenGL整体是一个状态机,通过改变状态就能改变后续的渲染方式,而EGLContext(EgL上下文)就保存有所有状态,因此可以通过共享EGLContext来实现同一场景渲染到不同的Surface上。

创建自己的EglHelper

1、得到Egl实例:
2、得到默认的显示设备(就是窗口)
3、初始化默认显示设备
4、设置显示设备的属性
5、从系统中获取对应属性的配置
6、创建EglContext,设置版本
7、创建渲染的Surface
8、绑定EglContext和Surface到显示设备中
9、刷新数据,显示渲染场景

public class EglHelper {
    EGL10 mEgl;
    EGLDisplay mEglDisplay;
    EGLContext mEglContext;
    EGLSurface mEglSurface;
    public void initEgl(Surface surface, EGLContext eglContext){
        //1、得到Egl实例
        mEgl = (EGL10) EGLContext.getEGL();
        //2、得到默认的显示设备(就是窗口)
        mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);

        if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
            throw new RuntimeException("eglGetDisplay failed");
        }

        //3、初始化默认显示设备
        int[] version = new int[2];
        if(!mEgl.eglInitialize(mEglDisplay, version)) {
            throw new RuntimeException("eglInitialize failed");
        }


        //4、设置显示设备的属性
        int[] attrbutes = new int[]{
                EGL10.EGL_RED_SIZE,8,
                EGL10.EGL_GREEN_SIZE,8,
                EGL10.EGL_BLUE_SIZE,8,
                EGL10.EGL_ALPHA_SIZE,8,
                EGL10.EGL_DEPTH_SIZE,8,
                EGL10.EGL_STENCIL_SIZE,8,
                EGL10.EGL_RENDERABLE_TYPE,4,//写死的
                EGL10.EGL_NONE};

        int[]num_config = new int[1];

        if (!mEgl.eglChooseConfig(mEglDisplay,attrbutes,null,1,num_config)) {
            throw new IllegalArgumentException("eglChooseConfig failed");
        }

        int numConfigs = num_config[0];
        if (numConfigs <= 0) {
            throw new IllegalArgumentException(
                    "No configs match configSpec");
        }


        //5、从系统中获取对应属性的配置
        EGLConfig[] configs = new EGLConfig[numConfigs];
        if (!mEgl.eglChooseConfig(mEglDisplay, attrbutes, configs, numConfigs,
                num_config)) {
            throw new IllegalArgumentException("eglChooseConfig#2 failed");
        }

        //6、创建EglContext
        int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION,2 /*mEGLContextClientVersion*/,
                EGL10.EGL_NONE };
        if (eglContext != null) {
            //如果
            mEglContext = mEgl.eglCreateContext(mEglDisplay,configs[0],eglContext,attrib_list );
        } else {
            mEglContext = mEgl.eglCreateContext(mEglDisplay,configs[0],EGL10.EGL_NO_CONTEXT,attrib_list );
        }

        //7、创建渲染的Surface
        mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay,configs[0],surface,attrib_list );

        //8、绑定EglContext和Surface到显示设备中
        if (!mEgl.eglMakeCurrent(mEglDisplay,mEglSurface,mEglSurface,mEglContext)){
            throw new RuntimeException("eglMakeCurrent fail");
        }
    }

    //刷新数据
    public boolean swapBuffers(){
        if (mEgl != null) {
            return mEgl.eglSwapBuffers(mEglDisplay,mEglSurface);
        } else {
            throw new RuntimeException("egl is null");
        }
    }


    public EGLContext getmEglContext() {
        return mEglContext;
    }

    public void destroyEgl(){
        if (mEgl != null) {
            mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE,
                    EGL10.EGL_NO_SURFACE,
                    EGL10.EGL_NO_CONTEXT);//解绑
            mEgl.eglDestroySurface(mEglDisplay,mEglSurface);
            mEglSurface = null;

            mEgl.eglDestroyContext(mEglDisplay,mEglContext);
            mEglContext = null;

            mEgl.eglTerminate(mEglDisplay);
            mEglDisplay = null;

            mEgl = null;
        }
    }
}
public class MainActivity extends AppCompatActivity {
    private SurfaceView surfaceView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        surfaceView = (SurfaceView)findViewById(R.id.sfv);

        surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(SurfaceHolder holder) {

            }

            @Override
            public void surfaceChanged(final SurfaceHolder holder, int format, final int width, final int height) {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        EglHelper eglHelper = new EglHelper();
                        eglHelper.initEgl(holder.getSurface(),null);

                        while (true) {
                            GLES20.glViewport(0,0,width,height);
                            //GLES20.glViewport(width / 2,0,width / 2,height);

                            GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
                            GLES20.glClearColor(1.0f,0.0f,0.0f,0.5f);

                            eglHelper.swapBuffers();

                            try {
                                Thread.sleep(16);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }).start();
            }

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {

            }
        });
    }
}

https://github.com/Xiaoben336/OpenGLESEGL

猜你喜欢

转载自blog.csdn.net/weixin_34125592/article/details/86984922