50a94be9538ac3a41617263c916e7018ee075551
[platform/core/uifw/libtdm.git] / src / tdm_buffer.c
1 /**************************************************************************
2
3 libtdm
4
5 Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
6
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>
13
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:
21
22 The above copyright notice and this permission notice (including the
23 next paragraph) shall be included in all copies or substantial portions
24 of the Software.
25
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.
33
34 **************************************************************************/
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include "tdm.h"
41 #include "tdm_private.h"
42 #include "tdm_list.h"
43
44 static int tdm_buffer_key;
45 #define TDM_BUFFER_KEY ((unsigned long)&tdm_buffer_key)
46
47 typedef struct _tdm_buffer_func_info {
48         tdm_buffer_release_handler release_func;
49         tdm_buffer_destroy_handler destroy_func;
50         void *user_data;
51
52         struct list_head link;
53 } tdm_buffer_func_info;
54
55 static void
56 _tdm_buffer_destroy_info(void *user_data)
57 {
58         tdm_buffer_info *buf_info = (tdm_buffer_info *)user_data;
59         tdm_buffer_func_info *func_info = NULL, *next = NULL;
60
61         if (buf_info->backend_ref_count > 0) {
62                 TDM_NEVER_GET_HERE();
63                 if (tdm_debug_buffer)
64                         TDM_INFO("%p", buf_info->buffer);
65         }
66
67         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) {
68                 LIST_DEL(&func_info->link);
69                 free(func_info);
70         }
71
72         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link)
73         func_info->destroy_func(buf_info->buffer, func_info->user_data);
74
75         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link) {
76                 LIST_DEL(&func_info->link);
77                 free(func_info);
78         }
79
80         if (tdm_debug_buffer)
81                 TDM_INFO("%p destroyed", buf_info->buffer);
82
83         free(buf_info);
84 }
85
86 INTERN tdm_buffer_info *
87 tdm_buffer_get_info(tbm_surface_h buffer)
88 {
89         tdm_buffer_info *buf_info = NULL;
90
91         if (!tbm_surface_internal_get_user_data(buffer, TDM_BUFFER_KEY,(void **)&buf_info)) {
92                 buf_info = calloc(1, sizeof(tdm_buffer_info));
93                 TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, NULL);
94
95                 buf_info->buffer = buffer;
96
97                 LIST_INITHEAD(&buf_info->release_funcs);
98                 LIST_INITHEAD(&buf_info->destroy_funcs);
99                 LIST_INITHEAD(&buf_info->link);
100
101                 if (!tbm_surface_internal_add_user_data(buffer, TDM_BUFFER_KEY, _tdm_buffer_destroy_info)) {
102                         TDM_WRN("FAIL to create user_data for surface %p", buffer);
103                         return NULL;
104                 }
105                 if (!tbm_surface_internal_set_user_data(buffer, TDM_BUFFER_KEY, buf_info)) {
106                         TDM_WRN("FAIL to set user_data for surface %p", buffer);
107                         return NULL;
108                 }
109
110                 if (tdm_debug_buffer)
111                         TDM_INFO("%p created", buf_info->buffer);
112         }
113
114         return buf_info;
115 }
116
117 EXTERN tdm_error
118 tdm_buffer_add_release_handler(tbm_surface_h buffer,
119                                tdm_buffer_release_handler func, void *user_data)
120 {
121         tdm_buffer_info *buf_info;
122         tdm_buffer_func_info *func_info;
123
124         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
125         TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
126
127         buf_info = tdm_buffer_get_info(buffer);
128         TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, TDM_ERROR_OUT_OF_MEMORY);
129
130         func_info = calloc(1, sizeof(tdm_buffer_func_info));
131         TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY);
132
133         func_info->release_func = func;
134         func_info->user_data = user_data;
135
136         LIST_ADD(&func_info->link, &buf_info->release_funcs);
137
138         return TDM_ERROR_NONE;
139 }
140
141 EXTERN void
142 tdm_buffer_remove_release_handler(tbm_surface_h buffer,
143                                   tdm_buffer_release_handler func, void *user_data)
144 {
145         tdm_buffer_info *buf_info;
146         tdm_buffer_func_info *func_info = NULL, *next = NULL;
147
148         TDM_RETURN_IF_FAIL(buffer != NULL);
149         TDM_RETURN_IF_FAIL(func != NULL);
150
151         buf_info = tdm_buffer_get_info(buffer);
152         TDM_RETURN_IF_FAIL(buf_info != NULL);
153
154         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) {
155                 if (func_info->release_func != func || func_info->user_data != user_data)
156                         continue;
157
158                 LIST_DEL(&func_info->link);
159                 free(func_info);
160
161                 return;
162         }
163 }
164
165
166 EXTERN tbm_surface_h
167 tdm_buffer_ref_backend(tbm_surface_h buffer)
168 {
169         tdm_buffer_info *buf_info;
170
171         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL);
172
173         buf_info = tdm_buffer_get_info(buffer);
174         TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, NULL);
175
176         buf_info->backend_ref_count++;
177         tbm_surface_internal_ref(buffer);
178
179         return buffer;
180 }
181
182 EXTERN void
183 tdm_buffer_unref_backend(tbm_surface_h buffer)
184 {
185         tdm_buffer_info *buf_info;
186         tdm_buffer_func_info *func_info = NULL, *next = NULL;
187
188         TDM_RETURN_IF_FAIL(buffer != NULL);
189
190         buf_info = tdm_buffer_get_info(buffer);
191         TDM_RETURN_IF_FAIL(buf_info != NULL);
192
193         buf_info->backend_ref_count--;
194         if (buf_info->backend_ref_count > 0) {
195                 tbm_surface_internal_unref(buffer);
196                 return;
197         }
198
199         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) {
200                 tbm_surface_internal_ref(buffer);
201                 func_info->release_func(buffer, func_info->user_data);
202                 tbm_surface_internal_unref(buffer);
203         }
204
205         tbm_surface_internal_unref(buffer);
206 }
207
208 EXTERN tdm_error
209 tdm_buffer_add_destroy_handler(tbm_surface_h buffer,
210                                tdm_buffer_destroy_handler func, void *user_data)
211 {
212         tdm_buffer_info *buf_info;
213         tdm_buffer_func_info *func_info;
214
215         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
216         TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
217
218         buf_info = tdm_buffer_get_info(buffer);
219         TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, TDM_ERROR_OUT_OF_MEMORY);
220
221         func_info = calloc(1, sizeof(tdm_buffer_func_info));
222         TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY);
223
224         func_info->destroy_func = func;
225         func_info->user_data = user_data;
226
227         LIST_ADD(&func_info->link, &buf_info->destroy_funcs);
228
229         return TDM_ERROR_NONE;
230 }
231
232 EXTERN void
233 tdm_buffer_remove_destroy_handler(tbm_surface_h buffer,
234                                   tdm_buffer_destroy_handler func, void *user_data)
235 {
236         tdm_buffer_info *buf_info;
237         tdm_buffer_func_info *func_info = NULL, *next = NULL;
238
239         TDM_RETURN_IF_FAIL(buffer != NULL);
240         TDM_RETURN_IF_FAIL(func != NULL);
241
242         buf_info = tdm_buffer_get_info(buffer);
243         TDM_RETURN_IF_FAIL(buf_info != NULL);
244
245         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link) {
246                 if (func_info->destroy_func != func || func_info->user_data != user_data)
247                         continue;
248
249                 LIST_DEL(&func_info->link);
250                 free(func_info);
251
252                 return;
253         }
254 }
255
256 INTERN tbm_surface_h
257 tdm_buffer_list_get_first_entry(struct list_head *list)
258 {
259         tdm_buffer_info *buf_info = NULL;
260
261         TDM_RETURN_VAL_IF_FAIL(list != NULL, NULL);
262
263         buf_info = container_of((list)->next, buf_info, link);
264
265         return buf_info->buffer;
266 }
267
268 INTERN void
269 tdm_buffer_list_dump(struct list_head *list)
270 {
271         tdm_buffer_info *buf_info = NULL;
272         char str[256], *p;
273         int len = sizeof (str);
274
275         TDM_RETURN_IF_FAIL(list != NULL);
276
277         p = str;
278         LIST_FOR_EACH_ENTRY(buf_info, list, link) {
279                 if (len > 0) {
280                         int l = snprintf(p, len, " %p", buf_info->buffer);
281                         p += l;
282                         len -= l;
283                 }
284                 else
285                         break;
286         }
287
288         TDM_INFO("\t %s", str);
289 }