remove unused code
[platform/adaptation/libtdm-drm.git] / src / tdm_drm_pp.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <pixman.h>
6
7 #include "tdm_drm.h"
8 #include "tdm_helper.h"
9
10 typedef struct _tdm_drm_pp_buffer {
11         tbm_surface_h src;
12         tbm_surface_h dst;
13
14         struct list_head link;
15 } tdm_drm_pp_buffer;
16
17 typedef struct _tdm_drm_pp_data {
18         tdm_drm_data *drm_data;
19
20         tdm_info_pp info;
21
22         struct list_head pending_buffer_list;
23
24         tdm_pp_done_handler done_func;
25         void *done_user_data;
26
27         struct list_head link;
28 } tdm_drm_pp_data;
29
30
31 static tbm_format pp_formats[] = {
32         TBM_FORMAT_ARGB8888,
33         TBM_FORMAT_XRGB8888,
34         TBM_FORMAT_YUV420,
35         TBM_FORMAT_YVU420
36 };
37
38 #define NUM_PP_FORMAT   (sizeof(pp_formats) / sizeof(pp_formats[0]))
39
40 static int pp_list_init;
41 static struct list_head pp_list;
42
43 static pixman_format_code_t
44 _tdm_drm_pp_pixman_get_format(tbm_format tbmfmt)
45 {
46         switch (tbmfmt) {
47         case TBM_FORMAT_ARGB8888:
48                 return PIXMAN_a8r8g8b8;
49         case TBM_FORMAT_XRGB8888:
50                 return PIXMAN_x8r8g8b8;
51         case TBM_FORMAT_YUV420:
52         case TBM_FORMAT_YVU420:
53                 return PIXMAN_yv12;
54         default:
55                 return 0;
56         }
57 }
58
59 int
60 _tdm_drm_pp_pixman_convert(pixman_op_t op,
61                                                    unsigned char *srcbuf, unsigned char *dstbuf,
62                                                    pixman_format_code_t src_format, pixman_format_code_t dst_format,
63                                                    int sbw, int sbh, int sx, int sy, int sw, int sh,
64                                                    int dbw, int dbh, int dx, int dy, int dw, int dh,
65                                                    int rotate, int hflip, int vflip)
66 {
67         pixman_image_t  *src_img;
68         pixman_image_t  *dst_img;
69         struct pixman_f_transform ft;
70         pixman_transform_t transform;
71         int                             src_stride, dst_stride;
72         int                             src_bpp;
73         int                             dst_bpp;
74         double                   scale_x, scale_y;
75         int                             rotate_step;
76         int                             ret = 0;
77
78         RETURN_VAL_IF_FAIL(srcbuf != NULL, 0);
79         RETURN_VAL_IF_FAIL(dstbuf != NULL, 0);
80
81         TDM_DBG("src(%dx%d: %d,%d %dx%d) dst(%dx%d: %d,%d %dx%d) flip(%d,%d), rot(%d)",
82                         sbw, sbh, sx, sy, sw, sh, dbw, dbh, dx, dy, dw, dh, hflip, vflip, rotate);
83
84         src_bpp = PIXMAN_FORMAT_BPP(src_format) / 8;
85         RETURN_VAL_IF_FAIL(src_bpp > 0, 0);
86
87         dst_bpp = PIXMAN_FORMAT_BPP(dst_format) / 8;
88         RETURN_VAL_IF_FAIL(dst_bpp > 0, 0);
89
90         rotate_step = (rotate + 360) / 90 % 4;
91
92         src_stride = sbw * src_bpp;
93         dst_stride = dbw * dst_bpp;
94
95         src_img = pixman_image_create_bits(src_format, sbw, sbh, (uint32_t *)srcbuf,
96                                                                            src_stride);
97         dst_img = pixman_image_create_bits(dst_format, dbw, dbh, (uint32_t *)dstbuf,
98                                                                            dst_stride);
99
100         GOTO_IF_FAIL(src_img != NULL, CANT_CONVERT);
101         GOTO_IF_FAIL(dst_img != NULL, CANT_CONVERT);
102
103         pixman_f_transform_init_identity(&ft);
104
105         if (hflip) {
106                 pixman_f_transform_scale(&ft, NULL, -1, 1);
107                 pixman_f_transform_translate(&ft, NULL, dw, 0);
108         }
109
110         if (vflip) {
111                 pixman_f_transform_scale(&ft, NULL, 1, -1);
112                 pixman_f_transform_translate(&ft, NULL, 0, dh);
113         }
114
115         if (rotate_step > 0) {
116                 int c = 0, s = 0, tx = 0, ty = 0;
117                 switch (rotate_step) {
118                 case 1: /* 90 degrees */
119                         s = -1, tx = -dw;
120                         break;
121                 case 2: /* 180 degrees */
122                         c = -1, tx = -dw, ty = -dh;
123                         break;
124                 case 3: /* 270 degrees */
125                         s = 1, ty = -dh;
126                         break;
127                 }
128
129                 pixman_f_transform_translate(&ft, NULL, tx, ty);
130                 pixman_f_transform_rotate(&ft, NULL, c, s);
131         }
132
133         if (rotate_step % 2 == 0) {
134                 scale_x = (double)sw / dw;
135                 scale_y = (double)sh / dh;
136         } else {
137                 scale_x = (double)sw / dh;
138                 scale_y = (double)sh / dw;
139         }
140
141         pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
142         pixman_f_transform_translate(&ft, NULL, sx, sy);
143
144         pixman_transform_from_pixman_f_transform(&transform, &ft);
145         pixman_image_set_transform(src_img, &transform);
146
147         pixman_image_composite(op, src_img, NULL, dst_img, 0, 0, 0, 0, dx, dy, dw, dh);
148
149         ret = 1;
150
151 CANT_CONVERT:
152         if (src_img)
153                 pixman_image_unref(src_img);
154         if (dst_img)
155                 pixman_image_unref(dst_img);
156
157         return ret;
158 }
159
160 static tdm_error
161 _tdm_drm_pp_convert(tdm_drm_pp_buffer *buffer, tdm_info_pp *info)
162 {
163         tbm_surface_info_s src_info, dst_info;
164         pixman_format_code_t src_format, dst_format;
165         int sbw, dbw;
166         int rotate = 0, hflip = 0;
167         tbm_bo bo = NULL;
168         int bo_cnt = 0;
169         int bo_size = 0;
170
171         RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
172         RETURN_VAL_IF_FAIL(buffer->src != NULL, TDM_ERROR_INVALID_PARAMETER);
173         RETURN_VAL_IF_FAIL(buffer->dst != NULL, TDM_ERROR_INVALID_PARAMETER);
174         RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
175
176         bo_cnt = tbm_surface_internal_get_num_bos(buffer->src);
177         RETURN_VAL_IF_FAIL(bo_cnt == 1, TDM_ERROR_INVALID_PARAMETER);
178
179         bo_cnt = tbm_surface_internal_get_num_bos(buffer->dst);
180         RETURN_VAL_IF_FAIL(bo_cnt == 1, TDM_ERROR_INVALID_PARAMETER);
181
182         bo = tbm_surface_internal_get_bo(buffer->src, 0);
183         RETURN_VAL_IF_FAIL(bo != NULL, TDM_ERROR_INVALID_PARAMETER);
184
185         bo_size = tbm_bo_size(bo);
186
187         /* not handle buffers which have 2 more gem handles */
188
189         memset(&src_info, 0, sizeof(tbm_surface_info_s));
190         tbm_surface_map(buffer->src, TBM_OPTION_READ, &src_info);
191         GOTO_IF_FAIL(src_info.planes[0].ptr != NULL, fail_convert);
192
193         memset(&dst_info, 0, sizeof(tbm_surface_info_s));
194         tbm_surface_map(buffer->dst, TBM_OPTION_WRITE, &dst_info);
195         GOTO_IF_FAIL(dst_info.planes[0].ptr != NULL, fail_convert);
196
197         src_format = _tdm_drm_pp_pixman_get_format(src_info.format);
198         GOTO_IF_FAIL(src_format > 0, fail_convert);
199         dst_format = _tdm_drm_pp_pixman_get_format(dst_info.format);
200         GOTO_IF_FAIL(dst_format > 0, fail_convert);
201
202         if (src_info.format == TBM_FORMAT_YUV420) {
203                 if (dst_info.format == TBM_FORMAT_XRGB8888)
204                         dst_format = PIXMAN_x8b8g8r8;
205                 else if (dst_info.format == TBM_FORMAT_ARGB8888)
206                         dst_format = PIXMAN_a8b8g8r8;
207                 else if (dst_info.format == TBM_FORMAT_YVU420) {
208                         TDM_ERR("can't convert %c%c%c%c to %c%c%c%c",
209                                         FOURCC_STR(src_info.format), FOURCC_STR(dst_info.format));
210                         goto fail_convert;
211                 }
212         }
213         /* need checking for other formats also? */
214
215         if (IS_RGB(src_info.format))
216                 sbw = src_info.planes[0].stride >> 2;
217         else
218                 sbw = src_info.planes[0].stride;
219
220         if (IS_RGB(dst_info.format))
221                 dbw = dst_info.planes[0].stride >> 2;
222         else
223                 dbw = dst_info.planes[0].stride;
224
225         rotate = (info->transform % 4) * 90;
226         if (info->transform >= TDM_TRANSFORM_FLIPPED)
227                 hflip = 1;
228
229         if (bo_size < src_info.planes[0].stride * src_info.height) {
230                 TDM_WRN("bo size(%d) is smaller than the expected size(%d)",
231                                 bo_size, src_info.planes[0].stride * src_info.height);
232                 goto fail_convert;
233         }
234
235         _tdm_drm_pp_pixman_convert(PIXMAN_OP_SRC,
236                                                            src_info.planes[0].ptr, dst_info.planes[0].ptr,
237                                                            src_format, dst_format,
238                                                            sbw, src_info.height,
239                                                            info->src_config.pos.x, info->src_config.pos.y,
240                                                            info->src_config.pos.w, info->src_config.pos.h,
241                                                            dbw, dst_info.height,
242                                                            info->dst_config.pos.x, info->dst_config.pos.y,
243                                                            info->dst_config.pos.w, info->dst_config.pos.h,
244                                                            rotate, hflip, 0);
245         tbm_surface_unmap(buffer->src);
246         tbm_surface_unmap(buffer->dst);
247
248         return TDM_ERROR_NONE;
249 fail_convert:
250         tbm_surface_unmap(buffer->src);
251         tbm_surface_unmap(buffer->dst);
252         return TDM_ERROR_OPERATION_FAILED;
253 }
254
255 tdm_error
256 tdm_drm_pp_get_capability(tdm_drm_data *drm_data, tdm_caps_pp *caps)
257 {
258         int i;
259
260         if (!caps) {
261                 TDM_ERR("invalid params");
262                 return TDM_ERROR_INVALID_PARAMETER;
263         }
264
265         caps->capabilities = TDM_PP_CAPABILITY_SYNC;
266
267         caps->format_count = NUM_PP_FORMAT;
268
269         /* will be freed in frontend */
270         caps->formats = calloc(1, sizeof pp_formats);
271         if (!caps->formats) {
272                 TDM_ERR("alloc failed");
273                 return TDM_ERROR_OUT_OF_MEMORY;
274         }
275         for (i = 0; i < caps->format_count; i++)
276                 caps->formats[i] = pp_formats[i];
277
278         caps->min_w = 16;
279         caps->min_h = 8;
280         caps->max_w = -1;   /* not defined */
281         caps->max_h = -1;
282         caps->preferred_align = 16;
283
284         return TDM_ERROR_NONE;
285 }
286
287 tdm_pp *
288 tdm_drm_pp_create(tdm_drm_data *drm_data, tdm_error *error)
289 {
290         tdm_drm_pp_data *pp_data = calloc(1, sizeof(tdm_drm_pp_data));
291         if (!pp_data) {
292                 TDM_ERR("alloc failed");
293                 if (error)
294                         *error = TDM_ERROR_OUT_OF_MEMORY;
295                 return NULL;
296         }
297
298         pp_data->drm_data = drm_data;
299
300         LIST_INITHEAD(&pp_data->pending_buffer_list);
301
302         if (!pp_list_init) {
303                 pp_list_init = 1;
304                 LIST_INITHEAD(&pp_list);
305         }
306         LIST_ADDTAIL(&pp_data->link, &pp_list);
307
308         return pp_data;
309 }
310
311 void
312 drm_pp_destroy(tdm_pp *pp)
313 {
314         tdm_drm_pp_data *pp_data = pp;
315         tdm_drm_pp_buffer *b = NULL, *bb = NULL;
316
317         if (!pp_data)
318                 return;
319
320         LIST_FOR_EACH_ENTRY_SAFE(b, bb, &pp_data->pending_buffer_list, link) {
321                 LIST_DEL(&b->link);
322                 free(b);
323         }
324
325         LIST_DEL(&pp_data->link);
326
327         free(pp_data);
328 }
329
330 tdm_error
331 drm_pp_set_info(tdm_pp *pp, tdm_info_pp *info)
332 {
333         tdm_drm_pp_data *pp_data = pp;
334
335         RETURN_VAL_IF_FAIL(pp_data, TDM_ERROR_INVALID_PARAMETER);
336         RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
337
338         pp_data->info = *info;
339
340         return TDM_ERROR_NONE;
341 }
342
343 tdm_error
344 drm_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst)
345 {
346         tdm_drm_pp_data *pp_data = pp;
347         tdm_drm_pp_buffer *buffer;
348
349         RETURN_VAL_IF_FAIL(pp_data, TDM_ERROR_INVALID_PARAMETER);
350         RETURN_VAL_IF_FAIL(src, TDM_ERROR_INVALID_PARAMETER);
351         RETURN_VAL_IF_FAIL(dst, TDM_ERROR_INVALID_PARAMETER);
352
353         if (tbm_surface_internal_get_num_bos(src) > 1 ||
354                 tbm_surface_internal_get_num_bos(dst) > 1) {
355                 TDM_ERR("can't handle multiple tbm bos");
356                 return TDM_ERROR_OPERATION_FAILED;
357         }
358
359         buffer = calloc(1, sizeof(tdm_drm_pp_buffer));
360         if (!buffer) {
361                 TDM_ERR("alloc failed");
362                 return TDM_ERROR_NONE;
363         }
364
365         LIST_ADDTAIL(&buffer->link, &pp_data->pending_buffer_list);
366
367         buffer->src = src;
368         buffer->dst = dst;
369
370         return TDM_ERROR_NONE;
371 }
372
373 tdm_error
374 drm_pp_commit(tdm_pp *pp)
375 {
376         tdm_drm_pp_data *pp_data = pp;
377         tdm_drm_pp_buffer *b = NULL, *bb = NULL;
378
379         RETURN_VAL_IF_FAIL(pp_data, TDM_ERROR_INVALID_PARAMETER);
380
381         LIST_FOR_EACH_ENTRY_SAFE(b, bb, &pp_data->pending_buffer_list, link) {
382                 LIST_DEL(&b->link);
383
384                 _tdm_drm_pp_convert(b, &pp_data->info);
385
386                 if (pp_data->done_func)
387                         pp_data->done_func(pp_data,
388                                                            b->src,
389                                                            b->dst,
390                                                            pp_data->done_user_data);
391                 free(b);
392         }
393
394         return TDM_ERROR_NONE;
395 }
396
397 tdm_error
398 drm_pp_set_done_handler(tdm_pp *pp, tdm_pp_done_handler func, void *user_data)
399 {
400         tdm_drm_pp_data *pp_data = pp;
401
402         RETURN_VAL_IF_FAIL(pp_data, TDM_ERROR_INVALID_PARAMETER);
403         RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
404
405         pp_data->done_func = func;
406         pp_data->done_user_data = user_data;
407
408         return TDM_ERROR_NONE;
409 }