tdm_virtual: support hwc mode 25/211825/2
authorJunkyeong Kim <jk0430.kim@samsung.com>
Fri, 9 Aug 2019 09:00:36 +0000 (18:00 +0900)
committerJunkyeong Kim <jk0430.kim@samsung.com>
Fri, 9 Aug 2019 09:14:56 +0000 (18:14 +0900)
Change-Id: I0b8241af46e33dab41ce2ab2297871895f00519e
Signed-off-by: Junkyeong Kim <jk0430.kim@samsung.com>
backends/virtual/Makefile.am
backends/virtual/tdm_virtual.c
backends/virtual/tdm_virtual.h
backends/virtual/tdm_virtual_display.c
backends/virtual/tdm_virtual_hwc.c [new file with mode: 0644]
backends/virtual/tdm_virtual_hwc.h [new file with mode: 0644]
backends/virtual/tdm_virtual_hwc_window.c [new file with mode: 0644]
backends/virtual/tdm_virtual_hwc_window.h [new file with mode: 0644]
src/tdm_backend.c
src/tdm_hwc.c

index 099b71e..d872dd9 100644 (file)
@@ -10,5 +10,7 @@ libtdm_virtual_la_LIBADD = $(TDM_LIBS) $(top_builddir)/src/libtdm.la
 
 libtdm_virtual_la_SOURCES = \
        tdm_virtual_display.c \
+       tdm_virtual_hwc.c \
+       tdm_virtual_hwc_window.c \
        tdm_virtual.c
 
index 580d440..dd64ae7 100644 (file)
@@ -4,6 +4,8 @@
 
 #include "tdm_virtual.h"
 
+#define TDM_HWC 1
+
 static tdm_virtual_data *virtual_data;
 
 void
@@ -31,6 +33,8 @@ tdm_virtual_init(tdm_display *dpy, tdm_error *error)
        tdm_func_display virtual_func_display;
        tdm_func_output virtual_func_output;
        tdm_func_voutput virtual_func_voutput;
+       tdm_func_hwc virtual_func_hwc;
+       tdm_func_hwc_window virtual_func_hwc_window;
        tdm_func_layer virtual_func_layer;
        tdm_error ret;
 
@@ -56,6 +60,10 @@ tdm_virtual_init(tdm_display *dpy, tdm_error *error)
                return NULL;
        }
 
+#if TDM_HWC
+       virtual_data->hwc_mode = 1;
+#endif
+
        LIST_INITHEAD(&virtual_data->voutput_list);
        LIST_INITHEAD(&virtual_data->output_list);
        LIST_INITHEAD(&virtual_data->buffer_list);
@@ -74,13 +82,42 @@ tdm_virtual_init(tdm_display *dpy, tdm_error *error)
        virtual_func_output.output_set_vblank_handler = virtual_output_set_vblank_handler;
        virtual_func_output.output_commit = virtual_output_commit;
        virtual_func_output.output_set_commit_handler = virtual_output_set_commit_handler;
-
        virtual_func_output.output_set_dpms = virtual_output_set_dpms;
        virtual_func_output.output_get_dpms = virtual_output_get_dpms;
-
        virtual_func_output.output_set_mode = virtual_output_set_mode;
        virtual_func_output.output_get_mode = virtual_output_get_mode;
        virtual_func_output.output_set_status_handler = virtual_output_set_status_handler;
+       if (virtual_data->hwc_mode) {
+               virtual_func_output.output_get_hwc = virtual_output_get_hwc;
+
+               memset(&virtual_func_hwc, 0, sizeof(virtual_func_hwc));
+               virtual_func_hwc.hwc_create_window = virtual_hwc_create_window;
+               virtual_func_hwc.hwc_get_video_supported_formats = virtual_hwc_get_video_supported_formats;
+               virtual_func_hwc.hwc_get_video_available_properties = NULL;
+               virtual_func_hwc.hwc_get_capabilities = virtual_hwc_get_capabilities;
+               virtual_func_hwc.hwc_get_available_properties = virtual_hwc_get_available_properties;
+               virtual_func_hwc.hwc_get_client_target_buffer_queue = virtual_hwc_get_client_target_buffer_queue;
+               virtual_func_hwc.hwc_set_client_target_buffer = virtual_hwc_set_client_target_buffer;
+               virtual_func_hwc.hwc_validate = virtual_hwc_validate;
+               virtual_func_hwc.hwc_get_changed_composition_types = virtual_hwc_get_changed_composition_types;
+               virtual_func_hwc.hwc_accept_validation  = virtual_hwc_accept_validation;
+               virtual_func_hwc.hwc_commit = virtual_hwc_commit;
+               virtual_func_hwc.hwc_set_commit_handler = virtual_hwc_set_commit_handler;
+
+               memset(&virtual_func_hwc_window, 0, sizeof(virtual_func_hwc_window));
+               virtual_func_hwc_window.hwc_window_destroy = virtual_hwc_window_destroy;
+               virtual_func_hwc_window.hwc_window_acquire_buffer_queue = NULL; // no need
+               virtual_func_hwc_window.hwc_window_release_buffer_queue = NULL; // no need
+               virtual_func_hwc_window.hwc_window_set_composition_type = virtual_hwc_window_set_composition_type;
+               virtual_func_hwc_window.hwc_window_set_buffer_damage = virtual_hwc_window_set_buffer_damage;
+               virtual_func_hwc_window.hwc_window_set_info = virtual_hwc_window_set_info;
+               virtual_func_hwc_window.hwc_window_set_buffer = virtual_hwc_window_set_buffer;
+               virtual_func_hwc_window.hwc_window_set_property = virtual_hwc_window_set_property;
+               virtual_func_hwc_window.hwc_window_get_property = virtual_hwc_window_get_property;
+               virtual_func_hwc_window.hwc_window_get_constraints = virtual_hwc_window_get_constraints;
+               virtual_func_hwc_window.hwc_window_set_name = virtual_hwc_window_set_name;
+               virtual_func_hwc_window.hwc_window_set_cursor_image = NULL; // no need
+       }
 
        memset(&virtual_func_voutput, 0, sizeof(virtual_func_voutput));
        virtual_func_voutput.voutput_destroy = virtual_voutput_destroy;
