set tdm output list's first element to main
[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_ERR("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_ERR("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         if (!tdm_thread_in_display_thread(syscall(SYS_gettid)))
200                 TDM_NEVER_GET_HERE();
201
202         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) {
203                 tbm_surface_internal_ref(buffer);
204                 func_info->release_func(buffer, func_info->user_data);
205                 tbm_surface_internal_unref(buffer);
206         }
207
208         tbm_surface_internal_unref(buffer);
209 }
210
211 EXTERN tdm_error
212 tdm_buffer_add_destroy_handler(tbm_surface_h buffer,
213                                tdm_buffer_destroy_handler func, void *user_data)
214 {
215         tdm_buffer_info *buf_info;
216         tdm_buffer_func_info *func_info;
217
218         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
219         TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
220
221         buf_info = tdm_buffer_get_info(buffer);
222         TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, TDM_ERROR_OUT_OF_MEMORY);
223
224         func_info = calloc(1, sizeof(tdm_buffer_func_info));
225         TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY);
226
227         func_info->destroy_func = func;
228         func_info->user_data = user_data;
229
230         LIST_ADD(&func_info->link, &buf_info->destroy_funcs);
231
232         return TDM_ERROR_NONE;
233 }
234
235 EXTERN void
236 tdm_buffer_remove_destroy_handler(tbm_surface_h buffer,
237                                   tdm_buffer_destroy_handler func, void *user_data)
238 {
239         tdm_buffer_info *buf_info;
240         tdm_buffer_func_info *func_info = NULL, *next = NULL;
241
242         TDM_RETURN_IF_FAIL(buffer != NULL);
243         TDM_RETURN_IF_FAIL(func != NULL);
244
245         buf_info = tdm_buffer_get_info(buffer);
246         TDM_RETURN_IF_FAIL(buf_info != NULL);
247
248         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link) {
249                 if (func_info->destroy_func != func || func_info->user_data != user_data)
250                         continue;
251
252                 LIST_DEL(&func_info->link);
253                 free(func_info);
254
255                 return;
256         }
257 }
258
259 INTERN tbm_surface_h
260 tdm_buffer_list_get_first_entry(struct list_head *list)
261 {
262         tdm_buffer_info *buf_info = NULL;
263
264         TDM_RETURN_VAL_IF_FAIL(list != NULL, NULL);
265
266         buf_info = container_of((list)->next, buf_info, link);
267
268         return buf_info->buffer;
269 }
270
271 INTERN void
272 tdm_buffer_list_dump(struct list_head *list)
273 {
274         tdm_buffer_info *buf_info = NULL;
275         char str[256], *p;
276         int len = sizeof (str);
277
278         TDM_RETURN_IF_FAIL(list != NULL);
279
280         p = str;
281         LIST_FOR_EACH_ENTRY(buf_info, list, link) {
282                 if (len > 0) {
283                         int l = snprintf(p, len, " %p", buf_info->buffer);
284                         p += l;
285                         len -= l;
286                 }
287                 else
288                         break;
289         }
290
291         TDM_INFO("\t %s", str);
292 }