get tdm_buffer from buffer_list
[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     free(buf_info);
164 }
165
166 EXTERN tdm_error
167 tdm_buffer_add_release_handler(tdm_buffer *buffer,
168                                tdm_buffer_release_handler func, void *user_data)
169 {
170     tdm_buffer_info *buf_info;
171     tdm_buffer_func_info *func_info;
172
173     TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
174     TDM_RETURN_VAL_IF_FAIL(func != NULL, TDM_ERROR_INVALID_PARAMETER);
175
176     func_info = calloc(1, sizeof(tdm_buffer_func_info));
177     TDM_RETURN_VAL_IF_FAIL(func_info != NULL, TDM_ERROR_OUT_OF_MEMORY);
178
179     func_info->func = func;
180     func_info->user_data = user_data;
181
182     buf_info = buffer;
183     LIST_ADD(&func_info->link, &buf_info->release_funcs);
184
185     return TDM_ERROR_NONE;
186 }
187
188 EXTERN void
189 tdm_buffer_remove_release_handler(tdm_buffer *buffer, tdm_buffer_release_handler func, void *user_data)
190 {
191     tdm_buffer_info *buf_info;
192     tdm_buffer_func_info *func_info = NULL, *next = NULL;
193
194     TDM_RETURN_IF_FAIL(buffer != NULL);
195     TDM_RETURN_IF_FAIL(func != NULL);
196
197     buf_info = buffer;
198     LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link)
199     {
200         if (func_info->func != func || func_info->user_data != user_data)
201             continue;
202
203         LIST_DEL(&func_info->link);
204         free(func_info);
205
206         return;
207     }
208 }
209
210
211 INTERN tdm_buffer*
212 tdm_buffer_ref_backend(tdm_buffer *buffer)
213 {
214     tdm_buffer_info *buf_info;
215
216     TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL);
217
218     buf_info = buffer;
219     buf_info->backend_ref_count++;
220
221     return buffer;
222 }
223
224 INTERN void
225 tdm_buffer_unref_backend(tdm_buffer *buffer)
226 {
227     tdm_buffer_info *buf_info;
228     tdm_buffer_func_info *func_info = NULL, *next = NULL;
229
230     TDM_RETURN_IF_FAIL(buffer != NULL);
231
232     buf_info = buffer;
233     buf_info->backend_ref_count--;
234
235     if (buf_info->backend_ref_count > 0)
236         return;
237
238     LIST_FOR_EACH_ENTRY_SAFE(func_info, next, &buf_info->release_funcs, link)
239         func_info->func(buffer, func_info->user_data);
240 }
241
242 INTERN tbm_surface_h
243 tdm_buffer_get_surface(tdm_buffer *buffer)
244 {
245     tdm_buffer_info *buf_info = buffer;
246
247     TDM_RETURN_VAL_IF_FAIL(buf_info != NULL, NULL);
248
249     return buf_info->buffer;
250 }
251
252 INTERN tdm_buffer*
253 tdm_buffer_get(tbm_surface_h buffer)
254 {
255     tdm_buffer_info *found;
256
257     TDM_RETURN_VAL_IF_FAIL(buffer != NULL, NULL);
258
259     if (!buffer_list_init)
260     {
261         LIST_INITHEAD(&buffer_list);
262         buffer_list_init = 1;
263     }
264
265     LIST_FOR_EACH_ENTRY(found, &buffer_list, link)
266     {
267         if (found->buffer == buffer)
268             return found;
269     }
270
271     return NULL;
272 }