tdm_dummy: Support hwc 68/316168/1
authorJunkyeong Kim <jk0430.kim@samsung.com>
Wed, 14 Aug 2024 09:12:29 +0000 (18:12 +0900)
committerJunkyeong Kim <jk0430.kim@samsung.com>
Wed, 14 Aug 2024 09:12:33 +0000 (18:12 +0900)
Change-Id: Iaa8a4f2bf1c48d2b9ca16a0a52497602ae350e8f
Signed-off-by: Junkyeong Kim <jk0430.kim@samsung.com>
backends/dummy/tdm_dummy.c
backends/dummy/tdm_dummy.h
backends/dummy/tdm_dummy_display.c

index a39f5794ae4a65ae2f8a609f248057fb6eb18010..55789ef2f4d12548d37abf23958a4d9d9219bec9 100644 (file)
@@ -31,6 +31,8 @@ tdm_dummy_init(tdm_display *dpy, tdm_error *error)
        tdm_func_display dummy_func_display;
        tdm_func_output dummy_func_output;
        tdm_func_layer dummy_func_layer;
+       tdm_func_hwc dummy_func_hwc;
+       tdm_func_hwc_window dummy_func_hwc_window;
        tdm_error ret;
 
        if (!dpy) {
@@ -73,6 +75,7 @@ tdm_dummy_init(tdm_display *dpy, tdm_error *error)
        dummy_func_output.output_set_commit_handler = dummy_output_set_commit_handler;
        dummy_func_output.output_set_mode = dummy_output_set_mode;
        dummy_func_output.output_get_mode = dummy_output_get_mode;
+       dummy_func_output.output_get_hwc = dummy_output_get_hwc;
 
        memset(&dummy_func_layer, 0, sizeof(dummy_func_layer));
        dummy_func_layer.layer_get_capability = dummy_layer_get_capability;
@@ -81,6 +84,39 @@ tdm_dummy_init(tdm_display *dpy, tdm_error *error)
        dummy_func_layer.layer_set_buffer = dummy_layer_set_buffer;
        dummy_func_layer.layer_unset_buffer = dummy_layer_unset_buffer;
 
+       memset(&dummy_func_hwc, 0, sizeof(dummy_func_hwc));
+       dummy_func_hwc.hwc_create_window = dummy_hwc_create_window;
+       dummy_func_hwc.hwc_get_video_supported_formats = dummy_hwc_get_video_supported_formats;
+       dummy_func_hwc.hwc_get_video_available_properties = NULL;
+       dummy_func_hwc.hwc_get_capabilities = dummy_hwc_get_capabilities;
+       dummy_func_hwc.hwc_get_available_properties = dummy_hwc_get_available_properties;
+       dummy_func_hwc.hwc_get_client_target_buffer_queue = dummy_hwc_get_client_target_buffer_queue;
+       dummy_func_hwc.hwc_set_client_target_buffer = dummy_hwc_set_client_target_buffer;
+       dummy_func_hwc.hwc_set_client_target_buffer_info = NULL;
+       dummy_func_hwc.hwc_set_client_target_acquire_fence = NULL;
+       dummy_func_hwc.hwc_validate = dummy_hwc_validate;
+       dummy_func_hwc.hwc_get_changed_composition_types = dummy_hwc_get_changed_composition_types;
+       dummy_func_hwc.hwc_accept_validation = dummy_hwc_accept_validation;
+       dummy_func_hwc.hwc_commit = dummy_hwc_commit;
+       dummy_func_hwc.hwc_set_commit_handler = dummy_hwc_set_commit_handler;
+       dummy_func_hwc.hwc_get_commit_fence = NULL;
+       dummy_func_hwc.hwc_get_release_fences = NULL;
+
+       memset(&dummy_func_hwc_window, 0, sizeof(dummy_func_hwc_window));
+       dummy_func_hwc_window.hwc_window_destroy = dummy_hwc_window_destroy;
+       dummy_func_hwc_window.hwc_window_acquire_buffer_queue = NULL; // no need
+       dummy_func_hwc_window.hwc_window_release_buffer_queue = NULL; // no need
+       dummy_func_hwc_window.hwc_window_set_composition_type = dummy_hwc_window_set_composition_type;
+       dummy_func_hwc_window.hwc_window_set_buffer_damage = dummy_hwc_window_set_buffer_damage;
+       dummy_func_hwc_window.hwc_window_set_info = dummy_hwc_window_set_info;
+       dummy_func_hwc_window.hwc_window_set_buffer = dummy_hwc_window_set_buffer;
+       dummy_func_hwc_window.hwc_window_set_property = dummy_hwc_window_set_property;
+       dummy_func_hwc_window.hwc_window_get_property = dummy_hwc_window_get_property;
+       dummy_func_hwc_window.hwc_window_get_constraints = dummy_hwc_window_get_constraints;
+       dummy_func_hwc_window.hwc_window_set_name = dummy_hwc_window_set_name;
+       dummy_func_hwc_window.hwc_window_set_cursor_image = NULL;;
+       dummy_func_hwc_window.hwc_window_set_acquire_fence = NULL;
+
        ret = tdm_backend_register_func_display(dpy, &dummy_func_display);
        if (ret != TDM_ERROR_NONE)
                goto failed;
@@ -93,6 +129,14 @@ tdm_dummy_init(tdm_display *dpy, tdm_error *error)
        if (ret != TDM_ERROR_NONE)
                goto failed;
 
+       ret = tdm_backend_register_func_hwc(dpy, &dummy_func_hwc);
+       if (ret != TDM_ERROR_NONE)
+               goto failed;
+
+       ret = tdm_backend_register_func_hwc_window(dpy, &dummy_func_hwc_window);
+       if (ret != TDM_ERROR_NONE)
+               goto failed;
+
        dummy_data->dpy = dpy;
 
        if (pipe(dummy_data->pipe) < 0) {
index a55f4c4210a452d77897a7563ae3c501fcde135c..f26304444152febc8b957e17e1aec54e76ed6577 100644 (file)
@@ -38,6 +38,29 @@ tdm_error    dummy_output_commit(tdm_output *output, int sync, void *user_data);
 tdm_error    dummy_output_set_commit_handler(tdm_output *output, tdm_output_commit_handler func);
 tdm_error    dummy_output_set_mode(tdm_output *output, const tdm_output_mode *mode);
 tdm_error    dummy_output_get_mode(tdm_output *output, const tdm_output_mode **mode);
+tdm_hwc*     dummy_output_get_hwc(tdm_output *output, tdm_error *error);
+
+tdm_hwc_window *dummy_hwc_create_window(tdm_hwc *hwc, tdm_error *error);
+tdm_error    dummy_hwc_get_video_supported_formats(tdm_output *output, const tbm_format **formats, int *count);
+tdm_error    dummy_hwc_get_capabilities(tdm_hwc *hwc, tdm_hwc_capability *capabilities);
+tdm_error    dummy_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count);
+tbm_surface_queue_h dummy_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error);
+tdm_error    dummy_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage);
+tdm_error    dummy_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types);
+tdm_error    dummy_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements, tdm_hwc_window **hwc_wnds, tdm_hwc_window_composition *composition_types);
+tdm_error    dummy_hwc_accept_validation(tdm_hwc *hwc);
+tdm_error    dummy_hwc_commit(tdm_hwc *hwc, int sync, void *user_data);
+tdm_error    dummy_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func);
+
+void         dummy_hwc_window_destroy(tdm_hwc_window *hwc_window);
+tdm_error    dummy_hwc_window_set_composition_type(tdm_hwc_window *hwc_window, tdm_hwc_window_composition composition_type);
+tdm_error    dummy_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_region damage);
+tdm_error    dummy_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info);
+tdm_error    dummy_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface);
+tdm_error    dummy_hwc_window_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value);
+tdm_error    dummy_hwc_window_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value);
+tdm_error    dummy_hwc_window_get_constraints(tdm_hwc_window *hwc_window, int *constraints);
+tdm_error    dummy_hwc_window_set_name(tdm_hwc_window *hwc_window, const char *name);
 
 tdm_error    dummy_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps);
 tdm_error    dummy_layer_set_info(tdm_layer *layer, tdm_info_layer *info);
