evas-engines: Port evas drm engines to use Ecore_Drm2 library
authorChris Michael <cpmichael@osg.samsung.com>
Tue, 3 May 2016 16:02:20 +0000 (12:02 -0400)
committerChris Michael <cpmichael@osg.samsung.com>
Fri, 27 May 2016 15:57:53 +0000 (11:57 -0400)
This patch ports the evas drm and gl_drm engines to use the new
Ecore_Drm2 library

Signed-off-by: Chris Michael <cpmichael@osg.samsung.com>
m4/evas_check_engine.m4
src/Makefile_Evas.am
src/modules/evas/engines/drm/Evas_Engine_Drm.h
src/modules/evas/engines/drm/evas_engine.c
src/modules/evas/engines/drm/evas_engine.h
src/modules/evas/engines/drm/evas_outbuf.c
src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h
src/modules/evas/engines/gl_drm/evas_engine.c
src/modules/evas/engines/gl_drm/evas_engine.h
src/modules/evas/engines/gl_drm/evas_outbuf.c

index 448a210..4789d4b 100644 (file)
@@ -597,16 +597,23 @@ AC_DEFUN([EVAS_CHECK_ENGINE_DEP_DRM],
 [
 
 requirement=""
-have_dep="yes"
+have_dep="no"
 have_hw_dep="no"
 evas_engine_[]$1[]_cflags=""
 evas_engine_[]$1[]_libs=""
 
+PKG_CHECK_EXISTS([libdrm],
+  [
+    have_dep="yes"
+    requirement="libdrm"
+  ], [have_dep="no"])
+
 if test "x${have_dep}" = "xyes" ; then
    if test "x$3" = "xstatic" ; then
       requirements_pc_evas="${requirement} ${requirements_pc_evas}"
       requirements_pc_deps_evas="${requirement} ${requirements_pc_deps_evas}"
    else
+      PKG_CHECK_MODULES([DRM], [${requirement}])
       evas_engine_[]$1[]_cflags="${DRM_CFLAGS}"
       evas_engine_[]$1[]_libs="${DRM_LIBS}"
    fi
@@ -636,10 +643,10 @@ else
    AC_MSG_ERROR([We currently do not support GL DRM without OpenGL ES. Please consider OpenGL ES if you want to use it.])
 fi
 
-PKG_CHECK_EXISTS([egl ${gl_library} gbm wayland-client >= REQUIRED_WAYLAND_VERSION],
+PKG_CHECK_EXISTS([egl ${gl_library} libdrm gbm wayland-client >= REQUIRED_WAYLAND_VERSION],
    [
     have_dep="yes"
-    requirement="egl ${gl_library} gbm wayland-client >= REQUIRED_WAYLAND_VERSION"
+    requirement="egl ${gl_library} libdrm gbm wayland-client >= REQUIRED_WAYLAND_VERSION"
    ],
    [have_dep="no"])
 
index daa11b8..19fea04 100644 (file)
@@ -1276,7 +1276,6 @@ endif
 endif
 
 if BUILD_ENGINE_DRM
-dist_installed_evasmainheaders_DATA += modules/evas/engines/drm/Evas_Engine_Drm.h
 DRM_SOURCES = \
 modules/evas/engines/drm/evas_outbuf.c \
 modules/evas/engines/drm/evas_engine.c \
@@ -1301,20 +1300,19 @@ modules_evas_engines_drm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
 -I$(top_srcdir)/src/lib/evas/cserve2 \
 -I$(top_srcdir)/src/modules/evas/engines/drm \
 @EVAS_CFLAGS@ \
-@ECORE_DRM_CFLAGS@ \
+@ECORE_DRM2_CFLAGS@ \
 @evas_engine_drm_cflags@
 modules_evas_engines_drm_module_la_LIBADD = \
 @USE_EVAS_LIBS@ \
-@USE_ECORE_DRM_LIBS@ \
+@USE_ECORE_DRM2_LIBS@ \
 @evas_engine_drm_libs@
-modules_evas_engines_drm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ @USE_ECORE_DRM_INTERNAL_LIBS@
+modules_evas_engines_drm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ @USE_ECORE_DRM2_INTERNAL_LIBS@
 modules_evas_engines_drm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
 modules_evas_engines_drm_module_la_LIBTOOLFLAGS = --tag=disable-static
 endif
 endif
 
 if BUILD_ENGINE_GL_DRM
-dist_installed_evasmainheaders_DATA += modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h
 GL_DRM_SOURCES = \
 modules/evas/engines/gl_drm/evas_outbuf.c \
 modules/evas/engines/gl_drm/evas_engine.c \
@@ -1339,13 +1337,13 @@ modules_evas_engines_gl_drm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
 -I$(top_srcdir)/src/lib/evas/cserve2 \
 -I$(top_srcdir)/src/modules/evas/engines/gl_drm \
 @EVAS_CFLAGS@ \
-@ECORE_DRM_CFLAGS@ \
+@ECORE_DRM2_CFLAGS@ \
 @evas_engine_gl_drm_cflags@
 modules_evas_engines_gl_drm_module_la_LIBADD = \
 @USE_EVAS_LIBS@ \
-@USE_ECORE_DRM_LIBS@ \
+@USE_ECORE_DRM2_LIBS@ \
 @evas_engine_gl_drm_libs@
-modules_evas_engines_gl_drm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ @USE_ECORE_DRM_INTERNAL_LIBS@
+modules_evas_engines_gl_drm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ @USE_ECORE_DRM2_INTERNAL_LIBS@
 modules_evas_engines_gl_drm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
 modules_evas_engines_gl_drm_module_la_LIBTOOLFLAGS = --tag=disable-static
 endif
index 136eb91..457db62 100644 (file)
@@ -1,11 +1,7 @@
 #ifndef _EVAS_ENGINE_DRM_H
 # define _EVAS_ENGINE_DRM_H
 
-# include <Ecore_Drm.h>
-
-typedef struct _Evas_Engine_Info_Drm Evas_Engine_Info_Drm;
-
-struct _Evas_Engine_Info_Drm
+typedef struct _Evas_Engine_Info_Drm
 {
    /* PRIVATE - don't mess with this baby or evas will poke its tongue out */
    /* at you and make nasty noises */
@@ -13,18 +9,17 @@ struct _Evas_Engine_Info_Drm
 
    struct
      {
-        unsigned int rotation, depth;
-        Eina_Bool destination_alpha : 1;
-        Eina_Bool vsync : 1;
+        int fd;
+        int depth, bpp;
+        unsigned int format, rotation;
 
-        unsigned int crtc_id, conn_id, buffer_id;
-
-        Eina_Bool use_hw_accel : 1;
-        Ecore_Drm_Device *dev;
+        void *output;
+        Eina_Bool alpha : 1;
+        Eina_Bool vsync : 1;
      } info;
 
    /* non-blocking or blocking mode */
    Evas_Engine_Render_Mode render_mode;
-};
+} Evas_Engine_Info_Drm;
 
 #endif
index 40365a9..e3cd01e 100644 (file)
@@ -1,65 +1,57 @@
 #include "evas_engine.h"
 
-/* local structures */
-typedef struct _Render_Engine Render_Engine;
-
-struct _Render_Engine
+typedef struct _Render_Engine
 {
    Render_Engine_Software_Generic generic;
-};
+} Render_Engine;
 
-/* function tables - filled in later (func and parent func) */
 static Evas_Func func, pfunc;
 
-/* external variables */
 int _evas_engine_drm_log_dom;
 
-/* local functions */
-static void *
-_output_setup(Evas_Engine_Info_Drm *info, int w, int h)
+static Render_Engine *
+_render_engine_setup(Evas_Engine_Info_Drm *info, int w, int h)
 {
-   Render_Engine *re = NULL;
+   Render_Engine *re;
    Outbuf *ob;
 
-   /* try to allocate space for our render engine structure */
-   if (!(re = calloc(1, sizeof(Render_Engine))))
-     goto on_error;
+   re = calloc(1, sizeof(Render_Engine));
+   if (!re) return NULL;
 
-   /* try to create new outbuf */
-   if (!(ob = evas_outbuf_setup(info, w, h)))
-     goto on_error;
+   ob = _outbuf_setup(info, w, h);
+   if (!ob) goto err;
 
    if (!evas_render_engine_software_generic_init(&re->generic, ob,
-                                                 evas_outbuf_buffer_state_get,
-                                                 evas_outbuf_rot_get,
-                                                 evas_outbuf_reconfigure, NULL,
-                                                 evas_outbuf_update_region_new,
-                                                 evas_outbuf_update_region_push,
-                                                 evas_outbuf_update_region_free,
-                                                 NULL, evas_outbuf_flush,
-                                                 evas_outbuf_free, 
+                                                 _outbuf_state_get,
+                                                 _outbuf_rotation_get,
+                                                 _outbuf_reconfigure,
+                                                 NULL,
+                                                 _outbuf_update_region_new,
+                                                 _outbuf_update_region_push,
+                                                 _outbuf_update_region_free,
+                                                 NULL,
+                                                 _outbuf_flush,
+                                                 _outbuf_free,
                                                  ob->w, ob->h))
-     goto on_error;
+     goto init_err;
 
-   /* return the allocated render_engine structure */
    return re;
 
- on_error:
-   if (re) evas_render_engine_software_generic_clean(&re->generic);
-
+init_err:
+   evas_render_engine_software_generic_clean(&re->generic);
+err:
    free(re);
    return NULL;
 }
 
-/* engine api functions */
 static void *
 eng_info(Evas *evas EINA_UNUSED)
 {
    Evas_Engine_Info_Drm *info;
 
    /* try to allocate space for our engine info structure */
-   if (!(info = calloc(1, sizeof(Evas_Engine_Info_Drm))))
-     return NULL;
+   info = calloc(1, sizeof(Evas_Engine_Info_Drm));
+   if (!info) return NULL;
 
    /* set some engine default properties */
    info->magic.magic = rand();
@@ -74,55 +66,47 @@ eng_info_free(Evas *evas EINA_UNUSED, void *einfo)
    Evas_Engine_Info_Drm *info;
 
    /* free the engine info */
-   if ((info = (Evas_Engine_Info_Drm *)einfo))
-     free(info);
+   info = (Evas_Engine_Info_Drm *)einfo;
+   free(info);
 }
 
 static int
 eng_setup(Evas *evas, void *einfo)
 {
-   Evas_Engine_Info_Drm *info;
-   Evas_Public_Data *epd;
    Render_Engine *re;
+   Evas_Public_Data *epd;
+   Evas_Engine_Info_Drm *info;
 
-   /* try to cast to our engine info structure */
-   if (!(info = (Evas_Engine_Info_Drm *)einfo)) return 0;
+   info = (Evas_Engine_Info_Drm *)einfo;
+   if (!info) return 0;
 
-   /* try to get the evas public data */
-   if (!(epd = eo_data_scope_get(evas, EVAS_CANVAS_CLASS))) return 0;
+   epd = eo_data_scope_get(evas, EVAS_CANVAS_CLASS);
+   if (!epd) return 0;
 
-   /* check for valid engine output */
-   if (!(re = epd->engine.data.output))
+   re = epd->engine.data.output;
+   if (!re)
      {
-        /* NB: If we have no valid output then assume we have not been
-         * initialized yet and call any needed common init routines */
         evas_common_init();
 
-        /* try to create a new render_engine */
-        if (!(re = _output_setup(info, epd->output.w, epd->output.h)))
-          return 0;
+        re = _render_engine_setup(info, epd->output.w, epd->output.h);
+        if (!re) return 0;
      }
    else
      {
         Outbuf *ob;
 
-        /* try to create a new outbuf */
-        ob = evas_outbuf_setup(info, epd->output.w, epd->output.h);
+        ob = _outbuf_setup(info, epd->output.w, epd->output.h);
         if (!ob) return 0;
 
-        /* if we have an existing outbuf, free it */
-        evas_render_engine_software_generic_update(&re->generic, ob, 
+        evas_render_engine_software_generic_update(&re->generic, ob,
                                                    ob->w, ob->h);
      }
 
-   /* reassign engine output */
    epd->engine.data.output = re;
    if (!epd->engine.data.output) return 0;
 
-   /* check for valid engine context */
    if (!epd->engine.data.context)
      {
-        /* create a context if needed */
         epd->engine.data.context =
           epd->engine.func->context_new(epd->engine.data.output);
      }
@@ -135,7 +119,8 @@ eng_output_free(void *data)
 {
    Render_Engine *re;
 
-   if ((re = data))
+   re = data;
+   if (re)
      {
         evas_render_engine_software_generic_clean(&re->generic);
         free(re);
@@ -144,7 +129,6 @@ eng_output_free(void *data)
    evas_common_shutdown();
 }
 
-/* module api functions */
 static int
 module_open(Evas_Module *em)
 {
@@ -165,6 +149,8 @@ module_open(Evas_Module *em)
         return 0;
      }
 
+   ecore_init();
+
    /* store parent functions */
    func = pfunc;
 
@@ -185,6 +171,8 @@ module_close(Evas_Module *em EINA_UNUSED)
 {
    /* unregister the eina log domain for this engine */
    eina_log_domain_unregister(_evas_engine_drm_log_dom);
+
+   ecore_shutdown();
 }
 
 static Evas_Module_Api evas_modapi =
index d513911..a1925b9 100644 (file)
@@ -6,8 +6,13 @@
 # include "evas_private.h"
 # include "Evas.h"
 # include "Evas_Engine_Drm.h"
+# include <Ecore.h>
+# include <Ecore_Drm2.h>
+# include <drm_fourcc.h>
+# include <xf86drm.h>
+# include <xf86drmMode.h>
 
-#include "../software_generic/Evas_Engine_Software_Generic.h"
+# include "../software_generic/Evas_Engine_Software_Generic.h"
 
 extern int _evas_engine_drm_log_dom;
 
@@ -36,35 +41,44 @@ extern int _evas_engine_drm_log_dom;
 # endif
 # define CRI(...) EINA_LOG_DOM_CRIT(_evas_engine_drm_log_dom, __VA_ARGS__)
 
-struct _Outbuf
+typedef struct _Outbuf_Fb
 {
-   Evas_Engine_Info_Drm *info;
+   int age;
+   Ecore_Drm2_Fb *fb;
+
+   Eina_Bool valid : 1;
+   Eina_Bool drawn : 1;
+   Eina_Bool busy : 1;
+} Outbuf_Fb;
 
-   int w, h;
-   int rotation;
-   unsigned int depth;
+struct _Outbuf
+{
+   int fd, w, h, bpp, rotation;
+   unsigned int depth, format;
 
    struct
      {
-        Ecore_Drm_Fb *buffer[4];
-
-        Eina_List *pending_writes;
-
-        int curr, last, num;
+        int num;
+        Outbuf_Fb ofb[4], *current;
+        Ecore_Drm2_Output *output;
+        Eina_List *pending;
      } priv;
 
-   Eina_Bool destination_alpha : 1;
+   drmEventContext ctx;
+   Ecore_Fd_Handler *hdlr;
+
+   Eina_Bool alpha : 1;
    Eina_Bool vsync : 1;
 };
 
-Outbuf *evas_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h);
-void evas_outbuf_free(Outbuf *ob);
-void evas_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth);
-Render_Engine_Swap_Mode evas_outbuf_buffer_state_get(Outbuf *ob);
-int evas_outbuf_rot_get(Outbuf *ob);
-void *evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch);
-void evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h);
-void evas_outbuf_update_region_free(Outbuf *ob, RGBA_Image *update);
-void evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode);
+Outbuf *_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h);
+void _outbuf_free(Outbuf *ob);
+int _outbuf_rotation_get(Outbuf *ob);
+void _outbuf_reconfigure(Outbuf *ob, int w, int h, int rotation, Outbuf_Depth depth);
+Render_Engine_Swap_Mode _outbuf_state_get(Outbuf *ob);
+void *_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch);
+void _outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h);
+void _outbuf_update_region_free(Outbuf *ob, RGBA_Image *update);
+void _outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode);
 
 #endif
index 64b3ba9..4c87f2d 100644 (file)
 #define GREEN_MASK 0x00ff00
 #define BLUE_MASK 0x0000ff
 
-static void 
-_evas_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count)
+static void _outbuf_tick_schedule(int fd, void *data);
+
+static Eina_Bool ticking = EINA_FALSE;
+
+static void
+_outbuf_tick_begin(void *data)
+{
+   Outbuf *ob;
+
+   ob = data;
+   ticking = EINA_TRUE;
+   if (ob) _outbuf_tick_schedule(ob->fd, ob);
+}
+
+static void
+_outbuf_tick_end(void *data EINA_UNUSED)
+{
+   ticking = EINA_FALSE;
+}
+
+static void
+_outbuf_tick_source_set(Outbuf *ob)
+{
+   if (ob)
+     {
+        ecore_animator_custom_source_tick_begin_callback_set
+          (_outbuf_tick_begin, ob);
+        ecore_animator_custom_source_tick_end_callback_set
+          (_outbuf_tick_end, ob);
+        ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM);
+     }
+   else
+     {
+        ecore_animator_custom_source_tick_begin_callback_set(NULL, NULL);
+        ecore_animator_custom_source_tick_end_callback_set(NULL, NULL);
+        ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
+     }
+}
+
+static void
+_outbuf_tick_schedule(int fd EINA_UNUSED, void *data)
+{
+   Outbuf *ob;
+   Outbuf_Fb *ofb;
+
+   ob = data;
+   if (!ticking) return;
+
+   ofb = ob->priv.current;
+   if (!ofb) return;
+
+   drmVBlank vbl =
+     {
+        .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
+        .request.sequence = 1,
+        .request.signal = (unsigned long)data,
+     };
+
+   if (drmWaitVBlank(fd, &vbl) < 0)
+     _outbuf_tick_source_set(NULL);
+}
+
+static void
+_cb_vblank(int fd, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data)
+{
+   ecore_animator_custom_tick();
+   if (ticking) _outbuf_tick_schedule(fd, data);
+}
+
+static void
+_cb_pageflip(int fd EINA_UNUSED, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data)
 {
-   Ecore_Drm_Fb *buff;
+   Outbuf *ob;
+   Outbuf_Fb *ofb;
+   Ecore_Drm2_Fb *next;
+
+   ob = data;
+
+   ofb = ob->priv.current;
+   if (ofb) ofb->busy = EINA_FALSE;
+
+   next = ecore_drm2_output_next_fb_get(ob->priv.output);
+   if (next)
+     {
+        ecore_drm2_output_next_fb_set(ob->priv.output, NULL);
+        if (ecore_drm2_fb_flip(next, ob->priv.output, ob) < 0)
+          _outbuf_tick_source_set(NULL);
+     }
+}
+
+static Eina_Bool
+_cb_drm_event(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
+{
+   Outbuf *ob;
+   int ret;
+
+   ob = data;
+   ret = drmHandleEvent(ob->fd, &ob->ctx);
+   if (ret)
+     {
+        WRN("drmHandleEvent failed to read an event");
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
 
-   buff = ob->priv.buffer[ob->priv.curr];
+static void
+_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count)
+{
+   /* Ecore_Drm2_Plane *plane; */
+   Outbuf_Fb *ofb;
+
+   ofb = ob->priv.current;
+   if (!ofb) return;
+
+   ecore_drm2_fb_dirty(ofb->fb, rects, count);
+   if (ecore_drm2_fb_flip(ofb->fb, ob->priv.output, ob) < 0)
+     {
+        _outbuf_tick_source_set(NULL);
+        return;
+     }
+
+   ofb->busy = EINA_TRUE;
+   ofb->drawn = EINA_TRUE;
+   ofb->age = 0;
+
+   /* plane = ecore_drm2_plane_find(ob->priv.output, ofb->fb, ob->format); */
+   /* if (plane) */
+   /*   { */
+   /*      drmVBlank vbl = */
+   /*        { */
+   /*           .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, */
+   /*           .request.sequence = 1, */
+   /*        }; */
+
+   /*      vbl.request.type |= ecore_drm2_output_vblank_get(ob->priv.output); */
+   /*      vbl.request.signal = (unsigned long)ofb; */
+
+   /*      ecore_drm2_fb_dirty(ofb->fb, rects, count); */
+
+   /*      if (!ecore_drm2_plane_fb_set(plane, ofb->fb)) */
+   /*        { */
+   /*           ERR("Failed to set FB on Plane"); */
+   /*           return; */
+   /*        } */
+
+   /*      if (drmWaitVBlank(ob->fd, &vbl) < 0) */
+   /*        { */
+   /*           _outbuf_tick_source_set(NULL); */
+   /*           return; */
+   /*        } */
+
+   /*      ofb->busy = EINA_TRUE; */
+   /*      ofb->drawn = EINA_TRUE; */
+   /*      ofb->age = 0; */
+
+   /*      ob->priv.current = NULL; */
+   /*   } */
+   /* else */
+   /*   WRN("Could not find a plane for this framebuffer"); */
+}
 
-   /* mark the fb as dirty */
-   ecore_drm_fb_dirty(buff, rects, count);
+static Eina_Bool
+_outbuf_fb_create(Outbuf *ob, Outbuf_Fb *ofb)
+{
+   ofb->fb =
+     ecore_drm2_fb_create(ob->fd, ob->w, ob->h,
+                          ob->depth, ob->bpp, ob->format);
+   if (!ofb->fb) return EINA_FALSE;
 
-   /* send this buffer to the crtc */
-   ecore_drm_fb_send(ob->info->info.dev, buff, NULL, NULL);
+   ofb->age = 0;
+   ofb->busy = EINA_FALSE;
+   ofb->drawn = EINA_FALSE;
+   ofb->valid = EINA_TRUE;
 
-   ob->priv.last = ob->priv.curr;
-   ob->priv.curr = (ob->priv.curr + 1) % ob->priv.num;
+   return EINA_TRUE;
+}
+
+static void
+_outbuf_fb_destroy(Outbuf_Fb *ofb)
+{
+   ecore_drm2_fb_destroy(ofb->fb);
+
+   memset(ofb, 0, sizeof(*ofb));
+   ofb->valid = EINA_FALSE;
+   ofb->busy = EINA_FALSE;
+   ofb->drawn = EINA_FALSE;
+   ofb->age = 0;
 }
 
 Outbuf *
-evas_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h)
+_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h)
 {
    Outbuf *ob;
    char *num;
    int i = 0;
 
-   /* try to allocate space for outbuf */
-   if (!(ob = calloc(1, sizeof(Outbuf)))) return NULL;
+   ob = calloc(1, sizeof(Outbuf));
+   if (!ob) return NULL;
 
-   /* set properties of outbuf */
    ob->w = w;
    ob->h = h;
+   ob->fd = info->info.fd;
+   ob->alpha = info->info.alpha;
+   ob->rotation = info->info.rotation;
 
-   ob->info = info;
+   ob->bpp = info->info.bpp;
    ob->depth = info->info.depth;
-   ob->rotation = info->info.rotation;
-   ob->destination_alpha = info->info.destination_alpha;
-   ob->vsync = info->info.vsync;
+   ob->format = info->info.format;
+
+   ob->priv.output = info->info.output;
 
-   /* we must triple-buffer to prevent problems with the page flip handler */
    ob->priv.num = 3;
 
-   /* check for buffer override */
-   if ((num = getenv("EVAS_DRM_BUFFERS")))
+   num = getenv("EVAS_DRM_BUFFERS");
+   if (num)
      {
         ob->priv.num = atoi(num);
-        if (ob->priv.num <= 0) ob->priv.num = 1;
+        if (ob->priv.num <= 0) ob->priv.num = 3;
         else if (ob->priv.num > 4) ob->priv.num = 4;
      }
 
-   /* check for vsync override */
-   if ((num = getenv("EVAS_DRM_VSYNC")))
-     ob->vsync = atoi(num);
-
-   /* try to create buffers */
-   for (; i < ob->priv.num; i++)
+   for (i = 0; i < ob->priv.num; i++)
      {
-        ob->priv.buffer[i] = 
-          ecore_drm_fb_create(ob->info->info.dev, ob->w, ob->h);
-        if (!ob->priv.buffer[i])
+        if (!_outbuf_fb_create(ob, &(ob->priv.ofb[i])))
           {
-             ERR("Failed to create buffer %d", i);
-             break;
+             WRN("Failed to create framebuffer %d", i);
+             continue;
           }
-
-        DBG("Evas Engine Created Dumb Buffer");
-        DBG("\tFb: %d", ob->priv.buffer[i]->id);
-        DBG("\tHandle: %d", ob->priv.buffer[i]->hdl);
-        DBG("\tStride: %d", ob->priv.buffer[i]->stride);
-        DBG("\tSize: %d", ob->priv.buffer[i]->size);
-        DBG("\tW: %d\tH: %d",
-            ob->priv.buffer[i]->w, ob->priv.buffer[i]->h);
      }
 
-   /* set the front buffer to be the one on the crtc */
-   ecore_drm_fb_send(info->info.dev, ob->priv.buffer[0], NULL, NULL);
+   /* setup vblank handler */
+   memset(&ob->ctx, 0, sizeof(ob->ctx));
+   ob->ctx.version = DRM_EVENT_CONTEXT_VERSION;
+   ob->ctx.vblank_handler = _cb_vblank;
+   ob->ctx.page_flip_handler = _cb_pageflip;
+
+   ob->hdlr =
+     ecore_main_fd_handler_add(ob->fd, ECORE_FD_READ, _cb_drm_event, ob,
+                               NULL, NULL);
+
+   _outbuf_tick_source_set(ob);
 
    return ob;
 }
 
 void
