Implement TDM HWC 41/256441/1
authorJunkyeong Kim <jk0430.kim@samsung.com>
Fri, 2 Apr 2021 11:14:43 +0000 (20:14 +0900)
committerJunkyeong Kim <jk0430.kim@samsung.com>
Fri, 2 Apr 2021 11:14:47 +0000 (20:14 +0900)
Change-Id: I8220d819bb52442e2660a2dde1fe555642a0e03b
Signed-off-by: Junkyeong Kim <jk0430.kim@samsung.com>
src/libtdm-fbdev/Makefile.am
src/libtdm-fbdev/tdm_fbdev.c
src/libtdm-fbdev/tdm_fbdev.h
src/libtdm-fbdev/tdm_fbdev_display.c
src/libtdm-fbdev/tdm_fbdev_hwc.c [new file with mode: 0644]
src/libtdm-fbdev/tdm_fbdev_hwc.h [new file with mode: 0644]
src/libtdm-fbdev/tdm_fbdev_hwc_window.c [new file with mode: 0644]
src/libtdm-fbdev/tdm_fbdev_hwc_window.h [new file with mode: 0644]
src/libtdm-fbdev/tdm_fbdev_types.h [new file with mode: 0644]

index 5bae8479e853f967563676456bf7e092942ec8a2..c0f804fee4871857c44a74c7533412700bf2e086 100644 (file)
@@ -9,4 +9,6 @@ libtdm_fbdev_la_LIBADD = $(TDM_DRM_LIBS) -ldl
 
 libtdm_fbdev_la_SOURCES = \
        tdm_fbdev_display.c \
+       tdm_fbdev_hwc.c \
+       tdm_fbdev_hwc_window.c \
        tdm_fbdev.c
index 33ef4efe75f2edbef345d85e1110b0a9751e511c..c3b9b2d6fbf7fe60f74e56df0a2eba958674e09b 100644 (file)
@@ -7,6 +7,8 @@
 
 #define TDM_FBDEV_NAME "fbdev"
 
+#define TDM_HWC 1
+
 static tdm_fbdev_data *fbdev_data;
 
 static int
@@ -160,6 +162,8 @@ tdm_fbdev_init(tdm_display *dpy, tdm_error *error)
        tdm_func_display fbdev_func_display;
        tdm_func_output fbdev_func_output;
        tdm_func_layer fbdev_func_layer;
+       tdm_func_hwc fbdev_func_hwc;
+       tdm_func_hwc_window fbdev_func_hwc_window;
        tdm_error ret;
 
        if (!dpy) {
@@ -184,6 +188,11 @@ tdm_fbdev_init(tdm_display *dpy, tdm_error *error)
                return NULL;
        }
 
+#if TDM_HWC
+       /* enable the tdm_hwc */
+       fbdev_data->hwc_mode = 1;
+#endif
+
        LIST_INITHEAD(&fbdev_data->buffer_list);
 
        memset(&fbdev_func_display, 0, sizeof(fbdev_func_display));
@@ -206,6 +215,38 @@ tdm_fbdev_init(tdm_display *dpy, tdm_error *error)
        fbdev_func_output.output_set_mode = fbdev_output_set_mode;
        fbdev_func_output.output_get_mode = fbdev_output_get_mode;
 
+       if (fbdev_data->hwc_mode) {
+               fbdev_func_output.output_get_hwc = fbdev_output_get_hwc;
+
+               memset(&fbdev_func_hwc, 0, sizeof(fbdev_func_hwc));
+               fbdev_func_hwc.hwc_create_window = fbdev_hwc_create_window;
+               fbdev_func_hwc.hwc_get_video_supported_formats = fbdev_hwc_get_video_supported_formats;
+               fbdev_func_hwc.hwc_get_video_available_properties = NULL;
+               fbdev_func_hwc.hwc_get_capabilities = fbdev_hwc_get_capabilities;
+               fbdev_func_hwc.hwc_get_available_properties = fbdev_hwc_get_available_properties;
+               fbdev_func_hwc.hwc_get_client_target_buffer_queue = fbdev_hwc_get_client_target_buffer_queue;
+               fbdev_func_hwc.hwc_set_client_target_buffer = fbdev_hwc_set_client_target_buffer;
+               fbdev_func_hwc.hwc_validate = fbdev_hwc_validate;
+               fbdev_func_hwc.hwc_get_changed_composition_types = fbdev_hwc_get_changed_composition_types;
+               fbdev_func_hwc.hwc_accept_validation = fbdev_hwc_accept_validation;
+               fbdev_func_hwc.hwc_commit = fbdev_hwc_commit;
+               fbdev_func_hwc.hwc_set_commit_handler = fbdev_hwc_set_commit_handler;
+
+               memset(&fbdev_func_hwc_window, 0, sizeof(fbdev_func_hwc_window));
+               fbdev_func_hwc_window.hwc_window_destroy = fbdev_hwc_window_destroy;
+               fbdev_func_hwc_window.hwc_window_acquire_buffer_queue = NULL; // no need
+               fbdev_func_hwc_window.hwc_window_release_buffer_queue = NULL; // no need
+               fbdev_func_hwc_window.hwc_window_set_composition_type = fbdev_hwc_window_set_composition_type;
+               fbdev_func_hwc_window.hwc_window_set_buffer_damage = fbdev_hwc_window_set_buffer_damage;
+               fbdev_func_hwc_window.hwc_window_set_info = fbdev_hwc_window_set_info;
+               fbdev_func_hwc_window.hwc_window_set_buffer = fbdev_hwc_window_set_buffer;
+               fbdev_func_hwc_window.hwc_window_set_property = fbdev_hwc_window_set_property;
+               fbdev_func_hwc_window.hwc_window_get_property = fbdev_hwc_window_get_property;
+               fbdev_func_hwc_window.hwc_window_get_constraints = fbdev_hwc_window_get_constraints;
+               fbdev_func_hwc_window.hwc_window_set_name = fbdev_hwc_window_set_name;
+               fbdev_func_hwc_window.hwc_window_set_cursor_image = fbdev_hwc_window_set_cursor_image;
+       }
+
        memset(&fbdev_func_layer, 0, sizeof(fbdev_func_layer));
        fbdev_func_layer.layer_get_capability = fbdev_layer_get_capability;
        fbdev_func_layer.layer_set_property = fbdev_layer_set_property;
