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;
85 int lock_after_cb_done = 0;
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 ret = pthread_mutex_trylock(&private_display->lock);
119 _pthread_mutex_unlock(&private_display->lock);
120 else if (ret == EBUSY) {
121 _pthread_mutex_unlock(&private_display->lock);
122 lock_after_cb_done = 1;
125 tdm_buffer_unref_backend(buffer);
127 if (lock_after_cb_done)
128 _pthread_mutex_lock(&private_display->lock);
131 INTERN tdm_private_capture *
132 tdm_capture_find_stamp(tdm_private_display *private_display, unsigned long stamp)
134 tdm_private_capture *private_capture = NULL;
136 LIST_FOR_EACH_ENTRY(private_capture, &private_display->capture_list, link) {
137 if (private_capture->stamp == stamp)
138 return private_capture;
144 INTERN tdm_private_capture *
145 tdm_capture_create_output_internal(tdm_private_output *private_output,
148 tdm_private_display *private_display = private_output->private_display;
149 tdm_func_output *func_output = &private_display->func_output;
150 tdm_func_capture *func_capture = &private_display->func_capture;
151 tdm_private_capture *private_capture = NULL;
152 tdm_capture *capture_backend = NULL;
153 tdm_error ret = TDM_ERROR_NONE;
155 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
156 TDM_ERR("no capture capability");
158 *error = TDM_ERROR_NO_CAPABILITY;
162 capture_backend = func_output->output_create_capture(
163 private_output->output_backend, &ret);
164 if (ret != TDM_ERROR_NONE) {
170 private_capture = calloc(1, sizeof(tdm_private_capture));
171 if (!private_capture) {
172 TDM_ERR("failed: alloc memory");
173 func_capture->capture_destroy(capture_backend);
175 *error = TDM_ERROR_OUT_OF_MEMORY;
179 ret = func_capture->capture_set_done_handler(capture_backend,
180 tdm_capture_cb_done, private_capture);
181 if (ret != TDM_ERROR_NONE) {
182 TDM_ERR("capture(%p) set capture_done_handler failed", private_capture);
183 func_capture->capture_destroy(capture_backend);
189 private_capture->stamp = tdm_helper_get_time_in_millis();
190 while (tdm_capture_find_stamp(private_display, private_capture->stamp))
191 private_capture->stamp++;
193 LIST_ADD(&private_capture->link, &private_output->capture_list);
194 LIST_ADD(&private_capture->display_link, &private_display->capture_list);
196 private_capture->target = TDM_CAPTURE_TARGET_OUTPUT;
197 private_capture->private_display = private_display;
198 private_capture->private_output = private_output;
199 private_capture->private_layer = NULL;
200 private_capture->capture_backend = capture_backend;
201 private_capture->owner_tid = syscall(SYS_gettid);
203 LIST_INITHEAD(&private_capture->pending_buffer_list);
204 LIST_INITHEAD(&private_capture->buffer_list);
207 *error = TDM_ERROR_NONE;
209 return private_capture;
212 INTERN tdm_private_capture *
213 tdm_capture_create_layer_internal(tdm_private_layer *private_layer,
216 tdm_private_output *private_output = private_layer->private_output;
217 tdm_private_display *private_display = private_output->private_display;
218 tdm_func_layer *func_layer = &private_display->func_layer;
219 tdm_func_capture *func_capture = &private_display->func_capture;
220 tdm_private_capture *private_capture = NULL;
221 tdm_capture *capture_backend = NULL;
222 tdm_error ret = TDM_ERROR_NONE;
224 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_CAPTURE)) {
225 TDM_ERR("no capture capability");
227 *error = TDM_ERROR_NO_CAPABILITY;
231 capture_backend = func_layer->layer_create_capture(private_layer->layer_backend,
233 if (ret != TDM_ERROR_NONE)
236 private_capture = calloc(1, sizeof(tdm_private_capture));
237 if (!private_capture) {
238 TDM_ERR("failed: alloc memory");
239 func_capture->capture_destroy(capture_backend);
241 *error = TDM_ERROR_OUT_OF_MEMORY;
245 private_capture->stamp = tdm_helper_get_time_in_millis();
246 while (tdm_capture_find_stamp(private_display, private_capture->stamp))
247 private_capture->stamp++;
249 LIST_ADD(&private_capture->link, &private_layer->capture_list);
250 LIST_ADD(&private_capture->display_link, &private_display->capture_list);
252 private_capture->target = TDM_CAPTURE_TARGET_LAYER;
253 private_capture->private_display = private_display;
254 private_capture->private_output = private_output;
255 private_capture->private_layer = private_layer;
256 private_capture->capture_backend = capture_backend;
257 private_capture->owner_tid = syscall(SYS_gettid);
259 LIST_INITHEAD(&private_capture->pending_buffer_list);
260 LIST_INITHEAD(&private_capture->buffer_list);
263 *error = TDM_ERROR_NONE;
265 return private_capture;
269 tdm_capture_destroy_internal(tdm_private_capture *private_capture)
271 tdm_private_display *private_display = private_capture->private_display;
272 tdm_func_capture *func_capture;
273 tdm_buffer_info *b = NULL, *bb = NULL;
275 if (!private_capture)
278 LIST_DEL(&private_capture->link);
279 LIST_DEL(&private_capture->display_link);
281 func_capture = &private_capture->private_display->func_capture;
282 func_capture->capture_destroy(private_capture->capture_backend);
284 if (!LIST_IS_EMPTY(&private_capture->pending_buffer_list)) {
285 TDM_ERR("capture(%p) not finished:", private_capture);
286 tdm_buffer_list_dump(&private_capture->pending_buffer_list);
288 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link) {
290 _pthread_mutex_unlock(&private_display->lock);
291 tdm_buffer_unref_backend(b->buffer);
292 _pthread_mutex_lock(&private_display->lock);
296 if (!LIST_IS_EMPTY(&private_capture->buffer_list)) {
297 TDM_ERR("capture(%p) not finished:", private_capture);
298 tdm_buffer_list_dump(&private_capture->buffer_list);
300 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->buffer_list, link) {
302 _pthread_mutex_unlock(&private_display->lock);
303 tdm_buffer_unref_backend(b->buffer);
304 _pthread_mutex_lock(&private_display->lock);
308 private_capture->stamp = 0;
309 free(private_capture);
313 tdm_capture_destroy(tdm_capture *capture)
315 tdm_private_capture *private_capture = capture;
316 tdm_private_display *private_display;
318 if (!private_capture)
321 private_display = private_capture->private_display;
323 _pthread_mutex_lock(&private_display->lock);
324 tdm_capture_destroy_internal(private_capture);
325 _pthread_mutex_unlock(&private_display->lock);
329 tdm_capture_set_info(tdm_capture *capture, tdm_info_capture *info)
331 CAPTURE_FUNC_ENTRY();
333 TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
335 _pthread_mutex_lock(&private_display->lock);
337 if (!func_capture->capture_set_info) {
338 _pthread_mutex_unlock(&private_display->lock);
339 TDM_DBG("failed: not implemented!!");
340 return TDM_ERROR_NOT_IMPLEMENTED;
343 ret = func_capture->capture_set_info(private_capture->capture_backend, info);
344 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
346 _pthread_mutex_unlock(&private_display->lock);
352 tdm_capture_attach(tdm_capture *capture, tbm_surface_h buffer)
354 CAPTURE_FUNC_ENTRY();
356 TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
358 _pthread_mutex_lock(&private_display->lock);
360 if (!func_capture->capture_attach) {
361 _pthread_mutex_unlock(&private_display->lock);
362 TDM_DBG("failed: not implemented!!");
363 return TDM_ERROR_NOT_IMPLEMENTED;
366 ret = _tdm_capture_check_if_exist(private_capture, buffer);
367 if (ret != TDM_ERROR_NONE) {
368 _pthread_mutex_unlock(&private_display->lock);
372 ret = func_capture->capture_attach(private_capture->capture_backend, buffer);
373 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
375 if (ret == TDM_ERROR_NONE) {
376 tdm_buffer_info *buf_info;
378 if ((buf_info = tdm_buffer_get_info(buffer)))
379 LIST_ADDTAIL(&buf_info->link, &private_capture->pending_buffer_list);
381 if (tdm_debug_buffer) {
382 TDM_INFO("capture(%p) attached:", private_capture);
383 tdm_buffer_list_dump(&private_capture->buffer_list);
387 _pthread_mutex_unlock(&private_display->lock);
393 tdm_capture_commit(tdm_capture *capture)
395 tdm_buffer_info *b = NULL, *bb = NULL;
396 tdm_private_output *private_output;
398 CAPTURE_FUNC_ENTRY();
400 _pthread_mutex_lock(&private_display->lock);
402 private_output = private_capture->private_output;
403 if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
404 TDM_WRN("output(%d) dpms: %s", private_output->pipe,
405 dpms_str(private_output->current_dpms_value));
406 _pthread_mutex_unlock(&private_display->lock);
407 return TDM_ERROR_BAD_REQUEST;
410 if (!func_capture->capture_commit) {
411 _pthread_mutex_unlock(&private_display->lock);
412 TDM_DBG("failed: not implemented!!");
413 return TDM_ERROR_NOT_IMPLEMENTED;
416 ret = func_capture->capture_commit(private_capture->capture_backend);
417 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
419 if (ret == TDM_ERROR_NONE) {
420 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link) {
422 tdm_buffer_ref_backend(b->buffer);
423 LIST_ADDTAIL(&b->link, &private_capture->buffer_list);
426 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link)
430 _pthread_mutex_unlock(&private_display->lock);