1 /**************************************************************************
5 Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
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>
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:
22 The above copyright notice and this permission notice (including the
23 next paragraph) shall be included in all copies or substantial portions
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.
34 **************************************************************************/
41 #include "tdm_backend.h"
42 #include "tdm_private.h"
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
55 _tdm_caputre_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer,
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;
66 TDM_INFO("capture(%p) done: %p", private_capture, buffer);
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);
72 if ((buf_info = tdm_buffer_get_info(buffer)))
73 LIST_DEL(&buf_info->link);
75 ret = pthread_mutex_trylock(&private_display->lock);
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;
83 tdm_buffer_unref_backend(buffer);
85 if (lock_after_cb_done)
86 pthread_mutex_lock(&private_display->lock);
89 INTERN tdm_private_capture *
90 tdm_capture_create_output_internal(tdm_private_output *private_output,
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;
100 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
101 TDM_ERR("no capture capability");
103 *error = TDM_ERROR_NO_CAPABILITY;
107 capture_backend = func_output->output_create_capture(
108 private_output->output_backend, &ret);
109 if (ret != TDM_ERROR_NONE) {
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);
120 *error = TDM_ERROR_OUT_OF_MEMORY;
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);
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;
141 LIST_INITHEAD(&private_capture->pending_buffer_list);
142 LIST_INITHEAD(&private_capture->buffer_list);
145 *error = TDM_ERROR_NONE;
147 return private_capture;
150 INTERN tdm_private_capture *
151 tdm_capture_create_layer_internal(tdm_private_layer *private_layer,
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;
162 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
163 TDM_ERR("no capture capability");
165 *error = TDM_ERROR_NO_CAPABILITY;
169 capture_backend = func_layer->layer_create_capture(private_layer->layer_backend,
171 if (ret != TDM_ERROR_NONE)
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);
179 *error = TDM_ERROR_OUT_OF_MEMORY;
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;
190 LIST_INITHEAD(&private_capture->pending_buffer_list);
191 LIST_INITHEAD(&private_capture->buffer_list);
194 *error = TDM_ERROR_NONE;
196 return private_capture;
200 tdm_capture_destroy_internal(tdm_private_capture *private_capture)
202 tdm_func_capture *func_capture;
203 tdm_buffer_info *b = NULL, *bb = NULL;
205 if (!private_capture)
208 LIST_DEL(&private_capture->link);
210 func_capture = &private_capture->private_display->func_capture;
211 func_capture->capture_destroy(private_capture->capture_backend);
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);
217 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link)
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);
225 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->buffer_list, link)
229 free(private_capture);
233 tdm_capture_destroy(tdm_capture *capture)
235 tdm_private_capture *private_capture = capture;
236 tdm_private_display *private_display;
238 if (!private_capture)
241 private_display = private_capture->private_display;
243 pthread_mutex_lock(&private_display->lock);
244 tdm_capture_destroy_internal(private_capture);
245 pthread_mutex_unlock(&private_display->lock);
249 tdm_capture_set_info(tdm_capture *capture, tdm_info_capture *info)
251 CAPTURE_FUNC_ENTRY();
253 TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
255 pthread_mutex_lock(&private_display->lock);
257 if (!func_capture->capture_set_info) {
258 pthread_mutex_unlock(&private_display->lock);
259 return TDM_ERROR_NONE;
262 ret = func_capture->capture_set_info(private_capture->capture_backend, info);
263 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
265 pthread_mutex_unlock(&private_display->lock);
271 tdm_capture_attach(tdm_capture *capture, tbm_surface_h buffer)
273 CAPTURE_FUNC_ENTRY();
275 TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
277 pthread_mutex_lock(&private_display->lock);
279 if (!func_capture->capture_attach) {
280 pthread_mutex_unlock(&private_display->lock);
281 return TDM_ERROR_NONE;
284 ret = func_capture->capture_attach(private_capture->capture_backend, buffer);
285 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
287 if (ret == TDM_ERROR_NONE) {
288 tdm_buffer_info *buf_info;
290 if ((buf_info = tdm_buffer_get_info(buffer)))
291 LIST_ADDTAIL(&buf_info->link, &private_capture->pending_buffer_list);
293 if (tdm_debug_buffer) {
294 TDM_INFO("capture(%p) attached:", private_capture);
295 tdm_buffer_list_dump(&private_capture->buffer_list);
299 pthread_mutex_unlock(&private_display->lock);
305 tdm_capture_commit(tdm_capture *capture)
307 tdm_buffer_info *b = NULL, *bb = NULL;
309 CAPTURE_FUNC_ENTRY();
311 pthread_mutex_lock(&private_display->lock);
313 if (!func_capture->capture_commit) {
314 pthread_mutex_unlock(&private_display->lock);
315 return TDM_ERROR_NONE;
318 ret = func_capture->capture_commit(private_capture->capture_backend);
319 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
321 if (ret == TDM_ERROR_NONE) {
322 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link) {
324 tdm_buffer_ref_backend(b->buffer);
325 LIST_ADDTAIL(&b->link, &private_capture->buffer_list);
328 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link)
332 pthread_mutex_unlock(&private_display->lock);