hwc: modify the functions with the new hwc api 43/175843/1
authorSooChan Lim <sc1.lim@samsung.com>
Thu, 12 Apr 2018 23:10:34 +0000 (08:10 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Fri, 13 Apr 2018 01:33:19 +0000 (10:33 +0900)
Change-Id: I2710e2f1529622f03d1894b71c93aab2a2abf009

src/tdm_vc4.c
src/tdm_vc4.h
src/tdm_vc4_display.c

index 9402d5f..9d58251 100644 (file)
@@ -231,6 +231,7 @@ tdm_vc4_init(tdm_display *dpy, tdm_error *error)
        tdm_func_display vc4_func_display;
        tdm_func_output vc4_func_output;
        tdm_func_layer vc4_func_layer;
+       tdm_func_hwc vc4_func_hwc;
        tdm_func_hwc_window vc4_func_hwc_window;
        tdm_error ret;
        char *str;
@@ -289,20 +290,32 @@ tdm_vc4_init(tdm_display *dpy, tdm_error *error)
        vc4_func_output.output_set_status_handler = vc4_output_set_status_handler;
 #endif
        if (vc4_data->hwc_mode) {
-               vc4_func_output.output_hwc_create_window = vc4_output_hwc_window_create;
-               vc4_func_output.output_hwc_destroy_window = vc4_output_hwc_window_destroy;
-               vc4_func_output.output_hwc_validate = vc4_output_hwc_validate;
-               vc4_func_output.output_hwc_get_changed_composition_types = vc4_output_hwc_get_changed_composition_types;
-               vc4_func_output.output_hwc_accept_changes = vc4_output_hwc_accept_changes;
-               vc4_func_output.output_hwc_get_target_buffer_queue = vc4_output_hwc_get_target_buffer_queue;
-               vc4_func_output.output_hwc_set_client_target_buffer = vc4_output_hwc_set_client_target_buffer;
+               vc4_func_output.output_get_hwc = vc4_output_get_hwc;
+
+               memset(&vc4_func_hwc, 0, sizeof(vc4_func_hwc));
+               vc4_func_hwc.hwc_create_window = vc4_hwc_create_window;
+
+               vc4_func_hwc.hwc_create_window = vc4_hwc_create_window;
+               vc4_func_hwc.hwc_get_supported_formats = vc4_hwc_get_supported_formats;
+               vc4_func_hwc.hwc_get_available_properties = vc4_hwc_get_available_properties;
+               vc4_func_hwc.hwc_get_client_target_buffer_queue = vc4_hwc_get_client_target_buffer_queue;
+               vc4_func_hwc.hwc_set_client_target_buffer = vc4_hwc_set_client_target_buffer;
+               vc4_func_hwc.hwc_validate = vc4_hwc_validate;
+               vc4_func_hwc.hwc_get_changed_composition_types = vc4_hwc_get_changed_composition_types;
+               vc4_func_hwc.hwc_accept_changes = vc4_hwc_accept_changes;
+               vc4_func_hwc.hwc_commit = vc4_hwc_commit;
+               vc4_func_hwc.hwc_set_commit_handler = vc4_hwc_set_commit_handler;
 
                memset(&vc4_func_hwc_window, 0, sizeof(vc4_func_hwc_window));
-               vc4_func_hwc_window.hwc_window_get_tbm_buffer_queue = vc4_hwc_window_get_tbm_buffer_queue;
-               vc4_func_hwc_window.hwc_window_set_buffer = vc4_hwc_window_set_buffer;
+               vc4_func_hwc_window.hwc_window_destroy = vc4_hwc_window_destroy;
+               vc4_func_hwc_window.hwc_window_get_buffer_queue = NULL;
                vc4_func_hwc_window.hwc_window_set_composition_type = vc4_hwc_window_set_composition_type;
-               vc4_func_hwc_window.hwc_window_set_info = vc4_hwc_window_set_info;
                vc4_func_hwc_window.hwc_window_set_buffer_damage = vc4_hwc_window_set_buffer_damage;
+               vc4_func_hwc_window.hwc_window_set_info = vc4_hwc_window_set_info;
+               vc4_func_hwc_window.hwc_window_get_info = vc4_hwc_window_get_info;
+               vc4_func_hwc_window.hwc_window_set_buffer = vc4_hwc_window_set_buffer;
+               vc4_func_hwc_window.hwc_window_set_property = vc4_hwc_window_set_property;
+               vc4_func_hwc_window.hwc_window_get_property = vc4_hwc_window_get_property;
        }
 
        memset(&vc4_func_layer, 0, sizeof(vc4_func_layer));
index 13250a2..11c537f 100644 (file)
@@ -48,16 +48,28 @@ tdm_error   vc4_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value);
 tdm_error      vc4_output_set_mode(tdm_output *output, const tdm_output_mode *mode);
 tdm_error      vc4_output_get_mode(tdm_output *output, const tdm_output_mode **mode);
 tdm_error      vc4_output_set_status_handler(tdm_output *output, tdm_output_status_handler func, void *user_data);
-tdm_hwc_window * vc4_output_hwc_window_create(tdm_output *output, tdm_error *error);
-tdm_error      vc4_output_hwc_window_destroy(tdm_output *output, tdm_hwc_window *hwc_window);
-tdm_error      vc4_output_hwc_validate(tdm_output *output, tdm_hwc_window **composited_wnds,
-                                                                       uint32_t num_wnds, uint32_t *num_types);
-tdm_error      vc4_output_hwc_get_changed_composition_types(tdm_output *output, uint32_t *num_elements,
-                                                                                tdm_hwc_window **hwc_window,
-                                                                                tdm_hwc_window_composition *composition_types);
-tdm_error      vc4_output_hwc_accept_changes(tdm_output *output);
-tbm_surface_queue_h vc4_output_hwc_get_target_buffer_queue(tdm_output *output, tdm_error *error);
-tdm_error      vc4_output_hwc_set_client_target_buffer(tdm_output *output, tbm_surface_h buffer, tdm_hwc_region damage);
+tdm_hwc    *vc4_output_get_hwc(tdm_output *output, tdm_error *error);
+
+tdm_hwc_window      *vc4_hwc_create_window(tdm_hwc *hwc, tdm_error *error);
+tdm_error            vc4_hwc_get_supported_formats(tdm_hwc *outphwcut, const tbm_format **formats, int *count);
+tdm_error            vc4_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count);
+tbm_surface_queue_h  vc4_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error);
+tdm_error            vc4_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage);
+tdm_error            vc4_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types);
+tdm_error            vc4_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements, tdm_hwc_window **hwc_window, tdm_hwc_window_composition *composition_types);
+tdm_error            vc4_hwc_accept_changes(tdm_hwc *hwc);
+tdm_error            vc4_hwc_commit(tdm_hwc *hwc, int sync, void *user_data);
+tdm_error            vc4_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func);
+
+void                 vc4_hwc_window_destroy(tdm_hwc_window *hwc_window);
+tdm_error            vc4_hwc_window_set_composition_type(tdm_hwc_window *hwc_window, tdm_hwc_window_composition composition_type);
+tdm_error            vc4_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_region damage);
+tdm_error            vc4_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info);
+tdm_error            vc4_hwc_window_get_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info);
+tdm_error               vc4_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface);
+tdm_error            vc4_hwc_window_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value);
+tdm_error            vc4_hwc_window_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value);
+
 tdm_error      vc4_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps);
 tdm_error      vc4_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value);
 tdm_error      vc4_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value);