-evas_outbuf_free(Outbuf *ob)
+_outbuf_free(Outbuf *ob)
 {
    int i = 0;
 
-   /* destroy the old buffers */
-   for (; i < ob->priv.num; i++)
-     ecore_drm_fb_destroy(ob->priv.buffer[i]);
+   for (i = 0; i < ob->priv.num; i++)
+     _outbuf_fb_destroy(&ob->priv.ofb[i]);
+
+   ecore_main_fd_handler_del(ob->hdlr);
 
-   /* free allocate space for outbuf */
    free(ob);
 }
 
+int
+_outbuf_rotation_get(Outbuf *ob)
+{
+   return ob->rotation;
+}
+
 void
-evas_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth)
+_outbuf_reconfigure(Outbuf *ob, int w, int h, int rotation, Outbuf_Depth depth)
 {
    int i = 0;
+   unsigned int format = DRM_FORMAT_ARGB8888;
 
-   /* check if we are inheriting the old buffer depth */
-   if (depth == OUTBUF_DEPTH_INHERIT) depth = ob->depth;
+   switch (depth)
+     {
+      case OUTBUF_DEPTH_RGB_16BPP_565_565_DITHERED:
+        format = DRM_FORMAT_RGB565;
+        break;
+      case OUTBUF_DEPTH_RGB_16BPP_555_555_DITHERED:
+        format = DRM_FORMAT_RGBX5551;
+        break;
+      case OUTBUF_DEPTH_RGB_16BPP_444_444_DITHERED:
+        format = DRM_FORMAT_RGBX4444;
+        break;
+      case OUTBUF_DEPTH_RGB_16BPP_565_444_DITHERED:
+        format = DRM_FORMAT_RGB565;
+        break;
+      case OUTBUF_DEPTH_RGB_32BPP_888_8888:
+        format = DRM_FORMAT_RGBX8888;
+        break;
+      case OUTBUF_DEPTH_ARGB_32BPP_8888_8888:
+        format = DRM_FORMAT_ARGB8888;
+        break;
+      case OUTBUF_DEPTH_BGRA_32BPP_8888_8888:
+        format = DRM_FORMAT_BGRA8888;
+        break;
+      case OUTBUF_DEPTH_BGR_32BPP_888_8888:
+        format = DRM_FORMAT_BGRX8888;
+        break;
+      case OUTBUF_DEPTH_RGB_24BPP_888_888:
+        format = DRM_FORMAT_RGB888;
+        break;
+      case OUTBUF_DEPTH_BGR_24BPP_888_888:
+        format = DRM_FORMAT_BGR888;
+        break;
+      case OUTBUF_DEPTH_INHERIT:
+      default:
+        depth = ob->depth;
+        format = ob->format;
+        break;
+     }
 
-   /* check for changes */
-   if ((ob->w == w) && (ob->h == h) &&
-       (ob->destination_alpha == ob->info->info.destination_alpha) &&
-       (ob->rotation == rot) &&
-       (ob->depth == depth))
+   if ((ob->w == w) && (ob->h == h) && (ob->rotation == rotation) &&
+       (ob->depth == depth) && (ob->format == format))
      return;
 
-   /* set new outbuf properties */
-   ob->rotation = rot;
    ob->depth = depth;
-   ob->destination_alpha = ob->info->info.destination_alpha;
+   ob->format = format;
+   ob->rotation = rotation;
 
-   /* handle rotation */
-   if ((ob->rotation == 0) || (ob->rotation == 180))
-     {
-        ob->w = w;
-        ob->h = h;
-     }
-   else
+   ob->w = w;
+   ob->h = h;
+   if ((ob->rotation == 90) || (ob->rotation == 270))
      {
         ob->w = h;
         ob->h = w;
      }
 
-   /* destroy the old buffers */
-   for (; i < ob->priv.num; i++)
-     ecore_drm_fb_destroy(ob->priv.buffer[i]);
+   for (i = 0; i < ob->priv.num; i++)
+     _outbuf_fb_destroy(&ob->priv.ofb[i]);
 
    for (i = 0; i < ob->priv.num; i++)
      {
-        ob->priv.buffer[i] = 
-          ecore_drm_fb_create(ob->info->info.dev, ob->w, ob->h);
-        if (!ob->priv.buffer[i])
+        if (!_outbuf_fb_create(ob, &(ob->priv.ofb[i])))
           {
-             ERR("Failed to create buffer %d", i);
-             break;
+             WRN("Failed to create framebuffer %d", i);
+             continue;
           }
      }
 }
 
