diff --git a/examples/common/entry_android.cpp b/examples/common/entry_android.cpp index c8e7ce17..54dd41f3 100644 --- a/examples/common/entry_android.cpp +++ b/examples/common/entry_android.cpp @@ -7,18 +7,193 @@ #if BX_PLATFORM_ANDROID +#include "entry_p.h" + #include -#include "entry.h" +#include + +#include +#include +#include +#include +#include +extern "C" +{ +#include +} // extern "C" + +extern int _main_(int _argc, char** _argv); namespace entry { + struct MainThreadEntry + { + int m_argc; + char** m_argv; + + static int32_t threadFunc(void* _userData); + }; + + struct Context + { + Context() + { + } + + void run(android_app* _app) + { + m_app = _app; + m_app->userData = (void*)this; + m_app->onAppCmd = onAppCmdCB; + m_app->onInputEvent = onInputEventCB; + + bgfx::androidSetWindow(m_app->window); + + const char* argv[1] = { "android.so" }; + MainThreadEntry mte; + mte.m_argc = 1; + mte.m_argv = const_cast(argv); + + bx::Thread thread; + thread.init(mte.threadFunc, &mte); + + while (0 == m_app->destroyRequested) + { + int32_t num; + android_poll_source* source; + /*int32_t id =*/ ALooper_pollAll(-1, NULL, &num, (void**)&source); + + if (NULL != source) + { + source->process(m_app, source); + } + } + + thread.shutdown(); + } + + void onAppCmd(int32_t _cmd) + { + switch (_cmd) + { + case APP_CMD_INPUT_CHANGED: + // Command from main thread: the AInputQueue has changed. Upon processing + // this command, android_app->inputQueue will be updated to the new queue + // (or NULL). + break; + + case APP_CMD_INIT_WINDOW: + // Command from main thread: a new ANativeWindow is ready for use. Upon + // receiving this command, android_app->window will contain the new window + // surface. + break; + + case APP_CMD_TERM_WINDOW: + // Command from main thread: the existing ANativeWindow needs to be + // 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. + break; + + case APP_CMD_WINDOW_RESIZED: + // Command from main thread: the current ANativeWindow has been resized. + // Please redraw with its new size. + break; + + case APP_CMD_WINDOW_REDRAW_NEEDED: + // Command from main thread: the system needs that the current ANativeWindow + // be redrawn. You should redraw the window before handing this to + // android_app_exec_cmd() in order to avoid transient drawing glitches. + break; + + case APP_CMD_CONTENT_RECT_CHANGED: + // Command from main thread: the content area of the window has changed, + // such as from the soft input window being shown or hidden. You can + // find the new content rect in android_app::contentRect. + break; + + case APP_CMD_GAINED_FOCUS: + // Command from main thread: the app's activity window has gained + // input focus. + break; + + case APP_CMD_LOST_FOCUS: + // Command from main thread: the app's activity window has lost + // input focus. + break; + + case APP_CMD_CONFIG_CHANGED: + // Command from main thread: the current device configuration has changed. + break; + + case APP_CMD_LOW_MEMORY: + // Command from main thread: the system is running low on memory. + // Try to reduce your memory use. + break; + + case APP_CMD_START: + // Command from main thread: the app's activity has been started. + break; + + case APP_CMD_RESUME: + // Command from main thread: the app's activity has been resumed. + break; + + case APP_CMD_SAVE_STATE: + // Command from main thread: the app should generate a new saved state + // for itself, to restore from later if needed. If you have saved state, + // allocate it with malloc and place it in android_app.savedState with + // the size in android_app.savedStateSize. The will be freed for you + // later. + break; + + case APP_CMD_PAUSE: + // Command from main thread: the app's activity has been paused. + break; + + case APP_CMD_STOP: + // Command from main thread: the app's activity has been stopped. + break; + + case APP_CMD_DESTROY: + // Command from main thread: the app's activity is being destroyed, + // and waiting for the app thread to clean up and exit before proceeding. + m_eventQueue.postExitEvent(); + break; + } + } + + int32_t onInputEvent(AInputEvent* _event) + { + return 0; + } + + static void onAppCmdCB(struct android_app* _app, int32_t _cmd) + { + Context* self = (Context*)_app->userData; + self->onAppCmd(_cmd); + } + + static int32_t onInputEventCB(struct android_app* _app, AInputEvent* _event) + { + Context* self = (Context*)_app->userData; + return self->onInputEvent(_event); + } + + EventQueue m_eventQueue; + android_app* m_app; + }; + + static Context s_ctx; + const Event* poll() { - return NULL; + return s_ctx.m_eventQueue.poll(); } void release(const Event* _event) { + s_ctx.m_eventQueue.release(_event); } void setWindowSize(uint32_t _width, uint32_t _height) @@ -33,13 +208,23 @@ namespace entry { } + int32_t MainThreadEntry::threadFunc(void* _userData) + { + MainThreadEntry* self = (MainThreadEntry*)_userData; + int32_t result = _main_(self->m_argc, self->m_argv); +// PostMessage(s_ctx.m_hwnd, WM_QUIT, 0, 0); + return result; + } + } // namespace entry extern int _main_(int _argc, char** _argv); -int main(int _argc, char** _argv) +extern "C" void android_main(android_app* _app) { - _main_(_argc, _argv); + using namespace entry; + app_dummy(); + s_ctx.run(_app); } #endif // BX_PLATFORM_ANDROID diff --git a/examples/common/entry_windows.cpp b/examples/common/entry_windows.cpp index 8f5a9ec2..ce9583b7 100644 --- a/examples/common/entry_windows.cpp +++ b/examples/common/entry_windows.cpp @@ -154,7 +154,7 @@ namespace entry s_translateKey['Z'] = Key::KeyZ; } - int32_t main(int _argc, char** _argv) + int32_t run(int _argc, char** _argv) { HINSTANCE instance = (HINSTANCE)GetModuleHandle(NULL); @@ -636,7 +636,7 @@ namespace entry int main(int _argc, char** _argv) { using namespace entry; - return s_ctx.main(_argc, _argv); + return s_ctx.run(_argc, _argv); } #endif // BX_PLATFORM_WINDOWS diff --git a/include/bgfxplatform.h b/include/bgfxplatform.h index f90aacb7..1df77171 100755 --- a/include/bgfxplatform.h +++ b/include/bgfxplatform.h @@ -13,11 +13,11 @@ #include #if BX_PLATFORM_ANDROID -struct android_app; +# include namespace bgfx { - androidSetAndroidApp(struct android_app* _app); + void androidSetWindow(::ANativeWindow* _window); } // namespace bgfx #elif BX_PLATFORM_LINUX @@ -38,14 +38,6 @@ namespace bgfx void naclSetIntefraces(::PP_Instance, const ::PPB_Instance*, const ::PPB_Graphics3D*, PostSwapBuffersFn); } // namespace bgfx -#elif BX_PLATFORM_WINDOWS -# include - -namespace bgfx -{ - void winSetHwnd(::HWND _hwnd); -} // namespace bgfx - #elif BX_PLATFORM_OSX # include # include @@ -55,6 +47,14 @@ namespace bgfx void osxSetNSWindow(void* _nsWindow); } // namespace bgfx +#elif BX_PLATFORM_WINDOWS +# include + +namespace bgfx +{ + void winSetHwnd(::HWND _hwnd); +} // namespace bgfx + #endif // BX_PLATFORM_ #endif // __BGFXPLATFORM_H__ diff --git a/src/bgfx.cpp b/src/bgfx.cpp index 2293c55c..f5ba8e44 100755 --- a/src/bgfx.cpp +++ b/src/bgfx.cpp @@ -33,12 +33,11 @@ namespace bgfx # define BGFX_CHECK_RENDER_THREAD() #endif // BGFX_CONFIG_MULTITHREADED -#if BX_PLATFORM_WINDOWS - HWND g_bgfxHwnd = NULL; - - void winSetHwnd(::HWND _hwnd) +#if BX_PLATFORM_ANDROID + ::ANativeWindow* g_bgfxAndroidWindow = NULL; + void androidSetWindow(ANativeWindow* _window) { - g_bgfxHwnd = _hwnd; + g_bgfxAndroidWindow = _window; } #elif BX_PLATFORM_OSX void* g_bgfxNSWindow = NULL; @@ -47,6 +46,13 @@ namespace bgfx { g_bgfxNSWindow = _nsWindow; } +#elif BX_PLATFORM_WINDOWS + ::HWND g_bgfxHwnd = NULL; + + void winSetHwnd(::HWND _hwnd) + { + g_bgfxHwnd = _hwnd; + } #endif // BX_PLATFORM_* struct CallbackStub : public CallbackI diff --git a/src/bgfx_p.h b/src/bgfx_p.h index 2460f5f4..3196c9c5 100755 --- a/src/bgfx_p.h +++ b/src/bgfx_p.h @@ -100,7 +100,9 @@ namespace stl { #endif // BGFX_CONFIG_USE_TINYSTL #include -#if BX_PLATFORM_WINDOWS +#if BX_PLATFORM_ANDROID +# include +#elif BX_PLATFORM_WINDOWS # include #elif BX_PLATFORM_XBOX360 # include @@ -152,10 +154,12 @@ namespace stl { namespace bgfx { -#if BX_PLATFORM_WINDOWS - extern HWND g_bgfxHwnd; +#if BX_PLATFORM_ANDROID + extern ::ANativeWindow* g_bgfxAndroidWindow; #elif BX_PLATFORM_OSX extern void* g_bgfxNSWindow; +#elif BX_PLATFORM_WINDOWS + extern ::HWND g_bgfxHwnd; #endif // BX_PLATFORM_* struct Clear diff --git a/src/glcontext_egl.cpp b/src/glcontext_egl.cpp index f72f4708..92c93d55 100644 --- a/src/glcontext_egl.cpp +++ b/src/glcontext_egl.cpp @@ -50,6 +50,13 @@ namespace bgfx success = eglChooseConfig(m_display, attrs, &config, 1, &numConfig); BGFX_FATAL(success, Fatal::UnableToInitialize, "eglChooseConfig"); +# if BX_PLATFORM_ANDROID + EGLint format; + eglGetConfigAttrib(m_display, config, EGL_NATIVE_VISUAL_ID, &format); + ANativeWindow_setBuffersGeometry(g_bgfxAndroidWindow, 0, 0, format); + nwt = g_bgfxAndroidWindow; +# endif // BX_PLATFORM_ANDROID + m_surface = eglCreateWindowSurface(m_display, config, nwt, NULL); BGFX_FATAL(m_surface != EGL_NO_SURFACE, Fatal::UnableToInitialize, "Failed to create surface.");