Skip to content

Commit 3d76fb8

Browse files
committed
fix possible rendering edge cases
1 parent 7ecb18d commit 3d76fb8

File tree

3 files changed

+151
-50
lines changed

3 files changed

+151
-50
lines changed

NativeApp/include/Android/AndroidAppBase.hpp

+37-8
Original file line numberDiff line numberDiff line change
@@ -12,22 +12,24 @@
1212
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1313
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
1414
*
15-
* In no event and under no legal theory, whether in tort (including negligence),
16-
* contract, or otherwise, unless required by applicable law (such as deliberate
15+
* In no event and under no legal theory, whether in tort (including negligence),
16+
* contract, or otherwise, unless required by applicable law (such as deliberate
1717
* and grossly negligent acts) or agreed to in writing, shall any Contributor be
18-
* liable for any damages, including any direct, indirect, special, incidental,
19-
* or consequential damages of any character arising as a result of this License or
20-
* out of the use or inability to use the software (including but not limited to damages
21-
* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
22-
* all other commercial damages or losses), even if such Contributor has been advised
18+
* liable for any damages, including any direct, indirect, special, incidental,
19+
* or consequential damages of any character arising as a result of this License or
20+
* out of the use or inability to use the software (including but not limited to damages
21+
* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
22+
* all other commercial damages or losses), even if such Contributor has been advised
2323
* of the possibility of such damages.
2424
*/
2525

2626
#pragma once
2727

2828
#include <memory>
29+
#include <mutex>
2930

3031
#include <android_native_app_glue.h>
32+
#include "FlagEnum.h"
3133
#include "AppBase.hpp"
3234

3335
#include "NDKHelper.h"
@@ -52,6 +54,27 @@ class AndroidAppBase : public AppBase
5254
static int32_t HandleInput(android_app* app, AInputEvent* event);
5355
static void HandleCmd(android_app* app, int32_t cmd);
5456

57+
// Android lifecycle status flags. Not app-specific
58+
enum APP_STATUS_FLAGS
59+
{
60+
APP_STATUS_FLAG_NONE = 0x00000000,
61+
62+
// Set between onCreate and onDestroy
63+
APP_STATUS_FLAG_RUNNING = 0x00000001,
64+
65+
// Set between onResume and onPause
66+
APP_STATUS_FLAG_ACTIVE = 0x00000002,
67+
68+
// Set between onWindowFocusChanged(true) and (false)
69+
APP_STATUS_FLAG_FOCUSED = 0x00000004,
70+
71+
// Set when the app's SurfaceHolder points to a
72+
// valid, nonzero-sized surface
73+
APP_STATUS_FLAG_HAS_REAL_SURFACE = 0x00000008
74+
};
75+
76+
APP_STATUS_FLAGS app_status_ = APP_STATUS_FLAG_NONE;
77+
5578
protected:
5679
virtual void Initialize()
5780
{
@@ -81,6 +104,8 @@ class AndroidAppBase : public AppBase
81104
android_app* app_ = nullptr;
82105
std::string native_activity_class_name_;
83106

107+
std::mutex mutex;
108+
84109
private:
85110
void UpdatePosition(AInputEvent* event, int32_t iIndex, float& fX, float& fY);
86111
void SuspendSensors();
@@ -89,11 +114,15 @@ class AndroidAppBase : public AppBase
89114
void UpdateFPS(float fFPS);
90115

91116
bool initialized_resources_ = false;
92-
bool has_focus_ = false;
117+
118+
int32_t window_width_ = 0;
119+
int32_t window_height_ = 0;
93120

94121
ASensorManager* sensor_manager_ = nullptr;
95122
const ASensor* accelerometer_sensor_ = nullptr;
96123
ASensorEventQueue* sensor_event_queue_ = nullptr;
97124
};
98125

126+
DEFINE_FLAG_ENUM_OPERATORS(AndroidAppBase::APP_STATUS_FLAGS)
127+
99128
} // namespace Diligent

NativeApp/src/Android/AndroidAppBase.cpp