@@ -227,6 +268,16 @@ tdm_fbdev_init(tdm_display *dpy, tdm_error *error)
        if (ret != TDM_ERROR_NONE)
                goto failed;
 
+       if (fbdev_data->hwc_mode) {
+               ret = tdm_backend_register_func_hwc(dpy, &fbdev_func_hwc);
+               if (ret != TDM_ERROR_NONE)
+                       goto failed;
+
+               ret = tdm_backend_register_func_hwc_window(dpy, &fbdev_func_hwc_window);
+               if (ret != TDM_ERROR_NONE)
+                       goto failed;
+       }
+
        fbdev_data->dpy = dpy;
 
        fbdev_data->fbdev_fd = _tdm_fbdev_open_fbdev();
index bc66fb02fc9ce441d523c5f17d706c55218b0cee..b76b8964b22759e3ea291b36a069e2f1abd14d0f 100644 (file)
@@ -21,6 +21,9 @@
 #include <tdm_backend.h>
 #include <tdm_log.h>
 #include <tdm_list.h>
+#include "tdm_fbdev_types.h"
+#include "tdm_fbdev_hwc.h"
+#include "tdm_fbdev_hwc_window.h"
 
 #define MAX_BUF 1
 
@@ -42,6 +45,31 @@ tdm_error            fbdev_output_set_dpms(tdm_output *output, tdm_output_dpms dpms_value)
 tdm_error              fbdev_output_get_dpms(tdm_output *output, tdm_output_dpms *dpms_value);
 tdm_error              fbdev_output_set_mode(tdm_output *output, const tdm_output_mode *mode);
 tdm_error              fbdev_output_get_mode(tdm_output *output, const tdm_output_mode **mode);
+tdm_hwc        *fbdev_output_get_hwc(tdm_output *output, tdm_error *error);
+
+tdm_hwc_window      *fbdev_hwc_create_window(tdm_hwc *hwc, tdm_error *error);
+tdm_error            fbdev_hwc_get_video_supported_formats(tdm_hwc *hwc, const tbm_format **formats, int *count);
+tdm_error            fbdev_hwc_get_capabilities(tdm_hwc *hwc, tdm_hwc_capability *capabilities);
+tdm_error            fbdev_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count);
+tbm_surface_queue_h  fbdev_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error);
+tdm_error            fbdev_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage);
+tdm_error            fbdev_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types);
+tdm_error            fbdev_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            fbdev_hwc_accept_validation(tdm_hwc *hwc);
+tdm_error            fbdev_hwc_commit(tdm_hwc *hwc, int sync, void *user_data);
+tdm_error            fbdev_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func);
+
+void            fbdev_hwc_window_destroy(tdm_hwc_window *hwc_window);
+tdm_error       fbdev_hwc_window_set_composition_type(tdm_hwc_window *hwc_window, tdm_hwc_window_composition composition_type);
+tdm_error       fbdev_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_region damage);
+tdm_error       fbdev_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info);
+tdm_error       fbdev_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface);
+tdm_error       fbdev_hwc_window_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value);
+tdm_error       fbdev_hwc_window_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value);
+tdm_error       fbdev_hwc_window_get_constraints(tdm_hwc_window *hwc_window, int *constraints);
+tdm_error       fbdev_hwc_window_set_name(tdm_hwc_window *hwc_window, const char *name);
+tdm_error       fbdev_hwc_window_set_cursor_image(tdm_hwc_window *hwc_window, int width, int height, int stride, void *ptr);
+
 tdm_error              fbdev_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps);
 tdm_error              fbdev_layer_set_property(tdm_layer *layer, unsigned int id, tdm_value value);
 tdm_error              fbdev_layer_get_property(tdm_layer *layer, unsigned int id, tdm_value *value);
@@ -50,110 +78,6 @@ tdm_error           fbdev_layer_get_info(tdm_layer *layer, tdm_info_layer *info);
 tdm_error              fbdev_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer);
 tdm_error              fbdev_layer_unset_buffer(tdm_layer *layer);
 
