apply libtdm 22/60522/1 accepted/tizen/ivi/20160228.232153 accepted/tizen/mobile/20160228.232051 accepted/tizen/tv/20160228.232104 accepted/tizen/wearable/20160228.232137 submit/tizen/20160229.555555
authorBoram Park <boram1288.park@samsung.com>
Sat, 13 Feb 2016 05:24:59 +0000 (14:24 +0900)
committerBoram Park <boram1288.park@samsung.com>
Sun, 28 Feb 2016 22:36:45 +0000 (07:36 +0900)
Change-Id: I32186ffd4d5733eaf6f763251405a5459e85277d

13 files changed:
configure.ac
packaging/efl.spec
src/Makefile_Ecore_Drm.am
src/lib/ecore_drm/Ecore_Drm.h
src/lib/ecore_drm/ecore_drm_device.c
src/lib/ecore_drm/ecore_drm_display.c [new file with mode: 0644]
src/lib/ecore_drm/ecore_drm_fb.c
src/lib/ecore_drm/ecore_drm_logind.c
src/lib/ecore_drm/ecore_drm_output.c
src/lib/ecore_drm/ecore_drm_private.h
src/lib/ecore_drm/ecore_drm_sprites.c
src/modules/ecore_evas/engines/drm/ecore_evas_drm.c
src/modules/evas/engines/gl_drm/evas_outbuf.c

index ef32407..6c71e0e 100644 (file)
@@ -3233,6 +3233,14 @@ if test "x${have_extra_touch_event}" = "xyes";then
   AC_DEFINE_UNQUOTED([LIBINPUT_SUPPORT_EXTRA_TOUCH_EVENT], [1], [libinput support extra touch event])
 fi
 
+EFL_DEPEND_PKG([ECORE_DRM], [TDM], [libtdm >= "1.0.0"], [have_tdm="yes"], [have_tdm="no"])
+AC_MSG_CHECKING([Use TDM])
+AC_MSG_RESULT([${have_tdm}])
+if test "x${have_tdm}" = "xyes" ; then
+   EFL_DEPEND_PKG([ECORE_DRM], [GBM], [gbm])
+   AC_DEFINE_UNQUOTED(HAVE_TDM, 1, [Support for tizen display HAL])
+fi
+
 EFL_EVAL_PKGS([ECORE_DRM])
 
 # Check for ttrace
index 36aa471..2b1d797 100644 (file)
@@ -99,7 +99,9 @@ BuildRequires:  pkgconfig(xcb)
 BuildRequires:  pkgconfig(xcb-sync)
 BuildRequires:  pkgconfig(xcb-dri3)
 %endif
+BuildRequires:  pkgconfig(gbm)
 BuildRequires:  pkgconfig(libtbm)
+BuildRequires:  pkgconfig(libtdm)
 BuildRequires:  pkgconfig(libdrm)
 BuildRequires:  pkgconfig(wayland-client)
 BuildRequires:  pkgconfig(wayland-server)
index c8a1eef..ec399ec 100644 (file)
@@ -9,6 +9,7 @@ dist_installed_ecoredrmmainheaders_DATA = \
   lib/ecore_drm/Ecore_Drm.h
 
 lib_ecore_drm_libecore_drm_la_SOURCES = \
+lib/ecore_drm/ecore_drm_display.c \
 lib/ecore_drm/ecore_drm_sprites.c \
 lib/ecore_drm/ecore_drm_fb.c \
 lib/ecore_drm/ecore_drm_evdev.c \
index 303d97a..34cc352 100644 (file)
@@ -72,6 +72,8 @@ typedef struct _Ecore_Drm_Fb
    void *mmap;
    int w, h;
    Eina_Bool pending_flip : 1;
+   void *dev;
+   void *hal_buffer;
 } Ecore_Drm_Fb;
 
 struct _Ecore_Drm_Device
@@ -131,6 +133,8 @@ struct _Ecore_Drm_Device
 
    Eina_Bool active : 1;
    Eina_Bool left_handed : 1;
+
+   void *hal_display;
 };
 
 struct _Ecore_Drm_Event_Activate
@@ -179,6 +183,7 @@ typedef struct _Ecore_Drm_Output_Mode
    int width, height;
    unsigned int refresh;
    drmModeModeInfo info;
+   const void *hal_mode;
 } Ecore_Drm_Output_Mode;
 
 /* opaque structure to represent a drm output */
@@ -1025,6 +1030,10 @@ EAPI unsigned int ecore_drm_output_crtc_id_get(Ecore_Drm_Output *output);
 EAPI void ecore_drm_output_current_fb_info_set(Ecore_Drm_Output *output, unsigned int handle, int w, int h, unsigned int format);
 EAPI void ecore_drm_output_current_fb_info_get(Ecore_Drm_Output *output, unsigned int *handle, int *w, int *h, unsigned int *format);
 
+EAPI Ecore_Drm_Fb *ecore_drm_display_output_primary_layer_fb_get(Ecore_Drm_Output *output);
+EAPI void ecore_drm_display_fb_add(Ecore_Drm_Fb *fb);
+EAPI void ecore_drm_display_fb_remove(Ecore_Drm_Fb *fb);
+
 # ifdef __cplusplus
 }
 # endif
index 8477366..a6a6e7e 100644 (file)
@@ -10,6 +10,8 @@
        ((x) >= (xx)) && ((y) >= (yy)))
 
 static Eina_List *drm_devices;
+
+#ifndef HAVE_TDM
 static int flip_count = 0;
 
 static void 
@@ -93,6 +95,7 @@ _ecore_drm_device_cb_event(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
 
    return ECORE_CALLBACK_RENEW;
 }
+#endif
 
 #if 0
 static Eina_Bool 
@@ -328,6 +331,47 @@ ecore_drm_device_free(Ecore_Drm_Device *dev)
 EAPI Eina_Bool 
 ecore_drm_device_open(Ecore_Drm_Device *dev)
 {
+#ifdef HAVE_TDM
+   int events = 0;
+   drmVersionPtr ver;
+
+   /* check for valid device */
+   if ((!dev) || (!dev->drm.name)) return EINA_FALSE;
+
+   TRACE_EFL_BEGIN(Device_Open);
+
+   dev->drm.fd = -1;
+   if (!_ecore_drm_display_init(dev))
+     {
+        TRACE_EFL_END();
+        return EINA_FALSE;
+     }
+
+   if ((ver = drmGetVersion(ecore_drm_device_fd_get(dev))))
+     {
+        drmFreeVersion(ver);
+        dev->drm.fd = ecore_drm_device_fd_get(dev);
+     }
+
+   /* try to create xkb context */
+   if (!(dev->xkb_ctx = _ecore_drm_device_cached_context_get(0)))
+     {
+        ERR("Failed to create xkb context: %m");
+        TRACE_EFL_END();
+        return EINA_FALSE;
+     }
+
+   events = (EEZE_UDEV_EVENT_ADD | EEZE_UDEV_EVENT_REMOVE |
+             EEZE_UDEV_EVENT_CHANGE);
+
+   dev->watch =
+     eeze_udev_watch_add(EEZE_UDEV_TYPE_DRM, events,
+                         _ecore_drm_device_cb_output_event, dev);
+
+   TRACE_EFL_END();
+
+   return EINA_TRUE;
+#else
    uint64_t caps;
    int events = 0;
    drmVersionPtr ver;
@@ -405,6 +449,7 @@ ecore_drm_device_open(Ecore_Drm_Device *dev)
    /*   ecore_idle_enterer_add(_ecore_drm_device_cb_idle, dev); */
 
    return EINA_TRUE;
+#endif
 }
 
 EAPI Eina_Bool 
@@ -422,8 +467,14 @@ ecore_drm_device_close(Ecore_Drm_Device *dev)
    if (dev->drm.hdlr) ecore_main_fd_handler_del(dev->drm.hdlr);
    dev->drm.hdlr = NULL;
 
+#ifdef HAVE_TDM
+   /* when we use TDM, dev->drm.fd comes from TDM. It will close in TDM. */
+   dev->drm.fd = -1;
+#endif
    _ecore_drm_launcher_device_close(dev->drm.name, dev->drm.fd);
 
+   _ecore_drm_display_destroy(dev);
+
    /* reset device fd */
    dev->drm.fd = -1;
 
@@ -441,6 +492,12 @@ ecore_drm_device_master_get(Ecore_Drm_Device *dev)
 {
    drm_magic_t mag;
 
+#ifdef HAVE_TDM
+   drmVersionPtr ver = drmGetVersion(ecore_drm_device_fd_get(dev));
+   if (ver) drmFreeVersion(ver);
+   else return EINA_TRUE;
+#endif
+
    /* check for valid device */
    if ((!dev) || (dev->drm.fd < 0)) return EINA_FALSE;
 
@@ -455,6 +512,12 @@ ecore_drm_device_master_get(Ecore_Drm_Device *dev)
 EAPI Eina_Bool 
 ecore_drm_device_master_set(Ecore_Drm_Device *dev)
 {
+#ifdef HAVE_TDM
+   drmVersionPtr ver = drmGetVersion(ecore_drm_device_fd_get(dev));
+   if (ver) drmFreeVersion(ver);
+   else return EINA_TRUE;
+#endif
+
    /* check for valid device */
    if ((!dev) || (dev->drm.fd < 0)) return EINA_FALSE;
 
@@ -468,6 +531,12 @@ ecore_drm_device_master_set(Ecore_Drm_Device *dev)
 EAPI Eina_Bool 
 ecore_drm_device_master_drop(Ecore_Drm_Device *dev)
 {
+#ifdef HAVE_TDM
+   drmVersionPtr ver = drmGetVersion(ecore_drm_device_fd_get(dev));
+   if (ver) drmFreeVersion(ver);
+   else return EINA_TRUE;
+#endif
+
    /* check for valid device */
    if ((!dev) || (dev->drm.fd < 0)) return EINA_FALSE;
 
@@ -482,6 +551,11 @@ EAPI int
 ecore_drm_device_fd_get(Ecore_Drm_Device *dev)
 {
    EINA_SAFETY_ON_NULL_RETURN_VAL(dev, -1);
+
+#ifdef HAVE_TDM
+   return _ecore_drm_display_get_fd(dev);
+#endif
+
    return dev->drm.fd;
 }
 
@@ -510,6 +584,12 @@ ecore_drm_device_name_get(Ecore_Drm_Device *dev)
    /* check for valid device */
    EINA_SAFETY_ON_TRUE_RETURN_VAL((!dev) || (dev->drm.fd < 0), NULL);
 
+#ifdef HAVE_TDM
+   /* Do we have to get drm.name from TDM? drm.path also? possible?
+    * I guess no.
+    */
+#endif
+
    return dev->drm.name;
 }
 
diff --git a/src/lib/ecore_drm/ecore_drm_display.c b/src/lib/ecore_drm/ecore_drm_display.c
new file mode 100644 (file)
index 0000000..c5edc9a
--- /dev/null
@@ -0,0 +1,929 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef HAVE_TDM
+# include <tdm.h>
+
+#include "ecore_drm_private.h"
+
+typedef struct _Ecore_Drm_Hal_Display
+{
+   tdm_display *display;
+
+   int fd;
+   Ecore_Fd_Handler *hdlr;
+} Ecore_Drm_Hal_Display;
+
+typedef struct _Ecore_Drm_Hal_Output
+{
+   tdm_output *output;
+   tdm_layer *primary_layer;
+} Ecore_Drm_Hal_Output;
+
+static const char *conn_types[] =
+{
+   "None", "VGA", "DVI-I", "DVI-D", "DVI-A",
+   "Composite", "S-Video", "LVDS", "Component", "DIN",
+   "DisplayPort", "HDMI-A", "HDMI-B", "TV", "eDP", "Virtual",
+   "DSI",
+};
+
+static int fb_data_key = 0;
+static Eina_List *fb_list = NULL;
+
+static Eina_Bool
+_ecore_drm_display_output_mode_set_with_fb(Ecore_Drm_Output *output, Ecore_Drm_Output_Mode *mode, Ecore_Drm_Fb *fb, int x, int y);
+
+static void
+_ecore_drm_display_output_cb_commit(tdm_output *output EINA_UNUSED, unsigned int sequence EINA_UNUSED,
+                                    unsigned int tv_sec EINA_UNUSED, unsigned int tv_usec EINA_UNUSED,
+                                    void *user_data)
+{
+   Ecore_Drm_Pageflip_Callback *cb;
+   static int flip_count = 0;
+
+   if (!(cb = user_data)) return;
+
+   flip_count++;
+   if (flip_count < cb->count) return;
+
+   cb->dev->current = cb->dev->next;
+   cb->dev->next = NULL;
+
+   flip_count = 0;
+   if (cb->func) cb->func(cb->data);
+   free(cb);
+}
+
+static void
+_ecore_drm_display_output_cb_vblank(tdm_output *output EINA_UNUSED, unsigned int sequence EINA_UNUSED,
+                                    unsigned int tv_sec EINA_UNUSED, unsigned int tv_usec EINA_UNUSED,
+                                    void *user_data)
+{
+   Ecore_Drm_VBlank_Callback *cb;
+
+   if (!(cb = user_data)) return;
+   if (cb->func) cb->func(cb->data);
+   free(cb);
+}
+
+static Eina_Bool
+_ecore_drm_display_cb_event(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
+{
+   Ecore_Drm_Hal_Display *hal_display;
+   tdm_error ret;
+
+   if (!(hal_display = data)) return ECORE_CALLBACK_RENEW;
+
+   ret = tdm_display_handle_events(hal_display->display);
+   if (ret != TDM_ERROR_NONE)
+     ERR("tdm_display_handle_events failed");
+
+   return ECORE_CALLBACK_RENEW;
+}
+
+Eina_Bool
+_ecore_drm_display_init(Ecore_Drm_Device *dev)
+{
+   Ecore_Drm_Hal_Display *hal_display;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
+
+   if (dev->hal_display)
+      return EINA_TRUE;
+
+   hal_display = calloc(1, sizeof(Ecore_Drm_Hal_Display));
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hal_display, EINA_FALSE);
+
+   hal_display->display = tdm_display_init(NULL);
+   if (!hal_display->display)
+     goto fail_init;
+
+   hal_display->fd = -1;
+   tdm_display_get_fd(hal_display->display, &hal_display->fd);
+   if (hal_display->fd < 0)
+     goto fail_fd;
+
+   hal_display->hdlr =
+     ecore_main_fd_handler_add(hal_display->fd, ECORE_FD_READ,
+                               _ecore_drm_display_cb_event, hal_display, NULL, NULL);
+   if (!hal_display->hdlr)
+     goto fail_hdlr;
+
+   dev->hal_display = hal_display;
+
+   return EINA_TRUE;
+
+fail_hdlr:
+fail_fd:
+   tdm_display_deinit(hal_display->display);
+fail_init:
+   free(hal_display);
+   return EINA_FALSE;
+}
+
+void
+_ecore_drm_display_destroy(Ecore_Drm_Device *dev)
+{
+   Ecore_Drm_Hal_Display *hal_display;
+
+   if (!dev || !(hal_display = dev->hal_display)) return;
+
+   if (hal_display->hdlr) ecore_main_fd_handler_del(hal_display->hdlr);
+   tdm_display_deinit(hal_display->display);
+
+   free(hal_display);
+   dev->hal_display = NULL;
+}
+
+int
+_ecore_drm_display_get_fd(Ecore_Drm_Device *dev)
+{
+   Ecore_Drm_Hal_Display *hal_display;
+
+   if (!dev || !(hal_display = dev->hal_display)) return -1;
+
+   return hal_display->fd;
+}
+
+Ecore_Drm_Fb*
+_ecore_drm_display_fb_find(void *hal_buffer)
+{
+   Ecore_Drm_Fb *fb;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(fb_list, l, fb)
+     {
+        if (fb->hal_buffer == hal_buffer)
+          return fb;
+     }
+
+   return NULL;
+}
+
+Ecore_Drm_Fb*
+_ecore_drm_display_fb_find_with_id(unsigned int id)
+{
+   Ecore_Drm_Fb *fb;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(fb_list, l, fb)
+     {
+        if (fb->id == id)
+          return fb;
+     }
+
+   return NULL;
+}
+
+Ecore_Drm_Fb*
+_ecore_drm_display_fb_create(Ecore_Drm_Device *dev, int width, int height)
+{
+   Ecore_Drm_Fb *fb;
+   tbm_bo bo;
+   tbm_surface_info_s info;
+   static unsigned int id = 0;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(dev, NULL);
+   EINA_SAFETY_ON_TRUE_RETURN_VAL((width < 1) || (height < 1), NULL);
+   if (!(fb = calloc(1, sizeof(Ecore_Drm_Fb)))) return NULL;
+
+   fb->dev = dev;
+   fb->hal_buffer =
+      tbm_surface_internal_create_with_flags(width, height, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
+   if (!fb->hal_buffer)
+     {
+        ERR("Could not create hal buffer");
+        goto create_err;
+     }
+
+   bo = tbm_surface_internal_get_bo(fb->hal_buffer, 0);
+   if (!bo)
+     {
+        ERR("Could not get tbm bo");
+        goto get_bo;
+     }
+
+   tbm_bo_add_user_data(bo, (unsigned long)&fb_data_key, NULL);
+   tbm_bo_set_user_data(bo, (unsigned long)&fb_data_key, fb);
+
+   tbm_surface_get_info(fb->hal_buffer, &info);
+
+   fb->from_client = EINA_TRUE;
+   fb->id = ++id;
+   fb->hdl = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
+   fb->stride = info.planes[0].stride;
+   fb->size = info.size;
+   fb->w = info.width;
+   fb->h = info.height;
+   fb->fd = ecore_drm_device_fd_get(dev);
+   fb->mmap = info.planes[0].ptr;
+
+   memset(fb->mmap, 0, fb->size);
+
+   ecore_drm_display_fb_add(fb);
+
+   return fb;
+
+get_bo:
+   tbm_surface_destroy(fb->hal_buffer);
+create_err:
+   free(fb);
+   return NULL;
+}
+
+void
+_ecore_drm_display_fb_destroy(Ecore_Drm_Fb *fb)
+{
+   if ((!fb) || (!fb->mmap)) return;
+
+   ecore_drm_display_fb_remove(fb);
+
+   if (fb->hal_buffer) tbm_surface_destroy(fb->hal_buffer);
+
+   free(fb);
+}
+
+EAPI void
+ecore_drm_display_fb_add(Ecore_Drm_Fb *fb)
+{
+   fb_list = eina_list_append(fb_list, fb);
+}
+
+EAPI void
+ecore_drm_display_fb_remove(Ecore_Drm_Fb *fb)
+{
+   fb_list = eina_list_remove(fb_list, fb);
+}
+
+void
+_ecore_drm_display_fb_set(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb)
+{
+   Ecore_Drm_Output *output;
+   Eina_List *l;
+
+   EINA_SAFETY_ON_NULL_RETURN(dev);
+   EINA_SAFETY_ON_NULL_RETURN(fb);
+
+   if (dev->dumb[0])
+     {
+        if ((fb->w != dev->dumb[0]->w) || (fb->h != dev->dumb[0]->h))
+          {
+             /* we need to copy from fb to dev->dumb */
+             WRN("Trying to set a Framebuffer of improper size !!");
+             return;
+          }
+     }
+
+   if (!dev->next) dev->next = fb;
+   if (!dev->next) return;
+
+   EINA_LIST_FOREACH(dev->outputs, l, output)
+     {
+        int x = 0, y = 0;
+
+        if ((!output->enabled) || (!output->current_mode)) continue;
+
+        if (!output->cloned)
+          {
+             x = output->x;
+             y = output->y;
+          }
+
+        if ((!dev->current) ||
+            (dev->current->stride != dev->next->stride))
+          {
+             if (!_ecore_drm_display_output_mode_set_with_fb(output, output->current_mode, dev->next, x, y))
+               {
+                  ERR("Failed to set Mode %dx%d for Output %s: %m",
+                      output->current_mode->width, output->current_mode->height,
+                      output->name);
+               }
+
+             /* TODO: set dpms on ?? */
+          }
+     }
+}
+
+void
+_ecore_drm_display_fb_send(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb, Ecore_Drm_Pageflip_Cb func, void *data)
+{
+   Ecore_Drm_Output *output;
+   Eina_List *l;
+   Ecore_Drm_Pageflip_Callback *cb;
+   Ecore_Drm_Hal_Display *hal_display;
+   tdm_error ret;
+
+   EINA_SAFETY_ON_NULL_RETURN(dev);
+   EINA_SAFETY_ON_NULL_RETURN(fb);
+   EINA_SAFETY_ON_NULL_RETURN(func);
+
+   if (eina_list_count(dev->outputs) < 1) return;
+
+   if (fb->pending_flip) return;
+
+   hal_display = dev->hal_display;
+   EINA_SAFETY_ON_NULL_RETURN(hal_display);
+
+   if (!(cb = calloc(1, sizeof(Ecore_Drm_Pageflip_Callback))))
+     return;
+
+   cb->dev = dev;
+   cb->func = func;
+   cb->data = data;
+
+   EINA_LIST_FOREACH(dev->outputs, l, output)
+     if (output->enabled) cb->count++;
+
+   EINA_LIST_FOREACH(dev->outputs, l, output)
+     {
+        Ecore_Drm_Hal_Output *hal_output;
+        tbm_surface_h tdm_buffer;
+
+        if ((!output->enabled) || (!output->current_mode)) continue;
+
+        hal_output = output->hal_output;
+        if (!hal_output || !hal_output->output) continue;;
+
+        tdm_buffer = fb->hal_buffer;
+
+        tdm_layer_set_buffer(hal_output->primary_layer, tdm_buffer);
+        ret = tdm_output_commit(hal_output->output, 0, _ecore_drm_display_output_cb_commit, cb);
+        if (ret != TDM_ERROR_NONE)
+          {
+             ERR("Cannot commit crtc %u: %m", output->crtc_id);
+             continue;
+          }
+
+        fb->pending_flip = EINA_TRUE;
+     }
+
+   while (fb->pending_flip)
+     {
+        ret = tdm_display_handle_events(hal_display->display);
+        if (ret != TDM_ERROR_NONE)
+          {
+             ERR("tdm_display_handle_events failed");
+                free(cb);
+                break;
+          }
+     }
+}
+
+static Ecore_Drm_Output_Mode*
+_ecore_drm_display_output_mode_add(Ecore_Drm_Output *output, const tdm_output_mode *tdm_mode)
+{
+   Ecore_Drm_Output_Mode *mode;
+   uint64_t refresh;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(tdm_mode, NULL);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL((tdm_mode->htotal > 0), NULL);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL((tdm_mode->vtotal > 0), NULL);
+
+   /* try to allocate space for mode */
+   if (!(mode = calloc(1, sizeof(Ecore_Drm_Output_Mode))))
+     {
+        ERR("Could not allocate space for mode");
+        return NULL;
+     }
+
+   mode->flags = 0;
+   mode->width = tdm_mode->hdisplay;
+   mode->height = tdm_mode->vdisplay;
+
+   refresh = (tdm_mode->clock * 1000000LL / tdm_mode->htotal + tdm_mode->vtotal / 2) / tdm_mode->vtotal;
+   if (tdm_mode->flags & TDM_OUTPUT_MODE_FLAG_INTERLACE)
+     refresh *= 2;
+   if (tdm_mode->flags & TDM_OUTPUT_MODE_FLAG_DBLSCAN)
+     refresh /= 2;
+   if (tdm_mode->vscan > 1)
+     refresh /= tdm_mode->vscan;
+
+   mode->refresh = refresh;
+   mode->hal_mode = tdm_mode;
+
+   if (tdm_mode->type & TDM_OUTPUT_MODE_TYPE_PREFERRED)
+     mode->flags |= TDM_OUTPUT_MODE_TYPE_PREFERRED;
+
+   output->modes = eina_list_append(output->modes, mode);
+
+   return mode;
+}
+
+static Ecore_Drm_Output*
+_ecore_drm_display_output_find(Ecore_Drm_Device *dev, unsigned int crtc_id)
+{
+   Ecore_Drm_Output *output;
+   Eina_List *l;
+
+   EINA_LIST_FOREACH(dev->outputs, l, output)
+     {
+        if (output->crtc_id == crtc_id)
+          return output;
+     }
+
+   return NULL;
+}
+
+static Ecore_Drm_Output*
+_ecore_drm_display_output_create(Ecore_Drm_Device *dev, unsigned int crtc_id, int x, int y, Eina_Bool cloned)
+{
+   Ecore_Drm_Output *output = NULL;
+   Ecore_Drm_Hal_Output *hal_output = NULL;
+   Ecore_Drm_Hal_Display *hal_display = dev->hal_display;
+   unsigned int mmWidth = 0, mmHeight = 0, subpixel = 0;
+   tdm_output *tdm_output_obj;
+   tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
+   const char *type;
+   const tdm_output_mode *tdm_modes = NULL;
+   const tdm_output_mode *tdm_mode = NULL;
+   int i, count;
+   Ecore_Drm_Output_Mode *mode, *current = NULL, *preferred = NULL, *best = NULL;
+   Eina_List *l;
+   char temp[TDM_NAME_LEN];
+   const char *maker = NULL, *model = NULL, *name = NULL;
+
+   tdm_output_obj = tdm_display_get_output(hal_display->display, crtc_id, NULL);
+   if (!tdm_output_obj) return NULL;
+
+   tdm_output_get_conn_status(tdm_output_obj, &status);
+   if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) return NULL;
+
+   if (!(output = calloc(1, sizeof(Ecore_Drm_Output)))) return NULL;
+   if (!(hal_output = calloc(1, sizeof(Ecore_Drm_Hal_Output))))
+     goto fail_hal_output;
+
+   output->hal_output = hal_output;
+   hal_output->output = tdm_output_obj;
+
+   tdm_output_get_layer_count(hal_output->output, &count);
+   for (i = 0; i < count; i++)
+   {
+      tdm_layer *layer = tdm_output_get_layer(hal_output->output, i, NULL);
+      tdm_layer_capability capabilities = 0;
+      tdm_layer_get_capabilities(layer, &capabilities);
+      if (capabilities & TDM_LAYER_CAPABILITY_PRIMARY)
+      {
+         hal_output->primary_layer = layer;
+         break;
+      }
+   }
+
+   if (!hal_output->primary_layer)
+     {
+        ERR("couldn't find primary layer");
+        goto fail_primary_layer;
+     }
+
+   output->x = x;
+   output->y = y;
+   output->dev = dev;
+   output->cloned = cloned;
+
+   tdm_output_get_physical_size(hal_output->output, &mmWidth, &mmHeight);
+   output->phys_width = mmWidth;
+   output->phys_height = mmHeight;
+   output->subpixel = tdm_output_get_subpixel(hal_output->output, &subpixel);
+
+   tdm_output_get_model_info(hal_output->output, &maker, &model, &name);
+
+   output->make = eina_stringshare_add(maker);
+   output->model = eina_stringshare_add(model);
+   output->name = eina_stringshare_add(name);
+
+   output->connected = (status > 0);
+   output->enabled = output->connected;
+
+   tdm_output_get_output_type(hal_output->output, &output->conn_type);
+   if (output->conn_type < ALEN(conn_types))
+     type = conn_types[output->conn_type];
+   else
+     type = "UNKNOWN";
+
+   snprintf(temp, sizeof(temp), "%s-%d", type, 0);
+   eina_stringshare_replace(&output->name, temp);
+
+   output->crtc_id = crtc_id;
+   output->pipe = crtc_id;
+   dev->crtc_allocator |= (1 << output->crtc_id);
+   output->conn_id = crtc_id;
+   dev->conn_allocator |= (1 << output->conn_id);
+
+   output->crtc = NULL;
+   output->dpms = NULL;
+
+   tdm_output_get_mode(hal_output->output, &tdm_mode);
+
+   tdm_output_get_available_modes(hal_output->output, &tdm_modes, &count);
+   for (i = 0; i < count; i++)
+     if (!_ecore_drm_display_output_mode_add(output, &tdm_modes[i]))
+       goto fail_add_mode;
+
+   EINA_LIST_REVERSE_FOREACH(output->modes, l, mode)
+     {
+        if (mode->hal_mode == tdm_mode)
+          current = mode;
+        if (mode->flags & TDM_OUTPUT_MODE_TYPE_PREFERRED)
+          preferred = mode;
+        best = mode;
+     }
+
+   if (current) output->current_mode = current;
+   else if (preferred) output->current_mode = preferred;
+   else if (best) output->current_mode = best;
+
+   if (!output->current_mode) goto fail_current;
+
+   output->current_mode->flags |= TDM_OUTPUT_MODE_TYPE_DEFAULT;
+
+   dev->outputs = eina_list_append(dev->outputs, output);
+
+   /* NB: 'primary' output property is not supported in HW, so we need to
+    * implement it via software. As such, the First output which gets
+    * listed via libdrm will be assigned 'primary' until user changes
+    * it via config */
+   if (eina_list_count(dev->outputs) == 1)
+     output->primary = EINA_TRUE;
+
+   DBG("Created New Output At %d,%d", output->x, output->y);
+   DBG("\tCrtc Pos: %d %d", output->x, output->y);
+   DBG("\tCrtc: %d", output->crtc_id);
+   DBG("\tConn: %d", output->conn_id);
+   DBG("\tMake: %s", output->make);
+   DBG("\tModel: %s", output->model);
+   DBG("\tName: %s", output->name);
+   DBG("\tCloned: %d", output->cloned);
+   DBG("\tPrimary: %d", output->primary);
+
+   EINA_LIST_FOREACH(output->modes, l, mode)
+     {
+        DBG("\tAdded Mode: %dx%d@%.1f%s%s%s",
+            mode->width, mode->height, (mode->refresh / 1000.0),
+            (mode->flags & DRM_MODE_TYPE_PREFERRED) ? ", preferred" : "",
+            (mode->flags & DRM_MODE_TYPE_DEFAULT) ? ", current" : "",
+            (count == 0) ? ", built-in" : "");
+     }
+
+   _ecore_drm_output_event_send(output, EINA_TRUE);
+
+   return output;
+
+fail_current:
+fail_add_mode:
+   EINA_LIST_FREE(output->modes, mode)
+     free(mode);
+   dev->crtc_allocator &= ~(1 << output->crtc_id);
+   dev->conn_allocator &= ~(1 << output->conn_id);
+   eina_stringshare_del(output->name);
+   eina_stringshare_del(output->model);
+   eina_stringshare_del(output->make);
+fail_primary_layer:
+   free(hal_output);
+fail_hal_output:
+   free(output);
+   return NULL;
+}
+
+void
+_ecore_drm_display_output_free(Ecore_Drm_Output *output)
+{
+   Ecore_Drm_Output_Mode *mode;
+
+   /* check for valid output */
+   if (!output) return;
+
+   if (output->pending_flip)
+     {
+        output->pending_destroy = EINA_TRUE;
+        return;
+     }
+
+   _ecore_drm_output_event_send(output, EINA_FALSE);
+
+   output->dev->outputs = eina_list_remove(output->dev->outputs, output);
+
+   /* free modes */
+   EINA_LIST_FREE(output->modes, mode)
+     free(mode);
+
+   /* free strings */
+   if (output->name) eina_stringshare_del(output->name);
+   if (output->model) eina_stringshare_del(output->model);
+   if (output->make) eina_stringshare_del(output->make);
+
+   free(output);
+}
+
+Eina_Bool
+_ecore_drm_display_outputs_create(Ecore_Drm_Device *dev)
+{
+   Eina_Bool ret = EINA_TRUE;
+   Ecore_Drm_Output *output = NULL;
+   int i = 0, x = 0, y = 0, count = 0;
+   Ecore_Drm_Hal_Display *hal_display;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(dev, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(dev->hal_display, EINA_FALSE);
+
+   hal_display = dev->hal_display;
+
+   tdm_display_get_output_count(hal_display->display, &count);
+   if (!(dev->crtcs = calloc(count, sizeof(unsigned int))))
+     {
+        ERR("Could not allocate space for crtcs");
+        return EINA_FALSE;
+     }
+
+   dev->crtc_count = count;
+   for (i = 0; i < count; i++)
+      dev->crtcs[i] = i;
+
+   dev->min_width = 0;
+   dev->min_height = 0;
+   dev->max_width = UINT32_MAX;
+   dev->max_height = UINT32_MAX;
+
+   for (i = 0; i < count; i++)
+     {
+        if (!(output = _ecore_drm_display_output_create(dev, i, x, y, EINA_FALSE)))
+          continue;
+
+        x += output->current_mode->width;
+     }
+
+   ret = EINA_TRUE;
+   if (eina_list_count(dev->outputs) < 1)
+     ret = EINA_FALSE;
+
+   return ret;
+}
+
+void
+_ecore_drm_display_outputs_update(Ecore_Drm_Device *dev)
+{
+   Ecore_Drm_Hal_Display *hal_display;
+   int i, count = 0, x = 0, y = 0;
+   Ecore_Drm_Output *output;
+
+   EINA_SAFETY_ON_NULL_RETURN(dev);
+   EINA_SAFETY_ON_NULL_RETURN(dev->hal_display);
+
+   hal_display = dev->hal_display;
+
+   tdm_display_get_output_count(hal_display->display, &count);
+
+   /* find any new connects */
+   for (i = 0; i < count; i++)
+     {
+        tdm_output_conn_status status = TDM_OUTPUT_CONN_STATUS_DISCONNECTED;
+        tdm_output *tdm_output_obj;
+
+        tdm_output_obj = tdm_display_get_output(hal_display->display, i, NULL);
+        output = _ecore_drm_display_output_find(dev, i);
+
+        tdm_output_get_conn_status(tdm_output_obj, &status);
+
+        if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED)
+          {
+             if (output)
+                _ecore_drm_display_output_free(output);
+
+             continue;
+          }
+
+        /* already created */
+        if (output) continue;
+
+        if (eina_list_count(dev->outputs) > 0)
+          {
+             Ecore_Drm_Output *last;
+
+             if ((last = eina_list_last_data_get(dev->outputs)))
+               x = last->x + last->current_mode->width;
+             else
+               x = 0;
+          }
+        else
+          x = 0;
+
+        /* try to create a new output */
+        /* NB: hotplugged outputs will be set to cloned by default */
+        _ecore_drm_display_output_create(dev, i, x, y, EINA_TRUE);
+     }
+}
+
+void
+_ecore_drm_display_output_render_enable(Ecore_Drm_Output *output)
+{
+   Ecore_Drm_Device *dev;
+
+   EINA_SAFETY_ON_NULL_RETURN(output);
+   EINA_SAFETY_ON_NULL_RETURN(output->dev);
+   EINA_SAFETY_ON_NULL_RETURN(output->current_mode);
+
+   if (!output->enabled) return;
+
+   dev = output->dev;
+
+   if (!dev->current)
+     {
+        /* schedule repaint */
+        /* NB: this will trigger a redraw at next idle */
+        output->need_repaint = EINA_TRUE;
+        return;
+     }
+
+   ecore_drm_output_dpms_set(output, DRM_MODE_DPMS_ON);
+
+   _ecore_drm_display_output_mode_set_with_fb(output, output->current_mode,
+                                              dev->current, output->x, output->y);
+}
+
+void
+_ecore_drm_display_output_render_disable(Ecore_Drm_Output *output)
+{
+   EINA_SAFETY_ON_NULL_RETURN(output);
+
+   output->need_repaint = EINA_FALSE;
+   if (!output->enabled) return;
+
+   ecore_drm_output_dpms_set(output, DRM_MODE_DPMS_OFF);
+}
+
+void
+_ecore_drm_display_output_dpms_set(Ecore_Drm_Output *output, int level)
+{
+   Ecore_Drm_Hal_Output *hal_output;
+
+   EINA_SAFETY_ON_NULL_RETURN(output);
+   EINA_SAFETY_ON_NULL_RETURN(output->dev);
+
+   hal_output = output->hal_output;
+   EINA_SAFETY_ON_NULL_RETURN(hal_output->output);
+
+   tdm_output_set_dpms(hal_output->output, level);
+}
+
+unsigned int
+_ecore_drm_display_output_crtc_buffer_get(Ecore_Drm_Output *output)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output->dev, 0);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output->dev->current, 0);
+
+   return output->dev->current->id;
+}
+
+void
+_ecore_drm_display_output_size_get(Ecore_Drm_Device *dev EINA_UNUSED, int id, int *w, int *h)
+{
+   Ecore_Drm_Fb *fb;
+
+   fb = _ecore_drm_display_fb_find_with_id(id);
+
+   if (w) *w = fb->w;
+   if (h) *h = fb->h;
+}
+
+void
+_ecore_drm_display_output_crtc_size_get(Ecore_Drm_Output *output, int *width, int *height)
+{
+   if (width) *width = 0;
+   if (height) *height = 0;
+
+   EINA_SAFETY_ON_NULL_RETURN(output);
+   EINA_SAFETY_ON_NULL_RETURN(output->current_mode);
+
+   if (width) *width = output->current_mode->width;
+   if (height) *height = output->current_mode->height;
+}
+
+static Eina_Bool
+_ecore_drm_display_output_mode_set_with_fb(Ecore_Drm_Output *output, Ecore_Drm_Output_Mode *mode,
+                                           Ecore_Drm_Fb *fb, int x, int y)
+{
+   Ecore_Drm_Hal_Output *hal_output;
+   Eina_Bool ret = EINA_TRUE;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output->dev, EINA_FALSE);
+
+   hal_output = output->hal_output;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hal_output->output, EINA_FALSE);
+
+   output->x = x;
+   output->y = y;
+   output->current_mode = mode;
+
+   if (mode && fb)
+     {
+        tdm_info_layer info;
+        tbm_surface_h tdm_buffer = NULL;
+        tbm_surface_info_s buffer_info;
+
+        EINA_SAFETY_ON_NULL_RETURN_VAL(mode->hal_mode, EINA_FALSE);
+
+        tdm_buffer = fb->hal_buffer;
+
+        tbm_surface_get_info(tdm_buffer, &buffer_info);
+        info.src_config.size.h = buffer_info.planes[0].stride >> 2;
+        info.src_config.size.v = tbm_surface_get_height(tdm_buffer);
+        info.src_config.pos.x = output->x;
+        info.src_config.pos.y = output->y;
+        info.src_config.pos.w = mode->width;
+        info.src_config.pos.h = mode->height;
+        info.src_config.format = tbm_surface_get_format(tdm_buffer);
+        info.dst_pos.x = 0;
+        info.dst_pos.y = 0;
+        info.dst_pos.w = info.src_config.pos.w;
+        info.dst_pos.h = info.src_config.pos.h;
+        info.transform = 0;
+
+        tdm_output_set_mode(hal_output->output, mode->hal_mode);
+        tdm_layer_set_info(hal_output->primary_layer, &info);
+        tdm_layer_set_buffer(hal_output->primary_layer, tdm_buffer);
+        TRACE_OUTPUT_BEGIN(Mode_Set);
+        tdm_output_commit(hal_output->output, 0, NULL, NULL);
+        TRACE_OUTPUT_END();
+     }
+   else
+     {
+        tdm_layer_set_buffer(hal_output->primary_layer, NULL);
+        tdm_output_commit(hal_output->output, 0, NULL, NULL);
+     }
+
+   return ret;
+}
+
+Eina_Bool
+_ecore_drm_display_output_mode_set(Ecore_Drm_Output *output, Ecore_Drm_Output_Mode *mode, int x, int y)
+{
+   Ecore_Drm_Device *dev;
+   Ecore_Drm_Fb *fb = NULL;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output->dev, EINA_FALSE);
+
+   dev = output->dev;
+
+   if (dev->current) fb = dev->current;
+   else if (dev->next) fb = dev->next;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(fb, EINA_FALSE);
+
+   return _ecore_drm_display_output_mode_set_with_fb(output, mode, fb, x, y);
+}
+
+Eina_Bool
+_ecore_drm_display_output_possible_crtc_get(Ecore_Drm_Output *output EINA_UNUSED, unsigned int crtc EINA_UNUSED)
+{
+   return EINA_TRUE;
+}
+
+Eina_Bool
+_ecore_drm_display_output_wait_vblank(Ecore_Drm_Output *output, int interval, Ecore_Drm_VBlank_Cb func, void *data)
+{
+   Ecore_Drm_Hal_Output *hal_output;
+   Ecore_Drm_VBlank_Callback *cb;
+   tdm_error ret;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(func, EINA_FALSE);
+
+   hal_output = output->hal_output;
+   EINA_SAFETY_ON_NULL_RETURN_VAL(hal_output->output, EINA_FALSE);
+
+   if (!(cb = calloc(1, sizeof(Ecore_Drm_VBlank_Callback))))
+     return EINA_FALSE;
+
+   cb->output = output;
+   cb->func = func;
+   cb->data = data;
+
+   ret = tdm_output_wait_vblank(hal_output->output, interval, 0, _ecore_drm_display_output_cb_vblank, cb);
+   if (ret != TDM_ERROR_NONE)
+     {
+        ERR("Error Wait VBlank: %m");
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
+EAPI Ecore_Drm_Fb*
+ecore_drm_display_output_primary_layer_fb_get(Ecore_Drm_Output *output)
+{
+   Ecore_Drm_Device *dev;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(output->dev, NULL);
+
+   dev = output->dev;
+
+   if (dev->current) return dev->current;
+   else if (dev->next) return dev->next;
+
+   return NULL;
+}
+
+#endif
index f99a98e..2c7b631 100644 (file)
@@ -2,6 +2,11 @@
 # include <config.h>
 #endif
 
+#ifdef HAVE_TDM
+# include <tbm_surface.h>
+# include <tbm_surface_internal.h>
+#endif
+
 #include "ecore_drm_private.h"
 
 /**
@@ -11,6 +16,7 @@
  * 
  */
 
+#ifndef HAVE_TDM
 static Eina_Bool
 _ecore_drm_fb_create2(int fd, Ecore_Drm_Fb *fb)
 {
@@ -46,10 +52,14 @@ _ecore_drm_fb_create2(int fd, Ecore_Drm_Fb *fb)
 
    return EINA_TRUE;
 }
+#endif
 
 EAPI Ecore_Drm_Fb *
 ecore_drm_fb_create(Ecore_Drm_Device *dev, int width, int height)
 {
+#ifdef HAVE_TDM
+   return _ecore_drm_display_fb_create(dev, width, height);
+#else
    Ecore_Drm_Fb *fb;
    struct drm_mode_create_dumb carg;
    struct drm_mode_destroy_dumb darg;
@@ -119,11 +129,15 @@ add_err:
 create_err:
    free(fb);
    return NULL;
+#endif
 }
 
 EAPI void 
 ecore_drm_fb_destroy(Ecore_Drm_Fb *fb)
 {
+#ifdef HAVE_TDM
+   _ecore_drm_display_fb_destroy(fb);
+#else
    struct drm_mode_destroy_dumb darg;
 
    if ((!fb) || (!fb->mmap)) return;
@@ -134,6 +148,7 @@ ecore_drm_fb_destroy(Ecore_Drm_Fb *fb)
    darg.handle = fb->hdl;
    drmIoctl(fb->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &darg);
    free(fb);
+#endif
 }
 
 EAPI void
@@ -143,6 +158,13 @@ ecore_drm_fb_dirty(Ecore_Drm_Fb *fb, Eina_Rectangle *rects, unsigned int count)
 
    if ((!rects) || (!count)) return;
 
+#ifdef HAVE_TDM
+   drmVersionPtr ver = drmGetVersion(ecore_drm_device_fd_get(fb->dev));
+   if (ver) drmFreeVersion(ver);
+   else return;
+   /* FIXME: need to let TDM know the dirty rects? */
+#endif
+
 #ifdef DRM_MODE_FEATURE_DIRTYFB
    drmModeClip *clip;
    unsigned int i = 0;
@@ -169,6 +191,9 @@ ecore_drm_fb_dirty(Ecore_Drm_Fb *fb, Eina_Rectangle *rects, unsigned int count)
 EAPI void
 ecore_drm_fb_set(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb)
 {
+#ifdef HAVE_TDM
+   _ecore_drm_display_fb_set(dev, fb);
+#else
    Ecore_Drm_Output *output;
    Eina_List *l;
 
@@ -215,11 +240,15 @@ ecore_drm_fb_set(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb)
              /* TODO: set dpms on ?? */
           }
      }
+#endif
 }
 
 EAPI void
 ecore_drm_fb_send(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb, Ecore_Drm_Pageflip_Cb func, void *data)
 {
+#ifdef HAVE_TDM
+   _ecore_drm_display_fb_send(dev, fb, func, data);
+#else
    Ecore_Drm_Output *output;
    Eina_List *l;
    Ecore_Drm_Pageflip_Callback *cb;
@@ -274,4 +303,5 @@ ecore_drm_fb_send(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb, Ecore_Drm_Pageflip_Cb
              break;
           }
      }
