fix the too many logs when enabled
[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 #include "tdm_helper.h"
44
45 #define CAPTURE_FUNC_ENTRY() \
46         tdm_func_capture *func_capture; \
47         tdm_private_display *private_display; \
48         tdm_private_capture *private_capture; \
49         tdm_error ret = TDM_ERROR_NONE; \
50         TDM_RETURN_VAL_IF_FAIL(capture != NULL, TDM_ERROR_INVALID_PARAMETER); \
51         private_capture = (tdm_private_capture*)capture; \
52         private_display = private_capture->private_display; \
53         func_capture = &private_display->func_capture
54
55 static tdm_error
56 _tdm_capture_check_if_exist(tdm_private_capture *private_capture,
57                                                         tbm_surface_h buffer)
58 {
59         tdm_buffer_info *buf_info = NULL;
60
61         LIST_FOR_EACH_ENTRY(buf_info, &private_capture->buffer_list, link) {
62                 if (buf_info->buffer == buffer) {
63                         TDM_ERR("%p attached twice", buffer);
64                         return TDM_ERROR_BAD_REQUEST;
65                 }
66         }
67
68         LIST_FOR_EACH_ENTRY(buf_info, &private_capture->pending_buffer_list, link) {
69                 if (buf_info->buffer == buffer) {
70                         TDM_ERR("%p attached twice", buffer);
71                         return TDM_ERROR_BAD_REQUEST;
72                 }
73         }
74
75         return TDM_ERROR_NONE;
76 }
77
78 INTERN void
79 tdm_capture_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer,
80                                         void *user_data)
81 {
82         tdm_private_capture *private_capture = user_data;
83         tdm_private_display *private_display = private_capture->private_display;
84         tdm_buffer_info *buf_info;
85         tbm_surface_h first_entry;
86
87         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
88
89         if (private_capture->owner_tid != syscall(SYS_gettid)) {
90                 tdm_thread_cb_capture_done capture_done;
91                 tdm_error ret;
92
93                 capture_done.base.type = TDM_THREAD_CB_PP_DONE;
94                 capture_done.base.length = sizeof capture_done;
95                 capture_done.capture_stamp = private_capture->stamp;
96                 capture_done.buffer = buffer;
97                 capture_done.user_data = user_data;
98
99                 ret = tdm_thread_send_cb(private_display->private_loop, &capture_done.base);
100                 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
101
102                 return;
103         }
104
105         if (private_capture->owner_tid != syscall(SYS_gettid))
106                 TDM_NEVER_GET_HERE();
107
108         if (tdm_debug_dump & TDM_DUMP_FLAG_CAPTURE) {
109                 char str[TDM_PATH_LEN];
110                 static int i;
111                 snprintf(str, TDM_PATH_LEN, "capture_%03d", i++);
112                 tdm_helper_dump_buffer_str(buffer, str);
113         }
114
115         if (tdm_debug_module & TDM_DEBUG_BUFFER)
116                 TDM_INFO("capture(%p) done: %p", private_capture, buffer);
117
118         first_entry = tdm_buffer_list_get_first_entry(&private_capture->buffer_list);
119         if (first_entry != buffer)
120                 TDM_ERR("%p is skipped", first_entry);
121
122         if ((buf_info = tdm_buffer_get_info(buffer)))
123                 LIST_DEL(&buf_info->link);
124
125         _pthread_mutex_unlock(&private_display->lock);
126         tdm_buffer_unref_backend(buffer);
127         _pthread_mutex_lock(&private_display->lock);
128 }
129
130 INTERN tdm_private_capture *
131 tdm_capture_find_stamp(tdm_private_display *private_display, unsigned long stamp)
132 {
133         tdm_private_capture *private_capture = NULL;
134
135         TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL);
136
137         LIST_FOR_EACH_ENTRY(private_capture, &private_display->capture_list, link) {
138                 if (private_capture->stamp == stamp)
139                         return private_capture;
140         }
141
142         return NULL;
143 }
144
145 INTERN tdm_private_capture *
146 tdm_capture_create_output_internal(tdm_private_output *private_output,
147                                                                    tdm_error *error)
148 {
149         tdm_private_display *private_display = private_output->private_display;
150         tdm_func_output *func_output = &private_display->func_output;
151         tdm_func_capture *func_capture = &private_display->func_capture;
152         tdm_private_capture *private_capture = NULL;
153         tdm_capture *capture_backend = NULL;
154         tdm_error ret = TDM_ERROR_NONE;
155
156         TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL);
157
158         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
159                 TDM_ERR("no capture capability");
160                 if (error)
161                         *error = TDM_ERROR_NO_CAPABILITY;
162                 return NULL;
163         }
164
165         capture_backend = func_output->output_create_capture(
166                                                   private_output->output_backend, &ret);
167         if (ret != TDM_ERROR_NONE) {
168                 if (error)
169                         *error = ret;
170                 return NULL;
171         }
172
173         private_capture = calloc(1, sizeof(tdm_private_capture));
174         if (!private_capture) {
175                 TDM_ERR("failed: alloc memory");
176                 func_capture->capture_destroy(capture_backend);
177                 if (error)
178                         *error = TDM_ERROR_OUT_OF_MEMORY;
179                 return NULL;
180         }
181
182         ret = func_capture->capture_set_done_handler(capture_backend,
183                         tdm_capture_cb_done, private_capture);
184         if (ret != TDM_ERROR_NONE) {
185                 TDM_ERR("capture(%p) set capture_done_handler failed", private_capture);
186                 func_capture->capture_destroy(capture_backend);
187                 if (error)
188                         *error = ret;
189                 return NULL;
190         }
191
192         private_capture->stamp = tdm_helper_get_time_in_millis();
193         while (tdm_capture_find_stamp(private_display, private_capture->stamp))
194                 private_capture->stamp++;
195
196         LIST_ADD(&private_capture->link, &private_output->capture_list);
197         LIST_ADD(&private_capture->display_link, &private_display->capture_list);
198
199         private_capture->target = TDM_CAPTURE_TARGET_OUTPUT;
200         private_capture->private_display = private_display;
201         private_capture->private_output = private_output;
202         private_capture->private_layer = NULL;
203         private_capture->capture_backend = capture_backend;
204         private_capture->owner_tid = syscall(SYS_gettid);
205
206         LIST_INITHEAD(&private_capture->pending_buffer_list);
207         LIST_INITHEAD(&private_capture->buffer_list);
208
209         if (error)
210                 *error = TDM_ERROR_NONE;
211
212         return private_capture;
213 }
214
215 INTERN tdm_private_capture *
216 tdm_capture_create_layer_internal(tdm_private_layer *private_layer,
217                                                                   tdm_error *error)
218 {
219         tdm_private_output *private_output = private_layer->private_output;
220         tdm_private_display *private_display = private_output->private_display;
221         tdm_func_layer *func_layer = &private_display->func_layer;
222         tdm_func_capture *func_capture = &private_display->func_capture;
223         tdm_private_capture *private_capture = NULL;
224         tdm_capture *capture_backend = NULL;
225         tdm_error ret = TDM_ERROR_NONE;
226
227         TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL);
228
229         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
230                 TDM_ERR("no capture capability");
231                 if (error)
232                         *error = TDM_ERROR_NO_CAPABILITY;
233                 return NULL;
234         }
235
236         capture_backend = func_layer->layer_create_capture(private_layer->layer_backend,
237                                           &ret);
238         if (ret != TDM_ERROR_NONE)
239                 return NULL;
240
241         private_capture = calloc(1, sizeof(tdm_private_capture));
242         if (!private_capture) {
243                 TDM_ERR("failed: alloc memory");
244                 func_capture->capture_destroy(capture_backend);
245                 if (error)
246                         *error = TDM_ERROR_OUT_OF_MEMORY;
247                 return NULL;
248         }
249
250         private_capture->stamp = tdm_helper_get_time_in_millis();
251         while (tdm_capture_find_stamp(private_display, private_capture->stamp))
252                 private_capture->stamp++;
253
254         LIST_ADD(&private_capture->link, &private_layer->capture_list);
255         LIST_ADD(&private_capture->display_link, &private_display->capture_list);
256
257         private_capture->target = TDM_CAPTURE_TARGET_LAYER;
258         private_capture->private_display = private_display;
259         private_capture->private_output = private_output;
260         private_capture->private_layer = private_layer;
261         private_capture->capture_backend = capture_backend;
262         private_capture->owner_tid = syscall(SYS_gettid);
263
264         LIST_INITHEAD(&private_capture->pending_buffer_list);
265         LIST_INITHEAD(&private_capture->buffer_list);
266
267         if (error)
268                 *error = TDM_ERROR_NONE;
269
270         return private_capture;
271 }
272
273 INTERN void
274 tdm_capture_destroy_internal(tdm_private_capture *private_capture)
275 {
276         tdm_private_display *private_display;
277         tdm_func_capture *func_capture;
278         tdm_buffer_info *b = NULL, *bb = NULL;
279
280         TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
281
282         if (!private_capture)
283                 return;
284
285         private_display = private_capture->private_display;
286
287         LIST_DEL(&private_capture->link);
288         LIST_DEL(&private_capture->display_link);
289
290         func_capture = &private_capture->private_display->func_capture;
291         func_capture->capture_destroy(private_capture->capture_backend);
292
293         if (!LIST_IS_EMPTY(&private_capture->pending_buffer_list)) {
294                 TDM_WRN("capture(%p) not finished:", private_capture);
295                 tdm_buffer_list_dump(&private_capture->pending_buffer_list);
296
297                 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link) {
298                         LIST_DEL(&b->link);
299                         _pthread_mutex_unlock(&private_display->lock);
300                         tdm_buffer_unref_backend(b->buffer);
301                         _pthread_mutex_lock(&private_display->lock);
302                 }
303         }
304
305         if (!LIST_IS_EMPTY(&private_capture->buffer_list)) {
306                 TDM_WRN("capture(%p) not finished:", private_capture);
307                 tdm_buffer_list_dump(&private_capture->buffer_list);
308
309                 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->buffer_list, link) {
310                         LIST_DEL(&b->link);
311                         _pthread_mutex_unlock(&private_display->lock);
312                         tdm_buffer_unref_backend(b->buffer);
313                         _pthread_mutex_lock(&private_display->lock);
314                 }
315         }
316
317         private_capture->stamp = 0;
318         free(private_capture);
319 }
320
321 EXTERN void
322 tdm_capture_destroy(tdm_capture *capture)
323 {
324         tdm_private_capture *private_capture = capture;
325         tdm_private_display *private_display;
326
327         if (!private_capture)
328                 return;
329
330         private_display = private_capture->private_display;
331
332         _pthread_mutex_lock(&private_display->lock);
333         tdm_capture_destroy_internal(private_capture);
334         _pthread_mutex_unlock(&private_display->lock);
335 }
336
337 EXTERN tdm_error
338 tdm_capture_set_info(tdm_capture *capture, tdm_info_capture *info)
339 {
340         CAPTURE_FUNC_ENTRY();
341
342         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
343
344         _pthread_mutex_lock(&private_display->lock);
345
346         if (!func_capture->capture_set_info) {
347                 _pthread_mutex_unlock(&private_display->lock);
348                 TDM_DBG("failed: not implemented!!");
349                 return TDM_ERROR_NOT_IMPLEMENTED;
350         }
351
352         ret = func_capture->capture_set_info(private_capture->capture_backend, info);
353         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
354
355         _pthread_mutex_unlock(&private_display->lock);
356
357         return ret;
358 }
359
360 EXTERN tdm_error
361 tdm_capture_attach(tdm_capture *capture, tbm_surface_h buffer)
362 {
363         CAPTURE_FUNC_ENTRY();
364
365         TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
366
367         _pthread_mutex_lock(&private_display->lock);
368
369         if (!func_capture->capture_attach) {
370                 _pthread_mutex_unlock(&private_display->lock);
371                 TDM_DBG("failed: not implemented!!");
372                 return TDM_ERROR_NOT_IMPLEMENTED;
373         }
374
375         ret = _tdm_capture_check_if_exist(private_capture, buffer);
376         if (ret != TDM_ERROR_NONE) {
377                 _pthread_mutex_unlock(&private_display->lock);
378                 return ret;
379         }
380
381         ret = func_capture->capture_attach(private_capture->capture_backend, buffer);
382         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
383
384         if (ret == TDM_ERROR_NONE) {
385                 tdm_buffer_info *buf_info;
386
387                 if ((buf_info = tdm_buffer_get_info(buffer)))
388                         LIST_ADDTAIL(&buf_info->link, &private_capture->pending_buffer_list);
389
390                 if (tdm_debug_module & TDM_DEBUG_BUFFER) {
391                         TDM_INFO("capture(%p) attached:", private_capture);
392                         tdm_buffer_list_dump(&private_capture->buffer_list);
393                 }
394         }
395
396         _pthread_mutex_unlock(&private_display->lock);
397
398         return ret;
399 }
400
401 EXTERN tdm_error
402 tdm_capture_commit(tdm_capture *capture)
403 {
404         tdm_buffer_info *b = NULL, *bb = NULL;
405         tdm_private_output *private_output;
406
407         CAPTURE_FUNC_ENTRY();
408
409         _pthread_mutex_lock(&private_display->lock);
410
411         private_output = private_capture->private_output;
412         if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
413                 TDM_ERR("output(%d) dpms: %s", private_output->pipe,
414                                 tdm_dpms_str(private_output->current_dpms_value));
415                 _pthread_mutex_unlock(&private_display->lock);
416                 return TDM_ERROR_BAD_REQUEST;
417         }
418
419         if (!func_capture->capture_commit) {
420                 _pthread_mutex_unlock(&private_display->lock);
421                 TDM_DBG("failed: not implemented!!");
422                 return TDM_ERROR_NOT_IMPLEMENTED;
423         }
424
425         ret = func_capture->capture_commit(private_capture->capture_backend);
426         TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
427
428         if (ret == TDM_ERROR_NONE) {
429                 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link) {
430                         LIST_DEL(&b->link);
431                         tdm_buffer_ref_backend(b->buffer);
432                         LIST_ADDTAIL(&b->link, &private_capture->buffer_list);
433                 }
434         } else {
435                 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link)
436                         LIST_DEL(&b->link);
437         }
438
439         _pthread_mutex_unlock(&private_display->lock);
440
441         return ret;
442 }