blob: 0767e82b7014746cb296bc424d3488e119b9e1d8 [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
89OSWindow *CreateOSWindow()
90{
91 // There should be only one live instance of AndroidWindow at a time,
92 // as there is only one Activity Surface behind it.
93 // Creating a new AndroidWindow each time works for ANGLETest,
94 // as it destroys an old window before creating a new one.
95 // TODO: use GLSurfaceView to support multiple windows
96 return new AndroidWindow();
97}
98
99static void onAppCmd(struct android_app *app, int32_t cmd)
100{
101 switch (cmd)
102 {
103 case APP_CMD_INIT_WINDOW:
104 pthread_mutex_lock(&sInitWindowMutex);
105 sInitWindowDone = true;
106 pthread_cond_broadcast(&sInitWindowCond);
107 pthread_mutex_unlock(&sInitWindowMutex);
108 break;
Jamie Madillba319ba2018-12-29 10:29:33 -0500109 // TODO: process other commands and pass them to AndroidWindow for handling
110 // TODO: figure out how to handle APP_CMD_PAUSE,
111 // which should immediately halt all the rendering,
112 // since Activity Surface is no longer available.
113 // Currently tests crash when paused, for example, due to device changing orientation
Yuly Novikova6426d62016-06-03 00:18:38 -0400114 }
115}
116
117static int32_t onInputEvent(struct android_app *app, AInputEvent *event)
118{
119 // TODO: Handle input events
120 return 0; // 0 == not handled
121}
122
123void android_main(struct android_app *app)
124{
125 int events;
126 struct android_poll_source *source;
127
128 sApp = app;
129 pthread_mutex_init(&sInitWindowMutex, nullptr);
130 pthread_cond_init(&sInitWindowCond, nullptr);
131
132 // Event handlers, invoked from source->process()
Jamie Madillba319ba2018-12-29 10:29:33 -0500133 app->onAppCmd = onAppCmd;
Yuly Novikova6426d62016-06-03 00:18:38 -0400134 app->onInputEvent = onInputEvent;
135
136 // Message loop, polling for events indefinitely (due to -1 timeout)
137 // Must be here in order to handle APP_CMD_INIT_WINDOW event,
138 // which occurs after AndroidWindow::initialize(), but before AndroidWindow::messageLoop
139 while (ALooper_pollAll(-1, nullptr, &events, reinterpret_cast<void **>(&source)) >= 0)
140 {
141 if (source != nullptr)
142 {
143 source->process(app, source);
144 }
145 }
146}