2 * Copyright © 2012 Collabora, Ltd.
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.
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.
29 #include <GLES2/gl2.h>
31 #include "compositor.h"
32 #include "android-framebuffer.h"
34 struct android_compositor;
36 struct android_output {
37 struct android_compositor *compositor;
38 struct weston_output base;
40 struct weston_mode mode;
41 struct android_framebuffer *fb;
42 EGLSurface egl_surface;
46 struct weston_seat base;
49 struct android_compositor {
50 struct weston_compositor base;
52 struct android_seat *seat;
55 static inline struct android_output *
56 to_android_output(struct weston_output *base)
58 return container_of(base, struct android_output, base);
61 static inline struct android_compositor *
62 to_android_compositor(struct weston_compositor *base)
64 return container_of(base, struct android_compositor, base);
68 egl_error_string(EGLint code)
70 #define MYERRCODE(x) case x: return #x;
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)
94 print_egl_error_state(void)
99 weston_log("EGL error state: %s (0x%04lx)\n",
100 egl_error_string(code), (long)code);
104 android_output_make_current(struct android_output *output)
106 struct android_compositor *compositor = output->compositor;
110 ret = eglMakeCurrent(compositor->base.display, output->egl_surface,
111 output->egl_surface, compositor->base.context);
112 if (ret == EGL_FALSE) {
116 weston_log("Failed to make EGL context current.\n");
117 print_egl_error_state();
125 android_finish_frame(void *data)
127 struct android_output *output = data;
129 weston_output_finish_frame(&output->base,
130 weston_compositor_get_time());
134 android_output_repaint(struct weston_output *base, pixman_region32_t *damage)
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;
143 if (android_output_make_current(output) < 0)
146 wl_list_for_each_reverse(surface, &compositor->base.surface_list, link)
147 weston_surface_draw(surface, &output->base, damage);
149 weston_output_do_read_pixels(&output->base);
151 ret = eglSwapBuffers(compositor->base.display, output->egl_surface);
152 if (ret == EGL_FALSE && !errored) {
154 weston_log("Failed in eglSwapBuffers.\n");
155 print_egl_error_state();
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);
164 android_output_destroy(struct weston_output *base)
166 struct android_output *output = to_android_output(base);
168 wl_list_remove(&output->base.link);
169 weston_output_destroy(&output->base);
171 android_framebuffer_destroy(output->fb);
176 static struct android_output *
177 android_output_create(struct android_compositor *compositor)
179 struct android_output *output;
181 output = calloc(1, sizeof *output);
185 output->fb = android_framebuffer_create();
191 output->compositor = compositor;
196 android_compositor_add_output(struct android_compositor *compositor,
197 struct android_output *output)
199 float mm_width, mm_height;
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;
208 /* only one static mode in list */
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);
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";
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),
228 wl_list_insert(compositor->base.output_list.prev, &output->base.link);
232 android_seat_destroy(struct android_seat *seat)
234 weston_seat_release(&seat->base);
238 static struct android_seat *
239 android_seat_create(struct android_compositor *compositor)
241 struct android_seat *seat;
243 seat = calloc(1, sizeof *seat);
247 weston_seat_init(&seat->base, &compositor->base);
248 compositor->base.seat = &seat->base;
254 android_egl_choose_config(struct android_compositor *compositor,
255 struct android_framebuffer *fb,
256 const EGLint *attribs)
265 * The logic is copied from Android frameworks/base/services/
266 * surfaceflinger/DisplayHardware/DisplayHardware.cpp
269 compositor->base.config = NULL;
271 ret = eglGetConfigs(compositor->base.display, NULL, 0, &count);
272 if (ret == EGL_FALSE || count < 1)
275 configs = calloc(count, sizeof *configs);
279 ret = eglChooseConfig(compositor->base.display, attribs, configs,
281 if (ret == EGL_FALSE || matched < 1)
284 for (i = 0; i < matched; ++i) {
286 ret = eglGetConfigAttrib(compositor->base.display, configs[i],
287 EGL_NATIVE_VISUAL_ID, &id);
288 if (ret == EGL_FALSE)
290 if (id > 0 && fb->format == id) {
291 compositor->base.config = configs[i];
298 if (!compositor->base.config)
305 android_init_egl(struct android_compositor *compositor,
306 struct android_output *output)
308 EGLint eglmajor, eglminor;
311 static const EGLint context_attrs[] = {
312 EGL_CONTEXT_CLIENT_VERSION, 2,
316 static const EGLint config_attrs[] = {
317 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
322 EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
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();
333 ret = eglInitialize(compositor->base.display, &eglmajor, &eglminor);
335 weston_log("Failed to initialise EGL.\n");
336 print_egl_error_state();
340 if (!eglBindAPI(EGL_OPENGL_ES_API)) {
341 weston_log("Failed to bind EGL_OPENGL_ES_API.\n");
342 print_egl_error_state();
346 ret = android_egl_choose_config(compositor, output->fb, config_attrs);
348 weston_log("Failed to find an EGL config.\n");
349 print_egl_error_state();
353 compositor->base.context = eglCreateContext(compositor->base.display,
354 compositor->base.config,
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();
363 output->egl_surface = eglCreateWindowSurface(compositor->base.display,
364 compositor->base.config,
365 output->fb->native_window,
367 if (output->egl_surface == EGL_NO_SURFACE) {
368 weston_log("Failed to create FB EGLSurface.\n");
369 print_egl_error_state();
373 if (android_output_make_current(output) < 0)
380 android_fini_egl(struct android_compositor *compositor)
382 eglMakeCurrent(compositor->base.display,
383 EGL_NO_SURFACE, EGL_NO_SURFACE,
386 eglTerminate(compositor->base.display);
391 android_compositor_destroy(struct weston_compositor *base)
393 struct android_compositor *compositor = to_android_compositor(base);
395 android_seat_destroy(compositor->seat);
397 /* destroys outputs, too */
398 weston_compositor_shutdown(&compositor->base);
400 android_fini_egl(compositor);
405 static struct weston_compositor *
406 android_compositor_create(struct wl_display *display, int argc, char *argv[],
407 const char *config_file)
409 struct android_compositor *compositor;
410 struct android_output *output;
412 compositor = calloc(1, sizeof *compositor);
413 if (compositor == NULL)
416 compositor->base.destroy = android_compositor_destroy;
418 compositor->base.focus = 1;
420 /* FIXME: all cleanup on failure is missing */
422 output = android_output_create(compositor);
426 if (android_init_egl(compositor, output) < 0)
429 if (weston_compositor_init(&compositor->base, display, argc, argv,
433 android_compositor_add_output(compositor, output);
435 compositor->seat = android_seat_create(compositor);
436 if (!compositor->seat)
439 return &compositor->base;
442 WL_EXPORT struct weston_compositor *
443 backend_init(struct wl_display *display, int argc, char *argv[],
444 const char *config_file)
446 return android_compositor_create(display, argc, argv, config_file);