美文网首页
android c++ OpenGLES Egl 环境搭建

android c++ OpenGLES Egl 环境搭建

作者: 曾大稳丶 | 来源:发表于2019-04-22 17:38 被阅读0次

    android搭建opengles 的egl环境之前使用java已经写过,但是一般实际开发opengles的相关代码都在native层,因为native的话效率会比java高很多,步骤都是一致的,只是换一种语言写而已。之前使用java写的opengles egl环境搭建点击下面链接:
    https://www.jianshu.com/p/ce3496ab9e02

    本文demo下载地址:
    https://github.com/ChinaZeng/NativeEglDemo

    步骤都是一样的:

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

    代码目录:

    代码目录
    1. 首先配置android ndk开发环境,我使用的是cmake
    cmake_minimum_required(VERSION 3.4.1)
    
    add_library( # Sets the name of the library.
            native-lib
            SHARED
            native-lib.cpp
            egl/EglHelper.cpp
            )
    
    target_link_libraries(
            native-lib
            EGL
            GLESv2
            android
            log
    )
    
    
    1. 书写EglHelper,这个类主要负责egl的环境初始化,绘制和销毁
    //环境搭建初始化
    int EglHelper::initEgl(EGLNativeWindowType window) {
        //1.得到默认的显示设备(就是窗口) -- eglGetDisplay
        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
        if (mEglDisplay == EGL_NO_DISPLAY) {
            LOGE("eglGetDisplay error");
            return -1;
        }
    
        //2. 初始化默认显示设备 -- eglInitialize
        EGLint *version = new EGLint[2];
        if (!eglInitialize(mEglDisplay, &version[0], &version[1])) {
            LOGE("eglInitialize error");
            return -1;
        }
    
        //3. 设置显示设备的属性
        const EGLint attrib_config_list[] = {
                EGL_RED_SIZE, 8,
                EGL_GREEN_SIZE, 8,
                EGL_BLUE_SIZE, 8,
                EGL_ALPHA_SIZE, 8,
                EGL_DEPTH_SIZE, 8,
                EGL_STENCIL_SIZE, 8,// 眼睛屏幕的距离
                EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,//版本号
                EGL_NONE
        };
    
        //3.1 根据所需的参数获取符合该参数的config_size,主要是解决有些手机eglChooseConfig失败的兼容性问题
        EGLint num_config;
    
        if (!eglChooseConfig(mEglDisplay, attrib_config_list, NULL, 1, &num_config)) {
            LOGE("eglChooseConfig error");
            return -1;
        }
        //3.2 根据获取到的config_size得到eglConfig
        EGLConfig eglConfig;
        if (!eglChooseConfig(mEglDisplay, attrib_config_list, &eglConfig, num_config, &num_config)) {
            LOGE("eglChooseConfig error");
            return -1;
        }
    
        //4. 创建egl上下文 eglCreateContext
        const EGLint attrib_ctx_list[] = {
                EGL_CONTEXT_CLIENT_VERSION, 2,
                EGL_NONE
        };
        mEglContext = eglCreateContext(mEglDisplay, eglConfig, NULL, attrib_ctx_list);
        if (mEglContext == EGL_NO_CONTEXT) {
            LOGE("eglCreateContext  error");
            return -1;
        }
        //5.创建渲染的surface
        mEglSurface = eglCreateWindowSurface(mEglDisplay, eglConfig, window, NULL);
        if (mEglSurface == EGL_NO_SURFACE) {
            LOGE("eglCreateWindowSurface  error");
            return -1;
        }
        //6. 绑定eglContext和surface到display
        if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
            LOGE("eglMakeCurrent  error");
            return -1;
        }
    
        //7. 刷新数据,显示渲染场景 -- eglSwapBuffers
    
        return 0;
    }
    
    //交换缓冲 绘制
    int EglHelper::swapBuffers() {
        if (mEglDisplay != EGL_NO_DISPLAY && mEglSurface != EGL_NO_SURFACE &&
            eglSwapBuffers(mEglDisplay, mEglSurface)) {
            return 0;
        }
        return -1;
    }
    //销毁
    void EglHelper::destroyEgl() {
        if (mEglDisplay != EGL_NO_DISPLAY) {
            //解绑display上的eglContext和surface
            eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    
            //销毁surface 和 eglContext
            if (mEglSurface != EGL_NO_SURFACE) {
                eglDestroySurface(mEglDisplay, mEglSurface);
                mEglSurface = EGL_NO_SURFACE;
            }
    
            if (mEglContext != EGL_NO_CONTEXT) {
                eglDestroyContext(mEglDisplay, mEglContext);
                mEglContext = EGL_NO_CONTEXT;
            }
    
            if (mEglDisplay != EGL_NO_DISPLAY) {
                eglTerminate(mEglDisplay);
                mEglDisplay = EGL_NO_DISPLAY;
            }
        }
    }
    

    书写EglThread,顾名思义,这个类主要负责开启一个线程然后根据外部的生命周期调用EglHelper完成egl的环境搭建,并且和外部交互。

    
    EglThread::EglThread() {
        pthread_mutex_init(&pthread_mutex, NULL);
        pthread_cond_init(&pthread_cond, NULL);
    }
    
    EglThread::~EglThread() {
        pthread_mutex_destroy(&pthread_mutex);
        pthread_cond_destroy(&pthread_cond);
    }
    
    
    void *eglThreadImpl(void *context) {
        EglThread *eglThread = static_cast<EglThread *>(context);
        if (!eglThread) {
            LOGE("eglThreadImpl eglThread is null");
            return 0;
        }
    
        EglHelper *eglHelper = new EglHelper();
    
        if (eglHelper->initEgl(eglThread->mANativeWindow) != 0) {
            LOGE("eglHelper initEgl error");
            return 0;
        }
        eglThread->isExit = false;
        while (!eglThread->isExit) {
    
            if (eglThread->isCreate) {
                eglThread->isCreate = false;
                eglThread->onCreate();
            }
    
            if (eglThread->isChange) {
                eglThread->isChange = false;
                eglThread->isStart = true;
                eglThread->onChange(eglThread->surfaceWidth, eglThread->surfaceHeight);
            }
    
            if (eglThread->isStart) {
                eglThread->onDraw();
                //切换缓冲区,显示
                eglHelper->swapBuffers();
    
                if (eglThread->mRenderType == RENDER_MODULE_AUTO) {
                    usleep(1000000 / 60);
                } else {
                    pthread_mutex_lock(&eglThread->pthread_mutex);
                    pthread_cond_wait(&eglThread->pthread_cond, &eglThread->pthread_mutex);
                    pthread_mutex_unlock(&eglThread->pthread_mutex);
                }
            }
    
        }
    
        eglHelper->destroyEgl();
        delete eglHelper;
        eglHelper = NULL;
        //return 0表示线程结束
        return 0;
    
    }
    
    
    void EglThread::onSurfaceCreate(EGLNativeWindowType window) {
        if (mEglThread == -1) {
            isCreate = true;
            mANativeWindow = window;
            pthread_create(&mEglThread, NULL, eglThreadImpl, this);
        }
    }
    
    
    void EglThread::onSurfaceChange(int width, int height) {
        if (mEglThread != -1) {
            surfaceWidth = width;
            surfaceHeight = height;
            isChange = true;
    
            notifyRender();
        }
    }
    
    void EglThread::setRenderModule(int renderType) {
        mRenderType = renderType;
        notifyRender();
    }
    
    void EglThread::notifyRender() {
        pthread_mutex_lock(&pthread_mutex);
        pthread_cond_signal(&pthread_cond);
        pthread_mutex_unlock(&pthread_mutex);
    }
    
    
    void EglThread::callBackOnCreate(EglThread::OnCreate onCreate) {
        this->onCreate = onCreate;
    }
    
    void EglThread::callBackOnChange(EglThread::OnChange onChange) {
        this->onChange = onChange;
    }
    
    void EglThread::callBackOnDraw(EglThread::OnDraw onDraw) {
        this->onDraw = onDraw;
    }
    
    
    
    1. 书写java层和native层交互,对应生命周期回调即可
      NationOpenGL.java
    public class NationOpenGL {
    
        static {
            System.loadLibrary("native-lib");
        }
    
        public native void nativeSurfaceCreate(Surface surface);
    
        public native void nativeSurfaceChanged(int width, int height);
    
        public native void nativeSurfaceDestroyed();
    
    }
    
    
    

    NativeGLSurfaceView.java

    public class NativeGLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
        private NationOpenGL mNationOpenGL;
    
        public NativeGLSurfaceView(Context context) {
            this(context, null);
        }
    
        public NativeGLSurfaceView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public NativeGLSurfaceView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            mNationOpenGL = new NationOpenGL();
            getHolder().addCallback(this);
        }
    
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            mNationOpenGL.nativeSurfaceCreate(holder.getSurface());
        }
    
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            mNationOpenGL.nativeSurfaceChanged(width, height);
        }
    
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            mNationOpenGL.nativeSurfaceDestroyed();
        }
    }
    

    native-lib.cpp

    EglThread *eglThread = NULL;
    
    
    void callBackOnCreate() {
        LOGE("callBackOnCreate");
    }
    
    void callBackOnChange(int width, int height) {
        glViewport(0, 0, width, height);
        LOGE("callBackOnChange");
    }
    
    void callBackOnDraw() {
        glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        LOGE("callBackOnDraw");
    }
    
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_zzw_nativeopnegldemo_opengl_NationOpenGL_nativeSurfaceCreate(JNIEnv *env, jobject instance,
                                                                          jobject surface) {
    
        eglThread = new EglThread();
        eglThread->callBackOnCreate(callBackOnCreate);
        eglThread->callBackOnChange(callBackOnChange);
        eglThread->callBackOnDraw(callBackOnDraw);
        eglThread->setRenderModule(RENDER_MODULE_MANUAL);
    
    
        ANativeWindow *nativeWindow = ANativeWindow_fromSurface(env, surface);
        eglThread->onSurfaceCreate(nativeWindow);
    }
    
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_zzw_nativeopnegldemo_opengl_NationOpenGL_nativeSurfaceChanged(JNIEnv *env,
                                                                           jobject instance, jint width,
                                                                           jint height) {
        if (eglThread) {
            eglThread->onSurfaceChange(width, height);
        }
    }
    
    
    extern "C"
    JNIEXPORT void JNICALL
    Java_com_zzw_nativeopnegldemo_opengl_NationOpenGL_nativeSurfaceDestroyed(JNIEnv *env,
                                                                             jobject instance) {
        if (eglThread) {
            eglThread->isExit = true;
            //等待线程结束
            pthread_join(eglThread, NULL);
            delete (eglThread);
            eglThread = NULL;
        }
    
    }
    

    相关文章

      网友评论

          本文标题:android c++ OpenGLES Egl 环境搭建

          本文链接:https://www.haomeiwen.com/subject/efeugqtx.html