1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  * Copyright (C) 2011 Intel Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * This file is derived from the "native-activity" sample of the android NDK
21  * r5b. The coding style has been adapted to the code style most commonly found
22  * in glib/gobject based projects.
23  */
24 
25 #include <android_native_app_glue.h>
26 
27 #include <glib.h>
28 #include <glib-android/glib-android.h>
29 #include <cogl/cogl.h>
30 
31 typedef struct
32 {
33   struct android_app* app;
34 
35   CoglContext *context;
36   CoglPrimitive *triangle;
37   CoglFramebuffer *fb;
38 } TestData;
39 
test_init(TestData * data)40 static int test_init (TestData* data)
41 {
42   CoglOnscreen *onscreen;
43   CoglError *error = NULL;
44   CoglVertexP2C4 triangle_vertices[] = {
45         {0, 0.7, 0xff, 0x00, 0x00, 0xff},
46         {-0.7, -0.7, 0x00, 0xff, 0x00, 0xff},
47         {0.7, -0.7, 0x00, 0x00, 0xff, 0xff}
48   };
49 
50   cogl_android_set_native_window (data->app->window);
51 
52   data->context = cogl_context_new (NULL, &error);
53   if (!data->context)
54     {
55       g_critical ("Failed to create context: %s\n", error->message);
56       return 1;
57     }
58 
59   onscreen = cogl_onscreen_new (data->context, 320, 420);
60 
61   /* Eventually there will be an implicit allocate on first use so this
62    * will become optional... */
63   data->fb = COGL_FRAMEBUFFER (onscreen);
64   if (!cogl_framebuffer_allocate (data->fb, &error))
65     {
66       if (error)
67         g_critical ("Failed to allocate framebuffer: %s\n", error->message);
68       else
69         g_critical ("Failed to allocate framebuffer");
70       return 1;
71     }
72 
73   cogl_onscreen_show (onscreen);
74 
75   cogl_push_framebuffer (data->fb);
76 
77   data->triangle = cogl_primitive_new_p2c4 (COGL_VERTICES_MODE_TRIANGLES,
78                                             3, triangle_vertices);
79 
80   return 0;
81 }
82 
test_draw_frame_and_swap(TestData * data)83 static test_draw_frame_and_swap (TestData *data)
84 {
85   if (data->context)
86     {
87       cogl_primitive_draw (data->triangle);
88       cogl_framebuffer_swap_buffers (data->fb);
89     }
90 }
91 
92 static void
test_fini(TestData * data)93 test_fini (TestData *data)
94 {
95   if (data->fb)
96     {
97       cogl_object_unref (data->triangle);
98       cogl_object_unref (data->fb);
99       cogl_object_unref (data->context);
100       data->triangle = NULL;
101       data->fb = NULL;
102       data->context = NULL;
103     }
104 }
105 
106 /**
107  * Process the next main command.
108  */
109 static void
test_handle_cmd(struct android_app * app,int32_t cmd)110 test_handle_cmd (struct android_app* app,
111                  int32_t             cmd)
112 {
113   TestData *data = (TestData *) app->userData;
114 
115   switch (cmd)
116     {
117     case APP_CMD_INIT_WINDOW:
118       /* The window is being shown, get it ready */
119       g_message ("command: INIT_WINDOW");
120       if (data->app->window != NULL)
121         {
122           test_init (data);
123           test_draw_frame_and_swap (data);
124         }
125       break;
126 
127     case APP_CMD_TERM_WINDOW:
128       /* The window is being hidden or closed, clean it up */
129       g_message ("command: TERM_WINDOW");
130       test_fini (data);
131       break;
132 
133     case APP_CMD_GAINED_FOCUS:
134       g_message ("command: GAINED_FOCUS");
135       break;
136 
137     case APP_CMD_LOST_FOCUS:
138       /* When our app loses focus, we stop monitoring the accelerometer.
139        * This is to avoid consuming battery while not being used. */
140       g_message ("command: LOST_FOCUS");
141       test_draw_frame_and_swap (data);
142       break;
143     }
144 }
145 
146 /**
147  * This is the main entry point of a native application that is using
148  * android_native_app_glue.  It runs in its own thread, with its own
149  * event loop for receiving input events and doing other things.
150  */
151 void
android_main(struct android_app * application)152 android_main (struct android_app* application)
153 {
154   TestData data;
155 
156   /* Make sure glue isn't stripped */
157   app_dummy ();
158 
159   g_android_init ();
160 
161   memset (&data, 0, sizeof (TestData));
162   application->userData = &data;
163   application->onAppCmd = test_handle_cmd;
164   data.app = application;
165 
166   while (1)
167     {
168       int events;
169       struct android_poll_source* source;
170 
171       while ((ALooper_pollAll (0, NULL, &events, (void**)&source)) >= 0)
172         {
173 
174           /* Process this event */
175           if (source != NULL)
176             source->process (application, source);
177 
178           /* Check if we are exiting */
179           if  (application->destroyRequested != 0)
180             {
181               test_fini (&data);
182               return;
183             }
184       }
185 
186       test_draw_frame_and_swap (&data);
187     }
188 }
189