apply wayland coding style
[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 typedef struct _tdm_buffer_info {
56         tbm_surface_h buffer;
57
58         /* ref_count for backend */
59         int backend_ref_count;
60
61         struct list_head release_funcs;
62         struct list_head destroy_funcs;
63 } tdm_buffer_info;
64
65 static void
66 _tdm_buffer_destroy_info(void *user_data)
67 {
68         tdm_buffer_info *buf_info = (tdm_buffer_info *)user_data;
69         tdm_buffer_func_info *func_info = NULL, *next = NULL;
70
71         if (buf_info->backend_ref_count > 0)
72                 TDM_NEVER_GET_HERE();
73
74         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) {
75                 LIST_DEL(&func_info->link);
76                 free(func_info);
77         }
78
79         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link)
80         func_info->destroy_func(buf_info->buffer, func_info->user_data);
81
82         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link) {
83                 LIST_DEL(&func_info->link);
84                 free(func_info);
85         }
86
87         free(buf_info);
88 }
89
90 static tdm_buffer_info *
91 _tdm_buffer_get_info(tbm_surface_h buffer)
92 {
93         tdm_buffer_info *buf_info = NULL;
94         tbm_bo bo;
95
96         bo = tbm_surface_internal_get_bo(buffer, 0);
97         TDM_RETURN_VAL_IF_FAIL(bo != NULL, NULL);
98
99         tbm_bo_get_user_data(bo, TDM_BUFFER_KEY, (void **)&buf_info);
100
101         if (!buf_info) {
102                 buf_info = calloc(1, sizeof(tdm_buffer_info));
103                 TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, NULL);
104
105                 buf_info->buffer = buffer;
106
107                 LIST_INITHEAD(&buf_info->release_funcs);
108                 LIST_INITHEAD(&buf_info->destroy_funcs);
109
110                 tbm_bo_add_user_data(bo, TDM_BUFFER_KEY, _tdm_buffer_destroy_info);
111                 tbm_bo_set_user_data(bo, TDM_BUFFER_KEY, buf_info);
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
178         return buffer;
179 }
180
181 EXTERN void
182 tdm_buffer_unref_backend(tbm_surface_h buffer)
183 {
184         tdm_buffer_info *buf_info;
185         tdm_buffer_func_info *func_info = NULL, *next = NULL;
186
187         TDM_RETURN_IF_FAIL(buffer != NULL);
188
189         buf_info = _tdm_buffer_get_info(buffer);
190         TDM_RETURN_IF_FAIL(buf_info != NULL);
191
192         buf_info->backend_ref_count--;
193
194         if (buf_info->backend_ref_count > 0)
195                 return;
196
197         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link) {
198                 tbm_surface_internal_ref(buffer);
199                 func_info->release_func(buffer, func_info->user_data);
200                 tbm_surface_internal_unref(buffer);
201         }
202 }
203
204 EXTERN tdm_error
205 tdm_buffer_add_destroy_handler(tbm_surface_h buffer,
206                                tdm_buffer_destroy_handler func, void *user_data)
207 {
208         tdm_buffer_info *buf_info;
209         tdm_buffer_func_info *func_info;
210
211         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
212         TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
213
214         buf_info = _tdm_buffer_get_info(buffer);
215         TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, TDM_ERROR_OUT_OF_MEMORY);
216
217         func_info = calloc(1, sizeof(tdm_buffer_func_info));
218         TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY);
219
220         func_info->destroy_func = func;
221         func_info->user_data = user_data;
222
223         LIST_ADD(&func_info->link, &buf_info->destroy_funcs);
224
225         return TDM_ERROR_NONE;
226 }
227
228 EXTERN void
229 tdm_buffer_remove_destroy_handler(tbm_surface_h buffer,
230                                   tdm_buffer_destroy_handler func, void *user_data)
231 {
232         tdm_buffer_info *buf_info;
233         tdm_buffer_func_info *func_info = NULL, *next = NULL;
234
235         TDM_RETURN_IF_FAIL(buffer != NULL);
236         TDM_RETURN_IF_FAIL(func != NULL);
237
238         buf_info = _tdm_buffer_get_info(buffer);
239         TDM_RETURN_IF_FAIL(buf_info != NULL);
240
241         LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link) {
242                 if (func_info->destroy_func != func || func_info->user_data != user_data)
243                         continue;
244
245                 LIST_DEL(&func_info->link);
246                 free(func_info);
247
248                 return;
249         }
250 }