@@ -45,6 +68,8 @@ tdm_error    dummy_layer_get_info(tdm_layer *layer, tdm_info_layer *info);
 tdm_error    dummy_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer);
 tdm_error    dummy_layer_unset_buffer(tdm_layer *layer);
 
+
+
 #define RETURN_VAL_IF_FAIL(cond, val) {\
     if (!(cond)) {\
         TDM_ERR("'%s' failed", #cond);\
index 0db047d320ebac0125a7803d56e779429e0ee6b2..6ab69beb892d34de87ecfd1c4ea3ebcb3712e9e0 100644 (file)
@@ -6,6 +6,8 @@
 
 typedef struct _tdm_dummy_output_data tdm_dummy_output_data;
 typedef struct _tdm_dummy_layer_data tdm_dummy_layer_data;
+typedef struct _tdm_dummy_hwc_data tdm_dummy_hwc_data;
+typedef struct _tdm_dummy_hwc_window_data tdm_dummy_hwc_window_data;
 typedef struct _tdm_dummy_event_data tdm_dummy_event_data;
 
 typedef enum {
@@ -13,6 +15,22 @@ typedef enum {
        TDM_DUMMY_EVENT_TYPE_COMMIT,
 } tdm_dummy_event_type;
 
+#define MIN_WIDTH      32
+
+#define NUM_LAYERS     1
+#define NUM_BUFFERS    3
+
+#define NUM_UI_LAYERS  1
+
+#define ZPOS_MAX       1
+#define ZPOS_0         0
+#define ZPOS_NONE      -999
+
+tbm_format hwc_window_video_formats[] = {
+       TBM_FORMAT_ARGB8888,
+       TBM_FORMAT_XRGB8888,
+};
+
 struct _tdm_dummy_event_data {
        struct list_head link;
 
@@ -45,6 +63,9 @@ struct _tdm_dummy_output_data {
        tdm_event_loop_source *timer;
        unsigned int timer_waiting;
        struct list_head timer_event_list;
+
+       int hwc_enable;
+       tdm_dummy_hwc_data *hwc_data;
 };
 
 struct _tdm_dummy_layer_data {
@@ -64,6 +85,50 @@ struct _tdm_dummy_layer_data {
        int display_buffer_changed;
 };
 
+struct _tdm_dummy_hwc_data {
+       tdm_dummy_hwc_window_data *target_hwc_window;
+
+       int need_validate;
+       int need_target_window;
+       int need_set_crtc;
+
+       int target_window_zpos;
+
+       tdm_dummy_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;
+};
+
+struct _tdm_dummy_hwc_window_data {
+       struct list_head link;
+
+       tdm_dummy_hwc_data *hwc_data;
+
+       tdm_hwc_window_info info;
+       tbm_surface_h surface;
+       tdm_hwc_window_composition client_type;
+       tdm_hwc_window_composition validated_type;
+       int lzpos;
+
+       char name[TDM_NAME_LEN];
+       struct {
+               int width;
+               int height;
+               int stride;
+               void *ptr;
+       } cursor_img;
+       int cursor_img_surface;
+       int cursor_img_refresh;
+
+       int acquire_fence;
+};
+
+tdm_error dummy_hwc_initailize_target_window(tdm_dummy_hwc_data *hwc_data);
+
 static void
 _tdm_dummy_display_cb_event(tdm_dummy_output_data *output_data, tdm_dummy_event_data *event_data,
                                                        unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec)
@@ -148,6 +213,226 @@ _tdm_dummy_display_destroy_layer_list(tdm_dummy_data *dummy_data)
        }
 }
 
+tdm_hwc_window *
+_dummy_hwc_create_window(tdm_hwc *hwc, tdm_hwc_window_info *info, tdm_error *error)
+{
+       tdm_dummy_hwc_data *hwc_data = hwc;
+       tdm_dummy_hwc_window_data *hwc_window_data = NULL;
+
+       if (error)
+               *error = TDM_ERROR_NONE;
+
+       if (!hwc_data) {
+               TDM_ERR("invalid params");
+               if (error)
+                       *error = TDM_ERROR_INVALID_PARAMETER;
+               return NULL;
+       }
+
+       hwc_window_data = calloc(1, sizeof(tdm_dummy_hwc_window_data));
+       if (!hwc_window_data) {
+               TDM_ERR("alloc failed");
+               if (error)
+                       *error = TDM_ERROR_OUT_OF_MEMORY;
+               return NULL;
+       }
+
+       hwc_window_data->hwc_data = hwc_data;
+       hwc_window_data->acquire_fence = -1;
+
+       if (info)
+               memcpy(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info));
+
+       LIST_INITHEAD(&hwc_window_data->link);
+
+       return hwc_window_data;
+}
+
+static tbm_surface_queue_h
+_dummy_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error)
+{
+       tdm_dummy_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 void
+_dummy_hwc_apply_policy(tdm_dummy_hwc_data *hwc_data , tdm_hwc_window **composited_wnds, uint32_t num_wnds)
+{
+       tdm_dummy_hwc_window_data *hwc_window_data = NULL;
+       tdm_dummy_hwc_window_data **composited_list = NULL;
+       int i = 0;
+
+       composited_list = (tdm_dummy_hwc_window_data **)composited_wnds;
+
+       /* initialize the validated_types */
+       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_NONE;
+       }
+
+       /* use the target_window to commit when there is no window. */
+       if (num_wnds == 0) {
+               hwc_data->need_target_window = 1;
+               hwc_data->target_hwc_window->lzpos = ZPOS_0;
+               return;
+       }
+
+       /* use only target_window */
+       for (i = 0; i < num_wnds; i++) {
+               composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_CLIENT;
+               composited_list[i]->lzpos = ZPOS_NONE;
+       }
+
+       hwc_data->need_target_window = 1;
+       hwc_data->target_hwc_window->lzpos = ZPOS_0;
+}
+
+static int
+_dummy_hwc_get_changed_number(tdm_dummy_hwc_data *hwc_data)
+{
+       int num = 0;
+       tdm_dummy_hwc_window_data *hwc_window_data = NULL;
+
+       LIST_FOR_EACH_ENTRY(hwc_window_data, &hwc_data->hwc_window_list, link) {
+               if (hwc_window_data->client_type == TDM_HWC_WIN_COMPOSITION_NONE)
+                       continue;
+
+               if (hwc_window_data->client_type != hwc_window_data->validated_type)
+                       num++;
+       }
+
+       return num;
+}
+
+const char *
+_comp_to_str(tdm_hwc_window_composition composition_type)
+{
+       if (composition_type == TDM_HWC_WIN_COMPOSITION_CLIENT)
+               return "CLIENT";
+       else if (composition_type == TDM_HWC_WIN_COMPOSITION_DEVICE)
+               return "DEVICE";
+       else if (composition_type == TDM_HWC_WIN_COMPOSITION_CURSOR)
+               return "CURSOR";
+       else if (composition_type == TDM_HWC_WIN_COMPOSITION_VIDEO)
+               return "VIDEO";
+       else if (composition_type == TDM_HWC_WIN_COMPOSITION_NONE)
+               return "SKIP";
+
+       return "unknown";
+}
+
+static void
+_print_validate_result(tdm_dummy_hwc_data *hwc_data, tdm_hwc_window **composited_wnds, uint32_t num_wnds)
+{
+       tdm_dummy_hwc_window_data *hwc_window_data = NULL;
+       int i;
+
+       for (i = 0; i < num_wnds; i++) {
+               hwc_window_data = composited_wnds[i];
+               switch (hwc_window_data->validated_type) {
+               case TDM_HWC_WIN_COMPOSITION_CLIENT:
+                       TDM_DBG(" window(%p) %s -> %s : lzpos(%d) -- {%s} on TARGET WINDOW", hwc_window_data,
+                                       _comp_to_str(hwc_window_data->client_type),
+                                       _comp_to_str(hwc_window_data->validated_type),
+                                       hwc_data->target_hwc_window->lzpos,
+                                       hwc_window_data->name ? hwc_window_data->name : "NONE");
+                       break;
+               case TDM_HWC_WIN_COMPOSITION_DEVICE:
+               case TDM_HWC_WIN_COMPOSITION_VIDEO:
+               case TDM_HWC_WIN_COMPOSITION_CURSOR:
+               case TDM_HWC_WIN_COMPOSITION_NONE:
+                       TDM_DBG(" window(%p) %s -> %s : lzpos(%d) -- {%s}", hwc_window_data,
+                                       _comp_to_str(hwc_window_data->client_type),
+                                       _comp_to_str(hwc_window_data->validated_type),
+                                       hwc_window_data->lzpos,
+                                       hwc_window_data->name ? hwc_window_data->name : "NONE");
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+
+static tdm_error
+_dummy_hwc_layer_attach_window(tdm_dummy_layer_data *layer_data, tdm_dummy_hwc_window_data *hwc_window_data)
+{
+       tdm_error ret = TDM_ERROR_NONE;
+
+       RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_OPERATION_FAILED);
+
+       if (hwc_window_data == NULL || hwc_window_data->surface == NULL) {
+               if (layer_data->display_buffer)
+                       ret = dummy_layer_unset_buffer(layer_data);
+               RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+       } else {
+               ret = dummy_layer_set_info((tdm_layer *)layer_data, (tdm_info_layer *)&(hwc_window_data->info));
+               RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+               RETURN_VAL_IF_FAIL(hwc_window_data->surface != NULL, TDM_ERROR_INVALID_PARAMETER);
+               ret = dummy_layer_set_buffer(layer_data, hwc_window_data->surface);
+               RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+       }
+
+       return ret;
+}
+
+static tdm_error
+_dummy_hwc_prepare_commit(tdm_dummy_hwc_data *hwc_data)
+{
+       tdm_dummy_layer_data *layer_data = NULL;
+       int use_layers_zpos[NUM_LAYERS] = {0,};
+       int lzpos = 0;
+
+       /* set target hwc window to the layer */
+       if (hwc_data->need_target_window) {
+               layer_data = hwc_data->output_data->primary_layer;
+               _dummy_hwc_layer_attach_window(layer_data, hwc_data->target_hwc_window);
+               use_layers_zpos[hwc_data->target_hwc_window->lzpos] = 1;
+       }
+
+       /* unset the unused layers */
+       for (lzpos = 0; lzpos < NUM_LAYERS; lzpos++) {
+               if (use_layers_zpos[lzpos])
+                       continue;
+
+               layer_data = hwc_data->output_data->primary_layer;
+               if (!layer_data)
+                       continue;
+
+               _dummy_hwc_layer_attach_window(layer_data, NULL);
+       }
+
+       /* for debug */
+       for (lzpos = NUM_LAYERS -1 ; lzpos >= 0; lzpos--) {
+               if (use_layers_zpos[lzpos])
+                       TDM_INFO(" lzpos(%d) : %s", lzpos, use_layers_zpos[lzpos] ? "SET" : "UNSET");
+       }
+
+       return TDM_ERROR_NONE;
+}
+
 tdm_error
 tdm_dummy_display_create_layer_list(tdm_dummy_data *dummy_data)
 {
@@ -551,6 +836,55 @@ dummy_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
        return TDM_ERROR_NONE;
 }
 
+tdm_hwc *
+dummy_output_get_hwc(tdm_output *output, tdm_error *error)
+{
+       tdm_dummy_hwc_data *hwc_data = NULL;
+       tdm_dummy_output_data *output_data = output;
+       tdm_error ret = TDM_ERROR_NONE;
+
+       if (!output_data) {
+               TDM_ERR("invalid params");
+               if (error)
+                       *error = TDM_ERROR_INVALID_PARAMETER;
+               return NULL;
+       }
+
+       if (output_data->hwc_data) {
+               TDM_INFO("hwc_data already exists");
+               if (error)
+                       *error = TDM_ERROR_NONE;
+               return output_data->hwc_data;
+       }
+
+       hwc_data = calloc(1, sizeof(tdm_dummy_hwc_data));
+       if (!hwc_data) {
+               TDM_ERR("alloc failed");
+               if (error)
+                       *error = TDM_ERROR_OUT_OF_MEMORY;
+               return NULL;
+       }
+       hwc_data->output_data = output_data;
+
+       LIST_INITHEAD(&hwc_data->hwc_window_list);
+
+       output_data->hwc_data = hwc_data;
+
+       ret = dummy_hwc_initailize_target_window(output_data->hwc_data);
+       if (ret != TDM_ERROR_NONE) {
+               TDM_ERR("create target hwc window failed (%d)", ret);
+               free(hwc_data);
+               if (error)
+                       *error = ret;
+               return NULL;
+       }
+
+       if (error)
+               *error = TDM_ERROR_NONE;
+
+       return hwc_data;
+}
+
 tdm_error
 dummy_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps)
 {
@@ -634,3 +968,389 @@ dummy_layer_unset_buffer(tdm_layer *layer)
 
        return TDM_ERROR_NONE;
 }
+
+tdm_error
+dummy_hwc_initailize_target_window(tdm_dummy_hwc_data *hwc_data)
+{
+       tdm_hwc_window_info info = {0};
+       tdm_error ret = TDM_ERROR_NONE;
+       tdm_dummy_hwc_window_data *target_hwc_window;
+
+       RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
+
+       info.dst_pos.x = 0;
+       info.dst_pos.y = 0;
+       info.dst_pos.w = 2;
+       info.dst_pos.h = 1;
+
+       info.src_config.pos.x = 0;
+       info.src_config.pos.y = 0;
+       info.src_config.pos.w = 2;
+       info.src_config.pos.h = 1;
+
+       info.src_config.size.h = 2;
+       info.src_config.size.v = 1;
+       info.src_config.format = TBM_FORMAT_ARGB8888;
+
+       target_hwc_window = _dummy_hwc_create_window(hwc_data, &info, &ret);
+       if (ret != TDM_ERROR_NONE) {
+               TDM_ERR("create target hwc window failed (%d)", ret);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       if (hwc_data->target_hwc_window)
+               dummy_hwc_window_destroy(hwc_data->target_hwc_window);
+
+       hwc_data->target_hwc_window = target_hwc_window;
+       hwc_data->need_set_crtc = 1;
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_hwc_window *
+dummy_hwc_create_window(tdm_hwc *hwc, tdm_error *error)
+{
+       tdm_dummy_hwc_data *hwc_data = hwc;
+       tdm_dummy_hwc_window_data *hwc_window_data = NULL;
+
+       RETURN_VAL_IF_FAIL(hwc_data, NULL);
+
+       hwc_window_data = _dummy_hwc_create_window(hwc_data, NULL, error);
+       RETURN_VAL_IF_FAIL(hwc_window_data, NULL);
+
+       LIST_ADDTAIL(&hwc_window_data->link, &hwc_data->hwc_window_list);
+
+       TDM_DBG("hwc_window(%p) create", hwc_window_data);
+       if (error)
+               *error = TDM_ERROR_NONE;
+
+       return hwc_window_data;
+}
+
+tdm_error
+dummy_hwc_get_video_supported_formats(tdm_hwc *hwc, const tbm_format **formats, int *count)
+{
+       RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(formats != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       // TODO: fix these formats.
+       *formats = hwc_window_video_formats;
+       *count = sizeof(hwc_window_video_formats) / sizeof(tbm_format);
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+dummy_hwc_get_capabilities(tdm_hwc *hwc, tdm_hwc_capability *capabilities)
+{
+       tdm_dummy_hwc_data *hwc_data = hwc;
+       tdm_dummy_data *dummy_data;
+
+       RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(hwc_data->output_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       dummy_data = hwc_data->output_data->dummy_data;
+       RETURN_VAL_IF_FAIL(dummy_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       *capabilities = 0;
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+dummy_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count)
+{
+       tdm_dummy_hwc_data *hwc_data = hwc;
+
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(props != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(count != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       *props = NULL;
+       *count = 0;
+
+       return TDM_ERROR_NONE;
+}
+
+tbm_surface_queue_h
+dummy_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error)
+{
+       tdm_dummy_hwc_data *hwc_data = hwc;
+       tbm_surface_queue_h tqueue = NULL;
+
+       if (error)
+               *error = TDM_ERROR_INVALID_PARAMETER;
+
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL);
+
+       if (hwc_data->target_hwc_window == NULL) {
+               if (error)
+                       *error = TDM_ERROR_OPERATION_FAILED;
+               return NULL;
+       }
+
+       tqueue = _dummy_hwc_window_get_tbm_buffer_queue(hwc_data->target_hwc_window, error);
+       RETURN_VAL_IF_FAIL(tqueue, NULL);
+
+       if (error)
+               *error = TDM_ERROR_NONE;
+
+       return tqueue;
+}
+
+tdm_error
+dummy_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage)
+{
+       tdm_dummy_hwc_data *hwc_data = hwc;
+       tdm_error err;
+
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window  != NULL, TDM_ERROR_OPERATION_FAILED);
+
+       err = dummy_hwc_window_set_buffer(hwc_data->target_hwc_window, buffer);
+       RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
+
+       err = dummy_hwc_window_set_buffer_damage(hwc_data->target_hwc_window, damage);
+       RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+dummy_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types)
+{
+       tdm_dummy_hwc_data *hwc_data = hwc;
+
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       TDM_DBG(" ==============Validate Virtual=================================");
+
+       _dummy_hwc_apply_policy(hwc_data, composited_wnds, num_wnds);
+
+       *num_types = _dummy_hwc_get_changed_number(hwc_data);
+
+       _print_validate_result(hwc_data, composited_wnds, num_wnds);
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+dummy_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements,
+                               tdm_hwc_window **hwc_wnds, tdm_hwc_window_composition *composition_types)
+{
+       tdm_dummy_hwc_data *hwc_data = hwc;
+       tdm_dummy_hwc_window_data *hwc_window_data = NULL;
+       int num = 0;
+
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(num_elements != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       if ((hwc_wnds == NULL) || (composition_types == NULL)) {
+               *num_elements = _dummy_hwc_get_changed_number(hwc_data);
+               return TDM_ERROR_NONE;
+       }
+
+       LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
+               if (hwc_window_data->client_type == TDM_HWC_WIN_COMPOSITION_NONE)
+                       continue;
+
+               if (num >= *num_elements)
+                       break;
+
+               if (hwc_window_data->client_type != hwc_window_data->validated_type) {
+                       composition_types[num] = hwc_window_data->validated_type;
+                       hwc_wnds[num] = hwc_window_data;
+                       num++;
+               }
+       }
+
+       /* set real num of changed composition types */
+       *num_elements = num;
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+dummy_hwc_accept_validation(tdm_hwc *hwc)
+{
+       tdm_dummy_hwc_data *hwc_data = hwc;
+       tdm_error ret = TDM_ERROR_NONE;
+
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(hwc_data->output_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       TDM_DBG(" ==============Accept Changes Done Virtual=================================");
+
+       ret = _dummy_hwc_prepare_commit(hwc_data);
+       RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+dummy_hwc_commit(tdm_hwc *hwc, int sync, void *user_data)
+{
+       tdm_dummy_hwc_data *hwc_data = hwc;
+       tdm_dummy_output_data *output_data = NULL;
+       tdm_error ret;
+
+       RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
+
+       output_data = hwc_data->output_data;
+       RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
+
+       TDM_DBG(" ==============COMMIT=================================");
+
+       ret = dummy_output_commit(output_data, sync, user_data);
+       RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+dummy_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func)
+{
+       tdm_dummy_hwc_data *hwc_data = hwc;
+
+       RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(func, TDM_ERROR_INVALID_PARAMETER);
+
+       hwc_data->commit_func = func;
+
+       return TDM_ERROR_NONE;
+}
+
+void
+dummy_hwc_window_destroy(tdm_hwc_window *hwc_window)
+{
+       tdm_dummy_hwc_window_data *hwc_window_data = hwc_window;
+
+       if (hwc_window_data == NULL)
+               return;
+
+       LIST_DEL(&hwc_window_data->link);
+
+       free(hwc_window_data);
+}
+
+tdm_error
+dummy_hwc_window_set_composition_type(tdm_hwc_window *hwc_window,
+                                                                       tdm_hwc_window_composition comp_type)
+{
+       tdm_dummy_hwc_window_data *hwc_window_data = hwc_window;
+       tdm_dummy_hwc_data *hwc_data = hwc_window_data->hwc_data;
+
+       RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       /* change the client_type when it is different from one which has before */
+       if (hwc_window_data->client_type == comp_type)
+               return TDM_ERROR_NONE;
+
+       hwc_window_data->client_type = comp_type;
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+dummy_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_region damage)
+{
+       tdm_dummy_hwc_window_data *hwc_window_data = hwc_window;
+
+       RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       //TODO::
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+dummy_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info)
+{
+       tdm_dummy_hwc_window_data *hwc_window_data = hwc_window;
+       tdm_dummy_hwc_data *hwc_data;
+
+       RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+       hwc_data = hwc_window_data->hwc_data;
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(info != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       if (!memcmp(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info)))
+               return TDM_ERROR_NONE;
+
+       hwc_window_data->info = *info;
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+dummy_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface)
+{
+       tdm_dummy_hwc_window_data *hwc_window_data = hwc_window;
+       tdm_error err = TDM_ERROR_OPERATION_FAILED;
+
+       RETURN_VAL_IF_FAIL(hwc_window_data != NULL, err);
+
+       if (hwc_window_data->surface == surface)
+               return TDM_ERROR_NONE;
+
+       hwc_window_data->surface = surface;
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+dummy_hwc_window_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value)
+{
+       tdm_dummy_hwc_window_data *hwc_window_data = hwc_window;
+
+       RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       //TODO:
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+dummy_hwc_window_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value)
+{
+       tdm_dummy_hwc_window_data *hwc_window_data = hwc_window;
+
+       RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       //TODO:
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+dummy_hwc_window_get_constraints(tdm_hwc_window *hwc_window, int *constraints)
+{
+       tdm_dummy_hwc_window_data *hwc_window_data = hwc_window;
+
+       RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(constraints != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       // no constraints
+       *constraints = 0;
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+dummy_hwc_window_set_name(tdm_hwc_window *hwc_window, const char *name)
+{
+       tdm_dummy_hwc_window_data *hwc_window_data = hwc_window;
+
+       RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       if (!name)
+               return TDM_ERROR_NONE;
+
+       snprintf(hwc_window_data->name, TDM_NAME_LEN, "%s", name);
+
+       return TDM_ERROR_NONE;
+}