@@ -66,12 +78,6 @@ tdm_error    vc4_layer_get_info(tdm_layer *layer, tdm_info_layer *info);
 tdm_error      vc4_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer);
 tdm_error      vc4_layer_unset_buffer(tdm_layer *layer);
 tdm_error      vc4_layer_get_buffer_flags(tdm_layer *layer, unsigned int *flags);
-tbm_surface_queue_h vc4_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error);
-tdm_error      vc4_hwc_window_set_composition_type(tdm_hwc_window *hwc_window,
-                                                                                               tdm_hwc_window_composition composition_type);
-tdm_error      vc4_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_hwc_region damage);
-tdm_error      vc4_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info);
-tdm_error      vc4_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface);
 
 
 /* drm module internal macros, structures, functions */
index d52a1bd..3cd3cec 100644 (file)
@@ -20,6 +20,8 @@ static int tdm_vc4_buffer_key;
 
 typedef struct _tdm_vc4_output_data tdm_vc4_output_data;
 typedef struct _tdm_vc4_layer_data tdm_vc4_layer_data;
+typedef struct _tdm_vc4_hwc_data tdm_vc4_hwc_data;
+
 typedef struct _tdm_vc4_hwc_window_data tdm_vc4_hwc_window_data;
 typedef struct _tdm_vc4_event_data tdm_vc4_event_data;
 
