From: <be...@us...> - 2012-05-04 07:37:49
|
Revision: 1293 http://freeglut.svn.sourceforge.net/freeglut/?rev=1293&view=rev Author: beuc Date: 2012-05-04 07:37:39 +0000 (Fri, 04 May 2012) Log Message: ----------- android: handle pause/unpause of application + recreate EGL window and OpenGL context accordingly Modified Paths: -------------- trunk/freeglut/freeglut/progs/test-shapes-gles1/test-shapes-gles1.c trunk/freeglut/freeglut/src/android/fg_internal_android.h trunk/freeglut/freeglut/src/android/fg_main_android.c trunk/freeglut/freeglut/src/android/fg_runtime_android.c trunk/freeglut/freeglut/src/android/fg_window_android.c Modified: trunk/freeglut/freeglut/progs/test-shapes-gles1/test-shapes-gles1.c =================================================================== --- trunk/freeglut/freeglut/progs/test-shapes-gles1/test-shapes-gles1.c 2012-05-03 16:40:20 UTC (rev 1292) +++ trunk/freeglut/freeglut/progs/test-shapes-gles1/test-shapes-gles1.c 2012-05-04 07:37:39 UTC (rev 1293) @@ -281,25 +281,7 @@ /* Program entry point */ -int -main(int argc, char *argv[]) -{ - glutInitWindowSize(640,480); - glutInitWindowPosition(40,40); - glutInit(&argc, argv); - glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE); - - glutCreateWindow("FreeGLUT Shapes"); - - glutReshapeFunc(resize); - glutDisplayFunc(display); - glutKeyboardFunc(key); - glutSpecialFunc(special); - glutIdleFunc(idle); - glutMouseFunc(onMouseClick); - - glutSetOption ( GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION ) ; - +void init_resources() { glClearColor(1,1,1,1); glEnable(GL_CULL_FACE); glCullFace(GL_BACK); @@ -320,7 +302,28 @@ glMaterialfv(GL_FRONT, GL_DIFFUSE, mat_diffuse); glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular); glMaterialfv(GL_FRONT, GL_SHININESS, high_shininess); +} +int +main(int argc, char *argv[]) +{ + glutInitWindowSize(640,480); + glutInitWindowPosition(40,40); + glutInit(&argc, argv); + glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH | GLUT_MULTISAMPLE); + + glutCreateWindow("FreeGLUT Shapes"); + + glutReshapeFunc(resize); + glutDisplayFunc(display); + glutKeyboardFunc(key); + glutSpecialFunc(special); + glutIdleFunc(idle); + glutMouseFunc(onMouseClick); + + glutSetOption ( GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION ) ; + + init_resources(); glutMainLoop(); #ifdef _MSC_VER Modified: trunk/freeglut/freeglut/src/android/fg_internal_android.h =================================================================== --- trunk/freeglut/freeglut/src/android/fg_internal_android.h 2012-05-03 16:40:20 UTC (rev 1292) +++ trunk/freeglut/freeglut/src/android/fg_internal_android.h 2012-05-04 07:37:39 UTC (rev 1293) @@ -34,10 +34,12 @@ /* -- GLOBAL TYPE DEFINITIONS ---------------------------------------------- */ /* The structure used by display initialization in freeglut_init.c */ typedef struct tagSFG_PlatformDisplay SFG_PlatformDisplay; +struct android_app; struct tagSFG_PlatformDisplay { struct tagSFG_PlatformDisplayEGL egl; - struct tagSFG_Window* single_window; + EGLNativeWindowType single_native_window; + struct android_app* app; }; typedef struct tagSFG_PlatformContext SFG_PlatformContext; Modified: trunk/freeglut/freeglut/src/android/fg_main_android.c =================================================================== --- trunk/freeglut/freeglut/src/android/fg_main_android.c 2012-05-03 16:40:20 UTC (rev 1292) +++ trunk/freeglut/freeglut/src/android/fg_main_android.c 2012-05-04 07:37:39 UTC (rev 1293) @@ -29,6 +29,7 @@ #include <GL/freeglut.h> #include "fg_internal.h" #include "fg_main.h" +#include "egl/fg_window_egl.h" #include <android/log.h> #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "FreeGLUT", __VA_ARGS__)) @@ -180,7 +181,9 @@ * Process the next input event. */ int32_t handle_input(struct android_app* app, AInputEvent* event) { - SFG_Window* window = fgStructure.CurrentWindow; + SFG_Window* window = fgWindowByHandle(app->window); + if (window == NULL) + return EVENT_NOT_HANDLED; /* FIXME: in Android, when key is repeated, down and up events happen most often at the exact same time. This makes it @@ -302,6 +305,7 @@ * Process the next main command. */ void handle_cmd(struct android_app* app, int32_t cmd) { + SFG_Window* window = fgWindowByHandle(app->window); /* may be NULL */ switch (cmd) { /* App life cycle, in that order: */ case APP_CMD_START: @@ -309,15 +313,12 @@ break; case APP_CMD_RESUME: LOGI("handle_cmd: APP_CMD_RESUME"); - /* If coming back from a pause: */ - /* - Recreate window context and surface */ - /* - Call user-defined hook to restore resources (textures...) */ - /* - Unpause GLUT callbacks */ + /* Cf. fgPlatformProcessSingleEvent */ break; case APP_CMD_INIT_WINDOW: /* surfaceCreated */ /* The window is being shown, get it ready. */ LOGI("handle_cmd: APP_CMD_INIT_WINDOW"); - fgDisplay.pDisplay.single_window->Window.Handle = app->window; + fgDisplay.pDisplay.single_native_window = app->window; /* glPlatformOpenWindow was waiting for Handle to be defined and will now return from fgPlatformProcessSingleEvent() */ break; @@ -326,7 +327,7 @@ break; case APP_CMD_WINDOW_RESIZED: LOGI("handle_cmd: APP_CMD_WINDOW_RESIZED"); - if (fgDisplay.pDisplay.single_window->Window.pContext.egl.Surface != EGL_NO_SURFACE) + if (window->Window.pContext.egl.Surface != EGL_NO_SURFACE) /* Make ProcessSingleEvent detect the new size, only available after the next SwapBuffer */ glutPostRedisplay(); @@ -335,23 +336,22 @@ case APP_CMD_SAVE_STATE: /* onSaveInstanceState */ /* The system has asked us to save our current state, when it pauses the application without destroying it right after. */ - /* app->savedState = ... */ - /* app->savedStateSize = ... */ + app->savedState = strdup("Detect me as non-NULL on next android_main"); + app->savedStateSize = strlen(app->savedState) + 1; LOGI("handle_cmd: APP_CMD_SAVE_STATE"); break; case APP_CMD_PAUSE: LOGI("handle_cmd: APP_CMD_PAUSE"); - /* - Pause GLUT callbacks */ + /* Cf. fgPlatformProcessSingleEvent */ break; case APP_CMD_LOST_FOCUS: LOGI("handle_cmd: APP_CMD_LOST_FOCUS"); break; case APP_CMD_TERM_WINDOW: /* surfaceDestroyed */ /* The application is being hidden, but may be restored */ - /* TODO: Pausing/resuming windows not ready yet, so killing it now */ - fgDestroyWindow(fgDisplay.pDisplay.single_window); - fgDisplay.pDisplay.single_window = NULL; LOGI("handle_cmd: APP_CMD_TERM_WINDOW"); + fghPlatformCloseWindowEGL(window); + fgDisplay.pDisplay.single_native_window = NULL; break; case APP_CMD_STOP: LOGI("handle_cmd: APP_CMD_STOP"); @@ -359,9 +359,14 @@ case APP_CMD_DESTROY: /* Activity.onDestroy */ LOGI("handle_cmd: APP_CMD_DESTROY"); /* User closed the application for good, let's kill the window */ - if (fgDisplay.pDisplay.single_window != NULL) { - fgDestroyWindow(fgDisplay.pDisplay.single_window); - fgDisplay.pDisplay.single_window = NULL; + { + /* Can't use fgWindowByHandle as app->window is NULL */ + SFG_Window* window = fgStructure.CurrentWindow; + if (window != NULL) { + fgDestroyWindow(window); + } else { + LOGI("APP_CMD_DESTROY: No current window"); + } } /* glue has already set android_app->destroyRequested=1 */ break; @@ -378,6 +383,11 @@ } } +void fgPlatformOpenWindow( SFG_Window* window, const char* title, + GLboolean positionUse, int x, int y, + GLboolean sizeUse, int w, int h, + GLboolean gameMode, GLboolean isSubWindow ); + void fgPlatformProcessSingleEvent ( void ) { /* When the screen is resized, the window handle still points to the @@ -389,7 +399,7 @@ /* Interestingly, on a Samsung Galaxy S/PowerVR SGX540 GPU/Android 2.3, that next SwapBuffer is fake (but still necessary to get the new size). */ - SFG_Window* window = fgDisplay.pDisplay.single_window; + SFG_Window* window = fgStructure.CurrentWindow; if (window != NULL && window->Window.Handle != NULL) { int32_t width = ANativeWindow_getWidth(window->Window.Handle); int32_t height = ANativeWindow_getHeight(window->Window.Handle); @@ -420,6 +430,32 @@ source->process(source->app, source); } } + + /* If we're not in RESUME state, Android paused us, so wait */ + struct android_app* app = fgDisplay.pDisplay.app; + if (app->destroyRequested != 1 && app->activityState != APP_CMD_RESUME) { + int FOREVER = -1; + while (app->destroyRequested != 1 && (app->activityState != APP_CMD_RESUME)) { + if ((ident=ALooper_pollOnce(FOREVER, NULL, &events, (void**)&source)) >= 0) { + /* Process this event. */ + if (source != NULL) { + source->process(source->app, source); + } + } + } + /* If coming back from a pause: */ + /* - Recreate window context and surface */ + /* - Call user-defined hook to restore resources (textures...) */ + /* - Exit pause looop */ + if (app->destroyRequested != 1) { + /* Android is full-screen only, simplified call.. */ + /* Ideally we'd have a fgPlatformReopenWindow() */ + fgPlatformOpenWindow(window, "", GL_FALSE, 0, 0, GL_FALSE, 0, 0, GL_FALSE, GL_FALSE); + /* TODO: INVOKE_WCB(*window, Pause?); */ + /* TODO: INVOKE_WCB(*window, LoadResources/ContextLost/...?); */ + /* TODO: INVOKE_WCB(*window, Resume?); */ + } + } } void fgPlatformMainLoopPreliminaryWork ( void ) Modified: trunk/freeglut/freeglut/src/android/fg_runtime_android.c =================================================================== --- trunk/freeglut/freeglut/src/android/fg_runtime_android.c 2012-05-03 16:40:20 UTC (rev 1292) +++ trunk/freeglut/freeglut/src/android/fg_runtime_android.c 2012-05-04 07:37:39 UTC (rev 1293) @@ -138,7 +138,7 @@ * event loop for receiving input events and doing other things. */ void android_main(struct android_app* app) { - LOGI("android_main"); + LOGI("android_main savedState=%p", app->savedState); /* Register window resize callback */ app->activity->callbacks->onNativeWindowResized = onNativeWindowResized; @@ -154,6 +154,7 @@ { char progname[5] = "self"; char* argv[] = {progname, NULL}; + fgDisplay.pDisplay.app = app; main(1, argv); /* FreeGLUT will exit() by itself if GLUT_ACTION_ON_WINDOW_CLOSE == GLUT_ACTION_EXIT */ @@ -161,14 +162,6 @@ LOGI("android_main: end"); - /* TODO: Pausing/resuming windows not ready yet, so exiting now */ - exit(0); - - /* Finish processing all events (namely APP_CMD_DESTROY) before - exiting thread */ - while (!app->destroyRequested) - fgPlatformProcessSingleEvent(); - /* Let NativeActivity restart us */ /* Users may want to forcibly exit() in their main() anyway because NativeActivity doesn't dlclose() us, so all statically-assigned Modified: trunk/freeglut/freeglut/src/android/fg_window_android.c =================================================================== --- trunk/freeglut/freeglut/src/android/fg_window_android.c 2012-05-03 16:40:20 UTC (rev 1292) +++ trunk/freeglut/freeglut/src/android/fg_window_android.c 2012-05-04 07:37:39 UTC (rev 1293) @@ -30,7 +30,7 @@ #include <GL/freeglut.h> #include "fg_internal.h" #include "egl/fg_window_egl.h" -#include "android/fg_main_android.h" +#include <android/native_app_glue/android_native_app_glue.h> /* * Opens a window. Requires a SFG_Window object created and attached @@ -42,28 +42,33 @@ GLboolean gameMode, GLboolean isSubWindow ) { /* TODO: only one full-screen window possible? */ - if (fgDisplay.pDisplay.single_window == NULL) { - fgDisplay.pDisplay.single_window = window; - } else { + if (fgDisplay.pDisplay.single_native_window != NULL) { fgWarning("You can't have more than one window on Android"); return; } - fghChooseConfig(&window->Window.pContext.egl.Config); - window->Window.Context = fghCreateNewContextEGL(window); - - /* Wait until window is available and OpenGL context is created */ + /* First, wait until Activity surface is available */ /* Normally events are processed through glutMainLoop(), but the user didn't call it yet, and the Android may not have initialized the View yet. So we need to wait for that to happen. */ /* We can't return from this function before the OpenGL context is properly made current with a valid surface. So we wait for the surface. */ - while (fgDisplay.pDisplay.single_window->Window.Handle == NULL) { + while (fgDisplay.pDisplay.single_native_window == NULL) { /* APP_CMD_INIT_WINDOW will do the job */ - fgPlatformProcessSingleEvent(); + int ident; + int events; + struct android_poll_source* source; + if ((ident=ALooper_pollOnce(0, NULL, &events, (void**)&source)) >= 0) + if (source != NULL) source->process(source->app, source); + /* fgPlatformProcessSingleEvent(); */ } + window->Window.Handle = fgDisplay.pDisplay.single_native_window; + /* Create context */ + fghChooseConfig(&window->Window.pContext.egl.Config); + window->Window.Context = fghCreateNewContextEGL(window); + EGLDisplay display = fgDisplay.pDisplay.egl.Display; /* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |