add layer_set_video_pos to backend interface
[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 typedef struct _tdm_buffer_func_info
45 {
46     tdm_buffer_release_handler release_func;
47     tdm_buffer_destroy_handler destroy_func;
48     void *user_data;
49
50     struct list_head link;
51 } tdm_buffer_func_info;
52
53 typedef struct _tdm_buffer_info
54 {
55     tbm_surface_h buffer;
56
57     /* ref_count for frontend */
58     int ref_count;
59
60     /* ref_count for backend */
61     int backend_ref_count;
62
63     struct list_head release_funcs;
64     struct list_head destroy_funcs;
65     struct list_head link;
66 } tdm_buffer_info;
67
68 static int buffer_list_init;
69 static struct list_head buffer_list;
70
71 static void
72 _tdm_buffer_destroy(tdm_buffer_info *buf_info)
73 {
74     tdm_buffer_func_info *func_info = NULL, *next = NULL;
75
76     TDM_WARNING_IF_FAIL(buf_info->ref_count == 0);
77     TDM_WARNING_IF_FAIL(buf_info->backend_ref_count == 0);
78
79     LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link)
80     {
81         LIST_DEL(&func_info->link);
82         free(func_info);
83     }
84
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);
87
88     LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link)
89     {
90         LIST_DEL(&func_info->link);
91         free(func_info);
92     }
93
94     LIST_DEL(&buf_info->link);
95
96     tbm_surface_internal_unref(buf_info->buffer);
97     free(buf_info);
98 }
99
100 EXTERN tdm_buffer*
101 tdm_buffer_create(tbm_surface_h buffer, tdm_error *error)
102 {
103     tdm_buffer_info *buf_info;
104
105     if (!buffer_list_init)
106     {
107         LIST_INITHEAD(&buffer_list);
108         buffer_list_init = 1;
109     }
110
111     if (!buffer)
112     {
113         if (error)
114             *error = TDM_ERROR_INVALID_PARAMETER;
115
116         TDM_ERR("'buffer != NULL' failed");
117
118         return NULL;
119     }
120
121     buf_info = calloc(1, sizeof(tdm_buffer_info));
122     if (!buf_info)
123     {
124         if (error)
125             *error = TDM_ERROR_OUT_OF_MEMORY;
126
127         TDM_ERR("'buf_info != NULL' failed");
128
129         return NULL;
130     }
131
132     buf_info->ref_count = 1;
133
134     tbm_surface_internal_ref(buffer);
135     buf_info->buffer = buffer;
136
137     LIST_INITHEAD(&buf_info->release_funcs);
138     LIST_INITHEAD(&buf_info->destroy_funcs);
139     LIST_ADDTAIL(&buf_info->link, &buffer_list);
140
141     if (error)
142         *error = TDM_ERROR_NONE;
143
144     return (tdm_buffer*)buf_info;
145 }
146
147 EXTERN tdm_buffer*
148 tdm_buffer_ref(tdm_buffer *buffer, tdm_error *error)
149 {
150     tdm_buffer_info *buf_info;
151
152     if (!buffer)
153     {
154         if (error)
155             *error = TDM_ERROR_INVALID_PARAMETER;
156
157         TDM_ERR("'buffer != NULL' failed");
158
159         return NULL;
160     }
161
162     buf_info = buffer;
163     buf_info->ref_count++;
164
165     if (error)
166         *error = TDM_ERROR_NONE;
167
168     return buffer;
169 }
170
171 EXTERN void
172 tdm_buffer_unref(tdm_buffer *buffer)
173 {
174     tdm_buffer_info *buf_info;
175
176     if (!buffer)
177         return;
178
179     buf_info = buffer;
180     TDM_RETURN_IF_FAIL (buf_info->ref_count > 0);
181
182     buf_info->ref_count--;
183
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)
186         return;
187
188     _tdm_buffer_destroy(buf_info);
189 }
190
191 EXTERN tdm_error
192 tdm_buffer_add_release_handler(tdm_buffer *buffer,
193                                tdm_buffer_release_handler func, void *user_data)
194 {
195     tdm_buffer_info *buf_info;
196     tdm_buffer_func_info *func_info;
197
198     TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
199     TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
200
201     func_info = calloc(1, sizeof(tdm_buffer_func_info));
202     TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY);
203
204     func_info->release_func = func;
205     func_info->user_data = user_data;
206
207     buf_info = buffer;
208     LIST_ADD(&func_info->link, &buf_info->release_funcs);
209
210     return TDM_ERROR_NONE;
211 }
212
213 EXTERN void
214 tdm_buffer_remove_release_handler(tdm_buffer *buffer, tdm_buffer_release_handler func, void *user_data)
215 {
216     tdm_buffer_info *buf_info;
217     tdm_buffer_func_info *func_info = NULL, *next = NULL;
218
219     TDM_RETURN_IF_FAIL(buffer != NULL);
220     TDM_RETURN_IF_FAIL(func != NULL);
221
222     buf_info = buffer;
223     LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link)
224     {
225         if (func_info->release_func != func || func_info->user_data != user_data)
226             continue;
227
228         LIST_DEL(&func_info->link);
229         free(func_info);
230
231         return;
232     }
233 }
234
235
236 EXTERN tdm_buffer*
237 tdm_buffer_ref_backend(tdm_buffer *buffer)
238 {
239     tdm_buffer_info *buf_info;
240
241     TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL);
242
243     buf_info = buffer;
244     buf_info->backend_ref_count++;
245
246     return buffer;
247 }
248
249 EXTERN void
250 tdm_buffer_unref_backend(tdm_buffer *buffer)
251 {
252     tdm_buffer_info *buf_info;
253     tdm_buffer_func_info *func_info = NULL, *next = NULL;
254     int old_ref_count;
255
256     TDM_RETURN_IF_FAIL(buffer != NULL);
257
258     buf_info = buffer;
259     buf_info->backend_ref_count--;
260
261     if (buf_info->backend_ref_count > 0)
262         return;
263
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.
267      */
268     old_ref_count = buf_info->ref_count;
269
270     LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link)
271         func_info->release_func(buffer, func_info->user_data);
272
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);
276 }
277
278 EXTERN tbm_surface_h
279 tdm_buffer_get_surface(tdm_buffer *buffer)
280 {
281     tdm_buffer_info *buf_info = buffer;
282
283     TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, NULL);
284
285     return buf_info->buffer;
286 }
287
288 EXTERN tdm_buffer*
289 tdm_buffer_get(tbm_surface_h buffer)
290 {
291     tdm_buffer_info *found;
292
293     TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL);
294
295     if (!buffer_list_init)
296     {
297         LIST_INITHEAD(&buffer_list);
298         buffer_list_init = 1;
299     }
300
301     LIST_FOR_EACH_ENTRY(found, &buffer_list, link)
302     {
303         if (found->buffer == buffer)
304             return found;
305     }
306
307     return NULL;
308 }
309
310 EXTERN tdm_error
311 tdm_buffer_add_destroy_handler(tdm_buffer *buffer, tdm_buffer_destroy_handler func, void *user_data)
312 {
313     tdm_buffer_info *buf_info;
314     tdm_buffer_func_info *func_info;
315
316     TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
317     TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
318
319     func_info = calloc(1, sizeof(tdm_buffer_func_info));
320     TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY);
321
322     func_info->destroy_func = func;
323     func_info->user_data = user_data;
324
325     buf_info = buffer;
326     LIST_ADD(&func_info->link, &buf_info->destroy_funcs);
327
328     return TDM_ERROR_NONE;
329 }
330
331 EXTERN void
332 tdm_buffer_remove_destroy_handler(tdm_buffer *buffer, tdm_buffer_destroy_handler func, void *user_data)
333 {
334     tdm_buffer_info *buf_info;
335     tdm_buffer_func_info *func_info = NULL, *next = NULL;
336
337     TDM_RETURN_IF_FAIL(buffer != NULL);
338     TDM_RETURN_IF_FAIL(func != NULL);
339
340     buf_info = buffer;
341     LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->destroy_funcs, link)
342     {
343         if (func_info->destroy_func != func || func_info->user_data != user_data)
344             continue;
345
346         LIST_DEL(&func_info->link);
347         free(func_info);
348
349         return;
350     }
351 }