+111-42
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,19 @@
1212
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1313
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
1414
*
15-
* In no event and under no legal theory, whether in tort (including negligence),
16-
* contract, or otherwise, unless required by applicable law (such as deliberate
15+
* In no event and under no legal theory, whether in tort (including negligence),
16+
* contract, or otherwise, unless required by applicable law (such as deliberate
1717
* and grossly negligent acts) or agreed to in writing, shall any Contributor be
18-
* liable for any damages, including any direct, indirect, special, incidental,
19-
* or consequential damages of any character arising as a result of this License or
20-
* out of the use or inability to use the software (including but not limited to damages
21-
* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
22-
* all other commercial damages or losses), even if such Contributor has been advised
18+
* liable for any damages, including any direct, indirect, special, incidental,
19+
* or consequential damages of any character arising as a result of this License or
20+
* out of the use or inability to use the software (including but not limited to damages
21+
* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
22+
* all other commercial damages or losses), even if such Contributor has been advised
2323
* of the possibility of such damages.
2424
*/
2525

2626
#include "AndroidAppBase.hpp"
27+
#include "Errors.hpp"
2728
#include "Timer.hpp"
2829

2930
#include <android/sensor.h>
@@ -118,22 +119,47 @@ void AndroidAppBase::HandleCmd(struct android_app* app, int32_t cmd)
118119
AndroidAppBase* eng = (AndroidAppBase*)app->userData;
119120
switch (cmd)
120121
{
121-
case APP_CMD_SAVE_STATE:
122-
break;
123-
124122
case APP_CMD_INIT_WINDOW:
125-
// The window is being shown, get it ready.
126-
if (app->window != NULL)
123+
LOG_INFO_MESSAGE("APP_CMD_INIT_WINDOW");
124+
app->window = app->pendingWindow;
125+
if (app->window &&
126+
ANativeWindow_getWidth(app->window) &&
127+
ANativeWindow_getHeight(app->window))
127128
{
129+
LOG_INFO_MESSAGE("INIT DISPLAY - HAS SURFACE");
128130
eng->InitDisplay();
129131
eng->DrawFrame();
132+
std::lock_guard<std::mutex> lock(eng->mutex);
133+
eng->app_status_ |= APP_STATUS_FLAG_HAS_REAL_SURFACE;
134+
}
135+
else
136+
{
137+
LOG_INFO_MESSAGE("NO SURFACE");
138+
std::lock_guard<std::mutex> lock(eng->mutex);
139+
eng->app_status_ &= ~APP_STATUS_FLAG_HAS_REAL_SURFACE;
130140
}
131141
break;
132142

133-
case APP_CMD_CONFIG_CHANGED:
143+
case APP_CMD_TERM_WINDOW:
144+
LOG_INFO_MESSAGE("APP_CMD_TERM_WINDOW - LOST SURFACE - TERM DISPLAY");
145+
{
146+
std::lock_guard<std::mutex> lock(eng->mutex);
147+
eng->app_status_ &= ~APP_STATUS_FLAG_HAS_REAL_SURFACE;
148+
}
149+
eng->TermDisplay();
150+
break;
151+
152+
// Note that as of NDK r21b (21.1.6352462), APP_CMD_CONTENT_RECT_CHANGED event is never
153+
// generated by android_native_app_glue
154+
case APP_CMD_CONTENT_RECT_CHANGED:
134155
{
135-
// This callback is not reliable for handling orientation changes. Depending on the
136-
// device, it may be called before or after the surface has been actually resized.
156+
LOG_INFO_MESSAGE("APP_CMD_CONTENT_RECT_CHANGED");
157+
158+
int32_t new_window_width =
159+
app->contentRect.right - app->contentRect.left;
160+
int32_t new_window_height =
161+
app->contentRect.bottom - app->contentRect.top;
162+
eng->WindowResize(new_window_width, new_window_height);
137163
break;
138164
}
139165

@@ -144,45 +170,87 @@ void AndroidAppBase::HandleCmd(struct android_app* app, int32_t cmd)
144170
// does not work either - the callback is only called once after the window has been created.
145171
case APP_CMD_WINDOW_RESIZED:
146172
{
147-
auto new_window_width = ANativeWindow_getWidth(app->window);
148-
auto new_window_height = ANativeWindow_getHeight(app->window);
149-
eng->WindowResize(new_window_width, new_window_height);
173+
LOG_INFO_MESSAGE("APP_CMD_WINDOW_RESIZED");
174+
if (app->window)
175+
{
176+
int32_t new_window_width = ANativeWindow_getWidth(app->window);
177+
int32_t new_window_height = ANativeWindow_getHeight(app->window);
178+
if (new_window_width && new_window_height)
179+
{
180+
eng->WindowResize(new_window_width, new_window_height);
181+
}
182+
}
150183
break;
151184
}
152185

153-
// Note that as of NDK r21b (21.1.6352462), APP_CMD_CONTENT_RECT_CHANGED event is never
154-
// generated by android_native_app_glue
155-
case APP_CMD_CONTENT_RECT_CHANGED:
156-
{
157-
auto new_window_width = app->contentRect.right - app->contentRect.left;
158-
auto new_window_height = app->contentRect.bottom - app->contentRect.top;
159-
eng->WindowResize(new_window_width, new_window_height);
186+
case APP_CMD_GAINED_FOCUS:
187+
LOG_INFO_MESSAGE("APP_CMD_GAINED_FOCUS - HAS FOCUS");
188+
{
189+
std::lock_guard<std::mutex> lock(eng->mutex);
190+
eng->app_status_ |= APP_STATUS_FLAG_FOCUSED;
191+
}
192+
eng->ResumeSensors();
193+
break;
194+
195+
case APP_CMD_LOST_FOCUS:
196+
LOG_INFO_MESSAGE("APP_CMD_LOST_FOCUS - LOST FOCUS");
197+
{
198+
std::lock_guard<std::mutex> lock(eng->mutex);
199+
eng->app_status_ &= ~APP_STATUS_FLAG_FOCUSED;
200+
}
201+
eng->SuspendSensors();
202+
break;
203+
204+
case APP_CMD_RESUME:
205+
LOG_INFO_MESSAGE("APP_CMD_RESUME - IS ACTIVE");
206+
{
207+
std::lock_guard<std::mutex> lock(eng->mutex);
208+
eng->app_status_ |= APP_STATUS_FLAG_ACTIVE;
209+
}
210+
break;
211+
212+
case APP_CMD_START:
213+
LOG_INFO_MESSAGE("APP_CMD_START");
160214
break;
161-
}
162215

163-
case APP_CMD_TERM_WINDOW:
164216
case APP_CMD_PAUSE:
165-
// The window is being hidden or closed, clean it up.
166-
eng->TermDisplay();
167-
eng->has_focus_ = false;
217+
LOG_INFO_MESSAGE("APP_CMD_PAUSE - IS NOT ACTIVE");
218+
{
219+
std::lock_guard<std::mutex> lock(eng->mutex);
220+
eng->app_status_ &= ~APP_STATUS_FLAG_ACTIVE;
221+
}
168222
break;
169223

170224
case APP_CMD_STOP:
225+
LOG_INFO_MESSAGE("APP_CMD_STOP");
171226
break;
172227

173-
case APP_CMD_GAINED_FOCUS:
174-
eng->ResumeSensors();
175-
//Start animation
176-
eng->has_focus_ = true;
228+
case APP_CMD_CONFIG_CHANGED:
229+
LOG_INFO_MESSAGE("APP_CMD_CONFIG_CHANGED");
230+
// AConfiguration_fromAssetManager(app->config, app->activity->assetManager);
231+
// This callback is not reliable for handling orientation changes. Depending on the
232+
// device, it may be called before or after the surface has been actually resized.
177233
break;
178234

179-
case APP_CMD_LOST_FOCUS:
180-
eng->SuspendSensors();
181-
// Also stop animating.
182-
eng->has_focus_ = false;
235+
case APP_CMD_DESTROY:
236+
LOG_INFO_MESSAGE("APP_CMD_DESTROY - IS NOT RUNNING");
237+
{
238+
std::lock_guard<std::mutex> lock(eng->mutex);
239+
eng->app_status_ &= ~APP_STATUS_FLAG_RUNNING;
240+
}
241+
break;
242+
243+
case APP_CMD_WINDOW_REDRAW_NEEDED:
244+
LOG_INFO_MESSAGE("APP_CMD_WINDOW_REDRAW_NEEDED");
245+
if (eng->IsReady()) eng->DrawFrame();
246+
break;
247+
248+
case APP_CMD_SAVE_STATE:
249+
LOG_INFO_MESSAGE("APP_CMD_SAVE_STATE");
183250
break;
184251

185252
case APP_CMD_LOW_MEMORY:
253+
LOG_INFO_MESSAGE("APP_CMD_LOW_MEMORY");
186254
//Free up GL resources
187255
eng->TrimMemory();
188256
break;
@@ -244,10 +312,11 @@ void AndroidAppBase::SetState(android_app* state, const char* native_activity_cl
244312

245313
bool AndroidAppBase::IsReady()
246314
{
247-
if (has_focus_)
248-
return true;
249-
250-
return false;
315+
std::lock_guard<std::mutex> lock(mutex);
316+
return (app_status_ & APP_STATUS_FLAG_RUNNING) != APP_STATUS_FLAG_NONE &&
317+
(app_status_ & APP_STATUS_FLAG_ACTIVE) != APP_STATUS_FLAG_NONE &&
318+
(app_status_ & APP_STATUS_FLAG_FOCUSED) != APP_STATUS_FLAG_NONE &&
319+
(app_status_ & APP_STATUS_FLAG_HAS_REAL_SURFACE) != APP_STATUS_FLAG_NONE;
251320
}
252321

253322
//void Engine::TransformPosition( ndk_helper::Vec2& vec )

NativeApp/src/Android/AndroidMain.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ using namespace Diligent;
4242
void android_main(android_app* state)
4343
{
4444
std::unique_ptr<AndroidAppBase> theApp(CreateApplication());
45+
46+
theApp->app_status_ |= AndroidAppBase::APP_STATUS_FLAG_RUNNING;
47+
4548
theApp->SetState(state, NATIVEACTIVITY_CLASS_NAME);
4649

4750
//Init helper functions

0 commit comments

Comments
 (0)