-/* Framebuffer moudel's internal macros, functions, structures */
-#define NEVER_GET_HERE() TDM_ERR("** NEVER GET HERE **")
-
-#define RETURN_VAL_IF_FAIL(cond, val) {\
-       if (!(cond)) {\
-               TDM_ERR("'%s' failed", #cond);\
-               return val;\
-       }       \
-}
-
-typedef struct _tdm_fbdev_output_data tdm_fbdev_output_data;
-typedef struct _tdm_fbdev_layer_data tdm_fbdev_layer_data;
-typedef struct _tdm_fbdev_display_buffer tdm_fbdev_display_buffer;
-
-typedef struct _tdm_fbdev_data {
-       tdm_fbdev_output_data *fbdev_output;
-
-       int fbdev_fd;
-
-       tdm_display *dpy;
-
-       struct fb_fix_screeninfo *finfo;
-       struct fb_var_screeninfo *vinfo;
-
-       struct list_head buffer_list;
-} tdm_fbdev_data;
-
-struct _tdm_fbdev_output_data {
-       tdm_fbdev_data *fbdev_data;
-       tdm_fbdev_layer_data *fbdev_layer;
-
-       uint32_t width;
-       uint32_t height;
-       uint32_t pitch;
-       uint32_t bpp;
-       size_t size;
-       uint32_t max_width;
-       uint32_t max_height;
-
-       /*
-        * Poinetr to Framebuffers's mapped memory
-        */
-       void *mem;
-
-       int count_modes;
-       tdm_output_mode *output_modes;
-       int mode_changed;
-
-       /*
-        * Frambuffer device back end currently support only one mode
-        */
-       const tdm_output_mode *current_mode;
-
-       tdm_output_type connector_type;
-       tdm_output_conn_status status;
-       unsigned int connector_type_id;
-
-       tdm_output_dpms dpms_value;
-
-       /*
-        * Event handlers
-        */
-       tdm_output_vblank_handler vblank_func;
-       tdm_output_commit_handler commit_func;
-
-       void *user_data;
-
-       /*
-        * Fake flags are used to simulate event-operated back end. Since tdm
-        *  library assumes its back ends to be event-operated and Framebuffer
-        *  device is not event-operated we have to make fake events
-        */
-       int is_vblank;
-       int is_commit;
-
-       int sequence;
-
-};
-
-struct _tdm_fbdev_layer_data {
-       tdm_fbdev_data *fbdev_data;
-       tdm_fbdev_output_data *fbdev_output;
-
-       tdm_fbdev_display_buffer *display_buffer;
-       int display_buffer_changed;
-
-       tdm_layer_capability capabilities;
-       tdm_info_layer info;
-       int info_changed;
-};
-
-enum {
-       DOWN = 0,
-       UP,
-};
-
-struct _tdm_fbdev_display_buffer {
-       struct list_head link;
-
-       int width;
-       int height;
-
-       tbm_surface_h buffer;
-};
 
 tdm_error      tdm_fbdev_creat_output(tdm_fbdev_data *fbdev_data);
 void           tdm_fbdev_destroy_output(tdm_fbdev_data *fbdev_data);
@@ -161,4 +85,6 @@ void         tdm_fbdev_destroy_output(tdm_fbdev_data *fbdev_data);
 tdm_error      tdm_fbdev_creat_layer(tdm_fbdev_data *fbdev_data);
 void           tdm_fbdev_destroy_layer(tdm_fbdev_data *fbdev_data);
 
+tdm_fbdev_layer_data *fbdev_output_data_get_layer_data(tdm_fbdev_output_data *output_data, int layer_zops);
+
 #endif /* _TDM_fbdev_H_ */
index 63ee64e7c5c79888ae2b5220b116c139c9c0d524..b9842d8b05851a97190aec31305d48fc9cb82847 100644 (file)
@@ -185,6 +185,9 @@ tdm_fbdev_creat_output(tdm_fbdev_data *fbdev_data)
        output->fbdev_data = fbdev_data;
        fbdev_data->fbdev_output = output;
 
+       if (fbdev_data->hwc_mode)
+               output->hwc_enable = 1;
+
        return TDM_ERROR_NONE;
 }
 
@@ -192,10 +195,15 @@ void
 tdm_fbdev_destroy_output(tdm_fbdev_data *fbdev_data)
 {
        tdm_fbdev_output_data *fbdev_output = fbdev_data->fbdev_output;
+       tdm_fbdev_hwc_data *hwc_data = NULL;
 
        if (fbdev_output == NULL)
                goto close;
 
+       hwc_data = fbdev_output->hwc_data;
+       if (hwc_data && hwc_data->target_hwc_window)
+               fbdev_hwc_window_destroy(hwc_data->target_hwc_window);
+
        if (fbdev_output->mem == NULL)
                goto close_2;
 
@@ -311,6 +319,7 @@ fbdev_display_handle_events(tdm_backend_data *bdata)
        tdm_fbdev_data *fbdev_data = (tdm_fbdev_data *) bdata;
        void *user_data;
        tdm_fbdev_output_data *fbdev_output;
+       tdm_fbdev_hwc_data *hwc_data;
        unsigned int sequence = 0;
        unsigned int tv_sec = 0;
        unsigned int tv_usec = 0;
@@ -340,10 +349,20 @@ fbdev_display_handle_events(tdm_backend_data *bdata)
                fbdev_output->vblank_func((tdm_output *) fbdev_data, sequence, tv_sec, tv_usec, user_data);
        }
 
-       if (fbdev_output->is_commit && fbdev_output->commit_func) {
-               fbdev_output->is_commit = DOWN;
-
-               fbdev_output->commit_func((tdm_output *) fbdev_data, sequence, tv_sec, tv_usec, user_data);
+       if (fbdev_output->is_commit) {
+               if (fbdev_output->hwc_enable) {
+                       hwc_data = fbdev_output->hwc_data;
+
+                       if (hwc_data && hwc_data->commit_func) {
+                               fbdev_output->is_commit = DOWN;
+                               hwc_data->commit_func(hwc_data, sequence, tv_sec, tv_usec, user_data);
+                       }
+               } else {
+                       if (fbdev_output->commit_func) {
+                               fbdev_output->is_commit = DOWN;
+                               fbdev_output->commit_func((tdm_output *) fbdev_data, sequence, tv_sec, tv_usec, user_data);
+                       }
+               }
        }
 
        return TDM_ERROR_NONE;
@@ -399,6 +418,9 @@ fbdev_output_get_capability(tdm_output *output, tdm_caps_output *caps)
        caps->prop_count = 0;
        caps->props = NULL;
 
+       if (fbdev_output->hwc_enable)
+               caps->capabilities |= TDM_OUTPUT_CAPABILITY_HWC;
+
        return TDM_ERROR_NONE;
 
 failed_get:
@@ -416,6 +438,12 @@ fbdev_output_get_layers(tdm_output *output, int *count, tdm_error *error)
        RETURN_VAL_IF_FAIL(fbdev_output, NULL);
        RETURN_VAL_IF_FAIL(count, NULL);
 
+       if (fbdev_output->hwc_enable) {
+               *count = 0;
+               ret = TDM_ERROR_NONE;
+               goto failed_get;
+       }
+
        /*
         * Framebuffer does not support layer, therefore create only
         *  one layer by libtdm's demand;
@@ -664,6 +692,11 @@ fbdev_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
         */
        fbdev_output->mode_changed = 0;
 
+       /* create or replace the target_window when the output mode is set */
+       if (fbdev_output->hwc_enable) {
+               fbdev_hwc_target_window_set_info(fbdev_output->hwc_data, fbdev_output->current_mode->hdisplay, fbdev_output->current_mode->vdisplay);
+       }
+
        return TDM_ERROR_NONE;
 }
 
