change deprecated APIs
[platform/core/uifw/libtdm.git] / src / tdm_capture.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_backend.h"
42 #include "tdm_private.h"
43
44 #define CAPTURE_FUNC_ENTRY() \
45     tdm_func_capture *func_capture; \
46     tdm_private_display *private_display; \
47     tdm_private_capture *private_capture; \
48     tdm_error ret = TDM_ERROR_NONE; \
49     TDM_RETURN_VAL_IF_FAIL(capture != NULL, TDM_ERROR_INVALID_PARAMETER); \
50     private_capture = (tdm_private_capture*)capture; \
51     private_display = private_capture->private_display; \
52     func_capture = &private_display->func_capture
53
54 static void
55 _tdm_caputre_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer,
56                      void *user_data)
57 {
58         tdm_private_capture *private_capture = user_data;
59         tdm_private_display *private_display = private_capture->private_display;
60         tdm_buffer_info *buf_info;
61         tbm_surface_h first_entry;
62         int lock_after_cb_done = 0;
63         int ret;
64
65         if (tdm_debug_buffer)
66                 TDM_INFO("capture(%p) done: %p", private_capture, buffer);
67
68         first_entry = tdm_buffer_list_get_first_entry(&private_capture->buffer_list);
69         if (first_entry != buffer)
70                 TDM_ERR("%p is skipped", first_entry);
71
72         if ((buf_info = tdm_buffer_get_info(buffer)))
73                 LIST_DEL(&buf_info->link);
74
75         ret = pthread_mutex_trylock(&private_display->lock);
76         if (ret == 0)
77                 pthread_mutex_unlock(&private_display->lock);
78         else  if (ret == EBUSY) {
79                 pthread_mutex_unlock(&private_display->lock);
80                 lock_after_cb_done = 1;
81         }
82
83         tdm_buffer_unref_backend(buffer);
84
85         if (lock_after_cb_done)
86                 pthread_mutex_lock(&private_display->lock);
87 }
88
89 INTERN tdm_private_capture *
90 tdm_capture_create_output_internal(tdm_private_output *private_output,
91                                    tdm_error *error)
92 {
93         tdm_private_display *private_display = private_output->private_display;
94         tdm_func_output *func_output = &private_display->func_output;
95         tdm_func_capture *func_capture = &private_display->func_capture;
96         tdm_private_capture *private_capture = NULL;
97         tdm_capture *capture_backend = NULL;
98         tdm_error ret = TDM_ERROR_NONE;
99
100         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
101                 TDM_ERR("no capture capability");
102                 if (error)
103                         *error = TDM_ERROR_NO_CAPABILITY;
104                 return NULL;
105         }
106
107         capture_backend = func_output->output_create_capture(
108                                   private_output->output_backend, &ret);
109         if (ret != TDM_ERROR_NONE) {
110                 if (error)
111                         *error = ret;
112                 return NULL;
113         }
114
115         private_capture = calloc(1, sizeof(tdm_private_capture));
116         if (!private_capture) {
117                 TDM_ERR("failed: alloc memory");
118                 func_capture->capture_destroy(capture_backend);
119                 if (error)
120                         *error = TDM_ERROR_OUT_OF_MEMORY;
121                 return NULL;
122         }
123
124         ret = func_capture->capture_set_done_handler(capture_backend,
125                         _tdm_caputre_cb_done, private_capture);
126         if (ret != TDM_ERROR_NONE) {
127                 TDM_ERR("capture(%p) set capture_done_handler failed", private_capture);
128                 func_capture->capture_destroy(capture_backend);
129                 if (error)
130                         *error = ret;
131                 return NULL;
132         }
133
134         LIST_ADD(&private_capture->link, &private_output->capture_list);
135         private_capture->target = TDM_CAPTURE_TARGET_OUTPUT;
136         private_capture->private_display = private_display;
137         private_capture->private_output = private_output;
138         private_capture->private_layer = NULL;
139         private_capture->capture_backend = capture_backend;
140
141         LIST_INITHEAD(&private_capture->pending_buffer_list);
142         LIST_INITHEAD(&private_capture->buffer_list);
143
144         if (error)
145                 *error = TDM_ERROR_NONE;
146
147         return private_capture;
148 }
149
150 INTERN tdm_private_capture *
151 tdm_capture_create_layer_internal(tdm_private_layer *private_layer,
152                                   tdm_error *error)
153 {
154         tdm_private_output *private_output = private_layer->private_output;
155         tdm_private_display *private_display = private_output->private_display;
156         tdm_func_layer *func_layer = &private_display->func_layer;
157         tdm_func_capture *func_capture = &private_display->func_capture;
158         tdm_private_capture *private_capture = NULL;
159         tdm_capture *capture_backend = NULL;
160         tdm_error ret = TDM_ERROR_NONE;
161
162         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
163                 TDM_ERR("no capture capability");
164                 if (error)
165                         *error = TDM_ERROR_NO_CAPABILITY;
166                 return NULL;
167         }
168
169         capture_backend = func_layer->layer_create_capture(private_layer->layer_backend,
170                           &ret);
171         if (ret != TDM_ERROR_NONE)
172                 return NULL;
173
174         private_capture = calloc(1, sizeof(tdm_private_capture));
175         if (!private_capture) {
176                 TDM_ERR("failed: alloc memory");
177                 func_capture->capture_destroy(capture_backend);
178                 if (error)
179                         *error = TDM_ERROR_OUT_OF_MEMORY;
180                 return NULL;
181         }
182
183         LIST_ADD(&private_capture->link, &private_output->capture_list);
184         private_capture->target = TDM_CAPTURE_TARGET_LAYER;
185         private_capture->private_display = private_display;
186         private_capture->private_output = private_output;
187         private_capture->private_layer = private_layer;
188         private_capture->capture_backend = capture_backend;
189
190         LIST_INITHEAD(&private_capture->pending_buffer_list);
191         LIST_INITHEAD(&private_capture->buffer_list);
192
193         if (error)
194                 *error = TDM_ERROR_NONE;
195
196         return private_capture;
197 }
198
199 INTERN void
200 tdm_capture_destroy_internal(tdm_private_capture *private_capture)
201 {
202         tdm_func_capture *func_capture;
203         tdm_buffer_info *b = NULL, *bb = NULL;
204
205         if (!private_capture)
206                 return;
207
208         LIST_DEL(&private_capture->link);
209
210         func_capture = &private_capture->private_display->func_capture;
211         func_capture->capture_destroy(private_capture->capture_backend);
212
213         if (!LIST_IS_EMPTY(&private_capture->pending_buffer_list)) {
214                 TDM_ERR("capture(%p) not finished:", private_capture);
215                 tdm_buffer_list_dump(&private_capture->pending_buffer_list);
216
217                 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link)
218                         LIST_DEL(&b->link);
219         }
220
221         if (!LIST_IS_EMPTY(&private_capture->buffer_list)) {
222                 TDM_ERR("capture(%p) not finished:", private_capture);
223                 tdm_buffer_list_dump(&private_capture->buffer_list);
224
225                 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->buffer_list, link)
226                         LIST_DEL(&b->link);
227         }
228
229         free(private_capture);
230 }
231
232 EXTERN void
233 tdm_capture_destroy(tdm_capture *capture)
234 {
235         tdm_private_capture *private_capture = capture;
236         tdm_private_display *private_display;
237
238         if (!private_capture)
239                 return;
240
241         private_display = private_capture->private_display;
242
243         pthread_mutex_lock(&private_display->lock);
244         tdm_capture_destroy_internal(private_capture);
245         pthread_mutex_unlock(&private_display->lock);
246 }
247
248 EXTERN tdm_error
249 tdm_capture_set_info(tdm_capture *capture, tdm_info_capture *info)
250 {
251         CAPTURE_FUNC_ENTRY();
252
253         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
254
255         pthread_mutex_lock(&private_display->lock);
256
257         if (!func_capture->capture_set_info) {
258                 pthread_mutex_unlock(&private_display->lock);
259                 return TDM_ERROR_NONE;
260         }
261
262         ret = func_capture->capture_set_info(private_capture->capture_backend, info);
263         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
264
265         pthread_mutex_unlock(&private_display->lock);
266
267         return ret;
268 }
269
270 EXTERN tdm_error
271 tdm_capture_attach(tdm_capture *capture, tbm_surface_h buffer)
272 {
273         CAPTURE_FUNC_ENTRY();
274
275         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
276
277         pthread_mutex_lock(&private_display->lock);
278
279         if (!func_capture->capture_attach) {
280                 pthread_mutex_unlock(&private_display->lock);
281                 return TDM_ERROR_NONE;
282         }
283
284         ret = func_capture->capture_attach(private_capture->capture_backend, buffer);
285         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
286
287         if (ret == TDM_ERROR_NONE) {
288                 tdm_buffer_info *buf_info;
289
290                 if ((buf_info = tdm_buffer_get_info(buffer)))
291                         LIST_ADDTAIL(&buf_info->link, &private_capture->pending_buffer_list);
292
293                 if (tdm_debug_buffer) {
294                         TDM_INFO("capture(%p) attached:", private_capture);
295                         tdm_buffer_list_dump(&private_capture->buffer_list);
296                 }
297         }
298
299         pthread_mutex_unlock(&private_display->lock);
300
301         return ret;
302 }
303
304 EXTERN tdm_error
305 tdm_capture_commit(tdm_capture *capture)
306 {
307         tdm_buffer_info *b = NULL, *bb = NULL;
308
309         CAPTURE_FUNC_ENTRY();
310
311         pthread_mutex_lock(&private_display->lock);
312
313         if (!func_capture->capture_commit) {
314                 pthread_mutex_unlock(&private_display->lock);
315                 return TDM_ERROR_NONE;
316         }
317
318         ret = func_capture->capture_commit(private_capture->capture_backend);
319         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
320
321         if (ret == TDM_ERROR_NONE) {
322                 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link) {
323                         LIST_DEL(&b->link);
324                         tdm_buffer_ref_backend(b->buffer);
325                         LIST_ADDTAIL(&b->link, &private_capture->buffer_list);
326                 }
327         } else {
328                 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link)
329                         LIST_DEL(&b->link);
330         }
331
332         pthread_mutex_unlock(&private_display->lock);
333
334         return ret;
335 }