1 /**************************************************************************
5 Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
7 Contact: Eunchul Kim <chulspro.kim@samsung.com>,
8 JinYoung Jeon <jy0.jeon@samsung.com>,
9 Taeheon Kim <th908.kim@samsung.com>,
10 YoungJun Cho <yj44.cho@samsung.com>,
11 SooChan Lim <sc1.lim@samsung.com>,
12 Boram Park <sc1.lim@samsung.com>
14 Permission is hereby granted, free of charge, to any person obtaining a
15 copy of this software and associated documentation files (the
16 "Software"), to deal in the Software without restriction, including
17 without limitation the rights to use, copy, modify, merge, publish,
18 distribute, sub license, and/or sell copies of the Software, and to
19 permit persons to whom the Software is furnished to do so, subject to
20 the following conditions:
22 The above copyright notice and this permission notice (including the
23 next paragraph) shall be included in all copies or substantial portions
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
27 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
29 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
30 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
31 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
32 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 **************************************************************************/
41 #include "tdm_private.h"
44 typedef struct _tdm_buffer_func_info
46 tdm_buffer_release_handler release_func;
47 tdm_buffer_destroy_handler destroy_func;
50 struct list_head link;
51 } tdm_buffer_func_info;
53 typedef struct _tdm_buffer_info
57 /* ref_count for frontend */
60 /* ref_count for backend */
61 int backend_ref_count;
63 struct list_head release_funcs;
64 struct list_head destroy_funcs;
65 struct list_head link;
68 static int buffer_list_init;
69 static struct list_head buffer_list;
72 _tdm_buffer_destroy(tdm_buffer_info *buf_info)
74 tdm_buffer_func_info *func_info = NULL, *next = NULL;
76 TDM_WARNING_IF_FAIL(buf_info->ref_count == 0);
77 TDM_WARNING_IF_FAIL(buf_info->backend_ref_count == 0);
79 LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link)
81 LIST_DEL(&func_info->link);
85 LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link)
86 func_info->destroy_func(buf_info, func_info->user_data);
88 LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link)
90 LIST_DEL(&func_info->link);
94 LIST_DEL(&buf_info->link);
96 tbm_surface_internal_unref(buf_info->buffer);
101 tdm_buffer_create(tbm_surface_h buffer, tdm_error *error)
103 tdm_buffer_info *buf_info;
105 if (!buffer_list_init)
107 LIST_INITHEAD(&buffer_list);
108 buffer_list_init = 1;
114 *error = TDM_ERROR_INVALID_PARAMETER;
116 TDM_ERR("'buffer != NULL' failed");
121 buf_info = calloc(1, sizeof(tdm_buffer_info));
125 *error = TDM_ERROR_OUT_OF_MEMORY;
127 TDM_ERR("'buf_info != NULL' failed");
132 buf_info->ref_count = 1;
134 tbm_surface_internal_ref(buffer);
135 buf_info->buffer = buffer;
137 LIST_INITHEAD(&buf_info->release_funcs);
138 LIST_INITHEAD(&buf_info->destroy_funcs);
139 LIST_ADDTAIL(&buf_info->link, &buffer_list);
142 *error = TDM_ERROR_NONE;
144 return (tdm_buffer*)buf_info;
148 tdm_buffer_ref(tdm_buffer *buffer, tdm_error *error)
150 tdm_buffer_info *buf_info;
155 *error = TDM_ERROR_INVALID_PARAMETER;
157 TDM_ERR("'buffer != NULL' failed");
163 buf_info->ref_count++;
166 *error = TDM_ERROR_NONE;
172 tdm_buffer_unref(tdm_buffer *buffer)
174 tdm_buffer_info *buf_info;
180 TDM_RETURN_IF_FAIL (buf_info->ref_count > 0);
182 buf_info->ref_count--;
184 /* destroy tdm_buffer when both ref_count and backend_ref_count are 0. */
185 if (buf_info->ref_count > 0 || buf_info->backend_ref_count > 0)
188 _tdm_buffer_destroy(buf_info);
192 tdm_buffer_add_release_handler(tdm_buffer *buffer,
193 tdm_buffer_release_handler func, void *user_data)
195 tdm_buffer_info *buf_info;
196 tdm_buffer_func_info *func_info;
198 TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
199 TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
201 func_info = calloc(1, sizeof(tdm_buffer_func_info));
202 TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY);
204 func_info->release_func = func;
205 func_info->user_data = user_data;
208 LIST_ADD(&func_info->link, &buf_info->release_funcs);
210 return TDM_ERROR_NONE;
214 tdm_buffer_remove_release_handler(tdm_buffer *buffer, tdm_buffer_release_handler func, void *user_data)
216 tdm_buffer_info *buf_info;
217 tdm_buffer_func_info *func_info = NULL, *next = NULL;
219 TDM_RETURN_IF_FAIL(buffer != NULL);
220 TDM_RETURN_IF_FAIL(func != NULL);
223 LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link)
225 if (func_info->release_func != func || func_info->user_data != user_data)
228 LIST_DEL(&func_info->link);
237 tdm_buffer_ref_backend(tdm_buffer *buffer)
239 tdm_buffer_info *buf_info;
241 TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL);
244 buf_info->backend_ref_count++;
250 tdm_buffer_unref_backend(tdm_buffer *buffer)
252 tdm_buffer_info *buf_info;
253 tdm_buffer_func_info *func_info = NULL, *next = NULL;
256 TDM_RETURN_IF_FAIL(buffer != NULL);
259 buf_info->backend_ref_count--;
261 if (buf_info->backend_ref_count > 0)
264 /* ref_count can become 0 in user release function. In that case, buf_info
265 * will be destroyed in tbm_buffer_unref. So we destroy buf_info in this
266 * function only in case that old_ref_count is 0.
268 old_ref_count = buf_info->ref_count;
270 LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link)
271 func_info->release_func(buffer, func_info->user_data);
273 /* finally, both ref_count and backend_ref_count are 0. destroy tdm_buffer */
274 if (old_ref_count == 0 && buf_info->ref_count == 0)
275 _tdm_buffer_destroy(buf_info);
279 tdm_buffer_get_surface(tdm_buffer *buffer)
281 tdm_buffer_info *buf_info = buffer;
283 TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, NULL);
285 return buf_info->buffer;
289 tdm_buffer_get(tbm_surface_h buffer)
291 tdm_buffer_info *found;
293 TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL);
295 if (!buffer_list_init)
297 LIST_INITHEAD(&buffer_list);
298 buffer_list_init = 1;
301 LIST_FOR_EACH_ENTRY(found, &buffer_list, link)
303 if (found->buffer == buffer)
311 tdm_buffer_add_destroy_handler(tdm_buffer *buffer, tdm_buffer_destroy_handler func, void *user_data)
313 tdm_buffer_info *buf_info;
314 tdm_buffer_func_info *func_info;
316 TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
317 TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
319 func_info = calloc(1, sizeof(tdm_buffer_func_info));
320 TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY);
322 func_info->destroy_func = func;
323 func_info->user_data = user_data;
326 LIST_ADD(&func_info->link, &buf_info->destroy_funcs);
328 return TDM_ERROR_NONE;
332 tdm_buffer_remove_destroy_handler(tdm_buffer *buffer, tdm_buffer_destroy_handler func, void *user_data)
334 tdm_buffer_info *buf_info;
335 tdm_buffer_func_info *func_info = NULL, *next = NULL;
337 TDM_RETURN_IF_FAIL(buffer != NULL);
338 TDM_RETURN_IF_FAIL(func != NULL);
341 LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link)
343 if (func_info->destroy_func != func || func_info->user_data != user_data)
346 LIST_DEL(&func_info->link);