@@ -75,16 +77,9 @@ struct _tdm_vc4_output_data {
        int crtc_enabled;
        unsigned int crtc_fb_id;
 
-       tdm_vc4_hwc_window_data *target_hwc_window;
-
-       int need_validate;
-       int need_target_buffer;
-       int hw_layer_count;
-       int need_set_crtc;
-       int top_layer_idx;
+       /* hwc */
        int hwc_enable;
-
-       struct list_head hwc_window_list;
+       tdm_vc4_hwc_data *hwc_data;
 };
 
 struct _tdm_vc4_layer_data {
@@ -105,12 +100,27 @@ struct _tdm_vc4_layer_data {
        int display_buffer_changed;
 };
 
+struct _tdm_vc4_hwc_data {
+       tdm_vc4_hwc_window_data *target_hwc_window;
+
+       int need_validate;
+       int need_target_buffer;
+       int hw_layer_count;
+       int need_set_crtc;
+       int top_layer_idx;
+
+       int target_window_zpos;
+
+       tdm_vc4_output_data *output_data;
+       struct list_head hwc_window_list;
+
+       tdm_hwc_commit_handler commit_func;
+};
 struct _tdm_vc4_hwc_window_data {
        struct list_head link;
 
        /* data which are fixed at initializing */
-       tdm_vc4_data *vc4_data;
-       tdm_vc4_output_data *output_data;
+       tdm_vc4_hwc_data *hwc_data;
 
        /* not fixed data below */
        tdm_hwc_window_info info;
@@ -126,12 +136,113 @@ struct _tdm_vc4_hwc_window_data {
        tdm_hwc_window_composition validated_type;
 };
 
+static const char *
+_comp_to_str(tdm_hwc_window_composition composition_type)
+{
+       if (composition_type == TDM_COMPOSITION_CLIENT)
+               return "CLIENT";
+       else if (composition_type == TDM_COMPOSITION_DEVICE_CANDIDATE)
+               return "DEVICE_CANDIDATE";
+       else if (composition_type == TDM_COMPOSITION_DEVICE)
+               return "DEVICE";
+       else if (composition_type == TDM_COMPOSITION_CURSOR)
+               return "CURSOR";
+
+       return "unknown";
+}
+
 tdm_hwc_window *
-_vc4_output_hwc_window_create(tdm_output *output, tdm_hwc_window_info *info,
-                                                               tdm_error *error);
+_vc4_hwc_create_window(tdm_hwc *hwc, tdm_hwc_window_info *info, tdm_error *error)
+{
+       tdm_vc4_hwc_window_data *hwc_window_data = NULL;
+       tdm_vc4_hwc_data *hwc_data = hwc;
+
+       if (error)
+               *error = TDM_ERROR_NONE;
+
+       hwc_window_data = calloc(1, sizeof(tdm_vc4_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;
+
+       if (info)
+               memcpy(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info));
+
+       return hwc_window_data;
+}
+
 static tdm_error
-_tdm_vc4_output_update_status(tdm_vc4_output_data *output_data,
-                                                         tdm_output_conn_status status);
+_vc4_hwc_initailize_target_window(tdm_vc4_hwc_data *hwc_data, int width, int height)
+{
+       tdm_hwc_window_info info = {0};
+       tdm_error ret = TDM_ERROR_NONE;
+       tdm_vc4_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.h = height;
+       info.dst_pos.w = width;
+
+       info.src_config.pos.x = 0;
+       info.src_config.pos.y = 0;
+       info.src_config.pos.h = height;
+       info.src_config.pos.w = width;
+
+       info.src_config.size.h = width;
+       info.src_config.size.v = height;
+       info.src_config.format = TBM_FORMAT_ARGB8888;
+
+       target_hwc_window = _vc4_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)
+               vc4_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;
+}
+
+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;
+       tbm_format format;
+
+       if (error)
+               *error = TDM_ERROR_INVALID_PARAMETER;
+
+       RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL);
+       hwc_window_data = hwc_window;
+
+       int wight = hwc_window_data->info.src_config.size.h;
+       int hight = hwc_window_data->info.src_config.size.v;
+
+       format = hwc_window_data->info.src_config.format;
+
+       tqueue = tbm_surface_queue_create(3, wight, hight, 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
 _tdm_vc4_display_buffer_destroy(void *user_data)
@@ -283,6 +394,24 @@ _tdm_vc4_display_set_fb(tdm_vc4_data *vc4_data, tbm_surface_h buffer, unsigned i
 }
 
 static tdm_error
+_tdm_vc4_output_update_status(tdm_vc4_output_data *output_data,
+                                                         tdm_output_conn_status status)
+{
+       RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
+
+       if (output_data->status == status)
+               return TDM_ERROR_NONE;
+
+       output_data->status = status;
+
+       if (output_data->status_func)
+               output_data->status_func(output_data, status,
+                                                                output_data->status_user_data);
+
+       return TDM_ERROR_NONE;
+}
+
+static tdm_error
 _tdm_vc4_display_set_crtc(tdm_vc4_data *vc4_data, tdm_vc4_output_data *output_data, int set)
 {
        int ret;
@@ -435,24 +564,6 @@ _tdm_vc4_display_wait_vblank(int fd, int pipe, uint *target_msc, void *data)
 }
 
 static tdm_error
-_tdm_vc4_output_update_status(tdm_vc4_output_data *output_data,
-                                                         tdm_output_conn_status status)
-{
-       RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
-
-       if (output_data->status == status)
-               return TDM_ERROR_NONE;
-
-       output_data->status = status;
-
-       if (output_data->status_func)
-               output_data->status_func(output_data, status,
-                                                                output_data->status_user_data);
-
-       return TDM_ERROR_NONE;
-}
-
-static tdm_error
 _tdm_vc4_display_commit_layer(tdm_vc4_layer_data *layer_data)
 {
        tdm_vc4_data *vc4_data = layer_data->vc4_data;
@@ -841,6 +952,129 @@ failed:
 }
 #endif
 
+static int
+_get_primary_layer_index(tdm_vc4_output_data *output_data)
+{
+       int i = 0;
+       tdm_vc4_layer_data *layer = NULL;
+
+       LIST_FOR_EACH_ENTRY(layer, &output_data->layer_list, link) {
+               if (layer->capabilities & TDM_LAYER_CAPABILITY_PRIMARY)
+                       return i;
+               i++;
+       }
+
+       return 0;
+}
+
+#if 0
+tdm_vc4_layer_data *
+_vc4_output_get_layer(tdm_vc4_output_data *output_data, int index)
+{
+       tdm_vc4_layer_data *l = NULL;
+       LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link)
+               if (l->zpos == index)
+                       return l;
+
+       return NULL;
+}
+
+static tdm_error
+_vc4_layer_attach_window(tdm_vc4_layer_data *layer_data,
+                                                       tdm_vc4_hwc_window_data *hwc_window_data)
+{
+       tdm_error ret;
+
+       if (hwc_window_data == NULL || !hwc_window_data->surface) {
+               ret = vc4_layer_unset_buffer(layer_data);
+               RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+       } else {
+               ret = vc4_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 = vc4_layer_set_buffer(layer_data, hwc_window_data->surface);
+               RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+       }
+
+       return ret;
+}
+
+static tdm_error
+_tdm_vc4_display_prepare_commit(tdm_vc4_output_data *output_data) {
+
+       tdm_vc4_layer_data * layer = NULL;
+       tdm_vc4_hwc_window_data *hw = NULL;
+       int num_hw_layer = 0;
+       int i;
+       int fb_idx = 0;
+
+       RETURN_VAL_IF_FAIL(output_data->need_validate == 0, TDM_ERROR_OPERATION_FAILED);
+
+       i = output_data->top_layer_idx;
+       num_hw_layer = LIST_LENGTH(&output_data->layer_list);
+       fb_idx = _get_primary_layer_index(output_data);
+
+       //set target hwc window
+       if (output_data->need_target_buffer) {
+               layer = _vc4_output_get_layer(output_data, fb_idx);
+               _vc4_layer_attach_window(layer, output_data->target_hwc_window);
+       }
+
+       //set hwc windows
+       LIST_FOR_EACH_ENTRY_REV(hw, &output_data->hwc_window_list, link) {
+               if (output_data->need_target_buffer && i == fb_idx) {
+                       i--;
+               }
+               if (hw->client_type != TDM_COMPOSITION_DEVICE)
+                       continue;
+               RETURN_VAL_IF_FAIL(i >= 0, TDM_ERROR_OPERATION_FAILED);
+               layer = _vc4_output_get_layer(output_data, i--);
+               _vc4_layer_attach_window(layer, hw);
+       }
+
+       //disable unused layer
+       while (i >= 0) {
+               layer = _vc4_output_get_layer(output_data, i--);
+               _vc4_layer_attach_window(layer, NULL);
+       }
+
+       i = output_data->top_layer_idx + 1;
+       while (i < num_hw_layer) {
+               layer = _vc4_output_get_layer(output_data, i++);
+               _vc4_layer_attach_window(layer, NULL);
+       }
+
+       return TDM_ERROR_NONE;
+}
+#endif
+
+static int
+_get_primary_layer_zpos(tdm_vc4_output_data *output_data)
+{
+       tdm_vc4_layer_data *layer_data = NULL;
+
+       LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
+               if (layer_data->capabilities & TDM_LAYER_CAPABILITY_PRIMARY)
+                       return layer_data->zpos;
+       }
+
+       return -1;
+}
+
+int
+_vc4_hwc_get_changed_number(tdm_vc4_hwc_data *hwc_data)
+{
+       int num = 0;
+       tdm_vc4_hwc_window_data *hw = NULL;
+
+       LIST_FOR_EACH_ENTRY(hw, &hwc_data->hwc_window_list, link) {
+               if (hw->client_type != hw->validated_type)
+                       num++;
+       }
+
+       return num;
+}
+
 tdm_error
 tdm_vc4_display_create_layer_list(tdm_vc4_data *vc4_data)
 {
@@ -871,14 +1105,15 @@ void
 tdm_vc4_display_destroy_output_list(tdm_vc4_data *vc4_data)
 {
        tdm_vc4_output_data *o = NULL, *oo = NULL;
+       tdm_vc4_hwc_data *hwc_data = NULL;
 
        if (LIST_IS_EMPTY(&vc4_data->output_list))
                return;
 
        LIST_FOR_EACH_ENTRY_SAFE(o, oo, &vc4_data->output_list, link) {
-
-               if (o->target_hwc_window)
-                       vc4_output_hwc_window_destroy(o, o->target_hwc_window);
+               hwc_data = o->hwc_data;
+               if (hwc_data && hwc_data->target_hwc_window)
+                       vc4_hwc_window_destroy(hwc_data->target_hwc_window);
 
                if (o->crtc_enabled) {
                        _tdm_vc4_display_set_crtc(vc4_data, o, 0);
@@ -1090,11 +1325,8 @@ tdm_vc4_display_create_output_list(tdm_vc4_data *vc4_data)
                                                                         &output_data->output_modes[j]);
        }
 
-       if (vc4_data->hwc_mode) {
+       if (vc4_data->hwc_mode)
                output_data->hwc_enable = 1;
-               output_data->target_hwc_window = NULL;
-               LIST_INITHEAD(&output_data->hwc_window_list);
-       }
 
        LIST_ADDTAIL(&output_data->link, &vc4_data->output_list);
 
@@ -1486,102 +1718,8 @@ vc4_output_set_vblank_handler(tdm_output *output,
        return TDM_ERROR_NONE;
 }
 
-tdm_vc4_layer_data *
-_vc4_output_get_layer(tdm_vc4_output_data *output_data, int index)
-{
-       tdm_vc4_layer_data *l = NULL;
-       LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link)
-               if (l->zpos == index)
-                       return l;
-
-       return NULL;
-}
-
-static tdm_error
-_vc4_layer_attach_window(tdm_vc4_layer_data *layer_data,
-                                                       tdm_vc4_hwc_window_data *hwc_window_data)
-{
-       tdm_error ret;
-
-       if (hwc_window_data == NULL || !hwc_window_data->surface) {
-               ret = vc4_layer_unset_buffer(layer_data);
-               RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
-       } else {
-               ret = vc4_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 = vc4_layer_set_buffer(layer_data, hwc_window_data->surface);
-               RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
-       }
-
-       return ret;
-}
-
-static int
-_get_primary_layer_index(tdm_vc4_output_data *vc4_output)
-{
-       int i = 0;
-       tdm_vc4_layer_data *layer = NULL;
-
-       LIST_FOR_EACH_ENTRY(layer, &vc4_output->layer_list, link) {
-               if (layer->capabilities & TDM_LAYER_CAPABILITY_PRIMARY)
-                       return i;
-               i++;
-       }
-
-       return 0;
-}
-
-static tdm_error
-_tdm_vc4_display_prepare_commit(tdm_vc4_output_data *output_data) {
-
-       tdm_vc4_layer_data * layer = NULL;
-       tdm_vc4_hwc_window_data *hw = NULL;
-       int num_hw_layer = 0;
-       int i;
-       int fb_idx = 0;
-
-       RETURN_VAL_IF_FAIL(output_data->need_validate == 0, TDM_ERROR_OPERATION_FAILED);
-
-       i = output_data->top_layer_idx;
-       num_hw_layer = LIST_LENGTH(&output_data->layer_list);
-       fb_idx = _get_primary_layer_index(output_data);
-
-       //set target hwc window
-       if (output_data->need_target_buffer) {
-               layer = _vc4_output_get_layer(output_data, fb_idx);
-               _vc4_layer_attach_window(layer, output_data->target_hwc_window);
-       }
-
-       //set hwc windows
-       LIST_FOR_EACH_ENTRY_REV(hw, &output_data->hwc_window_list, link) {
-               if (output_data->need_target_buffer && i == fb_idx) {
-                       i--;
-               }
-               if (hw->client_type != TDM_COMPOSITION_DEVICE)
-                       continue;
-               RETURN_VAL_IF_FAIL(i >= 0, TDM_ERROR_OPERATION_FAILED);
-               layer = _vc4_output_get_layer(output_data, i--);
-               _vc4_layer_attach_window(layer, hw);
-       }
-
-       //disable unused layer
-       while (i >= 0) {
-               layer = _vc4_output_get_layer(output_data, i--);
-               _vc4_layer_attach_window(layer, NULL);
-       }
-
-       i = output_data->top_layer_idx + 1;
-       while (i < num_hw_layer) {
-               layer = _vc4_output_get_layer(output_data, i++);
-               _vc4_layer_attach_window(layer, NULL);
-       }
-
-       return TDM_ERROR_NONE;
-}
-
-tdm_error
-vc4_output_commit(tdm_output *output, int sync, void *user_data)
+tdm_error
+vc4_output_commit(tdm_output *output, int sync, void *user_data)
 {
        tdm_vc4_output_data *output_data = output;
        tdm_vc4_data *vc4_data;
@@ -1593,10 +1731,12 @@ vc4_output_commit(tdm_output *output, int sync, void *user_data)
 
        vc4_data = output_data->vc4_data;
 
+#if 0
        if (output_data->hwc_enable) {
                ret = _tdm_vc4_display_prepare_commit(output_data);
                RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
        }
+#endif
 
        LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
                ret = _tdm_vc4_display_commit_layer(layer_data);
@@ -1711,41 +1851,18 @@ tdm_error
 vc4_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
 {
        tdm_vc4_output_data *output_data = output;
+       tdm_error ret = TDM_ERROR_NONE;
 
        RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
        RETURN_VAL_IF_FAIL(mode, TDM_ERROR_INVALID_PARAMETER);
 
+       /* create or replace the target_window when the output mode is set */
        if (output_data->hwc_enable) {
-
-               tdm_hwc_window_info info = {0};
-               tdm_error ret = TDM_ERROR_NONE;
-               tdm_vc4_hwc_window_data *target_hwc_window;
-
-               info.dst_pos.x = 0;
-               info.dst_pos.y = 0;
-               info.dst_pos.h = mode->vdisplay;;
-               info.dst_pos.w = mode->hdisplay;
-
-               info.src_config.pos.x = 0;
-               info.src_config.pos.y = 0;
-               info.src_config.pos.h = mode->vdisplay;
-               info.src_config.pos.w = mode->hdisplay;
-
-               info.src_config.size.h = mode->hdisplay;
-               info.src_config.size.v = mode->vdisplay;
-               info.src_config.format = TBM_FORMAT_ARGB8888;
-
-               target_hwc_window = _vc4_output_hwc_window_create(output_data, &info, &ret);
+               ret = _vc4_hwc_initailize_target_window(output_data->hwc_data, mode->hdisplay, mode->hdisplay);
                if (ret != TDM_ERROR_NONE) {
                        TDM_ERR("create target hwc window failed (%d)", ret);
-                       return TDM_ERROR_OPERATION_FAILED;
+                       return ret;
                }
-
-               if (output_data->target_hwc_window)
-                       vc4_output_hwc_window_destroy(output, output_data->target_hwc_window);
-
-               output_data->target_hwc_window = target_hwc_window;
-               output_data->need_set_crtc = 1;
        }
 
        output_data->current_mode = mode;
@@ -1782,19 +1899,6 @@ vc4_output_set_status_handler(tdm_output *output,
        return TDM_ERROR_NONE;
 }
 
-static int
-_get_primary_layer_zpos(tdm_vc4_output_data *output_data)
-{
-       tdm_vc4_layer_data *layer_data = NULL;
-
-       LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
-               if (layer_data->capabilities & TDM_LAYER_CAPABILITY_PRIMARY)
-                       return layer_data->zpos;
-       }
-
-       return -1;
-}
-
 tdm_error
 vc4_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps)
 {
@@ -2021,147 +2125,80 @@ vc4_layer_unset_buffer(tdm_layer *layer)
        return TDM_ERROR_NONE;
 }
 
-int
-_vc4_output_get_changed_number(tdm_vc4_output_data *vc4_output)
-{
-       int num = 0;
-       tdm_vc4_hwc_window_data *hw = NULL;
-
-       LIST_FOR_EACH_ENTRY(hw, &vc4_output->hwc_window_list, link) {
-               if (hw->client_type != hw->validated_type)
-                       num++;
-       }
-
-       return num;
-}
-
 tdm_hwc_window *
-_vc4_output_hwc_window_create(tdm_output *output, tdm_hwc_window_info *info, tdm_error *error)
+vc4_hwc_create_window(tdm_hwc *hwc, tdm_error *error)
 {
-       tdm_vc4_hwc_window_data *vc4_hwc_window = NULL;
-       tdm_vc4_output_data *vc4_output = output;
-
-       if (error)
-               *error = TDM_ERROR_NONE;
+       tdm_vc4_hwc_window_data *hwc_window_data = NULL;
+       tdm_vc4_hwc_data *hwc_data = hwc;
 
-       if (!vc4_output) {
+       if (!hwc_data) {
                TDM_ERR("invalid params");
                if (error)
                        *error = TDM_ERROR_INVALID_PARAMETER;
                return NULL;
        }
 
-       vc4_hwc_window = calloc(1, sizeof(tdm_vc4_hwc_window_data));
-       if (!vc4_hwc_window) {
-               TDM_ERR("alloc failed");
-               if (error)
-                       *error = TDM_ERROR_OUT_OF_MEMORY;
+       hwc_window_data = _vc4_hwc_create_window(hwc_data, NULL, error);
+       if (hwc_window_data == NULL)
                return NULL;
-       }
-
-       if ((vc4_hwc_window->vc4_data = vc4_output->vc4_data) == NULL) {
-               TDM_ERR("invalid params");
-               if (error)
-                       *error = TDM_ERROR_INVALID_PARAMETER;
-               goto fail;
-       }
 
-       vc4_hwc_window->output_data = output;
-
-       if (info)
-               memcpy(&vc4_hwc_window->info, info, sizeof(tdm_hwc_window_info));
-
-       return vc4_hwc_window;
-fail:
-       if (vc4_hwc_window)
-               free(vc4_hwc_window);
-
-       return NULL;
-}
-
-tdm_hwc_window *
-vc4_output_hwc_window_create(tdm_output *output, tdm_error *error)
-{
-       tdm_vc4_hwc_window_data *vc4_hwc_window = NULL;
-       tdm_vc4_output_data *vc4_output = output;
+       LIST_ADDTAIL(&hwc_window_data->link, &hwc_data->hwc_window_list);
 
-       vc4_hwc_window = _vc4_output_hwc_window_create(vc4_output, NULL, error);
-       if (vc4_hwc_window == NULL)
-               return NULL;
-
-       LIST_ADDTAIL(&vc4_hwc_window->link, &vc4_output->hwc_window_list);
-
-       TDM_DBG("hwc_window(%p) create", vc4_hwc_window);
+       TDM_DBG("hwc_window(%p) create", hwc_window_data);
        if (error)
                *error = TDM_ERROR_NONE;
 
-       return vc4_hwc_window;
+       return hwc_window_data;
 }
 
-tdm_error
-vc4_output_hwc_window_destroy(tdm_output *output, tdm_hwc_window *hwc_window)
+void
+vc4_hwc_window_destroy(tdm_hwc_window *hwc_window)
 {
-       tdm_vc4_hwc_window_data *vc4_hwc_window = hwc_window;
+       tdm_vc4_hwc_window_data *hwc_window_data = hwc_window;
 
-       LIST_DEL(&vc4_hwc_window->link);
+       if (!hwc_window_data)
+               return;
 
-       free(vc4_hwc_window);
+       LIST_DEL(&hwc_window_data->link);
 
-       return TDM_ERROR_NONE;
-}
-
-static const char *
-_comp_to_str(tdm_hwc_window_composition composition_type)
-{
-       if (composition_type == TDM_COMPOSITION_CLIENT)
-               return "CLIENT";
-       else if (composition_type == TDM_COMPOSITION_DEVICE_CANDIDATE)
-               return "DEVICE_CANDIDATE";
-       else if (composition_type == TDM_COMPOSITION_DEVICE)
-               return "DEVICE";
-       else if (composition_type == TDM_COMPOSITION_CURSOR)
-               return "CURSOR";
-
-       return "unknown";
+       free(hwc_window_data);
 }
 
 tdm_error
-vc4_output_hwc_validate(tdm_output *output, tdm_hwc_window **composited_wnds,
+vc4_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds,
                                        uint32_t num_wnds, uint32_t *num_types)
 {
-       tdm_vc4_output_data *vc4_output = output;
-       tdm_vc4_data *vc4_data = NULL;
-       RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
+       tdm_vc4_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_vc4_hwc_window_data *hw = NULL;
        int hw_layer_count = 0;
        int need_target_buffer = 0;
-       int max_hw_layer = LIST_LENGTH(&vc4_output->layer_list);
-       int fb_index = _get_primary_layer_index(vc4_output);
+       int max_hw_layer = LIST_LENGTH(&hwc_data->output_data->layer_list);
+       int fb_index = _get_primary_layer_index(hwc_data->output_data);
        int i = 0;
        int top_layer_idx = fb_index;
 
-       vc4_data = vc4_output->vc4_data;
-       RETURN_VAL_IF_FAIL(vc4_data != NULL, TDM_ERROR_INVALID_PARAMETER);
-
-       if (vc4_output->need_set_crtc) {
+       if (hwc_data->need_set_crtc) {
                need_target_buffer = 1;
 
-               LIST_FOR_EACH_ENTRY(hw, &vc4_output->hwc_window_list, link) {
+               LIST_FOR_EACH_ENTRY(hw, &hwc_data->hwc_window_list, link) {
                        hw->validated_type = TDM_COMPOSITION_CLIENT;
                }
        } else {
                int layer_idx;
-               int num_hwc_windows = LIST_LENGTH(&vc4_output->hwc_window_list);
+               int num_hwc_windows = LIST_LENGTH(&hwc_data->hwc_window_list);
 
-               LIST_FOR_EACH_ENTRY(hw, &vc4_output->hwc_window_list, link) {
+               LIST_FOR_EACH_ENTRY(hw, &hwc_data->hwc_window_list, link) {
                        hw->validated_type = TDM_COMPOSITION_CLIENT;
                }
 
                /* mark the top window */
                if (num_hwc_windows > 1) {
                        layer_idx = max_hw_layer;
-                       LIST_FOR_EACH_ENTRY_REV(hw, &vc4_output->hwc_window_list, link) {
+                       LIST_FOR_EACH_ENTRY_REV(hw, &hwc_data->hwc_window_list, link) {
                                layer_idx--;
                                if (hw->client_type == TDM_COMPOSITION_DEVICE && layer_idx != fb_index) {
                                        //check format
@@ -2185,7 +2222,7 @@ vc4_output_hwc_validate(tdm_output *output, tdm_hwc_window **composited_wnds,
 
                /* mark the bottom windows */
                layer_idx = -1;
-               LIST_FOR_EACH_ENTRY(hw, &vc4_output->hwc_window_list, link) {
+               LIST_FOR_EACH_ENTRY(hw, &hwc_data->hwc_window_list, link) {
                        layer_idx++;
                        /* break if the remaining windows are already marked */
                        if (hw->validated_type == TDM_COMPOSITION_DEVICE)
@@ -2204,9 +2241,9 @@ vc4_output_hwc_validate(tdm_output *output, tdm_hwc_window **composited_wnds,
                }
        }
 
-       LIST_FOR_EACH_ENTRY(hw, &vc4_output->hwc_window_list, link) {
+       LIST_FOR_EACH_ENTRY(hw, &hwc_data->hwc_window_list, link) {
                if (need_target_buffer && fb_index == i++)
-                       TDM_DBG(" window(%p) target", vc4_output->target_hwc_window);
+                       TDM_DBG(" window(%p) target", hwc_data->target_hwc_window);
                else
                        TDM_DBG(" window(%p) type: %s -> %s", hw,
                                        _comp_to_str(hw->client_type), _comp_to_str(hw->validated_type));
@@ -2215,37 +2252,37 @@ vc4_output_hwc_validate(tdm_output *output, tdm_hwc_window **composited_wnds,
        if (need_target_buffer)
                hw_layer_count++;
 
-       vc4_output->need_target_buffer = need_target_buffer;
-       vc4_output->hw_layer_count = hw_layer_count;
-       vc4_output->top_layer_idx = top_layer_idx;
+       hwc_data->need_target_buffer = need_target_buffer;
+       hwc_data->hw_layer_count = hw_layer_count;
+       hwc_data->top_layer_idx = top_layer_idx;
 
-       *num_types = _vc4_output_get_changed_number(vc4_output);
+       *num_types = _vc4_hwc_get_changed_number(hwc_data);
 
        if (*num_types == 0)
-               vc4_output->need_validate = 0;
+               hwc_data->need_validate = 0;
 
        return TDM_ERROR_NONE;
 }
 
 tdm_error
-vc4_output_hwc_get_changed_composition_types(tdm_output *output,
+vc4_hwc_get_changed_composition_types(tdm_hwc *hwc,
                                                                                 uint32_t *num_elements,
                                                                                 tdm_hwc_window **hwc_window,
                                                                                 tdm_hwc_window_composition *composition_types)
 {
-       tdm_vc4_output_data *vc4_output = output;
+       tdm_vc4_hwc_data *hwc_data = hwc;
        int num = 0;
 
-       RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
        RETURN_VAL_IF_FAIL(num_elements != NULL, TDM_ERROR_INVALID_PARAMETER);
 
        if ((hwc_window == NULL) || (composition_types == NULL)) {
-               *num_elements = _vc4_output_get_changed_number(vc4_output);
+               *num_elements = _vc4_hwc_get_changed_number(hwc_data);
                return TDM_ERROR_NONE;
        }
 
        tdm_vc4_hwc_window_data *hw = NULL;
-       LIST_FOR_EACH_ENTRY_REV(hw, &vc4_output->hwc_window_list, link) {
+       LIST_FOR_EACH_ENTRY_REV(hw, &hwc_data->hwc_window_list, link) {
 
                if (num >= *num_elements)
                        break;
@@ -2264,39 +2301,39 @@ vc4_output_hwc_get_changed_composition_types(tdm_output *output,
 }
 
 tdm_error
-vc4_output_hwc_accept_changes(tdm_output *output)
+vc4_hwc_accept_changes(tdm_hwc *hwc)
 {
-       tdm_vc4_output_data *vc4_output = output;
+       tdm_vc4_hwc_data *hwc_data = hwc;
 
-       RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
 
        tdm_vc4_hwc_window_data *hw = NULL;
-       LIST_FOR_EACH_ENTRY_REV(hw, &vc4_output->hwc_window_list, link)
+       LIST_FOR_EACH_ENTRY_REV(hw, &hwc_data->hwc_window_list, link)
                hw->client_type = hw->validated_type;
 
-       vc4_output->need_validate = 0;
+       hwc_data->need_validate = 0;
 
        return TDM_ERROR_NONE;
 }
 
 tbm_surface_queue_h
-vc4_output_hwc_get_target_buffer_queue(tdm_output *output, tdm_error *error)
+vc4_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error)
 {
-       tdm_vc4_output_data *vc4_output = output;
+       tdm_vc4_hwc_data *hwc_data = hwc;
        tbm_surface_queue_h tqueue = NULL;
 
        if (error)
                *error = TDM_ERROR_INVALID_PARAMETER;
 
-       RETURN_VAL_IF_FAIL(vc4_output != NULL, NULL);
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, NULL);
 
-       if (vc4_output->target_hwc_window == NULL) {
+       if (hwc_data->target_hwc_window == NULL) {
                if (error)
                        *error = TDM_ERROR_OPERATION_FAILED;
                return NULL;
        }
 
-       tqueue = vc4_hwc_window_get_tbm_buffer_queue(vc4_output->target_hwc_window, error);
+       tqueue = _vc4_hwc_window_get_tbm_buffer_queue(hwc_data->target_hwc_window, error);
        RETURN_VAL_IF_FAIL(tqueue, NULL);
 
        if (error)
@@ -2306,129 +2343,250 @@ vc4_output_hwc_get_target_buffer_queue(tdm_output *output, tdm_error *error)
 }
 
 tdm_error
-vc4_output_hwc_set_client_target_buffer(tdm_output *output, tbm_surface_h buffer, tdm_hwc_region damage)
+vc4_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage)
 {
-       tdm_vc4_output_data *vc4_output = output;
+       tdm_vc4_hwc_data *hwc_data = hwc;
        tdm_error err;
 
-       RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
-       RETURN_VAL_IF_FAIL(vc4_output->target_hwc_window != NULL, TDM_ERROR_OPERATION_FAILED);
+       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 = vc4_hwc_window_set_buffer(vc4_output->target_hwc_window, buffer);
+       err = vc4_hwc_window_set_buffer(hwc_data->target_hwc_window, buffer);
        RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
 
-       err = vc4_hwc_window_set_buffer_damage(vc4_output->target_hwc_window, damage);
+       err = vc4_hwc_window_set_buffer_damage(hwc_data->target_hwc_window, damage);
        RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
 
        return TDM_ERROR_NONE;
 }
 
-
-tbm_surface_queue_h
-vc4_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error)
+tdm_error
+vc4_hwc_window_set_composition_type(tdm_hwc_window *hwc_window,
+                                                                       tdm_hwc_window_composition comp_type)
 {
-       tdm_vc4_hwc_window_data *vc4_hwc_window = NULL;
-       tdm_vc4_output_data *vc4_output = NULL;
-       tbm_surface_queue_h tqueue = NULL;
-       tbm_format format;
+       tdm_vc4_hwc_window_data *hwc_window_data = hwc_window;
+       tdm_vc4_hwc_data *hwc_data = hwc_window_data->hwc_data;
 
-       if (error)
-               *error = TDM_ERROR_INVALID_PARAMETER;
+       RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
 
-       RETURN_VAL_IF_FAIL(hwc_window != NULL, NULL);
-       vc4_hwc_window = hwc_window;
-       vc4_output = vc4_hwc_window->output_data;
-       RETURN_VAL_IF_FAIL(vc4_output != NULL, NULL);
+       if (hwc_window_data->client_type == comp_type)
+               return TDM_ERROR_NONE;
 
-       int wight = vc4_hwc_window->info.src_config.size.h;
-       int hight = vc4_hwc_window->info.src_config.size.v;
+       hwc_window_data->client_type = comp_type;
+       hwc_data->need_validate = 1;
 
-       format = vc4_hwc_window->info.src_config.format;
+       return TDM_ERROR_NONE;
 
-       tqueue = tbm_surface_queue_create(3, wight, hight, format, TBM_BO_SCANOUT);
-       if (error)
-               *error = TDM_ERROR_OPERATION_FAILED;
-       RETURN_VAL_IF_FAIL(tqueue != NULL, NULL);
+}
 
-       if (error)
-               *error = TDM_ERROR_NONE;
+tdm_error
+vc4_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_region damage)
+{
+       tdm_vc4_hwc_window_data *hwc_window_data = hwc_window;
+       tdm_vc4_hwc_data *hwc_data = hwc_window_data->hwc_data;
 
-       return tqueue;
+       RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       //TODO::
 
+       return TDM_ERROR_NONE;
 }
 
 tdm_error
-vc4_hwc_window_set_composition_type(tdm_hwc_window *hwc_window,
-                                                                       tdm_hwc_window_composition comp_type)
+vc4_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info)
 {
-       tdm_vc4_hwc_window_data *vc4_hwc_window = hwc_window;
-       tdm_vc4_output_data *vc4_output = vc4_hwc_window->output_data;
+       tdm_vc4_hwc_window_data *hwc_window_data = hwc_window;
+       tdm_vc4_hwc_data *hwc_data = hwc_window_data->hwc_data;
 
-       RETURN_VAL_IF_FAIL(vc4_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
-       RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
 
-       if (vc4_hwc_window->client_type == comp_type)
+       if (!memcmp(&hwc_window_data->info, info, sizeof(tdm_hwc_window_info)))
                return TDM_ERROR_NONE;
 
-       vc4_hwc_window->client_type = comp_type;
-       vc4_output->need_validate = 1;
+       hwc_window_data->info = *info;
+       hwc_data->need_validate = 1;
 
        return TDM_ERROR_NONE;
-
 }
 
 tdm_error
-vc4_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_hwc_region damage)
+vc4_hwc_window_get_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info)
 {
-       tdm_vc4_hwc_window_data *vc4_hwc_window = hwc_window;
-       tdm_vc4_output_data *vc4_output = vc4_hwc_window->output_data;
+       tdm_vc4_hwc_window_data *hwc_window_data = hwc_window;
 
-       RETURN_VAL_IF_FAIL(vc4_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
-       RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(info, TDM_ERROR_INVALID_PARAMETER);
 
-       //TODO::
+       *info = hwc_window_data->info;
 
        return TDM_ERROR_NONE;
 }
 
 tdm_error
-vc4_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info)
+vc4_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface)
 {
-       tdm_vc4_hwc_window_data *vc4_hwc_window = hwc_window;
-       tdm_vc4_output_data *vc4_output = vc4_hwc_window->output_data;
+       tdm_vc4_hwc_window_data *hwc_window_data = hwc_window;
+       tdm_error err = TDM_ERROR_OPERATION_FAILED;
 
-       RETURN_VAL_IF_FAIL(vc4_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
-       RETURN_VAL_IF_FAIL(vc4_output != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(hwc_window_data != NULL, err);
 
-       if (!memcmp(&vc4_hwc_window->info, info, sizeof(tdm_hwc_window_info)))
+       if (hwc_window_data->surface == surface)
                return TDM_ERROR_NONE;
 
-       vc4_hwc_window->info = *info;
-       vc4_output->need_validate = 1;
+       hwc_window_data->surface = surface;
 
        return TDM_ERROR_NONE;
 }
 
 tdm_error
-vc4_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface)
+vc4_hwc_get_supported_formats(tdm_hwc *hwc, const tbm_format **formats, int *count)
+{
+       tdm_vc4_hwc_data *hwc_data = hwc;
+
+       RETURN_VAL_IF_FAIL(hwc_data != 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:
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+vc4_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count)
+{
+       tdm_vc4_hwc_data *hwc_data = hwc;
+
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       // TODO:
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+vc4_hwc_commit(tdm_hwc *hwc, int sync, void *user_data)
 {
-       tdm_vc4_hwc_window_data *vc4_hwc_window = hwc_window;
-       tdm_vc4_output_data *vc4_output;
+// TODO:
+#if 0
+       tdm_vc4_output_data *output_data = output;
        tdm_vc4_data *vc4_data;
-       tdm_error err = TDM_ERROR_OPERATION_FAILED;
+       tdm_vc4_layer_data *layer_data = NULL;
+       tdm_error ret;
+       int do_waitvblank = 1;
 
-       RETURN_VAL_IF_FAIL(vc4_hwc_window != NULL, err);
+       RETURN_VAL_IF_FAIL(output_data, TDM_ERROR_INVALID_PARAMETER);
 
-       vc4_output = vc4_hwc_window->output_data;
-       vc4_data = vc4_hwc_window->vc4_data;
+       vc4_data = output_data->vc4_data;
 
-       RETURN_VAL_IF_FAIL(vc4_output != NULL, err);
-       RETURN_VAL_IF_FAIL(vc4_data != NULL, err);
+       if (output_data->hwc_enable) {
+               ret = _vc4_output_hwc_prepare_commit(output_data);
+               RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+       }
 
-       if (vc4_hwc_window->surface == surface)
-               return TDM_ERROR_NONE;
+       LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
+               if (layer_data == output_data->primary_layer) {
+                       if (!layer_data->display_buffer ||
+                               (output_data->current_mode->hdisplay == layer_data->info.src_config.pos.w &&
+                               output_data->current_mode->vdisplay == layer_data->info.src_config.pos.h)) {
+                               ret = _tdm_vc4_output_commit_primary_layer(layer_data, user_data,
+                                                                                                                                                 &do_waitvblank);
+                               output_data->need_set_crtc = 0;
+                       } else
+                               ret = _tdm_vc4_output_commit_layer(layer_data);
+
+                       if (ret != TDM_ERROR_NONE)
+                               return ret;
+               } else {
+                       ret = _tdm_vc4_output_commit_layer(layer_data);
+                       if (ret != TDM_ERROR_NONE)
+                               return ret;
+               }
+       }
+
+       if (do_waitvblank == 1) {
+               tdm_vc4_event_data *event_data = calloc(1, sizeof(tdm_vc4_event_data));
+               uint target_msc;
+
+               if (!event_data) {
+                       TDM_ERR("alloc failed");
+                       return TDM_ERROR_OUT_OF_MEMORY;
+               }
+
+               ret = _tdm_vc4_output_get_cur_msc(vc4_data->drm_fd, output_data->pipe,
+                                                                                        &target_msc);
+               if (ret != TDM_ERROR_NONE) {
+                       free(event_data);
+                       return ret;
+               }
+
+               target_msc++;
+
+               event_data->type = TDM_vc4_EVENT_TYPE_COMMIT;
+               event_data->output_data = output_data;
+               event_data->user_data = user_data;
 
-       vc4_hwc_window->surface = surface;
+               ret = _tdm_vc4_output_wait_vblank(vc4_data->drm_fd, output_data->pipe,
+                                                                                        &target_msc, event_data);
+               if (ret != TDM_ERROR_NONE) {
+                       free(event_data);
+                       return ret;
+               }
+       }
+#endif
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+vc4_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func)
+{
+       tdm_vc4_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;
+}
+
+tdm_error
+vc4_hwc_window_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value)
+{
+       tdm_vc4_hwc_window_data *hwc_window_data = hwc_window;
+
+       RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+#if 0
+       output_data = hwc_window_data->output_data;
+       RETURN_VAL_IF_FAIL(output_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       layer_data = _vc4_output_get_layer(output_data, hwc_window_data->assigned_layer_zpos);
+
+       return vc4_layer_set_property(layer_data, id, value);
+#endif
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+vc4_hwc_window_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value)
+{
+       tdm_vc4_hwc_window_data *hwc_window_data = hwc_window;
+
+       RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+#if 0
+       output_data = hwc_window_data->output_data;
+       RETURN_VAL_IF_FAIL(output_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       layer_data = _vc4_output_get_layer(output_data, hwc_window_data->assigned_layer_zpos);
+
+       return vc4_layer_get_property(layer_data, id, value);
+#endif
 
        return TDM_ERROR_NONE;
 }