android egl 代码,Android OpenGL ES - EGL C++实现

PS

本篇继续上一篇的内容,咱们来对Native EGL环境实现的各个步骤进行详细解析

EGL Native层的实现

咱们仍是先来回顾一下流程图

1460000038363516android

以及代码git

//(1) 将线程附加到虚拟机,并获取env

if (that->m_jvm_for_thread->AttachCurrentThread(&env, NULL) != JNI_OK) {

LOGE(that->TAG, "线程初始化异常");

return;

}

// (2) 初始化 EGL

if (!that->InitEGL()) {

//解除线程和jvm关联

that->m_jvm_for_thread->DetachCurrentThread();

return;

}

//进入循环

while (true) {

//根据OpenGL渲染状态进入不一样的处理

switch (that->m_state) {

//刷新Surface,从外面设置Surface后m_state置为该状态,说明已经从外部(java层)得到Surface的对象了

case FRESH_SURFACE:

LOGI(that->TAG, "Loop Render FRESH_SURFACE")

// (3) 初始化Window

that->InitDspWindow(env);

// (4) 建立EglSurface

that->CreateSurface();

// m_state置为RENDERING状态进入渲染

that->m_state = RENDERING;

break;

case RENDERING:

LOGI(that->TAG, "Loop Render RENDERING")

// (5) 渲染

that->Render();

break;

case STOP:

LOGI(that->TAG, "Loop Render STOP")

//(6) 解除线程和jvm关联

that->ReleaseRender();

that->m_jvm_for_thread->DetachCurrentThread();

return;

case SURFACE_DESTROY:

LOGI(that->TAG, "Loop Render SURFACE_DESTROY")

//(7) 释放资源

that->DestroySurface();

that->m_state = NO_SURFACE;

break;

case NO_SURFACE:

default:

break;

}

usleep(20000);

}

}

首先第(1)步将线程附加到虚拟机,并获取env,这一步简单明了,咱们从第(2)步开始github

EGL封装准备

咱们在上一篇就知道了EGL的一些基础知识,EGLDiaplay,EGLConfig,EGLSurface,EGLContext,咱们须要把这些基础类进行封装,那么如何进行封装呢,咱们先看一下对于咱们上篇文章中自定义的GLRender类须要什么

gl_render.hsegmentfault

//Surface引用,必需要使用引用,不然没法在线程中操做

jobject m_surface_ref = NULL;

//本地屏幕

ANativeWindow *m_native_window = NULL;

//EGL显示表面 注意这里是咱们自定义的EglSurface包装类而不是系统提供的EGLSurface哦

EglSurface *m_egl_surface = NULL;

对于gl_render来讲输入的是外部的Surface对象,咱们这里的是jobject m_surface_ref,那么输出须要的是ANativeWindow,EglSurfaceapp

关于

ANativeWindow能够查看官方文档

ANativeWindow

那么EglSurface呢,jvm

egl_surface.hoop

class EglSurface {

private:

const char *TAG = "EglSurface";

//本地屏幕

ANativeWindow *m_native_window = NULL;

//封装了EGLDisplay EGLConfig EGLContext的自定义类

EglCore *m_core;

//EGL API提供的 EGLSurface

EGLSurface m_surface;

}

能够看到咱们上面的定义的思想也是V(View)和C(Controller)进行了分离。

egl_core.hthis

class EglCore {

private:

const char *TAG = "EglCore";

//EGL显示窗口

EGLDisplay m_egl_dsp = EGL_NO_DISPLAY;

//EGL上下文

EGLContext m_egl_context = EGL_NO_CONTEXT;

//EGL配置

EGLConfig m_egl_config;

}

有了上面的准备工做后,咱们就跟着流程图的步骤来一步步走spa

(2)初始化EGL

gl_render.cpp

bool GLRender::InitEGL() {

//建立EglSurface对象

m_egl_surface = new EglSurface();

//调用EglSurface的init方法

return m_egl_surface->Init();

}

egl_surface.cpp

PS

咱们上面也说了EGL的初始化主要是对EGLDisplay EGLConfig EGLContext的操做,因此如今是对EGLCore的操做

EglSurface::EglSurface() {

//建立EGLCore

m_core = new EglCore();

}

bool EglSurface::Init() {

//调用EGLCore的init方法

return m_core->Init(NULL);

}

egl_core.cpp

EglCore::EglCore() {

}

