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