1 /*
2 * Copyright 2025 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <android/native_window_jni.h>
18 #include <android_native_app_glue.h>
19
20 #include <chrono>
21 #include <thread>
22
23 #include "vulkan_renderer.h"
24
25 struct AppState {
26 VulkanRenderer renderer;
27 bool canRender = false;
28 };
29
onAppCmd(struct android_app * app,int32_t cmd)30 static void onAppCmd(struct android_app *app, int32_t cmd) {
31 auto *appState = (AppState *)app->userData;
32 switch (cmd) {
33 case APP_CMD_START:
34 if (app->window != nullptr) {
35 appState->renderer.reset(app->window, app->activity->assetManager);
36 appState->renderer.init();
37 appState->canRender = true;
38 }
39 case APP_CMD_INIT_WINDOW:
40 if (app->window != nullptr) {
41 appState->renderer.reset(app->window, app->activity->assetManager);
42 if (!appState->renderer.initialized) {
43 appState->renderer.init();
44 }
45 appState->canRender = true;
46 }
47 break;
48 case APP_CMD_TERM_WINDOW:
49 appState->canRender = false;
50 break;
51 case APP_CMD_DESTROY:
52 appState->renderer.cleanup();
53 default:
54 break;
55 }
56 }
57
android_main(struct android_app * app)58 void android_main(struct android_app *app) {
59 AppState appState{};
60
61 app->userData = &appState;
62 app->onAppCmd = onAppCmd;
63
64 int frame = 0;
65
66 while (true) {
67 int ident;
68 int events;
69 android_poll_source *source;
70 while ((ident = ALooper_pollOnce(appState.canRender ? 0 : -1, nullptr, &events,
71 (void **)&source)) >= 0) {
72 if (source != nullptr) {
73 source->process(app, source);
74 }
75 }
76
77 appState.renderer.render();
78 if (++frame % 10 == 0) {
79 std::this_thread::sleep_for(std::chrono::milliseconds(200));
80 }
81 }
82 }