+#endif
 }
index 833e945..8124b06 100644 (file)
@@ -158,7 +158,9 @@ _ecore_drm_logind_cb_activate(void *data, int type EINA_UNUSED, void *event)
      }
    else
      {
+#ifndef HAVE_TDM
         Ecore_Drm_Sprite *sprite;
+#endif
 
         /* disable inputs */
         EINA_LIST_FOREACH(dev->inputs, l, input)
@@ -168,9 +170,11 @@ _ecore_drm_logind_cb_activate(void *data, int type EINA_UNUSED, void *event)
         EINA_LIST_FOREACH(dev->outputs, l, output)
           _ecore_drm_output_render_disable(output);
 
+#ifndef HAVE_TDM
         /* disable sprites */
         EINA_LIST_FOREACH(dev->sprites, l, sprite)
           ecore_drm_sprites_fb_set(sprite, 0, 0);
+#endif
      }
 
    return ECORE_CALLBACK_PASS_ON;
index ae12dcd..252748d 100644 (file)
@@ -5,6 +5,7 @@
 #include "ecore_drm_private.h"
 #include <ctype.h>
 
+#ifndef HAVE_TDM
 #define EDID_DESCRIPTOR_ALPHANUMERIC_DATA_STRING 0xfe
 #define EDID_DESCRIPTOR_DISPLAY_PRODUCT_NAME 0xfc
 #define EDID_DESCRIPTOR_DISPLAY_PRODUCT_SERIAL_NUMBER 0xff
