#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <xf86drm.h>
+#include <tbm_bufmgr.h>
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
#include <Elementary.h>
#include <Ecore_Evas.h>
#if X11
+#include <X11/Xlib.h>
+#include <X11/extensions/Xvlib.h>
+#include <X11/extensions/Xvproto.h>
+#include <X11/extensions/Xdamage.h>
+#include <dri2.h>
#include <Ecore_X.h>
#include <utilX.h>
#endif /* end of X11 */
#include <wayland-client.h>
#include "tizen_notification-client-protocol.h"
#include "tizen_window_screen-client-protocol.h"
+#include "tizen-buffer-pool-client-protocol.h"
+#include "screenshooter-client-protocol.h"
#endif /* end of WAYLAND */
/* callback handler index */
void *data;
} Efl_Util_Callback_Info;
+#if WAYLAND
typedef struct _Efl_Util_Wl_Surface_Lv_Info
{
void *surface; /* wl_surface */
Eina_Bool wait_for_done;
} Efl_Util_Wl_Surface_Scr_Mode_Info;
+typedef struct _Efl_Util_Wl_Output_Info
+{
+ struct wl_output *output;
+ int offset_x, offset_y, width, height;
+} Efl_Util_Wl_Output_Info;
+#endif
+
typedef struct _Efl_Util_Data
{
/* x11 related stuffs */
struct tizen_window_screen *proto;
Eina_Hash *hash;
} scr_mode;
+ struct
+ {
+ struct screenshooter *screenshooter;
+ struct tizen_buffer_pool *buffer_pool;
+ Eina_List *output_list;
+ } shot;
#endif /* end of WAYLAND */
} wl;
} Efl_Util_Data;
#if WAYLAND
NULL,
{ NULL, NULL }, /* tizen_notification protocol */
- { NULL, NULL } /* tizen_window_screen protocol */
+ { NULL, NULL }, /* tizen_window_screen protocol */
+ { NULL, NULL, NULL } /* screenshooter protocol */
#endif /* end of WAYLAND */
}
};
if (_eflutil.wl.init) return EINA_TRUE;
+ ecore_wl_init(NULL);
+
_eflutil.wl.dpy = ecore_wl_display_get();
EINA_SAFETY_ON_NULL_RETURN_VAL(_eflutil.wl.dpy, EINA_FALSE);
}
static void
+_cb_wl_output_geometry(void *data, struct wl_output *wl_output, int x, int y,
+ int physical_width, int physical_height, int subpixel,
+ const char *make, const char *model, int transform)
+{
+ Efl_Util_Wl_Output_Info *output = wl_output_get_user_data(wl_output);
+ if (wl_output == output->output)
+ {
+ output->offset_x = x;
+ output->offset_y = y;
+ }
+}
+
+static void
+_cb_wl_output_mode(void *data, struct wl_output *wl_output, uint32_t flags,
+ int width, int height, int refresh)
+{
+ Efl_Util_Wl_Output_Info *output = wl_output_get_user_data(wl_output);
+ if (wl_output == output->output && (flags & WL_OUTPUT_MODE_CURRENT))
+ {
+ output->width = width;
+ output->height = height;
+ }
+}
+
+static void
+_cb_wl_output_done(void *data, struct wl_output *wl_output)
+{
+}
+
+static void
+_cb_wl_output_scale(void *data, struct wl_output *wl_output, int32_t factor)
+{
+}
+
+static const struct wl_output_listener output_listener =
+{
+ _cb_wl_output_geometry,
+ _cb_wl_output_mode,
+ _cb_wl_output_done,
+ _cb_wl_output_scale
+};
+
+static void
+_cb_wl_screenshot_done(void *data, struct screenshooter *screenshooter)
+{
+ Eina_Bool *shot_done = (Eina_Bool*)data;
+ if (shot_done)
+ *shot_done = EINA_TRUE;
+}
+
+static const struct screenshooter_listener screenshooter_listener =
+{
+ _cb_wl_screenshot_done
+};
+
+static void
_cb_wl_reg_global(void *data,
struct wl_registry *reg,
unsigned int name,
_eflutil.wl.scr_mode.hash = eina_hash_pointer_new(free);
_eflutil.wl.scr_mode.proto = proto;
}
+ else if (strcmp(interface, "wl_output") == 0)
+ {
+ Efl_Util_Wl_Output_Info *output = calloc(1, sizeof(Efl_Util_Wl_Output_Info));
+ EINA_SAFETY_ON_NULL_RETURN(output);
+
+ _eflutil.wl.shot.output_list = eina_list_append(_eflutil.wl.shot.output_list, output);
+
+ output->output = wl_registry_bind(reg, name, &wl_output_interface, version);
+ wl_output_add_listener(output->output, &output_listener, output);
+ }
+ else if (strcmp(interface, "tizen_buffer_pool") == 0)
+ {
+ _eflutil.wl.shot.buffer_pool = wl_registry_bind(reg, name, &tizen_buffer_pool_interface, 1);
+ }
+ else if (strcmp(interface, "screenshooter") == 0)
+ {
+ _eflutil.wl.shot.screenshooter = wl_registry_bind(reg, name, &screenshooter_interface, version);
+ screenshooter_add_listener(_eflutil.wl.shot.screenshooter, &screenshooter_listener, NULL);
+ }
}
static void
return EFL_UTIL_ERROR_NONE;
}
-API efl_util_screenshot_h
-efl_util_screenshot_initialize(int width,
- int height)
+struct _efl_util_screenshot_h
+{
+ int width;
+ int height;
+
+#if X11
+ Ecore_X_Display *dpy;
+ int internal_display;
+ int screen;
+ Window root;
+ Pixmap pixmap;
+ GC gc;
+ Atom atom_capture;
+
+ /* port */
+ int port;
+
+ /* damage */
+ Damage damage;
+ int damage_base;
+
+ /* dri2 */
+ int eventBase, errorBase;
+ int dri2Major, dri2Minor;
+ char *driver_name, *device_name;
+ drm_magic_t magic;
+
+ /* drm */
+ int drm_fd;
+#endif
+
+ Eina_Bool shot_done;
+
+ /* tbm bufmgr */
+ tbm_bufmgr bufmgr;
+};
+
+/* scrrenshot handle */
+static efl_util_screenshot_h g_screenshot;
+
+#if X11
+#define FOURCC(a,b,c,d) (((unsigned)d&0xff)<<24 | ((unsigned)c&0xff)<<16 | ((unsigned)b&0xff)<<8 | ((unsigned)a&0xff))
+#define FOURCC_RGB32 FOURCC('R','G','B','4')
+#define TIMEOUT_CAPTURE 3
+
+/* x error handling */
+static Bool g_efl_util_x_error_caught;
+
+static int
+_efl_util_screenshot_x_error_handle(Display *dpy, XErrorEvent *ev)
{
+ if (!g_screenshot || (dpy != g_screenshot->dpy))
+ return 0;
+
+ g_efl_util_x_error_caught = True;
+
return 0;
}
-API tbm_surface_h
-efl_util_screenshot_take_tbm_surface(efl_util_screenshot_h screenshot)
+static int
+_efl_util_screenshot_get_port(Display *dpy, unsigned int id, Window win)
{
- return 0;
+ unsigned int ver, rev, req_base, evt_base, err_base;
+ unsigned int adaptors;
+ XvAdaptorInfo *ai = NULL;
+ XvImageFormatValues *fo = NULL;
+ int formats;
+ int i, j, p;
+
+ if (XvQueryExtension(dpy, &ver, &rev, &req_base, &evt_base, &err_base) != Success)
+ {
+ fprintf(stderr, "[screenshot] fail: no XV extension. \n");
+ return -1;
+ }
+
+ if (XvQueryAdaptors(dpy, win, &adaptors, &ai) != Success)
+ {
+ fprintf(stderr, "[screenshot] fail: query adaptors. \n");
+ return -1;
+ }
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(ai, -1);
+
+ for (i = 0; i < adaptors; i++)
+ {
+ int support_format = False;
+
+ if (!(ai[i].type & XvInputMask) ||
+ !(ai[i].type & XvStillMask))
+ continue;
+
+ p = ai[i].base_id;
+
+ fo = XvListImageFormats(dpy, p, &formats);
+ for (j = 0; j < formats; j++)
+ if (fo[j].id == (int)id)
+ support_format = True;
+
+ if (fo)
+ XFree(fo);
+
+ if (!support_format)
+ continue;
+
+ for (; p < ai[i].base_id + ai[i].num_ports; p++)
+ {
+ if (XvGrabPort(dpy, p, 0) == Success)
+ {
+ XvFreeAdaptorInfo(ai);
+ return p;
+ }
+ }
+ }
+
+ XvFreeAdaptorInfo(ai);
+
+ XSync(dpy, False);
+
+ return -1;
}
-API int
-efl_util_screenshot_deinitialize(efl_util_screenshot_h screenshot)
+static int _efl_util_screenshot_get_best_size(Display *dpy, int port, int width, int height, unsigned int *best_width, unsigned int *best_height)
+{
+ XErrorHandler old_handler = NULL;
+
+ Atom atom_capture = XInternAtom(dpy, "_USER_WM_PORT_ATTRIBUTE_CAPTURE", False);
+
+ g_efl_util_x_error_caught = False;
+ old_handler = XSetErrorHandler(_efl_util_screenshot_x_error_handle);
+
+ XvSetPortAttribute(dpy, port, atom_capture, 1);
+ XSync(dpy, False);
+
+ g_efl_util_x_error_caught = False;
+ XSetErrorHandler(old_handler);
+
+ XvQueryBestSize(dpy, port, 0, 0, 0, width, height, best_width, best_height);
+ if (best_width <= 0 || best_height <= 0)
+ return 0;
+
+ return 1;
+}
+#endif
+
+API efl_util_screenshot_h efl_util_screenshot_initialize(int width, int height)
+{
+#if X11
+ efl_util_screenshot_h screenshot = NULL;
+ int depth = 0;
+ int damage_err_base = 0;
+ unsigned int best_width = 0;
+ unsigned int best_height = 0;
+
+ EINA_SAFETY_ON_FALSE_GOTO(width > 0, fail_param);
+ EINA_SAFETY_ON_FALSE_GOTO(height > 0, fail_param);
+
+ if (g_screenshot != NULL)
+ {
+ if (g_screenshot->width != width || g_screenshot->height != height)
+ {
+ // TODO: recreate pixmap and update information
+ if (!_efl_util_screenshot_get_best_size(screenshot->dpy, screenshot->port, width, height, &best_width, &best_height))
+ {
+ set_last_result(EFL_UTIL_ERROR_SCREENSHOT_INIT_FAIL);
+ return NULL;
+ }
+
+ g_screenshot->width = width;
+ g_screenshot->height = height;
+ }
+
+ return g_screenshot;
+ }
+
+ screenshot = calloc(1, sizeof(struct _efl_util_screenshot_h));
+ EINA_SAFETY_ON_NULL_GOTO(screenshot, fail_memory);
+
+ /* set dpy */
+ screenshot->dpy = ecore_x_display_get();
+ if (!screenshot->dpy)
+ {
+ screenshot->dpy = XOpenDisplay(0);
+ EINA_SAFETY_ON_NULL_GOTO(screenshot, fail_init);
+
+ /* for XCloseDisplay at denitialization */
+ screenshot->internal_display = 1;
+ }
+
+ /* set screen */
+ screenshot->screen = DefaultScreen(screenshot->dpy);
+
+ /* set root window */
+ screenshot->root = DefaultRootWindow(screenshot->dpy);
+
+ /* initialize capture adaptor */
+ screenshot->port = _efl_util_screenshot_get_port(screenshot->dpy, FOURCC_RGB32, screenshot->root);
+ EINA_SAFETY_ON_FALSE_GOTO(screenshot->port > 0, fail_init);
+
+ /* get the best size */
+ _efl_util_screenshot_get_best_size(screenshot->dpy, screenshot->port, width, height, &best_width, &best_height);
+ EINA_SAFETY_ON_FALSE_GOTO(best_width > 0, fail_init);
+ EINA_SAFETY_ON_FALSE_GOTO(best_height > 0, fail_init);
+
+ /* set the width and the height */
+ screenshot->width = best_width;
+ screenshot->height = best_height;
+
+ /* create a pixmap */
+ depth = DefaultDepth(screenshot->dpy, screenshot->screen);
+ screenshot->pixmap = XCreatePixmap(screenshot->dpy, screenshot->root, screenshot->width, screenshot->height, depth);
+ EINA_SAFETY_ON_FALSE_GOTO(screenshot->pixmap > 0, fail_init);
+
+ screenshot->gc = XCreateGC(screenshot->dpy, screenshot->pixmap, 0, 0);
+ EINA_SAFETY_ON_NULL_GOTO(screenshot->gc, fail_init);
+
+ XSetForeground(screenshot->dpy, screenshot->gc, 0xFF000000);
+ XFillRectangle(screenshot->dpy, screenshot->pixmap, screenshot->gc, 0, 0, width, height);
+
+ /* initialize damage */
+ if (!XDamageQueryExtension(screenshot->dpy, &screenshot->damage_base, &damage_err_base))
+ goto fail_init;
+
+ screenshot->damage = XDamageCreate(screenshot->dpy, screenshot->pixmap, XDamageReportNonEmpty);
+ EINA_SAFETY_ON_FALSE_GOTO(screenshot->damage > 0, fail_init);
+
+ /* initialize dri3 and dri2 */
+ if (!DRI2QueryExtension(screenshot->dpy, &screenshot->eventBase, &screenshot->errorBase))
+ {
+ fprintf(stderr, "[screenshot] fail: DRI2QueryExtention\n");
+ goto fail_init;
+ }
+
+ if (!DRI2QueryVersion(screenshot->dpy, &screenshot->dri2Major, &screenshot->dri2Minor))
+ {
+ fprintf(stderr, "[screenshot] fail: DRI2QueryVersion\n");
+ goto fail_init;
+ }
+
+ if (!DRI2Connect(screenshot->dpy, screenshot->root, &screenshot->driver_name, &screenshot->device_name))
+ {
+ fprintf(stderr, "[screenshot] fail: DRI2Connect\n");
+ goto fail_init;
+ }
+
+ screenshot->drm_fd = open(screenshot->device_name, O_RDWR);
+ EINA_SAFETY_ON_FALSE_GOTO(screenshot->drm_fd >= 0, fail_init);
+
+ if (drmGetMagic(screenshot->drm_fd, &screenshot->magic))
+ {
+ fprintf(stderr, "[screenshot] fail: drmGetMagic\n");
+ goto fail_init;
+ }
+
+ if (!DRI2Authenticate(screenshot->dpy, screenshot->root, screenshot->magic))
+ {
+ fprintf(stderr, "[screenshot] fail: DRI2Authenticate\n");
+ goto fail_init;
+ }
+
+ if (!drmAuthMagic(screenshot->drm_fd, screenshot->magic))
+ {
+ fprintf(stderr, "[screenshot] fail: drmAuthMagic\n");
+ goto fail_init;
+ }
+
+ DRI2CreateDrawable(screenshot->dpy, screenshot->pixmap);
+
+ /* tbm bufmgr */
+ screenshot->bufmgr = tbm_bufmgr_init(screenshot->drm_fd);
+ EINA_SAFETY_ON_NULL_GOTO(screenshot->bufmgr, fail_init);
+
+ XFlush(screenshot->dpy);
+
+ g_screenshot = screenshot;
+ set_last_result(EFL_UTIL_ERROR_NONE);
+
+ return g_screenshot;
+#endif
+
+#if WAYLAND
+ efl_util_screenshot_h screenshot = NULL;
+
+ if (!_eflutil.wl.shot.screenshooter)
+ {
+ int ret = 0;
+ _wl_init();
+ while (!_eflutil.wl.shot.screenshooter && ret != -1)
+ ret = wl_display_dispatch(_eflutil.wl.dpy);
+ EINA_SAFETY_ON_NULL_GOTO(_eflutil.wl.shot.screenshooter, fail_init);
+ EINA_SAFETY_ON_NULL_GOTO(_eflutil.wl.shot.buffer_pool, fail_init);
+ }
+
+ EINA_SAFETY_ON_FALSE_GOTO(width > 0, fail_param);
+ EINA_SAFETY_ON_FALSE_GOTO(height > 0, fail_param);
+
+ if (g_screenshot)
+ {
+ if (g_screenshot->width != width || g_screenshot->height != height)
+ {
+ g_screenshot->width = width;
+ g_screenshot->height = height;
+ }
+
+ return g_screenshot;
+ }
+
+ screenshot = calloc(1, sizeof(struct _efl_util_screenshot_h));
+ EINA_SAFETY_ON_NULL_GOTO(screenshot, fail_memory);
+
+ screenshot->width = width;
+ screenshot->height = height;
+
+ screenshot->bufmgr = tbm_bufmgr_init(-1);
+ EINA_SAFETY_ON_NULL_GOTO(screenshot->bufmgr, fail_init);
+
+ g_screenshot = screenshot;
+ set_last_result(EFL_UTIL_ERROR_NONE);
+
+ screenshooter_set_user_data(_eflutil.wl.shot.screenshooter, &screenshot->shot_done);
+
+ return g_screenshot;
+#endif
+fail_param:
+ if (screenshot)
+ efl_util_screenshot_deinitialize(screenshot);
+ set_last_result(EFL_UTIL_ERROR_INVALID_PARAMETER);
+ return NULL;
+fail_memory:
+ if (screenshot)
+ efl_util_screenshot_deinitialize(screenshot);
+ set_last_result(EFL_UTIL_ERROR_OUT_OF_MEMORY);
+ return NULL;
+fail_init:
+ if (screenshot)
+ efl_util_screenshot_deinitialize(screenshot);
+ set_last_result(EFL_UTIL_ERROR_SCREENSHOT_INIT_FAIL);
+ return NULL;
+}
+
+API int efl_util_screenshot_deinitialize(efl_util_screenshot_h screenshot)
{
+#if X11
+ if (!screenshot)
+ return EFL_UTIL_ERROR_INVALID_PARAMETER;
+
+ /* tbm bufmgr */
+ if (screenshot->bufmgr)
+ tbm_bufmgr_deinit(screenshot->bufmgr);
+
+ DRI2DestroyDrawable(screenshot->dpy, screenshot->pixmap);
+
+ /* dri2 */
+ if (screenshot->drm_fd)
+ close(screenshot->drm_fd);
+ if (screenshot->driver_name)
+ free(screenshot->driver_name);
+ if (screenshot->device_name)
+ free(screenshot->device_name);
+
+ /* xv */
+ if (screenshot->port > 0 && screenshot->pixmap > 0)
+ XvStopVideo(screenshot->dpy, screenshot->port, screenshot->pixmap);
+
+ /* damage */
+ if (screenshot->damage)
+ XDamageDestroy(screenshot->dpy, screenshot->damage);
+
+ /* gc */
+ if (screenshot->gc)
+ XFreeGC(screenshot->dpy, screenshot->gc);
+
+ /* pixmap */
+ if (screenshot->pixmap > 0)
+ XFreePixmap(screenshot->dpy, screenshot->pixmap);
+
+ /* port */
+ if (screenshot->port > 0)
+ XvUngrabPort(screenshot->dpy, screenshot->port, 0);
+
+ XSync(screenshot->dpy, False);
+
+ /* dpy */
+ if (screenshot->internal_display ==1 && screenshot->dpy)
+ XCloseDisplay(screenshot->dpy);
+
+ free(screenshot);
+ g_screenshot = NULL;
+
return EFL_UTIL_ERROR_NONE;
+#endif
+#if WAYLAND
+ if (!screenshot)
+ return EFL_UTIL_ERROR_NONE;
+
+ if (screenshot->bufmgr)
+ tbm_bufmgr_deinit(screenshot->bufmgr);
+
+ free(screenshot);
+ g_screenshot = NULL;
+
+ if (_eflutil.wl.shot.screenshooter)
+ screenshooter_set_user_data(_eflutil.wl.shot.screenshooter, NULL);
+
+ return EFL_UTIL_ERROR_NONE;
+#endif
+}
+
+
+API tbm_surface_h efl_util_screenshot_take_tbm_surface(efl_util_screenshot_h screenshot)
+{
+#if X11
+ XEvent ev = {0,};
+ XErrorHandler old_handler = NULL;
+ unsigned int attachment = DRI2BufferFrontLeft;
+ int nbufs = 0;
+ DRI2Buffer *bufs = NULL;
+ tbm_bo t_bo = NULL;
+ tbm_surface_h t_surface = NULL;
+ int buf_width = 0;
+ int buf_height = 0;
+ tbm_surface_info_s surf_info;
+ int i;
+
+ if (screenshot != g_screenshot)
+ {
+ set_last_result(EFL_UTIL_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ /* for flush other pending requests and pending events */
+ XSync(screenshot->dpy, 0);
+
+ g_efl_util_x_error_caught = False;
+ old_handler = XSetErrorHandler(_efl_util_screenshot_x_error_handle);
+
+ /* dump here */
+ XvPutStill(screenshot->dpy, screenshot->port, screenshot->pixmap, screenshot->gc,
+ 0, 0, screenshot->width, screenshot->height,
+ 0, 0, screenshot->width, screenshot->height);
+
+ XSync(screenshot->dpy, 0);
+
+ if (g_efl_util_x_error_caught)
+ {
+ g_efl_util_x_error_caught = False;
+ XSetErrorHandler(old_handler);
+ goto fail;
+ }
+
+ g_efl_util_x_error_caught = False;
+ XSetErrorHandler(old_handler);
+
+ if (XPending(screenshot->dpy))
+ XNextEvent(screenshot->dpy, &ev);
+ else
+ {
+ int fd = ConnectionNumber(screenshot->dpy);
+ fd_set mask;
+ struct timeval tv;
+ int ret;
+
+ FD_ZERO(&mask);
+ FD_SET(fd, &mask);
+
+ tv.tv_usec = 0;
+ tv.tv_sec = TIMEOUT_CAPTURE;
+
+ ret = select(fd + 1, &mask, 0, 0, &tv);
+ if (ret < 0)
+ fprintf(stderr, "[screenshot] fail: select.\n");
+ else if (ret == 0)
+ fprintf(stderr, "[screenshot] fail: timeout(%d sec)!\n", TIMEOUT_CAPTURE);
+ else if (XPending(screenshot->dpy))
+ XNextEvent(screenshot->dpy, &ev);
+ else
+ fprintf(stderr, "[screenshot] fail: not passed a event!\n");
+ }
+
+ /* check if the capture is done by xserver and pixmap has got the captured image */
+ if (ev.type == (screenshot->damage_base + XDamageNotify))
+ {
+ XDamageNotifyEvent *damage_ev = (XDamageNotifyEvent *)&ev;
+ if (damage_ev->drawable == screenshot->pixmap)
+ {
+ /* Get DRI2 FrontLeft buffer of the pixmap */
+ bufs = DRI2GetBuffers(screenshot->dpy, screenshot->pixmap, &buf_width, &buf_height, &attachment, 1, &nbufs);
+ if (!bufs)
+ {
+ fprintf(stderr, "[screenshot] fail: DRI2GetBuffers\n");
+ goto fail;
+ }
+
+ t_bo = tbm_bo_import(screenshot->bufmgr, bufs[0].name);
+ if (!t_bo)
+ {
+ fprintf(stderr, "[screenshot] fail: import tbm_bo!\n");
+ goto fail;
+ }
+
+ surf_info.width = buf_width;
+ surf_info.height = buf_height;
+ surf_info.format = TBM_FORMAT_XRGB8888;
+ surf_info.bpp = 32;
+ surf_info.size = bufs->pitch * surf_info.height;
+ surf_info.num_planes = 1;
+ for (i = 0; i < surf_info.num_planes; i++)
+ {
+ surf_info.planes[i].size = bufs->pitch * surf_info.height;
+ surf_info.planes[i].stride = bufs->pitch;
+ surf_info.planes[i].offset = 0;
+ }
+ t_surface = tbm_surface_internal_create_with_bos(&surf_info, &t_bo, 1);
+ if (!t_surface)
+ {
+ fprintf(stderr, "[screenshot] fail: get tbm_surface!\n");
+ goto fail;
+ }
+
+ tbm_bo_unref(t_bo);
+ free(bufs);
+
+ XDamageSubtract(screenshot->dpy, screenshot->damage, None, None );
+
+ set_last_result(EFL_UTIL_ERROR_NONE);
+
+ return t_surface;
+ }
+
+ XDamageSubtract(screenshot->dpy, screenshot->damage, None, None );
+ }
+
+fail:
+
+ if (t_bo)
+ tbm_bo_unref(t_bo);
+ if (bufs)
+ free(bufs);
+
+ set_last_result(EFL_UTIL_ERROR_SCREENSHOT_EXECUTION_FAIL);
+
+ return NULL;
+#endif
+
+#if WAYLAND
+ tbm_bo t_bo = NULL;
+ tbm_surface_h t_surface = NULL;
+ struct wl_buffer *buffer = NULL;
+ tbm_surface_info_s info;
+ Efl_Util_Wl_Output_Info *output;
+ int ret = 0;
+
+ if (screenshot != g_screenshot)
+ {
+ set_last_result(EFL_UTIL_ERROR_INVALID_PARAMETER);
+ return NULL;
+ }
+
+ output = eina_list_nth(_eflutil.wl.shot.output_list, 0);
+ if (!output)
+ {
+ fprintf(stderr, "[screenshot] fail: no output for screenshot\n");
+ goto fail;
+ }
+
+ t_surface = tbm_surface_create(screenshot->width, screenshot->height, TBM_FORMAT_XRGB8888);
+ if (!t_surface)
+ {
+ fprintf(stderr, "[screenshot] fail: tbm_surface_create\n");
+ goto fail;
+ }
+
+ t_bo = tbm_surface_internal_get_bo(t_surface, 0);
+ if (!t_bo)
+ {
+ fprintf(stderr, "[screenshot] fail: no tbm_bo for screenshot\n");
+ goto fail;
+ }
+
+ tbm_surface_get_info(t_surface, &info);
+
+ buffer =
+ tizen_buffer_pool_create_buffer(_eflutil.wl.shot.buffer_pool,
+ tbm_bo_export(t_bo),
+ info.width, info.height,
+ info.planes[0].stride,
+ TIZEN_BUFFER_POOL_FORMAT_XRGB8888);
+ if (!buffer)
+ {
+ fprintf(stderr, "[screenshot] fail: create wl_buffer for screenshot\n");
+ goto fail;
+ }
+
+ screenshooter_shoot(_eflutil.wl.shot.screenshooter, output->output, buffer);
+
+ screenshot->shot_done = EINA_FALSE;
+ while (!screenshot->shot_done && ret != -1)
+ ret = wl_display_dispatch(_eflutil.wl.dpy);
+
+ if (ret == -1)
+ {
+ fprintf(stderr, "[screenshot] fail: screenshooter_shoot\n");
+ goto fail;
+ }
+
+ wl_buffer_destroy(buffer);
+
+ return t_surface;
+
+fail:
+ if (t_surface)
+ tbm_surface_destroy(t_surface);
+ if (buffer);
+ wl_buffer_destroy(buffer);
+
+ set_last_result(EFL_UTIL_ERROR_SCREENSHOT_EXECUTION_FAIL);
+
+ return NULL;
+#endif
}
--- /dev/null
+#ifndef TIZEN_BUFFER_POOL_CLIENT_PROTOCOL_H
+#define TIZEN_BUFFER_POOL_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 tizen_buffer_pool;
+
+extern const struct wl_interface tizen_buffer_pool_interface;
+
+#ifndef TIZEN_BUFFER_POOL_ERROR_ENUM
+#define TIZEN_BUFFER_POOL_ERROR_ENUM
+enum tizen_buffer_pool_error {
+ TIZEN_BUFFER_POOL_ERROR_INVALID_FORMAT = 0,
+ TIZEN_BUFFER_POOL_ERROR_INVALID_NAME = 1,
+};
+#endif /* TIZEN_BUFFER_POOL_ERROR_ENUM */
+
+#ifndef TIZEN_BUFFER_POOL_CAPABILITY_ENUM
+#define TIZEN_BUFFER_POOL_CAPABILITY_ENUM
+enum tizen_buffer_pool_capability {
+ TIZEN_BUFFER_POOL_CAPABILITY_DEFAULT = 0,
+ TIZEN_BUFFER_POOL_CAPABILITY_VIDEO = 0x1,
+ TIZEN_BUFFER_POOL_CAPABILITY_SCREENMIRROR = 0x2,
+};
+#endif /* TIZEN_BUFFER_POOL_CAPABILITY_ENUM */
+
+#ifndef TIZEN_BUFFER_POOL_FORMAT_ENUM
+#define TIZEN_BUFFER_POOL_FORMAT_ENUM
+enum tizen_buffer_pool_format {
+ TIZEN_BUFFER_POOL_FORMAT_C8 = 0x20203843,
+ TIZEN_BUFFER_POOL_FORMAT_RGB332 = 0x38424752,
+ TIZEN_BUFFER_POOL_FORMAT_BGR233 = 0x38524742,
+ TIZEN_BUFFER_POOL_FORMAT_XRGB4444 = 0x32315258,
+ TIZEN_BUFFER_POOL_FORMAT_XBGR4444 = 0x32314258,
+ TIZEN_BUFFER_POOL_FORMAT_RGBX4444 = 0x32315852,
+ TIZEN_BUFFER_POOL_FORMAT_BGRX4444 = 0x32315842,
+ TIZEN_BUFFER_POOL_FORMAT_ARGB4444 = 0x32315241,
+ TIZEN_BUFFER_POOL_FORMAT_ABGR4444 = 0x32314241,
+ TIZEN_BUFFER_POOL_FORMAT_RGBA4444 = 0x32314152,
+ TIZEN_BUFFER_POOL_FORMAT_BGRA4444 = 0x32314142,
+ TIZEN_BUFFER_POOL_FORMAT_XRGB1555 = 0x35315258,
+ TIZEN_BUFFER_POOL_FORMAT_XBGR1555 = 0x35314258,
+ TIZEN_BUFFER_POOL_FORMAT_RGBX5551 = 0x35315852,
+ TIZEN_BUFFER_POOL_FORMAT_BGRX5551 = 0x35315842,
+ TIZEN_BUFFER_POOL_FORMAT_ARGB1555 = 0x35315241,
+ TIZEN_BUFFER_POOL_FORMAT_ABGR1555 = 0x35314241,
+ TIZEN_BUFFER_POOL_FORMAT_RGBA5551 = 0x35314152,
+ TIZEN_BUFFER_POOL_FORMAT_BGRA5551 = 0x35314142,
+ TIZEN_BUFFER_POOL_FORMAT_RGB565 = 0x36314752,
+ TIZEN_BUFFER_POOL_FORMAT_BGR565 = 0x36314742,
+ TIZEN_BUFFER_POOL_FORMAT_RGB888 = 0x34324752,
+ TIZEN_BUFFER_POOL_FORMAT_BGR888 = 0x34324742,
+ TIZEN_BUFFER_POOL_FORMAT_XRGB8888 = 0x34325258,
+ TIZEN_BUFFER_POOL_FORMAT_XBGR8888 = 0x34324258,
+ TIZEN_BUFFER_POOL_FORMAT_RGBX8888 = 0x34325852,
+ TIZEN_BUFFER_POOL_FORMAT_BGRX8888 = 0x34325842,
+ TIZEN_BUFFER_POOL_FORMAT_ARGB8888 = 0x34325241,
+ TIZEN_BUFFER_POOL_FORMAT_ABGR8888 = 0x34324241,
+ TIZEN_BUFFER_POOL_FORMAT_RGBA8888 = 0x34324152,
+ TIZEN_BUFFER_POOL_FORMAT_BGRA8888 = 0x34324142,
+ TIZEN_BUFFER_POOL_FORMAT_XRGB2101010 = 0x30335258,
+ TIZEN_BUFFER_POOL_FORMAT_XBGR2101010 = 0x30334258,
+ TIZEN_BUFFER_POOL_FORMAT_RGBX1010102 = 0x30335852,
+ TIZEN_BUFFER_POOL_FORMAT_BGRX1010102 = 0x30335842,
+ TIZEN_BUFFER_POOL_FORMAT_ARGB2101010 = 0x30335241,
+ TIZEN_BUFFER_POOL_FORMAT_ABGR2101010 = 0x30334241,
+ TIZEN_BUFFER_POOL_FORMAT_RGBA1010102 = 0x30334152,
+ TIZEN_BUFFER_POOL_FORMAT_BGRA1010102 = 0x30334142,
+ TIZEN_BUFFER_POOL_FORMAT_YUYV = 0x56595559,
+ TIZEN_BUFFER_POOL_FORMAT_YVYU = 0x55595659,
+ TIZEN_BUFFER_POOL_FORMAT_UYVY = 0x59565955,
+ TIZEN_BUFFER_POOL_FORMAT_VYUY = 0x59555956,
+ TIZEN_BUFFER_POOL_FORMAT_AYUV = 0x56555941,
+ TIZEN_BUFFER_POOL_FORMAT_NV12 = 0x3231564e,
+ TIZEN_BUFFER_POOL_FORMAT_NV21 = 0x3132564e,
+ TIZEN_BUFFER_POOL_FORMAT_NV16 = 0x3631564e,
+ TIZEN_BUFFER_POOL_FORMAT_NV61 = 0x3136564e,
+ TIZEN_BUFFER_POOL_FORMAT_YUV410 = 0x39565559,
+ TIZEN_BUFFER_POOL_FORMAT_YVU410 = 0x39555659,
+ TIZEN_BUFFER_POOL_FORMAT_YUV411 = 0x31315559,
+ TIZEN_BUFFER_POOL_FORMAT_YVU411 = 0x31315659,
+ TIZEN_BUFFER_POOL_FORMAT_YUV420 = 0x32315559,
+ TIZEN_BUFFER_POOL_FORMAT_YVU420 = 0x32315659,
+ TIZEN_BUFFER_POOL_FORMAT_YUV422 = 0x36315559,
+ TIZEN_BUFFER_POOL_FORMAT_YVU422 = 0x36315659,
+ TIZEN_BUFFER_POOL_FORMAT_YUV444 = 0x34325559,
+ TIZEN_BUFFER_POOL_FORMAT_YVU444 = 0x34325659,
+ TIZEN_BUFFER_POOL_FORMAT_ST12 = 0x32315453,
+ TIZEN_BUFFER_POOL_FORMAT_SN12 = 0x32314e53,
+};
+#endif /* TIZEN_BUFFER_POOL_FORMAT_ENUM */
+
+struct tizen_buffer_pool_listener {
+ /**
+ * device - (none)
+ * @name: (none)
+ */
+ void (*device)(void *data,
+ struct tizen_buffer_pool *tizen_buffer_pool,
+ const char *name);
+ /**
+ * authenticated - (none)
+ */
+ void (*authenticated)(void *data,
+ struct tizen_buffer_pool *tizen_buffer_pool);
+ /**
+ * capabilities - (none)
+ * @value: (none)
+ */
+ void (*capabilities)(void *data,
+ struct tizen_buffer_pool *tizen_buffer_pool,
+ uint32_t value);
+ /**
+ * format - (none)
+ * @format: (none)
+ */
+ void (*format)(void *data,
+ struct tizen_buffer_pool *tizen_buffer_pool,
+ uint32_t format);
+};
+
+static inline int
+tizen_buffer_pool_add_listener(struct tizen_buffer_pool *tizen_buffer_pool,
+ const struct tizen_buffer_pool_listener *listener, void *data)
+{
+ return wl_proxy_add_listener((struct wl_proxy *) tizen_buffer_pool,
+ (void (**)(void)) listener, data);
+}
+
+#define TIZEN_BUFFER_POOL_AUTHENTICATE 0
+#define TIZEN_BUFFER_POOL_CREATE_BUFFER 1
+#define TIZEN_BUFFER_POOL_CREATE_PLANAR_BUFFER 2
+
+static inline void
+tizen_buffer_pool_set_user_data(struct tizen_buffer_pool *tizen_buffer_pool, void *user_data)
+{
+ wl_proxy_set_user_data((struct wl_proxy *) tizen_buffer_pool, user_data);
+}
+
+static inline void *
+tizen_buffer_pool_get_user_data(struct tizen_buffer_pool *tizen_buffer_pool)
+{
+ return wl_proxy_get_user_data((struct wl_proxy *) tizen_buffer_pool);
+}
+
+static inline void
+tizen_buffer_pool_destroy(struct tizen_buffer_pool *tizen_buffer_pool)
+{
+ wl_proxy_destroy((struct wl_proxy *) tizen_buffer_pool);
+}
+
+static inline void
+tizen_buffer_pool_authenticate(struct tizen_buffer_pool *tizen_buffer_pool, uint32_t id)
+{
+ wl_proxy_marshal((struct wl_proxy *) tizen_buffer_pool,
+ TIZEN_BUFFER_POOL_AUTHENTICATE, id);
+}
+
+static inline struct wl_buffer *
+tizen_buffer_pool_create_buffer(struct tizen_buffer_pool *tizen_buffer_pool, uint32_t name, int32_t width, int32_t height, uint32_t stride, uint32_t format)
+{
+ struct wl_proxy *id;
+
+ id = wl_proxy_marshal_constructor((struct wl_proxy *) tizen_buffer_pool,
+ TIZEN_BUFFER_POOL_CREATE_BUFFER, &wl_buffer_interface, NULL, name, width, height, stride, format);
+
+ return (struct wl_buffer *) id;
+}
+
+static inline struct wl_buffer *
+tizen_buffer_pool_create_planar_buffer(struct tizen_buffer_pool *tizen_buffer_pool, int32_t width, int32_t height, uint32_t format, uint32_t name0, int32_t offset0, int32_t stride0, uint32_t name1, int32_t offset1, int32_t stride1, uint32_t name2, int32_t offset2, int32_t stride2)
+{
+ struct wl_proxy *id;
+
+ id = wl_proxy_marshal_constructor((struct wl_proxy *) tizen_buffer_pool,
+ TIZEN_BUFFER_POOL_CREATE_PLANAR_BUFFER, &wl_buffer_interface, NULL, width, height, format, name0, offset0, stride0, name1, offset1, stride1, name2, offset2, stride2);
+
+ return (struct wl_buffer *) id;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif