2012-12-27 44 views
15

我正在爲使用opengl/egl的Android進行開發。我的應用程序需要第二個上下文來從第二個線程加載紋理。爲什麼eglMakeCurrent()與EGL_BAD_MATCH失敗?

我的代碼工作正常,在Android 2.3,但是當我嘗試4.0.3 Android設備或仿真器上的代碼,eglMakeCurrent()失敗,EGL_BAD_MATCH。

第二上下文的初始化和它的像素緩衝區中的所有工作正常了,所以我不知道從哪裏開始尋找這個錯誤。

這是初始化代碼:

ANativeWindow *window = (ANativeWindow*)displaySurface; 

EGLint dummy, format; 

display = eglGetDisplay(EGL_DEFAULT_DISPLAY); 

eglInitialize(display, 0, 0); 

EGLint contextAttribs[] = 
{ 
    EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE 
}; 

const EGLint configAttribs[] = 
{ 
    EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 
    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 
    EGL_BLUE_SIZE, 8, 
    EGL_GREEN_SIZE, 8, 
    EGL_RED_SIZE, 8, 
    EGL_ALPHA_SIZE, 8, 
    EGL_BUFFER_SIZE, 32, 
    EGL_DEPTH_SIZE, 24, 
    EGL_NONE 
}; 

EGLint numConfigs; 
EGLConfig config; 

eglChooseConfig(display, configAttribs, &config, 1, &numConfigs); 
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format); 
ANativeWindow_setBuffersGeometry(window, 0, 0, format); 

surface = eglCreateWindowSurface(display, config, window, NULL); 
if(surface == NULL) 
    Trace("error creating window surface: " + GetEglError()); 

context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs); 
if(context == NULL) 
    Trace("error creating main context: " + GetEglError()); 

const EGLint auxConfigAttribs[] = 
{ 
    EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, 
    EGL_BLUE_SIZE, 8, 
    EGL_GREEN_SIZE, 8, 
    EGL_RED_SIZE, 8, 
    EGL_ALPHA_SIZE, 8, 
    EGL_DEPTH_SIZE, 0, 
    EGL_STENCIL_SIZE, 0, 
    EGL_NONE 
}; 

EGLint pbufferAttribs[] = 
{ 
    EGL_WIDTH, 1, 
    EGL_HEIGHT, 1, 
    EGL_TEXTURE_TARGET, EGL_NO_TEXTURE, 
    EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE, 
    EGL_NONE 
}; 

EGLint auxNumConfigs; 
EGLConfig auxConfig; 

eglChooseConfig(display, auxConfigAttribs, &auxConfig, 1, &auxNumConfigs); 

auxSurface = eglCreatePbufferSurface(display, auxConfig, pbufferAttribs); 
if(auxSurface == NULL) 
    Trace("error creating pbuffer surface: " + GetEglError()); 

auxContext = eglCreateContext(display, auxConfig, context, contextAttribs); 
if(auxSurface == NULL) 
    Trace("error creating auxilliary context: " + GetEglError()); 

if(!eglMakeCurrent(display, surface, surface, context)) 
    Trace("could not make main context current: " + GetEglError()); 

在我的Android 2.3設備(HTC Desire的),上面的初始化代碼作品完美,我可以使auxContext電流,負載紋理就好了。但在我的Android 4.0.3設備(Samsung Nexus S)和我的Android 4.1設備(Galaxy Note 2)eglMakeCurrent()失敗後,EGL_BAD_MATCH成功初始化後失敗。

有誰知道爲什麼我會收到此錯誤?

+1

我注意到有時從Galaxy S2調用eglMakeCurrent時會得到EGL_BAD_MATCH。我相信我已經將錯誤條件縮小到了a)在不同的線程上創建上下文而不是當前的上下文,或者b)使上下文成爲當前第二線程而不從第一線程釋放它。 – nmr

+0

看到的解決方案 – bitwise

回答

11

啊,這是我真正有所瞭解。 ;)[花了5年時間完成各種EGL實現的最佳部分]。

我敢肯定你的surface是不同的格式,以實際的顯示面。我不確定究竟會發生什麼差別,或者你需要改變什麼。 EGL_DEPTH_SIZE也許?你可以嘗試枚舉可用的模式,看看是否有可能。我知道,這有點痛苦,但過去我曾經在那裏做過幾次 - 不同之處在於我通常可以通過EGL源代碼查看並確定我做錯了什麼...... ;)

+0

