blob: 930d9ec233a9903365a67f0f09d47937d4e8a5b4 [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
Jamie Madillba319ba2018-12-29 10:29:33 -05009#include "util/android/AndroidWindow.h"
Yuly Novikova6426d62016-06-03 00:18:38 -040010
11#include <pthread.h>
12
Yuly Novikova6426d62016-06-03 00:18:38 -040013#include "common/debug.h"
Jamie Madillba319ba2018-12-29 10:29:33 -050014#include "util/android/third_party/android_native_app_glue.h"
Yuly Novikova6426d62016-06-03 00:18:38 -040015
16namespace
17{
Jamie Madillba319ba2018-12-29 10:29:33 -050018struct android_app *sApp = nullptr;
19pthread_mutex_t sInitWindowMutex;
20pthread_cond_t sInitWindowCond;
21bool sInitWindowDone = false;
Yuly Novikova6426d62016-06-03 00:18:38 -040022} // namespace
23
Jamie Madillba319ba2018-12-29 10:29:33 -050024AndroidWindow::AndroidWindow() {}
Yuly Novikova6426d62016-06-03 00:18:38 -040025
Jamie Madillba319ba2018-12-29 10:29:33 -050026AndroidWindow::~AndroidWindow() {}
Yuly Novikova6426d62016-06-03 00:18:38 -040027
28bool AndroidWindow::initialize(const std::string &name, size_t width, size_t height)
29{
30 return resize(width, height);
31}
Jamie Madillba319ba2018-12-29 10:29:33 -050032void AndroidWindow::destroy() {}
Yuly Novikova6426d62016-06-03 00:18:38 -040033
34EGLNativeWindowType AndroidWindow::getNativeWindow() const
35{
36 // Return the entire Activity Surface for now
37 // sApp->window is valid only after sInitWindowDone, which is true after initialize()
38 return sApp->window;
39}
40
41EGLNativeDisplayType AndroidWindow::getNativeDisplay() const
42{
43 return EGL_DEFAULT_DISPLAY;
44}
45
46void AndroidWindow::messageLoop()
47{
48 // TODO: accumulate events in the real message loop of android_main,
49 // and process them here
50}
51
52void AndroidWindow::setMousePosition(int x, int y)
53{
54 UNIMPLEMENTED();
55}
56
57bool AndroidWindow::setPosition(int x, int y)
58{
59 UNIMPLEMENTED();
60 return false;
61}
62
63bool AndroidWindow::resize(int width, int height)
64{
Jamie Madillba319ba2018-12-29 10:29:33 -050065 mWidth = width;
Yuly Novikova6426d62016-06-03 00:18:38 -040066 mHeight = height;
67
68 // sApp->window used below is valid only after Activity Surface is created
69 pthread_mutex_lock(&sInitWindowMutex);
70 while (!sInitWindowDone)
71 {
72 pthread_cond_wait(&sInitWindowCond, &sInitWindowMutex);
73 }
74 pthread_mutex_unlock(&sInitWindowMutex);
75
76 // TODO: figure out a way to set the format as well,
77 // which is available only after EGLWindow initialization
78 int32_t err = ANativeWindow_setBuffersGeometry(sApp->window, mWidth, mHeight, 0);
79 return err == 0;
80}
81
Jamie Madillba319ba2018-12-29 10:29:33 -050082void AndroidWindow::setVisible(bool isVisible) {}
Yuly Novikova6426d62016-06-03 00:18:38 -040083
84void AndroidWindow::signalTestEvent()
85{
86 UNIMPLEMENTED();
87}
88
Yuly Novikova6426d62016-06-03 00:18:38 -040089static void onAppCmd(struct android_app *app, int32_t cmd)
90{
91 switch (cmd)
92 {
93 case APP_CMD_INIT_WINDOW:
94 pthread_mutex_lock(&sInitWindowMutex);
95 sInitWindowDone = true;
96 pthread_cond_broadcast(&sInitWindowCond);
97 pthread_mutex_unlock(&sInitWindowMutex);
98 break;
Jamie Madillba319ba2018-12-29 10:29:33 -050099 // TODO: process other commands and pass them to AndroidWindow for handling
100 // TODO: figure out how to handle APP_CMD_PAUSE,
101 // which should immediately halt all the rendering,
102 // since Activity Surface is no longer available.
103 // Currently tests crash when paused, for example, due to device changing orientation
Yuly Novikova6426d62016-06-03 00:18:38 -0400104 }
105}
106
107static int32_t onInputEvent(struct android_app *app, AInputEvent *event)
108{
109 // TODO: Handle input events
110 return 0; // 0 == not handled
111}
112
113void android_main(struct android_app *app)
114{
115 int events;
116 struct android_poll_source *source;
117
118 sApp = app;
119 pthread_mutex_init(&sInitWindowMutex, nullptr);
120 pthread_cond_init(&sInitWindowCond, nullptr);
121
122 // Event handlers, invoked from source->process()
Jamie Madillba319ba2018-12-29 10:29:33 -0500123 app->onAppCmd = onAppCmd;
Yuly Novikova6426d62016-06-03 00:18:38 -0400124 app->onInputEvent = onInputEvent;
125
126 // Message loop, polling for events indefinitely (due to -1 timeout)
127 // Must be here in order to handle APP_CMD_INIT_WINDOW event,
128 // which occurs after AndroidWindow::initialize(), but before AndroidWindow::messageLoop
129 while (ALooper_pollAll(-1, nullptr, &events, reinterpret_cast<void **>(&source)) >= 0)
130 {
131 if (source != nullptr)
132 {
133 source->process(app, source);
134 }
135 }
136}
Jamie Madillad398ee2019-01-03 13:01:08 -0500137
138// static
139OSWindow *OSWindow::New()
140{
141 // There should be only one live instance of AndroidWindow at a time,
142 // as there is only one Activity Surface behind it.
143 // Creating a new AndroidWindow each time works for ANGLETest,
144 // as it destroys an old window before creating a new one.
145 // TODO: use GLSurfaceView to support multiple windows
146 return new AndroidWindow();
147}