-Render_Engine_Swap_Mode
-evas_outbuf_buffer_state_get(Outbuf *ob)
+static Outbuf_Fb *
+_outbuf_fb_wait(Outbuf *ob)
 {
-   int delta;
+   int iter = 0, i = 0;
 
-   /* check for valid output buffer */
-   if (!ob) return MODE_FULL;
+   while (iter++ < 10)
+     {
+        for (i = 0; i < ob->priv.num; i++)
+          {
+             if (ob->priv.ofb[i].busy) continue;
+             if (ob->priv.ofb[i].valid) return &(ob->priv.ofb[i]);
+          }
+
+        drmHandleEvent(ob->fd, &ob->ctx);
+     }
+
+   return NULL;
+}
+
+static Eina_Bool
+_outbuf_fb_assign(Outbuf *ob)
+{
+   int i;
 
-   delta = (ob->priv.last - ob->priv.curr + ob->priv.num) % ob->priv.num;
+   ob->priv.current = _outbuf_fb_wait(ob);
 
-   /* This is the number of frame since last frame */
-   switch (delta)
+   if (!ob->priv.current)
      {
-      case 0:
-        return MODE_COPY;
-      case 1:
-        return MODE_DOUBLE;
-      case 2:
-        return MODE_TRIPLE;
-      case 3:
-        return MODE_QUADRUPLE;
-      default:
-        return MODE_FULL;
+        WRN("No Free Buffers. Dropping a frame");
+        for (i = 0; i < ob->priv.num; i++)
+          {
+             if (ob->priv.ofb[i].valid)
+               {
+                  ob->priv.ofb[i].age = 0;
+                  ob->priv.ofb[i].drawn = EINA_FALSE;
+               }
+          }
+
+        return EINA_FALSE;
      }
+
+   for (i = 0; i < ob->priv.num; i++)
+     {
+        if ((ob->priv.ofb[i].valid) && (ob->priv.ofb[i].drawn))
+          {
+             ob->priv.ofb[i].age++;
+             if (ob->priv.ofb[i].age > ob->priv.num)
+               {
+                  ob->priv.ofb[i].age = 0;
+                  ob->priv.ofb[i].drawn = EINA_FALSE;
+               }
+          }
+     }
+
+   return EINA_TRUE;
+}
+
+Render_Engine_Swap_Mode
+_outbuf_state_get(Outbuf *ob)
+{
+   int age;
+
+   if (!_outbuf_fb_assign(ob)) return MODE_FULL;
+
+   age = ob->priv.current->age;
+   if (age > ob->priv.num) return MODE_FULL;
+   else if (age == 1) return MODE_COPY;
+   else if (age == 2) return MODE_DOUBLE;
+   else if (age == 3) return MODE_TRIPLE;
+   else if (age == 4) return MODE_QUADRUPLE;
+
+   return MODE_FULL;
 }
 
 void *
-evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch)
+_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch)
 {
    RGBA_Image *img = NULL;
 
    if ((w <= 0) || (h <= 0)) return NULL;
 
-   /* DBG("Outbuf Region New: %d %d %d %d", x, y, w, h); */
-
    RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, ob->w, ob->h);
 
-   if ((ob->rotation == 0) && (ob->depth == 32))
+   if ((ob->rotation == 0))// && (ob->depth == 32))
      {
         Eina_Rectangle *rect;
 
@@ -204,7 +451,7 @@ evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, i
              return NULL;
           }
 
-        img->cache_entry.flags.alpha = ob->destination_alpha;
+        img->cache_entry.flags.alpha = ob->alpha;
 
 #ifdef EVAS_CSERVE2
         if (evas_cserve2_use_get())
@@ -221,48 +468,52 @@ evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, i
         if (ch) *ch = h;
 
         /* add this cached image data to pending writes */
-        ob->priv.pending_writes = 
-          eina_list_append(ob->priv.pending_writes, img);
+        ob->priv.pending = 
+          eina_list_append(ob->priv.pending, img);
      }
 
    return img;
 }
 
-void 
-evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h)
+void
+_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h)
 {
    Gfx_Func_Convert func = NULL;
    Eina_Rectangle rect = {0, 0, 0, 0}, pr;
    DATA32 *src;
    DATA8 *dst;
-   Ecore_Drm_Fb *buff;
+   Ecore_Drm2_Fb *buff;
    int bpp = 0, bpl = 0;
    int rx = 0, ry = 0;
+   int bw = 0, bh = 0;
 
    /* check for valid output buffer */
    if (!ob) return;
 
    /* check for pending writes */
-   if (!ob->priv.pending_writes) return;
+   if (!ob->priv.pending) return;
 
    /* check for valid source data */
    if (!(src = update->image.data)) return;
 
    /* check for valid desination data */
-   buff = ob->priv.buffer[ob->priv.curr];
-   if (!(dst = buff->mmap)) return;
+   if (!ob->priv.current) return;
+   buff = ob->priv.current->fb;
+
+   dst = ecore_drm2_fb_data_get(buff);
+   if (!dst) return;
 
    if ((ob->rotation == 0) || (ob->rotation == 180))
      {
         func = 
-          evas_common_convert_func_get(0, w, h, ob->depth
+          evas_common_convert_func_get(0, w, h, ob->bpp
                                        RED_MASK, GREEN_MASK, BLUE_MASK,
                                        PAL_MODE_NONE, ob->rotation);
      }
    else if ((ob->rotation == 90) || (ob->rotation == 270))
      {
         func = 
-          evas_common_convert_func_get(0, h, w, ob->depth
+          evas_common_convert_func_get(0, h, w, ob->bpp
                                        RED_MASK, GREEN_MASK, BLUE_MASK,
                                        PAL_MODE_NONE, ob->rotation);
      }
@@ -304,15 +555,18 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int
         rect.h = w;
      }
 
-   bpp = (ob->depth / 8);
-   if (bpp <= 0) return;
+   bpp = ob->bpp / 8;
+   bw = ob->w;
+   bh = ob->h;
+   /* bpp = (ob->depth / 8); */
+   /* if (bpp <= 0) return; */
 
-   bpl = buff->stride;
+   bpl = ecore_drm2_fb_stride_get(buff);
 
    if (ob->rotation == 0)
      {
         RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 
-                           0, 0, buff->w, buff->h);
+                           0, 0, bw, bh);
         dst += (bpl * rect.y) + (rect.x * bpp);
         w -= rx;
      }