@@ -107,6 +144,16 @@ tdm_virtual_init(tdm_display *dpy, tdm_error *error)
        if (ret != TDM_ERROR_NONE)
                goto failed;
 
+       if (virtual_data->hwc_mode) {
+               ret = tdm_backend_register_func_hwc(dpy, &virtual_func_hwc);
+               if (ret != TDM_ERROR_NONE)
+                       goto failed;
+
+               ret = tdm_backend_register_func_hwc_window(dpy, &virtual_func_hwc_window);
+               if (ret != TDM_ERROR_NONE)
+                       goto failed;
+       }
+
        ret = tdm_backend_register_func_voutput(dpy, &virtual_func_voutput);
        if (ret != TDM_ERROR_NONE)
                goto failed;
index 0a5c377..cc36d58 100644 (file)
@@ -52,12 +52,50 @@ tdm_output *virtual_voutput_get_output(tdm_voutput *voutput, tdm_error *error);
 tdm_error virtual_voutput_set_commit_func(tdm_voutput *voutput,  tdm_voutput_commit_handler commit_func);
 tdm_error virtual_voutput_commit_done(tdm_voutput *voutput);
 
+tdm_hwc *virtual_output_get_hwc(tdm_output *output, tdm_error *error);
+tdm_hwc_window *virtual_hwc_create_window(tdm_hwc *hwc, tdm_error *error);
+tdm_error virtual_hwc_get_video_supported_formats(tdm_output *output, const tbm_format **formats, int *count);
+tdm_error virtual_hwc_get_capabilities(tdm_hwc *hwc, tdm_hwc_capability *capabilities);
+tdm_error virtual_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count);
+tbm_surface_queue_h virtual_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error);
+tdm_error virtual_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage);
+tdm_error virtual_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types);
+tdm_error virtual_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 virtual_hwc_accept_validation(tdm_hwc *hwc);
+tdm_error virtual_hwc_commit(tdm_hwc *hwc, int sync, void *user_data);
+tdm_error virtual_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func);
+
+void virtual_hwc_window_destroy(tdm_hwc_window *hwc_window);
+tdm_error virtual_hwc_window_set_composition_type(tdm_hwc_window *hwc_window, tdm_hwc_window_composition composition_type);
+tdm_error virtual_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_region damage);
+tdm_error virtual_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info);
+tdm_error virtual_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface);
+tdm_error virtual_hwc_window_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value);
+tdm_error virtual_hwc_window_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value);
+tdm_error virtual_hwc_window_get_constraints(tdm_hwc_window *hwc_window, int *constraints);
+tdm_error virtual_hwc_window_set_name(tdm_hwc_window *hwc_window, const char *name);
+
 tdm_error virtual_layer_get_capability(tdm_layer *layer, tdm_caps_layer *caps);
 tdm_error virtual_layer_set_info(tdm_layer *layer, tdm_info_layer *info);
 tdm_error virtual_layer_get_info(tdm_layer *layer, tdm_info_layer *info);
 tdm_error virtual_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer);
 tdm_error virtual_layer_unset_buffer(tdm_layer *layer);
 
+#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 RETURN_IF_FAIL(cond) { \
+       if (!(cond)) { \
+               TDM_ERR("'%s' failed", #cond); \
+               return; \
+       } \
+}
+
 #define RETURN_VAL_IF_FAIL(cond, val) {\
        if (!(cond)) {\
                TDM_ERR("'%s' failed", #cond);\
@@ -72,16 +110,140 @@ tdm_error virtual_layer_unset_buffer(tdm_layer *layer);
        }\
 }
 
