日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

与context的关系_你还不知道 OpenGL ES 和 EGL 的关系?

發布時間:2024/8/23 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 与context的关系_你还不知道 OpenGL ES 和 EGL 的关系? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

什么是 EGL

EGL 是 OpenGL ES 和本地窗口系統(Native Window System)之間的通信接口,它的主要作用:
  • 與設備的原生窗口系統通信;

  • 查詢繪圖表面的可用類型和配置;

  • 創建繪圖表面;

  • 在OpenGL ES 和其他圖形渲染API之間同步渲染;

  • 管理紋理貼圖等渲染資源。

OpenGL ES 的平臺無關性正是借助 EGL 實現的,EGL 屏蔽了不同平臺的差異(Apple 提供了自己的 EGL API 的 iOS 實現,自稱 EAGL)。

本地窗口相關的 API 提供了訪問本地窗口系統的接口,而 EGL 可以創建渲染表面 EGLSurface ,同時提供了圖形渲染上下文 EGLContext,用來進行狀態管理,接下來 OpenGL ES 就可以在這個渲染表面上繪制。

egl、opengles 和設備之間的關系

圖片中:

  • Display(EGLDisplay) 是對實際顯示設備的抽象;

  • Surface(EGLSurface)是對用來存儲圖像的內存區域 FrameBuffer 的抽象,包括 Color Buffer(顏色緩沖區), Stencil Buffer(模板緩沖區) ,Depth Buffer(深度緩沖區);

  • Context (EGLContext) 存儲 OpenGL ES 繪圖的一些狀態信息;

在 Android 平臺上開發 OpenGL ES 應用時,類 GLSurfaceView 已經為我們提供了對 Display , Surface , Context 的管理,即 GLSurfaceView 內部實現了對 EGL 的封裝,可以很方便地利用接口 GLSurfaceView.Renderer 的實現,使用 OpenGL ES API 進行渲染繪制,很大程度上提升了 OpenGLES 開發的便利性。

當然我們也可以自己實現對 EGL 的封裝,本文就是在 Native 層對 EGL 進行封裝,不借助于 GLSurfaceView ,實現圖片后臺渲染,利用 GPU 完成對圖像的高效處理。

EGL 的應用

EGL 后臺渲染實現效果圖

使用 EGL 渲染的一般步驟:

  • 獲取 EGLDisplay 對象,建立與本地窗口系統的連接調用 eglGetDisplay 方法得到 EGLDisplay。
  • 初始化 EGL 方法打開連接之后,調用 eglInitialize 方法初始化。
  • 獲取 EGLConfig 對象,確定渲染表面的配置信息調用 eglChooseConfig 方法得到 EGLConfig。
  • 創建渲染表面 EGLSurface通過 EGLDisplay 和 EGLConfig ,調用 eglCreateWindowSurface 或 eglCreatePbufferSurface 方法創建渲染表面,得到 EGLSurface,其中 eglCreateWindowSurface 用于創建屏幕上渲染區域,eglCreatePbufferSurface 用于創建屏幕外渲染區域。
  • 創建渲染上下文 EGLContext?通過 EGLDisplay 和 EGLConfig ,調用 eglCreateContext 方法創建渲染上下文,得到 EGLContext。
  • 綁定上下文通過 eglMakeCurrent 方法將 EGLSurface、EGLContext、EGLDisplay 三者綁定,綁定成功之后 OpenGLES 環境就創建好了,接下來便可以進行渲染。
  • 交換緩沖OpenGLES 繪制結束后,使用 eglSwapBuffers 方法交換前后緩沖,將繪制內容顯示到屏幕上,而屏幕外的渲染不需要調用此方法。
  • 釋放 EGL 環境繪制結束后,不再需要使用 EGL 時,需要取消 eglMakeCurrent 的綁定,銷毀 ?EGLDisplay、EGLSurface、EGLContext 三個對象。

代碼實現:

//?創建?GLES?環境
int?BgRender::CreateGlesEnv()
{
????//?EGL?config?attributes
????const?EGLint?confAttr[]?=
????{
????????????EGL_RENDERABLE_TYPE,?EGL_OPENGL_ES3_BIT_KHR,
????????????EGL_SURFACE_TYPE,EGL_PBUFFER_BIT,//EGL_WINDOW_BIT?EGL_PBUFFER_BIT?we?will?create?a?pixelbuffer?surface
????????????EGL_RED_SIZE,???8,
????????????EGL_GREEN_SIZE,?8,
????????????EGL_BLUE_SIZE,??8,
????????????EGL_ALPHA_SIZE,?8,//?if?you?need?the?alpha?channel
????????????EGL_DEPTH_SIZE,?8,//?if?you?need?the?depth?buffer
????????????EGL_STENCIL_SIZE,8,
????????????EGL_NONE
????};

????//?EGL?context?attributes
????const?EGLint?ctxAttr[]?=?{
????????????EGL_CONTEXT_CLIENT_VERSION,?2,
????????????EGL_NONE
????};

????//?surface?attributes
????//?the?surface?size?is?set?to?the?input?frame?size
????const?EGLint?surfaceAttr[]?=?{
????????????EGL_WIDTH,?1,
????????????EGL_HEIGHT,1,
????????????EGL_NONE
????};
????EGLint?eglMajVers,?eglMinVers;
????EGLint?numConfigs;

????int?resultCode?=?0;
????do
????{
????????//1.?獲取?EGLDisplay?對象,建立與本地窗口系統的連接
????????m_eglDisplay?=?eglGetDisplay(EGL_DEFAULT_DISPLAY);
????????if(m_eglDisplay?==?EGL_NO_DISPLAY)
????????{
????????????//Unable?to?open?connection?to?local?windowing?system
????????????LOGCATE("BgRender::CreateGlesEnv?Unable?to?open?connection?to?local?windowing?system");
????????????resultCode?=?-1;
????????????break;
????????}

????????//2.?初始化?EGL?方法
????????if(!eglInitialize(m_eglDisplay,?&eglMajVers,?&eglMinVers))
????????{
????????????//?Unable?to?initialize?EGL.?Handle?and?recover
????????????LOGCATE("BgRender::CreateGlesEnv?Unable?to?initialize?EGL");
????????????resultCode?=?-1;
????????????break;
????????}

????????LOGCATE("BgRender::CreateGlesEnv?EGL?init?with?version?%d.%d",?eglMajVers,?eglMinVers);

????????//3.?獲取?EGLConfig?對象,確定渲染表面的配置信息
????????if(!eglChooseConfig(m_eglDisplay,?confAttr,?&m_eglConf,?1,?&numConfigs))
????????{
????????????LOGCATE("BgRender::CreateGlesEnv?some?config?is?wrong");
????????????resultCode?=?-1;
????????????break;
????????}

????????//4.?創建渲染表面?EGLSurface,?使用?eglCreatePbufferSurface?創建屏幕外渲染區域
????????m_eglSurface?=?eglCreatePbufferSurface(m_eglDisplay,?m_eglConf,?surfaceAttr);
????????if(m_eglSurface?==?EGL_NO_SURFACE)
????????{
????????????switch(eglGetError())
????????????{
????????????????case?EGL_BAD_ALLOC:
????????????????????//?Not?enough?resources?available.?Handle?and?recover
????????????????????LOGCATE("BgRender::CreateGlesEnv?Not?enough?resources?available");
????????????????????break;
????????????????case?EGL_BAD_CONFIG:
????????????????????//?Verify?that?provided?EGLConfig?is?valid
????????????????????LOGCATE("BgRender::CreateGlesEnv?provided?EGLConfig?is?invalid");
????????????????????break;
????????????????case?EGL_BAD_PARAMETER:
????????????????????//?Verify?that?the?EGL_WIDTH?and?EGL_HEIGHT?are
????????????????????//?non-negative?values
????????????????????LOGCATE("BgRender::CreateGlesEnv?provided?EGL_WIDTH?and?EGL_HEIGHT?is?invalid");
????????????????????break;
????????????????case?EGL_BAD_MATCH:
????????????????????//?Check?window?and?EGLConfig?attributes?to?determine
????????????????????//?compatibility?and?pbuffer-texture?parameters
????????????????????LOGCATE("BgRender::CreateGlesEnv?Check?window?and?EGLConfig?attributes");
????????????????????break;
????????????}
????????}

????????//5.?創建渲染上下文?EGLContext
????????m_eglCtx?=?eglCreateContext(m_eglDisplay,?m_eglConf,?EGL_NO_CONTEXT,?ctxAttr);
????????if(m_eglCtx?==?EGL_NO_CONTEXT)
????????{
????????????EGLint?error?=?eglGetError();
????????????if(error?==?EGL_BAD_CONFIG)
????????????{
????????????????//?Handle?error?and?recover
????????????????LOGCATE("BgRender::CreateGlesEnv?EGL_BAD_CONFIG");
????????????????resultCode?=?-1;
????????????????break;
????????????}
????????}

????????//6.?綁定上下文
????????if(!eglMakeCurrent(m_eglDisplay,?m_eglSurface,?m_eglSurface,?m_eglCtx))
????????{
????????????LOGCATE("BgRender::CreateGlesEnv?MakeCurrent?failed");
????????????resultCode?=?-1;
????????????break;
????????}
????????LOGCATE("BgRender::CreateGlesEnv?initialize?success!");
????}
????while?(false);

????if?(resultCode?!=?0)
????{
????????LOGCATE("BgRender::CreateGlesEnv?fail");
????}

????return?resultCode;
}