@@ -320,7 +574,7 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int
      {
         pr = rect;
         RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 
-                           0, 0, buff->w, buff->h);
+                           0, 0, bw, bh);
         rx = pr.w - rect.w;
         ry = pr.h - rect.h;
         src += (update->cache_entry.w * ry) + rx;
@@ -330,7 +584,7 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int
      {
         pr = rect;
         RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 
-                           0, 0, buff->w, buff->h);
+                           0, 0, bw, bh);
         rx = pr.w - rect.w; ry = pr.h - rect.h;
         src += ry;
         w -= ry;
@@ -339,7 +593,7 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int
      {
         pr = rect;
         RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, 
-                           0, 0, buff->w, buff->h);
+                           0, 0, bw, bh);
         rx = pr.w - rect.w; ry = pr.h - rect.h;
         src += (update->cache_entry.w * rx);
         w -= ry;
@@ -352,13 +606,13 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int
 }
 
 void
-evas_outbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED)
+_outbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED)
 {
-   /* evas_cache_image_drop(&update->cache_entry); */
+
 }
 
 void
-evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode render_mode)
+_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode render_mode)
 {
    Eina_Rectangle *r;
    RGBA_Image *img;
@@ -367,19 +621,21 @@ evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode
    if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return;
 
    /* get number of pending writes */
-   n = eina_list_count(ob->priv.pending_writes);
+   n = eina_list_count(ob->priv.pending);
    if (n == 0) return;
 
    /* allocate rectangles */
-   if (!(r = alloca(n * sizeof(Eina_Rectangle)))) return;
+   r = alloca(n * sizeof(Eina_Rectangle));
+   if (!r) return;
 
    /* loop the pending writes */
-   EINA_LIST_FREE(ob->priv.pending_writes, img)
+   EINA_LIST_FREE(ob->priv.pending, img)
      {
         Eina_Rectangle *rect;
         int x = 0, y = 0, w = 0, h = 0;
 
-        if (!(rect = img->extended_info)) continue;
+        rect = img->extended_info;
+        if (!rect) continue;
 
         x = rect->x; y = rect->y; w = rect->w; h = rect->h;
 
@@ -430,11 +686,5 @@ evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode
      }
 
    /* force a buffer swap */
-   _evas_outbuf_buffer_swap(ob, r, n);
-}
-
-int
-evas_outbuf_rot_get(Outbuf *ob)
-{
-   return ob->rotation;
+   _outbuf_buffer_swap(ob, r, n);
 }
index 71ab60c..514aa80 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _EVAS_ENGINE_GL_DRM_H
 # define _EVAS_ENGINE_GL_DRM_H
 
-# include <Ecore_Drm.h>
+# include <Ecore_Drm2.h>
 # include <gbm.h>
 
 typedef enum _Evas_Engine_Info_GL_Drm_Swap_Mode
@@ -26,11 +26,11 @@ struct _Evas_Engine_Info_GL_Drm
      {
         struct gbm_device *gbm;
 
+        int fd, bpp;
         unsigned int rotation, depth;
-        unsigned int crtc_id, conn_id, buffer_id;
         unsigned int format, flags;
 
-        Ecore_Drm_Device *dev;
+        void *output;
 
         Eina_Bool destination_alpha : 1;
         Eina_Bool vsync : 1;
index d8d4312..29f2e0c 100644 (file)
@@ -118,12 +118,9 @@ static const EVGL_Interface evgl_funcs =
 Eina_Bool
 eng_gbm_init(Evas_Engine_Info_GL_Drm *info)
 {
-   Ecore_Drm_Device *dev;
-
    if (!info) return EINA_FALSE;
-   if (!(dev = info->info.dev)) return EINA_FALSE;
 
-   if (!(info->info.gbm = gbm_create_device(dev->drm.fd)))
+   if (!(info->info.gbm = gbm_create_device(info->info.fd)))
      {
         ERR("Coult not create gbm device");
         return EINA_FALSE;
@@ -146,13 +143,6 @@ eng_gbm_shutdown(Evas_Engine_Info_GL_Drm *info)
    return EINA_TRUE;
 }
 
-/* local inline functions */
-static inline Outbuf *
-eng_get_ob(Render_Engine *re)
-{
-   return re->generic.software.ob;
-}
-
 /* local functions */
 static void
 gl_symbols(void)
@@ -362,6 +352,8 @@ evgl_eng_native_window_create(void *data)
    Render_Engine *re;
    struct gbm_surface *surface;
    Evas_Engine_Info_GL_Drm *info;
+   unsigned int format = GBM_FORMAT_XRGB8888;
+   unsigned int flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
 
    re = (Render_Engine *)data;
    if (!re)
@@ -377,9 +369,9 @@ evgl_eng_native_window_create(void *data)
         return NULL;
      }
 
-   surface = gbm_surface_create(info->info.gbm,
-                                eng_get_ob(re)->w, eng_get_ob(re)->h,
-                                info->info.format, info->info.flags);
+   surface =
+     gbm_surface_create(info->info.gbm,
+                        eng_get_ob(re)->w, eng_get_ob(re)->h, format, flags);
    if (!surface)
      {
         ERR("Could not create gl drm window");
@@ -786,6 +778,37 @@ _native_cb_free(void *image)
    free(n);
 }
 
+static void
+_cb_vblank(int fd, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data)
+{
+   evas_outbuf_vblank(data, fd);
+}
+
+static void
+_cb_page_flip(int fd, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data)
+{
+   evas_outbuf_page_flip(data, fd);
+}
+
+static Eina_Bool
+_cb_drm_event(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED)
+{
+   Render_Engine *re;
+   int ret;
+
+   re = data;
+   if (!re) return EINA_TRUE;
+
+   ret = drmHandleEvent(re->fd, &re->ctx);
+   if (ret)
+     {
+        ERR("drmHandleEvent failed to read an event: %m");
+        return EINA_FALSE;
+     }
+
+   return EINA_TRUE;
+}
+
 /* engine specific override functions */
 static void *
 eng_info(Evas *eo_e EINA_UNUSED)
@@ -899,6 +922,17 @@ eng_setup(Evas *evas, void *in)
              return 0;
           }
 
