screenshooter: Grab pixel data directly before buffer swap
[profile/ivi/weston-ivi-shell.git] / src / compositor-x11.c
index c3eaab7..6d9bb0e 100644 (file)
@@ -48,6 +48,8 @@
 struct x11_compositor {
        struct weston_compositor         base;
 
+       EGLSurface               dummy_pbuffer;
+
        Display                 *dpy;
        xcb_connection_t        *conn;
        xcb_screen_t            *screen;
@@ -117,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
        };
@@ -132,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");
@@ -143,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;
@@ -166,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");
@@ -204,6 +212,8 @@ x11_output_repaint(struct weston_output *output_base,
        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);
@@ -443,11 +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.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);
 
@@ -486,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;
        }
 
@@ -532,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)) {
@@ -576,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;
@@ -627,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);
@@ -638,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;
@@ -665,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:
@@ -718,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++)