From: Boram Park Date: Thu, 24 Nov 2016 10:42:18 +0000 (+0900) Subject: correct capture behavior X-Git-Tag: submit/tizen/20161128.110729~9 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b0e33fed70ca1fc25fec654350976ae0d1a3aa53;p=platform%2Fcore%2Fuifw%2Flibtdm.git correct capture behavior Change-Id: I9e3a7b4f8f612f7a507f1ceaecf05465d210676e --- diff --git a/src/tdm_buffer.c b/src/tdm_buffer.c index f6a5aea0..68ca4441 100644 --- a/src/tdm_buffer.c +++ b/src/tdm_buffer.c @@ -215,8 +215,8 @@ tdm_buffer_unref_backend(tbm_surface_h buffer) return; } - if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) - TDM_NEVER_GET_HERE(); +// if (!tdm_thread_in_display_thread(syscall(SYS_gettid))) +// TDM_NEVER_GET_HERE(); LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) { tbm_surface_internal_ref(buffer); diff --git a/src/tdm_capture.c b/src/tdm_capture.c index 798f7389..c532754f 100644 --- a/src/tdm_capture.c +++ b/src/tdm_capture.c @@ -52,27 +52,52 @@ private_display = private_capture->private_display; \ func_capture = &private_display->func_capture -static tdm_error -_tdm_capture_check_if_exist(tdm_private_capture *private_capture, - tbm_surface_h buffer) +static void +_tdm_capture_print_list(struct list_head *list) { - tdm_buffer_info *buf_info = NULL; + tdm_capture_private_buffer *b = NULL; + char str[512], *p; + int len = sizeof(str); + + TDM_RETURN_IF_FAIL(list != NULL); + + p = str; + LIST_FOR_EACH_ENTRY(b, list, link) { + if (len > 0) { + int l = snprintf(p, len, " (%p)", b->buffer); + p += l; + len -= l; + } else + break; + } - LIST_FOR_EACH_ENTRY(buf_info, &private_capture->buffer_list, link) { - if (buf_info->buffer == buffer) { - TDM_ERR("%p attached twice", buffer); - return TDM_ERROR_BAD_REQUEST; - } + TDM_INFO("\t %s", str); +} + +static tdm_capture_private_buffer * +_tdm_capture_find_tbm_buffer(struct list_head *list, tbm_surface_h buffer) +{ + tdm_capture_private_buffer *b = NULL, *bb = NULL; + + LIST_FOR_EACH_ENTRY_SAFE(b, bb, list, link) { + if (b->buffer == buffer) + return b; } - LIST_FOR_EACH_ENTRY(buf_info, &private_capture->pending_buffer_list, link) { - if (buf_info->buffer == buffer) { - TDM_ERR("%p attached twice", buffer); - return TDM_ERROR_BAD_REQUEST; - } + return NULL; +} + +static tdm_capture_private_buffer * +_tdm_capture_find_buffer(struct list_head *list, tdm_capture_private_buffer *capture_buffer) +{ + tdm_capture_private_buffer *b = NULL, *bb = NULL; + + LIST_FOR_EACH_ENTRY_SAFE(b, bb, list, link) { + if (b == capture_buffer) + return b; } - return TDM_ERROR_NONE; + return NULL; } INTERN void @@ -81,8 +106,7 @@ tdm_capture_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer, { tdm_private_capture *private_capture = user_data; tdm_private_display *private_display = private_capture->private_display; - tdm_buffer_info *buf_info; - tbm_surface_h first_entry; + tdm_capture_private_buffer *capture_buffer = NULL, *first_entry = NULL; TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED()); @@ -90,7 +114,7 @@ tdm_capture_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer, tdm_thread_cb_capture_done capture_done; tdm_error ret; - capture_done.base.type = TDM_THREAD_CB_PP_DONE; + capture_done.base.type = TDM_THREAD_CB_CAPTURE_DONE; capture_done.base.length = sizeof capture_done; capture_done.capture_stamp = private_capture->stamp; capture_done.buffer = buffer; @@ -115,18 +139,25 @@ tdm_capture_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer, if (tdm_debug_module & TDM_DEBUG_BUFFER) TDM_INFO("capture(%p) done: %p", private_capture, buffer); - first_entry = tdm_buffer_list_get_first_entry(&private_capture->buffer_list); - if (first_entry != buffer) - TDM_ERR("%p is skipped", first_entry); + if (!LIST_IS_EMPTY(&private_capture->buffer_list)) { + first_entry = container_of((&private_capture->buffer_list)->next, capture_buffer, link); + if (first_entry->buffer != buffer) + TDM_ERR("buffer(%p) is skipped", first_entry->buffer); + } else { + TDM_NEVER_GET_HERE(); + } - if ((buf_info = tdm_buffer_get_info(buffer))) - LIST_DEL(&buf_info->link); + if ((capture_buffer = _tdm_capture_find_tbm_buffer(&private_capture->buffer_list, buffer))) { + LIST_DEL(&capture_buffer->link); - _pthread_mutex_unlock(&private_display->lock); - if (private_capture->done_func) - private_capture->done_func(private_capture, buffer, private_capture->done_user_data); - tdm_buffer_unref_backend(buffer); - _pthread_mutex_lock(&private_display->lock); + _pthread_mutex_unlock(&private_display->lock); + if (private_capture->done_func) + private_capture->done_func(capture_buffer, buffer, private_capture->done_user_data); + tdm_buffer_unref_backend(buffer); + _pthread_mutex_lock(&private_display->lock); + + free(capture_buffer); + } } INTERN tdm_private_capture * @@ -136,7 +167,7 @@ tdm_capture_find_stamp(tdm_private_display *private_display, double stamp) TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL); - LIST_FOR_EACH_ENTRY(private_capture, &private_display->capture_list, link) { + LIST_FOR_EACH_ENTRY(private_capture, &private_display->capture_list, display_link) { if (private_capture->stamp == stamp) return private_capture; } @@ -215,6 +246,8 @@ tdm_capture_create_output_internal(tdm_private_output *private_output, LIST_INITHEAD(&private_capture->pending_buffer_list); LIST_INITHEAD(&private_capture->buffer_list); + TDM_DBG("capture(%p) create", private_capture); + if (error) *error = TDM_ERROR_NONE; @@ -280,6 +313,8 @@ tdm_capture_create_layer_internal(tdm_private_layer *private_layer, LIST_INITHEAD(&private_capture->pending_buffer_list); LIST_INITHEAD(&private_capture->buffer_list); + TDM_DBG("capture(%p) create", private_capture); + if (error) *error = TDM_ERROR_NONE; @@ -308,25 +343,27 @@ tdm_capture_destroy_internal(tdm_private_capture *private_capture) if (!LIST_IS_EMPTY(&private_capture->pending_buffer_list)) { TDM_WRN("capture(%p) not finished:", private_capture); - tdm_buffer_list_dump(&private_capture->pending_buffer_list); + _tdm_capture_print_list(&private_capture->pending_buffer_list); LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link) { LIST_DEL(&b->link); _pthread_mutex_unlock(&private_display->lock); tdm_buffer_unref_backend(b->buffer); _pthread_mutex_lock(&private_display->lock); + free(b); } } if (!LIST_IS_EMPTY(&private_capture->buffer_list)) { TDM_WRN("capture(%p) not finished:", private_capture); - tdm_buffer_list_dump(&private_capture->buffer_list); + _tdm_capture_print_list(&private_capture->buffer_list); LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->buffer_list, link) { LIST_DEL(&b->link); _pthread_mutex_unlock(&private_display->lock); tdm_buffer_unref_backend(b->buffer); _pthread_mutex_lock(&private_display->lock); + free(b); } } @@ -343,6 +380,8 @@ tdm_capture_destroy(tdm_capture *capture) if (!private_capture) return; + TDM_DBG("capture(%p) destroy", private_capture); + private_display = private_capture->private_display; _pthread_mutex_lock(&private_display->lock); @@ -356,6 +395,7 @@ tdm_capture_set_info(tdm_capture *capture, tdm_info_capture *info) CAPTURE_FUNC_ENTRY(); TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(info->type != 0, TDM_ERROR_INVALID_PARAMETER); _pthread_mutex_lock(&private_display->lock); @@ -365,6 +405,19 @@ tdm_capture_set_info(tdm_capture *capture, tdm_info_capture *info) return TDM_ERROR_NOT_IMPLEMENTED; } + if (info->type == TDM_CAPTURE_TYPE_STREAM && info->frequency == 0) { + tdm_private_output *private_output = private_capture->private_output; + info->frequency = private_output->current_mode->vrefresh; + } + + TDM_INFO("capture(%p) info: dst(%dx%d %d,%d %dx%d %c%c%c%c) trans(%d) type(%d) freq(%d) flags(%x)", + private_capture, + info->dst_config.size.h, info->dst_config.size.v, + info->dst_config.pos.x, info->dst_config.pos.y, + info->dst_config.pos.w, info->dst_config.pos.h, + FOURCC_STR(info->dst_config.format), + info->transform, info->type, info->frequency, info->flags); + ret = func_capture->capture_set_info(private_capture->capture_backend, info); TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); @@ -402,6 +455,8 @@ tdm_capture_set_done_handler(tdm_capture *capture, tdm_capture_done_handler func EXTERN tdm_error tdm_capture_attach(tdm_capture *capture, tbm_surface_h buffer) { + tdm_capture_private_buffer *capture_buffer; + CAPTURE_FUNC_ENTRY(); TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER); @@ -414,25 +469,41 @@ tdm_capture_attach(tdm_capture *capture, tbm_surface_h buffer) return TDM_ERROR_NOT_IMPLEMENTED; } - ret = _tdm_capture_check_if_exist(private_capture, buffer); - if (ret != TDM_ERROR_NONE) { + if (tdm_display_check_module_abi(private_display, 1, 2) && + private_display->caps_capture.max_attach_count > 0) { + int length = LIST_LENGTH(&private_capture->pending_buffer_list) + + LIST_LENGTH(&private_capture->buffer_list); + if (length >= private_display->caps_capture.max_attach_count) { + _pthread_mutex_unlock(&private_display->lock); + TDM_DBG("failed: too many attached!! max_attach_count(%d)", + private_display->caps_capture.max_attach_count); + return TDM_ERROR_BAD_REQUEST; + } + } + + capture_buffer = calloc(1, sizeof *capture_buffer); + if (!capture_buffer) { _pthread_mutex_unlock(&private_display->lock); - return ret; + TDM_ERR("alloc failed"); + return TDM_ERROR_OUT_OF_MEMORY; } ret = func_capture->capture_attach(private_capture->capture_backend, buffer); TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); - if (ret == TDM_ERROR_NONE) { - tdm_buffer_info *buf_info; + if (ret != TDM_ERROR_NONE) { + free(capture_buffer); + _pthread_mutex_unlock(&private_display->lock); + TDM_ERR("attach failed"); + return ret; + } - if ((buf_info = tdm_buffer_get_info(buffer))) - LIST_ADDTAIL(&buf_info->link, &private_capture->pending_buffer_list); + LIST_ADDTAIL(&capture_buffer->link, &private_capture->pending_buffer_list); + capture_buffer->buffer = tdm_buffer_ref_backend(buffer); - if (tdm_debug_module & TDM_DEBUG_BUFFER) { - TDM_INFO("capture(%p) attached:", private_capture); - tdm_buffer_list_dump(&private_capture->buffer_list); - } + if (tdm_debug_module & TDM_DEBUG_BUFFER) { + TDM_INFO("capture(%p) attached:", private_capture); + tdm_buffer_list_dump(&private_capture->buffer_list); } _pthread_mutex_unlock(&private_display->lock); @@ -443,8 +514,9 @@ tdm_capture_attach(tdm_capture *capture, tbm_surface_h buffer) EXTERN tdm_error tdm_capture_commit(tdm_capture *capture) { - tdm_buffer_info *b = NULL, *bb = NULL; + tdm_capture_private_buffer *b = NULL, *bb = NULL; tdm_private_output *private_output; + struct list_head commit_buffer_list; CAPTURE_FUNC_ENTRY(); @@ -464,18 +536,36 @@ tdm_capture_commit(tdm_capture *capture) return TDM_ERROR_NOT_IMPLEMENTED; } + LIST_INITHEAD(&commit_buffer_list); + + LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link) { + LIST_DEL(&b->link); + LIST_ADDTAIL(&b->link, &private_capture->buffer_list); + LIST_ADDTAIL(&b->commit_link, &commit_buffer_list); + } + ret = func_capture->capture_commit(private_capture->capture_backend); TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE); - if (ret == TDM_ERROR_NONE) { - LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link) { + LIST_FOR_EACH_ENTRY_SAFE(b, bb, &commit_buffer_list, commit_link) { + LIST_DEL(&b->commit_link); + + if (!_tdm_capture_find_buffer(&private_capture->buffer_list, b)) + continue; + + if (ret != TDM_ERROR_NONE) { + /* Not to call the user release handler when failed. + * Do we have to call this function here really? + * User better use set_done_handler to know when pp is done. Using + * buffer_release_handler is not good. + */ + tdm_buffer_remove_release_handler_internal(b->buffer); + + _pthread_mutex_unlock(&private_display->lock); + tdm_buffer_unref_backend(b->buffer); + _pthread_mutex_lock(&private_display->lock); LIST_DEL(&b->link); - tdm_buffer_ref_backend(b->buffer); - LIST_ADDTAIL(&b->link, &private_capture->buffer_list); } - } else { - LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link) - LIST_DEL(&b->link); } _pthread_mutex_unlock(&private_display->lock); diff --git a/src/tdm_pp.c b/src/tdm_pp.c index 93b78797..563ae0de 100644 --- a/src/tdm_pp.c +++ b/src/tdm_pp.c @@ -71,7 +71,7 @@ _tdm_pp_print_list(struct list_head *list) break; } - TDM_INFO("\t %s", str); + TDM_WRN("\t %s", str); } static tdm_pp_private_buffer * diff --git a/src/tdm_private.h b/src/tdm_private.h index eb6f6d66..57497829 100644 --- a/src/tdm_private.h +++ b/src/tdm_private.h @@ -344,6 +344,12 @@ typedef struct _tdm_pp_private_buffer { struct list_head commit_link; } tdm_pp_private_buffer; +typedef struct _tdm_capture_private_buffer { + tbm_surface_h buffer; + struct list_head link; + struct list_head commit_link; +} tdm_capture_private_buffer; + int tdm_display_check_module_abi(tdm_private_display *private_display, int abimaj, int abimin); diff --git a/tools/tdm_test_server.c b/tools/tdm_test_server.c index 4ea6d117..d6942a8b 100644 --- a/tools/tdm_test_server.c +++ b/tools/tdm_test_server.c @@ -801,14 +801,38 @@ exit_test(int sig) printf("got signal: %d\n", sig); - LIST_FOR_EACH_ENTRY_SAFE(o, oo, &data->output_list, link) { - LIST_DEL(&o->link); + LIST_FOR_EACH_ENTRY_SAFE(c, cc, &data->capture_list, link) { + LIST_DEL(&c->link); + tdm_capture_destroy(c->capture); + free(c); + } - LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) { - LIST_DEL(&l->link); + LIST_FOR_EACH_ENTRY_SAFE(p, pp, &data->pp_list, link) { + tdm_display_lock(data->display); + tdm_event_loop_source_remove(p->timer_source); + tdm_display_unlock(data->display); + + tdm_pp_destroy(p->pp); + } + LIST_FOR_EACH_ENTRY_SAFE(o, oo, &data->output_list, link) { + LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) { tdm_layer_unset_buffer(l->layer); + } + tdm_output_commit(o->output, 0, NULL, NULL); + } + + LIST_FOR_EACH_ENTRY_SAFE(p, pp, &data->pp_list, link) { + LIST_DEL(&p->link); + for (i = 0; i < TDM_ARRAY_SIZE(p->bufs); i++) + tbm_surface_destroy(p->bufs[i]); + free(p); + } + LIST_FOR_EACH_ENTRY_SAFE(o, oo, &data->output_list, link) { + LIST_DEL(&o->link); + LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) { + LIST_DEL(&l->link); LIST_FOR_EACH_ENTRY_SAFE(w, ww, &l->prop_list, link) { LIST_DEL(&w->link); free(w); @@ -817,9 +841,6 @@ exit_test(int sig) tbm_surface_destroy(l->bufs[i]); free(l); } - - tdm_output_commit(o->output, 0, NULL, NULL); - LIST_FOR_EACH_ENTRY_SAFE(w, ww, &o->prop_list, link) { LIST_DEL(&w->link); free(w); @@ -828,26 +849,6 @@ exit_test(int sig) free(o); } - - LIST_FOR_EACH_ENTRY_SAFE(p, pp, &data->pp_list, link) { - LIST_DEL(&p->link); - - tdm_display_lock(data->display); - tdm_event_loop_source_remove(p->timer_source); - tdm_display_unlock(data->display); - - tdm_pp_destroy(p->pp); - for (i = 0; i < TDM_ARRAY_SIZE(p->bufs); i++) - tbm_surface_destroy(p->bufs[i]); - free(p); - } - - LIST_FOR_EACH_ENTRY_SAFE(c, cc, &data->capture_list, link) { - LIST_DEL(&c->link); - tdm_capture_destroy(c->capture); - free(c); - } - if (data->display) tdm_display_deinit(data->display);