raster pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=aaefbaa43ebea08ecd67732a785bf89c3b7f847e

commit aaefbaa43ebea08ecd67732a785bf89c3b7f847e
Author: Carsten Haitzler (Rasterman) <[email protected]>
Date:   Tue Jul 29 20:00:53 2014 +0900

    ecore_x - vsync  fix drm support to work again
    
    due to mesa changes to hide dri2 symbols, i have had to work on a fix
    that makes this work again by going right to drm. now it works and
    animators shoudl be vsynced on drm drivers if possible (only 1 card -
    use card 0). already existing nvidia solution that uses a lot more
    memory is there. others - no support. timers only
---
 src/lib/ecore_x/xlib/ecore_x_image.c |  15 ++-
 src/lib/ecore_x/xlib/ecore_x_vsync.c | 252 ++++++++++++++++-------------------
 2 files changed, 123 insertions(+), 144 deletions(-)

diff --git a/src/lib/ecore_x/xlib/ecore_x_image.c 
b/src/lib/ecore_x/xlib/ecore_x_image.c
index 6188cb0..6dfe931 100644
--- a/src/lib/ecore_x/xlib/ecore_x_image.c
+++ b/src/lib/ecore_x/xlib/ecore_x_image.c
@@ -86,7 +86,7 @@ _ecore_x_image_error_handler(Display *d EINA_UNUSED, 
XErrorEvent *ev)
    return 0;
 }
 
-static void
+int
 _ecore_x_image_shm_check(void)
 {
    XErrorHandler ph;
@@ -94,12 +94,12 @@ _ecore_x_image_shm_check(void)
    XImage *xim;
 
    if (_ecore_x_image_shm_can != -1)
-     return;
+     return _ecore_x_image_shm_can;
 
    if (!XShmQueryExtension(_ecore_x_disp))
      {
         _ecore_x_image_shm_can = 0;
-        return;
+        return _ecore_x_image_shm_can;
      }
    
    XSync(_ecore_x_disp, False);
@@ -116,7 +116,7 @@ _ecore_x_image_shm_check(void)
    if (!xim)
      {
         _ecore_x_image_shm_can = 0;
-        return;
+        return _ecore_x_image_shm_can;
      }
 
    shminfo.shmid = shmget(IPC_PRIVATE, xim->bytes_per_line * xim->height,
@@ -126,7 +126,7 @@ _ecore_x_image_shm_check(void)
         ERR("%s", strerror(errno));
         XDestroyImage(xim);
         _ecore_x_image_shm_can = 0;
-        return;
+        return _ecore_x_image_shm_can;
      }
 
    shminfo.readOnly = False;
@@ -137,7 +137,7 @@ _ecore_x_image_shm_check(void)
      {
         XDestroyImage(xim);
         _ecore_x_image_shm_can = 0;
-        return;
+        return _ecore_x_image_shm_can;
      }
 
    ph = XSetErrorHandler((XErrorHandler)_ecore_x_image_error_handler);
@@ -153,7 +153,7 @@ _ecore_x_image_shm_check(void)
         shmdt(shminfo.shmaddr);
         shmctl(shminfo.shmid, IPC_RMID, 0);
         _ecore_x_image_shm_can = 0;
-        return;
+        return _ecore_x_image_shm_can;
      }
 
    XShmDetach(_ecore_x_disp, &shminfo);
@@ -162,6 +162,7 @@ _ecore_x_image_shm_check(void)
    shmctl(shminfo.shmid, IPC_RMID, 0);
 
    _ecore_x_image_shm_can = 1;
+   return _ecore_x_image_shm_can;
 }
 
 struct _Ecore_X_Image
diff --git a/src/lib/ecore_x/xlib/ecore_x_vsync.c 
b/src/lib/ecore_x/xlib/ecore_x_vsync.c
index a228e9e..7aed4be 100644
--- a/src/lib/ecore_x/xlib/ecore_x_vsync.c
+++ b/src/lib/ecore_x/xlib/ecore_x_vsync.c
@@ -16,20 +16,19 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 
-#define ECORE_X_VSYNC_DRI2 1
+#define ECORE_X_VSYNC_DRM 1
 
 static Ecore_X_Window vsync_root = 0;
 
+int _ecore_x_image_shm_check(void);
 
 
 
 
-#ifdef ECORE_X_VSYNC_DRI2
+#ifdef ECORE_X_VSYNC_DRM
 // relevant header bits of dri/drm inlined here to avoid needing external
 // headers to build
 /// drm
