Add support for wayland opengles compositing accepted/tizen/common/20150410.071835 accepted/tizen/mobile/20150410.075339 accepted/tizen/tv/20150410.075156 accepted/tizen/wearable/20150410.075251 submit/tizen/20150409.161222
authorGwanglim Lee <gl77.lee@samsung.com>
Thu, 9 Apr 2015 13:42:28 +0000 (22:42 +0900)
committerGwanglim Lee <gl77.lee@samsung.com>
Thu, 9 Apr 2015 13:42:28 +0000 (22:42 +0900)
Change-Id: Ibcfe29ba861863b7738e80401fca5825bb5b4d14

src/bin/e_comp_wl.c
src/bin/e_comp_wl.h
src/bin/e_pixmap.c
src/modules/wl_drm/e_mod_main.c

index a43fd01b3b70e956dc5d73424bf629fa7dfdd300..805906b65825b44e25a4ee7342b712fe3e013044 100644 (file)
@@ -1083,10 +1083,24 @@ _e_comp_wl_surface_state_commit(E_Client *ec, E_Comp_Wl_Surface_State *state)
    /* put state damages into surface */
    if ((!ec->comp->nocomp) && (ec->frame))
      {
-        EINA_LIST_FREE(state->damages, dmg)
+        /* FIXME: workaround for bad wayland egl driver which doesn't send damage request */
+        if (!eina_list_count(state->damages))
           {
-             e_comp_object_damage(ec->frame, dmg->x, dmg->y, dmg->w, dmg->h);
-             eina_rectangle_free(dmg);
+             if (ec->comp_data->buffer_ref.buffer->type == E_COMP_WL_BUFFER_TYPE_NATIVE)
+               {
+                  e_comp_object_damage(ec->frame,
+                                       0, 0,
+                                       ec->comp_data->buffer_ref.buffer->w,
+                                       ec->comp_data->buffer_ref.buffer->h);
+               }
+          }
+        else
+          {
+             EINA_LIST_FREE(state->damages, dmg)
+               {
+                  e_comp_object_damage(ec->frame, dmg->x, dmg->y, dmg->w, dmg->h);
+                  eina_rectangle_free(dmg);
+               }
           }
      }
 
@@ -2349,6 +2363,83 @@ _e_comp_wl_cb_output_bind(struct wl_client *client, void *data, uint32_t version
      wl_output_send_done(resource);
 }
 
+static void
+_e_comp_wl_gl_init(E_Comp_Data *cdata)
+{
+   Evas_GL *evasgl = NULL;
+   Evas_GL_API *glapi = NULL;
+   Evas_GL_Context *ctx = NULL;
+   Evas_GL_Surface *sfc = NULL;
+   Evas_GL_Config *cfg = NULL;
+   Eina_Bool res;
+   const char *name;
+
+   if (!e_comp_gl_get()) return;
+
+   name = ecore_evas_engine_name_get(e_comp->ee);
+   if (!name) return;
+   if (strcmp(name, "gl_drm")) return;
+
+   /* create dummy evas gl to bind wayland display of enlightenment to egl display */
+   evasgl = evas_gl_new(e_comp->evas);
+   EINA_SAFETY_ON_NULL_GOTO(evasgl, err);
+
+   glapi = evas_gl_api_get(evasgl);
+   EINA_SAFETY_ON_NULL_GOTO(glapi, err);
+
+   cfg = evas_gl_config_new();
+   EINA_SAFETY_ON_NULL_GOTO(cfg, err);
+
+   sfc = evas_gl_surface_create(evasgl, cfg, 1, 1);
+   EINA_SAFETY_ON_NULL_GOTO(sfc, err);
+
+   ctx = evas_gl_context_create(evasgl, NULL);
+   EINA_SAFETY_ON_NULL_GOTO(ctx, err);
+
+   res = evas_gl_make_current(evasgl, sfc, ctx);
+   EINA_SAFETY_ON_FALSE_GOTO(res, err);
+
+   res = glapi->evasglBindWaylandDisplay(evasgl, cdata->wl.disp);
+   EINA_SAFETY_ON_FALSE_GOTO(res, err);
+
+   evas_gl_config_free(cfg);
+
+   cdata->gl.evasgl = evasgl;
+   cdata->gl.api = glapi;
+   cdata->gl.sfc = sfc;
+   cdata->gl.ctx = ctx;
+
+   /* for native surface */
+   e_comp->gl = 1;
+
+   return;
+
+err:
+   evas_gl_config_free(cfg);
+   evas_gl_make_current(evasgl, NULL, NULL);
+   evas_gl_context_destroy(evasgl, ctx);
+   evas_gl_surface_destroy(evasgl, sfc);
+   evas_gl_free(evasgl);
+}
+
+static void
+_e_comp_wl_gl_shutdown(E_Comp_Data *cdata)
+{
+   if (!cdata->gl.evasgl) return;
+
+   cdata->gl.api->evasglUnbindWaylandDisplay(cdata->gl.evasgl, cdata->wl.disp);
+
+   evas_gl_make_current(cdata->gl.evasgl, NULL, NULL);
+   evas_gl_context_destroy(cdata->gl.evasgl, cdata->gl.ctx);
+   evas_gl_surface_destroy(cdata->gl.evasgl, cdata->gl.sfc);
+   evas_gl_free(cdata->gl.evasgl);
+
+   cdata->gl.sfc = NULL;
+   cdata->gl.ctx = NULL;
+   cdata->gl.api = NULL;
+   cdata->gl.evasgl = NULL;
+}
+
 static Eina_Bool
 _e_comp_wl_compositor_create(void)
 {
@@ -2438,6 +2529,8 @@ _e_comp_wl_compositor_create(void)
         goto input_err;
      }
 
