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[] = {
37 #define NUM_PP_FORMAT (sizeof(pp_formats) / sizeof(pp_formats[0]))
39 static int pp_list_init;
40 static struct list_head pp_list;
42 static pixman_format_code_t
43 _tdm_drm_pp_pixman_get_format(tbm_format tbmfmt)
46 case TBM_FORMAT_ARGB8888:
47 return PIXMAN_a8r8g8b8;
48 case TBM_FORMAT_XRGB8888:
49 return PIXMAN_x8r8g8b8;
50 case TBM_FORMAT_YUV420:
51 case TBM_FORMAT_YVU420:
59 _tdm_drm_pp_pixman_convert(pixman_op_t op,
60 unsigned char *srcbuf, unsigned char *dstbuf,
61 pixman_format_code_t src_format, pixman_format_code_t dst_format,
62 int sbw, int sbh, int sx, int sy, int sw, int sh,
63 int dbw, int dbh, int dx, int dy, int dw, int dh,
64 int rotate, int hflip, int vflip)
66 pixman_image_t *src_img;
67 pixman_image_t *dst_img;
68 struct pixman_f_transform ft;
69 pixman_transform_t transform;
70 int src_stride, dst_stride;
73 double scale_x, scale_y;
77 RETURN_VAL_IF_FAIL(srcbuf != NULL, 0);
78 RETURN_VAL_IF_FAIL(dstbuf != NULL, 0);
80 TDM_DBG("src(%dx%d: %d,%d %dx%d) dst(%dx%d: %d,%d %dx%d) flip(%d,%d), rot(%d)",
81 sbw, sbh, sx, sy, sw, sh, dbw, dbh, dx, dy, dw, dh, hflip, vflip, rotate);
83 src_bpp = PIXMAN_FORMAT_BPP(src_format) / 8;
84 RETURN_VAL_IF_FAIL(src_bpp > 0, 0);
86 dst_bpp = PIXMAN_FORMAT_BPP(dst_format) / 8;
87 RETURN_VAL_IF_FAIL(dst_bpp > 0, 0);
89 rotate_step = (rotate + 360) / 90 % 4;
91 src_stride = sbw * src_bpp;
92 dst_stride = dbw * dst_bpp;
94 src_img = pixman_image_create_bits(src_format, sbw, sbh, (uint32_t *)srcbuf,
96 dst_img = pixman_image_create_bits(dst_format, dbw, dbh, (uint32_t *)dstbuf,
99 GOTO_IF_FAIL(src_img != NULL, CANT_CONVERT);
100 GOTO_IF_FAIL(dst_img != NULL, CANT_CONVERT);
102 pixman_f_transform_init_identity(&ft);
105 pixman_f_transform_scale(&ft, NULL, -1, 1);
106 pixman_f_transform_translate(&ft, NULL, dw, 0);
110 pixman_f_transform_scale(&ft, NULL, 1, -1);
111 pixman_f_transform_translate(&ft, NULL, 0, dh);
114 if (rotate_step > 0) {
115 int c = 0, s = 0, tx = 0, ty = 0;
116 switch (rotate_step) {
117 case 1: /* 90 degrees */
120 case 2: /* 180 degrees */
121 c = -1, tx = -dw, ty = -dh;
123 case 3: /* 270 degrees */
128 pixman_f_transform_translate(&ft, NULL, tx, ty);
129 pixman_f_transform_rotate(&ft, NULL, c, s);
132 if (rotate_step % 2 == 0) {
133 scale_x = (double)sw / dw;
134 scale_y = (double)sh / dh;
136 scale_x = (double)sw / dh;
137 scale_y = (double)sh / dw;
140 pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
141 pixman_f_transform_translate(&ft, NULL, sx, sy);
143 pixman_transform_from_pixman_f_transform(&transform, &ft);
144 pixman_image_set_transform(src_img, &transform);
146 pixman_image_composite(op, src_img, NULL, dst_img, 0, 0, 0, 0, dx, dy, dw, dh);
152 pixman_image_unref(src_img);
154 pixman_image_unref(dst_img);
160 _tdm_drm_pp_convert(tdm_drm_pp_buffer *buffer, tdm_info_pp *info)
162 tbm_surface_info_s src_info, dst_info;
163 pixman_format_code_t src_format, dst_format;
165 int rotate = 0, hflip = 0;
170 RETURN_VAL_IF_FAIL(buffer != NULL, TDM_ERROR_INVALID_PARAMETER);
171 RETURN_VAL_IF_FAIL(buffer->src != NULL, TDM_ERROR_INVALID_PARAMETER);
172 RETURN_VAL_IF_FAIL(buffer->dst != NULL, TDM_ERROR_INVALID_PARAMETER);
173 RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
175 bo_cnt = tbm_surface_internal_get_num_bos(buffer->src);
176 RETURN_VAL_IF_FAIL(bo_cnt == 1, TDM_ERROR_INVALID_PARAMETER);
178 bo_cnt = tbm_surface_internal_get_num_bos(buffer->dst);
179 RETURN_VAL_IF_FAIL(bo_cnt == 1, TDM_ERROR_INVALID_PARAMETER);
181 bo = tbm_surface_internal_get_bo(buffer->src, 0);
182 RETURN_VAL_IF_FAIL(bo != NULL, TDM_ERROR_INVALID_PARAMETER);
184 bo_size = tbm_bo_size(bo);
186 /* not handle buffers which have 2 more gem handles */
188 memset(&src_info, 0, sizeof(tbm_surface_info_s));
189 tbm_surface_map(buffer->src, TBM_OPTION_READ, &src_info);
190 GOTO_IF_FAIL(src_info.planes[0].ptr != NULL, fail_convert);
192 memset(&dst_info, 0, sizeof(tbm_surface_info_s));
193 tbm_surface_map(buffer->dst, TBM_OPTION_WRITE, &dst_info);
194 GOTO_IF_FAIL(dst_info.planes[0].ptr != NULL, fail_convert);
196 src_format = _tdm_drm_pp_pixman_get_format(src_info.format);
197 GOTO_IF_FAIL(src_format > 0, fail_convert);
198 dst_format = _tdm_drm_pp_pixman_get_format(dst_info.format);
199 GOTO_IF_FAIL(dst_format > 0, fail_convert);
201 GOTO_IF_FAIL(pixman_format_supported_destination(dst_format), fail_convert);
203 if (src_info.format == TBM_FORMAT_YUV420) {
204 if (dst_info.format == TBM_FORMAT_XRGB8888)
205 dst_format = PIXMAN_x8b8g8r8;
206 else if (dst_info.format == TBM_FORMAT_ARGB8888)
207 dst_format = PIXMAN_a8b8g8r8;
208 else if (dst_info.format == TBM_FORMAT_YVU420) {
209 TDM_ERR("can't convert %c%c%c%c to %c%c%c%c",
210 FOURCC_STR(src_info.format), FOURCC_STR(dst_info.format));
214 /* need checking for other formats also? */
216 if (IS_RGB(src_info.format))
217 sbw = src_info.planes[0].stride >> 2;
219 sbw = src_info.planes[0].stride;
221 if (IS_RGB(dst_info.format))
222 dbw = dst_info.planes[0].stride >> 2;
224 dbw = dst_info.planes[0].stride;
226 rotate = (info->transform % 4) * 90;
227 if (info->transform >= TDM_TRANSFORM_FLIPPED)
230 if (bo_size < src_info.planes[0].stride * src_info.height) {
231 TDM_WRN("bo size(%d) is smaller than the expected size(%d)",
232 bo_size, src_info.planes[0].stride * src_info.height);
236 _tdm_drm_pp_pixman_convert(PIXMAN_OP_SRC,
237 src_info.planes[0].ptr, dst_info.planes[0].ptr,
238 src_format, dst_format,
239 sbw, src_info.height,
240 info->src_config.pos.x, info->src_config.pos.y,
241 info->src_config.pos.w, info->src_config.pos.h,
242 dbw, dst_info.height,
243 info->dst_config.pos.x, info->dst_config.pos.y,
244 info->dst_config.pos.w, info->dst_config.pos.h,
246 tbm_surface_unmap(buffer->src);
247 tbm_surface_unmap(buffer->dst);
249 return TDM_ERROR_NONE;
251 tbm_surface_unmap(buffer->src);
252 tbm_surface_unmap(buffer->dst);
253 return TDM_ERROR_OPERATION_FAILED;
257 tdm_drm_pp_get_capability(tdm_drm_data *drm_data, tdm_caps_pp *caps)
262 TDM_ERR("invalid params");
263 return TDM_ERROR_INVALID_PARAMETER;
266 caps->capabilities = TDM_PP_CAPABILITY_SYNC;
268 caps->format_count = NUM_PP_FORMAT;
270 /* will be freed in frontend */
271 caps->formats = calloc(1, sizeof pp_formats);
272 if (!caps->formats) {
273 TDM_ERR("alloc failed");
274 return TDM_ERROR_OUT_OF_MEMORY;
276 for (i = 0; i < caps->format_count; i++)
277 caps->formats[i] = pp_formats[i];
281 caps->max_w = -1; /* not defined */
283 caps->preferred_align = 16;
285 return TDM_ERROR_NONE;
289 tdm_drm_pp_create(tdm_drm_data *drm_data, tdm_error *error)
291 tdm_drm_pp_data *pp_data = calloc(1, sizeof(tdm_drm_pp_data));
293 TDM_ERR("alloc failed");
295 *error = TDM_ERROR_OUT_OF_MEMORY;
299 pp_data->drm_data = drm_data;
301 LIST_INITHEAD(&pp_data->pending_buffer_list);
305 LIST_INITHEAD(&pp_list);
307 LIST_ADDTAIL(&pp_data->link, &pp_list);
313 drm_pp_destroy(tdm_pp *pp)
315 tdm_drm_pp_data *pp_data = pp;
316 tdm_drm_pp_buffer *b = NULL, *bb = NULL;
321 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &pp_data->pending_buffer_list, link) {
326 LIST_DEL(&pp_data->link);
332 drm_pp_set_info(tdm_pp *pp, tdm_info_pp *info)
334 tdm_drm_pp_data *pp_data = pp;
336 RETURN_VAL_IF_FAIL(pp_data, TDM_ERROR_INVALID_PARAMETER);
337 RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
339 pp_data->info = *info;
341 return TDM_ERROR_NONE;
345 drm_pp_attach(tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst)
347 tdm_drm_pp_data *pp_data = pp;
348 tdm_drm_pp_buffer *buffer;
350 RETURN_VAL_IF_FAIL(pp_data, TDM_ERROR_INVALID_PARAMETER);
351 RETURN_VAL_IF_FAIL(src, TDM_ERROR_INVALID_PARAMETER);
352 RETURN_VAL_IF_FAIL(dst, TDM_ERROR_INVALID_PARAMETER);
354 if (tbm_surface_internal_get_num_bos(src) > 1 ||
355 tbm_surface_internal_get_num_bos(dst) > 1) {
356 TDM_ERR("can't handle multiple tbm bos");
357 return TDM_ERROR_OPERATION_FAILED;
360 buffer = calloc(1, sizeof(tdm_drm_pp_buffer));
362 TDM_ERR("alloc failed");
363 return TDM_ERROR_NONE;
366 LIST_ADDTAIL(&buffer->link, &pp_data->pending_buffer_list);
371 return TDM_ERROR_NONE;
375 drm_pp_commit(tdm_pp *pp)
377 tdm_drm_pp_data *pp_data = pp;
378 tdm_drm_pp_buffer *b = NULL, *bb = NULL;
380 RETURN_VAL_IF_FAIL(pp_data, TDM_ERROR_INVALID_PARAMETER);
382 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &pp_data->pending_buffer_list, link) {
385 _tdm_drm_pp_convert(b, &pp_data->info);
387 if (pp_data->done_func)
388 pp_data->done_func(pp_data,
391 pp_data->done_user_data);
395 return TDM_ERROR_NONE;
399 drm_pp_set_done_handler(tdm_pp *pp, tdm_pp_done_handler func, void *user_data)
401 tdm_drm_pp_data *pp_data = pp;
403 RETURN_VAL_IF_FAIL(pp_data, TDM_ERROR_INVALID_PARAMETER);
404 RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
406 pp_data->done_func = func;
407 pp_data->done_user_data = user_data;
409 return TDM_ERROR_NONE;