| Summary: | [OpenGLES] SDL_EGL_UnloadLibrary is not called at all on SDL_Quit | ||
|---|---|---|---|
| Product: | SDL | Reporter: | kaisyu |
| Component: | video | Assignee: | Sam Lantinga <slouken> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | major | ||
| Priority: | P2 | ||
| Version: | HG 2.1 | ||
| Hardware: | All | ||
| OS: | All | ||
Can you check to make sure this is fixed? https://hg.libsdl.org/SDL/rev/a32fd6b7412b (In reply to Sam Lantinga from comment #1) > Can you check to make sure this is fixed? > https://hg.libsdl.org/SDL/rev/a32fd6b7412b I've tested 'testgles' and 'testgles2' with the revision a32fd6b7412b on my Ubuntu 16.04 desktop PC and they work perfectly. SDL_EGL_UnloadLibrary is called well all the time. Thanks. Thanks! |
In case of OpenGLES, the sequences of loading and unloading driver library should be like that: SDL_Init ... SDL_GL_LoadLibrary SDL_EGL_LoadLibrary ... SDL_Quit ... SDL_GL_UnloadLibrary SDL_EGL_UnloadLibrary ... However, according to my test results, the varible '_this->gl_config.driver_loaded' does not allow 'SDL_GL_UnloadLibrary' to call 'SDL_EGL_UnloadLibrary'. I have tested the 'testgles2' sample in SDL 2.0.5 official release source package on my Ubuntu 16.04 Desktop PC. Refer to the following logs: $ ./testgles2 INFO: SDL_VideoInit_REAL => driver_name:(null) INFO: SDL_GL_LoadLibrary_REAL => path:(null), _this:0x1c12d20 INFO: SDL_GL_LoadLibrary_REAL 2 => _this->gl_config.driver_loaded:0 INFO: SDL_GL_LoadLibrary_REAL 4 INFO: SDL_GL_LoadLibrary_REAL 5 => retval:0 INFO: SDL_GL_LoadLibrary_REAL 6 => _this->gl_config.driver_loaded:1 INFO: SDL_GL_LoadLibrary_REAL END => retval:0 INFO: SDL_GL_UnloadLibrary_REAL INFO: SDL_GL_UnloadLibrary_REAL 3 => _this->gl_config.driver_loaded:1 INFO: SDL_GL_UnloadLibrary_REAL 5 => _this->GL_UnloadLibrary:0x7efd41a4d4e0 INFO: SDL_GL_UnloadLibrary_REAL END INFO: SDL_GL_LoadLibrary_REAL => path:(null), _this:0x1c12d20 INFO: SDL_GL_LoadLibrary_REAL 2 => _this->gl_config.driver_loaded:0 INFO: SDL_GL_LoadLibrary_REAL 4 INFO: SDL_EGL_LoadLibrary => egl_path:(null) INFO: SDL_EGL_LoadLibrary => _this->gl_config.driver_loaded:1 INFO: SDL_GL_LoadLibrary_REAL 5 => retval:0 INFO: SDL_GL_LoadLibrary_REAL 6 => _this->gl_config.driver_loaded:2 INFO: SDL_GL_LoadLibrary_REAL END => retval:0 INFO: Screen bpp: 24 INFO: INFO: Vendor : VMware, Inc. INFO: Renderer : Gallium 0.4 on llvmpipe (LLVM 3.8, 256 bits) INFO: Version : OpenGL ES 3.0 Mesa 11.2.0 INFO: Extensions : GL_EXT_blend_minmax GL_EXT_multi_draw_arrays GL_EXT_texture_compression_dxt1 GL_EXT_texture_format_BGRA8888 GL_OES_compressed_ETC1_RGB8_texture GL_OES_depth24 GL_OES_element _index_uint GL_OES_fbo_render_mipmap GL_OES_mapbuffer GL_OES_rgb8_rgba8 GL_OES_standard_derivatives GL_OES_stencil8 GL_OES_texture_3D GL_OES_texture_float GL_OES_texture_float_linear GL_OES_te xture_half_float GL_OES_texture_half_float_linear GL_OES_texture_npot GL_OES_EGL_image GL_OES_depth_texture GL_OES_packed_depth_stencil GL_EXT_texture_type_2_10_10_10_REV GL_OES_get_program_bi nary GL_APPLE_texture_max_level GL_EXT_discard_framebuffer GL_EXT_read_format_bgra GL_NV_fbo_color_attachments GL_OES_EGL_image_external GL_OES_EGL_sync GL_OES_vertex_array_object GL_ANGLE_tex ture_compression_dxt3 GL_ANGLE_texture_compression_dxt5 GL_EXT_texture_rg GL_EXT_unpack_subimage GL_NV_draw_buffers GL_NV_read_buffer GL_NV_read_depth GL_NV_read_depth_stencil GL_NV_read_stenc il GL_EXT_draw_buffers GL_EXT_map_buffer_range GL_KHR_debug GL_OES_depth_texture_cube_map GL_OES_surfaceless_context GL_EXT_color_buffer_float GL_EXT_separate_shader_objects GL_EXT_shader_inte ger_mix GL_EXT_draw_elements_base_vertex GL_KHR_context_flush_control GL_OES_draw_elements_base_vertex GL_OES_texture_stencil8 GL_EXT_blend_func_extended INFO: INFO: SDL_GL_RED_SIZE: requested 5, got 8 INFO: SDL_GL_GREEN_SIZE: requested 5, got 8 INFO: SDL_GL_BLUE_SIZE: requested 5, got 8 INFO: SDL_GL_DEPTH_SIZE: requested 16, got 16 INFO: 31.38 frames per second INFO: SDL_GL_UnloadLibrary_REAL INFO: SDL_GL_UnloadLibrary_REAL 3 => _this->gl_config.driver_loaded:2 INFO: SDL_GL_UnloadLibrary_REAL 4 => _this->gl_config.driver_loaded:1 Here is my modified code for logging: src/video/SDL_egl.c void SDL_EGL_UnloadLibrary(_THIS) { SDL_Log("%s => _this->egl_data:%p", __FUNCTION__, _this->egl_data); if (_this->egl_data) { SDL_Log("%s 2 => egl_display:%p", __FUNCTION__, _this->egl_data->egl_display); if (_this->egl_data->egl_display) { _this->egl_data->eglTerminate(_this->egl_data->egl_display); _this->egl_data->egl_display = NULL; } SDL_Log("%s 3 => dll_handle:%p", __FUNCTION__, _this->egl_data->dll_handle); if (_this->egl_data->dll_handle) { SDL_UnloadObject(_this->egl_data->dll_handle); _this->egl_data->dll_handle = NULL; } SDL_Log("%s 4 => egl_dll_handle:%p", __FUNCTION__, _this->egl_data->egl_dll_handle); if (_this->egl_data->egl_dll_handle) { SDL_UnloadObject(_this->egl_data->egl_dll_handle); _this->egl_data->egl_dll_handle = NULL; } SDL_Log("%s 5", __FUNCTION__); SDL_free(_this->egl_data); _this->egl_data = NULL; } SDL_Log("%s END", __FUNCTION__); } int SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display) { void *dll_handle = NULL, *egl_dll_handle = NULL; /* The naming is counter intuitive, but hey, I just work here -- Gabriel */ const char *path = NULL; #if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT const char *d3dcompiler; #endif SDL_Log("%s => egl_path:%s", __FUNCTION__, egl_path); if (_this->egl_data) { return SDL_SetError("OpenGL ES context already created"); } _this->egl_data = (struct SDL_EGL_VideoData *) SDL_calloc(1, sizeof(SDL_EGL_VideoData)); if (!_this->egl_data) { return SDL_OutOfMemory(); } #if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT d3dcompiler = SDL_GetHint(SDL_HINT_VIDEO_WIN_D3DCOMPILER); if (!d3dcompiler) { if (WIN_IsWindowsVistaOrGreater()) { d3dcompiler = "d3dcompiler_46.dll"; } else { d3dcompiler = "d3dcompiler_43.dll"; } } if (SDL_strcasecmp(d3dcompiler, "none") != 0) { SDL_LoadObject(d3dcompiler); } #endif /* A funny thing, loading EGL.so first does not work on the Raspberry, so we load libGL* first */ path = SDL_getenv("SDL_VIDEO_GL_DRIVER"); if (path != NULL) { egl_dll_handle = SDL_LoadObject(path); } if (egl_dll_handle == NULL) { if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) { if (_this->gl_config.major_version > 1) { path = DEFAULT_OGL_ES2; egl_dll_handle = SDL_LoadObject(path); } else { path = DEFAULT_OGL_ES; egl_dll_handle = SDL_LoadObject(path); if (egl_dll_handle == NULL) { path = DEFAULT_OGL_ES_PVR; egl_dll_handle = SDL_LoadObject(path); } } } #ifdef DEFAULT_OGL else { path = DEFAULT_OGL; egl_dll_handle = SDL_LoadObject(path); } #endif } _this->egl_data->egl_dll_handle = egl_dll_handle; if (egl_dll_handle == NULL) { return SDL_SetError("Could not initialize OpenGL / GLES library"); } /* Loading libGL* in the previous step took care of loading libEGL.so, but we future proof by double checking */ if (egl_path != NULL) { dll_handle = SDL_LoadObject(egl_path); } /* Try loading a EGL symbol, if it does not work try the default library paths */ if (dll_handle == NULL || SDL_LoadFunction(dll_handle, "eglChooseConfig") == NULL) { if (dll_handle != NULL) { SDL_UnloadObject(dll_handle); } path = SDL_getenv("SDL_VIDEO_EGL_DRIVER"); if (path == NULL) { path = DEFAULT_EGL; } dll_handle = SDL_LoadObject(path); if (dll_handle == NULL || SDL_LoadFunction(dll_handle, "eglChooseConfig") == NULL) { if (dll_handle != NULL) { SDL_UnloadObject(dll_handle); } return SDL_SetError("Could not load EGL library"); } SDL_ClearError(); } _this->egl_data->dll_handle = dll_handle; /* Load new function pointers */ LOAD_FUNC(eglGetDisplay); LOAD_FUNC(eglInitialize); LOAD_FUNC(eglTerminate); LOAD_FUNC(eglGetProcAddress); LOAD_FUNC(eglChooseConfig); LOAD_FUNC(eglGetConfigAttrib); LOAD_FUNC(eglCreateContext); LOAD_FUNC(eglDestroyContext); LOAD_FUNC(eglCreateWindowSurface); LOAD_FUNC(eglDestroySurface); LOAD_FUNC(eglMakeCurrent); LOAD_FUNC(eglSwapBuffers); LOAD_FUNC(eglSwapInterval); LOAD_FUNC(eglWaitNative); LOAD_FUNC(eglWaitGL); LOAD_FUNC(eglBindAPI); LOAD_FUNC(eglQueryString); #if !defined(__WINRT__) _this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display); if (!_this->egl_data->egl_display) { return SDL_SetError("Could not get EGL display"); } if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) { return SDL_SetError("Could not initialize EGL"); } #endif /* FIXME: Since 'driver_loaded' will increase in the 'SDL_GL_LoadLibrary' function, the following line must be commented out. */ _this->gl_config.driver_loaded = 1; SDL_Log("%s => _this->gl_config.driver_loaded:%d", __FUNCTION__, _this->gl_config.driver_loaded); if (path) { SDL_strlcpy(_this->gl_config.driver_path, path, sizeof(_this->gl_config.driver_path) - 1); } else { *_this->gl_config.driver_path = '\0'; } return 0; } ---- src/video/SDL_video.c SDL_GL_LoadLibrary(const char *path) { int retval; SDL_Log("%s => path:%s, _this:%p", __FUNCTION__, path, _this); if (!_this) { return SDL_UninitializedVideo(); } SDL_Log("%s 2 => _this->gl_config.driver_loaded:%d", __FUNCTION__, _this->gl_config.driver_loaded); if (_this->gl_config.driver_loaded) { if (path && SDL_strcmp(path, _this->gl_config.driver_path) != 0) { SDL_Log("%s ERROR 1", __FUNCTION__); return SDL_SetError("OpenGL library already loaded"); } SDL_Log("%s 3", __FUNCTION__); retval = 0; } else { if (!_this->GL_LoadLibrary) { SDL_Log("%s ERROR 2", __FUNCTION__); return SDL_SetError("No dynamic GL support in video driver"); } SDL_Log("%s 4", __FUNCTION__); retval = _this->GL_LoadLibrary(_this, path); } SDL_Log("%s 5 => retval:%d", __FUNCTION__, retval); if (retval == 0) { ++_this->gl_config.driver_loaded; SDL_Log("%s 6 => _this->gl_config.driver_loaded:%d", __FUNCTION__, _this->gl_config.driver_loaded); } else { SDL_Log("%s 7", __FUNCTION__); if (_this->GL_UnloadLibrary) { SDL_Log("%s 8", __FUNCTION__); _this->GL_UnloadLibrary(_this); } } SDL_Log("%s END => retval:%d", __FUNCTION__, retval); return (retval); } void SDL_GL_UnloadLibrary(void) { SDL_Log("%s", __FUNCTION__); if (!_this) { SDL_Log("%s 2", __FUNCTION__); SDL_UninitializedVideo(); return; } SDL_Log("%s 3 => _this->gl_config.driver_loaded:%d", __FUNCTION__, _this->gl_config.driver_loaded); if (_this->gl_config.driver_loaded > 0) { if (--_this->gl_config.driver_loaded > 0) { SDL_Log("%s 4 => _this->gl_config.driver_loaded:%d", __FUNCTION__, _this->gl_config.driver_loaded); return; } SDL_Log("%s 5 => _this->GL_UnloadLibrary:%p", __FUNCTION__, _this->GL_UnloadLibrary); if (_this->GL_UnloadLibrary) { _this->GL_UnloadLibrary(_this); } } SDL_Log("%s END", __FUNCTION__); } ---- I guess that it is a kind of old bugs which are not found yet. Just in case if it is intended code, please let me know why. After commenting out '_this->gl_config.driver_loaded = 1;' line in the 'SDL_EGL_LoadLibrary' function, 'SDL_EGL_UnloadLibrary' is called normally. Refer to the following logs: $ ./testgles2 INFO: SDL_VideoInit_REAL => driver_name:(null) INFO: SDL_GL_LoadLibrary_REAL => path:(null), _this:0x1c90d20 INFO: SDL_GL_LoadLibrary_REAL 2 => _this->gl_config.driver_loaded:0 INFO: SDL_GL_LoadLibrary_REAL 4 INFO: SDL_GL_LoadLibrary_REAL 5 => retval:0 INFO: SDL_GL_LoadLibrary_REAL 6 => _this->gl_config.driver_loaded:1 INFO: SDL_GL_LoadLibrary_REAL END => retval:0 INFO: SDL_GL_UnloadLibrary_REAL INFO: SDL_GL_UnloadLibrary_REAL 3 => _this->gl_config.driver_loaded:1 INFO: SDL_GL_UnloadLibrary_REAL 5 => _this->GL_UnloadLibrary:0x7f486e1ab4e0 INFO: SDL_GL_UnloadLibrary_REAL END INFO: SDL_GL_LoadLibrary_REAL => path:(null), _this:0x1c90d20 INFO: SDL_GL_LoadLibrary_REAL 2 => _this->gl_config.driver_loaded:0 INFO: SDL_GL_LoadLibrary_REAL 4 INFO: SDL_EGL_LoadLibrary => egl_path:(null) INFO: SDL_EGL_LoadLibrary => _this->gl_config.driver_loaded:0 INFO: SDL_GL_LoadLibrary_REAL 5 => retval:0 INFO: SDL_GL_LoadLibrary_REAL 6 => _this->gl_config.driver_loaded:1 INFO: SDL_GL_LoadLibrary_REAL END => retval:0 INFO: Screen bpp: 24 INFO: INFO: Vendor : VMware, Inc. INFO: Renderer : Gallium 0.4 on llvmpipe (LLVM 3.8, 256 bits) INFO: Version : OpenGL ES 3.0 Mesa 11.2.0 INFO: Extensions : GL_EXT_blend_minmax GL_EXT_multi_draw_arrays GL_EXT_texture_compression_dxt1 GL_EXT_texture_format_BGRA8888 GL_OES_compressed_ETC1_RGB8_texture GL_OES_depth24 GL_OES_element _index_uint GL_OES_fbo_render_mipmap GL_OES_mapbuffer GL_OES_rgb8_rgba8 GL_OES_standard_derivatives GL_OES_stencil8 GL_OES_texture_3D GL_OES_texture_float GL_OES_texture_float_linear GL_OES_te xture_half_float GL_OES_texture_half_float_linear GL_OES_texture_npot GL_OES_EGL_image GL_OES_depth_texture GL_OES_packed_depth_stencil GL_EXT_texture_type_2_10_10_10_REV GL_OES_get_program_bi nary GL_APPLE_texture_max_level GL_EXT_discard_framebuffer GL_EXT_read_format_bgra GL_NV_fbo_color_attachments GL_OES_EGL_image_external GL_OES_EGL_sync GL_OES_vertex_array_object GL_ANGLE_tex ture_compression_dxt3 GL_ANGLE_texture_compression_dxt5 GL_EXT_texture_rg GL_EXT_unpack_subimage GL_NV_draw_buffers GL_NV_read_buffer GL_NV_read_depth GL_NV_read_depth_stencil GL_NV_read_stenc il GL_EXT_draw_buffers GL_EXT_map_buffer_range GL_KHR_debug GL_OES_depth_texture_cube_map GL_OES_surfaceless_context GL_EXT_color_buffer_float GL_EXT_separate_shader_objects GL_EXT_shader_inte ger_mix GL_EXT_draw_elements_base_vertex GL_KHR_context_flush_control GL_OES_draw_elements_base_vertex GL_OES_texture_stencil8 GL_EXT_blend_func_extended INFO: INFO: SDL_GL_RED_SIZE: requested 5, got 8 INFO: SDL_GL_GREEN_SIZE: requested 5, got 8 INFO: SDL_GL_BLUE_SIZE: requested 5, got 8 INFO: SDL_GL_DEPTH_SIZE: requested 16, got 16 INFO: 29.66 frames per second INFO: SDL_GL_UnloadLibrary_REAL INFO: SDL_GL_UnloadLibrary_REAL 3 => _this->gl_config.driver_loaded:1 INFO: SDL_GL_UnloadLibrary_REAL 5 => _this->GL_UnloadLibrary:0x7f486e1890e0 INFO: SDL_EGL_UnloadLibrary => _this->egl_data:0x1cdbda0 INFO: SDL_EGL_UnloadLibrary 2 => egl_display:0x1d0be40 INFO: SDL_EGL_UnloadLibrary 3 => dll_handle:0x1d2d910 INFO: SDL_EGL_UnloadLibrary 4 => egl_dll_handle:0x1d2d460 INFO: SDL_EGL_UnloadLibrary 5 INFO: SDL_EGL_UnloadLibrary END INFO: SDL_GL_UnloadLibrary_REAL END