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;
99 int lock_after_cb_done = 0;
102 if (tdm_debug_buffer)
103 TDM_INFO("pp(%p) done: src(%p) dst(%p)", private_pp, src, dst);
105 first_entry = tdm_buffer_list_get_first_entry(&private_pp->src_buffer_list);
106 if (first_entry != src)
107 TDM_ERR("src(%p) is skipped", first_entry);
109 first_entry = tdm_buffer_list_get_first_entry(&private_pp->dst_buffer_list);
110 if (first_entry != dst)
111 TDM_ERR("dst(%p) is skipped", first_entry);
113 if ((buf_info = tdm_buffer_get_info(src)))
114 LIST_DEL(&buf_info->link);
116 if ((buf_info = tdm_buffer_get_info(dst)))
117 LIST_DEL(&buf_info->link);
119 ret = pthread_mutex_trylock(&private_display->lock);
121 pthread_mutex_unlock(&private_display->lock);
122 else if (ret == EBUSY) {
123 pthread_mutex_unlock(&private_display->lock);
124 lock_after_cb_done = 1;
127 tdm_buffer_unref_backend(src);
128 tdm_buffer_unref_backend(dst);
130 if (lock_after_cb_done)
131 pthread_mutex_lock(&private_display->lock);
134 INTERN tdm_private_pp *
135 tdm_pp_create_internal(tdm_private_display *private_display, tdm_error *error)
137 tdm_func_display *func_display;
138 tdm_func_pp *func_pp;
139 tdm_private_pp *private_pp = NULL;
140 tdm_pp *pp_backend = NULL;
141 tdm_error ret = TDM_ERROR_NONE;
143 func_display = &private_display->func_display;
144 func_pp = &private_display->func_pp;
146 if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
147 TDM_ERR("no pp capability");
149 *error = TDM_ERROR_NO_CAPABILITY;
153 pp_backend = func_display->display_create_pp(private_display->bdata, &ret);
154 if (ret != TDM_ERROR_NONE) {
160 private_pp = calloc(1, sizeof(tdm_private_pp));
162 TDM_ERR("failed: alloc memory");
163 func_pp->pp_destroy(pp_backend);
165 *error = TDM_ERROR_OUT_OF_MEMORY;
169 ret = func_pp->pp_set_done_handler(pp_backend, _tdm_pp_cb_done, private_pp);
170 if (ret != TDM_ERROR_NONE) {
171 TDM_ERR("spp(%p) et pp_done_handler failed", private_pp);
172 func_pp->pp_destroy(pp_backend);
178 LIST_ADD(&private_pp->link, &private_display->pp_list);
179 private_pp->private_display = private_display;
180 private_pp->pp_backend = pp_backend;
182 LIST_INITHEAD(&private_pp->src_pending_buffer_list);
183 LIST_INITHEAD(&private_pp->dst_pending_buffer_list);
184 LIST_INITHEAD(&private_pp->src_buffer_list);
185 LIST_INITHEAD(&private_pp->dst_buffer_list);
188 *error = TDM_ERROR_NONE;
194 tdm_pp_destroy_internal(tdm_private_pp *private_pp)
196 tdm_private_display *private_display;
197 tdm_func_pp *func_pp;
198 tdm_buffer_info *b = NULL, *bb = NULL;
203 private_display = private_pp->private_display;
204 func_pp = &private_display->func_pp;
206 LIST_DEL(&private_pp->link);
208 func_pp->pp_destroy(private_pp->pp_backend);
210 if (!LIST_IS_EMPTY(&private_pp->src_pending_buffer_list)) {
211 TDM_ERR("pp(%p) not finished:", private_pp);
212 tdm_buffer_list_dump(&private_pp->src_pending_buffer_list);
214 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->src_pending_buffer_list, link) {
216 pthread_mutex_unlock(&private_display->lock);
217 tdm_buffer_unref_backend(b->buffer);
218 pthread_mutex_lock(&private_display->lock);
222 if (!LIST_IS_EMPTY(&private_pp->dst_pending_buffer_list)) {
223 TDM_ERR("pp(%p) not finished:", private_pp);
224 tdm_buffer_list_dump(&private_pp->dst_pending_buffer_list);
226 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->dst_pending_buffer_list, link) {
228 pthread_mutex_unlock(&private_display->lock);
229 tdm_buffer_unref_backend(b->buffer);
230 pthread_mutex_lock(&private_display->lock);
234 if (!LIST_IS_EMPTY(&private_pp->src_buffer_list)) {
235 TDM_ERR("pp(%p) not finished:", private_pp);
236 tdm_buffer_list_dump(&private_pp->src_buffer_list);
238 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->src_buffer_list, link) {
240 pthread_mutex_unlock(&private_display->lock);
241 tdm_buffer_unref_backend(b->buffer);
242 pthread_mutex_lock(&private_display->lock);
246 if (!LIST_IS_EMPTY(&private_pp->dst_buffer_list)) {
247 TDM_ERR("pp(%p) not finished:", private_pp);
248 tdm_buffer_list_dump(&private_pp->dst_buffer_list);
250 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->dst_buffer_list, link) {
252 pthread_mutex_unlock(&private_display->lock);
253 tdm_buffer_unref_backend(b->buffer);
254 pthread_mutex_lock(&private_display->lock);
262 tdm_pp_destroy(tdm_pp *pp)
264 tdm_private_pp *private_pp = pp;
265 tdm_private_display *private_display;
270 private_display = private_pp->private_display;
272 pthread_mutex_lock(&private_display->lock);
273 tdm_pp_destroy_internal(private_pp);
274 pthread_mutex_unlock(&private_display->lock);
278 tdm_pp_set_info(tdm_pp *pp, tdm_info_pp *info)
282 TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
284 pthread_mutex_lock(&private_display->lock);
286 if (!func_pp->pp_set_info) {
287 pthread_mutex_unlock(&private_display->lock);
288 return TDM_ERROR_NONE;
291 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)",
292 private_pp, info->src_config.size.h, info->src_config.size.v,
293 info->src_config.pos.x, info->src_config.pos.y,
294 info->src_config.pos.w, info->src_config.pos.h,
295 FOURCC_STR(info->src_config.format),
296 info->dst_config.size.h, info->dst_config.size.v,
297 info->dst_config.pos.x, info->dst_config.pos.y,
298 info->dst_config.pos.w, info->dst_config.pos.h,
299 FOURCC_STR(info->dst_config.format),
300 info->transform, info->sync, info->flags);
302 ret = func_pp->pp_set_info(private_pp->pp_backend, info);
303 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
305 pthread_mutex_unlock(&private_display->lock);
311 tdm_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst)
315 TDM_RETURN_VAL_IF_FAIL(src != NULL, TDM_ERROR_INVALID_PARAMETER);
316 TDM_RETURN_VAL_IF_FAIL(dst != NULL, TDM_ERROR_INVALID_PARAMETER);
318 pthread_mutex_lock(&private_display->lock);
320 if (!func_pp->pp_attach) {
321 pthread_mutex_unlock(&private_display->lock);
322 return TDM_ERROR_NONE;
325 ret = _tdm_pp_check_if_exist(private_pp, src, dst);
326 if (ret != TDM_ERROR_NONE) {
327 pthread_mutex_unlock(&private_display->lock);
331 ret = func_pp->pp_attach(private_pp->pp_backend, src, dst);
332 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
334 if (ret == TDM_ERROR_NONE) {
335 tdm_buffer_info *buf_info;
337 if ((buf_info = tdm_buffer_get_info(src)))
338 LIST_ADDTAIL(&buf_info->link, &private_pp->src_pending_buffer_list);
340 if ((buf_info = tdm_buffer_get_info(dst)))
341 LIST_ADDTAIL(&buf_info->link, &private_pp->dst_pending_buffer_list);
343 if (tdm_debug_buffer) {
344 TDM_INFO("pp(%p) attached:", private_pp);
345 tdm_buffer_list_dump(&private_pp->src_pending_buffer_list);
346 tdm_buffer_list_dump(&private_pp->dst_pending_buffer_list);
350 pthread_mutex_unlock(&private_display->lock);
356 tdm_pp_commit(tdm_pp *pp)
358 tdm_buffer_info *b = NULL, *bb = NULL;
362 pthread_mutex_lock(&private_display->lock);
364 if (!func_pp->pp_commit) {
365 pthread_mutex_unlock(&private_display->lock);
366 return TDM_ERROR_NONE;
369 ret = func_pp->pp_commit(private_pp->pp_backend);
370 TDM_WARNING_IF_FAIL(ret == TDM_ERROR_NONE);
372 if (ret == TDM_ERROR_NONE) {
373 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->src_pending_buffer_list, link) {
375 tdm_buffer_ref_backend(b->buffer);
376 LIST_ADDTAIL(&b->link, &private_pp->src_buffer_list);
379 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->dst_pending_buffer_list, link) {
381 tdm_buffer_ref_backend(b->buffer);
382 LIST_ADDTAIL(&b->link, &private_pp->dst_buffer_list);
385 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->src_pending_buffer_list, link)
387 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &private_pp->dst_pending_buffer_list, link)
391 pthread_mutex_unlock(&private_display->lock);