From ec4c2c1a40f8e0f02683c7557f6f57c9db00b794 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Tue, 8 Dec 2015 20:35:50 +0900 Subject: [PATCH 01/16] elimiate race condition of capture callback Change-Id: I0eeeaac9b76474174272eba47ebfd7e23f0d14f6 --- src/tdm_capture.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/tdm_capture.c b/src/tdm_capture.c index f63d2b8..fa592ec 100644 --- a/src/tdm_capture.c +++ b/src/tdm_capture.c @@ -54,7 +54,20 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. static void _tdm_caputre_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer, void *user_data) { + tdm_private_capture *private_capture = user_data; + tdm_private_display *private_display = private_capture->private_display; + int lock_after_cb_done = 0; + + if (pthread_mutex_trylock(&private_display->lock)) + { + pthread_mutex_unlock(&private_display->lock); + lock_after_cb_done = 1; + } + tdm_buffer_unref_backend(tdm_buffer_get(buffer)); + + if (lock_after_cb_done) + pthread_mutex_lock(&private_display->lock); } INTERN tdm_private_capture* -- 2.7.4 From 0528570f64e42d86e92d7edb5bd7a93e609f36dd Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 9 Dec 2015 12:45:00 +0900 Subject: [PATCH 02/16] change double pointer to one pointer in tdm_caps_output Change-Id: I81737bfacdf0423dce368d0dd6188ec71d41ad98 --- include/tdm_backend.h | 2 +- src/tdm.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/tdm_backend.h b/include/tdm_backend.h index 1957987..bd4e9d7 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -59,7 +59,7 @@ typedef struct _tdm_caps_output unsigned int type_id; unsigned int mode_count; - tdm_output_mode **modes; + tdm_output_mode *modes; unsigned int prop_count; tdm_prop *props; diff --git a/src/tdm.c b/src/tdm.c index 7d5e16e..794540f 100644 --- a/src/tdm.c +++ b/src/tdm.c @@ -308,8 +308,8 @@ _tdm_display_update_caps_output(tdm_private_display *private_display, TDM_DBG("output props: %d, %s", caps->props[i].id, caps->props[i].name); for (i = 0; i < caps->mode_count; i++) TDM_DBG("output modes: name(%s), size(%dx%d), refresh(%d), flags(%d), type(%d)", - caps->modes[i]->name, caps->modes[i]->width, caps->modes[i]->height, - caps->modes[i]->refresh, caps->modes[i]->flags, caps->modes[i]->type); + caps->modes[i].name, caps->modes[i].width, caps->modes[i].height, + caps->modes[i].refresh, caps->modes[i].flags, caps->modes[i].type); TDM_DBG("output min : %dx%d", caps->min_w, caps->min_h); TDM_DBG("output max : %dx%d", caps->max_w, caps->max_h); TDM_DBG("output align: %d", caps->preferred_align); -- 2.7.4 From d61bb7194d28a31d9efad842e7eefde410eb3eac Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Fri, 11 Dec 2015 14:27:00 +0900 Subject: [PATCH 03/16] use tdm_buffer instead of tbm_surface for backend - add tdm buffer destroy handler Change-Id: I6edf927ded6c7e07cfcf396f279c5ab8fc49e4de Signed-off-by: Junkyeong Kim --- include/tdm_backend.h | 16 +++++++++--- src/tdm_buffer.c | 71 +++++++++++++++++++++++++++++++++++++++++++++------ src/tdm_capture.c | 4 +-- src/tdm_display.c | 3 +-- src/tdm_private.h | 5 ---- 5 files changed, 79 insertions(+), 20 deletions(-) diff --git a/include/tdm_backend.h b/include/tdm_backend.h index bd4e9d7..81eb89c 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -147,7 +147,7 @@ typedef struct _tdm_func_display tdm_error (*layer_get_property)(tdm_layer *layer, unsigned int id, tdm_value *value); tdm_error (*layer_set_info)(tdm_layer *layer, tdm_info_layer *info); tdm_error (*layer_get_info)(tdm_layer *layer, tdm_info_layer *info); - tdm_error (*layer_set_buffer)(tdm_layer *layer, tbm_surface_h buffer); + tdm_error (*layer_set_buffer)(tdm_layer *layer, tdm_buffer *buffer); tdm_error (*layer_unset_buffer)(tdm_layer *layer); tdm_capture *(*layer_create_capture)(tdm_layer *layer, tdm_error *error); } tdm_func_display; @@ -163,13 +163,13 @@ typedef struct _tdm_func_pp tdm_error (*pp_set_done_handler)(tdm_pp *pp, tdm_pp_done_handler func, void *user_data); } tdm_func_pp; -typedef void (*tdm_capture_done_handler)(tdm_capture *capture, tbm_surface_h buffer, void *user_data); +typedef void (*tdm_capture_done_handler)(tdm_capture *capture, tdm_buffer *buffer, void *user_data); typedef struct _tdm_func_capture { void (*capture_destroy)(tdm_capture *capture); /* init */ tdm_error (*capture_set_info)(tdm_capture *capture, tdm_info_capture *info); - tdm_error (*capture_attach)(tdm_capture *capture, tbm_surface_h buffer); + tdm_error (*capture_attach)(tdm_capture *capture, tdm_buffer *buffer); tdm_error (*capture_commit)(tdm_capture *capture); /* init */ tdm_error (*capture_set_done_handler)(tdm_capture *capture, tdm_capture_done_handler func, void *user_data); } tdm_func_capture; @@ -198,6 +198,16 @@ tdm_error tdm_backend_register_func_display(tdm_display *dpy, tdm_func_display * tdm_error tdm_backend_register_func_pp(tdm_display *dpy, tdm_func_pp *func_pp); tdm_error tdm_backend_register_func_capture(tdm_display *dpy, tdm_func_capture *func_capture); +typedef void (*tdm_buffer_destroy_handler)(tdm_buffer *buffer, void *user_data); + +tdm_buffer* tdm_buffer_ref_backend(tdm_buffer *buffer); +void tdm_buffer_unref_backend(tdm_buffer *buffer); +tbm_surface_h tdm_buffer_get_surface(tdm_buffer *buffer); +tdm_buffer* tdm_buffer_get(tbm_surface_h buffer); +tdm_error tdm_buffer_add_destroy_handler(tdm_buffer *buffer, tdm_buffer_destroy_handler func, void *user_data); +void tdm_buffer_remove_destroy_handler(tdm_buffer *buffer, tdm_buffer_destroy_handler func, void *user_data); + + #ifdef __cplusplus } #endif diff --git a/src/tdm_buffer.c b/src/tdm_buffer.c index 31b0d88..508b9bd 100644 --- a/src/tdm_buffer.c +++ b/src/tdm_buffer.c @@ -43,7 +43,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. typedef struct _tdm_buffer_func_info { - tdm_buffer_release_handler func; + tdm_buffer_release_handler release_func; + tdm_buffer_destroy_handler destroy_func; void *user_data; struct list_head link; @@ -60,6 +61,7 @@ typedef struct _tdm_buffer_info int backend_ref_count; struct list_head release_funcs; + struct list_head destroy_funcs; struct list_head link; } tdm_buffer_info; @@ -80,6 +82,15 @@ _tdm_buffer_destroy(tdm_buffer_info *buf_info) free(func_info); } + LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link) + func_info->destroy_func(buf_info, func_info->user_data); + + LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link) + { + LIST_DEL(&func_info->link); + free(func_info); + } + LIST_DEL(&buf_info->link); tbm_surface_internal_unref(buf_info->buffer); @@ -124,6 +135,7 @@ tdm_buffer_create(tbm_surface_h buffer, tdm_error *error) buf_info->buffer = buffer; LIST_INITHEAD(&buf_info->release_funcs); + LIST_INITHEAD(&buf_info->destroy_funcs); LIST_ADDTAIL(&buf_info->link, &buffer_list); if (error) @@ -189,7 +201,7 @@ tdm_buffer_add_release_handler(tdm_buffer *buffer, func_info = calloc(1, sizeof(tdm_buffer_func_info)); TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY); - func_info->func = func; + func_info->release_func = func; func_info->user_data = user_data; buf_info = buffer; @@ -210,7 +222,7 @@ tdm_buffer_remove_release_handler(tdm_buffer *buffer, tdm_buffer_release_handler buf_info = buffer; LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) { - if (func_info->func != func || func_info->user_data != user_data) + if (func_info->release_func != func || func_info->user_data != user_data) continue; LIST_DEL(&func_info->link); @@ -221,7 +233,7 @@ tdm_buffer_remove_release_handler(tdm_buffer *buffer, tdm_buffer_release_handler } -INTERN tdm_buffer* +EXTERN tdm_buffer* tdm_buffer_ref_backend(tdm_buffer *buffer) { tdm_buffer_info *buf_info; @@ -234,7 +246,7 @@ tdm_buffer_ref_backend(tdm_buffer *buffer) return buffer; } -INTERN void +EXTERN void tdm_buffer_unref_backend(tdm_buffer *buffer) { tdm_buffer_info *buf_info; @@ -256,14 +268,14 @@ tdm_buffer_unref_backend(tdm_buffer *buffer) old_ref_count = buf_info->ref_count; LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) - func_info->func(buffer, func_info->user_data); + func_info->release_func(buffer, func_info->user_data); /* finally, both ref_count and backend_ref_count are 0. destroy tdm_buffer */ if (old_ref_count == 0 && buf_info->ref_count == 0) _tdm_buffer_destroy(buf_info); } -INTERN tbm_surface_h +EXTERN tbm_surface_h tdm_buffer_get_surface(tdm_buffer *buffer) { tdm_buffer_info *buf_info = buffer; @@ -273,7 +285,7 @@ tdm_buffer_get_surface(tdm_buffer *buffer) return buf_info->buffer; } -INTERN tdm_buffer* +EXTERN tdm_buffer* tdm_buffer_get(tbm_surface_h buffer) { tdm_buffer_info *found; @@ -294,3 +306,46 @@ tdm_buffer_get(tbm_surface_h buffer) return NULL; } + +EXTERN tdm_error +tdm_buffer_add_destroy_handler(tdm_buffer *buffer, tdm_buffer_destroy_handler func, void *user_data) +{ + tdm_buffer_info *buf_info; + tdm_buffer_func_info *func_info; + + TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); + + func_info = calloc(1, sizeof(tdm_buffer_func_info)); + TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY); + + func_info->destroy_func = func; + func_info->user_data = user_data; + + buf_info = buffer; + LIST_ADD(&func_info->link, &buf_info->destroy_funcs); + + return TDM_ERROR_NONE; +} + +EXTERN void +tdm_buffer_remove_destroy_handler(tdm_buffer *buffer, tdm_buffer_destroy_handler func, void *user_data) +{ + tdm_buffer_info *buf_info; + tdm_buffer_func_info *func_info = NULL, *next = NULL; + + TDM_RETURN_IF_FAIL(buffer != NULL); + TDM_RETURN_IF_FAIL(func != NULL); + + buf_info = buffer; + LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link) + { + if (func_info->destroy_func != func || func_info->user_data != user_data) + continue; + + LIST_DEL(&func_info->link); + free(func_info); + + return; + } +} diff --git a/src/tdm_capture.c b/src/tdm_capture.c index fa592ec..46927c2 100644 --- a/src/tdm_capture.c +++ b/src/tdm_capture.c @@ -52,7 +52,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. func_capture = private_capture->func_capture static void -_tdm_caputre_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer, void *user_data) +_tdm_caputre_cb_done(tdm_capture *capture_backend, tdm_buffer *buffer, void *user_data) { tdm_private_capture *private_capture = user_data; tdm_private_display *private_display = private_capture->private_display; @@ -64,7 +64,7 @@ _tdm_caputre_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer, void *u lock_after_cb_done = 1; } - tdm_buffer_unref_backend(tdm_buffer_get(buffer)); + tdm_buffer_unref_backend(buffer); if (lock_after_cb_done) pthread_mutex_lock(&private_display->lock); diff --git a/src/tdm_display.c b/src/tdm_display.c index 082e6b5..0ae9bb5 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -1040,8 +1040,7 @@ tdm_layer_set_buffer(tdm_layer *layer, tdm_buffer *buffer) private_layer->waiting_buffer = tdm_buffer_ref_backend(buffer); - ret = func_display->layer_set_buffer(private_layer->layer_backend, - tdm_buffer_get_surface(buffer)); + ret = func_display->layer_set_buffer(private_layer->layer_backend, buffer); pthread_mutex_unlock(&private_display->lock); diff --git a/src/tdm_private.h b/src/tdm_private.h index 635682f..657ef4b 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -256,11 +256,6 @@ struct _tdm_private_commit_handler void *user_data; }; -tdm_buffer* tdm_buffer_ref_backend(tdm_buffer *buffer); -void tdm_buffer_unref_backend(tdm_buffer *buffer); -tbm_surface_h tdm_buffer_get_surface(tdm_buffer *buffer); -tdm_buffer* tdm_buffer_get(tbm_surface_h buffer); - tdm_private_pp* tdm_pp_create_internal(tdm_private_display *private_display, tdm_error *error); void tdm_pp_destroy_internal(tdm_private_pp *private_pp); -- 2.7.4 From 6f7e4d98706710265287efb05f23fe58a0686470 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Tue, 15 Dec 2015 19:01:11 +0900 Subject: [PATCH 04/16] add layer_set_video_pos to backend interface Change-Id: I80d1d31ab78f68f8859ce70b67d2e56a431e18b5 --- include/tdm.h | 1 + include/tdm_backend.h | 1 + src/tdm_display.c | 29 +++++++++++++++++++++++++++++ 3 files changed, 31 insertions(+) diff --git a/include/tdm.h b/include/tdm.h index 23bcde8..da6a006 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -115,6 +115,7 @@ tdm_error tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info); tdm_error tdm_layer_set_buffer(tdm_layer *layer, tdm_buffer *buffer); // layer has only one buffer tdm_error tdm_layer_unset_buffer(tdm_layer *layer); tdm_error tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable); +tdm_error tdm_layer_set_video_pos(tdm_layer *layer, int zpos); tdm_capture *tdm_layer_create_capture(tdm_layer *layer, tdm_error *error); diff --git a/include/tdm_backend.h b/include/tdm_backend.h index 81eb89c..c649d73 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -149,6 +149,7 @@ typedef struct _tdm_func_display tdm_error (*layer_get_info)(tdm_layer *layer, tdm_info_layer *info); tdm_error (*layer_set_buffer)(tdm_layer *layer, tdm_buffer *buffer); tdm_error (*layer_unset_buffer)(tdm_layer *layer); + tdm_error (*layer_set_video_pos)(tdm_layer *layer, int zpos); tdm_capture *(*layer_create_capture)(tdm_layer *layer, tdm_error *error); } tdm_func_display; diff --git a/src/tdm_display.c b/src/tdm_display.c index 0ae9bb5..109c808 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -1104,6 +1104,35 @@ tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable) return ret; } +EXTERN tdm_error +tdm_layer_set_video_pos(tdm_layer *layer, int zpos) +{ + tdm_func_display *func_display; + LAYER_FUNC_ENTRY(); + + pthread_mutex_lock(&private_display->lock); + + func_display = &private_display->func_display; + + if (!(private_layer->caps.capabilities & TDM_LAYER_CAPABILITY_VIDEO)) + { + TDM_ERR("layer is not video layer"); + pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_INVALID_PARAMETER; + } + + if (!func_display->layer_set_video_pos) + { + pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_NONE; + } + + ret = func_display->layer_set_video_pos(private_layer->layer_backend, zpos); + + pthread_mutex_unlock(&private_display->lock); + + return ret; +} EXTERN tdm_capture* tdm_layer_create_capture(tdm_layer *layer, tdm_error *error) -- 2.7.4 From 1a056b9b8bad1290c248857cace922568233dff1 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Mon, 21 Dec 2015 10:51:57 +0900 Subject: [PATCH 05/16] unlock mutex after try_lock Change-Id: I7e11a01bc27edfd9aff8168833c3b1813544d0b4 --- src/tdm_capture.c | 6 +++++- src/tdm_pp.c | 6 +++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/tdm_capture.c b/src/tdm_capture.c index 46927c2..56610c7 100644 --- a/src/tdm_capture.c +++ b/src/tdm_capture.c @@ -57,8 +57,12 @@ _tdm_caputre_cb_done(tdm_capture *capture_backend, tdm_buffer *buffer, void *use tdm_private_capture *private_capture = user_data; tdm_private_display *private_display = private_capture->private_display; int lock_after_cb_done = 0; + int ret; - if (pthread_mutex_trylock(&private_display->lock)) + ret = pthread_mutex_trylock(&private_display->lock); + if (ret == 0) + pthread_mutex_unlock(&private_display->lock); + else if (ret == EBUSY) { pthread_mutex_unlock(&private_display->lock); lock_after_cb_done = 1; diff --git a/src/tdm_pp.c b/src/tdm_pp.c index 959674d..a8f1858 100644 --- a/src/tdm_pp.c +++ b/src/tdm_pp.c @@ -57,8 +57,12 @@ _tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst, void * tdm_private_pp *private_pp = user_data; tdm_private_display *private_display = private_pp->private_display; int lock_after_cb_done = 0; + int ret; - if (pthread_mutex_trylock(&private_display->lock)) + ret = pthread_mutex_trylock(&private_display->lock); + if (ret == 0) + pthread_mutex_unlock(&private_display->lock); + else if (ret == EBUSY) { pthread_mutex_unlock(&private_display->lock); lock_after_cb_done = 1; -- 2.7.4 From 185e798a72524e859647f28c13609f678f33bf29 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Tue, 22 Dec 2015 11:36:51 +0900 Subject: [PATCH 06/16] change input/output parameter's type Change-Id: Id8f985919a9da55448852b70715068a934c2a909 --- include/tdm.h | 6 +++--- include/tdm_backend.h | 2 +- src/tdm_display.c | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/tdm.h b/include/tdm.h index da6a006..4a6708e 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -71,7 +71,7 @@ tdm_error tdm_display_get_pp_available_size(tdm_display *dpy, int *min_w, int tdm_error tdm_display_get_capture_capabilities(tdm_display *dpy, tdm_capture_capability *capabilities); tdm_error tdm_display_get_catpure_available_formats(tdm_display *dpy, const tbm_format **formats, int *count); tdm_error tdm_display_get_output_count(tdm_display *dpy, int *count); -const tdm_output* tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error); +tdm_output* tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error); tdm_pp* tdm_display_create_pp(tdm_display *dpy, tdm_error *error); @@ -80,7 +80,7 @@ tdm_pp* tdm_display_create_pp(tdm_display *dpy, tdm_error *error); tdm_error tdm_output_get_conn_status(tdm_output *output, tdm_output_conn_status *status); tdm_error tdm_output_get_output_type(tdm_output *output, tdm_output_type *type); tdm_error tdm_output_get_layer_count(tdm_output *output, int *count); -const tdm_layer* tdm_output_get_layer(tdm_output *output, int index, tdm_error *error); +tdm_layer* tdm_output_get_layer(tdm_output *output, int index, tdm_error *error); tdm_error tdm_output_get_available_properties(tdm_output *output, const tdm_prop **props, int *count); tdm_error tdm_output_get_available_modes(tdm_output *output, const tdm_output_mode **modes, int *count); tdm_error tdm_output_get_available_size(tdm_output *output, int *min_w, int *min_h, int *max_w, int *max_h, int *preferred_align); @@ -93,7 +93,7 @@ tdm_error tdm_output_get_property(tdm_output *output, unsigned int id, tdm_val tdm_error tdm_output_wait_vblank(tdm_output *output, int interval, int sync, tdm_output_vblank_handler func, void *user_data); tdm_error tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data); -tdm_error tdm_output_set_mode(tdm_output *output, tdm_output_mode *mode); +tdm_error tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode); tdm_error tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode); tdm_error tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value); diff --git a/include/tdm_backend.h b/include/tdm_backend.h index c649d73..bfb6119 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -138,7 +138,7 @@ typedef struct _tdm_func_display tdm_error (*output_set_commit_handler)(tdm_output *output, tdm_output_commit_handler func); tdm_error (*output_set_dpms)(tdm_output *output, tdm_output_dpms dpms_value); tdm_error (*output_get_dpms)(tdm_output *output, tdm_output_dpms *dpms_value); - tdm_error (*output_set_mode)(tdm_output *output, tdm_output_mode *mode); + tdm_error (*output_set_mode)(tdm_output *output, const tdm_output_mode *mode); tdm_error (*output_get_mode)(tdm_output *output, const tdm_output_mode **mode); tdm_capture *(*output_create_capture)(tdm_output *output, tdm_error *error); diff --git a/src/tdm_display.c b/src/tdm_display.c index 109c808..3b9d12e 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -226,7 +226,7 @@ tdm_display_get_output_count(tdm_display *dpy, int *count) } -EXTERN const tdm_output* +EXTERN tdm_output* tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error) { tdm_private_output *private_output = NULL; @@ -245,7 +245,7 @@ tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error) if (i == index) { pthread_mutex_unlock(&private_display->lock); - return (const tdm_output*)private_output; + return private_output; } i++; } @@ -377,7 +377,7 @@ tdm_output_get_layer_count(tdm_output *output, int *count) } -EXTERN const tdm_layer* +EXTERN tdm_layer* tdm_output_get_layer(tdm_output *output, int index, tdm_error *error) { tdm_private_layer *private_layer = NULL; @@ -727,7 +727,7 @@ tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, } EXTERN tdm_error -tdm_output_set_mode(tdm_output *output, tdm_output_mode *mode) +tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode) { tdm_func_display *func_display; OUTPUT_FUNC_ENTRY(); -- 2.7.4 From 7760ef17c78e7cbe8d2991c3b2f1bb02d8392d28 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Tue, 22 Dec 2015 16:43:06 +0900 Subject: [PATCH 07/16] change buffer type from tdm_buffer to tbm_surface Change-Id: Idd7dc7aea84488b76ba78b91c9b98a02ea4563c5 --- include/tdm.h | 15 ++-- include/tdm_backend.h | 18 ++--- include/tdm_types.h | 1 - src/tdm_buffer.c | 198 +++++++++++++------------------------------------- src/tdm_capture.c | 7 +- src/tdm_display.c | 2 +- src/tdm_pp.c | 10 +-- src/tdm_private.h | 4 +- 8 files changed, 75 insertions(+), 180 deletions(-) diff --git a/include/tdm.h b/include/tdm.h index 4a6708e..98daa25 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -112,7 +112,7 @@ tdm_error tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value tdm_error tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value); tdm_error tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info); tdm_error tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info); -tdm_error tdm_layer_set_buffer(tdm_layer *layer, tdm_buffer *buffer); // layer has only one buffer +tdm_error tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer); // layer has only one buffer tdm_error tdm_layer_unset_buffer(tdm_layer *layer); tdm_error tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable); tdm_error tdm_layer_set_video_pos(tdm_layer *layer, int zpos); @@ -123,26 +123,23 @@ tdm_capture *tdm_layer_create_capture(tdm_layer *layer, tdm_error *error); void tdm_pp_destroy(tdm_pp *pp); tdm_error tdm_pp_set_info(tdm_pp *pp, tdm_info_pp *info); -tdm_error tdm_pp_attach(tdm_pp *pp, tdm_buffer *src, tdm_buffer *dst); +tdm_error tdm_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst); tdm_error tdm_pp_commit(tdm_pp *pp); /////////////////////////////////////////////////////////////////////////////// void tdm_capture_destroy(tdm_capture *capture); tdm_error tdm_capture_set_info(tdm_capture *capture, tdm_info_capture *info); -tdm_error tdm_capture_attach(tdm_capture *capture, tdm_buffer *buffer); +tdm_error tdm_capture_attach(tdm_capture *capture, tbm_surface_h buffer); tdm_error tdm_capture_commit(tdm_capture *capture); /////////////////////////////////////////////////////////////////////////////// -typedef void (*tdm_buffer_release_handler)(tdm_buffer *buffer, void *user_data); +typedef void (*tdm_buffer_release_handler)(tbm_surface_h buffer, void *user_data); /* not pthread safe */ -tdm_buffer *tdm_buffer_create(tbm_surface_h buffer, tdm_error *error); -tdm_buffer *tdm_buffer_ref(tdm_buffer *buffer, tdm_error *error); -void tdm_buffer_unref(tdm_buffer *buffer); -tdm_error tdm_buffer_add_release_handler(tdm_buffer *buffer, tdm_buffer_release_handler func, void *user_data); -void tdm_buffer_remove_release_handler(tdm_buffer *buffer, tdm_buffer_release_handler func, void *user_data); +tdm_error tdm_buffer_add_release_handler(tbm_surface_h buffer, tdm_buffer_release_handler func, void *user_data); +void tdm_buffer_remove_release_handler(tbm_surface_h buffer, tdm_buffer_release_handler func, void *user_data); #ifdef __cplusplus } diff --git a/include/tdm_backend.h b/include/tdm_backend.h index bfb6119..461a632 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -147,7 +147,7 @@ typedef struct _tdm_func_display tdm_error (*layer_get_property)(tdm_layer *layer, unsigned int id, tdm_value *value); tdm_error (*layer_set_info)(tdm_layer *layer, tdm_info_layer *info); tdm_error (*layer_get_info)(tdm_layer *layer, tdm_info_layer *info); - tdm_error (*layer_set_buffer)(tdm_layer *layer, tdm_buffer *buffer); + tdm_error (*layer_set_buffer)(tdm_layer *layer, tbm_surface_h buffer); tdm_error (*layer_unset_buffer)(tdm_layer *layer); tdm_error (*layer_set_video_pos)(tdm_layer *layer, int zpos); tdm_capture *(*layer_create_capture)(tdm_layer *layer, tdm_error *error); @@ -164,13 +164,13 @@ typedef struct _tdm_func_pp tdm_error (*pp_set_done_handler)(tdm_pp *pp, tdm_pp_done_handler func, void *user_data); } tdm_func_pp; -typedef void (*tdm_capture_done_handler)(tdm_capture *capture, tdm_buffer *buffer, void *user_data); +typedef void (*tdm_capture_done_handler)(tdm_capture *capture, tbm_surface_h buffer, void *user_data); typedef struct _tdm_func_capture { void (*capture_destroy)(tdm_capture *capture); /* init */ tdm_error (*capture_set_info)(tdm_capture *capture, tdm_info_capture *info); - tdm_error (*capture_attach)(tdm_capture *capture, tdm_buffer *buffer); + tdm_error (*capture_attach)(tdm_capture *capture, tbm_surface_h buffer); tdm_error (*capture_commit)(tdm_capture *capture); /* init */ tdm_error (*capture_set_done_handler)(tdm_capture *capture, tdm_capture_done_handler func, void *user_data); } tdm_func_capture; @@ -199,14 +199,12 @@ tdm_error tdm_backend_register_func_display(tdm_display *dpy, tdm_func_display * tdm_error tdm_backend_register_func_pp(tdm_display *dpy, tdm_func_pp *func_pp); tdm_error tdm_backend_register_func_capture(tdm_display *dpy, tdm_func_capture *func_capture); -typedef void (*tdm_buffer_destroy_handler)(tdm_buffer *buffer, void *user_data); +typedef void (*tdm_buffer_destroy_handler)(tbm_surface_h buffer, void *user_data); -tdm_buffer* tdm_buffer_ref_backend(tdm_buffer *buffer); -void tdm_buffer_unref_backend(tdm_buffer *buffer); -tbm_surface_h tdm_buffer_get_surface(tdm_buffer *buffer); -tdm_buffer* tdm_buffer_get(tbm_surface_h buffer); -tdm_error tdm_buffer_add_destroy_handler(tdm_buffer *buffer, tdm_buffer_destroy_handler func, void *user_data); -void tdm_buffer_remove_destroy_handler(tdm_buffer *buffer, tdm_buffer_destroy_handler func, void *user_data); +tbm_surface_h tdm_buffer_ref_backend(tbm_surface_h buffer); +void tdm_buffer_unref_backend(tbm_surface_h buffer); +tdm_error tdm_buffer_add_destroy_handler(tbm_surface_h buffer, tdm_buffer_destroy_handler func, void *user_data); +void tdm_buffer_remove_destroy_handler(tbm_surface_h buffer, tdm_buffer_destroy_handler func, void *user_data); #ifdef __cplusplus diff --git a/include/tdm_types.h b/include/tdm_types.h index e5e577b..c054d04 100644 --- a/include/tdm_types.h +++ b/include/tdm_types.h @@ -242,7 +242,6 @@ typedef struct _tdm_info_capture typedef void tdm_display; typedef void tdm_output; typedef void tdm_layer; -typedef void tdm_buffer; typedef void tdm_capture; typedef void tdm_pp; diff --git a/src/tdm_buffer.c b/src/tdm_buffer.c index 508b9bd..149b944 100644 --- a/src/tdm_buffer.c +++ b/src/tdm_buffer.c @@ -41,6 +41,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "tdm_private.h" #include "tdm_list.h" +static int tdm_buffer_key; +#define TDM_BUFFER_KEY ((unsigned long)&tdm_buffer_key) + typedef struct _tdm_buffer_func_info { tdm_buffer_release_handler release_func; @@ -54,27 +57,21 @@ typedef struct _tdm_buffer_info { tbm_surface_h buffer; - /* ref_count for frontend */ - int ref_count; - /* ref_count for backend */ int backend_ref_count; struct list_head release_funcs; struct list_head destroy_funcs; - struct list_head link; } tdm_buffer_info; -static int buffer_list_init; -static struct list_head buffer_list; - static void -_tdm_buffer_destroy(tdm_buffer_info *buf_info) +_tdm_buffer_destroy_info(void *user_data) { + tdm_buffer_info *buf_info = (tdm_buffer_info*)user_data; tdm_buffer_func_info *func_info = NULL, *next = NULL; - TDM_WARNING_IF_FAIL(buf_info->ref_count == 0); - TDM_WARNING_IF_FAIL(buf_info->backend_ref_count == 0); + if (buf_info->backend_ref_count > 0) + TDM_NEVER_GET_HERE(); LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) { @@ -83,7 +80,7 @@ _tdm_buffer_destroy(tdm_buffer_info *buf_info) } LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link) - func_info->destroy_func(buf_info, func_info->user_data); + func_info->destroy_func(buf_info->buffer, func_info->user_data); LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link) { @@ -91,105 +88,39 @@ _tdm_buffer_destroy(tdm_buffer_info *buf_info) free(func_info); } - LIST_DEL(&buf_info->link); - - tbm_surface_internal_unref(buf_info->buffer); free(buf_info); } -EXTERN tdm_buffer* -tdm_buffer_create(tbm_surface_h buffer, tdm_error *error) +static tdm_buffer_info* +_tdm_buffer_get_info(tbm_surface_h buffer) { - tdm_buffer_info *buf_info; - - if (!buffer_list_init) - { - LIST_INITHEAD(&buffer_list); - buffer_list_init = 1; - } + tdm_buffer_info *buf_info = NULL; + tbm_bo bo; - if (!buffer) - { - if (error) - *error = TDM_ERROR_INVALID_PARAMETER; + bo = tbm_surface_internal_get_bo(buffer, 0); + TDM_RETURN_VAL_IF_FAIL(bo != NULL, NULL); - TDM_ERR("'buffer != NULL' failed"); + tbm_bo_get_user_data(bo, TDM_BUFFER_KEY, (void**)&buf_info); - return NULL; - } - - buf_info = calloc(1, sizeof(tdm_buffer_info)); if (!buf_info) { - if (error) - *error = TDM_ERROR_OUT_OF_MEMORY; - - TDM_ERR("'buf_info != NULL' failed"); - - return NULL; - } - - buf_info->ref_count = 1; - - tbm_surface_internal_ref(buffer); - buf_info->buffer = buffer; + buf_info = calloc(1, sizeof(tdm_buffer_info)); + TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL); - LIST_INITHEAD(&buf_info->release_funcs); - LIST_INITHEAD(&buf_info->destroy_funcs); - LIST_ADDTAIL(&buf_info->link, &buffer_list); + buf_info->buffer = buffer; - if (error) - *error = TDM_ERROR_NONE; + LIST_INITHEAD(&buf_info->release_funcs); + LIST_INITHEAD(&buf_info->destroy_funcs); - return (tdm_buffer*)buf_info; -} - -EXTERN tdm_buffer* -tdm_buffer_ref(tdm_buffer *buffer, tdm_error *error) -{ - tdm_buffer_info *buf_info; - - if (!buffer) - { - if (error) - *error = TDM_ERROR_INVALID_PARAMETER; - - TDM_ERR("'buffer != NULL' failed"); - - return NULL; + tbm_bo_add_user_data(bo, TDM_BUFFER_KEY, _tdm_buffer_destroy_info); + tbm_bo_set_user_data(bo, TDM_BUFFER_KEY, buf_info); } - buf_info = buffer; - buf_info->ref_count++; - - if (error) - *error = TDM_ERROR_NONE; - - return buffer; -} - -EXTERN void -tdm_buffer_unref(tdm_buffer *buffer) -{ - tdm_buffer_info *buf_info; - - if (!buffer) - return; - - buf_info = buffer; - TDM_RETURN_IF_FAIL (buf_info->ref_count > 0); - - buf_info->ref_count--; - - /* destroy tdm_buffer when both ref_count and backend_ref_count are 0. */ - if (buf_info->ref_count > 0 || buf_info->backend_ref_count > 0) - return; - - _tdm_buffer_destroy(buf_info); + return buf_info; } EXTERN tdm_error -tdm_buffer_add_release_handler(tdm_buffer *buffer, +tdm_buffer_add_release_handler(tbm_surface_h buffer, tdm_buffer_release_handler func, void *user_data) { tdm_buffer_info *buf_info; @@ -198,20 +129,22 @@ tdm_buffer_add_release_handler(tdm_buffer *buffer, TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); + buf_info = _tdm_buffer_get_info(buffer); + TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, TDM_ERROR_OUT_OF_MEMORY); + func_info = calloc(1, sizeof(tdm_buffer_func_info)); TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY); func_info->release_func = func; func_info->user_data = user_data; - buf_info = buffer; LIST_ADD(&func_info->link, &buf_info->release_funcs); return TDM_ERROR_NONE; } EXTERN void -tdm_buffer_remove_release_handler(tdm_buffer *buffer, tdm_buffer_release_handler func, void *user_data) +tdm_buffer_remove_release_handler(tbm_surface_h buffer, tdm_buffer_release_handler func, void *user_data) { tdm_buffer_info *buf_info; tdm_buffer_func_info *func_info = NULL, *next = NULL; @@ -219,7 +152,9 @@ tdm_buffer_remove_release_handler(tdm_buffer *buffer, tdm_buffer_release_handler TDM_RETURN_IF_FAIL(buffer != NULL); TDM_RETURN_IF_FAIL(func != NULL); - buf_info = buffer; + buf_info = _tdm_buffer_get_info(buffer); + TDM_RETURN_IF_FAIL(buf_info != NULL); + LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) { if (func_info->release_func != func || func_info->user_data != user_data) @@ -233,82 +168,47 @@ tdm_buffer_remove_release_handler(tdm_buffer *buffer, tdm_buffer_release_handler } -EXTERN tdm_buffer* -tdm_buffer_ref_backend(tdm_buffer *buffer) +EXTERN tbm_surface_h +tdm_buffer_ref_backend(tbm_surface_h buffer) { tdm_buffer_info *buf_info; TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL); - buf_info = buffer; + buf_info = _tdm_buffer_get_info(buffer); + TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, NULL); + buf_info->backend_ref_count++; return buffer; } EXTERN void -tdm_buffer_unref_backend(tdm_buffer *buffer) +tdm_buffer_unref_backend(tbm_surface_h buffer) { tdm_buffer_info *buf_info; tdm_buffer_func_info *func_info = NULL, *next = NULL; - int old_ref_count; TDM_RETURN_IF_FAIL(buffer != NULL); - buf_info = buffer; + buf_info = _tdm_buffer_get_info(buffer); + TDM_RETURN_IF_FAIL(buf_info != NULL); + buf_info->backend_ref_count--; if (buf_info->backend_ref_count > 0) return; - /* ref_count can become 0 in user release function. In that case, buf_info - * will be destroyed in tbm_buffer_unref. So we destroy buf_info in this - * function only in case that old_ref_count is 0. - */ - old_ref_count = buf_info->ref_count; - LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) - func_info->release_func(buffer, func_info->user_data); - - /* finally, both ref_count and backend_ref_count are 0. destroy tdm_buffer */ - if (old_ref_count == 0 && buf_info->ref_count == 0) - _tdm_buffer_destroy(buf_info); -} - -EXTERN tbm_surface_h -tdm_buffer_get_surface(tdm_buffer *buffer) -{ - tdm_buffer_info *buf_info = buffer; - - TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, NULL); - - return buf_info->buffer; -} - -EXTERN tdm_buffer* -tdm_buffer_get(tbm_surface_h buffer) -{ - tdm_buffer_info *found; - - TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL); - - if (!buffer_list_init) - { - LIST_INITHEAD(&buffer_list); - buffer_list_init = 1; - } - - LIST_FOR_EACH_ENTRY(found, &buffer_list, link) { - if (found->buffer == buffer) - return found; + tbm_surface_internal_ref(buffer); + func_info->release_func(buffer, func_info->user_data); + tbm_surface_internal_unref(buffer); } - - return NULL; } EXTERN tdm_error -tdm_buffer_add_destroy_handler(tdm_buffer *buffer, tdm_buffer_destroy_handler func, void *user_data) +tdm_buffer_add_destroy_handler(tbm_surface_h buffer, tdm_buffer_destroy_handler func, void *user_data) { tdm_buffer_info *buf_info; tdm_buffer_func_info *func_info; @@ -316,20 +216,22 @@ tdm_buffer_add_destroy_handler(tdm_buffer *buffer, tdm_buffer_destroy_handler fu TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER); TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); + buf_info = _tdm_buffer_get_info(buffer); + TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, TDM_ERROR_OUT_OF_MEMORY); + func_info = calloc(1, sizeof(tdm_buffer_func_info)); TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY); func_info->destroy_func = func; func_info->user_data = user_data; - buf_info = buffer; LIST_ADD(&func_info->link, &buf_info->destroy_funcs); return TDM_ERROR_NONE; } EXTERN void -tdm_buffer_remove_destroy_handler(tdm_buffer *buffer, tdm_buffer_destroy_handler func, void *user_data) +tdm_buffer_remove_destroy_handler(tbm_surface_h buffer, tdm_buffer_destroy_handler func, void *user_data) { tdm_buffer_info *buf_info; tdm_buffer_func_info *func_info = NULL, *next = NULL; @@ -337,7 +239,9 @@ tdm_buffer_remove_destroy_handler(tdm_buffer *buffer, tdm_buffer_destroy_handler TDM_RETURN_IF_FAIL(buffer != NULL); TDM_RETURN_IF_FAIL(func != NULL); - buf_info = buffer; + buf_info = _tdm_buffer_get_info(buffer); + TDM_RETURN_IF_FAIL(buf_info != NULL); + LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link) { if (func_info->destroy_func != func || func_info->user_data != user_data) diff --git a/src/tdm_capture.c b/src/tdm_capture.c index 56610c7..92e306a 100644 --- a/src/tdm_capture.c +++ b/src/tdm_capture.c @@ -52,7 +52,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. func_capture = private_capture->func_capture static void -_tdm_caputre_cb_done(tdm_capture *capture_backend, tdm_buffer *buffer, void *user_data) +_tdm_caputre_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer, void *user_data) { tdm_private_capture *private_capture = user_data; tdm_private_display *private_display = private_capture->private_display; @@ -245,7 +245,7 @@ tdm_capture_set_info(tdm_capture *capture, tdm_info_capture *info) } EXTERN tdm_error -tdm_capture_attach(tdm_capture *capture, tdm_buffer *buffer) +tdm_capture_attach(tdm_capture *capture, tbm_surface_h buffer) { CAPTURE_FUNC_ENTRY(); @@ -260,8 +260,7 @@ tdm_capture_attach(tdm_capture *capture, tdm_buffer *buffer) } tdm_buffer_ref_backend(buffer); - ret = func_capture->capture_attach(private_capture->capture_backend, - tdm_buffer_get_surface(buffer)); + ret = func_capture->capture_attach(private_capture->capture_backend, buffer); pthread_mutex_unlock(&private_display->lock); diff --git a/src/tdm_display.c b/src/tdm_display.c index 3b9d12e..862c3d4 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -1012,7 +1012,7 @@ tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info) } EXTERN tdm_error -tdm_layer_set_buffer(tdm_layer *layer, tdm_buffer *buffer) +tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) { tdm_func_display *func_display; LAYER_FUNC_ENTRY(); diff --git a/src/tdm_pp.c b/src/tdm_pp.c index a8f1858..492db45 100644 --- a/src/tdm_pp.c +++ b/src/tdm_pp.c @@ -68,8 +68,8 @@ _tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst, void * lock_after_cb_done = 1; } - tdm_buffer_unref_backend(tdm_buffer_get(src)); - tdm_buffer_unref_backend(tdm_buffer_get(dst)); + tdm_buffer_unref_backend(src); + tdm_buffer_unref_backend(dst); if (lock_after_cb_done) pthread_mutex_lock(&private_display->lock); @@ -190,7 +190,7 @@ tdm_pp_set_info(tdm_pp *pp, tdm_info_pp *info) } EXTERN tdm_error -tdm_pp_attach(tdm_pp *pp, tdm_buffer *src, tdm_buffer *dst) +tdm_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst) { PP_FUNC_ENTRY(); @@ -207,9 +207,7 @@ tdm_pp_attach(tdm_pp *pp, tdm_buffer *src, tdm_buffer *dst) tdm_buffer_ref_backend(src); tdm_buffer_ref_backend(dst); - ret = func_pp->pp_attach(private_pp->pp_backend, - tdm_buffer_get_surface(src), - tdm_buffer_get_surface(dst)); + ret = func_pp->pp_attach(private_pp->pp_backend, src, dst); pthread_mutex_unlock(&private_display->lock); diff --git a/src/tdm_private.h b/src/tdm_private.h index 657ef4b..1a9df49 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -206,8 +206,8 @@ struct _tdm_private_layer tdm_caps_layer caps; tdm_layer *layer_backend; - tdm_buffer *waiting_buffer; - tdm_buffer *showing_buffer; + tbm_surface_h waiting_buffer; + tbm_surface_h showing_buffer; struct list_head capture_list; -- 2.7.4 From ace19867a6e822b2275fc135cbcbc2f80612baf0 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Tue, 22 Dec 2015 20:27:43 +0900 Subject: [PATCH 08/16] packaging: upgrade version to 1.0.1 Change-Id: I6c860b3db08c982213ed09e2b5670487e5fa6ce2 --- packaging/libtdm.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index 0d7cb56..e505c35 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -1,5 +1,5 @@ Name: libtdm -Version: 1.0.0 +Version: 1.0.1 Release: 0 Summary: User Library of Tizen Display Manager Group: Development/Libraries -- 2.7.4 From acea9df33fafe8c77811a014c068ab77e423d228 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 23 Dec 2015 19:43:48 +0900 Subject: [PATCH 09/16] fix svace issue Change-Id: I1adae5445f0e403ce4e482b182e1903c9508c648 --- src/tdm_buffer.c | 2 +- src/tdm_display.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tdm_buffer.c b/src/tdm_buffer.c index 149b944..9b112c0 100644 --- a/src/tdm_buffer.c +++ b/src/tdm_buffer.c @@ -105,7 +105,7 @@ _tdm_buffer_get_info(tbm_surface_h buffer) if (!buf_info) { buf_info = calloc(1, sizeof(tdm_buffer_info)); - TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL); + TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, NULL); buf_info->buffer = buffer; diff --git a/src/tdm_display.c b/src/tdm_display.c index 862c3d4..f904a18 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -591,7 +591,7 @@ _tdm_output_cb_commit(tdm_output *output_backend, unsigned int sequence, tdm_private_commit_handler *commit_handler = user_data; tdm_private_display *private_display; tdm_private_output *private_output; - tdm_private_layer *private_layer; + tdm_private_layer *private_layer = NULL; TDM_RETURN_IF_FAIL(commit_handler); -- 2.7.4 From 6ae1989353da6d3ae62324d26e5ac8befad2563f Mon Sep 17 00:00:00 2001 From: Boram Park Date: Tue, 29 Dec 2015 13:36:53 +0900 Subject: [PATCH 10/16] add doxygen document Change-Id: I12b2711b22f6ffe62162ec19464867711be8cef5 --- include/tdm.h | 582 ++++++++++++++++++++++++++++++++++++++++----- include/tdm_backend.h | 641 +++++++++++++++++++++++++++++++++++++++++++++----- include/tdm_helper.h | 13 + include/tdm_log.h | 10 + include/tdm_types.h | 253 ++++++++++++++------ src/tdm_capture.c | 4 +- src/tdm_display.c | 41 +++- src/tdm_pp.c | 2 +- src/tdm_private.h | 5 + 9 files changed, 1359 insertions(+), 192 deletions(-) diff --git a/include/tdm.h b/include/tdm.h index 98daa25..dc1719f 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -46,100 +46,570 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. extern "C" { #endif -/////////////////////////////////////////////////////////////////////////////// - +/** + * @file tdm.h + * @brief The header file for a frontend user. + * @par Example + * @code + #include //for a frontend user + * @endcode + * @details + * TDM stands for Tizen Display Manager. It's the display HAL layer for tizen + * display server. It offers the frontend APIs(@ref tdm.h) for a frontend user + * and the abstraction interface(@ref tdm_backend.h) for a hardware vendor.\n + * \n + * TDM consists of display/output/layer/pp/capture objects. A frontend user can + * get the output/layer/pp/capture hardware information with each object. + * Basically, TDM supposes that all hardware devices have fixed outputs and + * layers. A frontend user can get these outputs and layers with + * #tdm_display_get_output_count, #tdm_display_get_output, #tdm_output_get_layer_count + * and #tdm_output_get_layer. To get a pp/capture object, however, a frontend + * user need to create a object with #tdm_display_create_pp, #tdm_output_create_capture + * and #tdm_layer_create_capture if available.\n + * \n + * All changes of output/layer/pp/capture objects are applied when commiting. + * See #tdm_output_commit, #tdm_pp_commit and #tdm_capture_commit.\n + * \n + * TDM has its own buffer release mechanism to let an user know when a TDM buffer + * becomes available for a next job. A frontend user can add a user release handler + * to a TDM buffer with #tdm_buffer_add_release_handler, and this handler will be + * called when it's disappered from screen or when pp/capture operation is done. + */ + +/** + * @brief The display capability enumeration + */ typedef enum { - TDM_DISPLAY_CAPABILITY_PP = (1<<0), - TDM_DISPLAY_CAPABILITY_CAPTURE = (1<<1), + TDM_DISPLAY_CAPABILITY_PP = (1<<0), /**< if hardware supports pp operation */ + TDM_DISPLAY_CAPABILITY_CAPTURE = (1<<1), /**< if hardware supports capture operation */ } tdm_display_capability; -/* not neccessary for user to know what backend is */ +/** + * @brief Initialize a display object + * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. + * @return A display object + * @see tdm_display_deinit + */ tdm_display* tdm_display_init(tdm_error *error); + +/** + * @brief Deinitialize a display object + * @param[in] dpy A display object + * @see tdm_display_init + */ void tdm_display_deinit(tdm_display *dpy); -tdm_error tdm_display_update(tdm_display *dpy); -/////////////////////////////////////////////////////////////////////////////// +/** + * @brief Update a display object + * @details + * When new output is connected, a frontend user need to call this function. + * And a frontend user can the new output information with tdm_output_get_xxx functions. + * @param[in] dpy A display object + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_display_update(tdm_display *dpy); +/** + * @brief Get the file descriptor + * @details TDM handles the events of fd with #tdm_display_handle_events. + * @param[in] dpy A display object + * @param[out] fd The file descriptor + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_display_handle_events + */ tdm_error tdm_display_get_fd(tdm_display *dpy, int *fd); + +/** + * @brief Handle the events + * @param[in] dpy A display object + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_display_get_fd + */ tdm_error tdm_display_handle_events(tdm_display *dpy); +/** + * @brief Get the capabilities of a display object. + * @details A frontend user can get whether TDM supports pp/capture functionality with this function. + * @param[in] dpy A display object + * @param[out] capabilities The capabilities of a display object + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error tdm_display_get_capabilities(tdm_display *dpy, tdm_display_capability *capabilities); + +/** + * @brief Get the pp capabilities of a display object. + * @param[in] dpy A display object + * @param[out] capabilities The pp capabilities + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error tdm_display_get_pp_capabilities(tdm_display *dpy, tdm_pp_capability *capabilities); + +/** + * @brief Get the pp available format array of a display object. + * @param[in] dpy A display object + * @param[out] formats The pp available format array + * @param[out] count The count of formats + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error tdm_display_get_pp_available_formats(tdm_display *dpy, const tbm_format **formats, int *count); + +/** + * @brief Get the pp available size of a display object. + * @details -1 means that a TDM backend module doesn't define the value. + * @param[in] dpy A display object + * @param[out] min_w The minimum width which TDM can handle + * @param[out] min_h The minimum height which TDM can handle + * @param[out] max_w The maximum width which TDM can handle + * @param[out] max_h The maximum height which TDM can handle + * @param[out] preferred_align The preferred align width which TDM can handle + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error tdm_display_get_pp_available_size(tdm_display *dpy, int *min_w, int *min_h, int *max_w, int *max_h, int *preferred_align); + +/** + * @brief Get the capture capabilities of a display object. + * @param[in] dpy A display object + * @param[out] capabilities The capture capabilities + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error tdm_display_get_capture_capabilities(tdm_display *dpy, tdm_capture_capability *capabilities); + +/** + * @brief Get the capture available format array of a display object. + * @param[in] dpy A display object + * @param[out] formats The capture available format array + * @param[out] count The count of formats + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error tdm_display_get_catpure_available_formats(tdm_display *dpy, const tbm_format **formats, int *count); + +/** + * @brief Get the output counts which a display object has. + * @param[in] dpy A display object + * @param[out] count The count of outputs + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_display_get_output + */ tdm_error tdm_display_get_output_count(tdm_display *dpy, int *count); + +/** + * @brief Get a output object which has the given index. + * @param[in] dpy A display object + * @param[in] index The index of a output object + * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. + * @return A output object if success. Otherwise, NULL. + * @see tdm_display_get_output_count + */ tdm_output* tdm_display_get_output(tdm_display *dpy, int index, tdm_error *error); +/** + * @brief Create a pp object. + * @param[in] dpy A display object + * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. + * @return A pp object if success. Otherwise, NULL. + * @see tdm_pp_destroy + */ tdm_pp* tdm_display_create_pp(tdm_display *dpy, tdm_error *error); -/////////////////////////////////////////////////////////////////////////////// - -tdm_error tdm_output_get_conn_status(tdm_output *output, tdm_output_conn_status *status); -tdm_error tdm_output_get_output_type(tdm_output *output, tdm_output_type *type); -tdm_error tdm_output_get_layer_count(tdm_output *output, int *count); -tdm_layer* tdm_output_get_layer(tdm_output *output, int index, tdm_error *error); -tdm_error tdm_output_get_available_properties(tdm_output *output, const tdm_prop **props, int *count); -tdm_error tdm_output_get_available_modes(tdm_output *output, const tdm_output_mode **modes, int *count); -tdm_error tdm_output_get_available_size(tdm_output *output, int *min_w, int *min_h, int *max_w, int *max_h, int *preferred_align); -tdm_error tdm_output_get_physical_size(tdm_output *output, unsigned int *mmWidth, unsigned int *mmHeight); -tdm_error tdm_output_get_subpixel(tdm_output *output, unsigned int *subpixel); -tdm_error tdm_output_get_pipe(tdm_output *output, unsigned int *pipe); - -tdm_error tdm_output_set_property(tdm_output *output, unsigned int id, tdm_value value); -tdm_error tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value); -tdm_error tdm_output_wait_vblank(tdm_output *output, int interval, int sync, tdm_output_vblank_handler func, void *user_data); -tdm_error tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data); - -tdm_error tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode); -tdm_error tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode); - -tdm_error tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value); -tdm_error tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value); - +/** + * @brief Get the connection status of a output object. + * @param[in] output A output object + * @param[out] status The connection status. + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_output_get_conn_status(tdm_output *output, tdm_output_conn_status *status); + +/** + * @brief Get the connection type of a output object. + * @param[in] output A output object + * @param[out] type The connection type. + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_output_get_output_type(tdm_output *output, tdm_output_type *type); + +/** + * @brief Get the layer counts which a output object has. + * @param[in] output A output object + * @param[out] count The count of layers + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_output_get_layer + */ +tdm_error tdm_output_get_layer_count(tdm_output *output, int *count); + +/** + * @brief Get a layer object which has the given index. + * @param[in] output A output object + * @param[in] index The index of a layer object + * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. + * @return A layer object if success. Otherwise, NULL. + * @see tdm_output_get_layer_count + */ +tdm_layer* tdm_output_get_layer(tdm_output *output, int index, tdm_error *error); + +/** + * @brief Get the available property array of a output object. + * @param[in] output A output object + * @param[out] props The available property array + * @param[out] count The count of properties + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_output_get_available_properties(tdm_output *output, const tdm_prop **props, int *count); + +/** + * @brief Get the available mode array of a output object. + * @param[in] output A output object + * @param[out] modes The available mode array + * @param[out] count The count of modes + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_output_get_available_modes(tdm_output *output, const tdm_output_mode **modes, int *count); + +/** + * @brief Get the available size of a output object. + * @details -1 means that a TDM backend module doesn't define the value. + * @param[in] output A output object + * @param[out] min_w The minimum width which TDM can handle + * @param[out] min_h The minimum height which TDM can handle + * @param[out] max_w The maximum width which TDM can handle + * @param[out] max_h The maximum height which TDM can handle + * @param[out] preferred_align The preferred align width which TDM can handle + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_output_get_available_size(tdm_output *output, int *min_w, int *min_h, int *max_w, int *max_h, int *preferred_align); + +/** + * @brief Get the physical size of a output object. + * @param[in] output A output object + * @param[out] mmWidth The milimeter width + * @param[out] mmHeight The milimeter height + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_output_get_physical_size(tdm_output *output, unsigned int *mmWidth, unsigned int *mmHeight); + +/** + * @brief Get the subpixel of a output object. + * @param[in] output A output object + * @param[out] subpixel The subpixel + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_output_get_subpixel(tdm_output *output, unsigned int *subpixel); + +/** + * @brief Get the pipe of a output object. + * @param[in] output A output object + * @param[out] pipe The pipe + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_output_get_pipe(tdm_output *output, unsigned int *pipe); + +/** + * @brief Set the property which has a given id. + * @param[in] output A output object + * @param[in] id The property id + * @param[in] value The value + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_output_set_property(tdm_output *output, unsigned int id, tdm_value value); + +/** + * @brief Get the property which has a given id + * @param[in] output A output object + * @param[in] id The property id + * @param[out] value The value + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_output_get_property(tdm_output *output, unsigned int id, tdm_value *value); + +/** + * @brief Wait for VBLANK + * @details After interval vblanks, a user vblank handler will be called. + * @param[in] output A output object + * @param[in] interval vblank interval + * @param[in] sync 0: asynchronous, 1:synchronous + * @param[in] user_data The user data + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see #tdm_output_vblank_handler + */ +tdm_error tdm_output_wait_vblank(tdm_output *output, int interval, int sync, tdm_output_vblank_handler func, void *user_data); + +/** + * @brief Commit changes for a output object + * @details After all change of a output object are applied, a user commit handler + * will be called. + * @param[in] output A output object + * @param[in] sync 0: asynchronous, 1:synchronous + * @param[in] user_data The user data + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_output_commit(tdm_output *output, int sync, tdm_output_commit_handler func, void *user_data); + +/** + * @brief Set one of available modes of a output object + * @param[in] output A output object + * @param[in] mode A output mode + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_output_set_mode(tdm_output *output, const tdm_output_mode *mode); + +/** + * @brief Get the mode of a output object + * @param[in] output A output object + * @param[out] mode A output mode + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_output_get_mode(tdm_output *output, const tdm_output_mode **mode); + +/** + * @brief Set DPMS of a output object + * @param[in] output A output object + * @param[in] dpms_value DPMS value + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value); + +/** + * @brief Get DPMS of a output object + * @param[in] output A output object + * @param[out] dpms_value DPMS value + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value); + +/** + * @brief Create a capture object of a output object + * @param[in] output A output object + * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. + * @return A capture object + * @see tdm_capture_destroy + */ tdm_capture *tdm_output_create_capture(tdm_output *output, tdm_error *error); -/////////////////////////////////////////////////////////////////////////////// - -tdm_error tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities); -tdm_error tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats, int *count); -tdm_error tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props, int *count); -tdm_error tdm_layer_get_zpos(tdm_layer *layer, unsigned int *zpos); /* zpos of layer is fixed */ - -tdm_error tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value); -tdm_error tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value); -tdm_error tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info); -tdm_error tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info); -tdm_error tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer); // layer has only one buffer -tdm_error tdm_layer_unset_buffer(tdm_layer *layer); -tdm_error tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable); -tdm_error tdm_layer_set_video_pos(tdm_layer *layer, int zpos); - +/** + * @brief Get the capabilities of a layer object. + * @param[in] layer A layer object + * @param[out] capabilities The capabilities of a layer object + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_layer_get_capabilities(tdm_layer *layer, tdm_layer_capability *capabilities); + +/** + * @brief Get the available format array of a layer object. + * @param[in] layer A layer object + * @param[out] formats The available format array + * @param[out] count The count of formats + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_layer_get_available_formats(tdm_layer *layer, const tbm_format **formats, int *count); + +/** + * @brief Get the available property array of a layer object. + * @param[in] layer A layer object + * @param[out] props The available property array + * @param[out] count The count of properties + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop **props, int *count); + +/** + * @brief Get the zpos of a layer object. + * @details + * - GRAPHIC layers have fixed zpos. It starts from 0. It's @b non-changeable. + * - But the zpos of VIDEO layers will be decided by a backend module side. + * - A frontend user only can set the relative zpos to VIDEO layers via #tdm_layer_set_video_pos + * - The zpos of video layers is less than GRAPHIC layers or more than GRAPHIC + * layers. ie, -1, -2, 4, 5 (if 0 <= GRAPHIC layer's zpos < 4). + * @param[in] layer A layer object + * @param[out] zpos The zpos + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_layer_set_video_pos, tdm_layer_capability + */ +tdm_error tdm_layer_get_zpos(tdm_layer *layer, unsigned int *zpos); + +/** + * @brief Set the property which has a given id. + * @param[in] layer A layer object + * @param[in] id The property id + * @param[in] value The value + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value); + +/** + * @brief Get the property which has a given id. + * @param[in] layer A layer object + * @param[in] id The property id + * @param[out] value The value + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value); + +/** + * @brief Set the geometry information to a layer object + * @details The geometry information will be applied when the output object + * of a layer object is committed. + * @param[in] layer A layer object + * @param[in] info The geometry information + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_output_commit + */ +tdm_error tdm_layer_set_info(tdm_layer *layer, tdm_info_layer *info); + +/** + * @brief Get the geometry information to a layer object + * @param[in] layer A layer object + * @param[out] info The geometry information + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_layer_get_info(tdm_layer *layer, tdm_info_layer *info); + +/** + * @brief Set a TDM buffer to a layer object + * @details A TDM buffer will be applied when the output object + * of a layer object is committed. + * @param[in] layer A layer object + * @param[in] buffer A TDM buffer + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_output_commit + */ +tdm_error tdm_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer); + +/** + * @brief Unset a TDM buffer from a layer object + * @details When this function is called, a current showing buffer will be + * disappeared from screen. Then nothing is showing on a layer object. + * @param[in] layer A layer object + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_layer_unset_buffer(tdm_layer *layer); + +/** + * @brief Check wheter a layer object is available for a frontend user to use. + * @details A layer object is not usable if a TDM buffer is showing on screen + * via this layer object. By calling #tdm_layer_unset_buffer, this layer object + * will become usable. + * @param[in] layer A layer object + * @param[out] usable 1 if usable, 0 if not usable + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_layer_is_usable(tdm_layer *layer, unsigned int *usable); + +/** + * @brief Set the relative zpos to a VIDEO layer object + * @details The zpos value is less than the minimum zpos of GRAPHIC layers, or + * it is more than the maximum zpos of GRAPHIC layers. + * @param[in] layer A VIDEO layer object + * @param[in] zpos The zpos + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_layer_get_zpos, tdm_layer_capability + */ +tdm_error tdm_layer_set_video_pos(tdm_layer *layer, int zpos); + +/** + * @brief Create a capture object of a layer object + * @param[in] output A output object + * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. + * @return A capture object + * @see tdm_capture_destroy + */ tdm_capture *tdm_layer_create_capture(tdm_layer *layer, tdm_error *error); -/////////////////////////////////////////////////////////////////////////////// - +/** + * @brief Destroy a pp object + * @param[in] pp A pp object + * @see tdm_display_create_pp + */ void tdm_pp_destroy(tdm_pp *pp); + +/** + * @brief Set the geometry information to a pp object + * @param[in] pp A pp object + * @param[in] info The geometry information + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_pp_commit + */ tdm_error tdm_pp_set_info(tdm_pp *pp, tdm_info_pp *info); + +/** + * @brief Attach a source buffer and a destination buffer to a pp object + * @param[in] pp A pp object + * @param[in] src A source buffer + * @param[in] dst A destination buffer + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_pp_commit, tdm_buffer_add_release_handler, tdm_buffer_release_handler + */ tdm_error tdm_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst); -tdm_error tdm_pp_commit(tdm_pp *pp); -/////////////////////////////////////////////////////////////////////////////// +/** + * @brief Commit changes for a pp object + * @param[in] pp A pp object + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_pp_commit(tdm_pp *pp); +/** + * @brief Destroy a capture object + * @param[in] capture A capture object + * @see tdm_output_create_capture, tdm_layer_create_capture + */ void tdm_capture_destroy(tdm_capture *capture); + +/** + * @brief Set the geometry information to a capture object + * @param[in] capture A capture object + * @param[in] info The geometry information + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_capture_commit + */ tdm_error tdm_capture_set_info(tdm_capture *capture, tdm_info_capture *info); + +/** + * @brief Attach a TDM buffer to a capture object + * @param[in] capture A capture object + * @param[in] buffer A TDM buffer + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_capture_commit, tdm_buffer_add_release_handler, tdm_buffer_release_handler + */ tdm_error tdm_capture_attach(tdm_capture *capture, tbm_surface_h buffer); -tdm_error tdm_capture_commit(tdm_capture *capture); -/////////////////////////////////////////////////////////////////////////////// +/** + * @brief Commit changes for a capture object + * @param[in] capture A capture object + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ +tdm_error tdm_capture_commit(tdm_capture *capture); +/** + * @brief The release handler of a TDM buffer + * @param[in] buffer A TDM buffer + * @param[in] user_data user data + * @see tdm_buffer_add_release_handler, tdm_buffer_remove_release_handler + */ typedef void (*tdm_buffer_release_handler)(tbm_surface_h buffer, void *user_data); -/* not pthread safe */ -tdm_error tdm_buffer_add_release_handler(tbm_surface_h buffer, tdm_buffer_release_handler func, void *user_data); -void tdm_buffer_remove_release_handler(tbm_surface_h buffer, tdm_buffer_release_handler func, void *user_data); +/** + * @brief Add a release handler to a TDM buffer + * @details + * TDM has its own buffer release mechanism to let an frontend user know when a TDM buffer + * becomes available for a next job. A TDM buffer can be used for TDM to show + * it on screen or to capture an output and a layer. After all operations, + * TDM will release it immediately when TDM doesn't need it any more. + * @param[in] buffer A TDM buffer + * @param[in] func A release handler + * @param[in] user_data user data + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_buffer_remove_release_handler + */ +tdm_error tdm_buffer_add_release_handler(tbm_surface_h buffer, tdm_buffer_release_handler func, void *user_data); + +/** + * @brief Remove a release handler from a TDM buffer + * @param[in] buffer A TDM buffer + * @param[in] func A release handler + * @param[in] user_data user data + * @see tdm_buffer_add_release_handler + */ +void tdm_buffer_remove_release_handler(tbm_surface_h buffer, tdm_buffer_release_handler func, void *user_data); #ifdef __cplusplus } diff --git a/include/tdm_backend.h b/include/tdm_backend.h index 461a632..829a288 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -44,137 +44,549 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. extern "C" { #endif +/** + * @file tdm_backend.h + * @brief The backend header file of TDM to implement a TDM backend module. + * @par Example + * @code + #include + * @endcode + */ + +/** + * @brief The backend module data + * @details + * The init() function of #tdm_backend_module returns the backend module data. + * And it will be passed to display functions of #tdm_func_display. + * @remark It @b SHOULD be freed in the deinit() function of #tdm_backend_module. + * @see tdm_backend_module, tdm_backend_module + */ typedef void tdm_backend_data; +/** + * @brief The display capabilities structure of a backend module + * @remark A backend module @b SHOULD fill this structure to let frontend know the + * backend display capabilities. + * @see The display_get_capabilitiy() function of #tdm_func_display + */ typedef struct _tdm_caps_display { - /* -1: not defined */ - int max_layer_count; + int max_layer_count; /**< The maximum layer count. -1 means "not defined" */ } tdm_caps_display; +/** + * @brief The capabilities structure of a output object + * @details + * If a output device has the size restriction, a backend module can let a user + * know it with min_w, min_h, max_w, max_h, preferred_align variables. + * @remark A backend module @b SHOULD fill this structure to let frontend know the + * backend output capabilities. + * @see The output_get_capability() function of #tdm_func_display + */ typedef struct _tdm_caps_output { - tdm_output_conn_status status; - tdm_output_type type; - unsigned int type_id; - - unsigned int mode_count; - tdm_output_mode *modes; - - unsigned int prop_count; - tdm_prop *props; - - unsigned int mmWidth; - unsigned int mmHeight; - unsigned int subpixel; - - /* -1: not defined */ - int min_w; - int min_h; - int max_w; - int max_h; - int preferred_align; + tdm_output_conn_status status; /**< The connection status */ + tdm_output_type type; /**< The connection type */ + unsigned int type_id; /**< The connection type id */ + + unsigned int mode_count; /**< The count of available modes */ + tdm_output_mode *modes; /**< The array of available modes */ + + unsigned int prop_count; /**< The count of available properties */ + tdm_prop *props; /**< The array of available properties */ + + unsigned int mmWidth; /**< The physical width (milimeter) */ + unsigned int mmHeight; /**< The physical height (milimeter) */ + unsigned int subpixel; /**< The subpixel */ + + int min_w; /**< The minimun width. -1 means "not defined" */ + int min_h; /**< The minimun height. -1 means "not defined" */ + int max_w; /**< The maximum width. -1 means "not defined" */ + int max_h; /**< The maximum height. -1 means "not defined" */ + int preferred_align; /**< The prefered align. -1 means "not defined" */ } tdm_caps_output; +/** + * @brief The capabilities structure of a layer object + * @remark A backend module @b SHOULD fill this structure to let frontend know the + * backend layer capabilities. + * @see The layer_get_capability() function of #tdm_func_display + */ typedef struct _tdm_caps_layer { - tdm_layer_capability capabilities; - unsigned int zpos; /* if VIDEO layer, zpos is -1 */ - - unsigned int format_count; - tbm_format *formats; - - unsigned int prop_count; - tdm_prop *props; + tdm_layer_capability capabilities; /**< The capabilities of layer */ + + /** + * The z-order + * - The zpos of GRAPHIC layers starts from 0, and it is @b non-changeable.\n + * - The zpos of VIDEO layers is less than graphic layers or more than graphic layers. + * ie, -1, -2, 4, 5 (if 0 <= GRAPHIC layer's zpos < 4).. It is @b changeable + * by layer_set_video_pos() function of #tdm_func_display + */ + int zpos; + + unsigned int format_count; /**< The count of available formats */ + tbm_format *formats; /**< The array of available formats */ + + unsigned int prop_count; /**< The count of available properties */ + tdm_prop *props; /**< The array of available properties */ } tdm_caps_layer; +/** + * @brief The capabilities structure of a pp object + * @details + * If a pp device has the size restriction, a backend module can let a user + * know it with min_w, min_h, max_w, max_h, preferred_align variables. + * @remark A backend module @b SHOULD fill this structure to let frontend know the + * backend pp capabilities if pp is available. + * @see The display_get_pp_capability() function of #tdm_func_display + */ typedef struct _tdm_caps_pp { - tdm_pp_capability capabilities; + tdm_pp_capability capabilities; /**< The capabilities of pp */ - unsigned int format_count; - tbm_format *formats; + unsigned int format_count; /**< The count of available formats */ + tbm_format *formats; /**< The array of available formats */ - /* -1: not defined */ - int min_w; - int min_h; - int max_w; - int max_h; - int preferred_align; + int min_w; /**< The minimun width. -1 means "not defined" */ + int min_h; /**< The minimun height. -1 means "not defined" */ + int max_w; /**< The maximum width. -1 means "not defined" */ + int max_h; /**< The maximum height. -1 means "not defined" */ + int preferred_align; /**< The prefered align. -1 means "not defined" */ } tdm_caps_pp; +/** + * @brief The capabilities structure of a capture object + * @details + * If a capture device has the size restriction, a backend module can let a user + * know it with min_w, min_h, max_w, max_h, preferred_align variables. + * @remark A backend module @b SHOULD fill this structure to let frontend know the + * backend capture capabilities if capture is available. + * @see The display_get_capture_capability() function of #tdm_func_display + */ typedef struct _tdm_caps_capture { - tdm_capture_capability capabilities; + tdm_capture_capability capabilities; /**< The capabilities of capture */ - unsigned int format_count; - tbm_format *formats; + unsigned int format_count; /**< The count of available formats */ + tbm_format *formats; /**< The array of available formats */ - /* -1: not defined */ - int min_w; - int min_h; - int max_w; - int max_h; - int preferred_align; + int min_w; /**< The minimun width. -1 means "not defined" */ + int min_h; /**< The minimun height. -1 means "not defined" */ + int max_w; /**< The maximum width. -1 means "not defined" */ + int max_h; /**< The maximum height. -1 means "not defined" */ + int preferred_align; /**< The prefered align. -1 means "not defined" */ } tdm_caps_capture; +/** + * @brief The display functions for a backend module. + */ typedef struct _tdm_func_display { - tdm_error (*display_get_capabilitiy)(tdm_backend_data *bdata, tdm_caps_display *caps); /* init */ - tdm_error (*display_get_pp_capability)(tdm_backend_data *bdata, tdm_caps_pp *caps); /* init */ - tdm_error (*display_get_capture_capability)(tdm_backend_data *bdata, tdm_caps_capture *caps); /* init */ - tdm_output **(*display_get_outputs)(tdm_backend_data *bdata, int *count, tdm_error *error); /* init */ + /** + * @brief Get the display capabilities of a backend module + * @details TDM calls this function at the initial time. And at the update time also. + * #tdm_caps_display containes the max layer count information, etc. + * @param[in] bdata The backend module data + * @param[out] caps The display capabilities of a backend module + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ + tdm_error (*display_get_capabilitiy)(tdm_backend_data *bdata, tdm_caps_display *caps); + + /** + * @brief Get the pp capabilities of a backend module + * @details This function can be NULL if a backend module doesn't have the pp capability. + * TDM calls this function at the initial time if available. And at the update time also. + * #tdm_caps_pp containes avaiable formats, size restriction information, etc. + * @param[in] bdata The backend module data + * @param[out] caps The pp capabilities of a backend module + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_backend_register_func_pp + */ + tdm_error (*display_get_pp_capability)(tdm_backend_data *bdata, tdm_caps_pp *caps); + + /** + * @brief Get the capture capabilities of a backend module + * @details This function can be NULL if a backend module doesn't have the capture capability. + * TDM calls this function at the initial time if available. And at the update time also. + * #tdm_caps_capture containes avaiable formats, size restriction information, etc. + * @param[in] bdata The backend module data + * @param[out] caps The capture capabilities of a backend module + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_backend_register_func_capture + */ + tdm_error (*display_get_capture_capability)(tdm_backend_data *bdata, tdm_caps_capture *caps); + + /** + * @brief Get a output array of a backend module + * @details A backend module @b SHOULD return the newly-allocated output array. + * it will be freed in frontend. + * @param[in] bdata The backend module data + * @param[out] count The count of outputs + * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. + * @return A output array which is newly-allocated + * @see tdm_backend_register_func_capture + */ + tdm_output **(*display_get_outputs)(tdm_backend_data *bdata, int *count, tdm_error *error); + + /** + * @brief Get the file descriptor of a backend module + * @details If a backend module handles one more fds, a backend module can return epoll's fd + * which is watching backend device fds. + * @param[in] bdata The backend module data + * @param[out] fd The fd of a backend module + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see display_handle_events() function of #tdm_func_display + */ tdm_error (*display_get_fd)(tdm_backend_data *bdata, int *fd); + + /** + * @brief Handle the events which happen on the fd of a backend module + * @param[in] bdata The backend module data + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error (*display_handle_events)(tdm_backend_data *bdata); + + /** + * @brief Create a pp object of a backend module + * @param[in] bdata The backend module data + * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. + * @return A pp object + * @see pp_destroy() function of #tdm_func_pp + */ tdm_pp* (*display_create_pp)(tdm_backend_data *bdata, tdm_error *error); - tdm_error (*output_get_capability)(tdm_output *output, tdm_caps_output *caps); /* init */ - tdm_layer **(*output_get_layers)(tdm_output *output, int *count, tdm_error *error); /* init */ + /** + * @brief Get the capabilities of a output object + * #tdm_caps_output containes connection, modes, avaiable properties, size restriction information, etc. + * @param[in] output A output object + * @param[out] caps The capabilities of a output object + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ + tdm_error (*output_get_capability)(tdm_output *output, tdm_caps_output *caps); + + /** + * @brief Get a layer array of a output object + * @details A backend module @b SHOULD return the newly-allocated layer array. + * it will be freed in frontend. + * @param[in] output A output object + * @param[out] count The count of layers + * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. + * @return A layer array which is newly-allocated + */ + tdm_layer **(*output_get_layers)(tdm_output *output, int *count, tdm_error *error); + + /** + * @brief Set the property which has a given id + * @param[in] output A output object + * @param[in] id The property id + * @param[in] value The value + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error (*output_set_property)(tdm_output *output, unsigned int id, tdm_value value); + + /** + * @brief Get the property which has a given id + * @param[in] output A output object + * @param[in] id The property id + * @param[out] value The value + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error (*output_get_property)(tdm_output *output, unsigned int id, tdm_value *value); + + /** + * @brief Wait for VBLANK + * @remark After interval vblanks, a backend module @b SHOULD call a user + * vblank handler. + * @param[in] output A output object + * @param[in] interval vblank interval + * @param[in] sync 0: asynchronous, 1:synchronous + * @param[in] user_data The user data + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see #tdm_output_vblank_handler + */ tdm_error (*output_wait_vblank)(tdm_output *output, int interval, int sync, void *user_data); + + /** + * @brief Set a user vblank handler + * @param[in] output A output object + * @param[in] func A user vblank handler + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error (*output_set_vblank_handler)(tdm_output *output, tdm_output_vblank_handler func); + + /** + * @brief Commit changes for a output object + * @remark After all change of a output object are applied, a backend module + * @b SHOULD call a user commit handler. + * @param[in] output A output object + * @param[in] sync 0: asynchronous, 1:synchronous + * @param[in] user_data The user data + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error (*output_commit)(tdm_output *output, int sync, void *user_data); + + /** + * @brief Set a user commit handler + * @param[in] output A output object + * @param[in] func A user commit handler + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error (*output_set_commit_handler)(tdm_output *output, tdm_output_commit_handler func); + + /** + * @brief Set DPMS of a output object + * @param[in] output A output object + * @param[in] dpms_value DPMS value + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error (*output_set_dpms)(tdm_output *output, tdm_output_dpms dpms_value); + + /** + * @brief Get DPMS of a output object + * @param[in] output A output object + * @param[out] dpms_value DPMS value + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error (*output_get_dpms)(tdm_output *output, tdm_output_dpms *dpms_value); + + /** + * @brief Set one of available modes of a output object + * @param[in] output A output object + * @param[in] mode A output mode + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error (*output_set_mode)(tdm_output *output, const tdm_output_mode *mode); + + /** + * @brief Get the mode of a output object + * @param[in] output A output object + * @param[out] mode A output mode + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error (*output_get_mode)(tdm_output *output, const tdm_output_mode **mode); + + /** + * @brief Create a capture object of a output object + * @param[in] output A output object + * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. + * @return A capture object + * @see capture_destroy() function of #tdm_func_capture + */ tdm_capture *(*output_create_capture)(tdm_output *output, tdm_error *error); - tdm_error (*layer_get_capability)(tdm_layer *layer, tdm_caps_layer *caps); /* init */ + /** + * @brief Get the capabilities of a layer object + * #tdm_caps_layer containes avaiable formats/properties, zpos information, etc. + * @param[in] layer A layer object + * @param[out] caps The capabilities of a layer object + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ + tdm_error (*layer_get_capability)(tdm_layer *layer, tdm_caps_layer *caps); + + /** + * @brief Set the property which has a given id. + * @param[in] layer A layer object + * @param[in] id The property id + * @param[in] value The value + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error (*layer_set_property)(tdm_layer *layer, unsigned int id, tdm_value value); + + /** + * @brief Get the property which has a given id. + * @param[in] layer A layer object + * @param[in] id The property id + * @param[out] value The value + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error (*layer_get_property)(tdm_layer *layer, unsigned int id, tdm_value *value); + + /** + * @brief Set the geometry information to a layer object + * @details The geometry information will be applied when the output object + * of a layer object is committed. + * @param[in] layer A layer object + * @param[in] info The geometry information + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see output_commit() function of #tdm_func_display + */ tdm_error (*layer_set_info)(tdm_layer *layer, tdm_info_layer *info); + + /** + * @brief Get the geometry information to a layer object + * @param[in] layer A layer object + * @param[out] info The geometry information + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error (*layer_get_info)(tdm_layer *layer, tdm_info_layer *info); + + /** + * @brief Set a TDM buffer to a layer object + * @details A TDM buffer will be applied when the output object + * of a layer object is committed. + * @param[in] layer A layer object + * @param[in] buffer A TDM buffer + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see output_commit() function of #tdm_func_display + */ tdm_error (*layer_set_buffer)(tdm_layer *layer, tbm_surface_h buffer); + + /** + * @brief Unset a TDM buffer from a layer object + * @details When this function is called, a current showing buffer will be + * disappeared from screen. Then nothing is showing on a layer object. + * @param[in] layer A layer object + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ tdm_error (*layer_unset_buffer)(tdm_layer *layer); + + /** + * @brief Set the zpos for a VIDEO layer object + * @details Especially this function is for a VIDEO layer. The zpos of + * GRAPHIC layers can't be changed. + * @param[in] layer A layer object + * @param[in] zpos z-order + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see @tdm_layer_capability + */ tdm_error (*layer_set_video_pos)(tdm_layer *layer, int zpos); + + /** + * @brief Create a capture object of a layer object + * @param[in] output A output object + * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. + * @return A capture object + * @see capture_destroy() function of #tdm_func_capture + */ tdm_capture *(*layer_create_capture)(tdm_layer *layer, tdm_error *error); } tdm_func_display; +/** + * @brief The done handler of a pp object + */ typedef void (*tdm_pp_done_handler)(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst, void *user_data); +/** + * @brief The pp functions for a backend module. + */ typedef struct _tdm_func_pp { - void (*pp_destroy)(tdm_pp *pp); /* init */ + /** + * @brief Destroy a pp object + * @param[in] pp A pp object + * @see display_create_pp() function of #tdm_func_display + */ + void (*pp_destroy)(tdm_pp *pp); + + /** + * @brief Set the geometry information to a pp object + * @details The geometry information will be applied when the pp object is committed. + * @param[in] pp A pp object + * @param[in] info The geometry information + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see pp_commit() function of #tdm_func_pp + */ tdm_error (*pp_set_info)(tdm_pp *pp, tdm_info_pp *info); + + /** + * @brief Attach a source buffer and a destination buffer to a pp object + * @details When pp_commit() function is called, a backend module converts + * the image of a source buffer to a destination buffer. + * @param[in] pp A pp object + * @param[in] src A source buffer + * @param[in] dst A destination buffer + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_pp_done_handler + * @see pp_set_info() function of #tdm_func_pp + * @see pp_commit() function of #tdm_func_pp + */ tdm_error (*pp_attach)(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst); - tdm_error (*pp_commit)(tdm_pp *pp); /* init */ + + /** + * @brief Commit changes for a pp object + * @param[in] pp A pp object + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ + tdm_error (*pp_commit)(tdm_pp *pp); + + /** + * @brief Set a user done handler to a pp object + * @param[in] pp A pp object + * @param[in] func A user done handler + * @param[in] user_data user data + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @remark When pp operation is done, a backend module @b SHOULD call #tdm_pp_done_handler. + */ tdm_error (*pp_set_done_handler)(tdm_pp *pp, tdm_pp_done_handler func, void *user_data); } tdm_func_pp; +/** + * @brief The done handler of a capture object + */ typedef void (*tdm_capture_done_handler)(tdm_capture *capture, tbm_surface_h buffer, void *user_data); +/** + * @brief The capture functions for a backend module. + */ typedef struct _tdm_func_capture { - void (*capture_destroy)(tdm_capture *capture); /* init */ + /** + * @brief Destroy a capture object + * @param[in] capture A capture object + * @see output_create_capture() function of #tdm_func_display + * @see layer_create_capture() function of #tdm_func_display + */ + void (*capture_destroy)(tdm_capture *capture); + + /** + * @brief Set the geometry information to a capture object + * @details The geometry information will be applied when the capture object is committed. + * @param[in] capture A capture object + * @param[in] info The geometry information + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see capture_commit() function of #tdm_func_capture + */ tdm_error (*capture_set_info)(tdm_capture *capture, tdm_info_capture *info); + + /** + * @brief Attach a TDM buffer to a capture object + * @details When capture_commit() function is called, a backend module dumps + * a output or a layer to a TDM buffer. + * @param[in] capture A capture object + * @param[in] buffer A TDM buffer + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_capture_done_handler + * @see capture_commit() function of #tdm_func_capture + */ tdm_error (*capture_attach)(tdm_capture *capture, tbm_surface_h buffer); - tdm_error (*capture_commit)(tdm_capture *capture); /* init */ + + /** + * @brief Commit changes for a capture object + * @param[in] capture A capture object + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + */ + tdm_error (*capture_commit)(tdm_capture *capture); + + /** + * @brief Set a user done handler to a capture object + * @param[in] capture A capture object + * @param[in] func A user done handler + * @param[in] user_data user data + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @remark When capture operation is done, a backend module @b SHOULD call #tdm_capture_done_handler. + */ tdm_error (*capture_set_done_handler)(tdm_capture *capture, tdm_capture_done_handler func, void *user_data); } tdm_func_capture; +/* + * ABI versions. Each version has a major and minor revision. Modules + * using lower minor revisions must work with servers of a higher minor + * revision. There is no compatibility between different major revisions. + * Whenever the ABI_ANSIC_VERSION is changed, the others must also be + * changed. The minor revision mask is 0x0000FFFF and the major revision + * mask is 0xFFFF0000. + */ #define TDM_BACKEND_MINOR_VERSION_MASK 0x0000FFFF #define TDM_BACKEND_MAJOR_VERSION_MASK 0xFFFF0000 #define TDM_BACKEND_GET_ABI_MINOR(v) ((v) & TDM_BACKEND_MINOR_VERSION_MASK) @@ -185,25 +597,124 @@ typedef struct _tdm_func_capture ((major) & TDM_BACKEND_MINOR_VERSION_MASK) #define TDM_BACKEND_ABI_VERSION SET_TDM_BACKEND_ABI_VERSION(1, 1) +/** + * @brief The backend module information of the entry point to initialize a TDM + * backend module. + * @details + * A backend module @b SHOULD define the global data symbol of which name is + * @b "tdm_backend_module_data". TDM will read this symbol, @b "tdm_backend_module_data", + * at the initial time and call init() function of #tdm_backend_module. + */ typedef struct _tdm_backend_module { - const char *name; - const char *vendor; - unsigned long abi_version; - + const char *name; /**< The module name of a backend module */ + const char *vendor; /**< The vendor name of a backend module */ + unsigned long abi_version; /**< The ABI version of a backend module */ + + /** + * @brief The init function of a backend module + * @param[in] dpy A display object + * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. + * @return The backend module data + * @see tdm_backend_data + */ tdm_backend_data* (*init)(tdm_display *dpy, tdm_error *error); + + /** + * @brief The deinit function of a backend module + * @param[in] bdata The backend module data + */ void (*deinit)(tdm_backend_data *bdata); } tdm_backend_module; +/** + * @brief Register the backend display functions to a display + * @details + * A backend module @b SHOULD set the backend display functions at least. + * @param[in] dpy A display object + * @param[in] func_display display functions + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_backend_register_func_pp, tdm_backend_register_func_capture + */ tdm_error tdm_backend_register_func_display(tdm_display *dpy, tdm_func_display *func_display); + +/** + * @brief Register the backend pp functions to a display + * @details + * A backend module can skip to register the backend pp functions + * if hardware device doesn't supports the memory to memory converting. + * @param[in] dpy A display object + * @param[in] func_pp pp functions + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_backend_register_func_display, tdm_backend_register_func_capture + */ tdm_error tdm_backend_register_func_pp(tdm_display *dpy, tdm_func_pp *func_pp); -tdm_error tdm_backend_register_func_capture(tdm_display *dpy, tdm_func_capture *func_capture); -typedef void (*tdm_buffer_destroy_handler)(tbm_surface_h buffer, void *user_data); +/** + * @brief Register the backend capture functions to a display + * @details + * A backend module can skip to register the backend capture functions + * if hardware device doesn't supports the memory to memory converting. + * @param[in] dpy A display object + * @param[in] func_capture capture functions + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_backend_register_func_display, tdm_backend_register_func_pp + */ +tdm_error tdm_backend_register_func_capture(tdm_display *dpy, tdm_func_capture *func_capture); +/** + * @brief Increase the ref_count of a TDM buffer + * @details + * TDM has its own buffer release mechanism to let an frontend user know when a TDM buffer + * becomes available for a next job. A TDM buffer can be used for TDM to show + * it on screen or to capture an output and a layer. After all operations, + * TDM will release it immediately when TDM doesn't need it any more. + * @param[in] buffer A TDM buffer + * @return A buffer itself. Otherwise, NULL. + * @remark + * - This function @b SHOULD be paired with #tdm_buffer_unref_backend. \n + * - For example, this function @b SHOULD be called in case that a backend module uses the TDM + * buffer of a layer for capturing a output or a layer to avoid tearing issue. + * @see tdm_buffer_unref_backend + */ tbm_surface_h tdm_buffer_ref_backend(tbm_surface_h buffer); + +/** + * @brief Decrease the ref_count of a TDM buffer + * @param[in] buffer A TDM buffer + * @see tdm_buffer_ref_backend + */ void tdm_buffer_unref_backend(tbm_surface_h buffer); + +/** + * @brief The destroy handler of a TDM buffer + * @param[in] buffer A TDM buffer + * @param[in] user_data user data + * @see tdm_buffer_add_destroy_handler, tdm_buffer_remove_destroy_handler + */ +typedef void (*tdm_buffer_destroy_handler)(tbm_surface_h buffer, void *user_data); + +/** + * @brief Add a destroy handler to a TDM buffer + * @details + * A backend module can add a TDM buffer destroy handler to a TDM buffer which + * is a #tbm_surface_h object. When the TDM buffer is destroyed, this handler will + * be called. + * @param[in] buffer A TDM buffer + * @param[in] func A destroy handler + * @param[in] user_data user data + * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see tdm_buffer_remove_destroy_handler + */ tdm_error tdm_buffer_add_destroy_handler(tbm_surface_h buffer, tdm_buffer_destroy_handler func, void *user_data); + +/** + * @brief Remove a destroy handler from a TDM buffer + * @param[in] buffer A TDM buffer + * @param[in] func A destroy handler + * @param[in] user_data user data + * @see tdm_buffer_add_destroy_handler + */ void tdm_buffer_remove_destroy_handler(tbm_surface_h buffer, tdm_buffer_destroy_handler func, void *user_data); diff --git a/include/tdm_helper.h b/include/tdm_helper.h index 870a3e5..53955b3 100644 --- a/include/tdm_helper.h +++ b/include/tdm_helper.h @@ -42,6 +42,19 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. extern "C" { #endif +/** + * @file tdm_helper.h + * @brief The header file to help a vendor to implement a backend module + * @remark + * tdm_helper_drm_fd is external drm_fd which is opened by ecore_drm. + * This is very @b TRICKY!! But we have no choice at this time because ecore_drm + * doesn't use tdm yet. When we make ecore_drm use tdm, tdm_helper_drm_fd will + * be removed. + * @warning + * If tdm_helper_drm_fd is more than -1, a tdm backend module @b SHOULDN't call + * drmWaitVBlank by itself. Moreover, drm events will be handled by ecore_drm. + * @todo + */ extern int tdm_helper_drm_fd; #ifdef __cplusplus diff --git a/include/tdm_log.h b/include/tdm_log.h index f0b999b..1952e2a 100644 --- a/include/tdm_log.h +++ b/include/tdm_log.h @@ -41,6 +41,16 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. extern "C" { #endif +/** + * @file tdm_log.h + * @brief The header file to print logs in frontend and backend modules + * @details + * The TDM debug log can be enable by setting "TDM_DEBUG" enviroment + * @par Example + * @code + $ export TDM_DEBUG=1 + * @endcode + */ extern int tdm_debug; //#define TDM_CONFIG_DLOG diff --git a/include/tdm_types.h b/include/tdm_types.h index c054d04..b48e8bc 100644 --- a/include/tdm_types.h +++ b/include/tdm_types.h @@ -44,101 +44,164 @@ extern "C" { #define TDM_NAME_LEN 64 +/** + * @file tdm_types.h + * @brief The header file which defines Enumerations and Structures for frontend and backend. + * @details + * Both frontend(#tdm.h) and backend(#tdm_backend.h) header files + * include #tdm_types.h + * @par Example + * @code + #include //for a frontend user + * @endcode + * @code + #include //for a vendor to implement a backend module + * @endcode + */ + +/** + * @brief The error enumeration + */ typedef enum { - TDM_ERROR_NONE = 0, - TDM_ERROR_BAD_REQUEST = -1, //bad request - TDM_ERROR_OPERATION_FAILED = -2, //operaion failed - TDM_ERROR_INVALID_PARAMETER = -3, //wrong input parameter - TDM_ERROR_PERMISSION_DENIED = -4, //access denied - TDM_ERROR_BUSY = -5, //hardware resource busy - TDM_ERROR_OUT_OF_MEMORY = -6, //no free memory - TDM_ERROR_BAD_MODULE = -7, //bad backend module - TDM_ERROR_NOT_IMPLEMENTED = -8, //not implemented + TDM_ERROR_NONE = 0, /**< none */ + TDM_ERROR_BAD_REQUEST = -1, /**< bad request */ + TDM_ERROR_OPERATION_FAILED = -2, /**< operaion failed */ + TDM_ERROR_INVALID_PARAMETER = -3, /**< wrong input parameter */ + TDM_ERROR_PERMISSION_DENIED = -4, /**< access denied */ + TDM_ERROR_BUSY = -5, /**< hardware resource busy */ + TDM_ERROR_OUT_OF_MEMORY = -6, /**< no free memory */ + TDM_ERROR_BAD_MODULE = -7, /**< bad backend module */ + TDM_ERROR_NOT_IMPLEMENTED = -8, /**< not implemented */ + TDM_ERROR_NO_CAPABILITY = -9, /**< no capability */ } tdm_error; +/** + * @brief The transform enumeration(rotate, flip) + */ typedef enum { - TDM_TRANSFORM_NORMAL = 0, - TDM_TRANSFORM_90 = 1, - TDM_TRANSFORM_180 = 2, - TDM_TRANSFORM_270 = 3, - TDM_TRANSFORM_FLIPPED = 4, - TDM_TRANSFORM_FLIPPED_90 = 5, - TDM_TRANSFORM_FLIPPED_180 = 6, - TDM_TRANSFORM_FLIPPED_270 = 7, - TDM_TRANSFORM_MAX = 8 + TDM_TRANSFORM_NORMAL = 0, /**< no transform */ + TDM_TRANSFORM_90 = 1, /**< rotate 90 */ + TDM_TRANSFORM_180 = 2, /**< rotate 180 */ + TDM_TRANSFORM_270 = 3, /**< rotate 270 */ + TDM_TRANSFORM_FLIPPED = 4, /**< no rotate and horizontal flip */ + TDM_TRANSFORM_FLIPPED_90 = 5, /**< rotate 90 and horizontal flip */ + TDM_TRANSFORM_FLIPPED_180 = 6, /**< rotate 180 and horizontal flip */ + TDM_TRANSFORM_FLIPPED_270 = 7, /**< rotate 270 and horizontal flip */ } tdm_transform; +/** + * @brief The output connection status enumeration + */ typedef enum { - TDM_OUTPUT_CONN_STATUS_DISCONNECTED, - TDM_OUTPUT_CONN_STATUS_CONNECTED, - TDM_OUTPUT_CONN_STATUS_MODE_SETTED, - TDM_OUTPUT_CONN_STATUS_MAX, + TDM_OUTPUT_CONN_STATUS_DISCONNECTED, /**< output disconnected */ + TDM_OUTPUT_CONN_STATUS_CONNECTED, /**< output connected */ + TDM_OUTPUT_CONN_STATUS_MODE_SETTED, /**< output connected and setted a mode */ } tdm_output_conn_status; -/* bit compatible with the libdrm definitions. */ +/** + * @brief The output connection status enumeration + * @detail bit compatible with the libdrm definitions. + */ typedef enum { - TDM_OUTPUT_TYPE_Unknown, - TDM_OUTPUT_TYPE_VGA, - TDM_OUTPUT_TYPE_DVII, - TDM_OUTPUT_TYPE_DVID, - TDM_OUTPUT_TYPE_DVIA, - TDM_OUTPUT_TYPE_Composite, - TDM_OUTPUT_TYPE_SVIDEO, - TDM_OUTPUT_TYPE_LVDS, - TDM_OUTPUT_TYPE_Component, - TDM_OUTPUT_TYPE_9PinDIN, - TDM_OUTPUT_TYPE_DisplayPort, - TDM_OUTPUT_TYPE_HDMIA, - TDM_OUTPUT_TYPE_HDMIB, - TDM_OUTPUT_TYPE_TV, - TDM_OUTPUT_TYPE_eDP, - TDM_OUTPUT_TYPE_VIRTUAL, - TDM_OUTPUT_TYPE_DSI, - TDM_OUTPUT_TYPE_MAX, + TDM_OUTPUT_TYPE_Unknown, /**< unknown */ + TDM_OUTPUT_TYPE_VGA, /**< VGA connection */ + TDM_OUTPUT_TYPE_DVII, /**< DVII connection */ + TDM_OUTPUT_TYPE_DVID, /**< DVID connection */ + TDM_OUTPUT_TYPE_DVIA, /**< DVIA connection */ + TDM_OUTPUT_TYPE_Composite, /**< Composite connection */ + TDM_OUTPUT_TYPE_SVIDEO, /**< SVIDEO connection */ + TDM_OUTPUT_TYPE_LVDS, /**< LVDS connection */ + TDM_OUTPUT_TYPE_Component, /**< Component connection */ + TDM_OUTPUT_TYPE_9PinDIN, /**< 9PinDIN connection */ + TDM_OUTPUT_TYPE_DisplayPort, /**< DisplayPort connection */ + TDM_OUTPUT_TYPE_HDMIA, /**< HDMIA connection */ + TDM_OUTPUT_TYPE_HDMIB, /**< HDMIB connection */ + TDM_OUTPUT_TYPE_TV, /**< TV connection */ + TDM_OUTPUT_TYPE_eDP, /**< eDP connection */ + TDM_OUTPUT_TYPE_VIRTUAL, /**< Virtual connection for WiFi Display */ + TDM_OUTPUT_TYPE_DSI, /**< DSI connection */ } tdm_output_type; -/* bit compatible with the drm definitions. */ +/** + * @brief The DPMS enumeration + * @detail bit compatible with the libdrm definitions. + */ typedef enum { - TDM_OUTPUT_DPMS_ON, - TDM_OUTPUT_DPMS_STANDBY, - TDM_OUTPUT_DPMS_SUSPEND, - TDM_OUTPUT_DPMS_OFF, - TDM_OUTPUT_DPMS_MAX, + TDM_OUTPUT_DPMS_ON, /**< On */ + TDM_OUTPUT_DPMS_STANDBY, /**< StandBy */ + TDM_OUTPUT_DPMS_SUSPEND, /**< Suspend */ + TDM_OUTPUT_DPMS_OFF, /**< Off */ } tdm_output_dpms; +/** + * @brief The layer capability enumeration + * @details + * A layer can have one of CURSOR, PRIMARY and OVERLAY capability. And a layer + * also can have one of GRAPHIC and VIDEO capability. And a layer also can have + * SCALE and TRANSFORM capability.\n + * @par Example + * @code + //For example + capabilities = TDM_LAYER_CAPABILITY_PRIMARY | TDM_LAYER_CAPABILITY_GRAPHIC; + capabilities = TDM_LAYER_CAPABILITY_OVERLAY | TDM_LAYER_CAPABILITY_GRAPHIC | TDM_LAYER_CAPABILITY_SCALE; + capabilities = TDM_LAYER_CAPABILITY_OVERLAY | TDM_LAYER_CAPABILITY_GRAPHIC | TDM_LAYER_CAPABILITY_SCALE | TDM_LAYER_CAPABILITY_TRANSFORM; + capabilities = TDM_LAYER_CAPABILITY_CURSOR | TDM_LAYER_CAPABILITY_GRAPHIC; + capabilities = TDM_LAYER_CAPABILITY_OVERLAY | TDM_LAYER_CAPABILITY_VIDEO; + * @endcode + * @remark + * - When a video plays, in most of cases, video buffers will be displayed to + * a GRAPHIC layer after converting RGB buffers via PP. In this case, a backend + * module doesn't need to offer VIDEO layer. + * - But in case that s vendor wants to handle a video by their own way, + * a backend module offer VIDEO layers. And a display server will pass a video + * buffer to a VIDEO layer without converting. + * - GRAPHIC layers have fixed zpos. But the zpos of VIDEO layer will be decided + * by a backend module side. + * - The frontend only can set the relative zpos to + * VIDEO layers via layer_set_video_pos() function of #tdm_func_display + */ typedef enum { - TDM_LAYER_CAPABILITY_CURSOR = (1<<0), - TDM_LAYER_CAPABILITY_PRIMARY = (1<<1), - TDM_LAYER_CAPABILITY_OVERLAY = (1<<2), - TDM_LAYER_CAPABILITY_SCALE = (1<<4), - TDM_LAYER_CAPABILITY_TRANSFORM = (1<<5), - TDM_LAYER_CAPABILITY_GRAPHIC = (1<<8), - TDM_LAYER_CAPABILITY_VIDEO = (1<<9), + TDM_LAYER_CAPABILITY_CURSOR = (1<<0), /**< cursor */ + TDM_LAYER_CAPABILITY_PRIMARY = (1<<1), /**< primary */ + TDM_LAYER_CAPABILITY_OVERLAY = (1<<2), /**< overlay */ + TDM_LAYER_CAPABILITY_GRAPHIC = (1<<4), /**< graphic */ + TDM_LAYER_CAPABILITY_VIDEO = (1<<5), /**< video */ + TDM_LAYER_CAPABILITY_SCALE = (1<<8), /**< if a layer has scale capability */ + TDM_LAYER_CAPABILITY_TRANSFORM = (1<<9), /**< if a layer has transform capability */ } tdm_layer_capability; +/** + * @brief The pp capability enumeration + */ typedef enum { - TDM_PP_CAPABILITY_SYNC = (1<<0), - TDM_PP_CAPABILITY_ASYNC = (1<<1), - TDM_PP_CAPABILITY_SCALE = (1<<4), - TDM_PP_CAPABILITY_TRANSFORM = (1<<5), + TDM_PP_CAPABILITY_SYNC = (1<<0), /**< The pp device supports synchronous operation */ + TDM_PP_CAPABILITY_ASYNC = (1<<1), /**< The pp device supports asynchronous operation */ + TDM_PP_CAPABILITY_SCALE = (1<<4), /**< The pp device supports scale operation */ + TDM_PP_CAPABILITY_TRANSFORM = (1<<5), /**< The pp device supports transform operation */ } tdm_pp_capability; +/** + * @brief The capture capability enumeration + */ typedef enum { - TDM_CAPTURE_CAPABILITY_OUTPUT = (1<<0), - TDM_CAPTURE_CAPABILITY_LAYER = (1<<1), - TDM_CAPTURE_CAPABILITY_SCALE = (1<<4), - TDM_CAPTURE_CAPABILITY_TRANSFORM = (1<<5), + TDM_CAPTURE_CAPABILITY_OUTPUT = (1<<0), /**< The capture device supports to dump a output */ + TDM_CAPTURE_CAPABILITY_LAYER = (1<<1), /**< The capture device supports to dump a layer */ + TDM_CAPTURE_CAPABILITY_SCALE = (1<<4), /**< The capture device supports scale operation */ + TDM_CAPTURE_CAPABILITY_TRANSFORM = (1<<5), /**< The capture device supports transform operation */ } tdm_capture_capability; -/* bit compatible with the drm definitions. */ +/** + * @brief The output mode type enumeration + * @detail bit compatible with the libdrm definitions. + */ typedef enum { TDM_OUTPUT_MODE_TYPE_BUILTIN = (1<<0), @@ -150,7 +213,10 @@ typedef enum TDM_OUTPUT_MODE_TYPE_DRIVER = (1<<6), } tdm_output_mode_type; -/* bit compatible with the drm definitions. */ +/** + * @brief The output mode flag enumeration + * @detail bit compatible with the libdrm definitions. + */ typedef enum { TDM_OUTPUT_MODE_FLAG_PHSYNC = (1<<0), @@ -169,6 +235,9 @@ typedef enum TDM_OUTPUT_MODE_FLAG_CLKDIV2 = (1<<13), } tdm_output_mode_flag; +/** + * @brief The output mode structure + */ typedef struct _tdm_output_mode { unsigned int width; @@ -179,17 +248,26 @@ typedef struct _tdm_output_mode char name[TDM_NAME_LEN]; } tdm_output_mode; +/** + * @brief The property structure + */ typedef struct _tdm_prop { unsigned int id; char name[TDM_NAME_LEN]; } tdm_prop; +/** + * @brief The size structure + */ typedef struct _tdm_size { - unsigned int h; - unsigned int v; + unsigned int h; /**< width */ + unsigned int v; /**< height */ } tdm_size; +/** + * @brief The pos structure + */ typedef struct _tdm_pos { unsigned int x; @@ -198,6 +276,9 @@ typedef struct _tdm_pos unsigned int h; } tdm_pos; +/** + * @brief The value union + */ typedef union { void *ptr; @@ -207,6 +288,9 @@ typedef union uint64_t u64; } tdm_value; +/** + * @brief The info config structure + */ typedef struct _tdm_info_config { tdm_size size; @@ -214,6 +298,9 @@ typedef struct _tdm_info_config tbm_format format; } tdm_info_config; +/** + * @brief The layer info structre + */ typedef struct _tdm_info_layer { tdm_info_config src_config; @@ -221,6 +308,9 @@ typedef struct _tdm_info_layer tdm_transform transform; } tdm_info_layer; +/** + * @brief The pp info structre + */ typedef struct _tdm_info_pp { tdm_info_config src_config; @@ -230,6 +320,9 @@ typedef struct _tdm_info_pp int flags; } tdm_info_pp; +/** + * @brief The capture info structre + */ typedef struct _tdm_info_capture { tdm_info_config dst_config; @@ -239,14 +332,42 @@ typedef struct _tdm_info_capture int flags; } tdm_info_capture; +/** + * @brief The tdm display object + */ typedef void tdm_display; + +/** + * @brief The tdm output object + */ typedef void tdm_output; + +/** + * @brief The tdm layer object + */ typedef void tdm_layer; + +/** + * @brief The tdm capture object + */ typedef void tdm_capture; + +/** + * @brief The tdm pp object + */ typedef void tdm_pp; +/** + * @brief The vblank handler + * @see output_set_vblank_handler() function of #tdm_func_display + */ typedef void (*tdm_output_vblank_handler)(tdm_output *output, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data); + +/** + * @brief The commit handler + * @see output_set_commit_handler() function of #tdm_func_display + */ typedef void (*tdm_output_commit_handler)(tdm_output *output, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data); diff --git a/src/tdm_capture.c b/src/tdm_capture.c index 92e306a..a1b91f3 100644 --- a/src/tdm_capture.c +++ b/src/tdm_capture.c @@ -92,7 +92,7 @@ tdm_capture_create_output_internal(tdm_private_output *private_output, tdm_error { TDM_ERR("no capture capability"); if (error) - *error = TDM_ERROR_BAD_REQUEST; + *error = TDM_ERROR_NO_CAPABILITY; return NULL; } @@ -158,7 +158,7 @@ tdm_capture_create_layer_internal(tdm_private_layer *private_layer, tdm_error *e { TDM_ERR("no capture capability"); if (error) - *error = TDM_ERROR_BAD_REQUEST; + *error = TDM_ERROR_NO_CAPABILITY; return NULL; } diff --git a/src/tdm_display.c b/src/tdm_display.c index f904a18..cad2151 100644 --- a/src/tdm_display.c +++ b/src/tdm_display.c @@ -116,6 +116,13 @@ tdm_display_get_pp_capabilities(tdm_display *dpy, tdm_pp_capability *capabilitie pthread_mutex_lock(&private_display->lock); + if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) + { + TDM_ERR("no pp capability"); + pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_NO_CAPABILITY; + } + *capabilities = private_display->caps_pp.capabilities; pthread_mutex_unlock(&private_display->lock); @@ -133,6 +140,13 @@ tdm_display_get_pp_available_formats(tdm_display *dpy, const tbm_format **format pthread_mutex_lock(&private_display->lock); + if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) + { + TDM_ERR("no pp capability"); + pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_NO_CAPABILITY; + } + *formats = (const tbm_format*)private_display->caps_pp.formats; *count = private_display->caps_pp.format_count; @@ -149,6 +163,13 @@ tdm_display_get_pp_available_size(tdm_display *dpy, int *min_w, int *min_h, pthread_mutex_lock(&private_display->lock); + if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) + { + TDM_ERR("no pp capability"); + pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_NO_CAPABILITY; + } + if (min_w) *min_w = private_display->caps_pp.min_w; if (min_h) @@ -174,6 +195,13 @@ tdm_display_get_capture_capabilities(tdm_display *dpy, tdm_capture_capability *c pthread_mutex_lock(&private_display->lock); + if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) + { + TDM_ERR("no capture capability"); + pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_NO_CAPABILITY; + } + *capabilities = private_display->caps_capture.capabilities; pthread_mutex_unlock(&private_display->lock); @@ -191,6 +219,13 @@ tdm_display_get_catpure_available_formats(tdm_display *dpy, const tbm_format **f pthread_mutex_lock(&private_display->lock); + if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) + { + TDM_ERR("no capture capability"); + pthread_mutex_unlock(&private_display->lock); + return TDM_ERROR_NO_CAPABILITY; + } + *formats = (const tbm_format*)private_display->caps_capture.formats; *count = private_display->caps_capture.format_count; @@ -782,8 +817,10 @@ tdm_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value) tdm_func_display *func_display; OUTPUT_FUNC_ENTRY(); - TDM_RETURN_VAL_IF_FAIL(dpms_value >= TDM_OUTPUT_DPMS_ON, TDM_ERROR_INVALID_PARAMETER); - TDM_RETURN_VAL_IF_FAIL(dpms_value < TDM_OUTPUT_DPMS_MAX, TDM_ERROR_INVALID_PARAMETER); + if (dpms_value < TDM_OUTPUT_DPMS_ON) + dpms_value = TDM_OUTPUT_DPMS_ON; + else if (dpms_value > TDM_OUTPUT_DPMS_OFF) + dpms_value = TDM_OUTPUT_DPMS_OFF; pthread_mutex_lock(&private_display->lock); diff --git a/src/tdm_pp.c b/src/tdm_pp.c index 492db45..bf83342 100644 --- a/src/tdm_pp.c +++ b/src/tdm_pp.c @@ -91,7 +91,7 @@ tdm_pp_create_internal(tdm_private_display *private_display, tdm_error *error) { TDM_ERR("no pp capability"); if (error) - *error = TDM_ERROR_BAD_REQUEST; + *error = TDM_ERROR_NO_CAPABILITY; return NULL; } diff --git a/src/tdm_private.h b/src/tdm_private.h index 1a9df49..98e5c07 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -57,6 +57,11 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. extern "C" { #endif +/** + * @file tdm_private.h + * @brief The private header file for a frontend library + */ + #undef EXTERN #undef DEPRECATED #undef INTERN -- 2.7.4 From 7fad99cf6e02e8ac725a1420a591b6894d844337 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 30 Dec 2015 10:35:49 +0900 Subject: [PATCH 11/16] fix doxygen bug Change-Id: Iee68da29728dcc907b589af08dfa5d7f59632e15 --- doc/Doxyfile | 313 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/tdm.h | 4 +- include/tdm_backend.h | 2 +- include/tdm_types.h | 12 +- 4 files changed, 323 insertions(+), 8 deletions(-) create mode 100644 doc/Doxyfile diff --git a/doc/Doxyfile b/doc/Doxyfile new file mode 100644 index 0000000..a6a2087 --- /dev/null +++ b/doc/Doxyfile @@ -0,0 +1,313 @@ +# Doxyfile 1.8.6 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +DOXYFILE_ENCODING = UTF-8 +PROJECT_NAME = "libtdm" +PROJECT_NUMBER = +PROJECT_BRIEF = +PROJECT_LOGO = +OUTPUT_DIRECTORY = doc +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +QT_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 4 +ALIASES += comment{1}="/* \1 */" +TCL_SUBST = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +OPTIMIZE_FOR_FORTRAN = NO +OPTIMIZE_OUTPUT_VHDL = NO +EXTENSION_MAPPING = +MARKDOWN_SUPPORT = YES +AUTOLINK_SUPPORT = YES +BUILTIN_STL_SUPPORT = NO +CPP_CLI_SUPPORT = NO +SIP_SUPPORT = NO +IDL_PROPERTY_SUPPORT = YES +DISTRIBUTE_GROUP_DOC = NO +SUBGROUPING = YES +INLINE_GROUPED_CLASSES = NO +INLINE_SIMPLE_STRUCTS = NO +TYPEDEF_HIDES_STRUCT = NO +LOOKUP_CACHE_SIZE = 0 +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_PACKAGE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +EXTRACT_ANON_NSPACES = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +SHOW_GROUPED_MEMB_INC = NO +FORCE_LOCAL_INCLUDES = NO +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_MEMBERS_CTORS_1ST = NO +SORT_GROUP_NAMES = NO +SORT_BY_SCOPE_NAME = NO +STRICT_PROTO_MATCHING = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_FILES = YES +SHOW_NAMESPACES = YES +FILE_VERSION_FILTER = +LAYOUT_FILE = +CITE_BIB_FILES = +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = \ + include/tdm.h \ + include/tdm_backend.h \ + include/tdm_list.h \ + include/tdm_log.h \ + include/tdm_types.h +INPUT_ENCODING = UTF-8 +FILE_PATTERNS = +RECURSIVE = NO +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXCLUDE_SYMBOLS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +FILTER_SOURCE_PATTERNS = +USE_MDFILE_AS_MAINPAGE = +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +REFERENCES_LINK_SOURCE = YES +SOURCE_TOOLTIPS = YES +USE_HTAGS = NO +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_EXTRA_STYLESHEET = +HTML_EXTRA_FILES = +HTML_COLORSTYLE_HUE = 220 +HTML_COLORSTYLE_SAT = 100 +HTML_COLORSTYLE_GAMMA = 80 +HTML_TIMESTAMP = YES +HTML_DYNAMIC_SECTIONS = NO +HTML_INDEX_NUM_ENTRIES = 100 +GENERATE_DOCSET = NO +DOCSET_FEEDNAME = "Doxygen generated docs" +DOCSET_BUNDLE_ID = org.doxygen.Project +DOCSET_PUBLISHER_ID = org.doxygen.Publisher +DOCSET_PUBLISHER_NAME = Publisher +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +CHM_INDEX_ENCODING = +BINARY_TOC = NO +TOC_EXPAND = NO +GENERATE_QHP = NO +QCH_FILE = +QHP_NAMESPACE = org.doxygen.Project +QHP_VIRTUAL_FOLDER = doc +QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = +QHG_LOCATION = +GENERATE_ECLIPSEHELP = NO +ECLIPSE_DOC_ID = org.doxygen.Project +DISABLE_INDEX = NO +GENERATE_TREEVIEW = NO +ENUM_VALUES_PER_LINE = 4 +TREEVIEW_WIDTH = 250 +EXT_LINKS_IN_WINDOW = NO +FORMULA_FONTSIZE = 10 +FORMULA_TRANSPARENT = YES +USE_MATHJAX = NO +MATHJAX_FORMAT = HTML-CSS +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest +MATHJAX_EXTENSIONS = +MATHJAX_CODEFILE = +SEARCHENGINE = YES +SERVER_BASED_SEARCH = NO +EXTERNAL_SEARCH = NO +SEARCHENGINE_URL = +SEARCHDATA_FILE = searchdata.xml +EXTERNAL_SEARCH_ID = +EXTRA_SEARCH_MAPPINGS = +#--------------------------------------------------------------------------- +# Configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4 +EXTRA_PACKAGES = +LATEX_HEADER = +LATEX_FOOTER = +LATEX_EXTRA_FILES = +PDF_HYPERLINKS = YES +USE_PDFLATEX = YES +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +LATEX_SOURCE_CODE = NO +LATEX_BIB_STYLE = plain +#--------------------------------------------------------------------------- +# Configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# Configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# Configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# Configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- +GENERATE_DOCBOOK = NO +DOCBOOK_OUTPUT = docbook +#--------------------------------------------------------------------------- +# Configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# Configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration options related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +EXTERNAL_PAGES = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +MSCGEN_PATH = +DIA_PATH = +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +DOT_NUM_THREADS = 0 +DOT_FONTNAME = Helvetica +DOT_FONTSIZE = 10 +DOT_FONTPATH = +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +UML_LIMIT_NUM_FIELDS = 10 +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +CALLER_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +INTERACTIVE_SVG = NO +DOT_PATH = +DOTFILE_DIRS = +MSCFILE_DIRS = +DIAFILE_DIRS = +DOT_GRAPH_MAX_NODES = 50 +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = YES +GENERATE_LEGEND = YES +DOT_CLEANUP = YES diff --git a/include/tdm.h b/include/tdm.h index dc1719f..3069b3b 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -327,6 +327,7 @@ tdm_error tdm_output_get_property(tdm_output *output, unsigned int id, tdm_va * @param[in] output A output object * @param[in] interval vblank interval * @param[in] sync 0: asynchronous, 1:synchronous + * @param[in] func A user vblank handler * @param[in] user_data The user data * @return #TDM_ERROR_NONE if success. Otherwise, error value. * @see #tdm_output_vblank_handler @@ -339,6 +340,7 @@ tdm_error tdm_output_wait_vblank(tdm_output *output, int interval, int sync, * will be called. * @param[in] output A output object * @param[in] sync 0: asynchronous, 1:synchronous + * @param[in] func A user commit handler * @param[in] user_data The user data * @return #TDM_ERROR_NONE if success. Otherwise, error value. */ @@ -507,7 +509,7 @@ tdm_error tdm_layer_set_video_pos(tdm_layer *layer, int zpos); /** * @brief Create a capture object of a layer object - * @param[in] output A output object + * @param[in] layer A layer object * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. * @return A capture object * @see tdm_capture_destroy diff --git a/include/tdm_backend.h b/include/tdm_backend.h index 829a288..a60441c 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -448,7 +448,7 @@ typedef struct _tdm_func_display * @param[in] layer A layer object * @param[in] zpos z-order * @return #TDM_ERROR_NONE if success. Otherwise, error value. - * @see @tdm_layer_capability + * @see tdm_layer_capability */ tdm_error (*layer_set_video_pos)(tdm_layer *layer, int zpos); diff --git a/include/tdm_types.h b/include/tdm_types.h index b48e8bc..33c8488 100644 --- a/include/tdm_types.h +++ b/include/tdm_types.h @@ -48,8 +48,8 @@ extern "C" { * @file tdm_types.h * @brief The header file which defines Enumerations and Structures for frontend and backend. * @details - * Both frontend(#tdm.h) and backend(#tdm_backend.h) header files - * include #tdm_types.h + * Both frontend(@ref tdm.h) and backend(@ref tdm_backend.h) header files + * include @ref tdm_types.h * @par Example * @code #include //for a frontend user @@ -103,7 +103,7 @@ typedef enum /** * @brief The output connection status enumeration - * @detail bit compatible with the libdrm definitions. + * @details bit compatible with the libdrm definitions. */ typedef enum { @@ -128,7 +128,7 @@ typedef enum /** * @brief The DPMS enumeration - * @detail bit compatible with the libdrm definitions. + * @details bit compatible with the libdrm definitions. */ typedef enum { @@ -200,7 +200,7 @@ typedef enum /** * @brief The output mode type enumeration - * @detail bit compatible with the libdrm definitions. + * @details bit compatible with the libdrm definitions. */ typedef enum { @@ -215,7 +215,7 @@ typedef enum /** * @brief The output mode flag enumeration - * @detail bit compatible with the libdrm definitions. + * @details bit compatible with the libdrm definitions. */ typedef enum { -- 2.7.4 From 88d3de8a4100afe907f9e873c2d037e5e6c99396 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 30 Dec 2015 11:41:43 +0900 Subject: [PATCH 12/16] add README file Change-Id: I54495cefc4dcf7d2467a6bf5e8aaf4d6675a70e5 --- README | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 README diff --git a/README b/README new file mode 100644 index 0000000..d425bb8 --- /dev/null +++ b/README @@ -0,0 +1,22 @@ +libtdm - Tizen Display Manager + +It's the display HAL layer for tizen display server. It offers the frontend +APIs(tdm.h) for a frontend user and the abstraction interface(tdm_backend.h) +for a hardware vendor. + +TDM consists of display/output/layer/pp/capture objects. A frontend user can +get the output/layer/pp/capture hardware information with each object. +Basically, TDM supposes that all hardware devices have fixed outputs and layers. + +All changes of output/layer/pp/capture objects are applied when committed. + +TDM has its own buffer release mechanism to let an user know when a TDM buffer +becomes available for a next job. + +Doxygen document +---------------- +- The doxygen document is created in the "doc/html" directory. +- How to create the doxygen document + $ doxygen doc/Doxyfile +- How to view the doxygen document + $ firefox doc/html/index.html -- 2.7.4 From a82fd8f1bd857ca77d455da096af8adbb9f9f7aa Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 30 Dec 2015 15:00:48 +0900 Subject: [PATCH 13/16] modify doxygen Change-Id: Iad1714e3224f39e4b77452e2fa4456949857711b --- .gitignore | 3 +- doc/Doxyfile | 1 + doc/tdm_doc.h | 141 +++++++++++++++++++++++++++ include/tdm.h | 23 +---- include/tdm_backend.h | 262 ++++++++++++++++++++++++++++++++++---------------- include/tdm_types.h | 4 - 6 files changed, 322 insertions(+), 112 deletions(-) create mode 100644 doc/tdm_doc.h diff --git a/.gitignore b/.gitignore index bd846ae..49d27e8 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,5 @@ stamp-h1 *.la *.lo *~ - +html/ +latex/ diff --git a/doc/Doxyfile b/doc/Doxyfile index a6a2087..47f90d0 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -98,6 +98,7 @@ WARN_LOGFILE = # Configuration options related to the input files #--------------------------------------------------------------------------- INPUT = \ + doc/tdm_doc.h \ include/tdm.h \ include/tdm_backend.h \ include/tdm_list.h \ diff --git a/doc/tdm_doc.h b/doc/tdm_doc.h new file mode 100644 index 0000000..3bdc3e3 --- /dev/null +++ b/doc/tdm_doc.h @@ -0,0 +1,141 @@ +/************************************************************************** + +libtdm + +Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved. + +Contact: Eunchul Kim , + JinYoung Jeon , + Taeheon Kim , + YoungJun Cho , + SooChan Lim , + Boram Park + +Permission is hereby granted, free of charge, to any person obtaining a +copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sub license, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice (including the +next paragraph) shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +**************************************************************************/ + +#ifndef _TDM_DOC_H_ +#define _TDM_DOC_H_ + +/** + * @mainpage TDM + * @author Boram Park, boram1288.park@samsung.com + * @date Dec 30, 2015 + * @version 1.0.0 + * @par Introduction + * TDM stands for Tizen Display Manager. It's the display HAL layer for tizen + * display server. It offers the frontend APIs(@ref tdm.h) for a frontend user + * and the abstraction interface(@ref tdm_backend.h) for a hardware vendor. + * \n + * @par Objects + * TDM consists of display/output/layer/pp/capture objects. A frontend user can + * get the output/layer/pp/capture hardware information with each object. + * Basically, TDM supposes that all display devices have fixed outputs and + * layers. A frontend user can get these outputs and layers with + * #tdm_display_get_output_count, #tdm_display_get_output, #tdm_output_get_layer_count + * and #tdm_output_get_layer. To get a pp/capture object, however, a frontend + * user need to create a object with #tdm_display_create_pp, #tdm_output_create_capture + * and #tdm_layer_create_capture if available.\n + * \n + * All changes of output/layer/pp/capture objects are applied when committed. + * See #tdm_output_commit, #tdm_pp_commit and #tdm_capture_commit. + * \n + * @par Buffer management + * TDM has its own buffer release mechanism to let an user know when a TDM buffer + * becomes available for a next job. A frontend user can add a user release handler + * to a TDM buffer with #tdm_buffer_add_release_handler, and this handler will be + * called when it's disappered from screen or when pp/capture operation is done. + * \n + * @par Implementing a TDM backend module(for a hardware vendor) + * A backend module @b SHOULD define the global data symbol of which name is + * @b "tdm_backend_module_data". TDM will read this symbol, @b "tdm_backend_module_data", + * at the initial time and call init() function of #tdm_backend_module. + * A backend module at least @b SHOULD register the #tdm_func_display functions + * to a display object with #tdm_backend_register_func_display() function in initial time.\n + * @code + #include + + static tdm_func_display drm_func_display = + { + drm_display_get_capabilitiy, + ... + drm_display_get_outputs, + ... + drm_output_get_capability, + drm_output_get_layers, + ... + drm_layer_get_capability, + ... + }; + + static tdm_drm_data *drm_data; + + tdm_backend_data* + tdm_drm_init(tdm_display *dpy, tdm_error *error) + { + ... + drm_data = calloc(1, sizeof(tdm_drm_data)); + ... + ret = tdm_backend_register_func_display(dpy, &drm_func_display); + if (ret != TDM_ERROR_NONE) + goto failed; + ... + return (tdm_backend_data*)drm_data; + } + + void + tdm_drm_deinit(tdm_backend_data *bdata) + { + ... + free(bdata); + } + + tdm_backend_module tdm_backend_module_data = + { + "drm", + "Samsung", + TDM_BACKEND_ABI_VERSION, + tdm_drm_init, + tdm_drm_deinit + }; + * @endcode + * \n + * A sample backend source code can be downloaded. + * @code + $ git clone ssh://{user_id}@review.tizen.org:29418/platform/core/uifw/libtdm-drm + * @endcode + * \n + * After loading a TDM backend module, TDM will call @b display_get_capabilitiy(), + * @b display_get_outputs(), @b output_get_capability(), @b output_get_layers(), + * @b layer_get_capability() functions to get the hardware information. That is, + * a TDM backend module @b SHOULD implement these 5 functions basically.\n + * \n + * In addition, if a hardware has a memory-to-memory converting device and the + * capture device, a backend module can register the #tdm_func_pp functions and + * #tdm_func_capture functions with #tdm_backend_register_func_pp() and + * #tdm_backend_register_func_capture().\n + * \n + * The @b "Remarks" part of explains what things should be + * careful for vendor to implement a TDM backend module. + */ + +#endif /* _TDM_DOC_H_ */ diff --git a/include/tdm.h b/include/tdm.h index 3069b3b..918de10 100644 --- a/include/tdm.h +++ b/include/tdm.h @@ -53,27 +53,6 @@ extern "C" { * @code #include //for a frontend user * @endcode - * @details - * TDM stands for Tizen Display Manager. It's the display HAL layer for tizen - * display server. It offers the frontend APIs(@ref tdm.h) for a frontend user - * and the abstraction interface(@ref tdm_backend.h) for a hardware vendor.\n - * \n - * TDM consists of display/output/layer/pp/capture objects. A frontend user can - * get the output/layer/pp/capture hardware information with each object. - * Basically, TDM supposes that all hardware devices have fixed outputs and - * layers. A frontend user can get these outputs and layers with - * #tdm_display_get_output_count, #tdm_display_get_output, #tdm_output_get_layer_count - * and #tdm_output_get_layer. To get a pp/capture object, however, a frontend - * user need to create a object with #tdm_display_create_pp, #tdm_output_create_capture - * and #tdm_layer_create_capture if available.\n - * \n - * All changes of output/layer/pp/capture objects are applied when commiting. - * See #tdm_output_commit, #tdm_pp_commit and #tdm_capture_commit.\n - * \n - * TDM has its own buffer release mechanism to let an user know when a TDM buffer - * becomes available for a next job. A frontend user can add a user release handler - * to a TDM buffer with #tdm_buffer_add_release_handler, and this handler will be - * called when it's disappered from screen or when pp/capture operation is done. */ /** @@ -420,7 +399,7 @@ tdm_error tdm_layer_get_available_properties(tdm_layer *layer, const tdm_prop * - But the zpos of VIDEO layers will be decided by a backend module side. * - A frontend user only can set the relative zpos to VIDEO layers via #tdm_layer_set_video_pos * - The zpos of video layers is less than GRAPHIC layers or more than GRAPHIC - * layers. ie, -1, -2, 4, 5 (if 0 <= GRAPHIC layer's zpos < 4). + * layers. ie, ..., -2, -1, 4, 5, ... (if 0 <= GRAPHIC layer's zpos < 4). * @param[in] layer A layer object * @param[out] zpos The zpos * @return #TDM_ERROR_NONE if success. Otherwise, error value. diff --git a/include/tdm_backend.h b/include/tdm_backend.h index a60441c..645d0de 100644 --- a/include/tdm_backend.h +++ b/include/tdm_backend.h @@ -58,15 +58,12 @@ extern "C" { * @details * The init() function of #tdm_backend_module returns the backend module data. * And it will be passed to display functions of #tdm_func_display. - * @remark It @b SHOULD be freed in the deinit() function of #tdm_backend_module. * @see tdm_backend_module, tdm_backend_module */ typedef void tdm_backend_data; /** * @brief The display capabilities structure of a backend module - * @remark A backend module @b SHOULD fill this structure to let frontend know the - * backend display capabilities. * @see The display_get_capabilitiy() function of #tdm_func_display */ typedef struct _tdm_caps_display @@ -76,11 +73,6 @@ typedef struct _tdm_caps_display /** * @brief The capabilities structure of a output object - * @details - * If a output device has the size restriction, a backend module can let a user - * know it with min_w, min_h, max_w, max_h, preferred_align variables. - * @remark A backend module @b SHOULD fill this structure to let frontend know the - * backend output capabilities. * @see The output_get_capability() function of #tdm_func_display */ typedef struct _tdm_caps_output @@ -90,10 +82,10 @@ typedef struct _tdm_caps_output unsigned int type_id; /**< The connection type id */ unsigned int mode_count; /**< The count of available modes */ - tdm_output_mode *modes; /**< The array of available modes */ + tdm_output_mode *modes; /**< The @b newly-allocated array of modes. will be freed in frontend. */ unsigned int prop_count; /**< The count of available properties */ - tdm_prop *props; /**< The array of available properties */ + tdm_prop *props; /**< The @b newly-allocated array of properties. will be freed in frontend. */ unsigned int mmWidth; /**< The physical width (milimeter) */ unsigned int mmHeight; /**< The physical height (milimeter) */ @@ -108,8 +100,6 @@ typedef struct _tdm_caps_output /** * @brief The capabilities structure of a layer object - * @remark A backend module @b SHOULD fill this structure to let frontend know the - * backend layer capabilities. * @see The layer_get_capability() function of #tdm_func_display */ typedef struct _tdm_caps_layer @@ -118,27 +108,28 @@ typedef struct _tdm_caps_layer /** * The z-order - * - The zpos of GRAPHIC layers starts from 0, and it is @b non-changeable.\n - * - The zpos of VIDEO layers is less than graphic layers or more than graphic layers. - * ie, -1, -2, 4, 5 (if 0 <= GRAPHIC layer's zpos < 4).. It is @b changeable - * by layer_set_video_pos() function of #tdm_func_display + * GRAPHIC layers are non-changeable. The zpos of GRAPHIC layers starts + * from 0. If there are 4 GRAPHIC layers, The zpos SHOULD be 0, 1, 2, 3.\n + * But the zpos of VIDEO layer is changeable by layer_set_video_pos() function + * of #tdm_func_display. And The zpos of VIDEO layers is less than GRAPHIC + * layers or more than GRAPHIC layers. + * ie, ..., -2, -1, 4, 5, ... (if 0 <= GRAPHIC layer's zpos < 4). + * The zpos of VIDEO layers is @b relative. It doesn't need to start + * from -1 or 4. Let's suppose that there are two VIDEO layers. + * One has -2 zpos. Another has -4 zpos. Then -2 Video layer is higher + * than -4 VIDEO layer. */ int zpos; unsigned int format_count; /**< The count of available formats */ - tbm_format *formats; /**< The array of available formats */ + tbm_format *formats; /**< The @b newly-allocated array of formats. will be freed in frontend. */ unsigned int prop_count; /**< The count of available properties */ - tdm_prop *props; /**< The array of available properties */ + tdm_prop *props; /**< The @b newly-allocated array of properties. will be freed in frontend. */ } tdm_caps_layer; /** * @brief The capabilities structure of a pp object - * @details - * If a pp device has the size restriction, a backend module can let a user - * know it with min_w, min_h, max_w, max_h, preferred_align variables. - * @remark A backend module @b SHOULD fill this structure to let frontend know the - * backend pp capabilities if pp is available. * @see The display_get_pp_capability() function of #tdm_func_display */ typedef struct _tdm_caps_pp @@ -146,7 +137,7 @@ typedef struct _tdm_caps_pp tdm_pp_capability capabilities; /**< The capabilities of pp */ unsigned int format_count; /**< The count of available formats */ - tbm_format *formats; /**< The array of available formats */ + tbm_format *formats; /**< The @b newly-allocated array. will be freed in frontend. */ int min_w; /**< The minimun width. -1 means "not defined" */ int min_h; /**< The minimun height. -1 means "not defined" */ @@ -157,11 +148,6 @@ typedef struct _tdm_caps_pp /** * @brief The capabilities structure of a capture object - * @details - * If a capture device has the size restriction, a backend module can let a user - * know it with min_w, min_h, max_w, max_h, preferred_align variables. - * @remark A backend module @b SHOULD fill this structure to let frontend know the - * backend capture capabilities if capture is available. * @see The display_get_capture_capability() function of #tdm_func_display */ typedef struct _tdm_caps_capture @@ -169,7 +155,7 @@ typedef struct _tdm_caps_capture tdm_capture_capability capabilities; /**< The capabilities of capture */ unsigned int format_count; /**< The count of available formats */ - tbm_format *formats; /**< The array of available formats */ + tbm_format *formats; /**< The @b newly-allocated array of formats. will be freed in frontend. */ int min_w; /**< The minimun width. -1 means "not defined" */ int min_h; /**< The minimun height. -1 means "not defined" */ @@ -185,63 +171,118 @@ typedef struct _tdm_func_display { /** * @brief Get the display capabilities of a backend module - * @details TDM calls this function at the initial time. And at the update time also. - * #tdm_caps_display containes the max layer count information, etc. * @param[in] bdata The backend module data * @param[out] caps The display capabilities of a backend module * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @remark + * A backend module @b SHOULD implement this function. TDM calls this function + * not only at the initial time, but also at the update time when new output + * is connected.\n + * If a hardware has the restriction of the number of max usable layer count, + * a backend module can set the max count to max_layer_count of #tdm_caps_display + * structure. Otherwise, set -1. */ tdm_error (*display_get_capabilitiy)(tdm_backend_data *bdata, tdm_caps_display *caps); /** * @brief Get the pp capabilities of a backend module - * @details This function can be NULL if a backend module doesn't have the pp capability. - * TDM calls this function at the initial time if available. And at the update time also. - * #tdm_caps_pp containes avaiable formats, size restriction information, etc. * @param[in] bdata The backend module data * @param[out] caps The pp capabilities of a backend module * @return #TDM_ERROR_NONE if success. Otherwise, error value. * @see tdm_backend_register_func_pp + * @remark + * TDM calls this function not only at the initial time, but also at the update + * time when new output is connected.\n + * A backend module doesn't need to implement this function if a hardware + * doesn't have the memory-to-memory converting device. Otherwise, a backend module + * @b SHOULD fill the #tdm_caps_pp data. #tdm_caps_pp contains the hardware + * restriction information which a converting device can handle. ie, format, size, etc. */ tdm_error (*display_get_pp_capability)(tdm_backend_data *bdata, tdm_caps_pp *caps); /** * @brief Get the capture capabilities of a backend module - * @details This function can be NULL if a backend module doesn't have the capture capability. - * TDM calls this function at the initial time if available. And at the update time also. - * #tdm_caps_capture containes avaiable formats, size restriction information, etc. * @param[in] bdata The backend module data * @param[out] caps The capture capabilities of a backend module * @return #TDM_ERROR_NONE if success. Otherwise, error value. * @see tdm_backend_register_func_capture + * @remark + * TDM calls this function not only at the initial time, but also at the update + * time when new output is connected.\n + * A backend module doesn't need to implement this function if a hardware + * doesn't have the capture device. Otherwise, a backend module @b SHOULD fill the + * #tdm_caps_capture data. #tdm_caps_capture contains the hardware restriction + * information which a capture device can handle. ie, format, size, etc. */ tdm_error (*display_get_capture_capability)(tdm_backend_data *bdata, tdm_caps_capture *caps); /** * @brief Get a output array of a backend module - * @details A backend module @b SHOULD return the newly-allocated output array. - * it will be freed in frontend. * @param[in] bdata The backend module data * @param[out] count The count of outputs * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. - * @return A output array which is newly-allocated + * @return A output array which is @b newly-allocated * @see tdm_backend_register_func_capture + * @remark + * A backend module @b SHOULD implement this function. TDM calls this function + * not only at the initial time, but also at the update time when new output + * is connected.\n + * A backend module @b SHOULD return the @b newly-allocated array which contains + * "tdm_output*" data. It will be freed in frontend. + * @par Example + * @code + tdm_output** + drm_display_get_outputs(tdm_backend_data *bdata, int *count, tdm_error *error) + { + tdm_drm_data *drm_data = bdata; + tdm_drm_output_data *output_data = NULL; + tdm_output **outputs; + int i; + + (*count) = 0; + LIST_FOR_EACH_ENTRY(output_data, &drm_data->output_list, link) + (*count)++; + + if ((*count) == 0) + { + if (error) *error = TDM_ERROR_NONE; + return NULL; + } + + // will be freed in frontend + outputs = calloc(*count, sizeof(tdm_drm_output_data*)); + if (!outputs) + { + (*count) = 0; + if (error) *error = TDM_ERROR_OUT_OF_MEMORY; + return NULL; + } + + i = 0; + LIST_FOR_EACH_ENTRY(output_data, &drm_data->output_list, link) + outputs[i++] = output_data; + + if (error) *error = TDM_ERROR_NONE; + + return outputs; + } + * @endcode */ tdm_output **(*display_get_outputs)(tdm_backend_data *bdata, int *count, tdm_error *error); /** * @brief Get the file descriptor of a backend module - * @details If a backend module handles one more fds, a backend module can return epoll's fd - * which is watching backend device fds. * @param[in] bdata The backend module data * @param[out] fd The fd of a backend module * @return #TDM_ERROR_NONE if success. Otherwise, error value. * @see display_handle_events() function of #tdm_func_display + * @remark + * A backend module can return epoll's fd which is watching the backend device one more fds. */ tdm_error (*display_get_fd)(tdm_backend_data *bdata, int *fd); /** - * @brief Handle the events which happen on the fd of a backend module + * @brief Handle the events which happens on the fd of a backend module * @param[in] bdata The backend module data * @return #TDM_ERROR_NONE if success. Otherwise, error value. */ @@ -253,26 +294,38 @@ typedef struct _tdm_func_display * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. * @return A pp object * @see pp_destroy() function of #tdm_func_pp + * @remark + * A backend module doesn't need to implement this function if a hardware + * doesn't have the memory-to-memory converting device. */ tdm_pp* (*display_create_pp)(tdm_backend_data *bdata, tdm_error *error); /** * @brief Get the capabilities of a output object - * #tdm_caps_output containes connection, modes, avaiable properties, size restriction information, etc. * @param[in] output A output object * @param[out] caps The capabilities of a output object * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @remark + * A backend module @b SHOULD implement this function. TDM calls this function + * not only at the initial time, but also at the update time when new output + * is connected.\n + * #tdm_caps_output contains connection status, modes, avaiable properties, + * size restriction information, etc. */ tdm_error (*output_get_capability)(tdm_output *output, tdm_caps_output *caps); /** * @brief Get a layer array of a output object - * @details A backend module @b SHOULD return the newly-allocated layer array. - * it will be freed in frontend. * @param[in] output A output object * @param[out] count The count of layers * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. - * @return A layer array which is newly-allocated + * @return A layer array which is @b newly-allocated + * @remark + * A backend module @b SHOULD implement this function. TDM calls this function + * not only at the initial time, but also at the update time when new output + * is connected.\n + * A backend module @b SHOULD return the @b newly-allocated array which contains + * "tdm_layer*" data. It will be freed in frontend. */ tdm_layer **(*output_get_layers)(tdm_output *output, int *count, tdm_error *error); @@ -296,14 +349,14 @@ typedef struct _tdm_func_display /** * @brief Wait for VBLANK - * @remark After interval vblanks, a backend module @b SHOULD call a user - * vblank handler. * @param[in] output A output object * @param[in] interval vblank interval * @param[in] sync 0: asynchronous, 1:synchronous * @param[in] user_data The user data * @return #TDM_ERROR_NONE if success. Otherwise, error value. - * @see #tdm_output_vblank_handler + * @see output_set_vblank_handler, tdm_output_vblank_handler + * @remark + * A backend module @b SHOULD call a user vblank handler after interval vblanks. */ tdm_error (*output_wait_vblank)(tdm_output *output, int interval, int sync, void *user_data); @@ -317,12 +370,14 @@ typedef struct _tdm_func_display /** * @brief Commit changes for a output object - * @remark After all change of a output object are applied, a backend module - * @b SHOULD call a user commit handler. * @param[in] output A output object * @param[in] sync 0: asynchronous, 1:synchronous * @param[in] user_data The user data * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @see output_set_commit_handler, tdm_output_commit_handler + * @remark + * A backend module @b SHOULD call a user commit handler after all change of + * a output object are applied. */ tdm_error (*output_commit)(tdm_output *output, int sync, void *user_data); @@ -372,15 +427,22 @@ typedef struct _tdm_func_display * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. * @return A capture object * @see capture_destroy() function of #tdm_func_capture + * @remark + * A backend module doesn't need to implement this function if a hardware + * doesn't have the capture device. */ tdm_capture *(*output_create_capture)(tdm_output *output, tdm_error *error); /** * @brief Get the capabilities of a layer object - * #tdm_caps_layer containes avaiable formats/properties, zpos information, etc. * @param[in] layer A layer object * @param[out] caps The capabilities of a layer object * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @remark + * A backend module @b SHOULD implement this function. TDM calls this function + * not only at the initial time, but also at the update time when new output + * is connected.\n + * #tdm_caps_layer contains avaiable formats/properties, zpos information, etc. */ tdm_error (*layer_get_capability)(tdm_layer *layer, tdm_caps_layer *caps); @@ -404,12 +466,13 @@ typedef struct _tdm_func_display /** * @brief Set the geometry information to a layer object - * @details The geometry information will be applied when the output object - * of a layer object is committed. * @param[in] layer A layer object * @param[in] info The geometry information * @return #TDM_ERROR_NONE if success. Otherwise, error value. * @see output_commit() function of #tdm_func_display + * @remark + * A backend module would apply the geometry information when the output object + * of a layer object is committed. */ tdm_error (*layer_set_info)(tdm_layer *layer, tdm_info_layer *info); @@ -423,32 +486,45 @@ typedef struct _tdm_func_display /** * @brief Set a TDM buffer to a layer object - * @details A TDM buffer will be applied when the output object - * of a layer object is committed. * @param[in] layer A layer object * @param[in] buffer A TDM buffer * @return #TDM_ERROR_NONE if success. Otherwise, error value. * @see output_commit() function of #tdm_func_display + * @remark + * A backend module would apply a TDM buffer when the output object + * of a layer object is committed. */ tdm_error (*layer_set_buffer)(tdm_layer *layer, tbm_surface_h buffer); /** * @brief Unset a TDM buffer from a layer object - * @details When this function is called, a current showing buffer will be - * disappeared from screen. Then nothing is showing on a layer object. * @param[in] layer A layer object * @return #TDM_ERROR_NONE if success. Otherwise, error value. + * @remark + * A backend module @b SHOULD hide the current showing buffer from screen. + * If needed, cleanup a layer object resource. */ tdm_error (*layer_unset_buffer)(tdm_layer *layer); /** * @brief Set the zpos for a VIDEO layer object - * @details Especially this function is for a VIDEO layer. The zpos of - * GRAPHIC layers can't be changed. * @param[in] layer A layer object * @param[in] zpos z-order * @return #TDM_ERROR_NONE if success. Otherwise, error value. - * @see tdm_layer_capability + * @see tdm_caps_layer, tdm_layer_capability + * @remark + * A backend module doesn't need to implement this function if a backend + * module doesn't have VIDEO layers.\n + * This function is for VIDEO layers. + * GRAPHIC layers are non-changeable. The zpos of GRAPHIC layers starts + * from 0. If there are 4 GRAPHIC layers, The zpos SHOULD be 0, 1, 2, 3.\n + * But the zpos of VIDEO layer is changeable. And The zpos of VIDEO layers + * is less than GRAPHIC layers or more than GRAPHIC layers. + * ie, ..., -2, -1, 4, 5, ... (if 0 <= GRAPHIC layer's zpos < 4). + * The zpos of VIDEO layers is @b relative. It doesn't need to start + * from -1 or 4. Let's suppose that there are two VIDEO layers. + * One has -2 zpos. Another has -4 zpos. Then -2 Video layer is higher + * than -4 VIDEO layer. */ tdm_error (*layer_set_video_pos)(tdm_layer *layer, int zpos); @@ -458,6 +534,9 @@ typedef struct _tdm_func_display * @param[out] error #TDM_ERROR_NONE if success. Otherwise, error value. * @return A capture object * @see capture_destroy() function of #tdm_func_capture + * @remark + * A backend module doesn't need to implement this function if a hardware + * doesn't have the capture device. */ tdm_capture *(*layer_create_capture)(tdm_layer *layer, tdm_error *error); } tdm_func_display; @@ -481,25 +560,29 @@ typedef struct _tdm_func_pp /** * @brief Set the geometry information to a pp object - * @details The geometry information will be applied when the pp object is committed. * @param[in] pp A pp object * @param[in] info The geometry information * @return #TDM_ERROR_NONE if success. Otherwise, error value. * @see pp_commit() function of #tdm_func_pp + * @remark + * A backend module would apply the geometry information when committed. */ tdm_error (*pp_set_info)(tdm_pp *pp, tdm_info_pp *info); /** * @brief Attach a source buffer and a destination buffer to a pp object - * @details When pp_commit() function is called, a backend module converts - * the image of a source buffer to a destination buffer. * @param[in] pp A pp object * @param[in] src A source buffer * @param[in] dst A destination buffer * @return #TDM_ERROR_NONE if success. Otherwise, error value. - * @see tdm_pp_done_handler * @see pp_set_info() function of #tdm_func_pp * @see pp_commit() function of #tdm_func_pp + * @see pp_set_done_handler, tdm_pp_done_handler + * @remark + * A backend module converts the image of a source buffer to a destination + * buffer when committed. The size/crop/transform information is set via + * #pp_set_info() of #tdm_func_pp. When done, a backend module @b SHOULD + * return the source/destination buffer via tdm_pp_done_handler. */ tdm_error (*pp_attach)(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst); @@ -516,7 +599,8 @@ typedef struct _tdm_func_pp * @param[in] func A user done handler * @param[in] user_data user data * @return #TDM_ERROR_NONE if success. Otherwise, error value. - * @remark When pp operation is done, a backend module @b SHOULD call #tdm_pp_done_handler. + * @remark + * A backend module @b SHOULD call #tdm_pp_done_handler when converintg a image is done. */ tdm_error (*pp_set_done_handler)(tdm_pp *pp, tdm_pp_done_handler func, void *user_data); } tdm_func_pp; @@ -541,11 +625,12 @@ typedef struct _tdm_func_capture /** * @brief Set the geometry information to a capture object - * @details The geometry information will be applied when the capture object is committed. * @param[in] capture A capture object * @param[in] info The geometry information * @return #TDM_ERROR_NONE if success. Otherwise, error value. * @see capture_commit() function of #tdm_func_capture + * @remark + * A backend module would apply the geometry information when committed. */ tdm_error (*capture_set_info)(tdm_capture *capture, tdm_info_capture *info); @@ -556,8 +641,14 @@ typedef struct _tdm_func_capture * @param[in] capture A capture object * @param[in] buffer A TDM buffer * @return #TDM_ERROR_NONE if success. Otherwise, error value. - * @see tdm_capture_done_handler + * @see capture_set_info() function of #tdm_func_capture * @see capture_commit() function of #tdm_func_capture + * @see capture_set_done_handler, tdm_capture_done_handler + * @remark + * A backend module dumps a output or a layer to to a TDM buffer when + * committed. The size/crop/transform information is set via #capture_set_info() + * of #tdm_func_capture. When done, a backend module @b SHOULD return the TDM + * buffer via tdm_capture_done_handler. */ tdm_error (*capture_attach)(tdm_capture *capture, tbm_surface_h buffer); @@ -574,7 +665,8 @@ typedef struct _tdm_func_capture * @param[in] func A user done handler * @param[in] user_data user data * @return #TDM_ERROR_NONE if success. Otherwise, error value. - * @remark When capture operation is done, a backend module @b SHOULD call #tdm_capture_done_handler. + * @remark + * A backend module @b SHOULD call #tdm_capture_done_handler when capture operation is done. */ tdm_error (*capture_set_done_handler)(tdm_capture *capture, tdm_capture_done_handler func, void *user_data); } tdm_func_capture; @@ -600,7 +692,7 @@ typedef struct _tdm_func_capture /** * @brief The backend module information of the entry point to initialize a TDM * backend module. - * @details + * @remark * A backend module @b SHOULD define the global data symbol of which name is * @b "tdm_backend_module_data". TDM will read this symbol, @b "tdm_backend_module_data", * at the initial time and call init() function of #tdm_backend_module. @@ -629,36 +721,36 @@ typedef struct _tdm_backend_module /** * @brief Register the backend display functions to a display - * @details - * A backend module @b SHOULD set the backend display functions at least. * @param[in] dpy A display object * @param[in] func_display display functions * @return #TDM_ERROR_NONE if success. Otherwise, error value. * @see tdm_backend_register_func_pp, tdm_backend_register_func_capture + * @remarks + * A backend module @b SHOULD set the backend display functions at least. */ tdm_error tdm_backend_register_func_display(tdm_display *dpy, tdm_func_display *func_display); /** * @brief Register the backend pp functions to a display - * @details - * A backend module can skip to register the backend pp functions - * if hardware device doesn't supports the memory to memory converting. * @param[in] dpy A display object * @param[in] func_pp pp functions * @return #TDM_ERROR_NONE if success. Otherwise, error value. * @see tdm_backend_register_func_display, tdm_backend_register_func_capture + * @remark + * A backend module doesn'tcan skip to register the backend pp functions + * if a hardware doesn't have the memory-to-memory converting device. */ tdm_error tdm_backend_register_func_pp(tdm_display *dpy, tdm_func_pp *func_pp); /** * @brief Register the backend capture functions to a display - * @details - * A backend module can skip to register the backend capture functions - * if hardware device doesn't supports the memory to memory converting. * @param[in] dpy A display object * @param[in] func_capture capture functions * @return #TDM_ERROR_NONE if success. Otherwise, error value. * @see tdm_backend_register_func_display, tdm_backend_register_func_pp + * @remark + * A backend module can skip to register the backend capture functions + * if a hardware doesn't have the capture device. */ tdm_error tdm_backend_register_func_capture(tdm_display *dpy, tdm_func_capture *func_capture); @@ -671,11 +763,11 @@ tdm_error tdm_backend_register_func_capture(tdm_display *dpy, tdm_func_capture * * TDM will release it immediately when TDM doesn't need it any more. * @param[in] buffer A TDM buffer * @return A buffer itself. Otherwise, NULL. + * @see tdm_buffer_unref_backend * @remark * - This function @b SHOULD be paired with #tdm_buffer_unref_backend. \n * - For example, this function @b SHOULD be called in case that a backend module uses the TDM * buffer of a layer for capturing a output or a layer to avoid tearing issue. - * @see tdm_buffer_unref_backend */ tbm_surface_h tdm_buffer_ref_backend(tbm_surface_h buffer); @@ -696,15 +788,15 @@ typedef void (*tdm_buffer_destroy_handler)(tbm_surface_h buffer, void *user_data /** * @brief Add a destroy handler to a TDM buffer - * @details - * A backend module can add a TDM buffer destroy handler to a TDM buffer which - * is a #tbm_surface_h object. When the TDM buffer is destroyed, this handler will - * be called. * @param[in] buffer A TDM buffer * @param[in] func A destroy handler * @param[in] user_data user data * @return #TDM_ERROR_NONE if success. Otherwise, error value. * @see tdm_buffer_remove_destroy_handler + * @remark + * A backend module can add a TDM buffer destroy handler to a TDM buffer which + * is a #tbm_surface_h object. When the TDM buffer is destroyed, this handler will + * be called. */ tdm_error tdm_buffer_add_destroy_handler(tbm_surface_h buffer, tdm_buffer_destroy_handler func, void *user_data); diff --git a/include/tdm_types.h b/include/tdm_types.h index 33c8488..120137a 100644 --- a/include/tdm_types.h +++ b/include/tdm_types.h @@ -160,10 +160,6 @@ typedef enum * - But in case that s vendor wants to handle a video by their own way, * a backend module offer VIDEO layers. And a display server will pass a video * buffer to a VIDEO layer without converting. - * - GRAPHIC layers have fixed zpos. But the zpos of VIDEO layer will be decided - * by a backend module side. - * - The frontend only can set the relative zpos to - * VIDEO layers via layer_set_video_pos() function of #tdm_func_display */ typedef enum { -- 2.7.4 From de8a46fd6d5ee74507a92a4a6a95e2316e877707 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Fri, 8 Jan 2016 20:56:47 +0900 Subject: [PATCH 14/16] doc: add tdm_helper.h to doxygen Change-Id: I7b972dc4a3ef24238d37212d4e1fbc9720b8721d --- doc/Doxyfile | 1 + include/tdm_helper.h | 45 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/doc/Doxyfile b/doc/Doxyfile index 47f90d0..cd3a6a7 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -101,6 +101,7 @@ INPUT = \ doc/tdm_doc.h \ include/tdm.h \ include/tdm_backend.h \ + include/tdm_helper.h \ include/tdm_list.h \ include/tdm_log.h \ include/tdm_types.h diff --git a/include/tdm_helper.h b/include/tdm_helper.h index 53955b3..245b7b0 100644 --- a/include/tdm_helper.h +++ b/include/tdm_helper.h @@ -52,7 +52,50 @@ extern "C" { * be removed. * @warning * If tdm_helper_drm_fd is more than -1, a tdm backend module @b SHOULDN't call - * drmWaitVBlank by itself. Moreover, drm events will be handled by ecore_drm. + * drmWaitVBlank by itself because a DRM vblank event will be handled in ecore_drm + * internally. In this case, a tdm backend module NEVER get a DRM vblank event. + * If a tdm backend module need to handle a vendor specific DRM event, + * drmAddUserHandler() of libdrm makes possible that a tdm backend module handle + * it. + * @par Example + * @code + static int + _tdm_drm_user_handler(struct drm_event *event) + { + if (event->type != DRM_VENDOR_XXX_EVENT) + return -1; + + //handling a vendor event + + return 0; + } + + ... + + drm_data->drm_fd = -1; + if (tdm_helper_drm_fd >= 0) + { + drm_data->drm_fd = tdm_helper_drm_fd; + drmAddUserHandler(tdm_helper_drm_fd, _tdm_drm_user_handler); + } + + if (drm_data->drm_fd < 0) + drm_data->drm_fd = _tdm_drm_open_drm(); + + ... + + drmRemoveUserHandler(tdm_helper_drm_fd, _tdm_drm_user_handler); + * @endcode + * @code + if (tdm_helper_drm_fd == -1) + { + ... + if (drmWaitVBlank(fd, &vbl)) + return TDM_ERROR_OPERATION_FAILED; + ... + } + * @endcode + * @endcode * @todo */ extern int tdm_helper_drm_fd; -- 2.7.4 From ee1a3e3f80e03a9517ff17bab0f505ffa135f228 Mon Sep 17 00:00:00 2001 From: Boram Park Date: Wed, 20 Jan 2016 10:06:04 +0900 Subject: [PATCH 15/16] add dump function for debugging Change-Id: Ifb2abab9390a850e1224c38c3ae693a0ec1b1815 --- configure.ac | 2 +- include/tdm_helper.h | 20 ++++++ packaging/libtdm.spec | 1 + src/tdm_helper.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 195 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 9cf040d..284ef1a 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ LT_INIT([disable-static]) # Enable quiet compiles on automake 1.11. m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) -PKG_CHECK_MODULES(TDM, libtbm pthread-stubs) +PKG_CHECK_MODULES(TDM, libtbm pthread-stubs libpng) AC_SUBST(TDM_CFLAGS) AC_SUBST(TDM_LIBS) diff --git a/include/tdm_helper.h b/include/tdm_helper.h index 245b7b0..d17c835 100644 --- a/include/tdm_helper.h +++ b/include/tdm_helper.h @@ -37,6 +37,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define _TDM_HELPER_H_ #include "tdm_types.h" +#include #ifdef __cplusplus extern "C" { @@ -100,6 +101,25 @@ extern "C" { */ extern int tdm_helper_drm_fd; +/** + * @brief Dump a buffer + * @details + * This function supports only if a buffer has below formats. + * - TBM_FORMAT_ARGB8888 + * - TBM_FORMAT_XRGB8888 + * - TBM_FORMAT_YVU420 + * - TBM_FORMAT_YUV420 + * - TBM_FORMAT_NV12 + * - TBM_FORMAT_NV21 + * - TBM_FORMAT_YUYV + * - TBM_FORMAT_UYVY + * The filename extension should be "png" for TBM_FORMAT_ARGB8888 and TBM_FORMAT_XRGB8888 + * or "yuv" for YUV formats. + * @param[in] buffer A TDM buffer + * @param[in] file The path of file. + */ +void tdm_helper_dump_buffer(tbm_surface_h buffer, const char *file); + #ifdef __cplusplus } #endif diff --git a/packaging/libtdm.spec b/packaging/libtdm.spec index e505c35..bd6ba7f 100644 --- a/packaging/libtdm.spec +++ b/packaging/libtdm.spec @@ -8,6 +8,7 @@ Source0: %{name}-%{version}.tar.gz Source1001: %{name}.manifest BuildRequires: pkgconfig(pthread-stubs) BuildRequires: pkgconfig(libtbm) +BuildRequires: pkgconfig(libpng) %description Common user library of Tizen Display Manager : libtdm front-end library diff --git a/src/tdm_helper.c b/src/tdm_helper.c index 46fd6ab..b99abe7 100644 --- a/src/tdm_helper.c +++ b/src/tdm_helper.c @@ -2,7 +2,179 @@ #include "config.h" #endif -#include "tdm_helper.h" +#include +#include +#include +#include +#include + +#include "tdm.h" +#include "tdm_private.h" + +#define PNG_DEPTH 8 int tdm_helper_drm_fd = -1; +static const char *dump_prefix[2] = {"png", "yuv"}; + +static void +_tdm_helper_dump_raw(const char *file, void *data1, int size1, void *data2, + int size2, void *data3, int size3) +{ + unsigned int *blocks; + FILE *fp = fopen(file, "w+"); + TDM_RETURN_IF_FAIL(fp != NULL); + + blocks = (unsigned int*)data1; + fwrite(blocks, 1, size1, fp); + + if (size2 > 0) + { + blocks = (unsigned int*)data2; + fwrite(blocks, 1, size2, fp); + } + + if (size3 > 0) + { + blocks = (unsigned int*)data3; + fwrite(blocks, 1, size3, fp); + } + + fclose(fp); +} + +static void +_tdm_helper_dump_png(const char *file, const void *data, int width, + int height) +{ + FILE *fp = fopen(file, "wb"); + TDM_RETURN_IF_FAIL(fp != NULL); + + png_structp pPngStruct = + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!pPngStruct) + { + fclose(fp); + return; + } + + png_infop pPngInfo = png_create_info_struct(pPngStruct); + if (!pPngInfo) + { + png_destroy_write_struct(&pPngStruct, NULL); + fclose(fp); + return; + } + + png_init_io(pPngStruct, fp); + png_set_IHDR(pPngStruct, + pPngInfo, + width, + height, + PNG_DEPTH, + PNG_COLOR_TYPE_RGBA, + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + png_set_bgr(pPngStruct); + png_write_info(pPngStruct, pPngInfo); + + const int pixel_size = 4; // RGBA + png_bytep *row_pointers = + png_malloc(pPngStruct, height * sizeof(png_byte*)); + + unsigned int *blocks = (unsigned int*)data; + int y = 0; + int x = 0; + + for (; y < height; ++y) + { + png_bytep row = + png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size); + row_pointers[y] = (png_bytep)row; + for (x = 0; x < width; ++x) + { + unsigned int curBlock = blocks[y * width + x]; + row[x * pixel_size] = (curBlock & 0xFF); + row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF; + row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF; + row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF; + } + } + + png_write_image(pPngStruct, row_pointers); + png_write_end(pPngStruct, pPngInfo); + + for (y = 0; y < height; y++) + png_free(pPngStruct, row_pointers[y]); + png_free(pPngStruct, row_pointers); + + png_destroy_write_struct(&pPngStruct, &pPngInfo); + + fclose(fp); +} + +EXTERN void +tdm_helper_dump_buffer(tbm_surface_h buffer, const char *file) +{ + tbm_surface_info_s info; + int len; + const char *prefix; + + TDM_RETURN_IF_FAIL(buffer != NULL); + TDM_RETURN_IF_FAIL(file != NULL); + + tbm_surface_get_info(buffer, &info); + + len = strnlen(file, 1024); + if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888) + prefix = dump_prefix[0]; + else + prefix = dump_prefix[1]; + + if (strncmp(file + (len - 3), prefix, 3)) + { + TDM_ERR("can't dump to '%s' file", file + (len - 3)); + return; + } + + switch(info.format) + { + case TBM_FORMAT_ARGB8888: + case TBM_FORMAT_XRGB8888: + _tdm_helper_dump_png(file, info.planes[0].ptr, + info.planes[0].stride >> 2, info.height); + break; + case TBM_FORMAT_YVU420: + case TBM_FORMAT_YUV420: + _tdm_helper_dump_raw(file, + info.planes[0].ptr + info.planes[0].offset, + info.planes[0].stride * info.height, + info.planes[1].ptr + info.planes[1].offset, + info.planes[1].stride * (info.height >> 1), + info.planes[2].ptr + info.planes[2].offset, + info.planes[2].stride * (info.height >> 1)); + break; + case TBM_FORMAT_NV12: + case TBM_FORMAT_NV21: + _tdm_helper_dump_raw(file, + info.planes[0].ptr + info.planes[0].offset, + info.planes[0].stride * info.height, + info.planes[1].ptr + info.planes[1].offset, + info.planes[1].stride * (info.height >> 1), NULL, + 0); + break; + case TBM_FORMAT_YUYV: + case TBM_FORMAT_UYVY: + _tdm_helper_dump_raw(file, + info.planes[0].ptr + info.planes[0].offset, + info.planes[0].stride * info.height, NULL, 0, + NULL, 0); + break; + default: + TDM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR (info.format)); + return; + } + + TDM_INFO("dump %s", file); +} -- 2.7.4 From 297f65a2ca292d17a69510c647bfbde544681b3d Mon Sep 17 00:00:00 2001 From: Junkyeong Kim Date: Fri, 22 Jan 2016 13:45:54 +0900 Subject: [PATCH 16/16] add -lpthread to Makefile Change-Id: I0ddd04eacd02ef0af3e0c85b7017030b94eebafa Signed-off-by: Junkyeong Kim --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 97356dc..f445f27 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,7 +7,7 @@ AM_CFLAGS = \ libtdm_la_LTLIBRARIES = libtdm.la libtdm_ladir = $(libdir) libtdm_la_LDFLAGS = -version-number 1:0:0 -no-undefined -libtdm_la_LIBADD = $(TDM_LIBS) -ldl +libtdm_la_LIBADD = $(TDM_LIBS) -ldl -lpthread libtdm_la_SOURCES = \ tdm_backend.c \ -- 2.7.4