From 331a1c2fff786a928ea28b89e5a85cb7c3be512e Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 17 Apr 2015 12:27:50 +0900 Subject: [PATCH] implementation wl_screenshooter server Change-Id: Iaf78519f3dc42eb63cb02f5ed6c8e19343c7b0ef --- configure.ac | 12 +- src/modules/Makefile.mk | 3 +- src/modules/Makefile_wl_screenshot.mk | 24 ++-- src/modules/wl_screenshot/e_mod_main.c | 7 ++ src/modules/wl_screenshot/e_screenshooter_server.c | 136 +++++++++++++++++++++ src/modules/wl_screenshot/e_screenshooter_server.h | 7 ++ .../e_screenshooter_server_protocol.h | 45 +++++++ 7 files changed, 223 insertions(+), 11 deletions(-) create mode 100644 src/modules/wl_screenshot/e_screenshooter_server.c create mode 100644 src/modules/wl_screenshot/e_screenshooter_server.h create mode 100644 src/modules/wl_screenshot/e_screenshooter_server_protocol.h diff --git a/configure.ac b/configure.ac index fcb2fb0..ffd2ef4 100644 --- a/configure.ac +++ b/configure.ac @@ -903,6 +903,16 @@ define([CHECK_MODULE_WL_FB], ]) AM_CONDITIONAL([HAVE_WL_FB], [test "x${WL_FB}" = "xtrue"]) +define([CHECK_MODULE_WL_SCREENSHOT], +[ + if test "x${have_wayland_clients}" = "xyes" || test "x${e_cv_want_wayland_only}" = "xyes"; then + AC_E_CHECK_PKG(WL_SCREENSHOT, [ ecore >= $efl_version eina >= $efl_version ], [WL_SCREENSHOT=true], [WL_SCREENSHOT=false]) + else + WL_SCREENSHOT=false + fi +]) +AM_CONDITIONAL([HAVE_WL_SCREENSHOT], [test "x${WL_SCREENSHOT}" = "xtrue"]) + define([CHECK_MODULE_WL_DRM], [ if test "x${have_wayland}" = "xyes" ; then @@ -968,7 +978,7 @@ AC_E_OPTIONAL_MODULE([wl_desktop_shell], $have_wayland, [CHECK_MODULE_WL_DESKTOP AC_E_OPTIONAL_MODULE([wl_x11], $have_wayland, $wl_x11) AC_E_OPTIONAL_MODULE([wl_fb], $have_wayland, [CHECK_MODULE_WL_FB]) AC_E_OPTIONAL_MODULE([wl_drm], $have_wayland, [CHECK_MODULE_WL_DRM]) -#AC_E_OPTIONAL_MODULE([wl_screenshot], true, [CHECK_MODULE_WL_SCREENSHOT]) +AC_E_OPTIONAL_MODULE([wl_screenshot], $have_wayland, [CHECK_MODULE_WL_SCREENSHOT]) AC_E_OPTIONAL_MODULE([policy_mobile], true) HALT="/sbin/shutdown -h now" diff --git a/src/modules/Makefile.mk b/src/modules/Makefile.mk index 6efe674..27184a9 100644 --- a/src/modules/Makefile.mk +++ b/src/modules/Makefile.mk @@ -129,7 +129,6 @@ include src/modules/Makefile_wl_x11.mk include src/modules/Makefile_wl_fb.mk -#if HAVE_WAYLAND_SCREENSHOT -#include src/modules/Makefile_wl_screenshot.mk +include src/modules/Makefile_wl_screenshot.mk include src/modules/Makefile_policy_mobile.mk diff --git a/src/modules/Makefile_wl_screenshot.mk b/src/modules/Makefile_wl_screenshot.mk index 09ceb83..9be71cd 100644 --- a/src/modules/Makefile_wl_screenshot.mk +++ b/src/modules/Makefile_wl_screenshot.mk @@ -1,7 +1,11 @@ EXTRA_DIST += src/modules/wl_screenshot/module.desktop.in \ src/modules/wl_screenshot/e-module-wl_screenshot.edj \ src/modules/wl_screenshot/e_screenshooter_client_protocol.h \ -src/modules/wl_screenshot/e_screenshooter_client_protocol.c +src/modules/wl_screenshot/e_screenshooter_client_protocol.c \ +src/modules/wl_screenshot/e_screenshooter_server.h \ +src/modules/wl_screenshot/e_screenshooter_server.c \ +src/modules/wl_screenshot/e_screenshooter_server_protocol.h + if USE_MODULE_WL_SCREENSHOT wl_screenshotdir = $(MDIR)/wl_screenshot wl_screenshot_DATA = src/modules/wl_screenshot/e-module-wl_screenshot.edj \ @@ -10,16 +14,20 @@ wl_screenshot_DATA = src/modules/wl_screenshot/e-module-wl_screenshot.edj \ wl_screenshotpkgdir = $(MDIR)/wl_screenshot/$(MODULE_ARCH) wl_screenshotpkg_LTLIBRARIES = src/modules/wl_screenshot/module.la -wl_screenshot_module_la_DEPENDENCIES = $(MDEPENDENCIES) -wl_screenshot_module_la_CPPFLAGS = $(MOD_CPPFLAGS) @WL_SCREENSHOT_CFLAGS@ @WAYLAND_CFLAGS@ -wl_screenshot_module_la_LIBADD = $(MOD_LIBS) @WL_SCREENSHOT_LIBS@ @WAYLAND_LIBS@ -wl_screenshot_module_la_LDFLAGS = $(MOD_LDFLAGS) # @WL_SCREENSHOT_LDFLAGS@ @WAYLAND_LDFLAGS@ -wl_screenshot_module_la_SOURCES = src/modules/wl_screenshot/e_mod_main.c \ +src_modules_wl_screenshot_module_la_DEPENDENCIES = $(MDEPENDENCIES) +src_modules_wl_screenshot_module_la_CPPFLAGS = $(MOD_CPPFLAGS) @WL_SCREENSHOT_CFLAGS@ @WAYLAND_CFLAGS@ -DNEED_WL +src_modules_wl_screenshot_module_la_LIBADD = $(LIBS) @WL_SCREENSHOT_LIBS@ @WAYLAND_LIBS@ +src_modules_wl_screenshot_module_la_LDFLAGS = $(MOD_LDFLAGS) + +src_modules_wl_screenshot_module_la_SOURCES = src/modules/wl_screenshot/e_mod_main.c \ src/modules/wl_screenshot/e_mod_main.h \ src/modules/wl_screenshot/e_screenshooter_client_protocol.h \ - src/modules/wl_screenshot/e_screenshooter_client_protocol.c + src/modules/wl_screenshot/e_screenshooter_client_protocol.c \ + src/modules/wl_screenshot/e_screenshooter_server.h \ + src/modules/wl_screenshot/e_screenshooter_server.c \ + src/modules/wl_screenshot/e_screenshooter_server_protocol.h -PHONIES: wl_screenshot install-wl_screenshot +PHONIES += wl_screenshot install-wl_screenshot wl_screenshot: $(wl_screenshotpkg_LTLIBRARIES) $(wl_screenshot_DATA) install-wl_screenshot: install-wl_screenshotDATA install-wl_screenshotpkgLTLIBRARIES endif diff --git a/src/modules/wl_screenshot/e_mod_main.c b/src/modules/wl_screenshot/e_mod_main.c index eadc89a..9a92fbf 100644 --- a/src/modules/wl_screenshot/e_mod_main.c +++ b/src/modules/wl_screenshot/e_mod_main.c @@ -3,6 +3,7 @@ #include #include #include "e_screenshooter_client_protocol.h" +#include "e_screenshooter_server.h" typedef struct _Instance Instance; struct _Instance @@ -62,6 +63,12 @@ e_modapi_init(E_Module *m) struct wl_display *disp; struct wl_registry *reg; + const char *engine_name; + EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, NULL); + engine_name = ecore_evas_engine_name_get(e_comp->ee); + if (!strncmp(engine_name, "drm", 3) || !strncmp(engine_name, "fb", 2)) + return e_screenshooter_server_init(m); + if (!ecore_wl_init(NULL)) return NULL; if (!(disp = ecore_wl_display_get())) diff --git a/src/modules/wl_screenshot/e_screenshooter_server.c b/src/modules/wl_screenshot/e_screenshooter_server.c new file mode 100644 index 0000000..5baa362 --- /dev/null +++ b/src/modules/wl_screenshot/e_screenshooter_server.c @@ -0,0 +1,136 @@ +#define E_COMP_WL +#include "e.h" +#include +#include +#include "e_screenshooter_server_protocol.h" +#include "e_screenshooter_server.h" + +static void +_e_screenshooter_center_rect (int src_w, int src_h, int dst_w, int dst_h, Eina_Rectangle *fit) +{ + float rw, rh; + + if (src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0 || !fit) + return; + + rw = (float)src_w / dst_w; + rh = (float)src_h / dst_h; + + if (rw > rh) + { + fit->w = dst_w; + fit->h = src_h * rw; + fit->x = 0; + fit->y = (dst_h - fit->h) / 2; + } + else if (rw < rh) + { + fit->w = src_w * rw; + fit->h = dst_h; + fit->x = (dst_w - fit->w) / 2; + fit->y = 0; + } + else + { + fit->w = dst_w; + fit->h = dst_h; + fit->x = 0; + fit->y = 0; + } +} + +static void +_e_screenshooter_shoot(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *output_resource, + struct wl_resource *buffer_resource) +{ + E_Comp_Wl_Output *output = wl_resource_get_user_data(output_resource); + struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get(buffer_resource); + Eina_Rectangle center = {0,}; + int32_t bw, bh, bs; + uint32_t bf; + void *bp; + + if (!output || !shm_buffer) + { + wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT, + "screenshooter failed: wrong %s resource", + (!output)?"output":"buffer"); + return; + } + + bw = wl_shm_buffer_get_width(shm_buffer); + bh = wl_shm_buffer_get_height(shm_buffer); + bf = wl_shm_buffer_get_format(shm_buffer); + bp = wl_shm_buffer_get_data(shm_buffer); + bs = wl_shm_buffer_get_stride(shm_buffer); + + _e_screenshooter_center_rect(output->w, output->h, bw, bh, ¢er); +printf ("@@@ %s(%d) %d, %d, %d, %x, s(%d,%d,%d,%d) d(%d,%d,%d,%d)\n", __FUNCTION__, __LINE__, + bs, bw, bh, bf, + output->x, output->y, output->w, output->h, + center.x, center.y, center.w, center.h); + /* do dump */ + wl_shm_buffer_begin_access(shm_buffer); + evas_render_copy(e_comp->evas, bp, bs, bw, bh, bf, + output->x, output->y, output->w, output->h, + center.x, center.y, center.w, center.h); + wl_shm_buffer_end_access(shm_buffer); + + /* done */ + screenshooter_send_done(resource); +} + +static const struct screenshooter_interface _e_screenshooter_interface = +{ + _e_screenshooter_shoot +}; + +static void +_e_screenshooter_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) +{ + E_Comp_Data *cdata; + struct wl_resource *res; + + if (!(cdata = data)) + { + wl_client_post_no_memory(client); + return; + } + + if (!(res = wl_resource_create(client, &screenshooter_interface, MIN(version, 1), id))) + { + ERR("Could not create screenshooter resource: %m"); + wl_client_post_no_memory(client); + return; + } + + wl_resource_set_implementation(res, &_e_screenshooter_interface, cdata, NULL); +} + +void* +e_screenshooter_server_init(E_Module *m) +{ + E_Comp_Data *cdata; + + if (!e_comp) return EINA_FALSE; + if (!(cdata = e_comp->wl_comp_data)) return EINA_FALSE; + if (!cdata->wl.disp) return EINA_FALSE; + + /* try to add screenshooter to wayland globals */ + if (!wl_global_create(cdata->wl.disp, &screenshooter_interface, 1, + cdata, _e_screenshooter_cb_bind)) + { + ERR("Could not add screenshooter to wayland globals: %m"); + return EINA_FALSE; + } + + return m; +} + +int +e_screenshooter_server_shutdown(E_Module *m) +{ + return 1; +} diff --git a/src/modules/wl_screenshot/e_screenshooter_server.h b/src/modules/wl_screenshot/e_screenshooter_server.h new file mode 100644 index 0000000..3320797 --- /dev/null +++ b/src/modules/wl_screenshot/e_screenshooter_server.h @@ -0,0 +1,7 @@ +#ifndef E_SCREENSHOOTER_SERVER_H +#define E_SCREENSHOOTER_SERVER_H + +void* e_screenshooter_server_init(E_Module *m); +int e_screenshooter_server_shutdown(E_Module *m); + +#endif diff --git a/src/modules/wl_screenshot/e_screenshooter_server_protocol.h b/src/modules/wl_screenshot/e_screenshooter_server_protocol.h new file mode 100644 index 0000000..c0bc888 --- /dev/null +++ b/src/modules/wl_screenshot/e_screenshooter_server_protocol.h @@ -0,0 +1,45 @@ +#ifndef E_SCREENSHOOTER_SERVER_PROTOCOL_H +#define E_SCREENSHOOTER_SERVER_PROTOCOL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include "wayland-util.h" + +struct wl_client; +struct wl_resource; + +struct screenshooter; + +extern const struct wl_interface screenshooter_interface; + +struct screenshooter_interface { + /** + * shoot - (none) + * @output: (none) + * @buffer: (none) + */ + void (*shoot)(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *output, + struct wl_resource *buffer); +}; + +#define SCREENSHOOTER_DONE 0 + +#define SCREENSHOOTER_DONE_SINCE_VERSION 1 + +static inline void +screenshooter_send_done(struct wl_resource *resource_) +{ + wl_resource_post_event(resource_, SCREENSHOOTER_DONE); +} + +#ifdef __cplusplus +} +#endif + +#endif -- 2.7.4