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