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 func;
49 struct list_head link;
50 } tdm_buffer_func_info;
52 typedef struct _tdm_buffer_info
56 /* ref_count for frontend */
59 /* ref_count for backend */
60 int backend_ref_count;
62 struct list_head release_funcs;
63 struct list_head link;
66 static int buffer_list_init;
67 static struct list_head buffer_list;
70 _tdm_buffer_destroy(tdm_buffer_info *buf_info)
72 tdm_buffer_func_info *func_info = NULL, *next = NULL;
74 TDM_WARNING_IF_FAIL(buf_info->ref_count == 0);
75 TDM_WARNING_IF_FAIL(buf_info->backend_ref_count == 0);
77 LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link)
79 LIST_DEL(&func_info->link);
83 LIST_DEL(&buf_info->link);
85 tbm_surface_internal_unref(buf_info->buffer);
90 tdm_buffer_create(tbm_surface_h buffer, tdm_error *error)
92 tdm_buffer_info *buf_info;
94 if (!buffer_list_init)
96 LIST_INITHEAD(&buffer_list);
103 *error = TDM_ERROR_INVALID_PARAMETER;
105 TDM_ERR("'buffer != NULL' failed");
110 buf_info = calloc(1, sizeof(tdm_buffer_info));
114 *error = TDM_ERROR_OUT_OF_MEMORY;
116 TDM_ERR("'buf_info != NULL' failed");
121 buf_info->ref_count = 1;
123 tbm_surface_internal_ref(buffer);
124 buf_info->buffer = buffer;
126 LIST_INITHEAD(&buf_info->release_funcs);
127 LIST_ADDTAIL(&buf_info->link, &buffer_list);
130 *error = TDM_ERROR_NONE;
132 return (tdm_buffer*)buf_info;
136 tdm_buffer_ref(tdm_buffer *buffer, tdm_error *error)
138 tdm_buffer_info *buf_info;
143 *error = TDM_ERROR_INVALID_PARAMETER;
145 TDM_ERR("'buffer != NULL' failed");
151 buf_info->ref_count++;
154 *error = TDM_ERROR_NONE;
160 tdm_buffer_unref(tdm_buffer *buffer)
162 tdm_buffer_info *buf_info;
168 TDM_RETURN_IF_FAIL (buf_info->ref_count > 0);
170 buf_info->ref_count--;
172 /* destroy tdm_buffer when both ref_count and backend_ref_count are 0. */
173 if (buf_info->ref_count > 0 || buf_info->backend_ref_count > 0)
176 _tdm_buffer_destroy(buf_info);
180 tdm_buffer_add_release_handler(tdm_buffer *buffer,
181 tdm_buffer_release_handler func, void *user_data)
183 tdm_buffer_info *buf_info;
184 tdm_buffer_func_info *func_info;
186 TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
187 TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
189 func_info = calloc(1, sizeof(tdm_buffer_func_info));
190 TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY);
192 func_info->func = func;
193 func_info->user_data = user_data;
196 LIST_ADD(&func_info->link, &buf_info->release_funcs);
198 return TDM_ERROR_NONE;
202 tdm_buffer_remove_release_handler(tdm_buffer *buffer, tdm_buffer_release_handler func, void *user_data)
204 tdm_buffer_info *buf_info;
205 tdm_buffer_func_info *func_info = NULL, *next = NULL;
207 TDM_RETURN_IF_FAIL(buffer != NULL);
208 TDM_RETURN_IF_FAIL(func != NULL);
211 LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link)
213 if (func_info->func != func || func_info->user_data != user_data)
216 LIST_DEL(&func_info->link);
225 tdm_buffer_ref_backend(tdm_buffer *buffer)
227 tdm_buffer_info *buf_info;
229 TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL);
232 buf_info->backend_ref_count++;
238 tdm_buffer_unref_backend(tdm_buffer *buffer)
240 tdm_buffer_info *buf_info;
241 tdm_buffer_func_info *func_info = NULL, *next = NULL;
244 TDM_RETURN_IF_FAIL(buffer != NULL);
247 buf_info->backend_ref_count--;
249 if (buf_info->backend_ref_count > 0)
252 /* ref_count can become 0 in user release function. In that case, buf_info
253 * will be destroyed in tbm_buffer_unref. So we destroy buf_info in this
254 * function only in case that old_ref_count is 0.
256 old_ref_count = buf_info->ref_count;
258 LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link)
259 func_info->func(buffer, func_info->user_data);
261 /* finally, both ref_count and backend_ref_count are 0. destroy tdm_buffer */
262 if (old_ref_count == 0 && buf_info->ref_count == 0)
263 _tdm_buffer_destroy(buf_info);
267 tdm_buffer_get_surface(tdm_buffer *buffer)
269 tdm_buffer_info *buf_info = buffer;
271 TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, NULL);
273 return buf_info->buffer;
277 tdm_buffer_get(tbm_surface_h buffer)
279 tdm_buffer_info *found;
281 TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL);
283 if (!buffer_list_init)
285 LIST_INITHEAD(&buffer_list);
286 buffer_list_init = 1;
289 LIST_FOR_EACH_ENTRY(found, &buffer_list, link)
291 if (found->buffer == buffer)