blob: e759cda55a6953d0319fa40367f1e9dd03b2dc4d [file] [log] [blame]
Yuly Novikova6426d62016-06-03 00:18:38 -04001//
2// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// AndroidWindow.cpp: Implementation of OSWindow for Android
8
Yuly Novikov9f088622018-12-29 20:46:15 +00009#include "android/AndroidWindow.h"
Yuly Novikova6426d62016-06-03 00:18:38 -040010
11#include <pthread.h>
12
Yuly Novikov9f088622018-12-29 20:46:15 +000013#include "android/third_party/android_native_app_glue.h"
Yuly Novikova6426d62016-06-03 00:18:38 -040014#include "common/debug.h"
15
16namespace
17{
Yuly Novikov9f088622018-12-29 20:46:15 +000018 struct android_app *sApp = nullptr;
19 pthread_mutex_t sInitWindowMutex;
20 pthread_cond_t sInitWindowCond;
21 bool sInitWindowDone = false;
Yuly Novikova6426d62016-06-03 00:18:38 -040022} // namespace
23
Yuly Novikov9f088622018-12-29 20:46:15 +000024AndroidWindow::AndroidWindow()
25{
26}
Yuly Novikova6426d62016-06-03 00:18:38 -040027
Yuly Novikov9f088622018-12-29 20:46:15 +000028AndroidWindow::~AndroidWindow()
29{
30}
Yuly Novikova6426d62016-06-03 00:18:38 -040031
32bool AndroidWindow::initialize(const std::string &name, size_t width, size_t height)
33{
34 return resize(width, height);
35}
Yuly Novikov9f088622018-12-29 20:46:15 +000036void AndroidWindow::destroy()
37{
38}
Yuly Novikova6426d62016-06-03 00:18:38 -040039
40EGLNativeWindowType AndroidWindow::getNativeWindow() const
41{
42 // Return the entire Activity Surface for now
43 // sApp->window is valid only after sInitWindowDone, which is true after initialize()
44 return sApp->window;
45}
46
47EGLNativeDisplayType AndroidWindow::getNativeDisplay() const
48{
49 return EGL_DEFAULT_DISPLAY;
50}
51
52void AndroidWindow::messageLoop()
53{
54 // TODO: accumulate events in the real message loop of android_main,
55 // and process them here
56}
57
58void AndroidWindow::setMousePosition(int x, int y)
59{
60 UNIMPLEMENTED();
61}
62
63bool AndroidWindow::setPosition(int x, int y)
64{
65 UNIMPLEMENTED();
66 return false;
67}
68
69bool AndroidWindow::resize(int width, int height)
70{
Yuly Novikov9f088622018-12-29 20:46:15 +000071 mWidth = width;
Yuly Novikova6426d62016-06-03 00:18:38 -040072 mHeight = height;
73
74 // sApp->window used below is valid only after Activity Surface is created
75 pthread_mutex_lock(&sInitWindowMutex);
76 while (!sInitWindowDone)
77 {
78 pthread_cond_wait(&sInitWindowCond, &sInitWindowMutex);
79 }
80 pthread_mutex_unlock(&sInitWindowMutex);
81
82 // TODO: figure out a way to set the format as well,
83 // which is available only after EGLWindow initialization
84 int32_t err = ANativeWindow_setBuffersGeometry(sApp->window, mWidth, mHeight, 0);
85 return err == 0;
86}
87
Yuly Novikov9f088622018-12-29 20:46:15 +000088void AndroidWindow::setVisible(bool isVisible)
89{
90}
Yuly Novikova6426d62016-06-03 00:18:38 -040091
92void AndroidWindow::signalTestEvent()
93{
94 UNIMPLEMENTED();
95}
96
97OSWindow *CreateOSWindow()
98{
99 // There should be only one live instance of AndroidWindow at a time,
100 // as there is only one Activity Surface behind it.
101 // Creating a new AndroidWindow each time works for ANGLETest,
102 // as it destroys an old window before creating a new one.
103 // TODO: use GLSurfaceView to support multiple windows
104 return new AndroidWindow();
105}
106
107static void onAppCmd(struct android_app *app, int32_t cmd)
108{
109 switch (cmd)
110 {
111 case APP_CMD_INIT_WINDOW:
112 pthread_mutex_lock(&sInitWindowMutex);
113 sInitWindowDone = true;
114 pthread_cond_broadcast(&sInitWindowCond);
115 pthread_mutex_unlock(&sInitWindowMutex);
116 break;
Yuly Novikov9f088622018-12-29 20:46:15 +0000117 // TODO: process other commands and pass them to AndroidWindow for handling
118 // TODO: figure out how to handle APP_CMD_PAUSE,
119 // which should immediately halt all the rendering,
120 // since Activity Surface is no longer available.
121 // Currently tests crash when paused, for example, due to device changing orientation
Yuly Novikova6426d62016-06-03 00:18:38 -0400122 }
123}
124
125static int32_t onInputEvent(struct android_app *app, AInputEvent *event)
126{
127 // TODO: Handle input events
128 return 0; // 0 == not handled
129}
130
131void android_main(struct android_app *app)
132{
133 int events;
134 struct android_poll_source *source;
135
136 sApp = app;
137 pthread_mutex_init(&sInitWindowMutex, nullptr);
138 pthread_cond_init(&sInitWindowCond, nullptr);
139
140 // Event handlers, invoked from source->process()
Yuly Novikov9f088622018-12-29 20:46:15 +0000141 app->onAppCmd = onAppCmd;
Yuly Novikova6426d62016-06-03 00:18:38 -0400142 app->onInputEvent = onInputEvent;
143
144 // Message loop, polling for events indefinitely (due to -1 timeout)
145 // Must be here in order to handle APP_CMD_INIT_WINDOW event,
146 // which occurs after AndroidWindow::initialize(), but before AndroidWindow::messageLoop
147 while (ALooper_pollAll(-1, nullptr, &events, reinterpret_cast<void **>(&source)) >= 0)
148 {
149 if (source != nullptr)
150 {
151 source->process(app, source);
152 }
153 }
154}