//渲染
void?BgRender::Draw()
{
????LOGCATE("BgRender::Draw");
????if?(m_ProgramObj?==?GL_NONE)?return;
????glViewport(0,?0,?m_RenderImage.width,?m_RenderImage.height);

????//?Do?FBO?off?screen?rendering
????glUseProgram(m_ProgramObj);
????glBindFramebuffer(GL_FRAMEBUFFER,?m_FboId);

????glBindVertexArray(m_VaoIds[0]);
????glActiveTexture(GL_TEXTURE0);
????glBindTexture(GL_TEXTURE_2D,?m_ImageTextureId);
????glUniform1i(m_SamplerLoc,?0);

????if?(m_TexSizeLoc?!=?GL_NONE)?{
????????GLfloat?size[2];
????????size[0]?=?m_RenderImage.width;
????????size[1]?=?m_RenderImage.height;
????????glUniform2fv(m_TexSizeLoc,?1,?&size[0]);
????}

????//7.?渲染
????GO_CHECK_GL_ERROR();
????glDrawElements(GL_TRIANGLES,?6,?GL_UNSIGNED_SHORT,?(const?void?*)0);
????GO_CHECK_GL_ERROR();
????glBindVertexArray(GL_NONE);
????glBindTexture(GL_TEXTURE_2D,?GL_NONE);

????//一旦解綁?FBO?后面就不能調用?readPixels
????//glBindFramebuffer(GL_FRAMEBUFFER,?GL_NONE);

}

//釋放?GLES?環境
void?BgRender::DestroyGlesEnv()
{
????//8.?釋放?EGL?環境
????if?(m_eglDisplay?!=?EGL_NO_DISPLAY)?{
????????eglMakeCurrent(m_eglDisplay,?EGL_NO_SURFACE,?EGL_NO_SURFACE,?EGL_NO_CONTEXT);
????????eglDestroyContext(m_eglDisplay,?m_eglCtx);
????????eglDestroySurface(m_eglDisplay,?m_eglSurface);
????????eglReleaseThread();
????????eglTerminate(m_eglDisplay);
????}

????m_eglDisplay?=?EGL_NO_DISPLAY;
????m_eglSurface?=?EGL_NO_SURFACE;
????m_eglCtx?=?EGL_NO_CONTEXT;

}

Java 層的代碼,主要是一個 ImageView 用于展示渲染前后的圖像。

//?創建渲染對象
NativeBgRender?mBgRender?=?new?NativeBgRender();
//?初始化創建?GLES?環境
mBgRender.native_BgRenderInit();
//?加載圖片數據到紋理
loadRGBAImage(R.drawable.java,?mBgRender);
//?離屏渲染
mBgRender.native_BgRenderDraw();
//?從緩沖區讀出渲染后的圖像數據,加載到?ImageView
mImageView.setImageBitmap(createBitmapFromGLSurface(0,?0,?421,?586));
//?釋放?GLES?環境
mBgRender.native_BgRenderUnInit();


private?void?loadRGBAImage(int?resId,?NativeBgRender?render)?{
????InputStream?is?=?this.getResources().openRawResource(resId);
????Bitmap?bitmap;
????try?{
????????bitmap?=?BitmapFactory.decodeStream(is);
????????if?(bitmap?!=?null)?{
????????????int?bytes?=?bitmap.getByteCount();
????????????ByteBuffer?buf?=?ByteBuffer.allocate(bytes);
????????????bitmap.copyPixelsToBuffer(buf);
????????????byte[]?byteArray?=?buf.array();
????????????render.native_BgRenderSetImageData(byteArray,?bitmap.getWidth(),?bitmap.getHeight());
????????}
????}
????finally
????{
????????try
????????{
????????????is.close();
????????}
????????catch(IOException?e)
????????{
????????????e.printStackTrace();
????????}
????}
}

private?Bitmap?createBitmapFromGLSurface(int?x,?int?y,?int?w,?int?h)?{
????int?bitmapBuffer[]?=?new?int[w?*?h];
????int?bitmapSource[]?=?new?int[w?*?h];
????IntBuffer?intBuffer?=?IntBuffer.wrap(bitmapBuffer);
????intBuffer.position(0);
????try?{
????????GLES20.glReadPixels(x,?y,?w,?h,?GLES20.GL_RGBA,?GLES20.GL_UNSIGNED_BYTE,
????????????????intBuffer);
????????int?offset1,?offset2;
????????for?(int?i?=?0;?i?????????????offset1?=?i?*?w;????????????offset2?=?(h?-?i?-?1)?*?w;????????????for?(int?j?=?0;?j?????????????????int?texturePixel?=?bitmapBuffer[offset1?+?j];????????????????int?blue?=?(texturePixel?>>?16)?&?0xff;????????????????int?red?=?(texturePixel?<16)?&?0x00ff0000;????????????????int?pixel?=?(texturePixel?&?0xff00ff00)?|?red?|?blue;????????????????bitmapSource[offset2?+?j]?=?pixel;????????????}????????}????}?catch?(GLException?e)?{????????return?null;????}????return?Bitmap.createBitmap(bitmapSource,?w,?h,?Bitmap.Config.ARGB_8888);}

技術交流,歡迎加我微信:ezglumes ,拉你入技術交流群。

推薦閱讀:

音視頻面試基礎題

OpenGL ES 學習資源分享

一文讀懂 YUV 的采樣與格式

OpenGL 之 GPUImage 源碼分析

推薦幾個堪稱教科書級別的 Android 音視頻入門項目

覺得不錯,點個在看唄~

總結

以上是生活随笔為你收集整理的与context的关系_你还不知道 OpenGL ES 和 EGL 的关系?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。