screenshooter: Grab pixel data directly before buffer swap
[profile/ivi/weston-ivi-shell.git] / src / compositor-x11.c
index 11cdb59..6d9bb0e 100644 (file)
 #include <EGL/egl.h>
 
 #include "compositor.h"
+#include "../shared/config-parser.h"
 
 struct x11_compositor {
        struct weston_compositor         base;
 
+       EGLSurface               dummy_pbuffer;
+
        Display                 *dpy;
        xcb_connection_t        *conn;
        xcb_screen_t            *screen;
@@ -116,13 +119,11 @@ x11_compositor_init_egl(struct x11_compositor *c)
 {
        EGLint major, minor;
        EGLint n;
-       const char *extensions;
        EGLint config_attribs[] = {
                EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
                EGL_RED_SIZE, 1,
                EGL_GREEN_SIZE, 1,
                EGL_BLUE_SIZE, 1,
-               EGL_DEPTH_SIZE, 1,
                EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
                EGL_NONE
        };
@@ -131,6 +132,12 @@ x11_compositor_init_egl(struct x11_compositor *c)
                EGL_NONE
        };
 
+       static const EGLint pbuffer_attribs[] = {
+               EGL_WIDTH, 10,
+               EGL_HEIGHT, 10,
+               EGL_NONE
+       };
+
        c->base.display = eglGetDisplay(c->dpy);
        if (c->base.display == NULL) {
                fprintf(stderr, "failed to create display\n");
@@ -142,12 +149,6 @@ x11_compositor_init_egl(struct x11_compositor *c)
                return -1;
        }
 
-       extensions = eglQueryString(c->base.display, EGL_EXTENSIONS);
-       if (!strstr(extensions, "EGL_KHR_surfaceless_gles2")) {
-               fprintf(stderr, "EGL_KHR_surfaceless_gles2 not available\n");
-               return -1;
-       }
-
        if (!eglBindAPI(EGL_OPENGL_ES_API)) {
                fprintf(stderr, "failed to bind EGL_OPENGL_ES_API\n");
                return -1;
@@ -165,6 +166,14 @@ x11_compositor_init_egl(struct x11_compositor *c)
                return -1;
        }
 
+       c->dummy_pbuffer = eglCreatePbufferSurface(c->base.display,
+                                                  c->base.config,
+                                                  pbuffer_attribs);
+       if (c->base.context == NULL) {
+               fprintf(stderr, "failed to create dummy pbuffer\n");
+               return -1;
+       }
+
        if (!eglMakeCurrent(c->base.display, EGL_NO_SURFACE,
                            EGL_NO_SURFACE, c->base.context)) {
                fprintf(stderr, "failed to make context current\n");
@@ -185,19 +194,29 @@ x11_compositor_fini_egl(struct x11_compositor *compositor)
        eglReleaseThread();
 }
 
-static int
-x11_output_prepare_render(struct weston_output *output_base)
+static void
+x11_output_repaint(struct weston_output *output_base,
+                  pixman_region32_t *damage)
 {
-       struct x11_output *output = (struct x11_output *) output_base;
-       struct weston_compositor *ec = output->base.compositor;
+       struct x11_output *output = (struct x11_output *)output_base;
+       struct x11_compositor *compositor =
+               (struct x11_compositor *)output->base.compositor;
+       struct weston_surface *surface;
 
-       if (!eglMakeCurrent(ec->display, output->egl_surface,
-                           output->egl_surface, ec->context)) {
+       if (!eglMakeCurrent(compositor->base.display, output->egl_surface,
+                           output->egl_surface, compositor->base.context)) {
                fprintf(stderr, "failed to make current\n");
-               return -1;
+               return;
        }
 
-       return 0;
+       wl_list_for_each_reverse(surface, &compositor->base.surface_list, link)
+               weston_surface_draw(surface, &output->base, damage);
+
+       weston_output_do_read_pixels(&output->base);
+
+       eglSwapBuffers(compositor->base.display, output->egl_surface);
+
+       wl_event_source_timer_update(output->finish_frame_timer, 10);
 }
 
 static int
@@ -214,36 +233,6 @@ finish_frame_handler(void *data)
        return 1;
 }
 
-static int
-x11_output_present(struct weston_output *output_base)
-{
-       struct x11_output *output = (struct x11_output *) output_base;
-       struct weston_compositor *ec = output->base.compositor;
-
-       if (x11_output_prepare_render(&output->base))
-               return -1;
-
-       eglSwapBuffers(ec->display, output->egl_surface);
-
-       wl_event_source_timer_update(output->finish_frame_timer, 10);
-
-       return 0;
-}
-
-static int
-x11_output_prepare_scanout_surface(struct weston_output *output_base,
-                                  struct weston_surface *es)
-{
-       return -1;
-}
-
-static int
-x11_output_set_cursor(struct weston_output *output_base,
-                     struct weston_input_device *input)
-{
-       return -1;
-}
-
 static void
 x11_output_destroy(struct weston_output *output_base)
 {
@@ -332,34 +321,37 @@ static void
 x11_output_set_icon(struct x11_compositor *c,
                    struct x11_output *output, const char *filename)
 {
-       uint32_t *icon, *pixels, stride;
+       uint32_t *icon;
        int32_t width, height;
+       pixman_image_t *image;
 
-       pixels = weston_load_image(filename, &width, &height, &stride);
-       if (!pixels)
+       image = load_image(filename);
+       if (!image)
                return;
+       width = pixman_image_get_width(image);
+       height = pixman_image_get_height(image);
        icon = malloc(width * height * 4 + 8);
        if (!icon) {
-               free(pixels);
+               pixman_image_unref(image);
                return;
        }
 
        icon[0] = width;
        icon[1] = height;
-       memcpy(icon + 2, pixels, width * height * 4);
+       memcpy(icon + 2, pixman_image_get_data(image), width * height * 4);
        xcb_change_property(c->conn, XCB_PROP_MODE_REPLACE, output->window,
                            c->atom.net_wm_icon, c->atom.cardinal, 32,
                            width * height + 2, icon);
        free(icon);
-       free(pixels);
+       pixman_image_unref(image);
 }
 
 static int
 x11_compositor_create_output(struct x11_compositor *c, int x, int y,
                             int width, int height, int fullscreen)
 {
-       static const char name[] = "Wayland Compositor";
-       static const char class[] = "wayland-1\0Wayland Compositor";
+       static const char name[] = "Weston Compositor";
+       static const char class[] = "weston-1\0Weston Compositor";
        struct x11_output *output;
        xcb_screen_iterator_t iter;
        struct wm_normal_hints normal_hints;
@@ -434,7 +426,7 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
                            c->atom.wm_class, c->atom.string, 8,
                            sizeof class, class);
 
-       x11_output_set_icon(c, output, DATADIR "/wayland/wayland.png");
+       x11_output_set_icon(c, output, DATADIR "/weston/wayland.png");
 
        xcb_map_window(c->conn, output->window);
 
@@ -461,12 +453,13 @@ x11_compositor_create_output(struct x11_compositor *c, int x, int y,
        output->finish_frame_timer =
                wl_event_loop_add_timer(loop, finish_frame_handler, output);
 
-       output->base.prepare_render = x11_output_prepare_render;
-       output->base.present = x11_output_present;
-       output->base.prepare_scanout_surface =
-               x11_output_prepare_scanout_surface;
-       output->base.set_hardware_cursor = x11_output_set_cursor;
+       output->base.origin = output->base.current;
+       output->base.repaint = x11_output_repaint;
        output->base.destroy = x11_output_destroy;
+       output->base.assign_planes = NULL;
+       output->base.set_backlight = NULL;
+       output->base.set_dpms = NULL;
+       output->base.switch_mode = NULL;
 
        wl_list_insert(c->base.output_list.prev, &output->base.link);
 
@@ -505,14 +498,28 @@ x11_compositor_deliver_button_event(struct x11_compositor *c,
                button = BTN_RIGHT;
                break;
        case 4:
+               if (state)
+                       notify_axis(c->base.input_device,
+                                     weston_compositor_get_time(),
+                                     WL_INPUT_DEVICE_AXIS_VERTICAL_SCROLL, 1);
+               return;
        case 5:
+               if (state)
+                       notify_axis(c->base.input_device,
+                                     weston_compositor_get_time(),
+                                     WL_INPUT_DEVICE_AXIS_VERTICAL_SCROLL, -1);
+               return;
        case 6:
+               if (state)
+                       notify_axis(c->base.input_device,
+                                     weston_compositor_get_time(),
+                                     WL_INPUT_DEVICE_AXIS_HORIZONTAL_SCROLL, 1);
+               return;
        case 7:
-               /* X11 sends wheel events as buttons events.  But
-                * linux input treats as REL_WHEEL, therefore not
-                * button type at all. When we update the input
-                * protocol and get the 'axis' event, we'll send
-                * scroll events as axis events. */
+               if (state)
+                       notify_axis(c->base.input_device,
+                                     weston_compositor_get_time(),
+                                     WL_INPUT_DEVICE_AXIS_HORIZONTAL_SCROLL, -1);
                return;
        }
 
@@ -551,7 +558,7 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data)
        xcb_focus_in_event_t *focus_in;
        xcb_atom_t atom;
        uint32_t *k;
-       int i, set;
+       uint32_t i, set;
 
        prev = NULL;
        while (x11_compositor_next_event(c, &event, mask)) {
@@ -595,9 +602,7 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data)
                        }
 
                        output = x11_compositor_find_output(c, focus_in->event);
-                       notify_keyboard_focus(c->base.input_device,
-                                             weston_compositor_get_time(),
-                                             &output->base, &c->keys);
+                       notify_keyboard_focus(c->base.input_device, &c->keys);
 
                        free(prev);
                        prev = NULL;
@@ -646,7 +651,6 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data)
                                break;
                        output = x11_compositor_find_output(c, enter_notify->event);
                        notify_pointer_focus(c->base.input_device,
-                                            weston_compositor_get_time(),
                                             &output->base,
                                             output->base.x + enter_notify->event_x,
                                             output->base.y + enter_notify->event_y);
