fix screenshots 50/78650/1 accepted/tizen/common/20160706.142818 accepted/tizen/ivi/20160706.132927 accepted/tizen/mobile/20160706.132526 accepted/tizen/tv/20160706.132513 accepted/tizen/wearable/20160706.132551 submit/tizen/20160706.112247
authorAnatolii Nikulin <nikulin.a@samsung.com>
Wed, 6 Jul 2016 09:42:44 +0000 (12:42 +0300)
committerAnatolii Nikulin <nikulin.a@samsung.com>
Wed, 6 Jul 2016 09:44:57 +0000 (12:44 +0300)
use tbm buffer for image instead shared memory

Change-Id: I60afc17c92adf39a8e6ef933d43e0b99a425ae93
Signed-off-by: Anatolii Nikulin <nikulin.a@samsung.com>
Makefile
helper/dacapture.c
helper/wayland-api.c [deleted file]
helper/wayland-api.h [deleted file]
packaging/swap-probe.spec

index cfed6fe..ae6410e 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -109,10 +109,20 @@ PROBE_SRCS =                                      \
        ./probe_file/da_io_stdc.c               \
 
 ifeq ($(WAYLAND_SUPPORT),y)
-UTILITY_SRCS += ./helper/wayland-api.c
 UTILITY_SRCS += ./helper/dacapture.c
 PROBE_SRCS += ./probe_event/orientation.c
 CFLAGS += -DWAYLAND_SUPPORT
+CFLAGS += -I/usr/include/wayland-extension/
+LDFLAGS+=-lecore                       \
+        -levas                         \
+        -ltizen-extension-client       \
+        -ltbm                          \
+        -leina                         \
+        -lecore_wayland                \
+        -lwayland-client               \
+        -lwayland-tbm-client           \
+        -lcapi-base-common             \
+        -lscreenshooter-client
 endif # WAYLAND_SUPPORT
 
 DUMMY_SRCS = ./custom_chart/da_chart_dummy.c
index d61bf26..4211071 100755 (executable)
 #include <Evas_Engine_Buffer.h>
 
 #include <wayland-client.h>
-#include "wayland-api.h"
+#include <wayland-tbm-client.h>
+#include <tbm_bufmgr.h>
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+#include <tizen-extension-client-protocol.h>
+#include <screenshooter-client-protocol.h>
+
 #include "real_functions.h"
 #include "daprobe.h"
 #include "dahelper.h"
 #define CAPTURE_TIMEOUT                2.0
 #define MAX_PATH_LENGTH 256
 
-struct screenshot_data {
-       struct wl_shm *shm;
+struct efl_data {
+       struct wl_display *wl_display;
+       struct wl_registry *wl_registry;
        struct screenshooter *screenshooter;
        struct wl_list output_list;
        int min_x, min_y, max_x, max_y;
        int buffer_copy_done;
+       int width, height;
 };
 
 struct screenshooter_output {
@@ -128,7 +136,7 @@ static void
 screenshot_done(void *data,
                struct screenshooter __attribute__((unused)) *screenshooter)
 {
-       struct screenshot_data *sdata = data;
+       struct efl_data *sdata = data;
        sdata->buffer_copy_done = 1;
 }
 
@@ -141,13 +149,12 @@ handle_global(void *data, struct wl_registry *registry,
              uint32_t name, const char *interface,
              uint32_t __attribute__((unused)) version)
 {
-       struct screenshot_data *sdata = data;
+       struct efl_data *sdata = data;
 
        if (strcmp(interface, "wl_output") == 0) {
                struct screenshooter_output *output = malloc(sizeof(*output));
 
                if (output) {
-                       PRINTMSG("allocate %p", output);
                        output->output = wl_registry_bind(registry, name,
                                                          &wl_output_interface,
                                                          1);
@@ -156,13 +163,13 @@ handle_global(void *data, struct wl_registry *registry,
                                               &output_listener,
                                               output);
                }
-       } else if (strcmp(interface, "wl_shm") == 0) {
-               sdata->shm = wl_registry_bind(registry, name, 
-                                             &wl_shm_interface, 1);
        } else if (strcmp(interface, "screenshooter") == 0) {
                sdata->screenshooter = wl_registry_bind(registry, name,
                                                 &screenshooter_interface,
                                                 1);
+               screenshooter_add_listener(sdata->screenshooter,
+                                          &screenshooter_listener,
+                                          sdata);
        }
 }
 
@@ -171,180 +178,33 @@ static const struct wl_registry_listener registry_listener = {
        NULL
 };
 
-static struct wl_buffer *
-create_shm_buffer(struct wl_shm *shm, int width, int height, void **data_out)
-{
-       char filename[] = "/tmp/wayland-shm-XXXXXX";
-       struct wl_shm_pool *pool;
-       struct wl_buffer *buffer;
-       int fd, size, stride;
-       void *data;
-
-       stride = width * 4;
-       size = stride * height;
-
-       fd = mkstemp(filename);
-       if (fd < 0)
-               return NULL;
-
-       if (ftruncate(fd, size) < 0) {
-               close(fd);
-               return NULL;
-       }
-
-       data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-       unlink(filename);
-
-       if (data == MAP_FAILED) {
-               close(fd);
-               return NULL;
-       }
-
-       pool = wl_shm_create_pool(shm, fd, size);
-       close(fd);
-       buffer = wl_shm_pool_create_buffer(pool, 0, width, height, stride,
-                                          WL_SHM_FORMAT_XRGB8888);
-       wl_shm_pool_destroy(pool);
-       *data_out = data;
-
-       return buffer;
-}
-
-static void *__screenshot_to_buf(struct screenshot_data *sdata, int width,
-                                int height)
-{
-       int output_stride, buffer_stride, i;
-       void *data, *d, *s;
-       struct screenshooter_output *output, *next;
-
-       buffer_stride = width * 4;
-       data = malloc(buffer_stride * height);
-       if (!data)
-               return NULL;
-
-       wl_list_for_each_safe(output, next, &sdata->output_list, link) {
-               output_stride = output->width * 4;
-               s = output->data;
-               d = data + (output->offset_y - sdata->min_y) * buffer_stride +
-                          (output->offset_x - sdata->min_x) * 4;
-
-               for (i = 0; i < output->height; i++) {
-                       memcpy(d, s, output_stride);
-                       d += buffer_stride;
-                       s += output_stride;
-               }
-
-               wl_list_remove(&output->link);
-               free(output);
-       }
-
-       return data;
-}
-
-static int
-set_buffer_size(struct screenshot_data *sdata, int *width, int *height)
+static void  __set_buffer_size(struct efl_data *data)
 {
        struct screenshooter_output *output;
 
-       sdata->min_x = sdata->min_y = INT_MAX;
-       sdata->max_x = sdata->max_y = INT_MIN;
+       data->min_x = data->min_y = INT_MAX;
+       data->max_x = data->max_y = INT_MIN;
        int position = 0;
 
-       wl_list_for_each_reverse(output, &sdata->output_list, link) {
+       wl_list_for_each_reverse(output, &data->output_list, link) {
                output->offset_x = position;
                position += output->width;
        }
 
-       wl_list_for_each(output, &sdata->output_list, link) {
-               sdata->min_x = MIN(sdata->min_x, output->offset_x);
-               sdata->min_y = MIN(sdata->min_y, output->offset_y);
-               sdata->max_x = MAX(sdata->max_x,
-                                  output->offset_x + output->width);
-               sdata->max_y = MAX(sdata->max_y,
-                                  output->offset_y + output->height);
+       wl_list_for_each(output, &data->output_list, link) {
+               data->min_x = MIN(data->min_x, output->offset_x);
+               data->min_y = MIN(data->min_y, output->offset_y);
+               data->max_x = MAX(data->max_x, output->offset_x + output->width);
+               data->max_y = MAX(data->max_y, output->offset_y + output->height);
        }
 
-       if (sdata->max_x <= sdata->min_x || sdata->max_y <= sdata->min_y)
-               return -1;
-
-       *width = sdata->max_x - sdata->min_x;
-       *height = sdata->max_y - sdata->min_y;
-
-       return 0;
-}
-
-static void *__capture_screnshot_wayland(int *width, int *height)
-{
-       struct wl_display *display = NULL;
-       struct wl_registry *registry;
-       struct screenshooter_output *output;
-       void *buf = NULL;
-       struct screenshot_data *sdata;
-       const char *wayland_socket = NULL;
-
-       wayland_socket = getenv("WAYLAND_SOCKET");
-       if (!wayland_socket)
-               wayland_socket = getenv("WAYLAND_DISPLAY");
-
-       if (!wayland_socket) {
-               PRINTERR("must be launched by wayland");
-               return NULL;
-       }
-
-       sdata = malloc(sizeof(*sdata));
-       if (!sdata)
-               return NULL;
-
-       sdata->shm = NULL;
-       sdata->screenshooter = NULL;
-       wl_list_init(&sdata->output_list);
-       sdata->min_x = 0;
-       sdata->min_y = 0;
-       sdata->max_x = 0;
-       sdata->max_y = 0;
-       sdata->buffer_copy_done = 0;
-
-       display = wl_display_connect(wayland_socket);
-       if (display == NULL)
-               goto out;
-
-       /* wl_list_init(&output_list); */
-       registry = wl_display_get_registry(display);
-       wl_registry_add_listener(registry, &registry_listener, sdata);
-       wl_display_dispatch(display);
-       wl_display_roundtrip(display);
-
-       if (sdata->screenshooter == NULL) {
-               PRINTERR("display doesn't support screenshooter");
-               return NULL;
-       }
-
-       screenshooter_add_listener(sdata->screenshooter, &screenshooter_listener,
-                                  sdata);
-
-       if (set_buffer_size(sdata, width, height))
-               return NULL;
-
-
-       wl_list_for_each(output, &sdata->output_list, link) {
-               output->buffer = create_shm_buffer(sdata->shm, output->width,
-                                                  output->height, &output->data);
-               screenshooter_shoot(sdata->screenshooter,
-                                          output->output,
-                                          output->buffer);
-               sdata->buffer_copy_done = 0;
-               while (!sdata->buffer_copy_done) {
-                       wl_display_roundtrip(display);
-               }
+       if (data->max_x <= data->min_x || data->max_y <= data->min_y) {
+               data->width = 0;
+               data->height = 0;
+       } else {
+               data->width = data->max_x - data->min_x;
+               data->height = data->max_y - data->min_y;
        }
-
-       buf = __screenshot_to_buf(sdata, *width, *height);
-
-out:
-       if (display)
-               wl_display_disconnect(display);
-       free(sdata);
-       return buf;
 }
 
 static Evas* create_canvas(int width, int height)
@@ -451,8 +311,13 @@ static void destroy_canvas(Evas* canvas)
        __evas_free_p(canvas);
 }
 
-int captureScreen()
+static int __save_to_png(const char *path, unsigned char *buf,
+                        int width, int height)
 {
+       int ret = -1, err;
+       Evas *ev = NULL;
+       Evas_Object *img;
+
        static void (*__evas_object_resize_p)(Evas_Object *obj,
                                              Evas_Coord w,
                                              Evas_Coord h);
@@ -473,13 +338,6 @@ int captureScreen()
                                                       const char *key,
                                                       const char *flags);
        static Evas_Object *(*__evas_object_image_add_p)(Evas *e);
-       static pthread_mutex_t captureScreenLock = PTHREAD_MUTEX_INITIALIZER;
-       char dstpath[MAX_PATH_LENGTH];
-       char *scrimage;
-       int width, height, err;
-       Evas *ev = NULL;
-       Evas_Object *img;
-       int ret = -1;
 
        rtld_default_set_once(__evas_object_resize_p,
                              "evas_object_resize");
@@ -496,36 +354,23 @@ int captureScreen()
        rtld_default_set_once(__evas_object_image_add_p,
                              "evas_object_image_add");
 
-       pthread_mutex_lock(&captureScreenLock);
-
-       inc_current_event_index();
-       scrimage = __capture_screnshot_wayland(&width, &height);
-       if (unlikely(scrimage == NULL)) {
-               ret = -1;
-               goto out;
-       }
-
        ev = create_canvas(width, height);
        if (unlikely(ev == NULL)) {
-               ret = -1;
-               goto out_image;
+               PRINTERR("failed to create canvas");
+               return -1;
        }
 
-       snprintf(dstpath, sizeof(dstpath),
-                SCREENSHOT_DIRECTORY "/%d_%d.png", getpid(),
-                getCurrentEventIndex());
-
        // make image buffer
        img = __evas_object_image_add_p(ev);
        if (unlikely(img == NULL)) {
-               ret = -1;
+               PRINTERR("failed to add image to canvas");
                goto out_canvas;
        }
 
        //image buffer set
        __evas_object_image_data_set_p(img, NULL);
        __evas_object_image_size_set_p(img, width, height);
-       __evas_object_image_data_set_p(img, scrimage);
+       __evas_object_image_data_set_p(img, buf);
 
        // resize image
        if (height > MAX_HEIGHT) {
@@ -537,8 +382,180 @@ int captureScreen()
        __evas_object_image_data_update_add_p(img, 0, 0, width, height);
 
        //save image to png file
-       err = __evas_object_image_save_p(img, dstpath, NULL, "compress=5");
-       if (err != 0) {
+       err = __evas_object_image_save_p(img, path, NULL, "compress=5");
+       if (err != 0)
+               ret = 0;
+
+out_canvas:
+       destroy_canvas(ev);
+
+       return ret;
+}
+
+static struct efl_data *__edata = NULL;
+
+void __wayland_deinit(void)
+{
+       struct screenshooter_output *output, *next;
+
+       if (!__edata)
+               return;
+
+       wl_list_for_each_safe(output, next, &__edata->output_list, link)
+               free(output);
+
+       wl_registry_destroy(__edata->wl_registry);
+       wl_display_disconnect(__edata->wl_display);
+       free(__edata);
+}
+
+struct efl_data *__wayland_init(void)
+{
+       struct wl_display *display = NULL;
+       struct wl_registry *registry;
+       struct efl_data *data;
+       const char *wayland_socket = NULL;
+
+       if (__edata)
+               return __edata;
+
+       wayland_socket = getenv("WAYLAND_SOCKET");
+       if (!wayland_socket)
+               wayland_socket = getenv("WAYLAND_DISPLAY");
+
+       if (!wayland_socket) {
+               PRINTERR("must be launched by wayland");
+               return NULL;
+       }
+
+       data = malloc(sizeof(*data));
+       if (!data)
+               return NULL;
+
+       data->screenshooter = NULL;
+       wl_list_init(&data->output_list);
+       data->min_x = 0;
+       data->min_y = 0;
+       data->max_x = 0;
+       data->max_y = 0;
+       data->buffer_copy_done = 0;
+
+       display = wl_display_connect(wayland_socket);
+       if (display == NULL) {
+               fprintf(stderr, "failed to create display: %m\n");
+               goto fail;
+       }
+       data->wl_display = display;
+
+       /* wl_list_init(&output_list); */
+       registry = wl_display_get_registry(display);
+       wl_registry_add_listener(registry, &registry_listener, data);
+       wl_display_dispatch(display);
+       wl_display_roundtrip(display);
+
+       data->wl_registry = registry;
+
+       __edata = data;
+
+       return data;
+fail:
+       free(data);
+       return NULL;
+}
+static int __capture_screnshot_wayland(const char *path)
+{
+       struct screenshooter_output *output;
+       struct efl_data *data;
+       tbm_surface_h t_surface;
+       struct wl_buffer *buffer;
+       struct wayland_tbm_client *tbm_client;
+       tbm_surface_info_s tsuri;
+       int plane_idx = 0;
+       int ret = -1;
+       int err;
+
+       data =  __wayland_init();
+       if (!data) {
+               PRINTERR("failed to init wayland protocol\n");
+               return -1;
+       }
+
+       if (!data->screenshooter) {
+               PRINTERR("display doesn't support screenshooter\n");
+               return -1;
+       }
+
+       __set_buffer_size(data);
+
+       tbm_client = wayland_tbm_client_init(data->wl_display);
+       if (!tbm_client) {
+               PRINTERR("failed to init tbm client\n");
+               return -1;
+       }
+
+       t_surface = tbm_surface_create(data->width, data->height, TBM_FORMAT_XRGB8888);
+       if (!t_surface) {
+               PRINTERR("failed to create tbm_surface\n");
+               goto fail_tbm_client;
+       }
+
+       buffer = wayland_tbm_client_create_buffer(tbm_client, t_surface);
+       if (!buffer) {
+               PRINTERR("failed to create wl_buffer for screenshot\n");
+               goto fail_tbm_surface;
+       }
+
+       wl_list_for_each(output, &data->output_list, link) {
+               screenshooter_shoot(data->screenshooter,
+                                          output->output,
+                                          buffer);
+               data->buffer_copy_done = 0;
+               while (!data->buffer_copy_done) {
+                       wl_display_roundtrip(data->wl_display);
+               }
+       }
+
+       err = tbm_surface_map(t_surface,
+                             TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE,
+                             &tsuri);
+       if (err != TBM_SURFACE_ERROR_NONE) {
+               PRINTERR("failed to map tbm_surface\n");
+               goto fail_map_surface;
+       }
+
+       ret = __save_to_png(path, tsuri.planes[plane_idx].ptr,
+                           data->width, data->height);
+
+       tbm_surface_unmap(t_surface);
+
+fail_map_surface:
+       wayland_tbm_client_destroy_buffer(tbm_client, buffer);
+
+fail_tbm_surface:
+       tbm_surface_destroy(t_surface);
+
+fail_tbm_client:
+       wayland_tbm_client_deinit(tbm_client);
+
+       return ret;
+}
+
+int captureScreen()
+{
+       static pthread_mutex_t captureScreenLock = PTHREAD_MUTEX_INITIALIZER;
+       char dstpath[MAX_PATH_LENGTH];
+       int ret = -1;
+
+       pthread_mutex_lock(&captureScreenLock);
+
+       inc_current_event_index();
+
+       snprintf(dstpath, sizeof(dstpath),
+                SCREENSHOT_DIRECTORY "/%d_%d.png", getpid(),
+                getCurrentEventIndex());
+
+       ret = __capture_screnshot_wayland(dstpath);
+       if (!ret) {
                if (chmod(dstpath, 0777) == -1)
                        PRINTWRN("cannot chmod -R777 <%s>", dstpath);
 
@@ -564,14 +581,6 @@ int captureScreen()
                ret = 0;
        }
 
-       // release resources
-out_canvas:
-       destroy_canvas(ev);
-
-out_image:
-       free(scrimage);
-
-out:
        pthread_mutex_unlock(&captureScreenLock);
        return ret;
 }
diff --git a/helper/wayland-api.c b/helper/wayland-api.c
deleted file mode 100644 (file)
index 5a3a8fb..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#include <stdlib.h>
-#include <stdint.h>
-#include "wayland-util.h"
-
-extern const struct wl_interface wl_buffer_interface;
-extern const struct wl_interface wl_output_interface;
-
-static const struct wl_interface *types[] = {
-       &wl_output_interface,
-       &wl_buffer_interface,
-};
-
-static const struct wl_message screenshooter_requests[] = {
-       { "shoot", "oo", types + 0 },
-};
-
-static const struct wl_message screenshooter_events[] = {
-       { "done", "", types + 0 },
-};
-
-WL_EXPORT const struct wl_interface screenshooter_interface = {
-       "screenshooter", 1,
-       1, screenshooter_requests,
-       1, screenshooter_events,
-};
-
diff --git a/helper/wayland-api.h b/helper/wayland-api.h
deleted file mode 100644 (file)
index 5518f2b..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-#ifndef SCREENSHOOTER_CLIENT_PROTOCOL_H
-#define SCREENSHOOTER_CLIENT_PROTOCOL_H
-
-#ifdef  __cplusplus
-extern "C" {
-#endif
-
-#include <stdint.h>
-#include <stddef.h>
-#include "wayland-client.h"
-
-struct wl_client;
-struct wl_resource;
-
-struct screenshooter;
-struct wl_buffer;
-struct wl_output;
-
-extern const struct wl_interface screenshooter_interface;
-
-struct screenshooter_listener {
-       /**
-        * done - (none)
-        */
-       void (*done)(void *data,
-                    struct screenshooter *screenshooter);
-};
-
-static inline int
-screenshooter_add_listener(struct screenshooter *screenshooter,
-                          const struct screenshooter_listener *listener, void *data)
-{
-       return wl_proxy_add_listener((struct wl_proxy *) screenshooter,
-                                    (void (**)(void)) listener, data);
-}
-
-#define SCREENSHOOTER_SHOOT    0
-
-static inline void
-screenshooter_set_user_data(struct screenshooter *screenshooter, void *user_data)
-{
-       wl_proxy_set_user_data((struct wl_proxy *) screenshooter, user_data);
-}
-
-static inline void *
-screenshooter_get_user_data(struct screenshooter *screenshooter)
-{
-       return wl_proxy_get_user_data((struct wl_proxy *) screenshooter);
-}
-
-static inline void
-screenshooter_destroy(struct screenshooter *screenshooter)
-{
-       wl_proxy_destroy((struct wl_proxy *) screenshooter);
-}
-
-static inline void
-screenshooter_shoot(struct screenshooter *screenshooter, struct wl_output *output, struct wl_buffer *buffer)
-{
-       wl_proxy_marshal((struct wl_proxy *) screenshooter,
-                        SCREENSHOOTER_SHOOT, output, buffer);
-}
-
-#ifdef  __cplusplus
-}
-#endif
-
-#endif
index feb89ea..f060b85 100644 (file)
@@ -27,6 +27,15 @@ BuildRequires: capi-system-runtime-info-devel
 BuildRequires: python
 BuildRequires: capi-appfw-application
 
+%if "%{_with_wayland}" == "1"
+BuildRequires:  pkgconfig(wayland-server)
+BuildRequires:  pkgconfig(wayland-tbm-client)
+BuildRequires:  pkgconfig(screenshooter-client)
+BuildRequires:  pkgconfig(ecore-wayland)
+BuildRequires:  pkgconfig(wayland-client) >= 1.0.0
+BuildRequires:  pkgconfig(tizen-extension-client)
+%endif
+
 # Applied python acceleration
 %ifarch armv7l
 BuildRequires: python-accel-armv7l-cross-arm