-typedef unsigned int drm_magic_t;
-
 typedef enum
 {
    DRM_VBLANK_ABSOLUTE = 0x00000000,
@@ -81,49 +80,24 @@ typedef struct _drmEventContext
 } drmEventContext;
 
 static int (*sym_drmClose)(int fd) = NULL;
-static int (*sym_drmGetMagic)(int fd,
-                              drm_magic_t *magic) = NULL;
 static int (*sym_drmWaitVBlank)(int fd,
                                 drmVBlank *vbl) = NULL;
 static int (*sym_drmHandleEvent)(int fd,
                                  drmEventContext *evctx) = NULL;
-
-//// dri
-
-static Bool (*sym_DRI2QueryExtension)(Display *display,
-                                      int *eventBase,
-                                      int *errorBase) = NULL;
-static Bool (*sym_DRI2QueryVersion)(Display *display,
-                                    int *major,
-                                    int *minor) = NULL;
-static Bool (*sym_DRI2Connect)(Display *display,
-                               XID window,
-                               char **driverName,
-                               char **deviceName) = NULL;
-static Bool (*sym_DRI2Authenticate)(Display *display,
-                                    XID window,
-                                    drm_magic_t magic) = NULL;
-
-//// dri/drm data needed
-static int dri2_event = 0;
-static int dri2_error = 0;
-static int dri2_major = 0;
-static int dri2_minor = 0;
-static char *device_name = 0;
-static char *driver_name = 0;
-static drm_magic_t drm_magic;
-
 static int drm_fd = -1;
 static int drm_event_is_busy = 0;
 static int drm_animators_interval = 1;
 static drmEventContext drm_evctx;
 static Ecore_Fd_Handler *dri_drm_fdh = NULL;
+static Ecore_Timer *_drm_fail_timer = NULL;
+static double _drm_fail_time = 0.1;
+static double _drm_fail_time2 = 1.0 / 60.0;
+static int _drm_fail_count = 0;
 
-static void *dri_lib = NULL;
 static void *drm_lib = NULL;
 
 static Eina_Bool
-_dri_drm_tick_schedule(void)
+_drm_tick_schedule(void)
 {
    drmVBlank vbl;
 
@@ -135,35 +109,72 @@ _dri_drm_tick_schedule(void)
 }
 
 static void
-_dri_drm_tick_begin(void *data EINA_UNUSED)
+_drm_tick_begin(void *data EINA_UNUSED)
 {
    drm_event_is_busy = 1;
-   _dri_drm_tick_schedule();
+   _drm_tick_schedule();
 }
 
 static void
-_dri_drm_tick_end(void *data EINA_UNUSED)
+_drm_tick_end(void *data EINA_UNUSED)
 {
+   if (_drm_fail_timer)
+     {
+        ecore_timer_del(_drm_fail_timer);
+        _drm_fail_timer = NULL;
+     }
    drm_event_is_busy = 0;
 }
 
-static void
-_dri_drm_vblank_handler(int fd EINA_UNUSED,
-                        unsigned int frame EINA_UNUSED,
-                        unsigned int sec EINA_UNUSED,
-                        unsigned int usec EINA_UNUSED,
-                        void *data EINA_UNUSED)
+static Eina_Bool
+_drm_fail_cb(void *data EINA_UNUSED)
 {
    if (drm_event_is_busy)
      {
-        // XXX: set looptime
+        _drm_fail_count++;
+        DBG("VSYNC FAIL %i %3.8f", _drm_fail_count, ecore_loop_time_get());
         ecore_animator_custom_tick();
-        _dri_drm_tick_schedule();
+        _drm_tick_schedule();
+        if (_drm_fail_count == 10)
+          {
+             _drm_fail_timer = ecore_timer_add(_drm_fail_time2, _drm_fail_cb, 
NULL);
+             return EINA_FALSE;
+          }
+     }
+   return EINA_TRUE;
+}
+
+static void
+_drm_vblank_handler(int fd EINA_UNUSED,
+                    unsigned int frame,
+                    unsigned int sec,
+                    unsigned int usec,
+                    void *data EINA_UNUSED)
+{
+   if (drm_event_is_busy)
+     {
+        double tim;
+        static double ptim = 0.0;
+        static unsigned int pframe = 0;
+
+        if (pframe != frame)
+          {
+             tim = (double)sec + ((double)usec / 1000000);
+             DBG("VSYNC %1.8f [%i] = delt %1.8f\n", tim, frame - pframe, tim - 
ptim);
+             ecore_loop_time_set(tim);
+             ecore_animator_custom_tick();
+             _drm_tick_schedule();
+             pframe = frame;
+             ptim = tim;
+             if (_drm_fail_timer) ecore_timer_del(_drm_fail_timer);
+             _drm_fail_timer = ecore_timer_add(_drm_fail_time, _drm_fail_cb, 
NULL);
+             _drm_fail_count = 0;
+          }
      }
 }
 
 static Eina_Bool
