diff --git a/examples/common/entry/entry.cpp b/examples/common/entry/entry.cpp index adabe7d89..4407b69ba 100644 --- a/examples/common/entry/entry.cpp +++ b/examples/common/entry/entry.cpp @@ -29,6 +29,9 @@ namespace entry static uint32_t s_width = ENTRY_DEFAULT_WIDTH; static uint32_t s_height = ENTRY_DEFAULT_HEIGHT; static bool s_exit = false; +#if BX_PLATFORM_ANDROID + extern WindowState s_window[ENTRY_CONFIG_MAX_WINDOWS]; +#endif // BX_PLATFORM_ANDROID static void resetMainWindow(uint32_t _width, uint32_t _height, uint32_t _reset) { @@ -45,6 +48,9 @@ namespace entry swapChain.width = _width; swapChain.height = _height; swapChain.flags = _reset & kSwapChainFlags; +#if BX_PLATFORM_ANDROID + swapChain.nwh = s_window[0].m_nwh; +#endif // BX_PLATFORM_ANDROID bgfx::reset(_reset & ~kSwapChainFlags, &swapChain); } @@ -902,6 +908,20 @@ restart: break; case Event::Window: +#if BX_PLATFORM_ANDROID + { + const WindowEvent* window = static_cast(ev); + if (window->m_handle.idx == 0) + { + s_window[0].m_nwh = window->m_nwh; + if (NULL != window->m_nwh) + { + handle = window->m_handle; + needReset = true; + } + } + } +#endif // BX_PLATFORM_ANDROID break; case Event::Suspend: diff --git a/examples/common/entry/entry_android.cpp b/examples/common/entry/entry_android.cpp index 6ba599af0..d7451babd 100644 --- a/examples/common/entry/entry_android.cpp +++ b/examples/common/entry/entry_android.cpp @@ -226,6 +226,7 @@ namespace entry DBG("ANativeWindow width %d, height %d", width, height); WindowHandle defaultWindow = { 0 }; + m_eventQueue.postWindowEvent(defaultWindow, m_window); m_eventQueue.postSizeEvent(defaultWindow, width, height); if (!m_thread.isRunning() ) @@ -240,6 +241,8 @@ namespace entry // terminated. Upon receiving this command, android_app->window still // contains the existing window; after calling android_app_exec_cmd // it will be set to NULL. + m_window = NULL; + m_eventQueue.postWindowEvent({ 0 }); break; case APP_CMD_WINDOW_RESIZED: diff --git a/include/bgfx/bgfx.h b/include/bgfx/bgfx.h index 0307469f0..aec3e4845 100644 --- a/include/bgfx/bgfx.h +++ b/include/bgfx/bgfx.h @@ -2593,7 +2593,10 @@ namespace bgfx /// chains wants. Otherwise the main window takes on this /// description: resize it, change its format, or change its /// per-surface flags. Fields left neutral keep their current - /// value, and `nwh`/`ndt` are ignored -- main's are bgfx's own. + /// value. On Android with a bgfx-owned EGL context, a new `nwh` + /// recreates the EGL window surface while preserving the context and + /// GPU resources. Native window replacement is not guaranteed on other + /// platforms; `ndt` must remain unchanged. /// Must be `NULL` when `bgfx::init` created no main window. /// /// @attention This call doesn’t change the window size, it just resizes diff --git a/src/glcontext_egl.cpp b/src/glcontext_egl.cpp index 857ae4294..a68a8ab8b 100644 --- a/src/glcontext_egl.cpp +++ b/src/glcontext_egl.cpp @@ -992,6 +992,12 @@ WL_EGL_IMPORT && NULL != m_display && NULL != m_nwh) { + // A new Android window can replace the EGLSurface without destroying the EGLContext. + if (m_nwh != _swapChain.nwh) + { + BX_TRACE("Android EGL window changed: %p -> %p", m_nwh, _swapChain.nwh); + m_nwh = _swapChain.nwh; + } EGLNativeWindowType nwh = (EGLNativeWindowType )m_nwh; eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); eglDestroySurface(m_display, m_surface);