#endif
#include <tdm_helper.h>
+#include <pixman.h>
#include "tdm_vc4.h"
#define MIN_WIDTH 32
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;
}
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;
_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;
}
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)
{
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) {
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;
}
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);
_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])