@@ -20,6 +21,7 @@ static const char *conn_types[] =
    "DisplayPort", "HDMI-A", "HDMI-B", "TV", "eDP", "Virtual",
    "DSI",
 };
+#endif
 
 EAPI int ECORE_DRM_EVENT_OUTPUT = 0;
 
@@ -34,7 +36,7 @@ _ecore_drm_output_event_free(void *data EINA_UNUSED, void *event)
    free(event);
 }
 
-static void
+void
 _ecore_drm_output_event_send(const Ecore_Drm_Output *output, Eina_Bool plug)
 {
    Ecore_Drm_Event_Output *e;
@@ -68,6 +70,7 @@ _ecore_drm_output_event_send(const Ecore_Drm_Output *output, Eina_Bool plug)
                    _ecore_drm_output_event_free, NULL);
 }
 
+#ifndef HAVE_TDM
 static drmModePropertyPtr
 _ecore_drm_output_property_get(int fd, drmModeConnectorPtr conn, const char *name)
 {
@@ -651,6 +654,7 @@ _ecore_drm_output_frame_finish(Ecore_Drm_Output *output)
 
    output->repaint_scheduled = EINA_FALSE;
 }
+#endif
 
 void 
 _ecore_drm_output_fb_release(Ecore_Drm_Output *output, Ecore_Drm_Fb *fb)
@@ -662,6 +666,7 @@ _ecore_drm_output_fb_release(Ecore_Drm_Output *output, Ecore_Drm_Fb *fb)
      ecore_drm_fb_destroy(fb);
 }
 
+#ifndef HAVE_TDM
 void 
 _ecore_drm_output_repaint_start(Ecore_Drm_Output *output)
 {
@@ -691,6 +696,7 @@ _ecore_drm_output_repaint_start(Ecore_Drm_Output *output)
 finish:
    _ecore_drm_output_frame_finish(output);
 }
+#endif
 
 static void
 _ecore_drm_output_delete(Ecore_Drm_Device *dev, Ecore_Drm_Output *output)
@@ -725,6 +731,9 @@ _ecore_drm_output_delete(Ecore_Drm_Device *dev, Ecore_Drm_Output *output)
 void
 _ecore_drm_outputs_update(Ecore_Drm_Device *dev)
 {
+#ifdef HAVE_TDM
+   _ecore_drm_display_outputs_update(dev);
+#else
    drmModeRes *res;
    drmModeConnector *conn;
    int i = 0, x = 0, y = 0;
@@ -798,11 +807,15 @@ next:
              _ecore_drm_output_delete(dev, destory_output);
           }
      }
+#endif
 }
 
 void
 _ecore_drm_output_render_enable(Ecore_Drm_Output *output)
 {
+#ifdef HAVE_TDM
+   _ecore_drm_display_output_render_enable(output);
+#else
    Ecore_Drm_Device *dev;
    Ecore_Drm_Output_Mode *mode;
    /* int x = 0, y = 0; */
@@ -839,19 +852,25 @@ _ecore_drm_output_render_enable(Ecore_Drm_Output *output)
         ERR("Failed to set Mode %dx%d for Output %s: %m",
             mode->width, mode->height, output->name);
      }
+#endif
 }
 
 void
 _ecore_drm_output_render_disable(Ecore_Drm_Output *output)
 {
+#ifdef HAVE_TDM
+   _ecore_drm_display_output_render_disable(output);
+#else
    EINA_SAFETY_ON_NULL_RETURN(output);
 
    output->need_repaint = EINA_FALSE;
    if (!output->enabled) return;
    ecore_drm_output_cursor_size_set(output, 0, 0, 0);
    ecore_drm_output_dpms_set(output, DRM_MODE_DPMS_OFF);
+#endif
 }
 
+#ifndef HAVE_TDM
 static void
 _ecore_drm_output_planes_get(Ecore_Drm_Device *dev)
 {
@@ -940,6 +959,7 @@ free_plane:
 
    drmModeFreePlaneResources(pres);
 }
+#endif
 
 /* public functions */
 
@@ -953,6 +973,15 @@ free_plane:
 EAPI Eina_Bool 
 ecore_drm_outputs_create(Ecore_Drm_Device *dev)
 {
+#ifdef HAVE_TDM
+   Eina_Bool ret;
+
+   TRACE_EFL_BEGIN(DRM OUTPUTS CREATE);
+   ret = _ecore_drm_display_outputs_create(dev);
+   TRACE_EFL_END();
+
+   return ret;
+#else
    Eina_Bool ret = EINA_TRUE;
    Ecore_Drm_Output *output = NULL;
    drmModeConnector *conn;
@@ -1030,14 +1059,20 @@ next:
    TRACE_EFL_END();
 
    return ret;
+#endif
 }
 
 EAPI void 
 ecore_drm_output_free(Ecore_Drm_Output *output)
 {
+#ifdef HAVE_TDM
+   _ecore_drm_display_output_free(output);
+#else
    _ecore_drm_output_free(output);
+#endif
 }
 
