From 2d43095a2e73fdb792e95e9a724163658242023a Mon Sep 17 00:00:00 2001 From: mgood7123 Date: Mon, 28 Jun 2021 13:45:23 +1000 Subject: [PATCH] fix possible rendering edge cases --- NativeApp/include/Android/AndroidAppBase.hpp | 45 ++++- NativeApp/src/Android/AndroidAppBase.cpp | 190 +++++++++++++++---- NativeApp/src/Android/AndroidMain.cpp | 3 + 3 files changed, 188 insertions(+), 50 deletions(-) diff --git a/NativeApp/include/Android/AndroidAppBase.hpp b/NativeApp/include/Android/AndroidAppBase.hpp index 79c5c3e5a..e9bb4cb60 100644 --- a/NativeApp/include/Android/AndroidAppBase.hpp +++ b/NativeApp/include/Android/AndroidAppBase.hpp @@ -12,22 +12,24 @@ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. * - * In no event and under no legal theory, whether in tort (including negligence), - * contract, or otherwise, unless required by applicable law (such as deliberate + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate * and grossly negligent acts) or agreed to in writing, shall any Contributor be - * liable for any damages, including any direct, indirect, special, incidental, - * or consequential damages of any character arising as a result of this License or - * out of the use or inability to use the software (including but not limited to damages - * for loss of goodwill, work stoppage, computer failure or malfunction, or any and - * all other commercial damages or losses), even if such Contributor has been advised + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised * of the possibility of such damages. */ #pragma once #include +#include #include +#include #include "AppBase.hpp" #include "NDKHelper.h" @@ -52,6 +54,27 @@ class AndroidAppBase : public AppBase static int32_t HandleInput(android_app* app, AInputEvent* event); static void HandleCmd(android_app* app, int32_t cmd); + enum APP_STATUS_FLAGS + { + APP_STATUS_FLAG_NONE = 0x00000000, + + // Android lifecycle status flags. Not app-specific + // Set between onCreate and onDestroy + APP_STATUS_FLAG_RUNNING = 0x00000001, + + // Set between onResume and onPause + APP_STATUS_FLAG_ACTIVE = 0x00000002, + + // Set between onWindowFocusChanged(true) and (false) + APP_STATUS_FLAG_FOCUSED = 0x00000004, + + // Set when the app's SurfaceHolder points to a + // valid, nonzero-sized surface + APP_STATUS_FLAG_HAS_REAL_SURFACE = 0x00000008 + }; + + APP_STATUS_FLAGS app_status_ = APP_STATUS_FLAG_NONE; + protected: virtual void Initialize() { @@ -81,6 +104,8 @@ class AndroidAppBase : public AppBase android_app* app_ = nullptr; std::string native_activity_class_name_; + std::mutex mutex; + private: void UpdatePosition(AInputEvent* event, int32_t iIndex, float& fX, float& fY); void SuspendSensors(); @@ -89,11 +114,15 @@ class AndroidAppBase : public AppBase void UpdateFPS(float fFPS); bool initialized_resources_ = false; - bool has_focus_ = false; + + int32_t window_width_ = 0; + int32_t window_height_ = 0; ASensorManager* sensor_manager_ = nullptr; const ASensor* accelerometer_sensor_ = nullptr; ASensorEventQueue* sensor_event_queue_ = nullptr; }; +DEFINE_FLAG_ENUM_OPERATORS(AndroidAppBase::APP_STATUS_FLAGS) + } // namespace Diligent diff --git a/NativeApp/src/Android/AndroidAppBase.cpp b/NativeApp/src/Android/AndroidAppBase.cpp index 5091b8321..4897c84e0 100644 --- a/NativeApp/src/Android/AndroidAppBase.cpp +++ b/NativeApp/src/Android/AndroidAppBase.cpp @@ -12,18 +12,19 @@ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. * - * In no event and under no legal theory, whether in tort (including negligence), - * contract, or otherwise, unless required by applicable law (such as deliberate + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate * and grossly negligent acts) or agreed to in writing, shall any Contributor be - * liable for any damages, including any direct, indirect, special, incidental, - * or consequential damages of any character arising as a result of this License or - * out of the use or inability to use the software (including but not limited to damages - * for loss of goodwill, work stoppage, computer failure or malfunction, or any and - * all other commercial damages or losses), even if such Contributor has been advised + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised * of the possibility of such damages. */ #include "AndroidAppBase.hpp" +#include "Errors.hpp" #include "Timer.hpp" #include @@ -118,22 +119,60 @@ void AndroidAppBase::HandleCmd(struct android_app* app, int32_t cmd) AndroidAppBase* eng = (AndroidAppBase*)app->userData; switch (cmd) { - case APP_CMD_SAVE_STATE: - break; - case APP_CMD_INIT_WINDOW: - // The window is being shown, get it ready. - if (app->window != NULL) +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("APP_CMD_INIT_WINDOW"); +#endif + app->window = app->pendingWindow; + if (app->window && + ANativeWindow_getWidth(app->window) && + ANativeWindow_getHeight(app->window)) { +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("INIT DISPLAY - HAS SURFACE"); +#endif eng->InitDisplay(); eng->DrawFrame(); + std::lock_guard lock(eng->mutex); + eng->app_status_ |= APP_STATUS_FLAG_HAS_REAL_SURFACE; + } + else + { +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("LOST SURFACE"); +#endif + std::lock_guard lock(eng->mutex); + eng->app_status_ &= ~APP_STATUS_FLAG_HAS_REAL_SURFACE; } break; - case APP_CMD_CONFIG_CHANGED: + case APP_CMD_TERM_WINDOW: +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("APP_CMD_TERM_WINDOW - LOST SURFACE"); +#endif + { + std::lock_guard lock(eng->mutex); + eng->app_status_ &= ~APP_STATUS_FLAG_HAS_REAL_SURFACE; + } +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("TERM DISPLAY"); +#endif + eng->TermDisplay(); + break; + + // Note that as of NDK r21b (21.1.6352462), APP_CMD_CONTENT_RECT_CHANGED event is never + // generated by android_native_app_glue + case APP_CMD_CONTENT_RECT_CHANGED: { - // This callback is not reliable for handling orientation changes. Depending on the - // device, it may be called before or after the surface has been actually resized. +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("APP_CMD_CONTENT_RECT_CHANGED"); +#endif + + int32_t new_window_width = + app->contentRect.right - app->contentRect.left; + int32_t new_window_height = + app->contentRect.bottom - app->contentRect.top; + eng->WindowResize(new_window_width, new_window_height); break; } @@ -144,45 +183,111 @@ void AndroidAppBase::HandleCmd(struct android_app* app, int32_t cmd) // does not work either - the callback is only called once after the window has been created. case APP_CMD_WINDOW_RESIZED: { - auto new_window_width = ANativeWindow_getWidth(app->window); - auto new_window_height = ANativeWindow_getHeight(app->window); - eng->WindowResize(new_window_width, new_window_height); +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("APP_CMD_WINDOW_RESIZED"); +#endif + if (app->window) + { + int32_t new_window_width = ANativeWindow_getWidth(app->window); + int32_t new_window_height = ANativeWindow_getHeight(app->window); + if (new_window_width && new_window_height) + { + eng->WindowResize(new_window_width, new_window_height); + } + } break; } - // Note that as of NDK r21b (21.1.6352462), APP_CMD_CONTENT_RECT_CHANGED event is never - // generated by android_native_app_glue - case APP_CMD_CONTENT_RECT_CHANGED: - { - auto new_window_width = app->contentRect.right - app->contentRect.left; - auto new_window_height = app->contentRect.bottom - app->contentRect.top; - eng->WindowResize(new_window_width, new_window_height); + case APP_CMD_GAINED_FOCUS: +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("APP_CMD_GAINED_FOCUS - HAS FOCUS"); +#endif + { + std::lock_guard lock(eng->mutex); + eng->app_status_ |= APP_STATUS_FLAG_FOCUSED; + } + eng->ResumeSensors(); + break; + + case APP_CMD_LOST_FOCUS: +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("APP_CMD_LOST_FOCUS - LOST FOCUS"); +#endif + { + std::lock_guard lock(eng->mutex); + eng->app_status_ &= ~APP_STATUS_FLAG_FOCUSED; + } + eng->SuspendSensors(); + break; + + case APP_CMD_RESUME: +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("APP_CMD_RESUME - IS ACTIVE"); +#endif + { + std::lock_guard lock(eng->mutex); + eng->app_status_ |= APP_STATUS_FLAG_ACTIVE; + } + break; + + case APP_CMD_START: +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("APP_CMD_START"); +#endif break; - } - case APP_CMD_TERM_WINDOW: case APP_CMD_PAUSE: - // The window is being hidden or closed, clean it up. - eng->TermDisplay(); - eng->has_focus_ = false; +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("APP_CMD_PAUSE - IS NOT ACTIVE"); +#endif + { + std::lock_guard lock(eng->mutex); + eng->app_status_ &= ~APP_STATUS_FLAG_ACTIVE; + } break; case APP_CMD_STOP: +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("APP_CMD_STOP"); +#endif break; - case APP_CMD_GAINED_FOCUS: - eng->ResumeSensors(); - //Start animation - eng->has_focus_ = true; + case APP_CMD_CONFIG_CHANGED: +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("APP_CMD_CONFIG_CHANGED"); +#endif + // AConfiguration_fromAssetManager(app->config, app->activity->assetManager); + // This callback is not reliable for handling orientation changes. Depending on the + // device, it may be called before or after the surface has been actually resized. break; - case APP_CMD_LOST_FOCUS: - eng->SuspendSensors(); - // Also stop animating. - eng->has_focus_ = false; + case APP_CMD_DESTROY: +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("APP_CMD_DESTROY - IS NOT RUNNING"); +#endif + { + std::lock_guard lock(eng->mutex); + eng->app_status_ &= ~APP_STATUS_FLAG_RUNNING; + } + break; + + case APP_CMD_WINDOW_REDRAW_NEEDED: +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("APP_CMD_WINDOW_REDRAW_NEEDED"); +#endif + if (eng->IsReady()) eng->DrawFrame(); + break; + + case APP_CMD_SAVE_STATE: +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("APP_CMD_SAVE_STATE"); +#endif break; case APP_CMD_LOW_MEMORY: +#if (DILIGENT_DEVLOPMENT) + LOG_INFO_MESSAGE("APP_CMD_LOW_MEMORY"); +#endif //Free up GL resources eng->TrimMemory(); break; @@ -244,10 +349,11 @@ void AndroidAppBase::SetState(android_app* state, const char* native_activity_cl bool AndroidAppBase::IsReady() { - if (has_focus_) - return true; - - return false; + std::lock_guard lock(mutex); + return (app_status_ & APP_STATUS_FLAG_RUNNING) != APP_STATUS_FLAG_NONE && + (app_status_ & APP_STATUS_FLAG_ACTIVE) != APP_STATUS_FLAG_NONE && + (app_status_ & APP_STATUS_FLAG_FOCUSED) != APP_STATUS_FLAG_NONE && + (app_status_ & APP_STATUS_FLAG_HAS_REAL_SURFACE) != APP_STATUS_FLAG_NONE; } //void Engine::TransformPosition( ndk_helper::Vec2& vec ) diff --git a/NativeApp/src/Android/AndroidMain.cpp b/NativeApp/src/Android/AndroidMain.cpp index 5186c8d2a..9bc1b6872 100644 --- a/NativeApp/src/Android/AndroidMain.cpp +++ b/NativeApp/src/Android/AndroidMain.cpp @@ -42,6 +42,9 @@ using namespace Diligent; void android_main(android_app* state) { std::unique_ptr theApp(CreateApplication()); + + theApp->app_status_ |= AndroidAppBase::APP_STATUS_FLAG_RUNNING; + theApp->SetState(state, NATIVEACTIVITY_CLASS_NAME); //Init helper functions