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_capture_check_if_exist(tdm_private_capture *private_capture,
58 tdm_buffer_info *buf_info = NULL;
60 LIST_FOR_EACH_ENTRY(buf_info, &private_capture->buffer_list, link) {
61 if (buf_info->buffer == buffer) {
62 TDM_ERR("%p attached twice", buffer);
63 return TDM_ERROR_BAD_REQUEST;
67 LIST_FOR_EACH_ENTRY(buf_info, &private_capture->pending_buffer_list, link) {
68 if (buf_info->buffer == buffer) {
69 TDM_ERR("%p attached twice", buffer);
70 return TDM_ERROR_BAD_REQUEST;
74 return TDM_ERROR_NONE;
78 tdm_capture_cb_done(tdm_capture *capture_backend, tbm_surface_h buffer,
81 tdm_private_capture *private_capture = user_data;
82 tdm_private_display *private_display = private_capture->private_display;
83 tdm_buffer_info *buf_info;
84 tbm_surface_h first_entry;
86 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
88 if (private_capture->owner_tid != syscall(SYS_gettid)) {
89 tdm_thread_cb_capture_done capture_done;
92 capture_done.base.type = TDM_THREAD_CB_PP_DONE;
93 capture_done.base.length = sizeof capture_done;
94 capture_done.capture_stamp = private_capture->stamp;
95 capture_done.buffer = buffer;
96 capture_done.user_data = user_data;
98 ret = tdm_thread_send_cb(private_display->private_loop, &capture_done.base);
99 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
104 if (private_capture->owner_tid != syscall(SYS_gettid))
105 TDM_NEVER_GET_HERE();
107 if (tdm_debug_buffer)
108 TDM_INFO("capture(%p) done: %p", private_capture, buffer);
110 first_entry = tdm_buffer_list_get_first_entry(&private_capture->buffer_list);
111 if (first_entry != buffer)
112 TDM_ERR("%p is skipped", first_entry);
114 if ((buf_info = tdm_buffer_get_info(buffer)))
115 LIST_DEL(&buf_info->link);
117 _pthread_mutex_unlock(&private_display->lock);
118 tdm_buffer_unref_backend(buffer);
119 _pthread_mutex_lock(&private_display->lock);
122 INTERN tdm_private_capture *
123 tdm_capture_find_stamp(tdm_private_display *private_display, unsigned long stamp)
125 tdm_private_capture *private_capture = NULL;
127 TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL);
129 LIST_FOR_EACH_ENTRY(private_capture, &private_display->capture_list, link) {
130 if (private_capture->stamp == stamp)
131 return private_capture;
137 INTERN tdm_private_capture *
138 tdm_capture_create_output_internal(tdm_private_output *private_output,
141 tdm_private_display *private_display = private_output->private_display;
142 tdm_func_output *func_output = &private_display->func_output;
143 tdm_func_capture *func_capture = &private_display->func_capture;
144 tdm_private_capture *private_capture = NULL;
145 tdm_capture *capture_backend = NULL;
146 tdm_error ret = TDM_ERROR_NONE;
148 TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL);
150 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
151 TDM_ERR("no capture capability");
153 *error = TDM_ERROR_NO_CAPABILITY;
157 capture_backend = func_output->output_create_capture(
158 private_output->output_backend, &ret);
159 if (ret != TDM_ERROR_NONE) {
165 private_capture = calloc(1, sizeof(tdm_private_capture));
166 if (!private_capture) {
167 TDM_ERR("failed: alloc memory");
168 func_capture->capture_destroy(capture_backend);
170 *error = TDM_ERROR_OUT_OF_MEMORY;
174 ret = func_capture->capture_set_done_handler(capture_backend,
175 tdm_capture_cb_done, private_capture);
176 if (ret != TDM_ERROR_NONE) {
177 TDM_ERR("capture(%p) set capture_done_handler failed", private_capture);
178 func_capture->capture_destroy(capture_backend);
184 private_capture->stamp = tdm_helper_get_time_in_millis();
185 while (tdm_capture_find_stamp(private_display, private_capture->stamp))
186 private_capture->stamp++;
188 LIST_ADD(&private_capture->link, &private_output->capture_list);
189 LIST_ADD(&private_capture->display_link, &private_display->capture_list);
191 private_capture->target = TDM_CAPTURE_TARGET_OUTPUT;
192 private_capture->private_display = private_display;
193 private_capture->private_output = private_output;
194 private_capture->private_layer = NULL;
195 private_capture->capture_backend = capture_backend;
196 private_capture->owner_tid = syscall(SYS_gettid);
198 LIST_INITHEAD(&private_capture->pending_buffer_list);
199 LIST_INITHEAD(&private_capture->buffer_list);
202 *error = TDM_ERROR_NONE;
204 return private_capture;
207 INTERN tdm_private_capture *
208 tdm_capture_create_layer_internal(tdm_private_layer *private_layer,
211 tdm_private_output *private_output = private_layer->private_output;
212 tdm_private_display *private_display = private_output->private_display;
213 tdm_func_layer *func_layer = &private_display->func_layer;
214 tdm_func_capture *func_capture = &private_display->func_capture;
215 tdm_private_capture *private_capture = NULL;
216 tdm_capture *capture_backend = NULL;
217 tdm_error ret = TDM_ERROR_NONE;
219 TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL);
221 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
222 TDM_ERR("no capture capability");
224 *error = TDM_ERROR_NO_CAPABILITY;
228 capture_backend = func_layer->layer_create_capture(private_layer->layer_backend,
230 if (ret != TDM_ERROR_NONE)
233 private_capture = calloc(1, sizeof(tdm_private_capture));
234 if (!private_capture) {
235 TDM_ERR("failed: alloc memory");
236 func_capture->capture_destroy(capture_backend);
238 *error = TDM_ERROR_OUT_OF_MEMORY;
242 private_capture->stamp = tdm_helper_get_time_in_millis();
243 while (tdm_capture_find_stamp(private_display, private_capture->stamp))
244 private_capture->stamp++;
246 LIST_ADD(&private_capture->link, &private_layer->capture_list);
247 LIST_ADD(&private_capture->display_link, &private_display->capture_list);
249 private_capture->target = TDM_CAPTURE_TARGET_LAYER;
250 private_capture->private_display = private_display;
251 private_capture->private_output = private_output;
252 private_capture->private_layer = private_layer;
253 private_capture->capture_backend = capture_backend;
254 private_capture->owner_tid = syscall(SYS_gettid);
256 LIST_INITHEAD(&private_capture->pending_buffer_list);
257 LIST_INITHEAD(&private_capture->buffer_list);
260 *error = TDM_ERROR_NONE;
262 return private_capture;
266 tdm_capture_destroy_internal(tdm_private_capture *private_capture)
268 tdm_private_display *private_display;
269 tdm_func_capture *func_capture;
270 tdm_buffer_info *b = NULL, *bb = NULL;
272 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
274 if (!private_capture)
277 private_display = private_capture->private_display;
279 LIST_DEL(&private_capture->link);
280 LIST_DEL(&private_capture->display_link);
282 func_capture = &private_capture->private_display->func_capture;
283 func_capture->capture_destroy(private_capture->capture_backend);
285 if (!LIST_IS_EMPTY(&private_capture->pending_buffer_list)) {
286 TDM_WRN("capture(%p) not finished:", private_capture);
287 tdm_buffer_list_dump(&private_capture->pending_buffer_list);
289 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link) {
291 _pthread_mutex_unlock(&private_display->lock);
292 tdm_buffer_unref_backend(b->buffer);
293 _pthread_mutex_lock(&private_display->lock);
297 if (!LIST_IS_EMPTY(&private_capture->buffer_list)) {
298 TDM_WRN("capture(%p) not finished:", private_capture);
299 tdm_buffer_list_dump(&private_capture->buffer_list);
301 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->buffer_list, link) {
303 _pthread_mutex_unlock(&private_display->lock);
304 tdm_buffer_unref_backend(b->buffer);
305 _pthread_mutex_lock(&private_display->lock);
309 private_capture->stamp = 0;
310 free(private_capture);
314 tdm_capture_destroy(tdm_capture *capture)
316 tdm_private_capture *private_capture = capture;
317 tdm_private_display *private_display;
319 if (!private_capture)
322 private_display = private_capture->private_display;
324 _pthread_mutex_lock(&private_display->lock);
325 tdm_capture_destroy_internal(private_capture);
326 _pthread_mutex_unlock(&private_display->lock);
330 tdm_capture_set_info(tdm_capture *capture, tdm_info_capture *info)
332 CAPTURE_FUNC_ENTRY();
334 TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
336 _pthread_mutex_lock(&private_display->lock);
338 if (!func_capture->capture_set_info) {
339 _pthread_mutex_unlock(&private_display->lock);
340 TDM_DBG("failed: not implemented!!");
341 return TDM_ERROR_NOT_IMPLEMENTED;
344 ret = func_capture->capture_set_info(private_capture->capture_backend, info);
345 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
347 _pthread_mutex_unlock(&private_display->lock);
353 tdm_capture_attach(tdm_capture *capture, tbm_surface_h buffer)
355 CAPTURE_FUNC_ENTRY();
357 TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
359 _pthread_mutex_lock(&private_display->lock);
361 if (!func_capture->capture_attach) {
362 _pthread_mutex_unlock(&private_display->lock);
363 TDM_DBG("failed: not implemented!!");
364 return TDM_ERROR_NOT_IMPLEMENTED;
367 ret = _tdm_capture_check_if_exist(private_capture, buffer);
368 if (ret != TDM_ERROR_NONE) {
369 _pthread_mutex_unlock(&private_display->lock);
373 ret = func_capture->capture_attach(private_capture->capture_backend, buffer);
374 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
376 if (ret == TDM_ERROR_NONE) {
377 tdm_buffer_info *buf_info;
379 if ((buf_info = tdm_buffer_get_info(buffer)))
380 LIST_ADDTAIL(&buf_info->link, &private_capture->pending_buffer_list);
382 if (tdm_debug_buffer) {
383 TDM_INFO("capture(%p) attached:", private_capture);
384 tdm_buffer_list_dump(&private_capture->buffer_list);
388 _pthread_mutex_unlock(&private_display->lock);
394 tdm_capture_commit(tdm_capture *capture)
396 tdm_buffer_info *b = NULL, *bb = NULL;
397 tdm_private_output *private_output;
399 CAPTURE_FUNC_ENTRY();
401 _pthread_mutex_lock(&private_display->lock);
403 private_output = private_capture->private_output;
404 if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
405 TDM_ERR("output(%d) dpms: %s", private_output->pipe,
406 dpms_str(private_output->current_dpms_value));
407 _pthread_mutex_unlock(&private_display->lock);
408 return TDM_ERROR_BAD_REQUEST;
411 if (!func_capture->capture_commit) {
412 _pthread_mutex_unlock(&private_display->lock);
413 TDM_DBG("failed: not implemented!!");
414 return TDM_ERROR_NOT_IMPLEMENTED;
417 ret = func_capture->capture_commit(private_capture->capture_backend);
418 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
420 if (ret == TDM_ERROR_NONE) {
421 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link) {
423 tdm_buffer_ref_backend(b->buffer);
424 LIST_ADDTAIL(&b->link, &private_capture->buffer_list);
427 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link)
431 _pthread_mutex_unlock(&private_display->lock);