+        re->fd = info->info.fd;
+
+        memset(&re->ctx, 0, sizeof(re->ctx));
+        re->ctx.version = DRM_EVENT_CONTEXT_VERSION;
+        re->ctx.vblank_handler = _cb_vblank;
+        re->ctx.page_flip_handler = _cb_page_flip;
+
+        re->hdlr =
+          ecore_main_fd_handler_add(info->info.fd, ECORE_FD_READ,
+                                    _cb_drm_event, re, NULL, NULL);
+
         /* try to create new outbuf */
         ob = evas_outbuf_new(info, epd->output.w, epd->output.h, swap_mode);
         if (!ob)
@@ -970,16 +1004,16 @@ eng_setup(Evas *evas, void *in)
                   re->generic.software.ob = NULL;
                   gl_wins--;
 
+                  if (ob_old) evas_outbuf_free(ob_old);
+
                   ob = evas_outbuf_new(info, epd->output.w, epd->output.h, swap_mode);
                   if (!ob)
                     {
-                       if (ob_old) evas_outbuf_free(ob_old);
                        free(re);
                        return 0;
                     }
 
                   evas_outbuf_use(ob);
-                  if (ob_old) evas_outbuf_free(ob_old);
 
                   ob->evas = evas;
 
@@ -1439,6 +1473,8 @@ module_open(Evas_Module *em)
         return 0;
      }
 
+   ecore_init();
+
    /* store it for later use */
    func = pfunc;
 
@@ -1471,6 +1507,8 @@ module_close(Evas_Module *em EINA_UNUSED)
    /* unregister the eina log domain for this engine */
    eina_log_domain_unregister(_evas_engine_gl_drm_log_dom);
    _evas_engine_gl_drm_log_dom = -1;
+
+   ecore_shutdown();
 }
 
 static Evas_Module_Api evas_modapi =
index f45a199..8a51d59 100644 (file)
@@ -7,6 +7,11 @@
 # include "Evas.h"
 # include "Evas_Engine_GL_Drm.h"
 
+# include <Ecore.h>
+# include <drm_fourcc.h>
+# include <xf86drm.h>
+# include <xf86drmMode.h>
+
 # define EGL_EGLEXT_PROTOTYPES
 # define GL_GLEXT_PROTOTYPES
 
@@ -64,6 +69,10 @@ typedef struct _Render_Engine Render_Engine;
 struct _Render_Engine
 {
    Render_Engine_GL_Generic generic;
+
+   int fd;
+   drmEventContext ctx;
+   Ecore_Fd_Handler *hdlr;
 };
 
 struct _Context_3D
@@ -80,11 +89,10 @@ struct _Outbuf
 
    Evas *evas; // used for pre_swap, post_swap
 
-   int w, h;
-   unsigned int rotation, depth;
+   int fd, w, h, bpp;
+   unsigned int rotation, depth, format;
    Render_Engine_Swap_Mode swap_mode;
 
-   /* struct gbm_device *gbm; */
    struct gbm_surface *surface;
 
    struct 
@@ -98,6 +106,7 @@ struct _Outbuf
    struct 
      {
         struct gbm_bo *bo[2];
+        Ecore_Drm2_Output *output;
      } priv;
 
    Eina_Bool destination_alpha : 1;
@@ -123,6 +132,9 @@ void *evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int
 void evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h);
 void evas_outbuf_update_region_free(Outbuf *ob, RGBA_Image *update);
 void evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode);
+void evas_outbuf_vblank(void *data, int fd);
+void evas_outbuf_page_flip(void *data, int fd);
+
 Evas_Engine_GL_Context* evas_outbuf_gl_context_get(Outbuf *ob);
 void *evas_outbuf_egl_display_get(Outbuf *ob);
 Context_3D *evas_outbuf_gl_context_new(Outbuf *ob);
@@ -138,6 +150,12 @@ _re_wincheck(Outbuf *ob)
    return EINA_FALSE;
 }
 
+static inline Outbuf *
+eng_get_ob(Render_Engine *re)
+{
+   return re->generic.software.ob;
+}
+
 extern unsigned int (*glsym_eglSwapBuffersWithDamage)(EGLDisplay a, void *b, const EGLint *d, EGLint c);
 extern unsigned int (*glsym_eglSetDamageRegionKHR)(EGLDisplay a, EGLSurface b, EGLint *c, EGLint d);
 
index b120216..ad3f2a0 100644 (file)
@@ -5,6 +5,7 @@
 static Outbuf *_evas_gl_drm_window = NULL;
 static EGLContext context = EGL_NO_CONTEXT;
 static int win_count = 0;
+static Eina_Bool ticking = EINA_FALSE;
 
 #ifdef EGL_MESA_platform_gbm
 static PFNEGLGETPLATFORMDISPLAYEXTPROC dlsym_eglGetPlatformDisplayEXT = NULL;
@@ -12,6 +13,79 @@ static PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC dlsym_eglCreatePlatformWindowSur
 #endif
 
 static void
