目錄
創(chuàng)新互聯(lián)公司成立與2013年,是專業(yè)互聯(lián)網(wǎng)技術服務公司,擁有項目網(wǎng)站建設、成都做網(wǎng)站網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元天水做網(wǎng)站,已為上家服務,為天水各地企業(yè)和個人服務,聯(lián)系電話:18982081108
零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 基礎
零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 特效
零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 轉(zhuǎn)場
零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES 函數(shù)
零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES GPUImage 使用
零基礎 OpenGL ES 學習路線推薦 : OpenGL ES 學習目錄 >> OpenGL ES GLSL 編程
EGLNativeDisplayType – 系統(tǒng)顯示類型,標識你所開發(fā)設備的物理屏幕,DX/OPenGL ES/Metal/Vulkan….
EGLNativeWindowType – 系統(tǒng)窗口,渲染顯示的窗口句柄
EGLDisplay – 關聯(lián) EGLNativeDisplayType 系統(tǒng)物理屏幕的通用數(shù)據(jù)類型,是平臺上 WGL / GLX / AGL 的等價物
EGLSurface – 渲染區(qū)域,相當于 OpenGL ES 繪圖的畫布 (一塊內(nèi)存空間),用戶想繪制的信息首先都要先繪制到 EGLSurface 上,然后通過 EGLDisplay 顯示
EGLConfig – 對 EGLSurface 的 EGL 配置,可以理解為繪制目標 framebuffer 的配置屬性
EGLContext – OpenGL ES 圖形上下文
EGLContext 上下文包含了操作所需的所有狀態(tài)信息,OpenGL ES 必須有一個可用的上下文才能進行繪圖。
創(chuàng)建了 EGLSurface 和 EGLContext 之后,因為可能有多個 EGLSurface 和 EGLContext ,所以需要通過 eglMakeCurrent 綁定 EGLSurface 來指定當前上下文
/*描述:創(chuàng)建 OpenGL ES EGLSurface
*參數(shù):
* display:指定顯示的連接
* draw:EGL 繪圖表面
* read:EGL 繪圖表面
* context:通過 eglCreateContext 創(chuàng)建的上下文
*
*返回值:成功是返回 EGL_TRUE,失敗時返回 EGL_FALSE
*/
EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(
EGLDisplay display,
EGLSurface draw,
EGLSurface read,
EGLContext context);
相關錯誤碼:
EGL_BAD_MATCH :提供了與窗口屬性不匹配的 EGLConfig,或該 EGLConfig 不支持渲染EGL_BAD_DISPLAY
EGL_NOT_INITIALIZED
EGL_BAD_SURFACE
EGL_BAD_CONTEXT
EGL_BAD_MATCH
EGL_BAD_ACCESS
EGL_BAD_NATIVE_PIXMAP
EGL_BAD_NATIVE_WINDOW
EGL_BAD_CURRENT_SURFACE
EGL_BAD_ALLOC
EGL_CONTEXT_LOST
/******************************************************************************************/
//@Author:猿說編程
//@Blog(個人博客地址): www.codersrc.com
//@File:OpenGL ES EGL eglMakeCurrent
//@Time:2022/08/04 07:30
//@Motto:不積跬步無以至千里,不積小流無以成江海,程序人生的精彩需要堅持不懈地積累!
/******************************************************************************************/
EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw,
EGLSurface read, EGLContext ctx)
{
if (egl_display_t::is_valid(dpy) == EGL_FALSE)
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
if (draw) {
egl_surface_t* s = (egl_surface_t*)draw;
if (!s->isValid())
return setError(EGL_BAD_SURFACE, EGL_FALSE);
if (s->dpy != dpy)
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
// TODO: check that draw is compatible with the context
}
if (read && read!=draw) {
egl_surface_t* s = (egl_surface_t*)read;
if (!s->isValid())
return setError(EGL_BAD_SURFACE, EGL_FALSE);
if (s->dpy != dpy)
return setError(EGL_BAD_DISPLAY, EGL_FALSE);
// TODO: check that read is compatible with the context
}
EGLContext current_ctx = EGL_NO_CONTEXT;
if ((read == EGL_NO_SURFACE && draw == EGL_NO_SURFACE) && (ctx != EGL_NO_CONTEXT))
return setError(EGL_BAD_MATCH, EGL_FALSE);
if ((read != EGL_NO_SURFACE || draw != EGL_NO_SURFACE) && (ctx == EGL_NO_CONTEXT))
return setError(EGL_BAD_MATCH, EGL_FALSE);
if (ctx == EGL_NO_CONTEXT) {
// if we're detaching, we need the current context
current_ctx = (EGLContext)getGlThreadSpecific();
} else {
egl_context_t* c = egl_context_t::context(ctx);
egl_surface_t* d = (egl_surface_t*)draw;
egl_surface_t* r = (egl_surface_t*)read;
if ((d && d->ctx && d->ctx != ctx) ||
(r && r->ctx && r->ctx != ctx)) {
// one of the surface is bound to a context in another thread
return setError(EGL_BAD_ACCESS, EGL_FALSE);
}
}
// 調(diào)用makeCurrent,將gl和當前的進程進行綁定。
ogles_context_t* gl = (ogles_context_t*)ctx;
if (makeCurrent(gl) == 0) {
if (ctx) {
egl_context_t* c = egl_context_t::context(ctx);
egl_surface_t* d = (egl_surface_t*)draw;
egl_surface_t* r = (egl_surface_t*)read;
if (c->draw) {// 斷開當前draw surface的綁定
egl_surface_t* s = reinterpret_cast(c->draw);
s->disconnect();
s->ctx = EGL_NO_CONTEXT;
if (s->zombie)
delete s;
}
if (c->read) {
// FIXME: unlock/disconnect the read surface too
}
// 將draw & read 綁定到當前的上下文。
c->draw = draw;
c->read = read;
if (c->flags & egl_context_t::NEVER_CURRENT) {
c->flags &= ~egl_context_t::NEVER_CURRENT;
GLint w = 0;
GLint h = 0;
if (draw) {
w = d->getWidth();
h = d->getHeight();
}
ogles_surfaceport(gl, 0, 0);
ogles_viewport(gl, 0, 0, w, h);
ogles_scissor(gl, 0, 0, w, h);
}
if (d) {
if (d->connect() == EGL_FALSE) {
return EGL_FALSE;
}
d->ctx = ctx;
d->bindDrawSurface(gl);
}
if (r) {
// FIXME: lock/connect the read surface too
r->ctx = ctx;
r->bindReadSurface(gl);
}
} else {//取消綁定
// if surfaces were bound to the context bound to this thread
// mark then as unbound.
if (current_ctx) {
egl_context_t* c = egl_context_t::context(current_ctx);
egl_surface_t* d = (egl_surface_t*)c->draw;
egl_surface_t* r = (egl_surface_t*)c->read;
if (d) {
c->draw = 0;
d->disconnect();
d->ctx = EGL_NO_CONTEXT;
if (d->zombie)
delete d;
}
if (r) {
c->read = 0;
r->ctx = EGL_NO_CONTEXT;
// FIXME: unlock/disconnect the read surface too
}
}
}
return EGL_TRUE;
}
return setError(EGL_BAD_ACCESS, EGL_FALSE);
}
一個應用程序可能創(chuàng)建多個 EGLContext 用于不同的用途,所以我們需要關聯(lián)特定的 EGLContext 和渲染表面。這一過程被稱作“指定當前上下文”,使用如下調(diào)用,關聯(lián)特定的 EGLContext 和某個 EGLSurface:
/******************************************************************************************/
//@Author:猿說編程
//@Blog(個人博客地址): www.codersrc.com
//@File:OpenGL ES EGL eglMakeCurrent
//@Time:2022/08/04 07:30
//@Motto:不積跬步無以至千里,不積小流無以成江海,程序人生的精彩需要堅持不懈地積累!
/******************************************************************************************/
EGLBoolean initializeWindow(EGLNativeWindow nativeWindow)
{
const EGLint configAttribs[] = {EGL_RENDER_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_DEPTH_SIZE, 24,
EGL_NONE};
const EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY)
if (display == EGL_NO_DISPLAY)
{
return EGL_FALSE;
}
EGLint major, minor;
if (!eglInitialize(display, &major, &minor))
{
return EGL_FALSE;
}
EGLConfig config;
EGLint numConfigs;
if (!eglChooseConfig(display, configAttribs, &config, 1, &numConfigs))
{
return EGL_FALSE;
}
EGLSurface window = eglCreateWindowSurface(display, config, nativeWindow, NULL);
if (window == EGL_NO_SURFACE)
{
return EGL_FALSE;
}
//創(chuàng)建上下文
EGLContext context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
if (context == EGL_NO_CONTEXT)
{
return EGL_FALSE;
}
//綁定使用當前上下文
if (!eglMakeCurrent(display, window, window, context))
{
return EGL_FALSE;
}
return EGL_TRUE;
}
某些情況下,我們想創(chuàng)建、使用多個 EGLContext ,對于這種情況,需要注意以下幾個情況:
EGLContext
。EGLContext
上。EGLContext
上,取決于使用的 GPU 的具體實現(xiàn),可能成功,也可能失敗。共享 EGLContext 這種方式在加載階段很有用。由于上傳數(shù)據(jù)到 GPU(尤其是紋理數(shù)據(jù)(textures))這類操作很重,如果想要維持幀率穩(wěn)定,應該在另一個線程進行上傳。
然而,對于上面多個 EGLContext 的 3 種情況的限制,必須在第一個 EGLContext 之外,創(chuàng)建第二個 EGLContext ,這個 EGLContext 將使用第一個 EGLContext 使用的內(nèi)部狀態(tài)信息。這兩個 Context 即共享 Context 上下文。
需要注意的是:這****兩個 EGLContext 共享的只是內(nèi)部狀態(tài)信息,它們兩個并不共享調(diào)用緩存(每個 EGLContext 各自擁有一個調(diào)用緩存)。
創(chuàng)建第二個 EGLContext 的方法:
/*描述:創(chuàng)建 OpenGL ES 上下文 EGLContext
*參數(shù):
* display:指定顯示的連接
* config:配置 EGLConfig
* share_context:允許其它 EGLContext 共享數(shù)據(jù),使用 EGL_NO_CONTEXT 表示不共享
* attribList:指定操作的屬性列表,只能接受一個屬性 EGL_CONTEXT_CLIENT_VERSION(設置 OpenGL ES 版本)
*
*返回值:成功時返回新創(chuàng)建的 EGLContext,失敗時返回 EGL_NO_CONTEXT
*/
EGLContext eglCreateContext(
EGLDisplay display,
EGLConfig config,
EGLContext share_context,
EGLint const * attrib_list);
注意:第三個參數(shù)
share_context
是最重要的,它就是第一個 Context ,表示共享上下文
在第二個線程,不進行任何的繪制,只進行上傳數(shù)據(jù)到 GPU 的操作。所以,給第二個 Context 的 Surface 應該是一個像素緩沖 (pixel buffer) Surface。
EGLSurface eglCreatePbufferSurface(
EGLDisplay display,
EGLConfig config,
EGLint const * attrib_list);
本文由博客 - 猿說編程 猿說編程 發(fā)布!