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 PP_FUNC_ENTRY() \
45 tdm_func_pp *func_pp; \
46 tdm_private_display *private_display; \
47 tdm_private_pp *private_pp; \
48 tdm_error ret = TDM_ERROR_NONE; \
49 TDM_RETURN_VAL_IF_FAIL(pp != NULL, TDM_ERROR_INVALID_PARAMETER); \
50 private_pp = (tdm_private_pp*)pp; \
51 private_display = private_pp->private_display; \
52 func_pp = &private_display->func_pp
55 _tdm_pp_check_if_exist(tdm_private_pp *private_pp,
56 tbm_surface_h src, tbm_surface_h dst)
58 tdm_buffer_info *buf_info = NULL;
60 LIST_FOR_EACH_ENTRY(buf_info, &private_pp->src_buffer_list, link) {
61 if (buf_info->buffer == src) {
62 TDM_ERR("%p attached twice", src);
63 return TDM_ERROR_BAD_REQUEST;
67 LIST_FOR_EACH_ENTRY(buf_info, &private_pp->src_pending_buffer_list, link) {
68 if (buf_info->buffer == src) {
69 TDM_ERR("%p attached twice", src);
70 return TDM_ERROR_BAD_REQUEST;
74 LIST_FOR_EACH_ENTRY(buf_info, &private_pp->dst_buffer_list, link) {
75 if (buf_info->buffer == dst) {
76 TDM_ERR("%p attached twice", dst);
77 return TDM_ERROR_BAD_REQUEST;
81 LIST_FOR_EACH_ENTRY(buf_info, &private_pp->dst_pending_buffer_list, link) {
82 if (buf_info->buffer == dst) {
83 TDM_ERR("%p attached twice", dst);
84 return TDM_ERROR_BAD_REQUEST;
88 return TDM_ERROR_NONE;
92 tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst,
95 tdm_private_pp *private_pp = user_data;
96 tdm_private_display *private_display = private_pp->private_display;
97 tdm_buffer_info *buf_info;
98 tbm_surface_h first_entry;
100 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
102 if (private_pp->owner_tid != syscall(SYS_gettid)) {
103 tdm_thread_cb_pp_done pp_done;
106 pp_done.base.type = TDM_THREAD_CB_PP_DONE;
107 pp_done.base.length = sizeof pp_done;
108 pp_done.pp_stamp = private_pp->stamp;
111 pp_done.user_data = user_data;
113 ret = tdm_thread_send_cb(private_display->private_loop, &pp_done.base);
114 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
119 if (private_pp->owner_tid != syscall(SYS_gettid))
120 TDM_NEVER_GET_HERE();
122 if (tdm_debug_buffer)
123 TDM_INFO("pp(%p) done: src(%p) dst(%p)", private_pp, src, dst);
125 first_entry = tdm_buffer_list_get_first_entry(&private_pp->src_buffer_list);
126 if (first_entry != src)
127 TDM_ERR("src(%p) is skipped", first_entry);
129 first_entry = tdm_buffer_list_get_first_entry(&private_pp->dst_buffer_list);
130 if (first_entry != dst)
131 TDM_ERR("dst(%p) is skipped", first_entry);
133 if ((buf_info = tdm_buffer_get_info(src)))
134 LIST_DEL(&buf_info->link);
136 if ((buf_info = tdm_buffer_get_info(dst)))
137 LIST_DEL(&buf_info->link);
139 _pthread_mutex_unlock(&private_display->lock);
140 tdm_buffer_unref_backend(src);
141 tdm_buffer_unref_backend(dst);
142 _pthread_mutex_lock(&private_display->lock);
145 INTERN tdm_private_pp *
146 tdm_pp_find_stamp(tdm_private_display *private_display, unsigned long stamp)
148 tdm_private_pp *private_pp = NULL;
150 TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL);
152 LIST_FOR_EACH_ENTRY(private_pp, &private_display->pp_list, link) {
153 if (private_pp->stamp == stamp)
160 INTERN tdm_private_pp *
161 tdm_pp_create_internal(tdm_private_display *private_display, tdm_error *error)
163 tdm_func_display *func_display;
164 tdm_func_pp *func_pp;
165 tdm_private_pp *private_pp = NULL;
166 tdm_pp *pp_backend = NULL;
167 tdm_error ret = TDM_ERROR_NONE;
169 TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), NULL);
171 func_display = &private_display->func_display;
172 func_pp = &private_display->func_pp;
174 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
175 TDM_ERR("no pp capability");
177 *error = TDM_ERROR_NO_CAPABILITY;
181 pp_backend = func_display->display_create_pp(private_display->bdata, &ret);
182 if (ret != TDM_ERROR_NONE) {
188 private_pp = calloc(1, sizeof(tdm_private_pp));
190 TDM_ERR("failed: alloc memory");
191 func_pp->pp_destroy(pp_backend);
193 *error = TDM_ERROR_OUT_OF_MEMORY;
197 ret = func_pp->pp_set_done_handler(pp_backend, tdm_pp_cb_done, private_pp);
198 if (ret != TDM_ERROR_NONE) {
199 TDM_ERR("spp(%p) et pp_done_handler failed", private_pp);
200 func_pp->pp_destroy(pp_backend);
206 private_pp->stamp = tdm_helper_get_time_in_millis();
207 while (tdm_pp_find_stamp(private_display, private_pp->stamp))
210 LIST_ADD(&private_pp->link, &private_display->pp_list);
211 private_pp->private_display = private_display;
212 private_pp->pp_backend = pp_backend;
213 private_pp->owner_tid = syscall(SYS_gettid);
215 LIST_INITHEAD(&private_pp->src_pending_buffer_list);
216 LIST_INITHEAD(&private_pp->dst_pending_buffer_list);
217 LIST_INITHEAD(&private_pp->src_buffer_list);
218 LIST_INITHEAD(&private_pp->dst_buffer_list);
221 *error = TDM_ERROR_NONE;
227 tdm_pp_destroy_internal(tdm_private_pp *private_pp)
229 tdm_private_display *private_display;
230 tdm_func_pp *func_pp;
231 tdm_buffer_info *b = NULL, *bb = NULL;
233 TDM_RETURN_IF_FAIL(TDM_MUTEX_IS_LOCKED());
238 private_display = private_pp->private_display;
239 func_pp = &private_display->func_pp;
241 LIST_DEL(&private_pp->link);
243 func_pp->pp_destroy(private_pp->pp_backend);
245 if (!LIST_IS_EMPTY(&private_pp->src_pending_buffer_list)) {
246 TDM_WRN("pp(%p) not finished:", private_pp);
247 tdm_buffer_list_dump(&private_pp->src_pending_buffer_list);
249 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->src_pending_buffer_list, link) {
251 _pthread_mutex_unlock(&private_display->lock);
252 tdm_buffer_unref_backend(b->buffer);
253 _pthread_mutex_lock(&private_display->lock);
257 if (!LIST_IS_EMPTY(&private_pp->dst_pending_buffer_list)) {
258 TDM_WRN("pp(%p) not finished:", private_pp);
259 tdm_buffer_list_dump(&private_pp->dst_pending_buffer_list);
261 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->dst_pending_buffer_list, link) {
263 _pthread_mutex_unlock(&private_display->lock);
264 tdm_buffer_unref_backend(b->buffer);
265 _pthread_mutex_lock(&private_display->lock);
269 if (!LIST_IS_EMPTY(&private_pp->src_buffer_list)) {
270 TDM_WRN("pp(%p) not finished:", private_pp);
271 tdm_buffer_list_dump(&private_pp->src_buffer_list);
273 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->src_buffer_list, link) {
275 _pthread_mutex_unlock(&private_display->lock);
276 tdm_buffer_unref_backend(b->buffer);
277 _pthread_mutex_lock(&private_display->lock);
281 if (!LIST_IS_EMPTY(&private_pp->dst_buffer_list)) {
282 TDM_WRN("pp(%p) not finished:", private_pp);
283 tdm_buffer_list_dump(&private_pp->dst_buffer_list);
285 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->dst_buffer_list, link) {
287 _pthread_mutex_unlock(&private_display->lock);
288 tdm_buffer_unref_backend(b->buffer);
289 _pthread_mutex_lock(&private_display->lock);
293 private_pp->stamp = 0;
298 tdm_pp_destroy(tdm_pp *pp)
300 tdm_private_pp *private_pp = pp;
301 tdm_private_display *private_display;
306 private_display = private_pp->private_display;
308 _pthread_mutex_lock(&private_display->lock);
309 tdm_pp_destroy_internal(private_pp);
310 _pthread_mutex_unlock(&private_display->lock);
314 tdm_pp_set_info(tdm_pp *pp, tdm_info_pp *info)
318 TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
320 _pthread_mutex_lock(&private_display->lock);
322 if (!func_pp->pp_set_info) {
323 _pthread_mutex_unlock(&private_display->lock);
324 TDM_DBG("failed: not implemented!!");
325 return TDM_ERROR_NOT_IMPLEMENTED;
328 TDM_INFO("pp(%p) info: src(%dx%d %d,%d %dx%d %c%c%c%c) dst(%dx%d %d,%d %dx%d %c%c%c%c) trans(%d) sync(%d) flags(%x)",
329 private_pp, info->src_config.size.h, info->src_config.size.v,
330 info->src_config.pos.x, info->src_config.pos.y,
331 info->src_config.pos.w, info->src_config.pos.h,
332 FOURCC_STR(info->src_config.format),
333 info->dst_config.size.h, info->dst_config.size.v,
334 info->dst_config.pos.x, info->dst_config.pos.y,
335 info->dst_config.pos.w, info->dst_config.pos.h,
336 FOURCC_STR(info->dst_config.format),
337 info->transform, info->sync, info->flags);
339 ret = func_pp->pp_set_info(private_pp->pp_backend, info);
340 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
342 _pthread_mutex_unlock(&private_display->lock);
348 tdm_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst)
352 TDM_RETURN_VAL_IF_FAIL(src != NULL, TDM_ERROR_INVALID_PARAMETER);
353 TDM_RETURN_VAL_IF_FAIL(dst != NULL, TDM_ERROR_INVALID_PARAMETER);
355 _pthread_mutex_lock(&private_display->lock);
357 if (!func_pp->pp_attach) {
358 _pthread_mutex_unlock(&private_display->lock);
359 TDM_DBG("failed: not implemented!!");
360 return TDM_ERROR_NOT_IMPLEMENTED;
363 ret = _tdm_pp_check_if_exist(private_pp, src, dst);
364 if (ret != TDM_ERROR_NONE) {
365 _pthread_mutex_unlock(&private_display->lock);
369 ret = func_pp->pp_attach(private_pp->pp_backend, src, dst);
370 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
372 if (ret == TDM_ERROR_NONE) {
373 tdm_buffer_info *buf_info;
375 if ((buf_info = tdm_buffer_get_info(src)))
376 LIST_ADDTAIL(&buf_info->link, &private_pp->src_pending_buffer_list);
378 if ((buf_info = tdm_buffer_get_info(dst)))
379 LIST_ADDTAIL(&buf_info->link, &private_pp->dst_pending_buffer_list);
381 if (tdm_debug_buffer) {
382 TDM_INFO("pp(%p) attached:", private_pp);
383 tdm_buffer_list_dump(&private_pp->src_pending_buffer_list);
384 tdm_buffer_list_dump(&private_pp->dst_pending_buffer_list);
388 _pthread_mutex_unlock(&private_display->lock);
394 tdm_pp_commit(tdm_pp *pp)
396 tdm_buffer_info *b = NULL, *bb = NULL;
400 _pthread_mutex_lock(&private_display->lock);
402 if (!func_pp->pp_commit) {
403 _pthread_mutex_unlock(&private_display->lock);
404 TDM_DBG("failed: not implemented!!");
405 return TDM_ERROR_NOT_IMPLEMENTED;
408 ret = func_pp->pp_commit(private_pp->pp_backend);
409 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
411 if (ret == TDM_ERROR_NONE) {
412 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->src_pending_buffer_list, link) {
414 tdm_buffer_ref_backend(b->buffer);
415 LIST_ADDTAIL(&b->link, &private_pp->src_buffer_list);
418 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->dst_pending_buffer_list, link) {
420 tdm_buffer_ref_backend(b->buffer);
421 LIST_ADDTAIL(&b->link, &private_pp->dst_buffer_list);
424 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->src_pending_buffer_list, link)
426 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->dst_pending_buffer_list, link)
430 _pthread_mutex_unlock(&private_display->lock);