support hw cursor transform 34/252234/1
authorChangyeon Lee <cyeon.lee@samsung.com>
Fri, 15 Jan 2021 07:01:32 +0000 (16:01 +0900)
committerChangyeon Lee <cyeon.lee@samsung.com>
Fri, 22 Jan 2021 07:12:01 +0000 (16:12 +0900)
Change-Id: I43ac311e0a924533a1c84199367f8042e8eaa6f9

src/tdm_nexell.h
src/tdm_nexell_hwc.c
src/tdm_nexell_hwc_window.c
src/tdm_nexell_types.h

index 461ea1d..c71f0e7 100644 (file)
@@ -106,5 +106,6 @@ tdm_nexell_layer_data * nexell_output_data_get_layer_data(tdm_nexell_output_data
 
 void                 tdm_nexell_data_destroy_buffer_list(tdm_nexell_data *nexell_data);
 tbm_surface_queue_h  tdm_nexell_hwc_window_create_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error);
+tbm_surface_queue_h  tdm_nexell_hwc_window_create_cursor_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error);
 void                 tdm_nexell_hwc_window_destroy_tbm_buffer_queue(tbm_surface_queue_h tqueue);
 #endif /* _TDM_NEXELL_H_ */
index 58d983f..89a4b16 100644 (file)
@@ -3,6 +3,7 @@
 #endif
 
 #include <tdm_helper.h>
+#include <pixman.h>
 #include "tdm_nexell.h"
 
 #define MIN_WIDTH      32
@@ -30,7 +31,96 @@ _comp_to_str(tdm_hwc_window_composition composition_type)
 }
 
 static int
-_nexell_hwc_cursor_buffer_unset(tdm_nexell_hwc_window_data *hwc_window_data)
+_nexell_hwc_cursor_buffer_image_render(tdm_nexell_hwc_data *hwc_data, tdm_nexell_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
+_nexell_hwc_cursor_window_surface_clear(tdm_nexell_hwc_window_data *hwc_window_data)
 {
        hwc_window_data->surface = NULL;
        hwc_window_data->cursor_img_surface = 0;
@@ -44,14 +134,35 @@ _nexell_hwc_cursor_buffer_unset(tdm_nexell_hwc_window_data *hwc_window_data)
 }
 
 static void
-_nexell_hwc_cursor_adjust_pos(tdm_nexell_hwc_window_data *hwc_window_data)
+_nexell_hwc_cursor_buffer_unset(tdm_nexell_hwc_data *hwc_data)
+{
+       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) {
+               tdm_nexell_hwc_window_destroy_tbm_buffer_queue(hwc_data->cursor_tqueue);
+               hwc_data->cursor_tqueue = NULL;
+       }
+}
+
+static void
+_nexell_hwc_cursor_adjust_pos(tdm_nexell_hwc_data *hwc_data, tdm_nexell_hwc_window_data *hwc_window_data)
 {
-       int x, y;
+       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;
 
@@ -63,65 +174,65 @@ static int
 _nexell_hwc_cursor_buffer_set(tdm_nexell_hwc_data *hwc_data, tdm_nexell_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;
+       tbm_surface_queue_error_e tsq_error = TBM_SURFACE_QUEUE_ERROR_NONE;
        int img_w, img_h;
-       tbm_format format;
-       unsigned int flags = TBM_BO_SCANOUT;
-       void *src_ptr = NULL, *dst_ptr = NULL;
-       int src_stride;
-       int i;
-
-       _nexell_hwc_cursor_adjust_pos(hwc_window_data);
-
-       if (!hwc_window_data->cursor_img_refresh && hwc_window_data->surface)
-               return 1;
+       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 = tdm_nexell_hwc_window_create_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);
+               _nexell_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;
+       _nexell_hwc_cursor_adjust_pos(hwc_data, hwc_window_data);
 
        return 1;
 }
@@ -241,6 +352,47 @@ tdm_nexell_hwc_window_create_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_er
        return tqueue;
 }
 
+tbm_surface_queue_h
+tdm_nexell_hwc_window_create_cursor_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error)
+{
+       tdm_nexell_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;
+}
+
 void
 tdm_nexell_hwc_window_destroy_tbm_buffer_queue(tbm_surface_queue_h tqueue)
 {
@@ -276,6 +428,7 @@ _nexell_hwc_prepare_commit(tdm_nexell_hwc_data *hwc_data)
        tdm_nexell_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) {
@@ -288,9 +441,8 @@ _nexell_hwc_prepare_commit(tdm_nexell_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)
-                               _nexell_hwc_cursor_buffer_unset(hwc_window_data);
+                               _nexell_hwc_cursor_window_surface_clear(hwc_window_data);
 
                        continue;
                }
@@ -299,8 +451,10 @@ _nexell_hwc_prepare_commit(tdm_nexell_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) {
                        _nexell_hwc_cursor_buffer_set(hwc_data, hwc_window_data);
+                       cursor_enabled = 1;
+               }
 
                layer_data = nexell_output_data_get_layer_data(hwc_data->output_data, hwc_window_data->lzpos);
                _nexell_hwc_layer_attach_window(layer_data, hwc_window_data);
@@ -319,6 +473,9 @@ _nexell_hwc_prepare_commit(tdm_nexell_hwc_data *hwc_data)
                _nexell_hwc_layer_attach_window(layer_data, NULL);
        }
 
+       if (!cursor_enabled)
+               _nexell_hwc_cursor_buffer_unset(hwc_data);
+
        /* for debug */
        for (lzpos = NUM_LAYERS -1 ; lzpos >= 0; lzpos--) {
                if (use_layers_zpos[lzpos])
index d1736ad..ffcd3c2 100644 (file)
@@ -25,7 +25,7 @@ nexell_hwc_window_acquire_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *er
        if (error)
                *error = TDM_ERROR_NONE;
 
-       if ((hwc_window_data->lzpos_queue < 0) || (hwc_window_data->lzpos_queue > NUM_LAYERS)) {
+       if ((hwc_window_data->lzpos_queue < 0) || (hwc_window_data->lzpos_queue >= NUM_LAYERS)) {
                TDM_ERR("invliad hwc_window:%p lzpos_queue:%d", hwc_window_data, hwc_window_data->lzpos);
                if (error)
                        *error = TDM_ERROR_OPERATION_FAILED;
@@ -38,7 +38,7 @@ nexell_hwc_window_acquire_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *er
                hwc_data->ui_buffer_queue[hwc_window_data->lzpos_queue].ref_cnt++;
        } else {
                tqueue = tdm_nexell_hwc_window_create_tbm_buffer_queue(hwc_window, error);
-               if (*error != TDM_ERROR_NONE) {
+               if (!tqueue) {
                        TDM_ERR("fail to create buffer queue");
                        return NULL;
                }
@@ -229,7 +229,6 @@ nexell_hwc_window_set_cursor_image(tdm_hwc_window *hwc_window, int width, int he
        tdm_nexell_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;
index 822cb05..be16585 100644 (file)
@@ -253,6 +253,7 @@ struct _tdm_nexell_hwc_data {
        tdm_nexell_output_data *output_data;
        struct list_head hwc_window_list;
 
+       tbm_surface_queue_h cursor_tqueue;
        tbm_surface_h cursor_tsurface;
 
        /* UI buffer_queue list for the reserved scanout memory */