的東西是明顯的答案的評論,即makeCurrent()工作正常,在所有手機上的主要方面,而不是在其他兩款手機的第二/共享上下文。然而,我發現一個帖子,也建議像你在說什麼:http://stackoverflow.com/questions/7523597/egl-bad-match-with-droid-droid-2 - 我可能會回來一個不同的配置比我要求**表面**,但然後創建與**請求**配置而不是**返回**配置,這可能是批量匹配的原因的像素緩衝區。 – bitwise

+1

是的,完全可以在一個,兩個,五個或十六個電話上運行設置,但在一個或兩個電話上失敗。我有一次負責測試EGL驅動程序的硬件特定模型,它使用了不同於我們可用的其他硬件的一組EGL配置。因此,無論何時將新測試引入測試套件,它幾乎肯定會在我的硬件上崩潰,但可以在其他所有硬件上運行。接下來的挑戰是在所有平臺上尋找一種「良好的折衷方案」 - 或者添加一些代碼來處理「如果我們有HW X,那麼做,否則做」。 –

+6

我試着枚舉所有的配置,這導致了兩個發現。首先,幾乎所有支持EGL_WINDOW_BIT的顯示配置都支持EGL_PBUFFER_BIT,這使得創建兩個單獨的配置完全沒有意義。第二件事情是,eglChooseConfig在所有Android設備/版本上似乎都不能正常工作。這可以通過設計來實現,因爲這發生在沒有GPU支持的模擬器之一上,但是我回來的配置甚至沒有滿足我饋入的規格。所以我編寫了自己的eglChooseConfig,並使用了相同的配置兩個表面,現在一切正常。 – bitwise

5

如果你得到這個錯誤,但沒有處理這個表面或紋理的東西,去運行並輸入.android 去AVD和你目前的模擬器通常在.img文件上刪除用戶日期文件,重新啓動你的模擬器然後測試。這適用於我,如果它發生在您的設備上進行測試時,清除數據並重新啓動您的應用程序。歡呼那些認爲這有幫助的人。

+0

這個問題被標記爲近2年前回答.. – bitwise

+13

是的,我知道,但由於某種原因,這個錯誤發生在我身上,而我接受的答案是沒有幫助我的情況。然後我解決它並將其發佈到此處。所以如果有人遇到這種錯誤,他們可能會覺得它很有用。 – ralphgabb

-2
int config_attrs[] = 
    { 
     EGL_RED_SIZE, 8, 

EGL_GREEN_SIZE, 8, 

     EGL_BLUE_SIZE, 8, 

     EGL_ALPHA_SIZE, 8, 

     EGL_BUFFER_SIZE, 16, 

     EGL_SURFACE_TYPE, EGL_WINDOW_BIT, 

     EGL_DEPTH_SIZE, 16, 

     EGL_STENCIL_SIZE, 8, 

     EGL_SAMPLE_BUFFERS, 0, 

     EGL_SAMPLES, 0, 
#ifdef _IRR_COMPILE_WITH_OGLES1_  
     EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, 
#else 
     EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, 
#endif 
     EGL_NONE, 0 
    }; 

    int context_attrs[] = 
    { 
#ifdef _IRR_COMPILE_WITH_OGLES1_   
     EGL_CONTEXT_CLIENT_VERSION, 1, 
#else 
     EGL_CONTEXT_CLIENT_VERSION, 2, 
#endif 
     EGL_NONE, 0 
    }; 

///// 
//ogles1 and ogles2 use different libEGL.dll, make sure 

s_egl_display = eglGetDisplay (g_hDC); 

    if (s_egl_display == EGL_NO_DISPLAY) 
    { 
     return; 
    } 

    if (!eglInitialize (s_egl_display, &major, &minor)) 
    { 
     return; 
    } 

    if (!eglChooseConfig (s_egl_display, config_attrs, &g_egl_config, 1, &configs) || (configs != 1)) 
    { 
     return; 
    } 

    s_egl_surface = eglCreateWindowSurface (s_egl_display, g_egl_config, g_hWnd, 0); 
    if (eglGetError() != EGL_SUCCESS) 
    { 
     return; 
    } 

    eRet = eglBindAPI(EGL_OPENGL_ES_API); 

    s_egl_context = eglCreateContext (s_egl_display, g_egl_config, EGL_NO_CONTEXT, context_attrs); 
    if (eglGetError() != EGL_SUCCESS) 
    { 
     return; 
    } 

    eglMakeCurrent (s_egl_display, s_egl_surface, s_egl_surface, s_egl_context); 
    if (eglGetError() != EGL_SUCCESS) 
    { 
     return; 
    } 
+1

請用一些詞語指導我們。 –