+_outbuf_tick_schedule(int fd, void *data)
+{
+   if (!ticking) return;
+
+   drmVBlank vbl =
+     {
+        .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT,
+        .request.sequence = 1,
+        .request.signal = (unsigned long)data,
+     };
+
+   drmWaitVBlank(fd, &vbl);
+}
+
+static void
+_outbuf_tick_begin(void *data)
+{
+   Outbuf *ob;
+
+   ob = data;
+   ticking = EINA_TRUE;
+   if (ob) _outbuf_tick_schedule(ob->fd, ob);
+}
+
+static void
+_outbuf_tick_end(void *data EINA_UNUSED)
+{
+   ticking = EINA_FALSE;
+}
+
+static void
+_outbuf_tick_source_set(Outbuf *ob)
+{
+   if (ob)
+     {
+        ecore_animator_custom_source_tick_begin_callback_set
+          (_outbuf_tick_begin, ob);
+        ecore_animator_custom_source_tick_end_callback_set
+          (_outbuf_tick_end, ob);
+        ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM);
+     }
+   else
+     {
+        ecore_animator_custom_source_tick_begin_callback_set(NULL, NULL);
+        ecore_animator_custom_source_tick_end_callback_set(NULL, NULL);
+        ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER);
+     }
+}
+
+void
+evas_outbuf_vblank(void *data, int fd)
+{
+   ecore_animator_custom_tick();
+   if (ticking) _outbuf_tick_schedule(fd, data);
+}
+
+void
+evas_outbuf_page_flip(void *data, int fd EINA_UNUSED)
+{
+   Outbuf *ob;
+   Ecore_Drm2_Fb *next;
+
+   ob = data;
+   next = ecore_drm2_output_next_fb_get(ob->priv.output);
+   if (next)
+     {
+        ecore_drm2_output_next_fb_set(ob->priv.output, NULL);
+        if (ecore_drm2_fb_flip(next, ob->priv.output, ob) < 0)
+          _outbuf_tick_source_set(NULL);
+     }
+}
+
+static void
 _evas_outbuf_gbm_surface_destroy(Outbuf *ob)
 {
    if (!ob) return;
@@ -25,63 +99,51 @@ _evas_outbuf_gbm_surface_destroy(Outbuf *ob)
 static void
 _evas_outbuf_gbm_surface_create(Outbuf *ob, int w, int h)
 {
+   unsigned int format = GBM_FORMAT_XRGB8888;
+   unsigned int flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
+
    if (!ob) return;
 
    ob->surface =
-     gbm_surface_create(ob->info->info.gbm, w, h,
-                        ob->info->info.format, ob->info->info.flags);
+     gbm_surface_create(ob->info->info.gbm, w, h, format, flags);
 
    if (!ob->surface) ERR("Failed to create gbm surface");
 }
 
 static void
-_evas_outbuf_fb_cb_destroy(struct gbm_bo *bo, void *data)
+_evas_outbuf_fb_cb_destroy(struct gbm_bo *bo EINA_UNUSED, void *data)
 {
-   Ecore_Drm_Fb *fb;
+   Ecore_Drm2_Fb *fb;
 
    fb = data;
-   if (fb)
-     {
-        struct gbm_device *gbm;
-
-        gbm = gbm_bo_get_device(bo);
-        drmModeRmFB(gbm_device_get_fd(gbm), fb->id);
-        free(fb);
-     }
+   if (fb) ecore_drm2_fb_destroy(fb);
 }
 
-static Ecore_Drm_Fb *
-_evas_outbuf_fb_get(Ecore_Drm_Device *dev, struct gbm_bo *bo)
+static Ecore_Drm2_Fb *
+_evas_outbuf_fb_get(Outbuf *ob, struct gbm_bo *bo)
 {
-   int ret;
-   Ecore_Drm_Fb *fb;
-   uint32_t format;
-   uint32_t handles[4], pitches[4], offsets[4];
+   Ecore_Drm2_Fb *fb;
+   uint32_t format, hdl, stride;
+   int w, h;
 
    fb = gbm_bo_get_user_data(bo);
    if (fb) return fb;
 
-   if (!(fb = calloc(1, sizeof(Ecore_Drm_Fb)))) return NULL;
-
    format = gbm_bo_get_format(bo);
-
-   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;
-
-   handles[0] = fb->hdl;
-   pitches[0] = fb->stride;
-   offsets[0] = 0;
-
-   ret = drmModeAddFB2(dev->drm.fd, fb->w, fb->h, format,
-                       handles, pitches, offsets, &(fb->id), 0);
-   if (ret)
-     ret = drmModeAddFB(dev->drm.fd, fb->w, fb->h, 24, 32,
-                        fb->stride, fb->hdl, &(fb->id));
-
-   if (ret) ERR("FAILED TO ADD FB: %m");
+   w = gbm_bo_get_width(bo);
+   h = gbm_bo_get_height(bo);
+   hdl = gbm_bo_get_handle(bo).u32;
+   stride = gbm_bo_get_stride(bo);
+   /* fb->size = fb->stride * fb->h; */
+
+   fb =
+     ecore_drm2_fb_gbm_create(ob->fd, w, h, ob->depth, ob->bpp,
+                              format, hdl, stride);
+   if (!fb)
+     {
+        ERR("Failed to create FBO");
+        return NULL;
+     }
 
    gbm_bo_set_user_data(bo, fb, _evas_outbuf_fb_cb_destroy);
 
@@ -91,7 +153,9 @@ _evas_outbuf_fb_get(Ecore_Drm_Device *dev, struct gbm_bo *bo)
 static void
 _evas_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count)
 {
-   Ecore_Drm_Fb *fb;
+   Ecore_Drm2_Fb *fb;
+
+   if (ob->priv.bo[1]) gbm_surface_release_buffer(ob->surface, ob->priv.bo[1]);
 
    /* Repulsive hack:  Right now we don't actually have a proper way to retire
     * buffers because the ticker and the flip handler are out of sync, the
@@ -106,15 +170,48 @@ _evas_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count)
    ob->priv.bo[0] = gbm_surface_lock_front_buffer(ob->surface);
    if (!ob->priv.bo[0])
      {
-        WRN("Could not lock front buffer");
+        WRN("Could not lock front buffer: %m");
         return;
      }
-   fb = _evas_outbuf_fb_get(ob->info->info.dev, ob->priv.bo[0]);
+
+   fb = _evas_outbuf_fb_get(ob, ob->priv.bo[0]);
    if (fb)
      {
-        ecore_drm_fb_dirty(fb, rects, count);
-        ecore_drm_fb_send(ob->info->info.dev, fb, NULL, NULL);
+        ecore_drm2_fb_dirty(fb, rects, count);
+        if (ecore_drm2_fb_flip(fb, ob->priv.output, ob) < 0)
+          _outbuf_tick_source_set(NULL);
+
+        /* Ecore_Drm2_Plane *plane; */
+
+        /* plane = ecore_drm2_plane_find(ob->priv.output, fb, ob->format); */
+        /* if (plane) */
+        /*   { */
+        /*      int ret; */
+        /*      drmVBlank vbl = */
+        /*        { */
+        /*           .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, */
+        /*           .request.sequence = 1, */
+        /*        }; */
+
+        /*      vbl.request.type |= ecore_drm2_output_vblank_get(ob->priv.output); */
+        /*      vbl.request.signal = (unsigned long)ob; */
+
+        /*      ecore_drm2_fb_dirty(fb, rects, count); */
+
+        /*      if (!ecore_drm2_plane_fb_set(plane, fb)) */
+        /*        { */
+        /*           ERR("Failed to set FB on Plane"); */
+        /*           return; */
+        /*        } */
+
+        /*      ret = drmWaitVBlank(ob->fd, &vbl); */
+        /*      if (ret) return; */
+        /*   } */
+        /* else */
+        /*   WRN("NO PLANE FOUND"); */
      }
+   else
+     WRN("Could not get FBO from Bo");
 }
 
 static Eina_Bool
@@ -253,9 +350,6 @@ _evas_outbuf_egl_setup(Outbuf *ob)
              return EINA_FALSE;
           }
 
-        DBG("Config Format: %d", format);
-        DBG("OB Format: %d", ob->info->info.format);
-
         if (format == (int)ob->info->info.format)
           {
              ob->egl.config = cfgs[i];
@@ -369,6 +463,11 @@ evas_outbuf_new(Evas_Engine_Info_GL_Drm *info, int w, int h, Render_Engine_Swap_
    /* ob->vsync = info->info.vsync; */
    ob->swap_mode = swap_mode;
 
+   ob->fd = info->info.fd;
+   ob->bpp = info->info.bpp;
+   ob->format = info->info.format;
+   ob->priv.output = info->info.output;
+
    /* if ((num = getenv("EVAS_GL_DRM_VSYNC"))) */
    /*   ob->vsync = atoi(num); */
 
@@ -383,6 +482,8 @@ evas_outbuf_new(Evas_Engine_Info_GL_Drm *info, int w, int h, Render_Engine_Swap_
         return NULL;
      }
 
+   _outbuf_tick_source_set(ob);
+
    return ob;
 }
 
@@ -577,9 +678,7 @@ evas_outbuf_buffer_state_get(Outbuf *ob)
         return swap_mode;
      }
    else
-     {
-        return MODE_FULL;
-     }
+     return MODE_FULL;
 
    return ob->swap_mode;
 }