summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjk7744.park <jk7744.park@samsung.com>2015-10-24 06:49:19 (GMT)
committerjk7744.park <jk7744.park@samsung.com>2015-10-24 06:49:19 (GMT)
commit89677f7b7136e7ce0df7135906d96a1af78937db (patch)
tree8b8adea9ab6f774ef2293d08e84f4c7206c00fb8
parente96a502e00afe2b6a5c5e72c6c14f96b835baa2f (diff)
downloadwidget-provider-accepted/tizen_2.4_mobile.zip
widget-provider-accepted/tizen_2.4_mobile.tar.gz
widget-provider-accepted/tizen_2.4_mobile.tar.bz2
-rw-r--r--widget_provider/include/widget_provider.h30
-rw-r--r--widget_provider/include/widget_provider_buffer.h10
-rw-r--r--[-rwxr-xr-x]widget_provider/include_internal/event.h0
-rw-r--r--[-rwxr-xr-x]widget_provider/include_internal/fb.h3
-rw-r--r--[-rwxr-xr-x]widget_provider/include_internal/provider_buffer_internal.h0
-rw-r--r--widget_provider/include_internal/util.h1
-rw-r--r--widget_provider/src/fb.c207
-rw-r--r--widget_provider/src/fb_wayland.c92
-rw-r--r--widget_provider/src/util.c13
-rw-r--r--widget_provider/src/widget_provider.c25
-rw-r--r--widget_provider/src/widget_provider_buffer.c62
-rw-r--r--widget_provider_app/include/util.h1
-rw-r--r--widget_provider_app/include/widget_provider_app.h11
-rw-r--r--widget_provider_app/include/widget_provider_app_internal.h2
-rw-r--r--widget_provider_app/src/client.c60
-rw-r--r--widget_provider_app/src/util.c14
16 files changed, 368 insertions, 163 deletions
diff --git a/widget_provider/include/widget_provider.h b/widget_provider/include/widget_provider.h
index 3e088f0..94fec5a 100644
--- a/widget_provider/include/widget_provider.h
+++ b/widget_provider/include/widget_provider.h
@@ -86,7 +86,8 @@ struct widget_event_arg {
WIDGET_EVENT_VIEWER_CONNECTED, /**< A new viewer is connected */
WIDGET_EVENT_VIEWER_DISCONNECTED, /**< The viewer is disconnected */
- WIDGET_EVENT_ORIENTATION /**< Orientation is changed */
+ WIDGET_EVENT_ORIENTATION, /**< Orientation is changed */
+ WIDGET_EVENT_CTRL_MODE /**< Control provider */
} type;
const char *pkgname; /**< Package name of a widget */
const char *id; /**< Instance Id of a widget */
@@ -228,6 +229,11 @@ struct widget_event_arg {
struct _orientation {
int degree; /**< Changed orientation */
} orientation;
+
+ struct _ctrl_mode {
+ int cmd;
+ int value;
+ } ctrl_mode;
} info;
};
@@ -295,6 +301,8 @@ typedef struct widget_event_table {
int (*viewer_connected)(struct widget_event_arg *arg, void *data); /**< New viewer is connected */
int (*viewer_disconnected)(struct widget_event_arg *arg, void *data); /**< The viewer is disconnected */
+
+ int (*ctrl_mode)(struct widget_event_arg *arg, void *data); /* Change the mode of provider */
} *widget_event_table_h;
/**
@@ -326,7 +334,7 @@ typedef struct widget_damage_region {
* @privilege %http://tizen.org/privilege/widget.provider
* @return 0 on success, otherwise a negative error value
* @retval #WIDGET_ERROR_NONE Successfully initialized
- * @retval #WIDGET_ERROR_INVALID_PARAMETER_PARAMETER Invalid arguments
+ * @retval #WIDGET_ERROR_INVALID_PARAMETER Invalid arguments
* @retval #WIDGET_ERROR_OUT_OF_MEMORY Out of memory
* @retval #WIDGET_ERROR_ALREADY_STARTED Already initialized
* @retval #WIDGET_ERROR_FAULT Failed to initialize
@@ -357,7 +365,7 @@ extern void *widget_provider_fini(void);
* @privilege %http://tizen.org/privilege/widget.provider
* @return 0 on success, otherwise a negative error value
* @retval #WIDGET_ERROR_NONE Successfully sent
- * @retval #WIDGET_ERROR_INVALID_PARAMETER_PARAMETER Invalid arguments
+ * @retval #WIDGET_ERROR_INVALID_PARAMETER Invalid arguments
* @retval #WIDGET_ERROR_FAULT Failed to initialize
*/
extern int widget_provider_send_hello(void);
@@ -373,9 +381,9 @@ extern int widget_provider_send_hello(void);
* @privlevel public
* @privilege %http://tizen.org/privilege/widget.provider
* @return 0 on success, otherwise a negative error value
- * @retval #WIDGET_STATUS_ERROR_NONE Successfully sent
- * @retval #WIDGET_STATUS_ERROR_INVALID_PARAMETER_PARAMETER Invalid arguments
- * @retval #WIDGET_STATUS_ERROR_FAULT Failed to initialize
+ * @retval #WIDGET_ERROR_NONE Successfully sent
+ * @retval #WIDGET_ERROR_INVALID_PARAMETER Invalid arguments
+ * @retval #WIDGET_ERROR_FAULT Failed to initialize
*/
extern int widget_provider_send_hello_sync(const char *pkgname);
@@ -389,7 +397,7 @@ extern int widget_provider_send_hello_sync(const char *pkgname);
* @privilege %http://tizen.org/privilege/widget.provider
* @return 0 on success, otherwise a negative error value
* @retval #WIDGET_ERROR_NONE Successfully sent
- * @retval #WIDGET_ERROR_INVALID_PARAMETER_PARAMETER provider is not initialized
+ * @retval #WIDGET_ERROR_INVALID_PARAMETER provider is not initialized
* @retval #WIDGET_ERROR_FAULT Failed to send ping message
*/
extern int widget_provider_send_ping(void);
@@ -414,7 +422,7 @@ extern int widget_provider_send_ping(void);
* @privilege %http://tizen.org/privilege/widget.provider
* @return 0 on success, otherwise a negative error value
* @retval #WIDGET_ERROR_NONE Successfully sent update event
- * @retval #WIDGET_ERROR_INVALID_PARAMETER_PARAMETER Invalid arguments
+ * @retval #WIDGET_ERROR_INVALID_PARAMETER Invalid arguments
* @retval #WIDGET_ERROR_FAULT There is error and it could not be recoverable
* @see widget_provider_send_direct_updated()
*/
@@ -457,7 +465,7 @@ extern int widget_provider_send_direct_updated(int fd, const char *pkgname, cons
* @privilege %http://tizen.org/privilege/widget.provider
* @return 0 on success, otherwise a negative error value
* @retval #WIDGET_ERROR_NONE Successfully sent update event
- * @retval #WIDGET_ERROR_INVALID_PARAMETER_PARAMETER Invalid arguments
+ * @retval #WIDGET_ERROR_INVALID_PARAMETER Invalid arguments
* @retval #WIDGET_ERROR_FAULT There is error and it could not be recoverable
*/
extern int widget_provider_send_extra_info(const char *pkgname, const char *id, double priority, const char *content_info, const char *title, const char *icon, const char *name);
@@ -475,7 +483,7 @@ extern int widget_provider_send_extra_info(const char *pkgname, const char *id,
* @privilege %http://tizen.org/privilege/widget.provider
* @return 0 on success, otherwise a negative error value
* @retval #WIDGET_ERROR_NONE
- * @retval #WIDGET_ERROR_INVALID_PARAMETER_PARAMETER
+ * @retval #WIDGET_ERROR_INVALID_PARAMETER
* @retval #WIDGET_ERROR_FAULT
* @see widget_provider_send_widget_update_end()
*/
@@ -491,7 +499,7 @@ extern int widget_provider_send_widget_update_begin(const char *pkgname, const c
* @privilege %http://tizen.org/privilege/widget.provider
* @return 0 on success, otherwise a negative error value
* @retval #WIDGET_ERROR_NONE
- * @retval #WIDGET_ERROR_INVALID_PARAMETER_PARAMETER
+ * @retval #WIDGET_ERROR_INVALID_PARAMETER
* @retval #WIDGET_ERROR_FAULT
* @see widget_provider_send_widget_update_begin()
*/
diff --git a/widget_provider/include/widget_provider_buffer.h b/widget_provider/include/widget_provider_buffer.h
index db00e9c..ad3a986 100644
--- a/widget_provider/include/widget_provider_buffer.h
+++ b/widget_provider/include/widget_provider_buffer.h
@@ -518,6 +518,16 @@ extern int widget_provider_buffer_frame_skip(widget_buffer_h info);
extern int widget_provider_buffer_clear_frame_skip(widget_buffer_h info);
/**
+ * @brief Dump the buffer to a file
+ * @details Used for debugging renderer.
+ * @param[in] info Buffer handle
+ * @param[in] file Output file
+ * @privlevel platform
+ * @privilege %http://developer.samsung.com/privilege/core/widget.provider
+ * @return address on success, otherwise @c NULL for error
+ */
+extern void *widget_provider_buffer_dump_frame(widget_buffer_h info, int idx);
+/**
* @}
*/
diff --git a/widget_provider/include_internal/event.h b/widget_provider/include_internal/event.h
index 34a4add..34a4add 100755..100644
--- a/widget_provider/include_internal/event.h
+++ b/widget_provider/include_internal/event.h
diff --git a/widget_provider/include_internal/fb.h b/widget_provider/include_internal/fb.h
index af4ee74..0821e80 100755..100644
--- a/widget_provider/include_internal/fb.h
+++ b/widget_provider/include_internal/fb.h
@@ -38,8 +38,11 @@ extern int fb_destroy_gem(struct fb_info *info);
extern void *fb_acquire_gem(struct fb_info *info);
extern int fb_release_gem(struct fb_info *info);
extern int fb_has_gem(struct fb_info *info);
+extern int fb_support_gem(struct fb_info *info);
extern int fb_sync_xdamage(struct fb_info *info, widget_damage_region_s *region);
extern int fb_stride(struct fb_info *info);
extern void fb_master_disconnected(void);
+
+extern void *fb_dump_frame(unsigned int pixmap, int w, int h, int depth);
/* End of a file */
diff --git a/widget_provider/include_internal/provider_buffer_internal.h b/widget_provider/include_internal/provider_buffer_internal.h
index deb7057..deb7057 100755..100644
--- a/widget_provider/include_internal/provider_buffer_internal.h
+++ b/widget_provider/include_internal/provider_buffer_internal.h
diff --git a/widget_provider/include_internal/util.h b/widget_provider/include_internal/util.h
index d3e8350..2d5a6bf 100644
--- a/widget_provider/include_internal/util.h
+++ b/widget_provider/include_internal/util.h
@@ -15,7 +15,6 @@
*/
extern double util_timestamp(void);
-extern const char *util_basename(const char *name);
#define SCHEMA_FILE "file://"
#define SCHEMA_PIXMAP "pixmap://"
diff --git a/widget_provider/src/fb.c b/widget_provider/src/fb.c
index a5917ba..d299948 100644
--- a/widget_provider/src/fb.c
+++ b/widget_provider/src/fb.c
@@ -79,7 +79,6 @@ struct gem_data {
static struct info {
tbm_bufmgr bufmgr;
int fd;
- struct dlist *gem_list;
struct dlist *shm_list;
Display *disp;
@@ -91,7 +90,6 @@ static struct info {
} s_info = {
.bufmgr = NULL,
.fd = -1,
- .gem_list = NULL,
.shm_list = NULL,
.disp = NULL,
@@ -274,22 +272,6 @@ int fb_sync(struct fb_info *info)
return WIDGET_ERROR_INVALID_PARAMETER;
}
-static inline struct fb_info *find_shm_by_pixmap(Pixmap id)
-{
- struct fb_info *info;
- struct dlist *l;
-
- info = NULL;
- dlist_foreach(s_info.shm_list, l, info) {
- if (info->handle == (int)id) {
- break;
- }
- info = NULL;
- }
-
- return info;
-}
-
static inline struct fb_info *find_shm_by_canvas(void *canvas)
{
struct pixmap_info *pixmap_info;
@@ -316,49 +298,9 @@ static inline struct fb_info *find_shm_by_canvas(void *canvas)
return info;
}
-static inline struct gem_data *find_gem_by_pixmap(Pixmap id)
-{
- struct gem_data *gem;
- struct dlist *l;
-
- gem = NULL;
- dlist_foreach(s_info.gem_list, l, gem) {
- if (gem->pixmap == id) {
- break;
- }
-
- gem = NULL;
- }
-
- return gem;
-}
-
-static inline struct gem_data *find_gem_by_canvas(void *canvas)
+static inline __attribute__((always_inline)) int create_pixmap_info(unsigned int pixmap, struct pixmap_info *pixmap_info, int bufsz, int w, int h, int pixels)
{
- struct gem_data *gem;
- struct dlist *l;
-
- gem = NULL;
- dlist_foreach(s_info.gem_list, l, gem) {
- if (gem->data == canvas || gem->compensate_data == canvas) {
- break;
- }
-
- gem = NULL;
- }
-
- return gem;
-}
-
-static inline int create_pixmap_info(struct fb_info *info)
-{
- struct pixmap_info *pixmap_info;
- widget_fb_t buffer;
-
- buffer = info->buffer;
- pixmap_info = (struct pixmap_info *)buffer->data;
-
- pixmap_info->si.shmid = shmget(IPC_PRIVATE, info->bufsz, IPC_CREAT | 0666);
+ pixmap_info->si.shmid = shmget(IPC_PRIVATE, bufsz, IPC_CREAT | 0666);
if (pixmap_info->si.shmid < 0) {
ErrPrint("shmget: %d\n", errno);
return WIDGET_ERROR_FAULT;
@@ -378,7 +320,7 @@ static inline int create_pixmap_info(struct fb_info *info)
* \NOTE
* XCreatePixmap can only uses 24 bits depth only.
*/
- pixmap_info->xim = XShmCreateImage(s_info.disp, s_info.visual, (info->pixels << 3), ZPixmap, NULL, &pixmap_info->si, info->w, info->h);
+ pixmap_info->xim = XShmCreateImage(s_info.disp, s_info.visual, (pixels << 3), ZPixmap, NULL, &pixmap_info->si, w, h);
if (pixmap_info->xim == NULL) {
if (shmdt(pixmap_info->si.shmaddr) < 0) {
ErrPrint("shmdt: %d\n", errno);
@@ -395,7 +337,7 @@ static inline int create_pixmap_info(struct fb_info *info)
XShmAttach(s_info.disp, &pixmap_info->si);
XSync(s_info.disp, False);
- pixmap_info->gc = XCreateGC(s_info.disp, (Pixmap)info->handle, 0, NULL);
+ pixmap_info->gc = XCreateGC(s_info.disp, (Pixmap)pixmap, 0, NULL);
if (!pixmap_info->gc) {
XShmDetach(s_info.disp, &pixmap_info->si);
XDestroyImage(pixmap_info->xim);
@@ -411,19 +353,12 @@ static inline int create_pixmap_info(struct fb_info *info)
return WIDGET_ERROR_FAULT;
}
- s_info.shm_list = dlist_append(s_info.shm_list, info);
- DbgPrint("SHMID: %d (Size: %d), %p\n", pixmap_info->si.shmid, info->bufsz, pixmap_info->si.shmaddr);
+ DbgPrint("SHMID: %d (Size: %d), %p\n", pixmap_info->si.shmid, bufsz, pixmap_info->si.shmaddr);
return WIDGET_ERROR_NONE;
}
-static inline int destroy_pixmap_info(struct fb_info *info)
+static inline int destroy_pixmap_info(struct pixmap_info *pixmap_info)
{
- struct pixmap_info *pixmap_info;
- widget_fb_t buffer;
-
- buffer = info->buffer;
- pixmap_info = (struct pixmap_info *)buffer->data;
-
XFreeGC(s_info.disp, pixmap_info->gc);
XShmDetach(s_info.disp, &pixmap_info->si);
XDestroyImage(pixmap_info->xim);
@@ -436,7 +371,6 @@ static inline int destroy_pixmap_info(struct fb_info *info)
ErrPrint("shmctl: %d\n", errno);
}
- dlist_remove_data(s_info.shm_list, info);
DbgPrint("Destroy a pixmap info\n");
return WIDGET_ERROR_NONE;
}
@@ -490,7 +424,13 @@ static inline struct gem_data *create_gem(Pixmap pixmap, int w, int h, int depth
return NULL;
}
- if (auto_align && gem->dri2_buffer->pitch != gem->w * gem->depth) {
+ /**
+ * @note
+ * If the "auto_align" is turned on, forcely allocate compensate buffer,
+ * Even if the (pitch == w * depth).
+ * "auto_align" will work like "enabling cache layer"
+ */
+ if (auto_align || gem->dri2_buffer->pitch != gem->w * gem->depth) {
gem->compensate_data = calloc(1, gem->w * gem->h * gem->depth);
if (!gem->compensate_data) {
ErrPrint("Failed to allocate heap\n");
@@ -501,19 +441,15 @@ static inline struct gem_data *create_gem(Pixmap pixmap, int w, int h, int depth
}
}
- s_info.gem_list = dlist_append(s_info.gem_list, gem);
-
- DbgPrint("dri2_buffer: %p, name: %p, %dx%d (%dx%d), pitch: %d, buf_count: %d, gem: %p\n",
+ DbgPrint("dri2_buffer: %p, name: %p, %dx%d (%dx%d), pitch: %d, buf_count: %d, gem: %p, comp: %p\n",
gem->dri2_buffer, gem->dri2_buffer->name,
gem->w, gem->h, w, h,
- gem->dri2_buffer->pitch, gem->buf_count, gem);
+ gem->dri2_buffer->pitch, gem->buf_count, gem, gem->compensate_data);
return gem;
}
static inline int destroy_gem(struct gem_data *gem)
{
- dlist_remove_data(s_info.gem_list, gem);
-
if (gem->compensate_data) {
DbgPrint("Release compensate buffer %p\n", gem->compensate_data);
free(gem->compensate_data);
@@ -538,7 +474,17 @@ static inline void *acquire_gem(struct gem_data *gem)
{
if (!gem->data) {
tbm_bo_handle handle;
- handle = tbm_bo_map(gem->pixmap_bo, TBM_DEVICE_CPU, TBM_OPTION_READ | TBM_OPTION_WRITE);
+ if (gem->compensate_data) {
+ /**
+ * @note
+ * Do not grab a lock in case of using compensate buffer.
+ * We just need to grab a lock only if the compensate buffer is not
+ * used. (directly access the gem buffer)
+ */
+ handle = tbm_bo_get_handle(gem->pixmap_bo, TBM_DEVICE_CPU);
+ } else {
+ handle = tbm_bo_map(gem->pixmap_bo, TBM_DEVICE_CPU, TBM_OPTION_READ | TBM_OPTION_WRITE);
+ }
gem->data = handle.ptr;
if (!gem->data) {
ErrPrint("Failed to get BO\n");
@@ -553,9 +499,12 @@ static inline void release_gem(struct gem_data *gem)
{
gem->refcnt--;
if (gem->refcnt == 0) {
+ /**
+ * @note
+ * If the gem->compensate_data is available,
+ * it means, acquire_gem didn't grab a lock.
+ */
if (gem->compensate_data && gem->data) {
- register int x;
- register int y;
int *gem_pixel;
int *pixel;
int gap;
@@ -564,12 +513,28 @@ static inline void release_gem(struct gem_data *gem)
gem_pixel = gem->data;
gap = gem->dri2_buffer->pitch - (gem->w * gem->depth);
- for (y = 0; y < gem->h; y++) {
- for (x = 0; x < gem->w; x++) {
- *gem_pixel++ = *pixel++;
+ /**
+ * @note
+ * write before copy the pixels, we should grab a lock
+ */
+ tbm_bo_map(gem->pixmap_bo, TBM_DEVICE_CPU, TBM_OPTION_READ | TBM_OPTION_WRITE);
+ if (gap == 0) {
+ /**
+ * @note
+ * I believe that the "memcpy" is faster than my code...
+ */
+ memcpy(gem_pixel, pixel, gem->dri2_buffer->pitch * gem->h);
+ } else {
+ register int x;
+ register int y;
+
+ for (y = 0; y < gem->h; y++) {
+ for (x = 0; x < gem->w; x++) {
+ *gem_pixel++ = *pixel++;
+ }
+
+ gem_pixel = (int *)(((char *)gem_pixel) + gap);
}
-
- gem_pixel = (int *)(((char *)gem_pixel) + gap);
}
}
tbm_bo_unmap(gem->pixmap_bo);
@@ -580,6 +545,60 @@ static inline void release_gem(struct gem_data *gem)
}
}
+void *fb_dump_frame(unsigned int pixmap, int w, int h, int depth)
+{
+ void *canvas;
+ void *buffer = NULL;
+
+ if (s_info.fd >= 0) {
+ struct gem_data *gem;
+
+ gem = create_gem(pixmap, w, h, depth, 1);
+ if (!gem) {
+ ErrPrint("Failed to create a gem\n");
+ return NULL;
+ }
+
+ canvas = acquire_gem(gem);
+ if (canvas) {
+ buffer = malloc(w * h * depth);
+ if (buffer) {
+ memcpy(buffer, canvas, w * h * depth);
+ } else {
+ ErrPrint("malloc: %d\n", errno);
+ }
+ release_gem(gem);
+ }
+
+ (void)destroy_gem(gem);
+ } else {
+ DbgPrint("Fallback to S/W Backend\n");
+ struct pixmap_info *info;
+
+ info = malloc(sizeof(*info));
+ if (info) {
+ if (create_pixmap_info(pixmap, info, w * h * depth, w, h, depth) == WIDGET_ERROR_NONE) {
+ canvas = info->si.shmaddr;
+ if (canvas) {
+ buffer = malloc(w * h * depth);
+ if (buffer) {
+ memcpy(buffer, canvas, w * h * depth);
+ } else {
+ ErrPrint("malloc: %d\n", errno);
+ }
+ } else {
+ ErrPrint("SHM not available (%u)\n", pixmap);
+ }
+ destroy_pixmap_info(info);
+ }
+ free(info);
+ } else {
+ ErrPrint("malloc: %d\n", errno);
+ }
+ }
+ return buffer;
+}
+
struct fb_info *fb_create(const char *id, int w, int h)
{
struct fb_info *info;
@@ -623,9 +642,14 @@ struct fb_info *fb_create(const char *id, int w, int h)
return info;
}
+int fb_support_gem(struct fb_info *info)
+{
+ return !strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)) && (s_info.fd >= 0);
+}
+
int fb_has_gem(struct fb_info *info)
{
- return !strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)) && (s_info.fd >= 0 || info->gem);
+ return !strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)) && info->gem;
}
int fb_create_gem(struct fb_info *info, int auto_align)
@@ -744,12 +768,14 @@ void *fb_acquire_buffer(struct fb_info *info)
info->buffer = buffer;
DbgPrint("Create PIXMAP Info\n");
- if (create_pixmap_info(info) < 0) {
+ if (create_pixmap_info(info->handle, (struct pixmap_info *)buffer->data, info->bufsz, info->w, info->h, info->pixels) != WIDGET_ERROR_NONE) {
free(buffer);
info->buffer = NULL;
info->bufsz = 0;
return NULL;
}
+
+ s_info.shm_list = dlist_append(s_info.shm_list, info);
} else if (!strncasecmp(info->id, SCHEMA_FILE, strlen(SCHEMA_FILE))) {
info->bufsz = info->w * info->h * info->pixels;
buffer = calloc(1, sizeof(*buffer) + info->bufsz);
@@ -835,10 +861,11 @@ int fb_release_buffer(void *data)
buffer->refcnt--;
if (buffer->refcnt == 0) {
if (info) {
- destroy_pixmap_info(info);
if (info->buffer == buffer) {
info->buffer = NULL;
}
+ dlist_remove_data(s_info.shm_list, info);
+ destroy_pixmap_info((struct pixmap_info *)buffer->data);
}
buffer->state = WIDGET_FB_STATE_DESTROYED;
free(buffer);
diff --git a/widget_provider/src/fb_wayland.c b/widget_provider/src/fb_wayland.c
index 1f9316b..02fb7cb 100644
--- a/widget_provider/src/fb_wayland.c
+++ b/widget_provider/src/fb_wayland.c
@@ -282,7 +282,12 @@ struct fb_info *fb_create(const char *id, int w, int h)
int fb_has_gem(struct fb_info *info)
{
- return !strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)) && (s_info.fd >= 0 || info->gem);
+ return !strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)) && info->gem;
+}
+
+int fb_support_gem(struct fb_info *info)
+{
+ return !strncasecmp(info->id, SCHEMA_PIXMAP, strlen(SCHEMA_PIXMAP)) && (s_info.fd >= 0);
}
static inline struct gem_data *create_gem(unsigned int pixmap, int w, int h, int depth, int auto_align)
@@ -339,6 +344,60 @@ static inline int destroy_gem(struct gem_data *gem)
return WIDGET_ERROR_NONE;
}
+static inline void *acquire_gem(struct gem_data *gem)
+{
+ if (!gem->data) {
+ tbm_bo_handle handle;
+ handle = tbm_bo_map(gem->pixmap_bo, TBM_DEVICE_CPU, TBM_OPTION_READ | TBM_OPTION_WRITE);
+ gem->data = handle.ptr;
+ if (!gem->data) {
+ ErrPrint("Failed to get BO\n");
+ }
+ }
+
+ gem->refcnt++;
+ return gem->data;
+}
+
+static inline void release_gem(struct gem_data *gem)
+{
+ gem->refcnt--;
+ if (gem->refcnt == 0) {
+ tbm_bo_unmap(gem->pixmap_bo);
+ gem->data = NULL;
+ } else if (gem->refcnt < 0) {
+ ErrPrint("Invalid refcnt: %d (reset)\n", gem->refcnt);
+ gem->refcnt = 0;
+ }
+}
+
+void *fb_dump_frame(unsigned int pixmap, int w, int h, int depth)
+{
+ struct gem_data *gem;
+ void *canvas;
+ void *buffer = NULL;
+
+ gem = create_gem(pixmap, w, h, depth, 1);
+ if (!gem) {
+ ErrPrint("Failed to create a gem\n");
+ return NULL;
+ }
+
+ canvas = acquire_gem(gem);
+ if (canvas) {
+ buffer = malloc(w * h * depth);
+ if (buffer) {
+ memcpy(buffer, canvas, w * h * depth);
+ } else {
+ ErrPrint("malloc: %d\n", errno);
+ }
+ release_gem(gem);
+ }
+
+ (void)destroy_gem(gem);
+ return buffer;
+}
+
int fb_create_gem(struct fb_info *info, int auto_align)
{
if (info->gem) {
@@ -364,43 +423,22 @@ int fb_destroy_gem(struct fb_info *info)
void *fb_acquire_gem(struct fb_info *info)
{
- struct gem_data *gem;
-
if (!info->gem) {
ErrPrint("Invalid FB info\n");
return NULL;
}
- gem = info->gem;
-
- if (!gem->data) {
- tbm_bo_handle handle;
- handle = tbm_bo_map(gem->pixmap_bo, TBM_DEVICE_CPU, TBM_OPTION_READ | TBM_OPTION_WRITE);
- gem->data = handle.ptr;
- if (!gem->data) {
- ErrPrint("Failed to get BO\n");
- }
- }
-
- gem->refcnt++;
- return gem->data;
+ return acquire_gem(info->gem);
}
int fb_release_gem(struct fb_info *info)
{
- struct gem_data *gem;
-
- gem = info->gem;
-
- gem->refcnt--;
- if (gem->refcnt == 0) {
- tbm_bo_unmap(gem->pixmap_bo);
- gem->data = NULL;
- } else if (gem->refcnt < 0) {
- ErrPrint("Invalid refcnt: %d (reset)\n", gem->refcnt);
- gem->refcnt = 0;
+ if (!info->gem) {
+ ErrPrint("Invalid FB info\n");
+ return WIDGET_ERROR_INVALID_PARAMETER;
}
+ release_gem(info->gem);
return WIDGET_ERROR_NONE;
}
diff --git a/widget_provider/src/util.c b/widget_provider/src/util.c
index 3df7c7e..2eb91a0 100644
--- a/widget_provider/src/util.c
+++ b/widget_provider/src/util.c
@@ -74,17 +74,4 @@ double util_timestamp(void)
#endif
}
-const char *util_basename(const char *name)
-{
- int length;
- length = name ? strlen(name) : 0;
- if (!length) {
- return ".";
- }
-
- while (--length > 0 && name[length] != '/');
-
- return length <= 0 ? name : name + length + (name[length] == '/');
-}
-
/* End of a file */
diff --git a/widget_provider/src/widget_provider.c b/widget_provider/src/widget_provider.c
index d5cdb2b..7c1bf3f 100644
--- a/widget_provider/src/widget_provider.c
+++ b/widget_provider/src/widget_provider.c
@@ -851,6 +851,27 @@ errout:
return NULL;
}
+struct packet *master_ctrl_mode(pid_t pid, int handle, const struct packet *packet)
+{
+ int ret;
+ struct widget_event_arg arg;
+
+ ret = packet_get(packet, "ssii", &arg.pkgname, &arg.id, &arg.info.ctrl_mode.cmd, &arg.info.ctrl_mode.value);
+ if (ret != 4) {
+ ErrPrint("Invalid packet\n");
+ goto errout;
+ }
+
+ arg.type = WIDGET_EVENT_CTRL_MODE;
+
+ if (s_info.table.ctrl_mode) {
+ (void)s_info.table.ctrl_mode(&arg, s_info.data);
+ }
+
+errout:
+ return NULL;
+}
+
struct packet *master_gbar_move(pid_t pid, int handle, const struct packet *packet)
{
struct widget_event_arg arg;
@@ -1187,6 +1208,10 @@ static struct method s_table[] = {
.handler = master_viewer_disconnected,
},
{
+ .cmd = CMD_STR_CTRL_MODE,
+ .handler = master_ctrl_mode,
+ },
+ {
.cmd = NULL,
.handler = NULL,
},
diff --git a/widget_provider/src/widget_provider_buffer.c b/widget_provider/src/widget_provider_buffer.c
index a8cc6c3..6c0cc03 100644
--- a/widget_provider/src/widget_provider_buffer.c
+++ b/widget_provider/src/widget_provider_buffer.c
@@ -1537,7 +1537,7 @@ struct packet *provider_buffer_gbar_mouse_on_scroll(pid_t pid, int handle, const
.type = WIDGET_BUFFER_EVENT_ON_SCROLL,
};
- if (packet_get(packet, "ssdiiii", &pkgname, &id, &data.timestamp, &data.info.pointer.x, &data.info.pointer.y, (int *)&data.info.pointer.source, &ratio_w, &ratio_h, &data.info.pointer.device) != 9) {
+ if (packet_get(packet, "ssdiiiddi", &pkgname, &id, &data.timestamp, &data.info.pointer.x, &data.info.pointer.y, (int *)&data.info.pointer.source, &ratio_w, &ratio_h, &data.info.pointer.device) != 9) {
ErrPrint("Invalid packet\n");
goto out;
}
@@ -2190,7 +2190,7 @@ EAPI int widget_provider_buffer_release(widget_buffer_h info)
return WIDGET_ERROR_INVALID_PARAMETER;
}
- widget_service_destroy_lock(info->lock_info);
+ widget_service_destroy_lock(info->lock_info, 0);
info->lock_info = NULL;
ret = send_release_request(info->type, info->pkgname, info->id);
@@ -2356,6 +2356,60 @@ EAPI unsigned int widget_provider_buffer_resource_id(widget_buffer_h info)
return pixmap;
}
+/**
+ * @note
+ * This API only used for PIXMAP.
+ * Because the address of canvas can be get by Evas layer easily except PIXMAP based one.
+ * So if a developer wants get the address of canvas which is created by pixmap,
+ * This API will help the developer to get the address of pixmap.
+ *
+ * If there is already created gem buffer, this will copy its contents
+ * or will try to create gem buffer if possible.
+ * If the system doesn't support GEM buffer, this will try to get buffer
+ * using XShm API.
+ */
+EAPI void *widget_provider_buffer_dump_frame(widget_buffer_h info, int idx)
+{
+ unsigned int pixmap;
+ void *buffer = NULL;
+
+ if (!info) {
+ return NULL;
+ }
+
+ if (idx == WIDGET_PRIMARY_BUFFER) {
+ if (fb_has_gem(info->fb)) {
+ void *addr;
+
+ addr = fb_acquire_gem(info->fb);
+ if (addr) {
+ buffer = malloc(info->width * info->height * info->pixel_size);
+ if (buffer) {
+ memcpy(buffer, addr, info->width * info->height * info->pixel_size);
+ }
+ fb_release_gem(info->fb);
+ }
+ } else {
+ pixmap = widget_provider_buffer_resource_id(info);
+ if (pixmap) {
+ buffer = fb_dump_frame(pixmap, info->width, info->height, info->pixel_size);
+ }
+ }
+ } else {
+ /**
+ * @note
+ * In this case, the provider buffer doesn't create the gem handler for this.
+ * So we have to use fb_dump_frame.
+ */
+ pixmap = widget_provider_buffer_extra_resource_id(info, idx);
+ if (pixmap) {
+ buffer = fb_dump_frame(pixmap, info->width, info->height, info->pixel_size);
+ }
+ }
+
+ return buffer;
+}
+
EAPI int widget_provider_buffer_is_support_hw(widget_buffer_h info)
{
if (!info || info->state != BUFFER_CREATED) {
@@ -2363,7 +2417,7 @@ EAPI int widget_provider_buffer_is_support_hw(widget_buffer_h info)
return WIDGET_ERROR_INVALID_PARAMETER;
}
- return fb_has_gem(info->fb);
+ return fb_support_gem(info->fb);
}
EAPI int widget_provider_buffer_create_hw(widget_buffer_h info)
@@ -2373,7 +2427,7 @@ EAPI int widget_provider_buffer_create_hw(widget_buffer_h info)
return WIDGET_ERROR_INVALID_PARAMETER;
}
- if (!fb_has_gem(info->fb)) {
+ if (!fb_support_gem(info->fb)) {
return WIDGET_ERROR_INVALID_PARAMETER;
}
diff --git a/widget_provider_app/include/util.h b/widget_provider_app/include/util.h
index d522f27..ed805c4 100644
--- a/widget_provider_app/include/util.h
+++ b/widget_provider_app/include/util.h
@@ -16,7 +16,6 @@
extern int util_check_ext(const char *icon, const char *ext);
extern double util_timestamp(void);
-extern const char *util_basename(const char *name);
extern char *util_get_current_module(char **symbol);
extern char *util_path_to_uri(const char *id);
extern void *util_timer_add(double interval, Eina_Bool (*cb)(void *data), void *data);
diff --git a/widget_provider_app/include/widget_provider_app.h b/widget_provider_app/include/widget_provider_app.h
index 3cb2dcc..37f6593 100644
--- a/widget_provider_app/include/widget_provider_app.h
+++ b/widget_provider_app/include/widget_provider_app.h
@@ -156,7 +156,11 @@ typedef void (*widget_provider_disconnected_cb)(void *data);
* @param[in] data user data
* @return 0 on success, otherwise a negative error value
*/
-typedef void (*widget_provider_orientation_changed)(const char *id, int degree, void *data);
+typedef void (*widget_provider_orientation_changed_cb)(const char *id, int degree, void *data);
+
+/**
+ */
+typedef void (*widget_provider_ctrl_mode_cb)(const char *id, int cmd, int value, void *data);
/**
* @brief Widget event callback table
@@ -172,7 +176,8 @@ typedef struct widget_provider_event_callback {
widget_provider_text_signal_cb text_signal; /**< Called when a text signal even emitted */
widget_provider_connected_cb connected; /**< Called when a provider is connected to master service */
widget_provider_disconnected_cb disconnected; /**< Called when a provider is disconnected from the master service */
- widget_provider_orientation_changed orientation;
+ widget_provider_orientation_changed_cb orientation;
+ widget_provider_ctrl_mode_cb ctrl_mode;
void *data; /**< Callback data */
} *widget_provider_event_callback_s;
@@ -284,6 +289,8 @@ extern int widget_provider_app_get_orientation(const char *id);
*/
extern char *widget_provider_app_get_widget_id(const char *id);
+extern int widget_provider_app_get_last_ctrl(const char *id, int *cmd, int *value);
+
/**
* @}
*/
diff --git a/widget_provider_app/include/widget_provider_app_internal.h b/widget_provider_app/include/widget_provider_app_internal.h
index f216158..2b030ca 100644
--- a/widget_provider_app/include/widget_provider_app_internal.h
+++ b/widget_provider_app/include/widget_provider_app_internal.h
@@ -350,4 +350,6 @@ extern int widget_provider_app_add_pre_callback(widget_pre_callback_e type, widg
extern int widget_provider_app_del_pre_callback(widget_pre_callback_e type, widget_pre_callback_t cb, void *data);
+extern int widget_provider_app_get_last_ctrl_mode(const char *id, int *cmd, int *value);
+
/* End of a file */
diff --git a/widget_provider_app/src/client.c b/widget_provider_app/src/client.c
index a5268dd..048abdc 100644
--- a/widget_provider_app/src/client.c
+++ b/widget_provider_app/src/client.c
@@ -75,6 +75,10 @@ struct item {
void *data;
Eina_List *handle_list;
int degree;
+ struct _last_ctrl_mode {
+ int cmd;
+ int value;
+ } last_ctrl_mode;
};
struct internal_item {
@@ -828,6 +832,30 @@ static int method_orientation(struct widget_event_arg *arg, void *data)
return WIDGET_ERROR_NONE;
}
+static int method_ctrl_mode(struct widget_event_arg *arg, void *data)
+{
+ struct widget_provider_event_callback *table = data;
+ struct item *inst;
+
+ inst = instance_find(arg->id);
+ if (!inst) {
+ return WIDGET_ERROR_INVALID_PARAMETER;
+ }
+
+ inst->last_ctrl_mode.cmd = arg->info.ctrl_mode.cmd;
+ inst->last_ctrl_mode.value = arg->info.ctrl_mode.value;
+
+ invoke_pre_callback(WIDGET_PRE_CTRL_MODE_CALLBACK, arg->id);
+
+ if (table->ctrl_mode) {
+ table->ctrl_mode(widget_util_uri_to_path(inst->id), arg->info.ctrl_mode.cmd, arg->info.ctrl_mode.value, table->data);
+ } else {
+ return WIDGET_ERROR_NOT_SUPPORTED;
+ }
+
+ return WIDGET_ERROR_NONE;
+}
+
static Eina_Bool send_ping_cb(void *data)
{
widget_provider_send_ping();
@@ -1272,6 +1300,7 @@ int client_init_sync(struct widget_provider_event_callback *table)
.gbar_destroy = method_gbar_destroyed,
.gbar_move = method_gbar_moved,
.orientation = method_orientation,
+ .ctrl_mode = method_ctrl_mode,
};
if (s_info.initialized == 1) {
@@ -1393,6 +1422,7 @@ int client_init(app_control_h service, struct widget_provider_event_callback *ta
.viewer_connected = method_viewer_connected,
.viewer_disconnected = method_viewer_disconnected,
.orientation = method_orientation,
+ .ctrl_mode = method_ctrl_mode,
};
if (s_info.initialized == 1) {
@@ -1895,6 +1925,36 @@ PAPI int widget_provider_app_get_orientation(const char *id)
return inst->degree;
}
+PAPI int widget_provider_app_get_last_ctrl_mode(const char *id, int *cmd, int *value)
+{
+ char *uri;
+ struct item *inst;
+
+ uri = util_path_to_uri(id);
+ if (!uri) {
+ ErrPrint("Invalid URI [%s]\n", id);
+ return WIDGET_ERROR_OUT_OF_MEMORY;
+ }
+
+ inst = instance_find(uri);
+ free(uri);
+
+ if (!inst) {
+ ErrPrint("[%s] is not exists\n", id);
+ return WIDGET_ERROR_NOT_EXIST;
+ }
+
+ if (cmd) {
+ *cmd = inst->last_ctrl_mode.cmd;
+ }
+
+ if (value) {
+ *value = inst->last_ctrl_mode.value;
+ }
+
+ return WIDGET_ERROR_NONE;
+}
+
/**
* } End of a file
*/
diff --git a/widget_provider_app/src/util.c b/widget_provider_app/src/util.c
index 610bac1..9343351 100644
--- a/widget_provider_app/src/util.c
+++ b/widget_provider_app/src/util.c
@@ -83,20 +83,6 @@ double util_timestamp(void)
#endif
}
-const char *util_basename(const char *name)
-{
- int length;
-
- length = name ? strlen(name) : 0;
- if (!length) {
- return ".";
- }
-
- while (--length > 0 && name[length] != '/');
-
- return length <= 0 ? name : name + length + (name[length] == '/');
-}
-
double util_time_delay_for_compensation(double period)
{
unsigned long long curtime;