diff options
author | Changyeon Lee <cyeon.lee@samsung.com> | 2021-01-19 14:25:08 +0900 |
---|---|---|
committer | Changyeon Lee <cyeon.lee@samsung.com> | 2021-01-19 14:37:46 +0900 |
commit | c91000438f5364e7db14fc328c3f2d48efe59398 (patch) | |
tree | 96b330c637a22f738af99950da6618dea4fc6456 | |
parent | ffc3419497e988f44a1f1fb31059354b62480c8c (diff) | |
download | libtdm-vc4-c91000438f5364e7db14fc328c3f2d48efe59398.tar.gz libtdm-vc4-c91000438f5364e7db14fc328c3f2d48efe59398.tar.bz2 libtdm-vc4-c91000438f5364e7db14fc328c3f2d48efe59398.zip |
support hw cursor transform
Change-Id: Id07e84336c1a5f81b4ac98dc4e868b5bd9b077fd
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | packaging/libtdm-vc4.spec | 1 | ||||
-rw-r--r-- | src/tdm_vc4_hwc.c | 331 | ||||
-rw-r--r-- | src/tdm_vc4_hwc_window.c | 1 | ||||
-rw-r--r-- | src/tdm_vc4_types.h | 1 |
5 files changed, 247 insertions, 89 deletions
diff --git a/configure.ac b/configure.ac index 497c60a..7dce675 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ LT_INIT([disable-static]) # Enable quiet compiles on automake 1.11. m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) -PKG_CHECK_MODULES(TDM_VC4, libtdm libtbm libdrm) +PKG_CHECK_MODULES(TDM_VC4, libtdm libtbm libdrm pixman-1) PKG_CHECK_MODULES(UDEV, libudev, [udev=yes], [udev=no]) if test x"$udev" = xyes; then AC_DEFINE(HAVE_UDEV,1,[Enable udev-based monitor hotplug detection]) diff --git a/packaging/libtdm-vc4.spec b/packaging/libtdm-vc4.spec index 69b7e51..42550c6 100644 --- a/packaging/libtdm-vc4.spec +++ b/packaging/libtdm-vc4.spec @@ -9,6 +9,7 @@ Source1001: %{name}.manifest BuildRequires: pkgconfig(libdrm) BuildRequires: pkgconfig(libudev) BuildRequires: pkgconfig(libtdm) +BuildRequires: pkgconfig(pixman-1) ExclusiveArch: %{arm} aarch64 %description diff --git a/src/tdm_vc4_hwc.c b/src/tdm_vc4_hwc.c index 584f356..fb81cfa 100644 --- a/src/tdm_vc4_hwc.c +++ b/src/tdm_vc4_hwc.c @@ -3,6 +3,7 @@ #endif #include <tdm_helper.h> +#include <pixman.h> #include "tdm_vc4.h" #define MIN_WIDTH 32 @@ -41,8 +42,168 @@ _comp_to_str(tdm_hwc_window_composition composition_type) return "unknown"; } +static tbm_surface_queue_h +_vc4_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error) +{ + tdm_vc4_hwc_window_data *hwc_window_data = NULL; + tbm_surface_queue_h tqueue = NULL; + int width, height; + tbm_format format; + + if (error) + *error = TDM_ERROR_INVALID_PARAMETER; + + RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL); + + hwc_window_data = hwc_window; + + width = hwc_window_data->info.src_config.size.h; + height = hwc_window_data->info.src_config.size.v; + format = hwc_window_data->info.src_config.format; + + tqueue = tbm_surface_queue_create(NUM_BUFFERS, width, height, format, TBM_BO_SCANOUT); + if (error) + *error = TDM_ERROR_OPERATION_FAILED; + RETURN_VAL_IF_FAIL(tqueue != NULL, NULL); + + if (error) + *error = TDM_ERROR_NONE; + + return tqueue; +} + +static tbm_surface_queue_h +_vc4_hwc_window_get_cursor_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error) +{ + tdm_vc4_hwc_window_data *hwc_window_data = NULL; + tbm_surface_queue_h tqueue = NULL; + int width, height; + + if (error) + *error = TDM_ERROR_INVALID_PARAMETER; + + RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL); + + hwc_window_data = hwc_window; + + switch (hwc_window_data->info.transform) { + case TDM_TRANSFORM_90: + case TDM_TRANSFORM_FLIPPED_90: + case TDM_TRANSFORM_270: + case TDM_TRANSFORM_FLIPPED_270: + width = hwc_window_data->cursor_img.height; + height = hwc_window_data->cursor_img.width; + break; + default: + width = hwc_window_data->cursor_img.width; + height = hwc_window_data->cursor_img.height; + break; + } + + tqueue = tbm_surface_queue_create(NUM_BUFFERS, width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT); + if (error) + *error = TDM_ERROR_OPERATION_FAILED; + RETURN_VAL_IF_FAIL(tqueue != NULL, NULL); + + tbm_surface_queue_set_modes(tqueue, TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE); + + if (error) + *error = TDM_ERROR_NONE; + + return tqueue; +} + static int -_vc4_hwc_cursor_buffer_unset(tdm_vc4_hwc_window_data *hwc_window_data) +_vc4_hwc_cursor_buffer_image_render(tdm_vc4_hwc_data *hwc_data, tdm_vc4_hwc_window_data *hwc_window_data) +{ + tbm_surface_info_s tsurface_info; + tbm_surface_error_e ret = TBM_SURFACE_ERROR_NONE; + void *src_ptr = NULL, *dst_ptr = NULL; + int src_stride, transform, img_w, img_h; + pixman_image_t *src_img = NULL, *dst_img = NULL; + pixman_transform_t t; + struct pixman_f_transform ft; + int c = 0, s = 0, tx = 0, ty = 0; + int i; + + ret = tbm_surface_map(hwc_data->cursor_tsurface, TBM_SURF_OPTION_WRITE, &tsurface_info); + if (ret != TBM_SURFACE_ERROR_NONE) { + TDM_ERR("Failed to map tsurface\n"); + return 0; + } + + src_ptr = hwc_window_data->cursor_img.ptr; + src_stride = hwc_window_data->cursor_img.stride; + img_w = hwc_window_data->cursor_img.width; + img_h = hwc_window_data->cursor_img.height; + transform = hwc_window_data->info.transform; + + dst_ptr = tsurface_info.planes[0].ptr; + + memset(dst_ptr, 0, tsurface_info.planes[0].stride * tsurface_info.height); + + if (transform) { + src_img = pixman_image_create_bits(PIXMAN_a8r8g8b8, img_w, img_h, (uint32_t*)src_ptr, src_stride); + if (!src_img) { + TDM_ERR("Failed to create src pixman\n"); + return 0; + } + + dst_img = pixman_image_create_bits(PIXMAN_a8r8g8b8, tsurface_info.width, tsurface_info.height, + (uint32_t*)dst_ptr, tsurface_info.planes[0].stride); + if (!dst_img) { + TDM_ERR("Failed to create dst pixman\n"); + return 0; + } + + pixman_f_transform_init_identity(&ft); + + if (transform >= TDM_TRANSFORM_FLIPPED) { + pixman_f_transform_scale(&ft, NULL, -1, 1); + pixman_f_transform_translate(&ft, NULL, tsurface_info.width, 0); + } + + switch (transform) { + case TDM_TRANSFORM_90: + case TDM_TRANSFORM_FLIPPED_90: + c = 0, s = 1, ty = -tsurface_info.height; + break; + case TDM_TRANSFORM_180: + case TDM_TRANSFORM_FLIPPED_180: + c = -1, s = 0, tx = -tsurface_info.width, ty = -tsurface_info.height; + break; + case TDM_TRANSFORM_270: + case TDM_TRANSFORM_FLIPPED_270: + c = 0, s = -1, tx = -tsurface_info.width; + break; + default: + break; + } + + pixman_f_transform_translate(&ft, NULL, tx, ty); + pixman_f_transform_rotate(&ft, NULL, c, s); + pixman_transform_from_pixman_f_transform(&t, &ft); + pixman_image_set_transform(src_img, &t); + pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img, 0, 0, 0, 0, 0, 0, + tsurface_info.width, tsurface_info.height); + pixman_image_unref(src_img); + pixman_image_unref(dst_img); + } + else { + for (i = 0 ; i < img_h ; i++) { + memcpy(dst_ptr, src_ptr, src_stride); + dst_ptr += tsurface_info.planes[0].stride; + src_ptr += src_stride; + } + } + + tbm_surface_unmap(hwc_data->cursor_tsurface); + + return 1; +} + +static int +_vc4_hwc_cursor_window_surface_clear(tdm_vc4_hwc_window_data *hwc_window_data) { hwc_window_data->surface = NULL; hwc_window_data->cursor_img_surface = 0; @@ -56,14 +217,35 @@ _vc4_hwc_cursor_buffer_unset(tdm_vc4_hwc_window_data *hwc_window_data) } static void -_vc4_hwc_cursor_adjust_pos(tdm_vc4_hwc_window_data *hwc_window_data) +_vc4_hwc_cursor_buffer_unset(tdm_vc4_hwc_data *hwc_data) { - int x, y; + if (hwc_data->cursor_tsurface) { + tbm_surface_queue_release(hwc_data->cursor_tqueue, hwc_data->cursor_tsurface); + hwc_data->cursor_tsurface = NULL; + } + + if (hwc_data->cursor_tqueue) { + tbm_surface_queue_destroy(hwc_data->cursor_tqueue); + hwc_data->cursor_tqueue = NULL; + } +} + +static void +_vc4_hwc_cursor_adjust_pos(tdm_vc4_hwc_data *hwc_data, tdm_vc4_hwc_window_data *hwc_window_data) +{ + int x, y, width, height; + + width = tbm_surface_get_width(hwc_data->cursor_tsurface); + height = tbm_surface_get_height(hwc_data->cursor_tsurface); + + hwc_window_data->info.src_config.pos.w = width; + hwc_window_data->info.src_config.pos.h = height; + hwc_window_data->info.dst_pos.w = width; + hwc_window_data->info.dst_pos.h = height; /* dst pos of cursor is possible set by negative value * this is temporary code. */ - x = hwc_window_data->info.dst_pos.x; y = hwc_window_data->info.dst_pos.y; @@ -75,65 +257,65 @@ static int _vc4_hwc_cursor_buffer_set(tdm_vc4_hwc_data *hwc_data, tdm_vc4_hwc_window_data *hwc_window_data) { tbm_surface_h cursor_tsurface = NULL; - tbm_surface_info_s tsurface_info; - tbm_surface_error_e ret = TBM_SURFACE_ERROR_NONE; - int img_w, img_h, new_w, new_h; - tbm_format format; - unsigned int flags = TBM_BO_SCANOUT; - void *src_ptr = NULL, *dst_ptr = NULL; - int src_stride; - int i; - - _vc4_hwc_cursor_adjust_pos(hwc_window_data); - - if (!hwc_window_data->cursor_img_refresh && hwc_window_data->surface) - return 1; + tbm_surface_queue_error_e tsq_error = TBM_SURFACE_QUEUE_ERROR_NONE; + int img_w, img_h; + int tqueue_w, tqueue_h; + tdm_error error; + + if (hwc_window_data->cursor_img_refresh || !hwc_window_data->surface) { + switch (hwc_window_data->info.transform) { + case TDM_TRANSFORM_90: + case TDM_TRANSFORM_FLIPPED_90: + case TDM_TRANSFORM_270: + case TDM_TRANSFORM_FLIPPED_270: + img_w = hwc_window_data->cursor_img.height; + img_h = hwc_window_data->cursor_img.width; + break; + default: + img_w = hwc_window_data->cursor_img.width; + img_h = hwc_window_data->cursor_img.height; + break; + } - img_w = hwc_window_data->cursor_img.width; - img_h = hwc_window_data->cursor_img.height; - format = hwc_window_data->info.src_config.format; + if (!hwc_data->cursor_tqueue) { + hwc_data->cursor_tqueue = _vc4_hwc_window_get_cursor_tbm_buffer_queue(hwc_window_data, &error); + if (error != TDM_ERROR_NONE) { + TDM_ERR("Failed to create cursor buffer queue error:%d", error); + return 0; + } + } else { + tqueue_w = tbm_surface_queue_get_width(hwc_data->cursor_tqueue); + tqueue_h = tbm_surface_queue_get_height(hwc_data->cursor_tqueue); + if ((img_w != tqueue_w) || (img_h != tqueue_h)) + tbm_surface_queue_reset(hwc_data->cursor_tqueue, img_w, img_h, TBM_FORMAT_ARGB8888); + } - if (hwc_data->cursor_tsurface) { - tbm_surface_internal_unref(hwc_data->cursor_tsurface); - hwc_data->cursor_tsurface = NULL; - } + if (hwc_data->cursor_tsurface) { + tbm_surface_queue_release(hwc_data->cursor_tqueue, hwc_data->cursor_tsurface); + hwc_data->cursor_tsurface = NULL; + } - cursor_tsurface = tbm_surface_internal_create_with_flags(img_w, img_h, format, flags); - RETURN_VAL_IF_FAIL(cursor_tsurface, 0); + if (!tbm_surface_queue_can_dequeue(hwc_data->cursor_tqueue, 0)) { + TDM_ERR("Can't dequeue cursor tqueue"); + return 0; + } - hwc_data->cursor_tsurface = cursor_tsurface; - ret = tbm_surface_map(hwc_data->cursor_tsurface, TBM_SURF_OPTION_WRITE, &tsurface_info); - if (ret != TBM_SURFACE_ERROR_NONE) { - TDM_ERR("Failed to map tsurface\n"); - tbm_surface_internal_unref(hwc_data->cursor_tsurface); - hwc_data->cursor_tsurface = NULL; - return 0; - } + tsq_error = tbm_surface_queue_dequeue(hwc_data->cursor_tqueue, &cursor_tsurface); + if (tsq_error != TBM_SURFACE_QUEUE_ERROR_NONE) { + TDM_ERR("Failed to dequeue cursor tqueue error:%d", tsq_error); + return 0; + } - src_ptr = hwc_window_data->cursor_img.ptr; - dst_ptr = tsurface_info.planes[0].ptr; - src_stride = hwc_window_data->cursor_img.stride; + hwc_data->cursor_tsurface = cursor_tsurface; - memset(dst_ptr, 0, tsurface_info.planes[0].stride * tsurface_info.height); + _vc4_hwc_cursor_buffer_image_render(hwc_data, hwc_window_data); - for (i = 0 ; i < img_h ; i++) { - memcpy(dst_ptr, src_ptr, src_stride); - dst_ptr += tsurface_info.planes[0].stride; - src_ptr += src_stride; + hwc_window_data->surface = cursor_tsurface; + hwc_window_data->cursor_img_surface = 1; + hwc_window_data->cursor_img_refresh = 0; } - tbm_surface_unmap(hwc_data->cursor_tsurface); - - hwc_window_data->surface = hwc_data->cursor_tsurface; - hwc_window_data->cursor_img_surface = 1; - - /* fix the dst_pos info of the cursor window */ - hwc_window_data->info.src_config.pos.w = img_w; - hwc_window_data->info.src_config.pos.h = img_h; - hwc_window_data->info.dst_pos.w = img_w; - hwc_window_data->info.dst_pos.h = img_h; - - hwc_window_data->cursor_img_refresh = 0; + _vc4_hwc_cursor_adjust_pos(hwc_data, hwc_window_data); return 1; } @@ -198,36 +380,6 @@ _vc4_hwc_window_can_set_on_hw_layer(tdm_vc4_hwc_window_data *hwc_window_data) return 1; } -static tbm_surface_queue_h -_vc4_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error) -{ - tdm_vc4_hwc_window_data *hwc_window_data = NULL; - tbm_surface_queue_h tqueue = NULL; - int width, height; - tbm_format format; - - if (error) - *error = TDM_ERROR_INVALID_PARAMETER; - - RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL); - - hwc_window_data = hwc_window; - - width = hwc_window_data->info.src_config.size.h; - height = hwc_window_data->info.src_config.size.v; - format = hwc_window_data->info.src_config.format; - - tqueue = tbm_surface_queue_create(NUM_BUFFERS, width, height, format, TBM_BO_SCANOUT); - if (error) - *error = TDM_ERROR_OPERATION_FAILED; - RETURN_VAL_IF_FAIL(tqueue != NULL, NULL); - - if (error) - *error = TDM_ERROR_NONE; - - return tqueue; -} - static tdm_error _vc4_hwc_layer_attach_window(tdm_vc4_layer_data *layer_data, tdm_vc4_hwc_window_data *hwc_window_data) { @@ -263,6 +415,7 @@ _vc4_hwc_prepare_commit(tdm_vc4_hwc_data *hwc_data) tdm_vc4_layer_data *layer_data = NULL; int use_layers_zpos[NUM_LAYERS] = {0,}; int lzpos = 0; + int cursor_enabled = 0; /* set target hwc window to the layer */ if (hwc_data->need_target_window) { @@ -275,9 +428,8 @@ _vc4_hwc_prepare_commit(tdm_vc4_hwc_data *hwc_data) LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) { if (hwc_window_data->validated_type == TDM_HWC_WIN_COMPOSITION_NONE || hwc_window_data->validated_type == TDM_HWC_WIN_COMPOSITION_CLIENT) { - if (hwc_window_data->cursor_img_surface) - _vc4_hwc_cursor_buffer_unset(hwc_window_data); + _vc4_hwc_cursor_window_surface_clear(hwc_window_data); continue; } @@ -286,8 +438,10 @@ _vc4_hwc_prepare_commit(tdm_vc4_hwc_data *hwc_data) continue; /* set the cursor buffer HERE if it needs */ - if (hwc_window_data->validated_type == TDM_HWC_WIN_COMPOSITION_CURSOR) + if (hwc_window_data->validated_type == TDM_HWC_WIN_COMPOSITION_CURSOR) { _vc4_hwc_cursor_buffer_set(hwc_data, hwc_window_data); + cursor_enabled = 1; + } layer_data = vc4_output_data_get_layer_data(hwc_data->output_data, hwc_window_data->lzpos); _vc4_hwc_layer_attach_window(layer_data, hwc_window_data); @@ -306,6 +460,9 @@ _vc4_hwc_prepare_commit(tdm_vc4_hwc_data *hwc_data) _vc4_hwc_layer_attach_window(layer_data, NULL); } + if (!cursor_enabled) + _vc4_hwc_cursor_buffer_unset(hwc_data); + /* for debug */ for (lzpos = NUM_LAYERS -1 ; lzpos >= 0; lzpos--) { if (use_layers_zpos[lzpos]) diff --git a/src/tdm_vc4_hwc_window.c b/src/tdm_vc4_hwc_window.c index 1d8721c..2d2996d 100644 --- a/src/tdm_vc4_hwc_window.c +++ b/src/tdm_vc4_hwc_window.c @@ -141,7 +141,6 @@ vc4_hwc_window_set_cursor_image(tdm_hwc_window *hwc_window, int width, int heigh tdm_vc4_hwc_window_data *hwc_window_data = hwc_window; RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER); - RETURN_VAL_IF_FAIL(hwc_window_data->client_type == TDM_HWC_WIN_COMPOSITION_CURSOR, TDM_ERROR_INVALID_PARAMETER); hwc_window_data->cursor_img.width = width; hwc_window_data->cursor_img.height = height; diff --git a/src/tdm_vc4_types.h b/src/tdm_vc4_types.h index b029aca..c5d50b7 100644 --- a/src/tdm_vc4_types.h +++ b/src/tdm_vc4_types.h @@ -254,6 +254,7 @@ struct _tdm_vc4_hwc_data { tdm_vc4_output_data *output_data; struct list_head hwc_window_list; + tbm_surface_queue_h cursor_tqueue; tbm_surface_h cursor_tsurface; tdm_hwc_commit_handler commit_func; |