-_dri_drm_cb(void *data EINA_UNUSED,
+_drm_cb(void *data EINA_UNUSED,
             Ecore_Fd_Handler *fd_handler EINA_UNUSED)
 {
    sym_drmHandleEvent(drm_fd, &drm_evctx);
@@ -175,7 +186,7 @@ _dri_drm_cb(void *data EINA_UNUSED,
 // gl/dri/drm etc. world. and handle graceful failure at runtime not
 // compile time
 static int
-_dri_drm_link(void)
+_drm_link(void)
 {
    const char *drm_libs[] =
    {
@@ -185,30 +196,16 @@ _dri_drm_link(void)
       "libdrm.so",
       NULL,
    };
-   const char *dri_libs[] =
-   {
-      "libdri2.so.2",
-      "libdri2.so.1",
-      "libdri2.so.0",
-      "libdri2.so",
-      "libGL.so.4",
-      "libGL.so.3",
-      "libGL.so.2",
-      "libGL.so.1",
-      "libGL.so.0",
-      "libGL.so",
-      NULL,
-   };
    int i, fail;
-#define SYM(lib, xx)                            \
-  do {                                          \
-       sym_ ## xx = dlsym(lib, #xx);            \
-       if (!(sym_ ## xx)) {                     \
-            fail = 1;                           \
-         }                                      \
-    } while (0)
-
-   if (dri_lib) return 1;
+#define SYM(lib, xx)                         \
+   do {                                      \
+      sym_ ## xx = dlsym(lib, #xx);          \
+      if (!(sym_ ## xx)) {                   \
+         fail = 1;                           \
+      }                                      \
+   } while (0)
+
+   if (drm_lib) return 1;
    for (i = 0; drm_libs[i]; i++)
      {
         drm_lib = dlopen(drm_libs[i], RTLD_LOCAL | RTLD_LAZY);
@@ -227,60 +224,31 @@ _dri_drm_link(void)
           }
      }
    if (!drm_lib) return 0;
-   for (i = 0; dri_libs[i]; i++)
-     {
-        dri_lib = dlopen(dri_libs[i], RTLD_LOCAL | RTLD_LAZY);
-        if (dri_lib)
-          {
-             fail = 0;
-             SYM(dri_lib, DRI2QueryExtension);
-             SYM(dri_lib, DRI2QueryVersion);
-             SYM(dri_lib, DRI2Connect);
-             SYM(dri_lib, DRI2Authenticate);
-             if (fail)
-               {
-                  dlclose(dri_lib);
-                  dri_lib = NULL;
-               }
-             else break;
-          }
-     }
-   if (!dri_lib)
-     {
-        dlclose(drm_lib);
-        drm_lib = NULL;
-        return 0;
-     }
    return 1;
 }
 
 static int
-_dri_drm_init(void)
+_drm_init(void)
 {
-   if (!sym_DRI2QueryExtension(_ecore_x_disp, &dri2_event, &dri2_error))
-     return 0;
-   if (!sym_DRI2QueryVersion(_ecore_x_disp, &dri2_major, &dri2_minor))
-     return 0;
-   if (dri2_major < 2)
-     return 0;
-   if (!sym_DRI2Connect(_ecore_x_disp, vsync_root, &driver_name, &device_name))
-     return 0;
-   drm_fd = open(device_name, O_RDWR);
-   if (drm_fd < 0)
-     return 0;
-   sym_drmGetMagic(drm_fd, &drm_magic);
-   if (!sym_DRI2Authenticate(_ecore_x_disp, vsync_root, drm_magic))
+   struct stat st;
+   char buf[512];
+
+   snprintf(buf, sizeof(buf), "/dev/dri/card1");
+   if (stat(buf, &st) == 0)
      {
-        close(drm_fd);
-        drm_fd = -1;
+        // XXX: 2 dri cards - ambiguous. unknown device for screen
         return 0;
      }
+   snprintf(buf, sizeof(buf), "/dev/dri/card0");
+   if (stat(buf, &st) != 0) return 0;
+   drm_fd = open(buf, O_RDWR);
+   if (drm_fd < 0) return 0;
    memset(&drm_evctx, 0, sizeof(drm_evctx));
    drm_evctx.version = DRM_EVENT_CONTEXT_VERSION;
-   drm_evctx.vblank_handler = _dri_drm_vblank_handler;
+   drm_evctx.vblank_handler = _drm_vblank_handler;
    drm_evctx.page_flip_handler = NULL;
 
-   if (!_dri_drm_tick_schedule())
+   if (!_drm_tick_schedule())
      {
         close(drm_fd);
         drm_fd = -1;
@@ -288,7 +256,7 @@ _dri_drm_init(void)
      }
 
    dri_drm_fdh = ecore_main_fd_handler_add(drm_fd, ECORE_FD_READ,
-                                           _dri_drm_cb, NULL, NULL, NULL);
+                                           _drm_cb, NULL, NULL, NULL);
    if (!dri_drm_fdh)
      {
         close(drm_fd);
@@ -299,7 +267,7 @@ _dri_drm_init(void)
 }
 
 static void
-_dri_drm_shutdown(void)
+_drm_shutdown(void)
 {
    if (drm_fd >= 0)
      {
@@ -311,36 +279,41 @@ _dri_drm_shutdown(void)
         ecore_main_fd_handler_del(dri_drm_fdh);
         dri_drm_fdh = NULL;
      }
+   if (_drm_fail_timer)
+     {
+        ecore_timer_del(_drm_fail_timer);
+        _drm_fail_timer = NULL;
+     }
 }
 
 static Eina_Bool
-_dri_animator_tick_source_set(void)
+_drm_animator_tick_source_set(void)
 {
    if (vsync_root)
      {
-        if (!_dri_drm_link())
+        if (!_drm_link())
           {
              ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
              return EINA_FALSE;
           }
-        _dri_drm_shutdown();
-        if (!_dri_drm_init())
+        _drm_shutdown();
+        if (!_drm_init())
           {
              vsync_root = 0;
              ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
              return EINA_FALSE;
           }
         ecore_animator_custom_source_tick_begin_callback_set
-          (_dri_drm_tick_begin, NULL);
+          (_drm_tick_begin, NULL);
         ecore_animator_custom_source_tick_end_callback_set
-          (_dri_drm_tick_end, NULL);
+          (_drm_tick_end, NULL);
         ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM);
      }
    else
      {
         if (drm_fd >= 0)
           {
-             _dri_drm_shutdown();
+             _drm_shutdown();
              ecore_animator_custom_source_tick_begin_callback_set
                (NULL, NULL);
              ecore_animator_custom_source_tick_end_callback_set
@@ -491,28 +464,33 @@ static void
 _vsync_init(void)
 {
    static int done = 0;
+   struct stat stb;
 
    if (done) return;
 
-#ifdef ECORE_X_VSYNC_DRI2
-   // preferred inline dri/drm if possible
-   if (_dri_drm_link())
+   if (_ecore_x_image_shm_check())
      {
-        _dri_drm_shutdown();
-        if (_dri_drm_init())
+#ifdef ECORE_X_VSYNC_DRM
+        // preferred inline drm if possible
+        if (!stat("/dev/dri/card0", &stb))
           {
-             mode = 1;
+             if (_drm_link())
+               {
+                  _drm_shutdown();
+                  if (_drm_init())
+                    {
+                       mode = 1;
+                    }
+               }
           }
-     }
 #endif
-   // nvidia gl vsync slave mode
-   if (mode == 0)
-     {
-        struct stat stb;
-
-        if (!stat("/dev/nvidiactl", &stb))
+        // nvidia gl vsync slave mode
+        if (mode == 0)
           {
-             mode = 2;
+             if (!stat("/dev/nvidiactl", &stb))
+               {
+                  mode = 2;
+               }
           }
      }
    done = 1;
@@ -528,8 +506,8 @@ ecore_x_vsync_animator_tick_source_set(Ecore_X_Window win)
      {
         _vsync_init();
         vsync_root = root;
-#ifdef ECORE_X_VSYNC_DRI2
-        if (mode == 1) return _dri_animator_tick_source_set();
+#ifdef ECORE_X_VSYNC_DRM
+        if (mode == 1) return _drm_animator_tick_source_set();
         else
 #endif
         if (mode == 2) return _glvsync_animator_tick_source_set();

-- 


Reply via email to