bool EglCore::Init(EGLContext share_ctx) {

if (m_egl_dsp != EGL_NO_DISPLAY) {

LOGE(TAG, "EGL already set up")

return true;

}

if (share_ctx == NULL) {

share_ctx = EGL_NO_CONTEXT;

}

//获取Dispaly

m_egl_dsp = eglGetDisplay(EGL_DEFAULT_DISPLAY);

if (m_egl_dsp == EGL_NO_DISPLAY || eglGetError() != EGL_SUCCESS) {

LOGE(TAG, "EGL init display fail")

return false;

}

EGLint major_ver, minor_ver;

//初始化egl

EGLBoolean success = eglInitialize(m_egl_dsp, &major_ver, &minor_ver);

if (success != EGL_TRUE || eglGetError() != EGL_SUCCESS) {

LOGE(TAG, "EGL init fail")

return false;

}

LOGI(TAG, "EGL version: %d.%d", major_ver, minor_ver)

//获取EGLConfig

m_egl_config = GetEGLConfig();

const EGLint attr[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};

//建立EGLContext

m_egl_context = eglCreateContext(m_egl_dsp, m_egl_config, share_ctx, attr);

if (m_egl_context == EGL_NO_CONTEXT) {

LOGE(TAG, "EGL create fail, error is %x", eglGetError());

return false; }

EGLint egl_format;

success = eglGetConfigAttrib(m_egl_dsp, m_egl_config, EGL_NATIVE_VISUAL_ID, &egl_format);

if (success != EGL_TRUE || eglGetError() != EGL_SUCCESS) {

LOGE(TAG, "EGL get config fail, error is %x", eglGetError())

return false;

}

LOGI(TAG, "EGL init success")

return true;

}

EGLConfig EglCore::GetEGLConfig() {

EGLint numConfigs;

EGLConfig config;

//但愿的最小配置,

static const EGLint CONFIG_ATTRIBS[] = {

EGL_BUFFER_SIZE, EGL_DONT_CARE,

EGL_RED_SIZE, 8,//R 位数

EGL_GREEN_SIZE, 8,//G 位数

EGL_BLUE_SIZE, 8,//B 位数

EGL_ALPHA_SIZE, 8,//A 位数

EGL_DEPTH_SIZE, 16,//深度

EGL_STENCIL_SIZE, EGL_DONT_CARE,

EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,

EGL_SURFACE_TYPE, EGL_WINDOW_BIT,

EGL_NONE // the end 结束标志

};

//根据你所设定的最小配置系统会选择一个知足你最低要求的配置,这个真正的配置每每要比你指望的属性更多

EGLBoolean success = eglChooseConfig(m_egl_dsp, CONFIG_ATTRIBS, &config, 1, &numConfigs);

if (!success || eglGetError() != EGL_SUCCESS) {

LOGE(TAG, "EGL config fail")

return NULL;

}

return config;

}

(3)建立Window

gl_render.cpp

void GLRender::InitDspWindow(JNIEnv *env) {

//传进来的Surface对象的引用

if (m_surface_ref != NULL) {

// 初始化窗口

m_native_window = ANativeWindow_fromSurface(env, m_surface_ref);

// 绘制区域的宽高

m_window_width = ANativeWindow_getWidth(m_native_window);

m_window_height = ANativeWindow_getHeight(m_native_window);

//设置宽高限制缓冲区中的像素数量

ANativeWindow_setBuffersGeometry(m_native_window, m_window_width,

m_window_height, WINDOW_FORMAT_RGBA_8888);

LOGD(TAG, "View Port width: %d, height: %d", m_window_width, m_window_height)

}

}

(4)建立EglSurface并绑定到线程

gl_render.cpp

void GLRender::CreateSurface() {

m_egl_surface->CreateEglSurface(m_native_window, m_window_width, m_window_height);

glViewport(0, 0, m_window_width, m_window_height);

}

egl_surface.cpp

/**

*

* @param native_window 传入上一步建立的ANativeWindow

* @param width

* @param height

*/

void EglSurface::CreateEglSurface(ANativeWindow *native_window, int width, int height) {

if (native_window != NULL) {

this->m_native_window = native_window;

m_surface = m_core->CreateWindSurface(m_native_window);

} else {

m_surface = m_core->CreateOffScreenSurface(width, height);

}

if (m_surface == NULL) {

LOGE(TAG, "EGL create window surface fail")

Release();

}

MakeCurrent();

}

void EglSurface::MakeCurrent() {

m_core->MakeCurrent(m_surface);

}

egl_core.cpp

EGLSurface EglCore::CreateWindSurface(ANativeWindow *window) {

//调用EGL Native API建立Window Surface

EGLSurface surface = eglCreateWindowSurface(m_egl_dsp, m_egl_config, window, 0);

if (eglGetError() != EGL_SUCCESS) {

LOGI(TAG, "EGL create window surface fail")

return NULL;

}

return surface;

}

void EglCore::MakeCurrent(EGLSurface egl_surface) {

//调用EGL Native API 绑定渲染环境到当前线程

if (!eglMakeCurrent(m_egl_dsp, egl_surface, egl_surface, m_egl_context)) {

LOGE(TAG, "EGL make current fail");

}

}

(5)渲染

gl_render.cpp

void GLRender::Render() {

if (RENDERING == m_state) {

pImageRender->DoDraw();//画画画....

m_egl_surface->SwapBuffers();

}

}

egl_surface.cpp

void EglSurface::SwapBuffers() {

m_core->SwapBuffer(m_surface);

}

egl_core.cpp

void EglCore::SwapBuffer(EGLSurface egl_surface) {

//调用EGL Native API

eglSwapBuffers(m_egl_dsp, egl_surface);

}

后面的中止与销毁就交给读者自行研究了。

代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值