-typedef struct _tdm_virtual_data {
+typedef struct _tdm_virtual_data tdm_virtual_data;
+typedef struct _tdm_virtual_output_data tdm_virtual_output_data;
+typedef struct _tdm_virtual_hwc_data tdm_virtual_hwc_data;
+typedef struct _tdm_virtual_hwc_window_data tdm_virtual_hwc_window_data;
+typedef struct _tdm_virtual_voutput_data tdm_virtual_voutput_data;
+typedef struct _tdm_virtual_layer_data tdm_virtual_layer_data;
+typedef struct _tdm_virtual_event_data tdm_virtual_event_data;
+
+typedef enum {
+       TDM_VIRTUAL_EVENT_TYPE_WAIT,
+       TDM_VIRTUAL_EVENT_TYPE_COMMIT,
+       TDM_VIRTUAL_EVENT_TYPE_VCOMMIT,
+} tdm_virtual_event_type;
+
+struct _tdm_virtual_data {
        tdm_display *dpy;
+       int hwc_mode;
 
        int pipe[2];
 
        struct list_head voutput_list;
        struct list_head output_list;
        struct list_head buffer_list;
-} tdm_virtual_data;
+};
 
-void tdm_virtual_display_destroy_output_list(tdm_virtual_data *virtual_data);
+struct _tdm_virtual_output_data {
+       struct list_head link;
+
+       /* data which are fixed at initializing */
+       tdm_virtual_data *virtual_data;
+       tdm_virtual_voutput_data *voutput_data;
+
+       char name[TDM_NAME_LEN]; /* output name */
+       uint32_t pipe;
+       tdm_output_type connector_type;
+       struct list_head layer_list;
+       tdm_virtual_layer_data *primary_layer;
+
+       tdm_output_dpms dpms;
+
+       /* not fixed data below */
+       tdm_output_vblank_handler vblank_func;
+       tdm_output_commit_handler commit_func;
+       void *commit_user_data;
+
+       tdm_output_conn_status status;
+       tdm_output_status_handler status_func;
+       void *status_user_data;
+
+       int mode_changed;
+       const tdm_output_mode *current_mode;
+
+       tdm_event_loop_source *timer;
+       unsigned int timer_waiting;
+       struct list_head timer_event_list;
+
+       /* hwc data */
+       int hwc_enable;
+       tdm_virtual_hwc_data *hwc_data;
+};
+
+struct _tdm_virtual_hwc_data {
+       tdm_virtual_hwc_window_data *target_hwc_window;
+
+       int need_validate;
+       int need_target_window;
+       int need_set_crtc;
+
+       int target_window_zpos;
 
+       tdm_virtual_output_data *output_data;
+       struct list_head hwc_window_list;
+
+       tdm_hwc_commit_handler commit_func;
+};
+
+struct _tdm_virtual_hwc_window_data {
+       struct list_head link;
+
+       tdm_virtual_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 _tdm_virtual_voutput_data {
+       struct list_head link;
+
+       /* data which are fixed at initializing */
+       tdm_virtual_data *virtual_data;
+       tdm_virtual_output_data *output_data;
+
+       char name[TDM_NAME_LEN]; /* output name */
+
+       tdm_voutput_commit_handler vcommit_func;
+
+       tdm_output_mode *output_modes;
+       int mode_count;
+
+       unsigned int mmwidth;
+       unsigned int mmheight;
+};
+
+struct _tdm_virtual_layer_data {
+       struct list_head link;
+
+       /* data which are fixed at initializing */
+       tdm_virtual_data *virtual_data;
+       tdm_virtual_output_data *output_data;
+       tdm_layer_capability capabilities;
+       int zpos;
+
+       /* not fixed data below */
+       tdm_info_layer info;
+       int info_changed;
+
+       tbm_surface_h display_buffer;
+       int display_buffer_changed;
+};
+
+struct _tdm_virtual_event_data {
+       struct list_head link;
+
+       tdm_virtual_event_type type;
+       tdm_virtual_output_data *output_data;
+       void *user_data;
+};
+
+void tdm_virtual_display_destroy_output_list(tdm_virtual_data *virtual_data);
+tdm_virtual_layer_data *virtual_output_data_get_layer_data(tdm_virtual_output_data *output_data, int layer_zpos);
+tdm_error    virtual_hwc_initailize_target_window(tdm_hwc *hwc_data, int width, int height);
 #endif /* _TDM_VIRTUAL_H_ */
index ea3f5af..89f0769 100644 (file)
@@ -4,98 +4,12 @@
 
 #include "tdm_virtual.h"
 
-typedef struct _tdm_virtual_output_data tdm_virtual_output_data;
-typedef struct _tdm_virtual_voutput_data tdm_virtual_voutput_data;
-typedef struct _tdm_virtual_layer_data tdm_virtual_layer_data;
-typedef struct _tdm_virtual_event_data tdm_virtual_event_data;
-
-typedef enum {
-       TDM_VIRTUAL_EVENT_TYPE_WAIT,
-       TDM_VIRTUAL_EVENT_TYPE_COMMIT,
-       TDM_VIRTUAL_EVENT_TYPE_VCOMMIT,
-} tdm_virtual_event_type;
-
-struct _tdm_virtual_event_data {
-       struct list_head link;
-
-       tdm_virtual_event_type type;
-       tdm_virtual_output_data *output_data;
-       void *user_data;
-};
-
-struct _tdm_virtual_output_data {
-       struct list_head link;
-
-       /* data which are fixed at initializing */
-       tdm_virtual_data *virtual_data;
-       tdm_virtual_voutput_data *voutput_data;
-
-       char name[TDM_NAME_LEN]; /* output name */
-       uint32_t pipe;
-       tdm_output_type connector_type;
-       struct list_head layer_list;
-       tdm_virtual_layer_data *primary_layer;
-
-       tdm_output_dpms dpms;
-
-       /* not fixed data below */
-       tdm_output_vblank_handler vblank_func;
-       tdm_output_commit_handler commit_func;
-       void *commit_user_data;
-
-       tdm_output_conn_status status;
-       tdm_output_status_handler status_func;
-       void *status_user_data;
-
-       int mode_changed;
-       const tdm_output_mode *current_mode;
-
-       tdm_event_loop_source *timer;
-       unsigned int timer_waiting;
-       struct list_head timer_event_list;
-};
-
-struct _tdm_virtual_voutput_data {
-       struct list_head link;
-
-       /* data which are fixed at initializing */
-       tdm_virtual_data *virtual_data;
-       tdm_virtual_output_data *output_data;
-
-       char name[TDM_NAME_LEN]; /* output name */
-
-       tdm_voutput_commit_handler vcommit_func;
-
-       tdm_output_mode *output_modes;
-       int mode_count;
-
-       unsigned int mmwidth;
-       unsigned int mmheight;
-};
-
-
-struct _tdm_virtual_layer_data {
-       struct list_head link;
-
-       /* data which are fixed at initializing */
-       tdm_virtual_data *virtual_data;
-       tdm_virtual_output_data *output_data;
-       tdm_layer_capability capabilities;
-       int zpos;
-
-       /* not fixed data below */
-       tdm_info_layer info;
-       int info_changed;
-
-       tbm_surface_h display_buffer;
-       int display_buffer_changed;
-};
-
 static void
 _tdm_virtual_display_cb_event(tdm_virtual_output_data *output_data, tdm_virtual_event_data *event_data,
                                                        unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec)
 {
        tdm_virtual_voutput_data *voutput_data = NULL;
+       tdm_virtual_hwc_data *hwc_data;
 
        switch (event_data->type) {
        case TDM_VIRTUAL_EVENT_TYPE_WAIT:
@@ -103,8 +17,20 @@ _tdm_virtual_display_cb_event(tdm_virtual_output_data *output_data, tdm_virtual_
                        output_data->vblank_func(output_data, sequence, tv_sec, tv_usec, event_data->user_data);
                break;
        case TDM_VIRTUAL_EVENT_TYPE_COMMIT:
-               if (output_data->commit_func)
-                       output_data->commit_func(output_data, sequence, tv_sec, tv_usec, event_data->user_data);
+               if (output_data->hwc_enable) {
+                       hwc_data = output_data->hwc_data;
+                       if (!hwc_data) {
+                               TDM_ERR("no hwc_data");
+                               break;
+                       }
+
+                       if (hwc_data->commit_func)
+                               hwc_data->commit_func(hwc_data, sequence,
+                                                                                tv_sec, tv_usec,
+                                                                                event_data->user_data);
+               } else
+                       if (output_data->commit_func)
+                               output_data->commit_func(output_data, sequence, tv_sec, tv_usec, event_data->user_data);
                break;
        case TDM_VIRTUAL_EVENT_TYPE_VCOMMIT:
                voutput_data = output_data->voutput_data;
@@ -343,6 +269,9 @@ virtual_output_get_capability(tdm_output *output, tdm_caps_output *caps)
 
        caps->prop_count = 0;
 
+       if (output_data->virtual_data->hwc_mode)
+               caps->capabilities |= TDM_OUTPUT_CAPABILITY_HWC;
+
        return TDM_ERROR_NONE;
 failed_get:
        memset(caps, 0, sizeof(tdm_caps_output));
@@ -361,6 +290,13 @@ virtual_output_get_layers(tdm_output *output,  int *count, tdm_error *error)
        RETURN_VAL_IF_FAIL(output_data, NULL);
        RETURN_VAL_IF_FAIL(count, NULL);
 
+       if (output_data->virtual_data->hwc_mode) {
+               TDM_INFO("layers aren't supported in HWC mode");
+               *count = 0;
+               ret = TDM_ERROR_NONE;
+               goto failed_get;
+       }
+
        *count = 0;
        LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link)
                (*count)++;
@@ -566,10 +502,20 @@ tdm_error
 virtual_output_set_mode(tdm_output *output, const tdm_output_mode *mode)
 {
        tdm_virtual_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->virtual_data->hwc_mode) {
+               ret = virtual_hwc_initailize_target_window(output_data->hwc_data, mode->hdisplay, mode->vdisplay);
+               if (ret != TDM_ERROR_NONE) {
+                       TDM_ERR("create target hwc window failed (%d)", ret);
+                       return ret;
+               }
+       }
+
        output_data->current_mode = mode;
        output_data->mode_changed = 1;
 
@@ -604,6 +550,45 @@ virtual_output_set_status_handler(tdm_output *output,
        return TDM_ERROR_NONE;
 }
 
+tdm_hwc *
+virtual_output_get_hwc(tdm_output *output, tdm_error *error)
+{
+       tdm_virtual_hwc_data *hwc_data = NULL;
+       tdm_virtual_output_data *output_data = output;
+
+       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_virtual_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;
+
+       if (error)
+               *error = TDM_ERROR_NONE;
+
+       return hwc_data;
+}
+
 tdm_error
 virtual_voutput_set_available_mode(tdm_voutput *voutput, const tdm_output_mode *modes, int count)
 {
@@ -875,6 +860,9 @@ virtual_display_voutput_create(tdm_backend_data *bdata, const char *name, tdm_er
 
        TDM_DBG("virtual output create(%s)(%p)(%p)", output_data->name, voutput_data, output_data);
 
+       if (output_data->virtual_data->hwc_mode)
+               output_data->hwc_enable = 1;
+
        return voutput_data;
 
 create_fail:
@@ -1005,3 +993,18 @@ virtual_voutput_commit_done(tdm_voutput *voutput)
        return TDM_ERROR_NONE;
 }
 
+tdm_virtual_layer_data *
+virtual_output_data_get_layer_data(tdm_virtual_output_data *output_data, int layer_zpos)
+{
+       tdm_virtual_layer_data *l = NULL;
+
+       RETURN_VAL_IF_FAIL(output_data, NULL);
+
+       LIST_FOR_EACH_ENTRY(l, &output_data->layer_list, link) {
+               if (l->zpos == layer_zpos)
+                       return l;
+       }
+
+       return NULL;
+}
+
diff --git a/backends/virtual/tdm_virtual_hwc.c b/backends/virtual/tdm_virtual_hwc.c
new file mode 100644 (file)
index 0000000..42031cc
--- /dev/null
@@ -0,0 +1,494 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <tdm_helper.h>
+#include "tdm_virtual.h"
+
+#define MIN_WIDTH      32
+
+#define NUM_LAYERS     1
+#define NUM_BUFFERS    3
+
+#define NUM_UI_LAYERS  1
+
+#define ZPOS_MAX       1
+#define ZPOS_0         0
+#define ZPOS_NONE      -999
+
+tbm_format hwc_window_video_formats[] = {
+       TBM_FORMAT_ARGB8888,
+       TBM_FORMAT_XRGB8888,
+};
+
+const char *
+_comp_to_str(tdm_hwc_window_composition composition_type)
+{
+       if (composition_type == TDM_HWC_WIN_COMPOSITION_CLIENT)
+               return "CLIENT";
+       else if (composition_type == TDM_HWC_WIN_COMPOSITION_DEVICE)
+               return "DEVICE";
+       else if (composition_type == TDM_HWC_WIN_COMPOSITION_CURSOR)
+               return "CURSOR";
+       else if (composition_type == TDM_HWC_WIN_COMPOSITION_VIDEO)
+               return "VIDEO";
+       else if (composition_type == TDM_HWC_WIN_COMPOSITION_NONE)
+               return "SKIP";
+
+       return "unknown";
+}
+
+static void
+_print_validate_result(tdm_virtual_hwc_data *hwc_data, tdm_hwc_window **composited_wnds, uint32_t num_wnds)
+{
+       tdm_virtual_hwc_window_data *hwc_window_data = NULL;
+       int i;
+
+       for (i = 0; i < num_wnds; i++) {
+               hwc_window_data = composited_wnds[i];
+               switch (hwc_window_data->validated_type) {
+               case TDM_HWC_WIN_COMPOSITION_CLIENT:
+                       TDM_DBG(" window(%p) %s -> %s : lzpos(%d) -- {%s} on TARGET WINDOW", hwc_window_data,
+                                       _comp_to_str(hwc_window_data->client_type),
+                                       _comp_to_str(hwc_window_data->validated_type),
+                                       hwc_data->target_hwc_window->lzpos,
+                                       hwc_window_data->name ? hwc_window_data->name : "NONE");
+                       break;
+               case TDM_HWC_WIN_COMPOSITION_DEVICE:
+               case TDM_HWC_WIN_COMPOSITION_VIDEO:
+               case TDM_HWC_WIN_COMPOSITION_CURSOR:
+               case TDM_HWC_WIN_COMPOSITION_NONE:
+                       TDM_DBG(" window(%p) %s -> %s : lzpos(%d) -- {%s}", hwc_window_data,
+                                       _comp_to_str(hwc_window_data->client_type),
+                                       _comp_to_str(hwc_window_data->validated_type),
+                                       hwc_window_data->lzpos,
+                                       hwc_window_data->name ? hwc_window_data->name : "NONE");
+                       break;
+               default:
+                       break;
+               }
+       }
+}
+
+static tbm_surface_queue_h
+_virtual_hwc_window_get_tbm_buffer_queue(tdm_hwc_window *hwc_window, tdm_error *error)
+{
+       tdm_virtual_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
+_virtual_hwc_layer_attach_window(tdm_virtual_layer_data *layer_data, tdm_virtual_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 = virtual_layer_unset_buffer(layer_data);
+               RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+       } else {
+               ret = virtual_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 = virtual_layer_set_buffer(layer_data, hwc_window_data->surface);
+               RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+       }
+
+       return ret;
+}
+
+static tdm_error
+_virtual_hwc_prepare_commit(tdm_virtual_hwc_data *hwc_data)
+{
+       tdm_virtual_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 = virtual_output_data_get_layer_data(hwc_data->output_data, hwc_data->target_hwc_window->lzpos);
+               _virtual_hwc_layer_attach_window(layer_data, hwc_data->target_hwc_window);
+               use_layers_zpos[hwc_data->target_hwc_window->lzpos] = 1;
+       }
+
+       /* unset the unused layers */
+       for (lzpos = 0; lzpos < NUM_LAYERS; lzpos++) {
+               if (use_layers_zpos[lzpos])
+                       continue;
+
+               layer_data = virtual_output_data_get_layer_data(hwc_data->output_data, lzpos);
+               if (!layer_data)
+                       continue;
+
+               _virtual_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
+_virtual_hwc_apply_policy(tdm_virtual_hwc_data *hwc_data , tdm_hwc_window **composited_wnds, uint32_t num_wnds)
+{
+       tdm_virtual_hwc_window_data *hwc_window_data = NULL;
+       tdm_virtual_hwc_window_data **composited_list = NULL;
+       int i = 0;
+
+       composited_list = (tdm_virtual_hwc_window_data **)composited_wnds;
+
+       /* initialize the validated_types */
+       LIST_FOR_EACH_ENTRY_REV(hwc_window_data, &hwc_data->hwc_window_list, link) {
+               if (hwc_window_data->validated_type != TDM_HWC_WIN_COMPOSITION_NONE)
+                       hwc_window_data->validated_type = TDM_HWC_WIN_COMPOSITION_NONE;
+       }
+
+       /* use the target_window to commit when there is no window. */
+       if (num_wnds == 0) {
+               hwc_data->need_target_window = 1;
+               hwc_data->target_hwc_window->lzpos = ZPOS_0;
+               return;
+       }
+
+       /* use onyl target_window */
+       for (i = 0; i < num_wnds; i++) {
+               composited_list[i]->validated_type = TDM_HWC_WIN_COMPOSITION_CLIENT;
+               composited_list[i]->lzpos = ZPOS_NONE;
+       }
+
+       hwc_data->need_target_window = 1;
+       hwc_data->target_hwc_window->lzpos = ZPOS_0;
+}
+
+static int
+_virtual_hwc_get_changed_number(tdm_virtual_hwc_data *hwc_data)
+{
+       int num = 0;
+       tdm_virtual_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 *
+_virtual_hwc_create_window(tdm_hwc *hwc, tdm_hwc_window_info *info, tdm_error *error)
+{
+       tdm_virtual_hwc_data *hwc_data = hwc;
+       tdm_virtual_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_virtual_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 *
+virtual_hwc_create_window(tdm_hwc *hwc, tdm_error *error)
+{
+       tdm_virtual_hwc_data *hwc_data = hwc;
+       tdm_virtual_hwc_window_data *hwc_window_data = NULL;
+
+       RETURN_VAL_IF_FAIL(hwc_data, NULL);
+
+       hwc_window_data = _virtual_hwc_create_window(hwc_data, NULL, error);
+       RETURN_VAL_IF_FAIL(hwc_window_data, NULL);
+
+       LIST_ADDTAIL(&hwc_window_data->link, &hwc_data->hwc_window_list);
+
+       TDM_DBG("hwc_window(%p) create", hwc_window_data);
+       if (error)
+               *error = TDM_ERROR_NONE;
+
+       return hwc_window_data;
+}
+
+tdm_error
+virtual_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
+virtual_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 = 0;
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+virtual_hwc_get_available_properties(tdm_hwc *hwc, const tdm_prop **props, int *count)
+{
+       tdm_virtual_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
+virtual_hwc_get_client_target_buffer_queue(tdm_hwc *hwc, tdm_error *error)
+{
+       tdm_virtual_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 = _virtual_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
+virtual_hwc_set_client_target_buffer(tdm_hwc *hwc, tbm_surface_h buffer, tdm_region damage)
+{
+       tdm_virtual_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);
+
+       TDM_INFO(" ==============Set Target Buffer Virtual=================================");
+
+       err = virtual_hwc_window_set_buffer(hwc_data->target_hwc_window, buffer);
+       RETURN_VAL_IF_FAIL(err == TDM_ERROR_NONE, err);
+
+       err = virtual_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
+virtual_hwc_validate(tdm_hwc *hwc, tdm_hwc_window **composited_wnds, uint32_t num_wnds, uint32_t *num_types)
+{
+       tdm_virtual_hwc_data *hwc_data = hwc;
+
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(num_types != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       TDM_DBG(" ==============Validate Virtual=================================");
+
+       _virtual_hwc_apply_policy(hwc_data, composited_wnds, num_wnds);
+
+       *num_types = _virtual_hwc_get_changed_number(hwc_data);
+
+       _print_validate_result(hwc_data, composited_wnds, num_wnds);
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+virtual_hwc_get_changed_composition_types(tdm_hwc *hwc, uint32_t *num_elements,
+                               tdm_hwc_window **hwc_wnds, tdm_hwc_window_composition *composition_types)
+{
+       tdm_virtual_hwc_data *hwc_data = hwc;
+       tdm_virtual_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 = _virtual_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
+virtual_hwc_accept_validation(tdm_hwc *hwc)
+{
+       tdm_virtual_hwc_data *hwc_data = hwc;
+       tdm_error ret = TDM_ERROR_NONE;
+
+       RETURN_VAL_IF_FAIL(hwc_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+       RETURN_VAL_IF_FAIL(hwc_data->output_data != NULL, TDM_ERROR_INVALID_PARAMETER);
+
+       TDM_DBG(" ==============Accept Changes Done Virtual=================================");
+
+       ret = _virtual_hwc_prepare_commit(hwc_data);
+       RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+virtual_hwc_commit(tdm_hwc *hwc, int sync, void *user_data)
+{
+       tdm_virtual_hwc_data *hwc_data = hwc;
+       tdm_virtual_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 Virtual=================================");
+
+       ret = virtual_output_commit(output_data, sync, user_data);
+       RETURN_VAL_IF_FAIL(ret == TDM_ERROR_NONE, ret);
+
+       return TDM_ERROR_NONE;
+}
+
+tdm_error
+virtual_hwc_set_commit_handler(tdm_hwc *hwc, tdm_hwc_commit_handler func)
+{
+       tdm_virtual_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
+virtual_hwc_initailize_target_window(tdm_hwc *hwc, int width, int height)
+{
+       tdm_hwc_window_info info = {0};
+       tdm_error ret = TDM_ERROR_NONE;
+       tdm_virtual_hwc_window_data *target_hwc_window;
+       tdm_virtual_hwc_data *hwc_data = hwc;
+
+       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 = _virtual_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)
+               virtual_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/backends/virtual/tdm_virtual_hwc.h b/backends/virtual/tdm_virtual_hwc.h
new file mode 100644 (file)
index 0000000..12bb05f
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef _TDM_VIRTUAL_HWC_H_
+#define _TDM_VIRTUAL_HWC_H_
+
+#include "tdm_virtual.h"
+
+tdm_error virtual_hwc_initailize_target_window(tdm_virtual_hwc_data *hwc_data, int width, int height);
+
+#endif /* _TDM_VIRTUAL_HWC_H_ */
diff --git a/backends/virtual/tdm_virtual_hwc_window.c b/backends/virtual/tdm_virtual_hwc_window.c
new file mode 100644 (file)
index 0000000..81a9094
--- /dev/null
@@ -0,0 +1,136 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "tdm_virtual.h"
+
+void
+virtual_hwc_window_destroy(tdm_hwc_window *hwc_window)
+{
+       tdm_virtual_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
+virtual_hwc_window_set_composition_type(tdm_hwc_window *hwc_window,
+                                                                       tdm_hwc_window_composition comp_type)
+{
+       tdm_virtual_hwc_window_data *hwc_window_data = hwc_window;
+       tdm_virtual_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
+virtual_hwc_window_set_buffer_damage(tdm_hwc_window *hwc_window, tdm_region damage)
+{
+       tdm_virtual_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
+virtual_hwc_window_set_info(tdm_hwc_window *hwc_window, tdm_hwc_window_info *info)
+{
+       tdm_virtual_hwc_window_data *hwc_window_data = hwc_window;
+       tdm_virtual_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
+virtual_hwc_window_set_buffer(tdm_hwc_window *hwc_window, tbm_surface_h surface)
+{
+       tdm_virtual_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
+virtual_hwc_window_set_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value value)
+{
+       tdm_virtual_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
+virtual_hwc_window_get_property(tdm_hwc_window *hwc_window, unsigned int id, tdm_value *value)
+{
+       tdm_virtual_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
+virtual_hwc_window_get_constraints(tdm_hwc_window *hwc_window, int *constraints)
+{
+       tdm_virtual_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
+virtual_hwc_window_set_name(tdm_hwc_window *hwc_window, const char *name)
+{
+       tdm_virtual_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;
+}
diff --git a/backends/virtual/tdm_virtual_hwc_window.h b/backends/virtual/tdm_virtual_hwc_window.h
new file mode 100644 (file)
index 0000000..e698090
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef _TDM_VIRTUAL_HWC_WINDOW_H_
+#define _TDM_VIRTUAL_HWC_WINDOW_H_
+
+#include "tdm_virtual.h"
+
+#endif /* _TDM_VIRTUAL_HWC_WINDOW_H_ */
index 12f6a2d..b0d1576 100644 (file)
@@ -159,7 +159,7 @@ tdm_backend_register_func_layer(tdm_display *dpy, tdm_func_layer *func_layer)
 EXTERN tdm_error
 tdm_backend_register_func_hwc(tdm_display *dpy, tdm_func_hwc *func_hwc)
 {
-       tdm_backend_module *module;
+//     tdm_backend_module *module;
 
        TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
 
@@ -168,10 +168,10 @@ tdm_backend_register_func_hwc(tdm_display *dpy, tdm_func_hwc *func_hwc)
        TDM_RETURN_VAL_IF_FAIL(func_hwc != NULL, TDM_ERROR_INVALID_PARAMETER);
 
        assert(private_display->current_module);
-
-       module = private_display->current_module->module_data;
-       if (_check_abi_version(module, 2, 0) < 0)
-               return TDM_ERROR_BAD_MODULE;
+// TODO : temp erase module check for virtual
+//     module = private_display->current_module->module_data;
+//     if (_check_abi_version(module, 2, 0) < 0)
+//             return TDM_ERROR_BAD_MODULE;
 
        private_display->current_module->func_hwc = *func_hwc;
 
@@ -181,7 +181,7 @@ tdm_backend_register_func_hwc(tdm_display *dpy, tdm_func_hwc *func_hwc)
 EXTERN tdm_error
 tdm_backend_register_func_hwc_window(tdm_display *dpy, tdm_func_hwc_window *func_hwc_window)
 {
-       tdm_backend_module *module;
+//     tdm_backend_module *module;
 
        TDM_RETURN_VAL_IF_FAIL(TDM_MUTEX_IS_LOCKED(), TDM_ERROR_OPERATION_FAILED);
 
@@ -190,10 +190,10 @@ tdm_backend_register_func_hwc_window(tdm_display *dpy, tdm_func_hwc_window *func
        TDM_RETURN_VAL_IF_FAIL(func_hwc_window != NULL, TDM_ERROR_INVALID_PARAMETER);
 
        assert(private_display->current_module);
-
-       module = private_display->current_module->module_data;
-       if (_check_abi_version(module, 2, 0) < 0)
-               return TDM_ERROR_BAD_MODULE;
+// TODO : temp erase module check for virtual
+//     module = private_display->current_module->module_data;
+//     if (_check_abi_version(module, 2, 0) < 0)
+//             return TDM_ERROR_BAD_MODULE;
 
        private_display->current_module->func_hwc_window = *func_hwc_window;
 
index 65f232c..f3537bc 100644 (file)
@@ -528,6 +528,8 @@ tdm_hwc_commit(tdm_hwc *hwc, int sync, tdm_hwc_commit_handler func, void *user_d
        tdm_private_module *private_module;
        tdm_func_hwc *func_hwc = NULL;
        tdm_private_hwc_commit_handler *hwc_commit_handler = NULL;
+       tdm_private_voutput *private_voutput = NULL;
+       tdm_private_voutput_commit_handler *voutput_commit_handler = NULL;
 
        HWC_FUNC_ENTRY();
 
@@ -558,6 +560,14 @@ tdm_hwc_commit(tdm_hwc *hwc, int sync, tdm_hwc_commit_handler func, void *user_d
        if (tdm_debug_module & TDM_DEBUG_COMMIT)
                TDM_INFO("hwc(%d) commit", private_hwc->index);
 
+       if (private_module == private_display->virtual_module) {
+               if (!private_output->private_voutput) {
+                       TDM_ERR("virtual module but don't have voutput");
+                       _pthread_mutex_unlock(&private_display->lock);
+                       return TDM_ERROR_BAD_MODULE;
+               }
+       }
+
        if (!private_hwc->regist_commit_cb) {
                private_hwc->regist_commit_cb = 1;
                ret = func_hwc->hwc_set_commit_handler(private_hwc->hwc_backend, _tdm_hwc_cb_commit);
@@ -595,6 +605,15 @@ tdm_hwc_commit(tdm_hwc *hwc, int sync, tdm_hwc_commit_handler func, void *user_d
        hwc_commit_handler->user_data = user_data;
        hwc_commit_handler->owner_tid = syscall(SYS_gettid);
 
+       if (private_module == private_display->virtual_module) {
+               private_voutput = private_output->private_voutput;
+
+               if (LIST_LENGTH(&private_voutput->voutput_commit_handler_list) != 0) {
+                       voutput_commit_handler = LIST_FIRST_ENTRY(&private_voutput->voutput_commit_handler_list, tdm_private_voutput_commit_handler, link);
+                       voutput_commit_handler->user_data = private_hwc->display_target_buffer;
+               }
+       }
+
        ret = func_hwc->hwc_commit(private_hwc->hwc_backend, sync, hwc_commit_handler);
        TDM_GOTO_IF_FAIL(ret == TDM_ERROR_NONE, commit_failed);