X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Ftdm_buffer.c;h=97857b42fde613722c94980598bba9874a2dd528;hb=d71f22895842611f3da167a328351be931e2e0af;hp=612b1bab2c1b7e10e0b5f1fdc277569fcebb4d60;hpb=e8016044fba558950625f837f8fbecadb6246074;p=platform%2Fcore%2Fuifw%2Flibtdm.git diff --git a/src/tdm_buffer.c b/src/tdm_buffer.c index 612b1ba..97857b4 100644 --- a/src/tdm_buffer.c +++ b/src/tdm_buffer.c @@ -1,274 +1,278 @@ /************************************************************************** - -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. - + * + * 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. + * **************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#include "tdm.h" #include "tdm_private.h" -#include "tdm_list.h" - -typedef struct _tdm_buffer_func_info -{ - tdm_buffer_release_handler func; - void *user_data; - - struct list_head link; -} tdm_buffer_func_info; - -typedef struct _tdm_buffer_info -{ - tbm_surface_h buffer; - /* frontend ref_count */ - int ref_count; +static int tdm_buffer_key; +#define TDM_BUFFER_KEY ((unsigned long)&tdm_buffer_key) - /* backend ref_count */ - int backend_ref_count; +typedef struct _tdm_buffer_func_info { + tdm_buffer_release_handler release_func; + tdm_buffer_destroy_handler destroy_func; + void *user_data; - struct list_head release_funcs; - struct list_head link; -} tdm_buffer_info; - -static int buffer_list_init; -static struct list_head buffer_list; + struct list_head link; +} tdm_buffer_func_info; -EXTERN tdm_buffer* -tdm_buffer_create(tbm_surface_h buffer, tdm_error *error) +static void +_tdm_buffer_destroy_info(void *user_data) { - tdm_buffer_info *buf_info; - - if (!buffer_list_init) - { - LIST_INITHEAD(&buffer_list); - buffer_list_init = 1; - } - - if (!buffer) - { - if (error) - *error = TDM_ERROR_INVALID_PARAMETER; + tdm_buffer_info *buf_info = (tdm_buffer_info *)user_data; + tdm_buffer_func_info *func_info = NULL, *next = NULL; - TDM_ERR("'buffer != NULL' failed"); + if (buf_info->backend_ref_count > 0) { + TDM_NEVER_GET_HERE(); + if (tdm_debug_module & TDM_DEBUG_BUFFER) + TDM_INFO("%p", buf_info->buffer); + } - return NULL; - } + LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) { + LIST_DEL(&func_info->link); + free(func_info); + } - buf_info = calloc(1, sizeof(tdm_buffer_info)); - if (!buf_info) - { - if (error) - *error = TDM_ERROR_OUT_OF_MEMORY; + LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link) + func_info->destroy_func(buf_info->buffer, func_info->user_data); - TDM_ERR("'buf_info != NULL' failed"); + LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link) { + LIST_DEL(&func_info->link); + free(func_info); + } - return NULL; - } + if (tdm_debug_module & TDM_DEBUG_BUFFER) + TDM_INFO("%p destroyed", buf_info->buffer); - buf_info->ref_count = 1; - - tbm_surface_internal_ref(buffer); - buf_info->buffer = buffer; - - LIST_INITHEAD(&buf_info->release_funcs); - LIST_ADDTAIL(&buf_info->link, &buffer_list); - - if (error) - *error = TDM_ERROR_NONE; + free(buf_info); +} - return (tdm_buffer*)buf_info; +INTERN tdm_buffer_info * +tdm_buffer_get_info(tbm_surface_h buffer) +{ + tdm_buffer_info *buf_info = NULL; + + if (!tbm_surface_internal_get_user_data(buffer, TDM_BUFFER_KEY, (void **)&buf_info)) { + buf_info = calloc(1, sizeof(tdm_buffer_info)); + TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, NULL); + + buf_info->buffer = buffer; + + LIST_INITHEAD(&buf_info->release_funcs); + LIST_INITHEAD(&buf_info->destroy_funcs); + LIST_INITHEAD(&buf_info->link); + + if (!tbm_surface_internal_add_user_data(buffer, TDM_BUFFER_KEY, _tdm_buffer_destroy_info)) { + TDM_ERR("FAIL to create user_data for surface %p", buffer); + free(buf_info); + return NULL; + } + if (!tbm_surface_internal_set_user_data(buffer, TDM_BUFFER_KEY, buf_info)) { + TDM_ERR("FAIL to set user_data for surface %p", buffer); + tbm_surface_internal_delete_user_data(buffer, TDM_BUFFER_KEY); + free(buf_info); + return NULL; + } + + if (tdm_debug_module & TDM_DEBUG_BUFFER) + TDM_INFO("%p created", buf_info->buffer); + } + + return buf_info; } -EXTERN tdm_buffer* -tdm_buffer_ref(tdm_buffer *buffer, tdm_error *error) +EXTERN tdm_error +tdm_buffer_add_release_handler(tbm_surface_h buffer, + tdm_buffer_release_handler func, void *user_data) { - tdm_buffer_info *buf_info; + tdm_buffer_info *buf_info; + tdm_buffer_func_info *func_info = NULL; - if (!buffer) - { - if (error) - *error = TDM_ERROR_INVALID_PARAMETER; + TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); - TDM_ERR("'buffer != NULL' failed"); + buf_info = tdm_buffer_get_info(buffer); + TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, TDM_ERROR_OUT_OF_MEMORY); - return NULL; - } + LIST_FOR_EACH_ENTRY(func_info, &buf_info->release_funcs, link) { + if (func_info->release_func == func && func_info->user_data == user_data) { + TDM_ERR("can't add twice"); + return TDM_ERROR_BAD_REQUEST; + } + } - buf_info = buffer; - buf_info->ref_count++; + func_info = calloc(1, sizeof(tdm_buffer_func_info)); + TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY); - if (error) - *error = TDM_ERROR_NONE; + func_info->release_func = func; + func_info->user_data = user_data; - return buffer; + LIST_ADDTAIL(&func_info->link, &buf_info->release_funcs); + + return TDM_ERROR_NONE; } EXTERN void -tdm_buffer_unref(tdm_buffer *buffer) +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; - - if (!buffer) - return; + tdm_buffer_info *buf_info; + tdm_buffer_func_info *func_info = NULL, *next = NULL; - buf_info = buffer; - buf_info->ref_count--; + TDM_RETURN_IF_FAIL(buffer != NULL); + TDM_RETURN_IF_FAIL(func != NULL); - if (buf_info->ref_count > 0) - return; + buf_info = tdm_buffer_get_info(buffer); + TDM_RETURN_IF_FAIL(buf_info != NULL); - /* Before ref_count become 0, all backend reference should be removed */ - TDM_WARNING_IF_FAIL(buf_info->backend_ref_count == 0); + 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) + continue; - LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) - { - LIST_DEL(&func_info->link); - free(func_info); - } + LIST_DEL(&func_info->link); + free(func_info); - LIST_DEL(&buf_info->link); - - free(buf_info); + return; + } } -EXTERN tdm_error -tdm_buffer_add_release_handler(tdm_buffer *buffer, - tdm_buffer_release_handler func, void *user_data) +EXTERN tbm_surface_h +tdm_buffer_ref_backend(tbm_surface_h buffer) { - tdm_buffer_info *buf_info; - tdm_buffer_func_info *func_info; + tdm_buffer_info *buf_info; - TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER); - TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL); - func_info = calloc(1, sizeof(tdm_buffer_func_info)); - TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY); + buf_info = tdm_buffer_get_info(buffer); + TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, NULL); - func_info->func = func; - func_info->user_data = user_data; + buf_info->backend_ref_count++; + tbm_surface_internal_ref(buffer); - buf_info = buffer; - LIST_ADD(&func_info->link, &buf_info->release_funcs); + if (tdm_debug_module & TDM_DEBUG_BUFFER) + TDM_INFO("buffer(%p) backend_ref_count(%d)", buffer, buf_info->backend_ref_count); - return TDM_ERROR_NONE; + return buffer; } EXTERN void -tdm_buffer_remove_release_handler(tdm_buffer *buffer, tdm_buffer_release_handler func, void *user_data) +tdm_buffer_unref_backend(tbm_surface_h buffer) { - tdm_buffer_info *buf_info; - tdm_buffer_func_info *func_info = NULL, *next = NULL; + 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); + TDM_RETURN_IF_FAIL(buffer != NULL); - 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) - continue; + buf_info = tdm_buffer_get_info(buffer); + TDM_RETURN_IF_FAIL(buf_info != NULL); - LIST_DEL(&func_info->link); - free(func_info); + buf_info->backend_ref_count--; - return; - } -} + if (tdm_debug_module & TDM_DEBUG_BUFFER) + TDM_INFO("buffer(%p) backend_ref_count(%d)", buffer, buf_info->backend_ref_count); + if (buf_info->backend_ref_count > 0) { + tbm_surface_internal_unref(buffer); + return; + } -INTERN tdm_buffer* -tdm_buffer_ref_backend(tdm_buffer *buffer) -{ - tdm_buffer_info *buf_info; + if (tdm_debug_module & TDM_DEBUG_BUFFER) + TDM_INFO("buffer(%p) released", buffer); - TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL); + tbm_surface_internal_ref(buffer); + LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) + func_info->release_func(buffer, func_info->user_data); + tbm_surface_internal_unref(buffer); - buf_info = buffer; - buf_info->backend_ref_count++; - - return buffer; + tbm_surface_internal_unref(buffer); } -INTERN void -tdm_buffer_unref_backend(tdm_buffer *buffer) +EXTERN tdm_error +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 = NULL, *next = NULL; + tdm_buffer_info *buf_info; + tdm_buffer_func_info *func_info = NULL; - TDM_RETURN_IF_FAIL(buffer != NULL); + TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER); + TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER); - buf_info = buffer; - buf_info->backend_ref_count--; + buf_info = tdm_buffer_get_info(buffer); + TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, TDM_ERROR_OUT_OF_MEMORY); - if (buf_info->backend_ref_count > 0) - return; + LIST_FOR_EACH_ENTRY(func_info, &buf_info->destroy_funcs, link) { + if (func_info->destroy_func == func && func_info->user_data == user_data) { + TDM_ERR("can't add twice"); + return TDM_ERROR_BAD_REQUEST; + } + } - LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) - func_info->func(buffer, func_info->user_data); -} + func_info = calloc(1, sizeof(tdm_buffer_func_info)); + TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY); -INTERN tbm_surface_h -tdm_buffer_get_surface(tdm_buffer *buffer) -{ - tdm_buffer_info *buf_info = buffer; + func_info->destroy_func = func; + func_info->user_data = user_data; - TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, NULL); + LIST_ADDTAIL(&func_info->link, &buf_info->destroy_funcs); - return buf_info->buffer; + return TDM_ERROR_NONE; } -INTERN tdm_buffer* -tdm_buffer_get(tbm_surface_h buffer) +EXTERN void +tdm_buffer_remove_destroy_handler(tbm_surface_h buffer, + tdm_buffer_destroy_handler func, void *user_data) { - tdm_buffer_info *found; + 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); - TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL); + buf_info = tdm_buffer_get_info(buffer); + TDM_RETURN_IF_FAIL(buf_info != NULL); - if (!buffer_list_init) - { - LIST_INITHEAD(&buffer_list); - buffer_list_init = 1; - } + 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_FOR_EACH_ENTRY(found, &buffer_list, link) - { - if (found->buffer == buffer) - return found; - } + LIST_DEL(&func_info->link); + free(func_info); - return NULL; + return; + } } +