@@ -680,6 +713,66 @@ fbdev_output_get_mode(tdm_output *output, const tdm_output_mode **mode)
        return TDM_ERROR_NONE;
 }
 
+tdm_hwc *
+fbdev_output_get_hwc(tdm_output *output, tdm_error *error)
+{
+       tdm_fbdev_hwc_data *hwc_data = NULL;
+       tdm_fbdev_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_fbdev_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 = fbdev_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_fbdev_layer_data *
+fbdev_output_data_get_layer_data(tdm_fbdev_output_data *output_data, int layer_zpos)
+{
+       RETURN_VAL_IF_FAIL(output_data, NULL);
+
+       if (layer_zpos == 0)
+               return output_data->fbdev_layer;
+
+       return NULL;
+}
+
 tdm_error
 fbdev_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps)
 {
diff --git a/src/libtdm-fbdev/tdm_fbdev_hwc.c b/src/libtdm-fbdev/tdm_fbdev_hwc.c
new file mode 100644 (file)
index 0000000..ed366c1
--- /dev/null
@@ -0,0 +1,804 @@
+/**************************************************************************
+
+libtdm_fbdev
+
+Copyright 2021 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tdm_helper.h>
+#include "tdm_fbdev.h"
+
+#define MIN_WIDTH      32
+
+#define NUM_LAYERS     4
+#define NUM_BUFFERS    3
+
+#define NUM_UI_LAYERS  1
+
+#define ZPOS_MAX       1
+#define ZPOS_CURSOR    2
+#define ZPOS_1         1
+#define ZPOS_0         0
+#define ZPOS_VIDEO1    0
+#define ZPOS_NONE      -999
+
+tbm_format hwc_window_video_formats[] = {
+       TBM_FORMAT_NV12,
+       TBM_FORMAT_YUV420
+};
+
+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 int
+_fbdev_hwc_cursor_buffer_unset(tdm_fbdev_hwc_window_data *hwc_window_data)
+{
+       hwc_window_data->surface = NULL;
+       hwc_window_data->cursor_img_surface = 0;
+
+       hwc_window_data->info.src_config.pos.w = hwc_window_data->cursor_img.width;
+       hwc_window_data->info.src_config.pos.h = hwc_window_data->cursor_img.height;
+       hwc_window_data->info.dst_pos.w = hwc_window_data->cursor_img.width;
+       hwc_window_data->info.dst_pos.h = hwc_window_data->cursor_img.height;
+
+       return 1;
+}
+
+static void
+_fbdev_hwc_cursor_adjust_pos(tdm_fbdev_hwc_window_data *hwc_window_data)
+{
+       int x, y;
+
+       /* 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;
+
+       if (x < 0) hwc_window_data->info.dst_pos.x = 0;
+       if (y < 0) hwc_window_data->info.dst_pos.y = 0;
+}
+
+static int
+_fbdev_hwc_cursor_buffer_set(tdm_fbdev_hwc_data *hwc_data, tdm_fbdev_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 new_format;
+       unsigned int flags = TBM_BO_SCANOUT;
+       void *src_ptr = NULL, *dst_ptr = NULL;
+       int src_stride;
+       int i;
+
+       _fbdev_hwc_cursor_adjust_pos(hwc_window_data);
+
+       if (!hwc_window_data->cursor_img_refresh && hwc_window_data->surface)
+               return 1;
+
+       img_w = hwc_window_data->cursor_img.width;
+       img_h = hwc_window_data->cursor_img.height;
+       new_format = hwc_window_data->info.src_config.format;
+
+       /* cursor restriction to set the cursor layer */
+       new_w = (CURSOR_MIN_W > img_w) ? CURSOR_MIN_W : img_w;
+       new_h = (CURSOR_MIN_H > img_h) ? CURSOR_MIN_H : img_h;
+
+       if (hwc_data->cursor_tsurface) {
+               tbm_surface_internal_unref(hwc_data->cursor_tsurface);
+               hwc_data->cursor_tsurface = NULL;
+       }
+
+       cursor_tsurface = tbm_surface_internal_create_with_flags(new_w, new_h, new_format, flags);
+       RETURN_VAL_IF_FAIL(cursor_tsurface, 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;
+       }
+
+       src_ptr = hwc_window_data->cursor_img.ptr;
+       dst_ptr = tsurface_info.planes[0].ptr;
+       src_stride = hwc_window_data->cursor_img.stride;
+
+       memset(dst_ptr, 0, tsurface_info.planes[0].stride * tsurface_info.height);
+
+       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);
+
+       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 = new_w;
+       hwc_window_data->info.src_config.pos.h = new_h;
+       hwc_window_data->info.dst_pos.w = new_w;
+       hwc_window_data->info.dst_pos.h = new_h;
+
+       hwc_window_data->cursor_img_refresh = 0;
+
+       return 1;
+}
+
+static void
+_print_validate_result(tdm_fbdev_hwc_data *hwc_data, tdm_hwc_window **composited_wnds, uint32_t num_wnds)
+{
+       tdm_fbdev_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_INFO(" 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_INFO(" 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 int
+_fbdev_hwc_window_can_set_on_hw_layer(tdm_fbdev_hwc_window_data *hwc_window_data)
+{
+       if (!hwc_window_data->surface)
+               return 0;
+
+       if (hwc_window_data->info.transform != TDM_TRANSFORM_NORMAL)
+               return 0;
+
+       if (hwc_window_data->info.src_config.pos.w != hwc_window_data->info.dst_pos.w)
+               return 0;
+
+       if (hwc_window_data->info.src_config.pos.h != hwc_window_data->info.dst_pos.h)
+               return 0;
+
+       if (!IS_RGB(hwc_window_data->info.src_config.format))
+               return 0;
+
+       if (hwc_window_data->info.dst_pos.x > hwc_window_data->hwc_data->output_data->current_mode->hdisplay ||
+               hwc_window_data->info.dst_pos.y > hwc_window_data->hwc_data->output_data->current_mode->vdisplay)
+               return 0;
+
+       if (hwc_window_data->info.src_config.pos.w < MIN_WIDTH || hwc_window_data->info.src_config.pos.w % 2)
+               return 0;
+
+       return 1;
+}
+
+static tbm_surface_queue_h
+_fbdev_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error)
+{
+       tdm_fbdev_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
+_fbdev_hwc_layer_attach_window(tdm_fbdev_layer_data *layer_data, tdm_fbdev_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 = fbdev_layer_unset_buffer(layer_data);
+               RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+       } else {
+               ret = fbdev_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 = fbdev_layer_set_buffer(layer_data, hwc_window_data->surface);
+               RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+       }
+
+       return ret;
+}
+
+static tdm_error
+_fbdev_hwc_prepare_commit(tdm_fbdev_hwc_data *hwc_data)
+{
+       tdm_fbdev_hwc_window_data *hwc_window_data = NULL;
+       tdm_fbdev_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 = fbdev_output_data_get_layer_data(hwc_data->output_data, hwc_data->target_hwc_window->lzpos);
+               _fbdev_hwc_layer_attach_window(layer_data, hwc_data->target_hwc_window);
+               use_layers_zpos[hwc_data->target_hwc_window->lzpos] = 1;
+       }
+
+       /* set the hwc_windows to the layers */
+       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)
+                               _fbdev_hwc_cursor_buffer_unset(hwc_window_data);
+
+                       continue;
+               }
+
+               if (hwc_window_data == hwc_data->target_hwc_window)
+                       continue;
+
+               /* set the cursor buffer HERE if it needs */
+               if (hwc_window_data->validated_type == TDM_HWC_WIN_COMPOSITION_CURSOR)
+                       _fbdev_hwc_cursor_buffer_set(hwc_data, hwc_window_data);
+
+               layer_data = fbdev_output_data_get_layer_data(hwc_data->output_data, hwc_window_data->lzpos);
+               _fbdev_hwc_layer_attach_window(layer_data, hwc_window_data);
+               use_layers_zpos[hwc_window_data->lzpos] = 1;
+       }
+
+       /* unset the unused layers */
+       for (lzpos = 0; lzpos < NUM_LAYERS; lzpos++) {
+               if (use_layers_zpos[lzpos])
+                       continue;
+
+               layer_data = fbdev_output_data_get_layer_data(hwc_data->output_data, lzpos);
+               if (!layer_data)
+                       continue;
+
+               _fbdev_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;
+}
+
+/* assign the validated_type to the composited_wnds
+ * assign the layer_zpos to the composited_wnds
+ */
+static void
+_fbdev_hwc_apply_policy(tdm_fbdev_hwc_data *hwc_data , tdm_hwc_window **composited_wnds, uint32_t num_wnds)
+{
+       tdm_fbdev_hwc_window_data *hwc_window_data = NULL;
+       tdm_fbdev_hwc_window_data **composited_list = NULL;
+       int client_count = 0;
+       int device_count = 0;
+       int video_count = 0;
+       int cursor_count = 0;
+       int ui_lzpos_top = ZPOS_0;
+       int ui_lzpos_bottom = ZPOS_0;
+       int num_ui_layers = NUM_UI_LAYERS;
+       int set_clients_below = 0;
+       int i = 0;
+
+       composited_list = (tdm_fbdev_hwc_window_data **)composited_wnds;
+
+       /* initialize the need_target_window */
+       hwc_data->need_target_window = 0;
+
+       /* 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 = ui_lzpos_bottom;
+               return;
+       }
+
+       /* 1. first check validate_type without target_window */
+       for (i = 0; i < num_wnds; i++) {
+               switch (composited_list[i]->client_type) {
+               case TDM_HWC_WIN_COMPOSITION_VIDEO:
+                       composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_VIDEO;
+                       video_count++;
+                       continue;
+               case TDM_HWC_WIN_COMPOSITION_CURSOR:
+                       if (set_clients_below) break;
+                       if (cursor_count > 0) break;
+
+                       composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_CURSOR;
+                       cursor_count++;
+                       continue;
+               case TDM_HWC_WIN_COMPOSITION_DEVICE:
+                       if (set_clients_below) break;
+                       if (num_ui_layers <= 0) break;
+                       if (!_fbdev_hwc_window_can_set_on_hw_layer(composited_list[i])) break;
+
+                       composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_DEVICE;
+                       device_count++;
+                       num_ui_layers--;
+                       continue;
+               default:
+                       break;
+               }
+
+               composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_CLIENT;
+               client_count++;
+               set_clients_below = 1;
+       }
+
+       /* 2. check need target window and set ui_lzpos top and bottom */
+       num_ui_layers = NUM_UI_LAYERS;
+
+       if (video_count > 0) {
+               ui_lzpos_bottom++;
+               num_ui_layers--;
+       }
+
+       if (client_count > 0) {
+               ui_lzpos_bottom++;
+               num_ui_layers--;
+               hwc_data->need_target_window = 1;
+               hwc_data->target_hwc_window->lzpos = ui_lzpos_bottom - 1;
+       }
+
+       if (num_ui_layers > device_count)
+               ui_lzpos_top = ui_lzpos_bottom + device_count - 1;
+
+       /* 3. set lzpos and modify validate_type with target_window */
+       for (i = 0; i < num_wnds; i++) {
+               switch (composited_list[i]->validated_type) {
+               case TDM_HWC_WIN_COMPOSITION_VIDEO:
+                       composited_list[i]->lzpos = ZPOS_VIDEO1;
+                       continue;
+               case TDM_HWC_WIN_COMPOSITION_CURSOR:
+                       composited_list[i]->lzpos = ZPOS_CURSOR;
+                       continue;
+               case TDM_HWC_WIN_COMPOSITION_DEVICE:
+                       if (num_ui_layers <= 0) break;
+                       composited_list[i]->lzpos = ui_lzpos_top;
+                       ui_lzpos_top--;
+                       num_ui_layers--;
+                       continue;
+               default:
+                       break;
+               }
+
+               composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_CLIENT;
+               composited_list[i]->lzpos = ZPOS_NONE;
+       }
+}
+
+static int
+_fbdev_hwc_get_changed_number(tdm_fbdev_hwc_data *hwc_data)
+{
+       int num = 0;
+       tdm_fbdev_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;
+}
+
+tdm_hwc_window *
+_fbdev_hwc_create_window(tdm_hwc *hwc, tdm_hwc_window_info *info, tdm_error *error)
+{
+       tdm_fbdev_hwc_data *hwc_data = hwc;
+       tdm_fbdev_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_fbdev_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));
+
+       LIST_INITHEAD(&hwc_window_data->link);
+
+       return hwc_window_data;
+}
+
+tdm_hwc_window *
+fbdev_hwc_create_window(tdm_hwc *hwc, tdm_error *error)
+{
+       tdm_fbdev_hwc_data *hwc_data = hwc;
+       tdm_fbdev_hwc_window_data *hwc_window_data = NULL;
+
+       RETURN_VAL_IF_FAIL(hwc_data, NULL);
+
+       hwc_window_data = _fbdev_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_INFO("hwc_window(%p) create", hwc_window_data);
+       if (error)
+               *error = TDM_ERROR_NONE;
+
+       return hwc_window_data;
+}
+
+tdm_error
+fbdev_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
+fbdev_hwc_get_capabilities(tdm_hwc *hwc, tdm_hwc_capability *capabilities)
+{
+       RETURN_VAL_IF_FAIL(hwc != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(capabilities != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       *capabilities |= TDM_HWC_CAPABILITY_VIDEO_SCALE;
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+fbdev_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count)
+{
+       tdm_fbdev_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
+fbdev_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error)
+{
+       tdm_fbdev_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 = _fbdev_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
+fbdev_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage)
+{
+       tdm_fbdev_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 = fbdev_hwc_window_set_buffer(hwc_data->target_hwc_window, buffer);
+       RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
+
+       err = fbdev_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
+fbdev_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types)
+{
+       tdm_fbdev_hwc_data *hwc_data = hwc;
+       tdm_fbdev_output_data *output_data;
+
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       output_data = hwc_data->output_data;
+       RETURN_VAL_IF_FAIL(output_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       TDM_INFO(" ==============Validate=================================");
+
+       _fbdev_hwc_apply_policy(hwc_data, composited_wnds, num_wnds);
+
+       *num_types = _fbdev_hwc_get_changed_number(hwc_data);
+
+       _print_validate_result(hwc_data, composited_wnds, num_wnds);
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+fbdev_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements,
+                               tdm_hwc_window **hwc_wnds, tdm_hwc_window_composition *composition_types)
+{
+       tdm_fbdev_hwc_data *hwc_data = hwc;
+       tdm_fbdev_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 = _fbdev_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
+fbdev_hwc_accept_validation(tdm_hwc *hwc)
+{
+       tdm_fbdev_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_INFO(" ==============Accept Changes Done=================================");
+
+       if (hwc_data->output_data->current_dpms != TDM_OUTPUT_DPMS_ON) {
+               TDM_ERR("dpms is not on. do not set buffer");
+               return TDM_ERROR_BAD_REQUEST;
+       }
+
+       ret = _fbdev_hwc_prepare_commit(hwc_data);
+       RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+fbdev_hwc_commit(tdm_hwc *hwc, int sync, void *user_data)
+{
+       tdm_fbdev_hwc_data *hwc_data = hwc;
+       tdm_fbdev_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_INFO(" ==============COMMIT=================================");
+
+       if (hwc_data->output_data->current_dpms != TDM_OUTPUT_DPMS_ON) {
+               TDM_ERR("dpms is not on. do not commit");
+               return TDM_ERROR_BAD_REQUEST;
+       }
+
+       ret = fbdev_output_commit(output_data, sync, user_data);
+       RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+
+       if (hwc_data->commit_func)
+               hwc_data->commit_func(hwc, output_data->sequence++, 0, 0, user_data);
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+fbdev_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func)
+{
+       tdm_fbdev_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
+fbdev_hwc_target_window_set_info(tdm_fbdev_hwc_data *hwc_data, int width, int height)
+{
+       tdm_hwc_window_info info = {0};
+       tdm_fbdev_hwc_window_data *target_hwc_window;
+       tdm_error ret = TDM_ERROR_NONE;
+
+       RETURN_VAL_IF_FAIL(hwc_data, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(hwc_data->target_hwc_window, TDM_ERROR_INVALID_PARAMETER);
+
+       target_hwc_window = hwc_data->target_hwc_window;
+
+       info.dst_pos.x = 0;
+       info.dst_pos.y = 0;
+       info.dst_pos.w = width;
+       info.dst_pos.h = height;
+
+       info.src_config.pos.x = 0;
+       info.src_config.pos.y = 0;
+       info.src_config.pos.w = width;
+       info.src_config.pos.h = height;
+
+       info.src_config.size.h = width;
+       info.src_config.size.v = height;
+       info.src_config.format = TBM_FORMAT_ARGB8888;
+
+       ret = fbdev_hwc_window_set_info(target_hwc_window, &info);
+       if (ret != TDM_ERROR_NONE) {
+               TDM_ERR("set info target hwc window failed (%d)", ret);
+               return TDM_ERROR_OPERATION_FAILED;
+       }
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+fbdev_hwc_initailize_target_window(tdm_fbdev_hwc_data *hwc_data)
+{
+       tdm_hwc_window_info info = {0};
+       tdm_error ret = TDM_ERROR_NONE;
+       tdm_fbdev_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 = _fbdev_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)
+               fbdev_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;
+}
diff --git a/src/libtdm-fbdev/tdm_fbdev_hwc.h b/src/libtdm-fbdev/tdm_fbdev_hwc.h
new file mode 100644 (file)
index 0000000..4a435f7
--- /dev/null
@@ -0,0 +1,39 @@
+/**************************************************************************
+
+libtdm_fbdev
+
+Copyright 2021 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef _TDM_FBDEV_HWC_H_
+#define _TDM_FBDEV_HWC_H_
+
+#include "tdm_fbdev.h"
+
+tdm_error fbdev_hwc_initailize_target_window(tdm_fbdev_hwc_data *hwc_data);
+tdm_error fbdev_hwc_target_window_set_info(tdm_fbdev_hwc_data *hwc_data, int width, int height);
+
+#endif /* _TDM_FBDEV_HWC_H_ */
diff --git a/src/libtdm-fbdev/tdm_fbdev_hwc_window.c b/src/libtdm-fbdev/tdm_fbdev_hwc_window.c
new file mode 100644 (file)
index 0000000..49c520f
--- /dev/null
@@ -0,0 +1,184 @@
+/**************************************************************************
+
+libtdm_fbdev
+
+Copyright 2021 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tdm_fbdev.h"
+
+void
+fbdev_hwc_window_destroy(tdm_hwc_window *hwc_window)
+{
+       tdm_fbdev_hwc_window_data *hwc_window_data = hwc_window;
+
+       RETURN_IF_FAIL(hwc_window_data != NULL);
+
+       LIST_DEL(&hwc_window_data->link);
+
+       free(hwc_window_data);
+}
+
+tdm_error
+fbdev_hwc_window_set_composition_type(tdm_hwc_window *hwc_window,
+                                                                       tdm_hwc_window_composition comp_type)
+{
+       tdm_fbdev_hwc_window_data *hwc_window_data = hwc_window;
+       tdm_fbdev_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
+fbdev_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_region damage)
+{
+       tdm_fbdev_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
+fbdev_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info)
+{
+       tdm_fbdev_hwc_window_data *hwc_window_data = hwc_window;
+       tdm_fbdev_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
+fbdev_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface)
+{
+       tdm_fbdev_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
+fbdev_hwc_window_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value)
+{
+       tdm_fbdev_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
+fbdev_hwc_window_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value)
+{
+       tdm_fbdev_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
+fbdev_hwc_window_get_constraints(tdm_hwc_window *hwc_window, int *constraints)
+{
+       tdm_fbdev_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
+fbdev_hwc_window_set_name(tdm_hwc_window *hwc_window, const char *name)
+{
+       tdm_fbdev_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;
+}
+
+tdm_error
+fbdev_hwc_window_set_cursor_image(tdm_hwc_window *hwc_window, int width, int height, int stride, void *ptr)
+{
+       tdm_fbdev_hwc_window_data *hwc_window_data = hwc_window;
+
+       RETURN_VAL_IF_FAIL(hwc_window_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(hwc_window_data->client_type == TDM_HWC_WIN_COMPOSITION_CURSOR, TDM_ERROR_INVALID_PARAMETER);
+
+       hwc_window_data->cursor_img.width = width;
+       hwc_window_data->cursor_img.height = height;
+       hwc_window_data->cursor_img.stride = stride;
+       hwc_window_data->cursor_img.ptr = ptr;
+
+       hwc_window_data->cursor_img_refresh = 1;
+
+       return TDM_ERROR_NONE;
+}
diff --git a/src/libtdm-fbdev/tdm_fbdev_hwc_window.h b/src/libtdm-fbdev/tdm_fbdev_hwc_window.h
new file mode 100644 (file)
index 0000000..e365b20
--- /dev/null
@@ -0,0 +1,36 @@
+/**************************************************************************
+
+libtdm_fbdev
+
+Copyright 2021 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef _TDM_FBDEV_HWC_WINDOW_H_
+#define _TDM_FBDEV_HWC_WINDOW_H_
+
+#include "tdm_fbdev.h"
+
+#endif /* _TDM_FBDEV_HWC_WINDOW_H_ */
\ No newline at end of file
diff --git a/src/libtdm-fbdev/tdm_fbdev_types.h b/src/libtdm-fbdev/tdm_fbdev_types.h
new file mode 100644 (file)
index 0000000..4db4cdc
--- /dev/null
@@ -0,0 +1,254 @@
+/**************************************************************************
+
+libtdm_drm
+
+Copyright 2015 Samsung Electronics co., Ltd. All Rights Reserved.
+
+Contact: SooChan Lim <sc1.lim@samsung.com>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef _TDM_FBDEV_TYPES_H_
+#define _TDM_FBDEV_TYPES_H_
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+
+#include <linux/fb.h>
+#include <xf86drm.h>
+#include <xf86drmMode.h>
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+#include <tdm_backend.h>
+#include <tdm_log.h>
+#include <tdm_list.h>
+#include <drm_fourcc.h>
+#include <tdm_helper.h>
+
+/* Framebuffer moudel's internal macros, functions, structures */
+#define NEVER_GET_HERE() TDM_ERR("** NEVER GET HERE **")
+
+#define C(b, m)                          (((b) >> (m)) & 0xFF)
+#define B(c, s)                          ((((unsigned int)(c)) & 0xff) << (s))
+#define FOURCC(a, b, c, d)      (B(d, 24) | B(c, 16) | B(b, 8) | B(a, 0))
+#define FOURCC_STR(id)   C(id, 0), C(id, 8), C(id, 16), C(id, 24)
+
+#define IS_RGB(format)   (format == TBM_FORMAT_XRGB8888 || format == TBM_FORMAT_ARGB8888 || \
+                                                        format == TBM_FORMAT_XBGR8888 || format == TBM_FORMAT_ABGR8888)
+
+#define CLEAR(x) memset(&(x), 0, sizeof(x))
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define SWAP(a, b)  ({int t; t = a; a = b; b = t; })
+#define ROUNDUP(x)  (ceil(floor((float)(height) / 4)))
+
+#define ALIGN_TO_16B(x)        ((((x) + (1 <<  4) - 1) >>  4) <<  4)
+#define ALIGN_TO_32B(x)        ((((x) + (1 <<  5) - 1) >>  5) <<  5)
+#define ALIGN_TO_128B(x)   ((((x) + (1 <<  7) - 1) >>  7) <<  7)
+#define ALIGN_TO_2KB(x)        ((((x) + (1 << 11) - 1) >> 11) << 11)
+#define ALIGN_TO_8KB(x)        ((((x) + (1 << 13) - 1) >> 13) << 13)
+#define ALIGN_TO_64KB(x)   ((((x) + (1 << 16) - 1) >> 16) << 16)
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+#define CURSOR_MIN_W 192
+#define CURSOR_MIN_H 192
+#define CURSOR_MAX_W 192
+#define CURSOR_MAX_H 192
+
+#define RETURN_VAL_IF_FAIL(cond, val) {\
+       if (!(cond)) {\
+               TDM_ERR("'%s' failed", #cond);\
+               return val;\
+       } \
+}
+
+#define RETURN_IF_FAIL(cond) {\
+       if (!(cond)) {\
+               TDM_ERR("'%s' failed", #cond);\
+               return;\
+       } \
+}
+
+#define GOTO_IF_FAIL(cond, val) {\
+       if (!(cond)) {\
+               TDM_ERR("'%s' failed", #cond);\
+               goto val;\
+       } \
+}
+
+typedef struct _tdm_fbdev_output_data tdm_fbdev_output_data;
+typedef struct _tdm_fbdev_layer_data tdm_fbdev_layer_data;
+typedef struct _tdm_fbdev_hwc_data tdm_fbdev_hwc_data;
+typedef struct _tdm_fbdev_hwc_window_data tdm_fbdev_hwc_window_data;
+typedef struct _tdm_fbdev_display_buffer tdm_fbdev_display_buffer;
+
+typedef struct _tdm_fbdev_data {
+       tdm_fbdev_output_data *fbdev_output;
+
+       int fbdev_fd;
+
+       tdm_display *dpy;
+
+       int hwc_mode;
+
+       struct fb_fix_screeninfo *finfo;
+       struct fb_var_screeninfo *vinfo;
+
+       struct list_head buffer_list;
+} tdm_fbdev_data;
+
+struct _tdm_fbdev_output_data {
+       tdm_fbdev_data *fbdev_data;
+       tdm_fbdev_layer_data *fbdev_layer;
+
+       uint32_t width;
+       uint32_t height;
+       uint32_t pitch;
+       uint32_t bpp;
+       size_t size;
+       uint32_t max_width;
+       uint32_t max_height;
+
+       /*
+        * Poinetr to Framebuffers's mapped memory
+        */
+       void *mem;
+
+       int count_modes;
+       tdm_output_mode *output_modes;
+       int mode_changed;
+
+       /*
+        * Frambuffer device back end currently support only one mode
+        */
+       const tdm_output_mode *current_mode;
+
+       tdm_output_type connector_type;
+       tdm_output_conn_status status;
+       unsigned int connector_type_id;
+
+       tdm_output_dpms dpms_value;
+
+       /*
+        * Event handlers
+        */
+       tdm_output_vblank_handler vblank_func;
+       tdm_output_commit_handler commit_func;
+
+       void *user_data;
+
+       /*
+        * Fake flags are used to simulate event-operated back end. Since tdm
+        *  library assumes its back ends to be event-operated and Framebuffer
+        *  device is not event-operated we have to make fake events
+        */
+       int is_vblank;
+       int is_commit;
+
+       int sequence;
+
+       /* hwc */
+       int hwc_enable;
+       tdm_fbdev_hwc_data *hwc_data;
+
+       /* dpms */
+       tdm_output_dpms current_dpms;
+};
+
+struct _tdm_fbdev_layer_data {
+       tdm_fbdev_data *fbdev_data;
+       tdm_fbdev_output_data *fbdev_output;
+
+       tdm_fbdev_display_buffer *display_buffer;
+       int display_buffer_changed;
+
+       tdm_layer_capability capabilities;
+       tdm_info_layer info;
+       int info_changed;
+};
+
+enum {
+       DOWN = 0,
+       UP,
+};
+
+struct _tdm_fbdev_display_buffer {
+       struct list_head link;
+
+       int width;
+       int height;
+
+       tbm_surface_h buffer;
+};
+
+
+struct _tdm_fbdev_hwc_data {
+       tdm_fbdev_hwc_window_data *target_hwc_window;
+
+       int need_validate;
+       int need_target_window;
+       int need_set_crtc;
+
+       int target_window_zpos;
+
+       tdm_fbdev_output_data *output_data;
+       struct list_head hwc_window_list;
+
+       tbm_surface_h cursor_tsurface;
+
+       tdm_hwc_commit_handler commit_func;
+};
+
+struct _tdm_fbdev_hwc_window_data {
+       struct list_head link;
+
+       tdm_fbdev_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;
+};
+
+#endif /* _TDM_FBDEV_TYPES_H_ */