+#ifndef HAVE_TDM
 EAPI void 
 ecore_drm_output_cursor_size_set(Ecore_Drm_Output *output, int handle, int w, int h)
 {
@@ -1045,6 +1080,7 @@ ecore_drm_output_cursor_size_set(Ecore_Drm_Output *output, int handle, int w, in
    if (!output->enabled) return;
    drmModeSetCursor(output->dev->drm.fd, output->crtc_id, handle, w, h);
 }
+#endif
 
 EAPI Eina_Bool 
 ecore_drm_output_enable(Ecore_Drm_Output *output)
@@ -1078,6 +1114,7 @@ ecore_drm_output_fb_release(Ecore_Drm_Output *output, Ecore_Drm_Fb *fb)
    _ecore_drm_output_fb_release(output, fb);
 }
 
+#ifndef HAVE_TDM
 EAPI void 
 ecore_drm_output_repaint(Ecore_Drm_Output *output)
 {
@@ -1173,10 +1210,14 @@ err:
         dev->next = NULL;
      }
 }
+#endif
 
 EAPI void 
 ecore_drm_output_size_get(Ecore_Drm_Device *dev, int output, int *w, int *h)
 {
+#ifdef HAVE_TDM
+   _ecore_drm_display_output_size_get(dev, output, w, h);
+#else
    drmModeFB *fb;
 
    if (w) *w = 0;
@@ -1187,6 +1228,7 @@ ecore_drm_output_size_get(Ecore_Drm_Device *dev, int output, int *w, int *h)
    if (w) *w = fb->width;
    if (h) *h = fb->height;
    drmModeFreeFB(fb);
+#endif
 }
 
 EAPI void 
@@ -1277,6 +1319,10 @@ ecore_drm_output_make_get(Ecore_Drm_Output *output)
 EAPI void
 ecore_drm_output_dpms_set(Ecore_Drm_Output *output, int level)
 {
+#ifdef HAVE_TDM
+   _ecore_drm_display_output_dpms_set(output, level);
+   output->dpms_level = level;
+#else
    EINA_SAFETY_ON_NULL_RETURN(output);
    EINA_SAFETY_ON_NULL_RETURN(output->dev);
    EINA_SAFETY_ON_NULL_RETURN(output->dpms);
@@ -1284,6 +1330,7 @@ ecore_drm_output_dpms_set(Ecore_Drm_Output *output, int level)
    drmModeConnectorSetProperty(output->dev->drm.fd, output->conn_id,
                                output->dpms->prop_id, level);
    output->dpms_level = level;
+#endif
 }
 
 EAPI int
@@ -1294,6 +1341,7 @@ ecore_drm_output_dpms_get(Ecore_Drm_Output *output)
    return output->dpms_level;
 }
 
+#ifndef HAVE_TDM
 EAPI void
 ecore_drm_output_gamma_set(Ecore_Drm_Output *output, uint16_t size, uint16_t *r, uint16_t *g, uint16_t *b)
 {
@@ -1306,6 +1354,7 @@ ecore_drm_output_gamma_set(Ecore_Drm_Output *output, uint16_t size, uint16_t *r,
    if (drmModeCrtcSetGamma(output->dev->drm.fd, output->crtc_id, size, r, g, b))
      ERR("Failed to set output gamma: %m");
 }
+#endif
 
 EAPI unsigned int
 ecore_drm_output_crtc_id_get(Ecore_Drm_Output *output)
@@ -1318,6 +1367,9 @@ ecore_drm_output_crtc_id_get(Ecore_Drm_Output *output)
 EAPI unsigned int
 ecore_drm_output_crtc_buffer_get(Ecore_Drm_Output *output)
 {
+#ifdef HAVE_TDM
+   return _ecore_drm_display_output_crtc_buffer_get(output);
+#else
    drmModeCrtc *crtc;
    unsigned int id = 0;
 
@@ -1332,6 +1384,7 @@ ecore_drm_output_crtc_buffer_get(Ecore_Drm_Output *output)
    drmModeFreeCrtc(crtc);
 
    return id;
+#endif
 }
 
 EAPI unsigned int
@@ -1441,6 +1494,9 @@ ecore_drm_output_primary_set(Ecore_Drm_Output *output)
 EAPI void
 ecore_drm_output_crtc_size_get(Ecore_Drm_Output *output, int *width, int *height)
 {
+#ifdef HAVE_TDM
+   _ecore_drm_display_output_crtc_size_get(output, width, height);
+#else
    if (width) *width = 0;
    if (height) *height = 0;
 
@@ -1448,11 +1504,15 @@ ecore_drm_output_crtc_size_get(Ecore_Drm_Output *output, int *width, int *height
 
    if (width) *width = output->crtc->width;
    if (height) *height = output->crtc->height;
+#endif
 }
 
 EAPI Eina_Bool
 ecore_drm_output_possible_crtc_get(Ecore_Drm_Output *output, unsigned int crtc)
 {
+#ifdef HAVE_TDM
+   return _ecore_drm_display_output_possible_crtc_get(output, crtc);
+#else
    Ecore_Drm_Device *dev;
    drmModeRes *res;
    drmModeConnector *conn;
@@ -1518,11 +1578,15 @@ next:
    drmModeFreeResources(res);
 
    return ret;
+#endif
 }
 
 EAPI Eina_Bool
 ecore_drm_output_mode_set(Ecore_Drm_Output *output, Ecore_Drm_Output_Mode *mode, int x, int y)
 {
+#ifdef HAVE_TDM
+   return _ecore_drm_display_output_mode_set(output, mode, x, y);
+#else
    Ecore_Drm_Device *dev;
    Eina_Bool ret = EINA_TRUE;
    unsigned int buffer = 0;
@@ -1566,6 +1630,7 @@ ecore_drm_output_mode_set(Ecore_Drm_Output *output, Ecore_Drm_Output_Mode *mode,
      }
 
    return ret;
+#endif
 }
 
 EAPI void
@@ -1597,6 +1662,9 @@ ecore_drm_output_current_fb_info_get(Ecore_Drm_Output *output, unsigned int *han
 EAPI Eina_Bool
 ecore_drm_output_wait_vblank(Ecore_Drm_Output *output, int interval, Ecore_Drm_VBlank_Cb func, void *data)
 {
+#ifdef HAVE_TDM
+   return _ecore_drm_display_output_wait_vblank(output, interval, func, data);
+#else
    Ecore_Drm_Device *dev;
    Ecore_Drm_VBlank_Callback *cb;
    drmVBlank vbl;
@@ -1628,4 +1696,5 @@ ecore_drm_output_wait_vblank(Ecore_Drm_Output *output, int interval, Ecore_Drm_V
      }
 
    return EINA_TRUE;
+#endif
 }
index 09ddfbe..d46a642 100644 (file)
@@ -177,6 +177,8 @@ struct _Ecore_Drm_Output
    int curr_fb_w;
    int curr_fb_h;
    int curr_fb_format;
+
+   void *hal_output;
 };
 
 struct _Ecore_Drm_Seat
@@ -294,6 +296,31 @@ int _ecore_drm_launcher_device_flags_set(int fd, int flags);
 
 Eina_Bool _ecore_drm_tty_switch(Ecore_Drm_Device *dev, int activate_vt);
 
+#ifdef HAVE_TDM
+void _ecore_drm_output_event_send(const Ecore_Drm_Output *output, Eina_Bool plug);
+
+Eina_Bool _ecore_drm_display_init(Ecore_Drm_Device *dev);
+void _ecore_drm_display_destroy(Ecore_Drm_Device *dev);
+int _ecore_drm_display_get_fd(Ecore_Drm_Device *dev);
+Ecore_Drm_Fb* _ecore_drm_display_fb_find(void *hal_buffer);
+Ecore_Drm_Fb* _ecore_drm_display_fb_create(Ecore_Drm_Device *dev, int width, int height);
+void _ecore_drm_display_fb_destroy(Ecore_Drm_Fb *fb);
+void _ecore_drm_display_fb_set(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb);
+void _ecore_drm_display_fb_send(Ecore_Drm_Device *dev, Ecore_Drm_Fb *fb, Ecore_Drm_Pageflip_Cb func, void *data);
+Eina_Bool _ecore_drm_display_outputs_create(Ecore_Drm_Device *dev);
+void _ecore_drm_display_output_free(Ecore_Drm_Output *output);
+void _ecore_drm_display_outputs_update(Ecore_Drm_Device *dev);
+void _ecore_drm_display_output_render_enable(Ecore_Drm_Output *output);
+void _ecore_drm_display_output_render_disable(Ecore_Drm_Output *output);
+void _ecore_drm_display_output_dpms_set(Ecore_Drm_Output *output, int level);
+unsigned int _ecore_drm_display_output_crtc_buffer_get(Ecore_Drm_Output *output);
+void _ecore_drm_display_output_size_get(Ecore_Drm_Device *dev, int id, int *w, int *h);
+void _ecore_drm_display_output_crtc_size_get(Ecore_Drm_Output *output, int *width, int *height);
+Eina_Bool _ecore_drm_display_output_mode_set(Ecore_Drm_Output *output, Ecore_Drm_Output_Mode *mode, int x, int y);
+Eina_Bool _ecore_drm_display_output_possible_crtc_get(Ecore_Drm_Output *output, unsigned int crtc);
+Eina_Bool _ecore_drm_display_output_wait_vblank(Ecore_Drm_Output *output, int interval, Ecore_Drm_VBlank_Cb func, void *data);
+#endif
+
 Ecore_Drm_Evdev *_ecore_drm_evdev_device_create(Ecore_Drm_Seat *seat, struct libinput_device *device);
 void _ecore_drm_evdev_device_destroy(Ecore_Drm_Evdev *evdev);
 Eina_Bool _ecore_drm_evdev_event_process(struct libinput_event *event);
index d3fa71d..fcef5e6 100644 (file)
@@ -16,6 +16,7 @@
 EAPI Eina_Bool 
 ecore_drm_sprites_create(Ecore_Drm_Device *dev)
 {
+#ifndef HAVE_TDM
    drmModePlaneRes *res;
    drmModePlane *p;
    unsigned int i = 0;
@@ -56,6 +57,7 @@ ecore_drm_sprites_create(Ecore_Drm_Device *dev)
 
    /* free resources */
    drmModeFreePlaneResources(res);
+#endif
 
    return EINA_TRUE;
 }
@@ -63,6 +65,7 @@ ecore_drm_sprites_create(Ecore_Drm_Device *dev)
 EAPI void 
 ecore_drm_sprites_destroy(Ecore_Drm_Device *dev)
 {
+#ifndef HAVE_TDM
    Ecore_Drm_Sprite *sprite;
 
    /* check for valid device */
@@ -77,11 +80,13 @@ ecore_drm_sprites_destroy(Ecore_Drm_Device *dev)
 
         free(sprite);
      }
+#endif
 }
 
 EAPI void 
 ecore_drm_sprites_fb_set(Ecore_Drm_Sprite *sprite, int fb_id, int flags)
 {
+#ifndef HAVE_TDM
    EINA_SAFETY_ON_TRUE_RETURN((!sprite) || (!sprite->output));
 
    if (fb_id)
@@ -98,11 +103,13 @@ ecore_drm_sprites_fb_set(Ecore_Drm_Sprite *sprite, int fb_id, int flags)
                         sprite->output->crtc_id, 0, 0, 
                         0, 0, 0, 0, 0, 0, 0, 0);
      }