+   _e_comp_wl_gl_init(cdata);
+
 #ifndef HAVE_WAYLAND_ONLY
    if (getenv("DISPLAY"))
      {
@@ -2611,6 +2704,11 @@ e_comp_wl_surface_create_signal_get(E_Comp *comp)
 EINTERN void
 e_comp_wl_shutdown(void)
 {
+   /* free evas gl */
+   E_Comp_Data *cdata;
+   if ((cdata = e_comp->wl_comp_data))
+     _e_comp_wl_gl_shutdown(cdata);
+
 #ifndef HAVE_WAYLAND_ONLY
    _e_comp_wl_compositor_cb_del(e_comp);
 #endif
@@ -2758,20 +2856,50 @@ e_comp_wl_buffer_reference(E_Comp_Wl_Buffer_Ref *ref, E_Comp_Wl_Buffer *buffer)
 EAPI E_Comp_Wl_Buffer *
 e_comp_wl_buffer_get(struct wl_resource *resource)
 {
-   E_Comp_Wl_Buffer *buffer;
+   E_Comp_Wl_Buffer *buffer = NULL;
    struct wl_listener *listener;
    struct wl_shm_buffer *shmbuff;
+   E_Comp_Data *cdata;
+   Eina_Bool res;
 
    listener =
      wl_resource_get_destroy_listener(resource, _e_comp_wl_buffer_cb_destroy);
    if (listener)
      return container_of(listener, E_Comp_Wl_Buffer, destroy_listener);
 
-   if (!(shmbuff = wl_shm_buffer_get(resource))) return NULL;
    if (!(buffer = E_NEW(E_Comp_Wl_Buffer, 1))) return NULL;
 
-   buffer->w = wl_shm_buffer_get_width(shmbuff);
-   buffer->h = wl_shm_buffer_get_height(shmbuff);
+   shmbuff = wl_shm_buffer_get(resource);
+
+   if (shmbuff)
+     {
+        buffer->type = E_COMP_WL_BUFFER_TYPE_SHM;
+
+        buffer->w = wl_shm_buffer_get_width(shmbuff);
+        buffer->h = wl_shm_buffer_get_height(shmbuff);
+     }
+   else
+     {
+        cdata = e_comp->wl_comp_data;
+        if (cdata->gl.api)
+          {
+             buffer->type = E_COMP_WL_BUFFER_TYPE_NATIVE;
+
+             res = cdata->gl.api->evasglQueryWaylandBuffer(cdata->gl.evasgl,
+                                                           resource,
+                                                           EVAS_GL_WIDTH,
+                                                           &buffer->w);
+             EINA_SAFETY_ON_FALSE_GOTO(res, err);
+
+             res = cdata->gl.api->evasglQueryWaylandBuffer(cdata->gl.evasgl,
+                                                           resource,
+                                                           EVAS_GL_HEIGHT,
+                                                           &buffer->h);
+             EINA_SAFETY_ON_FALSE_GOTO(res, err);
+          }
+        else
+          goto err;
+     }
 
    buffer->resource = resource;
    wl_signal_init(&buffer->destroy_signal);
@@ -2779,6 +2907,11 @@ e_comp_wl_buffer_get(struct wl_resource *resource)
    wl_resource_add_destroy_listener(resource, &buffer->destroy_listener);
 
    return buffer;
+
+err:
+   ERR("Invalid resource:%u", wl_resource_get_id(resource));
+   E_FREE(buffer);
+   return NULL;
 }
 
 /**
index 5d0143c2475a4ef6c18bc23f248221c5605fa40f..a888a7eeeb5e38c77860f65c29506d2f787183fe 100644 (file)
@@ -36,6 +36,8 @@
       (type *)( (char *)__mptr - offsetof(type,member) ); \
    })
 
+#include <Evas_GL.h>
+
 typedef struct _E_Comp_Wl_Buffer E_Comp_Wl_Buffer;
 typedef struct _E_Comp_Wl_Buffer_Ref E_Comp_Wl_Buffer_Ref;
 typedef struct _E_Comp_Wl_Subsurf_Data E_Comp_Wl_Subsurf_Data;
@@ -44,16 +46,20 @@ typedef struct _E_Comp_Wl_Client_Data E_Comp_Wl_Client_Data;
 typedef struct _E_Comp_Wl_Data E_Comp_Wl_Data;
 typedef struct _E_Comp_Wl_Output E_Comp_Wl_Output;
 
+typedef enum _E_Comp_Wl_Buffer_Type
+{
+   E_COMP_WL_BUFFER_TYPE_NONE = 0,
+   E_COMP_WL_BUFFER_TYPE_SHM = 1,
+   E_COMP_WL_BUFFER_TYPE_NATIVE = 2
+} E_Comp_Wl_Buffer_Type;
+
 struct _E_Comp_Wl_Buffer
 {
+   E_Comp_Wl_Buffer_Type type;
    struct wl_resource *resource;
    struct wl_signal destroy_signal;
    struct wl_listener destroy_listener;
-   union
-     {
-        struct wl_shm_buffer *shm_buffer;
-        void *legacy_buffer;
-     };
+   struct wl_shm_buffer *shm_buffer;
    int32_t w, h;
    uint32_t busy;
 };
@@ -205,6 +211,14 @@ struct _E_Comp_Wl_Data
         char *area;
      } xkb;
 
+   struct
+     {
+        Evas_GL *evasgl;
+        Evas_GL_API *api;
+        Evas_GL_Surface *sfc;
+        Evas_GL_Context *ctx;
+     } gl;
+
    Eina_List *outputs;
 
    Ecore_Fd_Handler *fd_hdlr;
index fdfe61939e5f44341d35e9fce444a0990a5daad1..5bb244503af166d01ca5f13b93817ef9ee6db178 100644 (file)
@@ -531,30 +531,56 @@ e_pixmap_resource_set(E_Pixmap *cp, void *resource)
 
         if (!buffer) return;
 
-        if (!(shm_buffer = wl_shm_buffer_get(buffer->resource)))
+        if (buffer->type == E_COMP_WL_BUFFER_TYPE_SHM)
           {
-             WRN("Cannot get shm buffer from buffer resource");
-             e_comp_wl_buffer_reference(&cp->buffer_ref, NULL);
-             return;
-          }
+             shm_buffer = wl_shm_buffer_get(buffer->resource);
+             if (!shm_buffer)
+               {
+                  ERR("No shm_buffer resource:%u", wl_resource_get_id(buffer->resource));
+                  e_comp_wl_buffer_reference(&cp->buffer_ref, NULL);
+                  return;
+               }
 
-        buffer->shm_buffer = shm_buffer;
-        cp->w = buffer->w;
-        cp->h = buffer->h;
-        /* buffer->w = cp->w = wl_shm_buffer_get_width(shm_buffer); */
-        /* buffer->h = cp->h = wl_shm_buffer_get_height(shm_buffer); */
+             buffer->shm_buffer = shm_buffer;
+             cp->w = buffer->w;
+             cp->h = buffer->h;
 
-        switch (wl_shm_buffer_get_format(shm_buffer))
-          {
-           case WL_SHM_FORMAT_ARGB8888:
-             cp->image_argb = EINA_TRUE;
-             break;
-           default:
-             cp->image_argb = EINA_FALSE;
-             break;
+             switch (wl_shm_buffer_get_format(shm_buffer))
+               {
+                case WL_SHM_FORMAT_ARGB8888:
+                   cp->image_argb = EINA_TRUE;
+                   break;
+                default:
+                   cp->image_argb = EINA_FALSE;
+                   break;
+               }
+
+             cp->data = wl_shm_buffer_get_data(shm_buffer);
           }
+        else if (buffer->type == E_COMP_WL_BUFFER_TYPE_NATIVE)
+          {
+             if (e_comp->gl)
+               {
+                  buffer->shm_buffer = NULL;
+                  cp->w = buffer->w;
+                  cp->h = buffer->h;
+                  cp->image_argb = EINA_FALSE; /* TODO: format */
+                  cp->data = NULL;
+               }
+             else
+               {
+                  ERR("Invalid native buffer resource:%u", wl_resource_get_id(buffer->resource));
+                  e_comp_wl_buffer_reference(&cp->buffer_ref, NULL);
+                  return;
+               }
 
-        cp->data = wl_shm_buffer_get_data(shm_buffer);
+          }
+        else
+          {
+             ERR("Invalid resource:%u", wl_resource_get_id(buffer->resource));
+             e_comp_wl_buffer_reference(&cp->buffer_ref, NULL);
+             return;
+          }
 
         cp->buffer_destroy_listener.notify = _e_pixmap_cb_buffer_destroy;
         wl_signal_add(&buffer->destroy_signal, &cp->buffer_destroy_listener);
@@ -592,15 +618,15 @@ e_pixmap_native_surface_init(E_Pixmap *cp, Evas_Native_Surface *ns)
         break;
       case E_PIXMAP_TYPE_WL:
 #if defined(HAVE_WAYLAND_CLIENTS) || defined(HAVE_WAYLAND_ONLY)
-        ns->type = EVAS_NATIVE_SURFACE_OPENGL;
-        ns->version = EVAS_NATIVE_SURFACE_VERSION;
-        ns->data.opengl.texture_id = 0;
-        ns->data.opengl.framebuffer_id = 0;
-        ns->data.opengl.x = 0;
-        ns->data.opengl.y = 0;
-        ns->data.opengl.w = cp->w;
-        ns->data.opengl.h = cp->h;
-        ret = EINA_TRUE;
+        if (cp->buffer_ref.buffer->type == E_COMP_WL_BUFFER_TYPE_NATIVE)
+          {
+             ns->type = EVAS_NATIVE_SURFACE_WL;
+             ns->version = EVAS_NATIVE_SURFACE_VERSION;
+             ns->data.wl.legacy_buffer = cp->buffer_ref.buffer->resource;
+             ret = EINA_TRUE;
+          }
+        else
+          ret = EINA_FALSE;
 #endif
         break;
       default:
index 5cc32b3ec016b18869ea0ea6e464217b8a400f0d..85d69a17714d2d9799211a002867af1ce0f698af 100644 (file)
@@ -79,34 +79,47 @@ EAPI void *
 e_modapi_init(E_Module *m)
 {
    E_Comp *comp;
-   int w = 0, h = 0;
+   int w = 0, h = 0, scr_w = 0, scr_h = 0;
+   char *env_w, *env_h;
 
    printf("LOAD WL_DRM MODULE\n");
 
-   /* try to init ecore_drm */
-   /* if (!ecore_drm_init()) */
-   /*   { */
-   /*      fprintf(stderr, "Could not initialize ecore_drm"); */
-   /*      return NULL; */
-   /*   } */
-
    if (!(comp = e_comp))
      {
         comp = e_comp_new();
         comp->comp_type = E_PIXMAP_TYPE_WL;
      }
 
+   /* set gl available if we have ecore_evas support */
+   if (ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_WAYLAND_EGL) ||
+       ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_OPENGL_DRM))
+     e_comp_gl_set(EINA_TRUE);
+
+   if ((env_w = getenv("E_SCREEN_WIDTH"))) scr_w = atoi(env_w);
+   if ((env_h = getenv("E_SCREEN_HEIGHT"))) scr_h = atoi(env_h);
+
+   if (scr_w <= 0) scr_w = 1;
+   if (scr_h <= 0) scr_h = 1;
+
+   DBG("GL available:%d config engine:%d screen size:%dx%d",
+       e_comp_gl_get(), e_comp_config_get()->engine, scr_w, scr_h);
+
    if ((e_comp_gl_get()) &&
        (e_comp_config_get()->engine == E_COMP_ENGINE_GL))
      {
-        comp->ee = ecore_evas_gl_drm_new(NULL, 0, 0, 0, 1, 1);
+        comp->ee = ecore_evas_gl_drm_new(NULL, 0, 0, 0, scr_w, scr_h);
+        DBG("Create ecore_evas_gl_drm canvas:%p", comp->ee);
+
         if (!comp->ee)
           e_comp_gl_set(EINA_FALSE);
      }
 
    /* fallback to framebuffer drm (non-accel) */
    if (!comp->ee)
-     comp->ee = ecore_evas_drm_new(NULL, 0, 0, 0, 1, 1);
+     {
+        comp->ee = ecore_evas_drm_new(NULL, 0, 0, 0, scr_w, scr_h);
+        DBG("Create ecore_evas_drm canvas:%p", comp->ee);
+     }
 
    if (!comp->ee)
      {
@@ -118,7 +131,11 @@ e_modapi_init(E_Module *m)
    ecore_evas_screen_geometry_get(comp->ee, NULL, NULL, &w, &h);
 
    /* resize the canvas */
-   ecore_evas_resize(comp->ee, w, h);
+   if (!((scr_w == w) && (scr_h == h)))
+     {
+        DBG("Change ecore_evas canvas size %dx%d -> %dx%d", scr_w, scr_h, w, h);
+        ecore_evas_resize(comp->ee, w, h);
+     }
 
    /* TODO: hook ecore_evas_callback_resize_set */