@@ -657,9 +661,7 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data)
                        if (enter_notify->state >= Button1Mask)
                                break;
                        output = x11_compositor_find_output(c, enter_notify->event);
-                       notify_pointer_focus(c->base.input_device,
-                                            weston_compositor_get_time(),
-                                            NULL,
+                       notify_pointer_focus(c->base.input_device, NULL,
                                             output->base.x + enter_notify->event_x,
                                             output->base.y + enter_notify->event_y);
                        break;
@@ -684,9 +686,7 @@ x11_compositor_handle_event(int fd, uint32_t mask, void *data)
                        if (focus_in->mode == XCB_NOTIFY_MODE_WHILE_GRABBED ||
                            focus_in->mode == XCB_NOTIFY_MODE_UNGRAB)
                                break;
-                       notify_keyboard_focus(c->base.input_device,
-                                             weston_compositor_get_time(),
-                                             NULL, NULL);
+                       notify_keyboard_focus(c->base.input_device, NULL);
                        break;
 
                default:
@@ -737,7 +737,7 @@ x11_compositor_get_resources(struct x11_compositor *c)
        xcb_intern_atom_reply_t *reply;
        xcb_pixmap_t pixmap;
        xcb_gc_t gc;
-       int i;
+       unsigned int i;
        uint8_t data[] = { 0, 0, 0, 0 };
 
        for (i = 0; i < ARRAY_LENGTH(atoms); i++)
@@ -785,7 +785,6 @@ x11_compositor_create(struct wl_display *display,
                      int width, int height, int count, int fullscreen)
 {
        struct x11_compositor *c;
-       struct wl_event_loop *loop;
        xcb_screen_iterator_t s;
        int i, x;
 
@@ -831,10 +830,9 @@ x11_compositor_create(struct wl_display *display,
        if (x11_input_create(c) < 0)
                return NULL;
 
-       loop = wl_display_get_event_loop(c->base.wl_display);
-
        c->xcb_source =
-               wl_event_loop_add_fd(loop, xcb_get_file_descriptor(c->conn),
+               wl_event_loop_add_fd(c->base.input_loop,
+                                    xcb_get_file_descriptor(c->conn),
                                     WL_EVENT_READABLE,
                                     x11_compositor_handle_event, c);
        wl_event_source_check(c->xcb_source);
@@ -842,36 +840,19 @@ x11_compositor_create(struct wl_display *display,
        return &c->base;
 }
 
-struct weston_compositor *
-backend_init(struct wl_display *display, char *options);
-
 WL_EXPORT struct weston_compositor *
-backend_init(struct wl_display *display, char *options)
+backend_init(struct wl_display *display, int argc, char *argv[])
 {
-       int width = 1024, height = 640, fullscreen = 0, count = 1, i;
-       char *p, *value;
+       int width = 1024, height = 640, fullscreen = 0, count = 1;
 
-       static char * const tokens[] = {
-               "width", "height", "fullscreen", "output-count", NULL
+       const struct weston_option x11_options[] = {
+               { WESTON_OPTION_INTEGER, "width", 0, &width },
+               { WESTON_OPTION_INTEGER, "height", 0, &height },
+               { WESTON_OPTION_BOOLEAN, "fullscreen", 0, &fullscreen },
+               { WESTON_OPTION_INTEGER, "output-count", 0, &count },
        };
-       
-       p = options;
-       while (i = getsubopt(&p, tokens, &value), i != -1) {
-               switch (i) {
-               case 0:
-                       width = strtol(value, NULL, 0);
-                       break;
-               case 1:
-                       height = strtol(value, NULL, 0);
-                       break;
-               case 2:
-                       fullscreen = 1;
-                       break;
-               case 3:
-                       count = strtol(value, NULL, 0);
-                       break;
-               }
-       }
+
+       parse_options(x11_options, ARRAY_LENGTH(x11_options), argc, argv);
 
        return x11_compositor_create(display,
                                     width, height, count, fullscreen);