Need to also set glDisable(GL_CULL_FACE) when drawing wireframe to match what was
[freeglut] / src / android / fg_runtime_android.c
1 /*
2  * freeglut_runtime_android.c
3  *
4  * Android runtime
5  *
6  * Copyright (C) 2012  Sylvain Beucler
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a
9  * copy of this software and associated documentation files (the "Software"),
10  * to deal in the Software without restriction, including without limitation
11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12  * and/or sell copies of the Software, and to permit persons to whom the
13  * Software is furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included
16  * in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * PAWEL W. OLSZTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
22  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  */
25
26 /* Parts taken from Android NDK's 'native-activity' sample : */
27 /*
28  * Copyright (C) 2010 The Android Open Source Project
29  * 
30  * Licensed under the Apache License, Version 2.0 (the "License");
31  * you may not use this file except in compliance with the License.
32  * You may obtain a copy of the License at
33  *
34  *      http://www.apache.org/licenses/LICENSE-2.0
35  *
36  * Unless required by applicable law or agreed to in writing, software
37  * distributed under the License is distributed on an "AS IS" BASIS,
38  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
39  * See the License for the specific language governing permissions and
40  * limitations under the License.
41  *
42  */
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <jni.h>
48 #include <android/log.h>
49 #include <android/asset_manager.h>
50 #include <android/native_window.h>
51 #include "android/native_app_glue/android_native_app_glue.h"
52
53 #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "FreeGLUT", __VA_ARGS__))
54 #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "FreeGLUT", __VA_ARGS__))
55
56 /* Cf. freeglut_main_android.c */
57 extern int32_t handle_input(struct android_app* app, AInputEvent* event);
58 extern void handle_cmd(struct android_app* app, int32_t cmd);
59
60 extern int main(int argc, char* argv[]);
61
62 /** NativeActivity Callbacks **/
63 /* Caution: they are called in the native_activity thread, not the
64    FreeGLUT thread. Use android_app_write_cmd. */
65
66 /* Could be used instead of onNativeWindowRedrawNeeded */
67 /* Deals with status bar presence */
68 static void onContentRectChanged(ANativeActivity* activity, const ARect* rect) {
69   LOGI("onContentRectChanged: l=%d,t=%d,r=%d,b=%d", rect->left, rect->top, rect->right, rect->bottom);
70 }
71
72 /* Bug: not called during a resize in android-9, only once on startup :/ */
73 static void onNativeWindowResized(ANativeActivity* activity, ANativeWindow* window) {
74   LOGI("onNativeWindowResized: %p\n", (void*)activity);
75 }
76
77 /* Called after a resize, compensate broken onNativeWindowResized */
78 static void onNativeWindowRedrawNeeded(ANativeActivity* activity, ANativeWindow* window) {
79   LOGI("onNativeWindowRedrawNeeded: %p\n", (void*)activity);
80   struct android_app* app = (struct android_app*)activity->instance;
81   //if (fgDisplay.pDisplay.single_window->Window.pContext.eglSurface != EGL_NO_SURFACE)
82   android_app_write_cmd(app, APP_CMD_WINDOW_RESIZED);
83 }
84
85 /**
86  * Extract all .apk assets to the application directory so they can be
87  * accessed using accessed.
88  * TODO: parse directories recursively
89  */
90 static void extract_assets(struct android_app* app) {
91   /* Get usable JNI context */
92   JNIEnv* env = app->activity->env;
93   JavaVM* vm = app->activity->vm;
94   (*vm)->AttachCurrentThread(vm, &env, NULL);
95   
96   {
97     /* Get a handle on our calling NativeActivity class */
98     jclass activityClass = (*env)->GetObjectClass(env, app->activity->clazz);
99     
100     /* Get path to cache dir (/data/data/org.myapp/cache) */
101     jmethodID getCacheDir = (*env)->GetMethodID(env, activityClass, "getCacheDir", "()Ljava/io/File;");
102     jobject file = (*env)->CallObjectMethod(env, app->activity->clazz, getCacheDir);
103     jclass fileClass = (*env)->FindClass(env, "java/io/File");
104     jmethodID getAbsolutePath = (*env)->GetMethodID(env, fileClass, "getAbsolutePath", "()Ljava/lang/String;");
105     jstring jpath = (jstring)(*env)->CallObjectMethod(env, file, getAbsolutePath);
106     const char* app_dir = (*env)->GetStringUTFChars(env, jpath, NULL);
107     
108     /* chdir in the application cache directory */
109     LOGI("app_dir: %s", app_dir);
110     chdir(app_dir);
111     (*env)->ReleaseStringUTFChars(env, jpath, app_dir);
112     
113     /* Pre-extract assets, to avoid Android-specific file opening */
114     {
115       AAssetManager* mgr = app->activity->assetManager;
116       AAssetDir* assetDir = AAssetManager_openDir(mgr, "");
117       const char* filename = (const char*)NULL;
118       while ((filename = AAssetDir_getNextFileName(assetDir)) != NULL) {
119         AAsset* asset = AAssetManager_open(mgr, filename, AASSET_MODE_STREAMING);
120         char buf[BUFSIZ];
121         int nb_read = 0;
122         FILE* out = fopen(filename, "w");
123         while ((nb_read = AAsset_read(asset, buf, BUFSIZ)) > 0)
124           fwrite(buf, nb_read, 1, out);
125         fclose(out);
126         AAsset_close(asset);
127       }
128       AAssetDir_close(assetDir);
129     }
130   }
131 }
132
133 /**
134  * This is the main entry point of a native application that is using
135  * android_native_app_glue.  It runs in its own thread, with its own
136  * event loop for receiving input events and doing other things.
137  */
138 void android_main(struct android_app* app) {
139   LOGI("android_main");
140
141   // Register window resize callback
142   app->activity->callbacks->onNativeWindowResized = onNativeWindowResized;
143   app->activity->callbacks->onContentRectChanged = onContentRectChanged;
144   app->activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded;
145   
146   app->onAppCmd = handle_cmd;
147   app->onInputEvent = handle_input;
148
149   extract_assets(app);
150
151   /* Call user's main */
152   {
153     char progname[5] = "self";
154     char* argv[] = {progname, NULL};
155     main(1, argv);
156   }
157
158   LOGI("android_main: end");
159   exit(0);
160 }