8 #include "tdm_helper.h"
10 typedef struct _tdm_drm_pp_buffer {
14 struct list_head link;
17 typedef struct _tdm_drm_pp_data {
18 tdm_drm_data *drm_data;
22 struct list_head pending_buffer_list;
24 tdm_pp_done_handler done_func;
27 struct list_head link;
31 static tbm_format pp_formats[] = {
38 #define NUM_PP_FORMAT (sizeof(pp_formats) / sizeof(pp_formats[0]))
40 static int pp_list_init;
41 static struct list_head pp_list;
43 static pixman_format_code_t
44 _tdm_drm_pp_pixman_get_format(tbm_format 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:
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)
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;
74 double scale_x, scale_y;
78 RETURN_VAL_IF_FAIL(srcbuf != NULL, 0);
79 RETURN_VAL_IF_FAIL(dstbuf != NULL, 0);
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);
84 src_bpp = PIXMAN_FORMAT_BPP(src_format) / 8;
85 RETURN_VAL_IF_FAIL(src_bpp > 0, 0);
87 dst_bpp = PIXMAN_FORMAT_BPP(dst_format) / 8;
88 RETURN_VAL_IF_FAIL(dst_bpp > 0, 0);
90 rotate_step = (rotate + 360) / 90 % 4;
92 src_stride = sbw * src_bpp;
93 dst_stride = dbw * dst_bpp;
95 src_img = pixman_image_create_bits(src_format, sbw, sbh, (uint32_t *)srcbuf,
97 dst_img = pixman_image_create_bits(dst_format, dbw, dbh, (uint32_t *)dstbuf,
100 GOTO_IF_FAIL(src_img != NULL, CANT_CONVERT);
101 GOTO_IF_FAIL(dst_img != NULL, CANT_CONVERT);
103 pixman_f_transform_init_identity(&ft);
106 pixman_f_transform_scale(&ft, NULL, -1, 1);
107 pixman_f_transform_translate(&ft, NULL, dw, 0);
111 pixman_f_transform_scale(&ft, NULL, 1, -1);
112 pixman_f_transform_translate(&ft, NULL, 0, dh);
115 if (rotate_step > 0) {
116 int c = 0, s = 0, tx = 0, ty = 0;
117 switch (rotate_step) {
118 case 1: /* 90 degrees */
121 case 2: /* 180 degrees */
122 c = -1, tx = -dw, ty = -dh;
124 case 3: /* 270 degrees */
129 pixman_f_transform_translate(&ft, NULL, tx, ty);
130 pixman_f_transform_rotate(&ft, NULL, c, s);
133 if (rotate_step % 2 == 0) {
134 scale_x = (double)sw / dw;
135 scale_y = (double)sh / dh;
137 scale_x = (double)sw / dh;
138 scale_y = (double)sh / dw;
141 pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
142 pixman_f_transform_translate(&ft, NULL, sx, sy);
144 pixman_transform_from_pixman_f_transform(&transform, &ft);
145 pixman_image_set_transform(src_img, &transform);
147 pixman_image_composite(op, src_img, NULL, dst_img, 0, 0, 0, 0, dx, dy, dw, dh);
153 pixman_image_unref(src_img);
155 pixman_image_unref(dst_img);
161 _tdm_drm_pp_convert(tdm_drm_pp_buffer *buffer, tdm_info_pp *info)
163 tbm_surface_info_s src_info, dst_info;
164 pixman_format_code_t src_format, dst_format;
166 int rotate = 0, hflip = 0;
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);
176 bo_cnt = tbm_surface_internal_get_num_bos(buffer->src);
177 RETURN_VAL_IF_FAIL(bo_cnt == 1, TDM_ERROR_INVALID_PARAMETER);
179 bo_cnt = tbm_surface_internal_get_num_bos(buffer->dst);
180 RETURN_VAL_IF_FAIL(bo_cnt == 1, TDM_ERROR_INVALID_PARAMETER);
182 bo = tbm_surface_internal_get_bo(buffer->src, 0);
183 RETURN_VAL_IF_FAIL(bo != NULL, TDM_ERROR_INVALID_PARAMETER);
185 bo_size = tbm_bo_size(bo);
187 /* not handle buffers which have 2 more gem handles */
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);
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);
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);
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));
213 /* need checking for other formats also? */
215 if (IS_RGB(src_info.format))
216 sbw = src_info.planes[0].stride >> 2;
218 sbw = src_info.planes[0].stride;
220 if (IS_RGB(dst_info.format))
221 dbw = dst_info.planes[0].stride >> 2;
223 dbw = dst_info.planes[0].stride;
225 rotate = (info->transform % 4) * 90;
226 if (info->transform >= TDM_TRANSFORM_FLIPPED)
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);
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,
245 tbm_surface_unmap(buffer->src);
246 tbm_surface_unmap(buffer->dst);
248 return TDM_ERROR_NONE;
250 tbm_surface_unmap(buffer->src);
251 tbm_surface_unmap(buffer->dst);
252 return TDM_ERROR_OPERATION_FAILED;
256 tdm_drm_pp_get_capability(tdm_drm_data *drm_data, tdm_caps_pp *caps)
261 TDM_ERR("invalid params");
262 return TDM_ERROR_INVALID_PARAMETER;
265 caps->capabilities = TDM_PP_CAPABILITY_SYNC;
267 caps->format_count = NUM_PP_FORMAT;
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;
275 for (i = 0; i < caps->format_count; i++)
276 caps->formats[i] = pp_formats[i];
280 caps->max_w = -1; /* not defined */
282 caps->preferred_align = 16;
284 return TDM_ERROR_NONE;
288 tdm_drm_pp_create(tdm_drm_data *drm_data, tdm_error *error)
290 tdm_drm_pp_data *pp_data = calloc(1, sizeof(tdm_drm_pp_data));
292 TDM_ERR("alloc failed");
294 *error = TDM_ERROR_OUT_OF_MEMORY;
298 pp_data->drm_data = drm_data;
300 LIST_INITHEAD(&pp_data->pending_buffer_list);
304 LIST_INITHEAD(&pp_list);
306 LIST_ADDTAIL(&pp_data->link, &pp_list);
312 drm_pp_destroy(tdm_pp *pp)
314 tdm_drm_pp_data *pp_data = pp;
315 tdm_drm_pp_buffer *b = NULL, *bb = NULL;
320 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &pp_data->pending_buffer_list, link) {
325 LIST_DEL(&pp_data->link);
331 drm_pp_set_info(tdm_pp *pp, tdm_info_pp *info)
333 tdm_drm_pp_data *pp_data = pp;
335 RETURN_VAL_IF_FAIL(pp_data, TDM_ERROR_INVALID_PARAMETER);
336 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
338 pp_data->info = *info;
340 return TDM_ERROR_NONE;
344 drm_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst)
346 tdm_drm_pp_data *pp_data = pp;
347 tdm_drm_pp_buffer *buffer;
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);
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;
359 buffer = calloc(1, sizeof(tdm_drm_pp_buffer));
361 TDM_ERR("alloc failed");
362 return TDM_ERROR_NONE;
365 LIST_ADDTAIL(&buffer->link, &pp_data->pending_buffer_list);
370 return TDM_ERROR_NONE;
374 drm_pp_commit(tdm_pp *pp)
376 tdm_drm_pp_data *pp_data = pp;
377 tdm_drm_pp_buffer *b = NULL, *bb = NULL;
379 RETURN_VAL_IF_FAIL(pp_data, TDM_ERROR_INVALID_PARAMETER);
381 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &pp_data->pending_buffer_list, link) {
384 _tdm_drm_pp_convert(b, &pp_data->info);
386 if (pp_data->done_func)
387 pp_data->done_func(pp_data,
390 pp_data->done_user_data);
394 return TDM_ERROR_NONE;
398 drm_pp_set_done_handler(tdm_pp *pp, tdm_pp_done_handler func, void *user_data)
400 tdm_drm_pp_data *pp_data = pp;
402 RETURN_VAL_IF_FAIL(pp_data, TDM_ERROR_INVALID_PARAMETER);
403 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
405 pp_data->done_func = func;
406 pp_data->done_user_data = user_data;
408 return TDM_ERROR_NONE;