Replace fprintf() by weston_log()
[profile/ivi/weston.git] / src / compositor-android.c
1 /*
2  * Copyright © 2012 Collabora, Ltd.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee, provided
6  * that the above copyright notice appear in all copies and that both that
7  * copyright notice and this permission notice appear in supporting
8  * documentation, and that the name of the copyright holders not be used in
9  * advertising or publicity pertaining to distribution of the software
10  * without specific, written prior permission.  The copyright holders make
11  * no representations about the suitability of this software for any
12  * purpose.  It is provided "as is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  */
22
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <math.h>
27
28 #include <EGL/egl.h>
29 #include <GLES2/gl2.h>
30
31 #include "compositor.h"
32 #include "android-framebuffer.h"
33
34 struct android_compositor;
35
36 struct android_output {
37         struct android_compositor *compositor;
38         struct weston_output base;
39
40         struct weston_mode mode;
41         struct android_framebuffer *fb;
42         EGLSurface egl_surface;
43 };
44
45 struct android_seat {
46         struct weston_seat base;
47 };
48
49 struct android_compositor {
50         struct weston_compositor base;
51
52         struct android_seat *seat;
53 };
54
55 static inline struct android_output *
56 to_android_output(struct weston_output *base)
57 {
58         return container_of(base, struct android_output, base);
59 }
60
61 static inline struct android_compositor *
62 to_android_compositor(struct weston_compositor *base)
63 {
64         return container_of(base, struct android_compositor, base);
65 }
66
67 static const char *
68 egl_error_string(EGLint code)
69 {
70 #define MYERRCODE(x) case x: return #x;
71         switch (code) {
72         MYERRCODE(EGL_SUCCESS)
73         MYERRCODE(EGL_NOT_INITIALIZED)
74         MYERRCODE(EGL_BAD_ACCESS)
75         MYERRCODE(EGL_BAD_ALLOC)
76         MYERRCODE(EGL_BAD_ATTRIBUTE)
77         MYERRCODE(EGL_BAD_CONTEXT)
78         MYERRCODE(EGL_BAD_CONFIG)
79         MYERRCODE(EGL_BAD_CURRENT_SURFACE)
80         MYERRCODE(EGL_BAD_DISPLAY)
81         MYERRCODE(EGL_BAD_SURFACE)
82         MYERRCODE(EGL_BAD_MATCH)
83         MYERRCODE(EGL_BAD_PARAMETER)
84         MYERRCODE(EGL_BAD_NATIVE_PIXMAP)
85         MYERRCODE(EGL_BAD_NATIVE_WINDOW)
86         MYERRCODE(EGL_CONTEXT_LOST)
87         default:
88                 return "unknown";
89         }
90 #undef MYERRCODE
91 }
92
93 static void
94 print_egl_error_state(void)
95 {
96         EGLint code;
97
98         code = eglGetError();
99         weston_log("EGL error state: %s (0x%04lx)\n",
100                 egl_error_string(code), (long)code);
101 }
102
103 static int
104 android_output_make_current(struct android_output *output)
105 {
106         struct android_compositor *compositor = output->compositor;
107         EGLBoolean ret;
108         static int errored;
109
110         ret = eglMakeCurrent(compositor->base.display, output->egl_surface,
111                              output->egl_surface, compositor->base.context);
112         if (ret == EGL_FALSE) {
113                 if (errored)
114                         return -1;
115                 errored = 1;
116                 weston_log("Failed to make EGL context current.\n");
117                 print_egl_error_state();
118                 return -1;
119         }
120
121         return 0;
122 }
123
124 static void
125 android_finish_frame(void *data)
126 {
127         struct android_output *output = data;
128
129         weston_output_finish_frame(&output->base,
130                                    weston_compositor_get_time());
131 }
132
133 static void
134 android_output_repaint(struct weston_output *base, pixman_region32_t *damage)
135 {
136         struct android_output *output = to_android_output(base);
137         struct android_compositor *compositor = output->compositor;
138         struct weston_surface *surface;
139         struct wl_event_loop *loop;
140         EGLBoolean ret;
141         static int errored;
142
143         if (android_output_make_current(output) < 0)
144                 return;
145
146         wl_list_for_each_reverse(surface, &compositor->base.surface_list, link)
147                 weston_surface_draw(surface, &output->base, damage);
148
149         weston_output_do_read_pixels(&output->base);
150
151         ret = eglSwapBuffers(compositor->base.display, output->egl_surface);
152         if (ret == EGL_FALSE && !errored) {
153                 errored = 1;
154                 weston_log("Failed in eglSwapBuffers.\n");
155                 print_egl_error_state();
156         }
157
158         /* FIXME: does Android have a way to signal page flip done? */
159         loop = wl_display_get_event_loop(compositor->base.wl_display);
160         wl_event_loop_add_idle(loop, android_finish_frame, output);
161 }
162
163 static void
164 android_output_destroy(struct weston_output *base)
165 {
166         struct android_output *output = to_android_output(base);
167
168         wl_list_remove(&output->base.link);
169         weston_output_destroy(&output->base);
170
171         android_framebuffer_destroy(output->fb);
172
173         free(output);
174 }
175
176 static struct android_output *
177 android_output_create(struct android_compositor *compositor)
178 {
179         struct android_output *output;
180
181         output = calloc(1, sizeof *output);
182         if (!output)
183                 return NULL;
184
185         output->fb = android_framebuffer_create();
186         if (!output->fb) {
187                 free(output);
188                 return NULL;
189         }
190
191         output->compositor = compositor;
192         return output;
193 }
194
195 static void
196 android_compositor_add_output(struct android_compositor *compositor,
197                               struct android_output *output)
198 {
199         float mm_width, mm_height;
200
201         output->base.repaint = android_output_repaint;
202         output->base.destroy = android_output_destroy;
203         output->base.assign_planes = NULL;
204         output->base.set_backlight = NULL;
205         output->base.set_dpms = NULL;
206         output->base.switch_mode = NULL;
207
208         /* only one static mode in list */
209         output->mode.flags =
210                 WL_OUTPUT_MODE_CURRENT | WL_OUTPUT_MODE_PREFERRED;
211         output->mode.width = output->fb->width;
212         output->mode.height = output->fb->height;
213         output->mode.refresh = ceilf(1000.0f * output->fb->refresh_rate);
214         wl_list_init(&output->base.mode_list);
215         wl_list_insert(&output->base.mode_list, &output->mode.link);
216
217         output->base.current = &output->mode;
218         output->base.origin = &output->mode;
219         output->base.subpixel = WL_OUTPUT_SUBPIXEL_UNKNOWN;
220         output->base.make = "unknown";
221         output->base.model = "unknown";
222
223         mm_width  = output->fb->width / output->fb->xdpi * 25.4f;
224         mm_height = output->fb->height / output->fb->ydpi * 25.4f;
225         weston_output_init(&output->base, &compositor->base,
226                            0, 0, round(mm_width), round(mm_height),
227                            WL_OUTPUT_FLIPPED);
228         wl_list_insert(compositor->base.output_list.prev, &output->base.link);
229 }
230
231 static void
232 android_seat_destroy(struct android_seat *seat)
233 {
234         weston_seat_release(&seat->base);
235         free(seat);
236 }
237
238 static struct android_seat *
239 android_seat_create(struct android_compositor *compositor)
240 {
241         struct android_seat *seat;
242
243         seat = calloc(1, sizeof *seat);
244         if (!seat)
245                 return NULL;
246
247         weston_seat_init(&seat->base, &compositor->base);
248         compositor->base.seat = &seat->base;
249
250         return seat;
251 }
252
253 static int
254 android_egl_choose_config(struct android_compositor *compositor,
255                           struct android_framebuffer *fb,
256                           const EGLint *attribs)
257 {
258         EGLBoolean ret;
259         EGLint count = 0;
260         EGLint matched = 0;
261         EGLConfig *configs;
262         int i;
263
264         /*
265          * The logic is copied from Android frameworks/base/services/
266          * surfaceflinger/DisplayHardware/DisplayHardware.cpp
267          */
268
269         compositor->base.config = NULL;
270
271         ret = eglGetConfigs(compositor->base.display, NULL, 0, &count);
272         if (ret == EGL_FALSE || count < 1)
273                 return -1;
274
275         configs = calloc(count, sizeof *configs);
276         if (!configs)
277                 return -1;
278
279         ret = eglChooseConfig(compositor->base.display, attribs, configs,
280                               count, &matched);
281         if (ret == EGL_FALSE || matched < 1)
282                 goto out;
283
284         for (i = 0; i < matched; ++i) {
285                 EGLint id;
286                 ret = eglGetConfigAttrib(compositor->base.display, configs[i],
287                                          EGL_NATIVE_VISUAL_ID, &id);
288                 if (ret == EGL_FALSE)
289                         continue;
290                 if (id > 0 && fb->format == id) {
291                         compositor->base.config = configs[i];
292                         break;
293                 }
294         }
295
296 out:
297         free(configs);
298         if (!compositor->base.config)
299                 return -1;
300
301         return 0;
302 }
303
304 static int
305 android_init_egl(struct android_compositor *compositor,
306                  struct android_output *output)
307 {
308         EGLint eglmajor, eglminor;
309         int ret;
310
311         static const EGLint context_attrs[] = {
312                 EGL_CONTEXT_CLIENT_VERSION, 2,
313                 EGL_NONE
314         };
315
316         static const EGLint config_attrs[] = {
317                 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
318                 EGL_RED_SIZE, 1,
319                 EGL_GREEN_SIZE, 1,
320                 EGL_BLUE_SIZE, 1,
321                 EGL_ALPHA_SIZE, 0,
322                 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
323                 EGL_NONE
324         };
325
326         compositor->base.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
327         if (compositor->base.display == EGL_NO_DISPLAY) {
328                 weston_log("Failed to create EGL display.\n");
329                 print_egl_error_state();
330                 return -1;
331         }
332
333         ret = eglInitialize(compositor->base.display, &eglmajor, &eglminor);
334         if (!ret) {
335                 weston_log("Failed to initialise EGL.\n");
336                 print_egl_error_state();
337                 return -1;
338         }
339
340         if (!eglBindAPI(EGL_OPENGL_ES_API)) {
341                 weston_log("Failed to bind EGL_OPENGL_ES_API.\n");
342                 print_egl_error_state();
343                 return -1;
344         }
345
346         ret = android_egl_choose_config(compositor, output->fb, config_attrs);
347         if (ret < 0) {
348                 weston_log("Failed to find an EGL config.\n");
349                 print_egl_error_state();
350                 return -1;
351         }
352
353         compositor->base.context = eglCreateContext(compositor->base.display,
354                                                     compositor->base.config,
355                                                     EGL_NO_CONTEXT,
356                                                     context_attrs);
357         if (compositor->base.context == EGL_NO_CONTEXT) {
358                 weston_log("Failed to create a GL ES 2 context.\n");
359                 print_egl_error_state();
360                 return -1;
361         }
362
363         output->egl_surface = eglCreateWindowSurface(compositor->base.display,
364                                                      compositor->base.config,
365                                                      output->fb->native_window,
366                                                      NULL);
367         if (output->egl_surface == EGL_NO_SURFACE) {
368                 weston_log("Failed to create FB EGLSurface.\n");
369                 print_egl_error_state();
370                 return -1;
371         }
372
373         if (android_output_make_current(output) < 0)
374                 return -1;
375
376         return 0;
377 }
378
379 static void
380 android_fini_egl(struct android_compositor *compositor)
381 {
382         eglMakeCurrent(compositor->base.display,
383                        EGL_NO_SURFACE, EGL_NO_SURFACE,
384                        EGL_NO_CONTEXT);
385
386         eglTerminate(compositor->base.display);
387         eglReleaseThread();
388 }
389
390 static void
391 android_compositor_destroy(struct weston_compositor *base)
392 {
393         struct android_compositor *compositor = to_android_compositor(base);
394
395         android_seat_destroy(compositor->seat);
396
397         /* destroys outputs, too */
398         weston_compositor_shutdown(&compositor->base);
399
400         android_fini_egl(compositor);
401
402         free(compositor);
403 }
404
405 static struct weston_compositor *
406 android_compositor_create(struct wl_display *display, int argc, char *argv[],
407                           const char *config_file)
408 {
409         struct android_compositor *compositor;
410         struct android_output *output;
411
412         compositor = calloc(1, sizeof *compositor);
413         if (compositor == NULL)
414                 return NULL;
415
416         compositor->base.destroy = android_compositor_destroy;
417
418         compositor->base.focus = 1;
419
420         /* FIXME: all cleanup on failure is missing */
421
422         output = android_output_create(compositor);
423         if (!output)
424                 return NULL;
425
426         if (android_init_egl(compositor, output) < 0)
427                 return NULL;
428
429         if (weston_compositor_init(&compositor->base, display, argc, argv,
430                                    config_file) < 0)
431                 return NULL;
432
433         android_compositor_add_output(compositor, output);
434
435         compositor->seat = android_seat_create(compositor);
436         if (!compositor->seat)
437                 return NULL;
438
439         return &compositor->base;
440 }
441
442 WL_EXPORT struct weston_compositor *
443 backend_init(struct wl_display *display, int argc, char *argv[],
444              const char *config_file)
445 {
446         return android_compositor_create(display, argc, argv, config_file);
447 }