5 #include "tdm_backend_drm.h"
7 typedef struct _tdm_drm_pp_buffer {
11 struct list_head link;
14 typedef struct _tdm_drm_pp_data {
15 tdm_drm_display *display_data;
19 struct list_head pending_buffer_list;
21 hal_tdm_pp_done_handler done_func;
24 struct list_head link;
28 static tbm_format pp_formats[] = {
34 #define NUM_PP_FORMAT (sizeof(pp_formats) / sizeof(pp_formats[0]))
36 static int pp_list_init;
37 static struct list_head pp_list;
39 static pixman_format_code_t
40 _tdm_drm_pp_pixman_get_format(tbm_format tbmfmt)
43 case TBM_FORMAT_ARGB8888:
44 return PIXMAN_a8r8g8b8;
45 case TBM_FORMAT_XRGB8888:
46 return PIXMAN_x8r8g8b8;
47 case TBM_FORMAT_YUV420:
48 case TBM_FORMAT_YVU420:
56 _tdm_drm_pp_pixman_convert(pixman_op_t op,
57 unsigned char *srcbuf, unsigned char *dstbuf,
58 pixman_format_code_t src_format, pixman_format_code_t dst_format,
59 int sbw, int sbh, int sx, int sy, int sw, int sh,
60 int dbw, int dbh, int dx, int dy, int dw, int dh,
61 int rotate, int hflip, int vflip)
63 pixman_image_t *src_img;
64 pixman_image_t *dst_img;
65 struct pixman_f_transform ft;
66 pixman_transform_t transform;
67 int src_stride, dst_stride;
70 double scale_x, scale_y;
74 RETURN_VAL_IF_FAIL(srcbuf != NULL, 0);
75 RETURN_VAL_IF_FAIL(dstbuf != NULL, 0);
77 TDM_BACKEND_DBG("src(%dx%d: %d,%d %dx%d) dst(%dx%d: %d,%d %dx%d) flip(%d,%d), rot(%d)",
78 sbw, sbh, sx, sy, sw, sh, dbw, dbh, dx, dy, dw, dh, hflip, vflip, rotate);
80 src_bpp = PIXMAN_FORMAT_BPP(src_format) / 8;
81 RETURN_VAL_IF_FAIL(src_bpp > 0, 0);
83 dst_bpp = PIXMAN_FORMAT_BPP(dst_format) / 8;
84 RETURN_VAL_IF_FAIL(dst_bpp > 0, 0);
86 rotate_step = (rotate + 360) / 90 % 4;
88 src_stride = sbw * src_bpp;
89 dst_stride = dbw * dst_bpp;
91 src_img = pixman_image_create_bits(src_format, sbw, sbh, (uint32_t *)srcbuf,
93 dst_img = pixman_image_create_bits(dst_format, dbw, dbh, (uint32_t *)dstbuf,
96 GOTO_IF_FAIL(src_img != NULL, CANT_CONVERT);
97 GOTO_IF_FAIL(dst_img != NULL, CANT_CONVERT);
99 pixman_f_transform_init_identity(&ft);
102 pixman_f_transform_scale(&ft, NULL, -1, 1);
103 pixman_f_transform_translate(&ft, NULL, dw, 0);
107 pixman_f_transform_scale(&ft, NULL, 1, -1);
108 pixman_f_transform_translate(&ft, NULL, 0, dh);
111 if (rotate_step > 0) {
112 int c = 0, s = 0, tx = 0, ty = 0;
113 switch (rotate_step) {
114 case 1: /* 90 degrees */
117 case 2: /* 180 degrees */
118 c = -1, tx = -dw, ty = -dh;
120 case 3: /* 270 degrees */
125 pixman_f_transform_translate(&ft, NULL, tx, ty);
126 pixman_f_transform_rotate(&ft, NULL, c, s);
129 if (rotate_step % 2 == 0) {
130 scale_x = (double)sw / dw;
131 scale_y = (double)sh / dh;
133 scale_x = (double)sw / dh;
134 scale_y = (double)sh / dw;
137 pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
138 pixman_f_transform_translate(&ft, NULL, sx, sy);
140 pixman_transform_from_pixman_f_transform(&transform, &ft);
141 pixman_image_set_transform(src_img, &transform);
143 pixman_image_composite(op, src_img, NULL, dst_img, 0, 0, 0, 0, dx, dy, dw, dh);
149 pixman_image_unref(src_img);
151 pixman_image_unref(dst_img);
157 _tdm_drm_pp_convert(tdm_drm_pp_buffer *buffer, hal_tdm_info_pp *info)
159 tbm_surface_info_s src_info, dst_info;
160 pixman_format_code_t src_format, dst_format;
162 int rotate = 0, hflip = 0;
167 RETURN_VAL_IF_FAIL(buffer != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
168 RETURN_VAL_IF_FAIL(buffer->src != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
169 RETURN_VAL_IF_FAIL(buffer->dst != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
170 RETURN_VAL_IF_FAIL(info != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
172 bo_cnt = tbm_surface_internal_get_num_bos(buffer->src);
173 RETURN_VAL_IF_FAIL(bo_cnt == 1, HAL_TDM_ERROR_INVALID_PARAMETER);
175 bo_cnt = tbm_surface_internal_get_num_bos(buffer->dst);
176 RETURN_VAL_IF_FAIL(bo_cnt == 1, HAL_TDM_ERROR_INVALID_PARAMETER);
178 bo = tbm_surface_internal_get_bo(buffer->src, 0);
179 RETURN_VAL_IF_FAIL(bo != NULL, HAL_TDM_ERROR_INVALID_PARAMETER);
181 bo_size = tbm_bo_size(bo);
183 /* not handle buffers which have 2 more gem handles */
185 memset(&src_info, 0, sizeof(tbm_surface_info_s));
186 tbm_surface_map(buffer->src, TBM_OPTION_READ, &src_info);
187 GOTO_IF_FAIL(src_info.planes[0].ptr != NULL, fail_convert);
189 memset(&dst_info, 0, sizeof(tbm_surface_info_s));
190 tbm_surface_map(buffer->dst, TBM_OPTION_WRITE, &dst_info);
191 GOTO_IF_FAIL(dst_info.planes[0].ptr != NULL, fail_convert);
193 src_format = _tdm_drm_pp_pixman_get_format(src_info.format);
194 GOTO_IF_FAIL(src_format > 0, fail_convert);
195 dst_format = _tdm_drm_pp_pixman_get_format(dst_info.format);
196 GOTO_IF_FAIL(dst_format > 0, fail_convert);
198 GOTO_IF_FAIL(pixman_format_supported_destination(dst_format), fail_convert);
200 if (src_info.format == TBM_FORMAT_YUV420) {
201 if (dst_info.format == TBM_FORMAT_XRGB8888)
202 dst_format = PIXMAN_x8b8g8r8;
203 else if (dst_info.format == TBM_FORMAT_ARGB8888)
204 dst_format = PIXMAN_a8b8g8r8;
205 else if (dst_info.format == TBM_FORMAT_YVU420) {
206 TDM_BACKEND_ERR("can't convert %c%c%c%c to %c%c%c%c",
207 FOURCC_STR(src_info.format), FOURCC_STR(dst_info.format));
211 /* need checking for other formats also? */
213 if (IS_RGB(src_info.format))
214 sbw = src_info.planes[0].stride >> 2;
216 sbw = src_info.planes[0].stride;
218 if (IS_RGB(dst_info.format))
219 dbw = dst_info.planes[0].stride >> 2;
221 dbw = dst_info.planes[0].stride;
223 rotate = (info->transform % 4) * 90;
224 if (info->transform >= HAL_TDM_TRANSFORM_FLIPPED)
227 if (bo_size < src_info.planes[0].stride * src_info.height) {
228 TDM_BACKEND_WRN("bo size(%d) is smaller than the expected size(%d)",
229 bo_size, src_info.planes[0].stride * src_info.height);
233 _tdm_drm_pp_pixman_convert(PIXMAN_OP_SRC,
234 src_info.planes[0].ptr, dst_info.planes[0].ptr,
235 src_format, dst_format,
236 sbw, src_info.height,
237 info->src_config.pos.x, info->src_config.pos.y,
238 info->src_config.pos.w, info->src_config.pos.h,
239 dbw, dst_info.height,
240 info->dst_config.pos.x, info->dst_config.pos.y,
241 info->dst_config.pos.w, info->dst_config.pos.h,
243 tbm_surface_unmap(buffer->src);
244 tbm_surface_unmap(buffer->dst);
246 return HAL_TDM_ERROR_NONE;
248 tbm_surface_unmap(buffer->src);
249 tbm_surface_unmap(buffer->dst);
250 return HAL_TDM_ERROR_OPERATION_FAILED;
254 tdm_drm_pp_get_capability(tdm_drm_display *display_data, hal_tdm_caps_pp *caps)
259 TDM_BACKEND_ERR("invalid params");
260 return HAL_TDM_ERROR_INVALID_PARAMETER;
263 caps->capabilities = HAL_TDM_PP_CAPABILITY_SYNC;
265 caps->format_count = NUM_PP_FORMAT;
267 /* will be freed in frontend */
268 caps->formats = calloc(1, sizeof pp_formats);
269 if (!caps->formats) {
270 TDM_BACKEND_ERR("alloc failed");
271 return HAL_TDM_ERROR_OUT_OF_MEMORY;
273 for (i = 0; i < caps->format_count; i++)
274 caps->formats[i] = pp_formats[i];
278 caps->max_w = -1; /* not defined */
280 caps->preferred_align = 16;
282 return HAL_TDM_ERROR_NONE;
286 tdm_drm_pp_create(tdm_drm_display *display_data, hal_tdm_error *error)
288 tdm_drm_pp_data *pp_data = calloc(1, sizeof(tdm_drm_pp_data));
290 TDM_BACKEND_ERR("alloc failed");
292 *error = HAL_TDM_ERROR_OUT_OF_MEMORY;
296 pp_data->display_data = display_data;
298 LIST_INITHEAD(&pp_data->pending_buffer_list);
302 LIST_INITHEAD(&pp_list);
304 LIST_ADDTAIL(&pp_data->link, &pp_list);
310 drm_pp_destroy(hal_tdm_pp *pp)
312 tdm_drm_pp_data *pp_data = pp;
313 tdm_drm_pp_buffer *b = NULL, *bb = NULL;
318 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &pp_data->pending_buffer_list, link) {
323 LIST_DEL(&pp_data->link);
329 drm_pp_set_info(hal_tdm_pp *pp, hal_tdm_info_pp *info)
331 tdm_drm_pp_data *pp_data = pp;
333 RETURN_VAL_IF_FAIL(pp_data, HAL_TDM_ERROR_INVALID_PARAMETER);
334 RETURN_VAL_IF_FAIL(info, HAL_TDM_ERROR_INVALID_PARAMETER);
336 pp_data->info = *info;
338 return HAL_TDM_ERROR_NONE;
342 drm_pp_attach(hal_tdm_pp *pp, tbm_surface_h src, tbm_surface_h dst)
344 tdm_drm_pp_data *pp_data = pp;
345 tdm_drm_pp_buffer *buffer;
347 RETURN_VAL_IF_FAIL(pp_data, HAL_TDM_ERROR_INVALID_PARAMETER);
348 RETURN_VAL_IF_FAIL(src, HAL_TDM_ERROR_INVALID_PARAMETER);
349 RETURN_VAL_IF_FAIL(dst, HAL_TDM_ERROR_INVALID_PARAMETER);
351 if (tbm_surface_internal_get_num_bos(src) > 1 ||
352 tbm_surface_internal_get_num_bos(dst) > 1) {
353 TDM_BACKEND_ERR("can't handle multiple tbm bos");
354 return HAL_TDM_ERROR_OPERATION_FAILED;
357 buffer = calloc(1, sizeof(tdm_drm_pp_buffer));
359 TDM_BACKEND_ERR("alloc failed");
360 return HAL_TDM_ERROR_NONE;
363 LIST_ADDTAIL(&buffer->link, &pp_data->pending_buffer_list);
368 return HAL_TDM_ERROR_NONE;
372 drm_pp_commit(hal_tdm_pp *pp)
374 tdm_drm_pp_data *pp_data = pp;
375 tdm_drm_pp_buffer *b = NULL, *bb = NULL;
377 RETURN_VAL_IF_FAIL(pp_data, HAL_TDM_ERROR_INVALID_PARAMETER);
379 LIST_FOR_EACH_ENTRY_SAFE(b, bb, &pp_data->pending_buffer_list, link) {
382 _tdm_drm_pp_convert(b, &pp_data->info);
384 if (pp_data->done_func)
385 pp_data->done_func(pp_data,
388 pp_data->done_user_data);
392 return HAL_TDM_ERROR_NONE;
396 drm_pp_set_done_handler(hal_tdm_pp *pp, hal_tdm_pp_done_handler func, void *user_data)
398 tdm_drm_pp_data *pp_data = pp;
400 RETURN_VAL_IF_FAIL(pp_data, HAL_TDM_ERROR_INVALID_PARAMETER);
401 RETURN_VAL_IF_FAIL(func, HAL_TDM_ERROR_INVALID_PARAMETER);
403 pp_data->done_func = func;
404 pp_data->done_user_data = user_data;
406 return HAL_TDM_ERROR_NONE;