+#endif
 }
 
 EAPI Eina_Bool 
 ecore_drm_sprites_crtc_supported(Ecore_Drm_Output *output, unsigned int supported)
 {
+#ifndef HAVE_TDM
    Ecore_Drm_Device *dev;
    unsigned int c = 0;
 
@@ -115,6 +122,6 @@ ecore_drm_sprites_crtc_supported(Ecore_Drm_Output *output, unsigned int supporte
         if (dev->crtcs[c] != output->crtc_id) continue;
         if ((supported) && (1 << c)) return EINA_FALSE;
      }
-
+#endif
    return EINA_TRUE;
 }
index 791091f..7f9fc87 100644 (file)
@@ -549,12 +549,14 @@ _ecore_evas_drm_init(const char *device)
         goto dev_open_err;
      }
 
+#ifndef HAVE_TDM
    /* try to create sprites */
    if (!ecore_drm_sprites_create(dev))
      {
         ERR("Could not create sprites: %m");
         goto sprite_err;
      }
+#endif
 
    /* try to create outputs */
    if (!ecore_drm_outputs_create(dev))
@@ -579,7 +581,9 @@ output_err:
    ecore_drm_inputs_destroy(dev);
 input_err:
    ecore_drm_sprites_destroy(dev);
+#ifndef HAVE_TDM
 sprite_err:
+#endif
    ecore_drm_device_close(dev);
 dev_open_err:
    ecore_drm_launcher_disconnect(dev);
index 839bb9d..2de4544 100644 (file)
@@ -1,7 +1,12 @@
+#include "config.h"
 #include "evas_engine.h"
 #include <sys/mman.h>
 #include "../gl_common/evas_gl_define.h"
 
+#ifdef HAVE_TDM
+#include <gbm.h>
+#endif
+
 /* local variables */
 static Outbuf *_evas_gl_drm_window = NULL;
 static EGLContext context = EGL_NO_CONTEXT;
@@ -38,6 +43,16 @@ _evas_outbuf_gbm_surface_create(Outbuf *ob, int w, int h)
 static void
 _evas_outbuf_fb_cb_destroy(struct gbm_bo *bo, void *data)
 {
+#ifdef HAVE_TDM
+   Ecore_Drm_Fb *fb;
+
+   fb = data;
+   if (fb)
+     {
+        ecore_drm_display_fb_remove(fb);
+        free(fb);
+     }
+#else
    Ecore_Drm_Fb *fb;
 
    fb = data;
@@ -49,11 +64,36 @@ _evas_outbuf_fb_cb_destroy(struct gbm_bo *bo, void *data)
         drmModeRmFB(gbm_device_get_fd(gbm), fb->id);
         free(fb);
      }
+#endif
 }
 
 static Ecore_Drm_Fb *
 _evas_outbuf_fb_get(Ecore_Drm_Device *dev, struct gbm_bo *bo)
 {
+#ifdef HAVE_TDM
+   int ret;
+   Ecore_Drm_Fb *fb;
+   static unsigned int id = 0;
+
+   fb = gbm_bo_get_user_data(bo);
+   if (fb) return fb;
+
+   if (!(fb = calloc(1, sizeof(Ecore_Drm_Fb)))) return NULL;
+
+   fb->id = ++id;
+   fb->w = gbm_bo_get_width(bo);
+   fb->h = gbm_bo_get_height(bo);
+   fb->hdl = gbm_bo_get_handle(bo).u32;
+   fb->stride = gbm_bo_get_stride(bo);
+   fb->size = fb->stride * fb->h;
+   fb->hal_buffer = gbm_tbm_get_surface(bo);
+
+   gbm_bo_set_user_data(bo, fb, _evas_outbuf_fb_cb_destroy);
+
+   ecore_drm_display_fb_add(fb);
+
+   return fb;
+#else
    int ret;
    Ecore_Drm_Fb *fb;
    uint32_t format;
@@ -87,6 +127,7 @@ _evas_outbuf_fb_get(Ecore_Drm_Device *dev, struct gbm_bo *bo)
    gbm_bo_set_user_data(bo, fb, _evas_outbuf_fb_cb_destroy);
 
    return fb;
+#endif
 }
 
 static void