first draft
[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 func;
47     void *user_data;
48
49     struct list_head link;
50 } tdm_buffer_func_info;
51
52 typedef struct _tdm_buffer_info
53 {
54     tbm_surface_h buffer;
55
56     /* frontend ref_count */
57     int ref_count;
58
59     /* backend ref_count */
60     int backend_ref_count;
61
62     struct list_head release_funcs;
63 } tdm_buffer_info;
64
65 EXTERN tdm_buffer*
66 tdm_buffer_create(tbm_surface_h buffer, tdm_error *error)
67 {
68     tdm_buffer_info *buf_info;
69
70     if (!buffer)
71     {
72         if (error)
73             *error = TDM_ERROR_INVALID_PARAMETER;
74
75         TDM_ERR("'buffer != NULL' failed");
76
77         return NULL;
78     }
79
80     buf_info = calloc(1, sizeof(tdm_buffer_info));
81     if (!buf_info)
82     {
83         if (error)
84             *error = TDM_ERROR_OUT_OF_MEMORY;
85
86         TDM_ERR("'buf_info != NULL' failed");
87
88         return NULL;
89     }
90
91     buf_info->ref_count = 1;
92
93     tbm_surface_internal_ref(buffer);
94     buf_info->buffer = buffer;
95
96     LIST_INITHEAD(&buf_info->release_funcs);
97
98     if (error)
99         error = TDM_ERROR_NONE;
100
101     return (tdm_buffer*)buf_info;
102 }
103
104 EXTERN tdm_buffer*
105 tdm_buffer_ref(tdm_buffer *buffer, tdm_error *error)
106 {
107     tdm_buffer_info *buf_info;
108
109     if (!buffer)
110     {
111         if (error)
112             *error = TDM_ERROR_INVALID_PARAMETER;
113
114         TDM_ERR("'buffer != NULL' failed");
115
116         return NULL;
117     }
118
119     buf_info = buffer;
120     buf_info->ref_count++;
121
122     if (error)
123         *error = TDM_ERROR_NONE;
124
125     return buffer;
126 }
127
128 EXTERN void
129 tdm_buffer_unref(tdm_buffer *buffer)
130 {
131     tdm_buffer_info *buf_info;
132     tdm_buffer_func_info *func_info = NULL, *next = NULL;
133
134     if (!buffer)
135         return;
136
137     buf_info = buffer;
138     buf_info->ref_count--;
139
140     if (buf_info->ref_count > 0)
141         return;
142
143     /* Before ref_count become 0, all backend reference should be removed */
144     TDM_WARNING_IF_FAIL(buf_info->backend_ref_count == 0);
145
146     LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link)
147     {
148         LIST_DEL(&func_info->link);
149         free(func_info);
150     }
151
152     free(buf_info);
153 }
154
155 EXTERN tdm_error
156 tdm_buffer_add_release_handler(tdm_buffer *buffer,
157                                tdm_buffer_release_handler func, void *user_data)
158 {
159     tdm_buffer_info *buf_info;
160     tdm_buffer_func_info *func_info;
161
162     TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
163     TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
164
165     func_info = calloc(1, sizeof(tdm_buffer_func_info));
166     TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY);
167
168     func_info->func = func;
169     func_info->user_data = user_data;
170
171     buf_info = buffer;
172     LIST_ADD(&func_info->link, &buf_info->release_funcs);
173
174     return TDM_ERROR_NONE;
175 }
176
177 EXTERN void
178 tdm_buffer_remove_release_handler(tdm_buffer *buffer, tdm_buffer_release_handler func, void *user_data)
179 {
180     tdm_buffer_info *buf_info;
181     tdm_buffer_func_info *func_info = NULL, *next = NULL;
182
183     TDM_RETURN_IF_FAIL(buffer != NULL);
184     TDM_RETURN_IF_FAIL(func != NULL);
185
186     buf_info = buffer;
187     LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link)
188     {
189         if (func_info->func != func || func_info->user_data != user_data)
190             continue;
191
192         LIST_DEL(&func_info->link);
193         free(func_info);
194
195         return;
196     }
197 }
198
199
200 INTERN tdm_buffer*
201 tdm_buffer_ref_backend(tdm_buffer *buffer)
202 {
203     tdm_buffer_info *buf_info;
204
205     TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL);
206
207     buf_info = buffer;
208     buf_info->backend_ref_count++;
209
210     return buffer;
211 }
212
213 INTERN void
214 tdm_buffer_unref_backend(tdm_buffer *buffer)
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
221     buf_info = buffer;
222     buf_info->backend_ref_count--;
223
224     if (buf_info->backend_ref_count > 0)
225         return;
226
227     LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link)
228         func_info->func(buffer, func_info->user_data);
229 }
230
231 INTERN tbm_surface_h
232 tdm_buffer_get_surface(tdm_buffer *buffer)
233 {
234     tdm_buffer_info *buf_info = buffer;
235
236     TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, NULL);
237
238     return buf_info->buffer;
239 }
240
241 #undef container_of
242 #define container_of(ptr, type, member) \
243     (type *)((char *)(ptr) - offsetof(type, member))
244
245 INTERN tdm_buffer*
246 tdm_buffer_get(tbm_surface_h buffer)
247 {
248     TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL);
249
250     return container_of(buffer, tdm_buffer_info, buffer);
251 }