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_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst,
58 tdm_private_pp *private_pp = user_data;
59 tdm_private_display *private_display = private_pp->private_display;
60 tdm_buffer_info *buf_info;
61 tbm_surface_h first_entry;
62 int lock_after_cb_done = 0;
66 TDM_INFO("pp(%p) done: src(%p) dst(%p)", private_pp, src, dst);
68 first_entry = tdm_buffer_list_get_first_entry(&private_pp->src_buffer_list);
69 if (first_entry != src)
70 TDM_ERR("src(%p) is skipped", first_entry);
72 first_entry = tdm_buffer_list_get_first_entry(&private_pp->dst_buffer_list);
73 if (first_entry != dst)
74 TDM_ERR("dst(%p) is skipped", first_entry);
76 if ((buf_info = tdm_buffer_get_info(src)))
77 LIST_DEL(&buf_info->link);
79 if ((buf_info = tdm_buffer_get_info(dst)))
80 LIST_DEL(&buf_info->link);
82 ret = pthread_mutex_trylock(&private_display->lock);
84 pthread_mutex_unlock(&private_display->lock);
85 else if (ret == EBUSY) {
86 pthread_mutex_unlock(&private_display->lock);
87 lock_after_cb_done = 1;
90 tdm_buffer_unref_backend(src);
91 tdm_buffer_unref_backend(dst);
93 if (lock_after_cb_done)
94 pthread_mutex_lock(&private_display->lock);
97 INTERN tdm_private_pp *
98 tdm_pp_create_internal(tdm_private_display *private_display, tdm_error *error)
100 tdm_func_display *func_display;
101 tdm_func_pp *func_pp;
102 tdm_private_pp *private_pp = NULL;
103 tdm_pp *pp_backend = NULL;
104 tdm_error ret = TDM_ERROR_NONE;
106 func_display = &private_display->func_display;
107 func_pp = &private_display->func_pp;
109 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
110 TDM_ERR("no pp capability");
112 *error = TDM_ERROR_NO_CAPABILITY;
116 pp_backend = func_display->display_create_pp(private_display->bdata, &ret);
117 if (ret != TDM_ERROR_NONE) {
123 private_pp = calloc(1, sizeof(tdm_private_pp));
125 TDM_ERR("failed: alloc memory");
126 func_pp->pp_destroy(pp_backend);
128 *error = TDM_ERROR_OUT_OF_MEMORY;
132 ret = func_pp->pp_set_done_handler(pp_backend, _tdm_pp_cb_done, private_pp);
133 if (ret != TDM_ERROR_NONE) {
134 TDM_ERR("spp(%p) et pp_done_handler failed", private_pp);
135 func_pp->pp_destroy(pp_backend);
141 LIST_ADD(&private_pp->link, &private_display->pp_list);
142 private_pp->private_display = private_display;
143 private_pp->pp_backend = pp_backend;
145 LIST_INITHEAD(&private_pp->src_pending_buffer_list);
146 LIST_INITHEAD(&private_pp->dst_pending_buffer_list);
147 LIST_INITHEAD(&private_pp->src_buffer_list);
148 LIST_INITHEAD(&private_pp->dst_buffer_list);
151 *error = TDM_ERROR_NONE;
157 tdm_pp_destroy_internal(tdm_private_pp *private_pp)
159 tdm_private_display *private_display;
160 tdm_func_pp *func_pp;
161 tdm_buffer_info *b = NULL, *bb = NULL;
166 private_display = private_pp->private_display;
167 func_pp = &private_display->func_pp;
169 LIST_DEL(&private_pp->link);
171 func_pp->pp_destroy(private_pp->pp_backend);
173 if (!LIST_IS_EMPTY(&private_pp->src_pending_buffer_list)) {
174 TDM_ERR("pp(%p) not finished:", private_pp);
175 tdm_buffer_list_dump(&private_pp->src_pending_buffer_list);
177 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->src_pending_buffer_list, link)
181 if (!LIST_IS_EMPTY(&private_pp->dst_pending_buffer_list)) {
182 TDM_ERR("pp(%p) not finished:", private_pp);
183 tdm_buffer_list_dump(&private_pp->dst_pending_buffer_list);
185 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->dst_pending_buffer_list, link)
189 if (!LIST_IS_EMPTY(&private_pp->src_buffer_list)) {
190 TDM_ERR("pp(%p) not finished:", private_pp);
191 tdm_buffer_list_dump(&private_pp->src_buffer_list);
193 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->src_buffer_list, link)
197 if (!LIST_IS_EMPTY(&private_pp->dst_buffer_list)) {
198 TDM_ERR("pp(%p) not finished:", private_pp);
199 tdm_buffer_list_dump(&private_pp->dst_buffer_list);
201 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->dst_buffer_list, link)
209 tdm_pp_destroy(tdm_pp *pp)
211 tdm_private_pp *private_pp = pp;
212 tdm_private_display *private_display;
217 private_display = private_pp->private_display;
219 pthread_mutex_lock(&private_display->lock);
220 tdm_pp_destroy_internal(private_pp);
221 pthread_mutex_unlock(&private_display->lock);
225 tdm_pp_set_info(tdm_pp *pp, tdm_info_pp *info)
229 TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
231 pthread_mutex_lock(&private_display->lock);
233 if (!func_pp->pp_set_info) {
234 pthread_mutex_unlock(&private_display->lock);
235 return TDM_ERROR_NONE;
238 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)",
239 private_pp, info->src_config.size.h, info->src_config.size.v,
240 info->src_config.pos.x, info->src_config.pos.y,
241 info->src_config.pos.w, info->src_config.pos.h,
242 FOURCC_STR(info->src_config.format),
243 info->dst_config.size.h, info->dst_config.size.v,
244 info->dst_config.pos.x, info->dst_config.pos.y,
245 info->dst_config.pos.w, info->dst_config.pos.h,
246 FOURCC_STR(info->dst_config.format),
247 info->transform, info->sync, info->flags);
249 ret = func_pp->pp_set_info(private_pp->pp_backend, info);
250 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
252 pthread_mutex_unlock(&private_display->lock);
258 tdm_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst)
262 TDM_RETURN_VAL_IF_FAIL(src != NULL, TDM_ERROR_INVALID_PARAMETER);
263 TDM_RETURN_VAL_IF_FAIL(dst != NULL, TDM_ERROR_INVALID_PARAMETER);
265 pthread_mutex_lock(&private_display->lock);
267 if (!func_pp->pp_attach) {
268 pthread_mutex_unlock(&private_display->lock);
269 return TDM_ERROR_NONE;
272 ret = func_pp->pp_attach(private_pp->pp_backend, src, dst);
273 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
275 if (ret == TDM_ERROR_NONE) {
276 tdm_buffer_info *buf_info;
278 if ((buf_info = tdm_buffer_get_info(src)))
279 LIST_ADDTAIL(&buf_info->link, &private_pp->src_pending_buffer_list);
281 if ((buf_info = tdm_buffer_get_info(dst)))
282 LIST_ADDTAIL(&buf_info->link, &private_pp->dst_pending_buffer_list);
284 if (tdm_debug_buffer) {
285 TDM_INFO("pp(%p) attached:", private_pp);
286 tdm_buffer_list_dump(&private_pp->src_pending_buffer_list);
287 tdm_buffer_list_dump(&private_pp->dst_pending_buffer_list);
291 pthread_mutex_unlock(&private_display->lock);
297 tdm_pp_commit(tdm_pp *pp)
299 tdm_buffer_info *b = NULL, *bb = NULL;
303 pthread_mutex_lock(&private_display->lock);
305 if (!func_pp->pp_commit) {
306 pthread_mutex_unlock(&private_display->lock);
307 return TDM_ERROR_NONE;
310 ret = func_pp->pp_commit(private_pp->pp_backend);
311 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
313 if (ret == TDM_ERROR_NONE) {
314 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->src_pending_buffer_list, link) {
316 tdm_buffer_ref_backend(b->buffer);
317 LIST_ADDTAIL(&b->link, &private_pp->src_buffer_list);
320 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->dst_pending_buffer_list, link) {
322 tdm_buffer_ref_backend(b->buffer);
323 LIST_ADDTAIL(&b->link, &private_pp->dst_buffer_list);
326 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->src_pending_buffer_list, link)
328 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->dst_pending_buffer_list, link)
332 pthread_mutex_unlock(&private_display->lock);