enhance log for buffer debugging
[platform/core/uifw/libtdm.git] / src / tdm_pp.c
1 /**************************************************************************
2
3 libtdm
4
5 Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
6
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>
13
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:
21
22 The above copyright notice and this permission notice (including the
23 next paragraph) shall be included in all copies or substantial portions
24 of the Software.
25
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.
33
34 **************************************************************************/
35
36 #ifdef HAVE_CONFIG_H
37 #include "config.h"
38 #endif
39
40 #include "tdm.h"
41 #include "tdm_backend.h"
42 #include "tdm_private.h"
43
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
53
54 static void
55 _tdm_pp_cb_done(tdm_pp *pp_backend, tbm_surface_h src, tbm_surface_h dst,
56                 void *user_data)
57 {
58         tdm_private_pp *private_pp = user_data;
59         tdm_private_display *private_display = private_pp->private_display;
60         int lock_after_cb_done = 0;
61         int ret;
62
63         ret = pthread_mutex_trylock(&private_display->lock);
64         if (ret == 0)
65                 pthread_mutex_unlock(&private_display->lock);
66         else  if (ret == EBUSY) {
67                 pthread_mutex_unlock(&private_display->lock);
68                 lock_after_cb_done = 1;
69         }
70
71         if (tdm_debug_buffer)
72                 TDM_INFO("done: %p", src);
73
74         tdm_buffer_remove_list(&private_pp->buffer_list, src);
75
76         tdm_buffer_unref_backend(src);
77         tdm_buffer_unref_backend(dst);
78
79         if (lock_after_cb_done)
80                 pthread_mutex_lock(&private_display->lock);
81 }
82
83 INTERN tdm_private_pp *
84 tdm_pp_create_internal(tdm_private_display *private_display, tdm_error *error)
85 {
86         tdm_func_display *func_display;
87         tdm_func_pp *func_pp;
88         tdm_private_pp *private_pp = NULL;
89         tdm_pp *pp_backend = NULL;
90         tdm_error ret = TDM_ERROR_NONE;
91
92         func_display = &private_display->func_display;
93         func_pp = &private_display->func_pp;
94
95         if (!(private_display->capabilities & TDM_DISPLAY_CAPABILITY_PP)) {
96                 TDM_ERR("no pp capability");
97                 if (error)
98                         *error = TDM_ERROR_NO_CAPABILITY;
99                 return NULL;
100         }
101
102         pp_backend = func_display->display_create_pp(private_display->bdata, &ret);
103         if (ret != TDM_ERROR_NONE) {
104                 if (error)
105                         *error = ret;
106                 return NULL;
107         }
108
109         private_pp = calloc(1, sizeof(tdm_private_pp));
110         if (!private_pp) {
111                 TDM_ERR("failed: alloc memory");
112                 func_pp->pp_destroy(pp_backend);
113                 if (error)
114                         *error = TDM_ERROR_OUT_OF_MEMORY;
115                 return NULL;
116         }
117
118         ret = func_pp->pp_set_done_handler(pp_backend, _tdm_pp_cb_done, private_pp);
119         if (ret != TDM_ERROR_NONE) {
120                 TDM_ERR("set pp_done_handler failed");
121                 func_pp->pp_destroy(pp_backend);
122                 if (error)
123                         *error = ret;
124                 return NULL;
125         }
126
127         LIST_ADD(&private_pp->link, &private_display->pp_list);
128         private_pp->private_display = private_display;
129         private_pp->pp_backend = pp_backend;
130
131         LIST_INITHEAD(&private_pp->buffer_list);
132
133         if (error)
134                 *error = TDM_ERROR_NONE;
135
136         return private_pp;
137 }
138
139 INTERN void
140 tdm_pp_destroy_internal(tdm_private_pp *private_pp)
141 {
142         tdm_func_pp *func_pp;
143
144         if (!private_pp)
145                 return;
146
147         func_pp = &private_pp->private_display->func_pp;
148
149         LIST_DEL(&private_pp->link);
150
151         func_pp->pp_destroy(private_pp->pp_backend);
152
153         if (!LIST_IS_EMPTY(&private_pp->buffer_list)) {
154                 char str[256] = {0,};
155                 tdm_buffer_dump_list(&private_pp->buffer_list, str, 256);
156                 if (strlen(str) > 0)
157                         TDM_WRN("not finished: %s buffers", str);
158         }
159
160         free(private_pp);
161 }
162
163 EXTERN void
164 tdm_pp_destroy(tdm_pp *pp)
165 {
166         tdm_private_pp *private_pp = pp;
167         tdm_private_display *private_display;
168
169         if (!private_pp)
170                 return;
171
172         private_display = private_pp->private_display;
173
174         pthread_mutex_lock(&private_display->lock);
175         tdm_pp_destroy_internal(private_pp);
176         pthread_mutex_unlock(&private_display->lock);
177 }
178
179 EXTERN tdm_error
180 tdm_pp_set_info(tdm_pp *pp, tdm_info_pp *info)
181 {
182         PP_FUNC_ENTRY();
183
184         TDM_RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
185
186         pthread_mutex_lock(&private_display->lock);
187
188         if (!func_pp->pp_set_info) {
189                 pthread_mutex_unlock(&private_display->lock);
190                 return TDM_ERROR_NONE;
191         }
192
193         TDM_INFO("pp 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)",
194                  info->src_config.size.h, info->src_config.size.v,
195                  info->src_config.pos.x, info->src_config.pos.y,
196                  info->src_config.pos.w, info->src_config.pos.h,
197                  FOURCC_STR(info->src_config.format),
198                  info->dst_config.size.h, info->dst_config.size.v,
199                  info->dst_config.pos.x, info->dst_config.pos.y,
200                  info->dst_config.pos.w, info->dst_config.pos.h,
201                  FOURCC_STR(info->dst_config.format),
202                  info->transform, info->sync, info->flags);
203
204         ret = func_pp->pp_set_info(private_pp->pp_backend, info);
205
206         pthread_mutex_unlock(&private_display->lock);
207
208         return ret;
209 }
210
211 EXTERN tdm_error
212 tdm_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst)
213 {
214         PP_FUNC_ENTRY();
215
216         TDM_RETURN_VAL_IF_FAIL(src != NULL, TDM_ERROR_INVALID_PARAMETER);
217         TDM_RETURN_VAL_IF_FAIL(dst != NULL, TDM_ERROR_INVALID_PARAMETER);
218
219         pthread_mutex_lock(&private_display->lock);
220
221         if (!func_pp->pp_attach) {
222                 pthread_mutex_unlock(&private_display->lock);
223                 return TDM_ERROR_NONE;
224         }
225
226         tdm_buffer_ref_backend(src);
227         tdm_buffer_ref_backend(dst);
228         ret = func_pp->pp_attach(private_pp->pp_backend, src, dst);
229
230         if (ret == TDM_ERROR_NONE)
231                 tdm_buffer_add_list(&private_pp->buffer_list, src);
232
233         if (tdm_debug_buffer) {
234                 char str[256] = {0,};
235                 tdm_buffer_dump_list(&private_pp->buffer_list, str, 256);
236                 TDM_INFO("attached: %s", str);
237         }
238
239         pthread_mutex_unlock(&private_display->lock);
240
241         return ret;
242 }
243
244 EXTERN tdm_error
245 tdm_pp_commit(tdm_pp *pp)
246 {
247         PP_FUNC_ENTRY();
248
249         pthread_mutex_lock(&private_display->lock);
250
251         if (!func_pp->pp_commit) {
252                 pthread_mutex_unlock(&private_display->lock);
253                 return TDM_ERROR_NONE;
254         }
255
256         ret = func_pp->pp_commit(private_pp->pp_backend);
257
258         pthread_mutex_unlock(&private_display->lock);
259
260         return ret;
261 }