3b8df91e157dca372ff1da0c0310827d03ad1d92
[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     struct list_head link;
64 } tdm_buffer_info;
65
66 static int buffer_list_init;
67 static struct list_head buffer_list;
68
69 EXTERN tdm_buffer*
70 tdm_buffer_create(tbm_surface_h buffer, tdm_error *error)
71 {
72     tdm_buffer_info *buf_info;
73
74     if (!buffer_list_init)
75     {
76         LIST_INITHEAD(&buffer_list);
77         buffer_list_init = 1;
78     }
79
80     if (!buffer)
81     {
82         if (error)
83             *error = TDM_ERROR_INVALID_PARAMETER;
84
85         TDM_ERR("'buffer != NULL' failed");
86
87         return NULL;
88     }
89
90     buf_info = calloc(1, sizeof(tdm_buffer_info));
91     if (!buf_info)
92     {
93         if (error)
94             *error = TDM_ERROR_OUT_OF_MEMORY;
95
96         TDM_ERR("'buf_info != NULL' failed");
97
98         return NULL;
99     }
100
101     buf_info->ref_count = 1;
102
103     tbm_surface_internal_ref(buffer);
104     buf_info->buffer = buffer;
105
106     LIST_INITHEAD(&buf_info->release_funcs);
107     LIST_ADDTAIL(&buf_info->link, &buffer_list);
108
109     if (error)
110         *error = TDM_ERROR_NONE;
111
112     return (tdm_buffer*)buf_info;
113 }
114
115 EXTERN tdm_buffer*
116 tdm_buffer_ref(tdm_buffer *buffer, tdm_error *error)
117 {
118     tdm_buffer_info *buf_info;
119
120     if (!buffer)
121     {
122         if (error)
123             *error = TDM_ERROR_INVALID_PARAMETER;
124
125         TDM_ERR("'buffer != NULL' failed");
126
127         return NULL;
128     }
129
130     buf_info = buffer;
131     buf_info->ref_count++;
132
133     if (error)
134         *error = TDM_ERROR_NONE;
135
136     return buffer;
137 }
138
139 EXTERN void
140 tdm_buffer_unref(tdm_buffer *buffer)
141 {
142     tdm_buffer_info *buf_info;
143     tdm_buffer_func_info *func_info = NULL, *next = NULL;
144
145     if (!buffer)
146         return;
147
148     buf_info = buffer;
149     buf_info->ref_count--;
150
151     if (buf_info->ref_count > 0)
152         return;
153
154     /* Before ref_count become 0, all backend reference should be removed */
155     TDM_WARNING_IF_FAIL(buf_info->backend_ref_count == 0);
156
157     LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link)
158     {
159         LIST_DEL(&func_info->link);
160         free(func_info);
161     }
162
163     LIST_DEL(&buf_info->link);
164
165     tbm_surface_internal_unref(buf_info->buffer);
166
167     free(buf_info);
168 }
169
170 EXTERN tdm_error
171 tdm_buffer_add_release_handler(tdm_buffer *buffer,
172                                tdm_buffer_release_handler func, void *user_data)
173 {
174     tdm_buffer_info *buf_info;
175     tdm_buffer_func_info *func_info;
176
177     TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
178     TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
179
180     func_info = calloc(1, sizeof(tdm_buffer_func_info));
181     TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY);
182
183     func_info->func = func;
184     func_info->user_data = user_data;
185
186     buf_info = buffer;
187     LIST_ADD(&func_info->link, &buf_info->release_funcs);
188
189     return TDM_ERROR_NONE;
190 }
191
192 EXTERN void
193 tdm_buffer_remove_release_handler(tdm_buffer *buffer, tdm_buffer_release_handler func, void *user_data)
194 {
195     tdm_buffer_info *buf_info;
196     tdm_buffer_func_info *func_info = NULL, *next = NULL;
197
198     TDM_RETURN_IF_FAIL(buffer != NULL);
199     TDM_RETURN_IF_FAIL(func != NULL);
200
201     buf_info = buffer;
202     LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link)
203     {
204         if (func_info->func != func || func_info->user_data != user_data)
205             continue;
206
207         LIST_DEL(&func_info->link);
208         free(func_info);
209
210         return;
211     }
212 }
213
214
215 INTERN tdm_buffer*
216 tdm_buffer_ref_backend(tdm_buffer *buffer)
217 {
218     tdm_buffer_info *buf_info;
219
220     TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL);
221
222     buf_info = buffer;
223     buf_info->backend_ref_count++;
224
225     return buffer;
226 }
227
228 INTERN void
229 tdm_buffer_unref_backend(tdm_buffer *buffer)
230 {
231     tdm_buffer_info *buf_info;
232     tdm_buffer_func_info *func_info = NULL, *next = NULL;
233
234     TDM_RETURN_IF_FAIL(buffer != NULL);
235
236     buf_info = buffer;
237     buf_info->backend_ref_count--;
238
239     if (buf_info->backend_ref_count > 0)
240         return;
241
242     LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link)
243         func_info->func(buffer, func_info->user_data);
244 }
245
246 INTERN tbm_surface_h
247 tdm_buffer_get_surface(tdm_buffer *buffer)
248 {
249     tdm_buffer_info *buf_info = buffer;
250
251     TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, NULL);
252
253     return buf_info->buffer;
254 }
255
256 INTERN tdm_buffer*
257 tdm_buffer_get(tbm_surface_h buffer)
258 {
259     tdm_buffer_info *found;
260
261     TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL);
262
263     if (!buffer_list_init)
264     {
265         LIST_INITHEAD(&buffer_list);
266         buffer_list_init = 1;
267     }
268
269     LIST_FOR_EACH_ENTRY(found, &buffer_list, link)
270     {
271         if (found->buffer == buffer)
272             return found;
273     }
274
275     return NULL;
276 }