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 = private_capture->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 LIST_DEL(&private_capture->link);
278 LIST_DEL(&private_capture->display_link);
280 func_capture = &private_capture->private_display->func_capture;
281 func_capture->capture_destroy(private_capture->capture_backend);
283 if (!LIST_IS_EMPTY(&private_capture->pending_buffer_list)) {
284 TDM_WRN("capture(%p) not finished:", private_capture);
285 tdm_buffer_list_dump(&private_capture->pending_buffer_list);
287 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link) {
289 _pthread_mutex_unlock(&private_display->lock);
290 tdm_buffer_unref_backend(b->buffer);
291 _pthread_mutex_lock(&private_display->lock);
295 if (!LIST_IS_EMPTY(&private_capture->buffer_list)) {
296 TDM_WRN("capture(%p) not finished:", private_capture);
297 tdm_buffer_list_dump(&private_capture->buffer_list);
299 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->buffer_list, link) {
301 _pthread_mutex_unlock(&private_display->lock);
302 tdm_buffer_unref_backend(b->buffer);
303 _pthread_mutex_lock(&private_display->lock);
307 private_capture->stamp = 0;
308 free(private_capture);
312 tdm_capture_destroy(tdm_capture *capture)
314 tdm_private_capture *private_capture = capture;
315 tdm_private_display *private_display;
317 if (!private_capture)
320 private_display = private_capture->private_display;
322 _pthread_mutex_lock(&private_display->lock);
323 tdm_capture_destroy_internal(private_capture);
324 _pthread_mutex_unlock(&private_display->lock);
328 tdm_capture_set_info(tdm_capture *capture, tdm_info_capture *info)
330 CAPTURE_FUNC_ENTRY();
332 TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
334 _pthread_mutex_lock(&private_display->lock);
336 if (!func_capture->capture_set_info) {
337 _pthread_mutex_unlock(&private_display->lock);
338 TDM_DBG("failed: not implemented!!");
339 return TDM_ERROR_NOT_IMPLEMENTED;
342 ret = func_capture->capture_set_info(private_capture->capture_backend, info);
343 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
345 _pthread_mutex_unlock(&private_display->lock);
351 tdm_capture_attach(tdm_capture *capture, tbm_surface_h buffer)
353 CAPTURE_FUNC_ENTRY();
355 TDM_RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
357 _pthread_mutex_lock(&private_display->lock);
359 if (!func_capture->capture_attach) {
360 _pthread_mutex_unlock(&private_display->lock);
361 TDM_DBG("failed: not implemented!!");
362 return TDM_ERROR_NOT_IMPLEMENTED;
365 ret = _tdm_capture_check_if_exist(private_capture, buffer);
366 if (ret != TDM_ERROR_NONE) {
367 _pthread_mutex_unlock(&private_display->lock);
371 ret = func_capture->capture_attach(private_capture->capture_backend, buffer);
372 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
374 if (ret == TDM_ERROR_NONE) {
375 tdm_buffer_info *buf_info;
377 if ((buf_info = tdm_buffer_get_info(buffer)))
378 LIST_ADDTAIL(&buf_info->link, &private_capture->pending_buffer_list);
380 if (tdm_debug_buffer) {
381 TDM_INFO("capture(%p) attached:", private_capture);
382 tdm_buffer_list_dump(&private_capture->buffer_list);
386 _pthread_mutex_unlock(&private_display->lock);
392 tdm_capture_commit(tdm_capture *capture)
394 tdm_buffer_info *b = NULL, *bb = NULL;
395 tdm_private_output *private_output;
397 CAPTURE_FUNC_ENTRY();
399 _pthread_mutex_lock(&private_display->lock);
401 private_output = private_capture->private_output;
402 if (private_output->current_dpms_value > TDM_OUTPUT_DPMS_ON) {
403 TDM_WRN("output(%d) dpms: %s", private_output->pipe,
404 dpms_str(private_output->current_dpms_value));
405 _pthread_mutex_unlock(&private_display->lock);
406 return TDM_ERROR_BAD_REQUEST;
409 if (!func_capture->capture_commit) {
410 _pthread_mutex_unlock(&private_display->lock);
411 TDM_DBG("failed: not implemented!!");
412 return TDM_ERROR_NOT_IMPLEMENTED;
415 ret = func_capture->capture_commit(private_capture->capture_backend);
416 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
418 if (ret == TDM_ERROR_NONE) {
419 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link) {
421 tdm_buffer_ref_backend(b->buffer);
422 LIST_ADDTAIL(&b->link, &private_capture->buffer_list);
425 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_capture->pending_buffer_list, link)
429 _pthread_mutex_unlock(&private_display->lock);