Add evas_wl_main file.
authorChris Michael <cp.michael@samsung.com>
Fri, 31 May 2013 08:37:48 +0000 (09:37 +0100)
committerChris Michael <cp.michael@samsung.com>
Fri, 31 May 2013 08:43:23 +0000 (09:43 +0100)
Signed-off-by: Chris Michael <cp.michael@samsung.com>
src/modules/evas/engines/wayland_egl/evas_wl_main.c [new file with mode: 0644]

diff --git a/src/modules/evas/engines/wayland_egl/evas_wl_main.c b/src/modules/evas/engines/wayland_egl/evas_wl_main.c
new file mode 100644 (file)
index 0000000..9ef7670
--- /dev/null
@@ -0,0 +1,307 @@
+#include "evas_engine.h"
+
+/* local function prototypes */
+
+/* local variables */
+static Evas_GL_Wl_Window *_evas_gl_wl_window = NULL;
+static EGLContext context = EGL_NO_CONTEXT;
+static int win_count = 0;
+
+Evas_GL_Wl_Window *
+eng_window_new(struct wl_display *display, struct wl_surface *surface, int screen, int depth, int w, int h, int indirect EINA_UNUSED, int alpha, int rot)
+{
+   Evas_GL_Wl_Window *gw;
+   int context_attrs[3];
+   int config_attrs[40];
+   int major_version, minor_version;
+   int num_config, n = 0;
+   const GLubyte *vendor, *renderer, *version;
+   Eina_Bool blacklist = EINA_FALSE;
+
+   /* try to allocate space for our window */
+   if (!(gw = calloc(1, sizeof(Evas_GL_Wl_Window))))
+     return NULL;
+
+   win_count++;
+   gw->disp = display;
+   gw->surface = surface;
+   gw->screen = screen;
+   gw->depth = depth;
+   gw->w = w;
+   gw->h = h;
+   gw->alpha = alpha;
+   gw->rot = rot;
+
+   context_attrs[0] = EGL_CONTEXT_CLIENT_VERSION;
+   context_attrs[1] = 2;
+   context_attrs[2] = EGL_NONE;
+
+   config_attrs[n++] = EGL_SURFACE_TYPE;
+   config_attrs[n++] = EGL_WINDOW_BIT;
+   config_attrs[n++] = EGL_RENDERABLE_TYPE;
+   config_attrs[n++] = EGL_OPENGL_ES2_BIT;
+# if 0
+   /* FIXME: n900 - omap3 sgx libs break here */
+   config_attrs[n++] = EGL_RED_SIZE;
+   config_attrs[n++] = 1;
+   config_attrs[n++] = EGL_GREEN_SIZE;
+   config_attrs[n++] = 1;
+   config_attrs[n++] = EGL_BLUE_SIZE;
+   config_attrs[n++] = 1;
+   /* FIXME: end n900 breakage */
+# endif
+   config_attrs[n++] = EGL_ALPHA_SIZE;
+   config_attrs[n++] = gw->alpha;
+   config_attrs[n++] = EGL_DEPTH_SIZE;
+   config_attrs[n++] = 0;
+   config_attrs[n++] = EGL_STENCIL_SIZE;
+   config_attrs[n++] = 0;
+   config_attrs[n++] = EGL_NONE;
+
+   /* FIXME: Remove this line as soon as eglGetDisplay() autodetection
+    * gets fixed. Currently it is incorrectly detecting wl_display and
+    * returning _EGL_PLATFORM_X11 instead of _EGL_PLATFORM_WAYLAND.
+    *
+    * See ticket #1972 for more info.
+    */
+
+   setenv("EGL_PLATFORM", "wayland", 1);
+
+   gw->egl_disp = eglGetDisplay((EGLNativeDisplayType)gw->disp);
+   if (!gw->egl_disp)
+     {
+        ERR("eglGetDisplay() fail. code=%#x", eglGetError());
+        eng_window_free(gw);
+        return NULL;
+     }
+   if (!eglInitialize(gw->egl_disp, &major_version, &minor_version))
+     {
+        ERR("eglInitialize() fail. code=%#x", eglGetError());
+        eng_window_free(gw);
+        return NULL;
+     }
+   eglBindAPI(EGL_OPENGL_ES_API);
+   if (eglGetError() != EGL_SUCCESS)
+     {
+        ERR("eglBindAPI() fail. code=%#x", eglGetError());
+        eng_window_free(gw);
+        return NULL;
+     }
+
+   num_config = 0;
+   if (!eglChooseConfig(gw->egl_disp, config_attrs, &gw->egl_config,
+                        1, &num_config) || (num_config != 1))
+     {
+        ERR("eglChooseConfig() fail. code=%#x", eglGetError());
+        eng_window_free(gw);
+        return NULL;
+     }
+
+   if ((gw->rot == 0) || (gw->rot == 180))
+     gw->win = wl_egl_window_create(gw->surface, gw->w, gw->h);
+   else if ((gw->rot == 90) || (gw->rot == 270))
+     gw->win = wl_egl_window_create(gw->surface, gw->h, gw->w);
+
+   gw->egl_surface[0] = 
+     eglCreateWindowSurface(gw->egl_disp, gw->egl_config,
+                            (EGLNativeWindowType)gw->win, NULL);
+   if (gw->egl_surface[0] == EGL_NO_SURFACE)
+     {
+        ERR("eglCreateWindowSurface() fail for %p. code=%#x", 
+            gw->win, eglGetError());
+        eng_window_free(gw);
+        return NULL;
+     }
+
+   gw->egl_context[0] = 
+     eglCreateContext(gw->egl_disp, gw->egl_config, context, context_attrs);
+   if (gw->egl_context[0] == EGL_NO_CONTEXT)
+     {
+        ERR("eglCreateContext() fail. code=%#x", eglGetError());
+        eng_window_free(gw);
+        return NULL;
+     }
+
+   if (context == EGL_NO_CONTEXT) context = gw->egl_context[0];
+
+   if (eglMakeCurrent(gw->egl_disp, gw->egl_surface[0],
+                      gw->egl_surface[0], gw->egl_context[0]) == EGL_FALSE)
+     {
+        ERR("eglMakeCurrent() fail. code=%#x", eglGetError());
+        eng_window_free(gw);
+        return NULL;
+     }
+
+   vendor = glGetString(GL_VENDOR);
+   renderer = glGetString(GL_RENDERER);
+   version = glGetString(GL_VERSION);
+   if (!vendor) vendor   = (unsigned char *)"-UNKNOWN-";
+   if (!renderer) renderer = (unsigned char *)"-UNKNOWN-";
+   if (!version) version  = (unsigned char *)"-UNKNOWN-";
+   if (getenv("EVAS_GL_INFO"))
+     {
+        fprintf(stderr, "vendor: %s\n", vendor);
+        fprintf(stderr, "renderer: %s\n", renderer);
+        fprintf(stderr, "version: %s\n", version);
+     }
+
+   if (strstr((const char *)vendor, "Mesa Project"))
+     {
+        if (strstr((const char *)renderer, "Software Rasterizer"))
+          blacklist = EINA_TRUE;
+     }
+   if (strstr((const char *)renderer, "softpipe"))
+     blacklist = EINA_TRUE;
+   if (strstr((const char *)renderer, "llvmpipe"))
+     blacklist = EINA_TRUE;
+   if ((blacklist) && (!getenv("EVAS_GL_NO_BLACKLIST")))
+     {
+        ERR("OpenGL Driver blacklisted:");
+        ERR("Vendor: %s", (const char *)vendor);
+        ERR("Renderer: %s", (const char *)renderer);
+        ERR("Version: %s", (const char *)version);
+        eng_window_free(gw);
+        return NULL;
+     }
+
+   if (!(gw->gl_context = evas_gl_common_context_new()))
+     {
+        eng_window_free(gw);
+        return NULL;
+     }
+
+   gw->gl_context->egldisp = gw->egl_disp;
+   gw->gl_context->eglctxt = gw->egl_context[0];
+
+   eng_window_use(gw);
+   evas_gl_common_context_resize(gw->gl_context, w, h, rot);
+
+   gw->surf = EINA_TRUE;
+
+   return gw;
+}
+
+void 
+eng_window_free(Evas_GL_Wl_Window *gw)
+{
+   int ref = 0;
+
+   win_count--;
+   eng_window_use(gw);
+
+   if (gw == _evas_gl_wl_window) _evas_gl_wl_window = NULL;
+
+   if (gw->gl_context)
+     {
+        ref = gw->gl_context->references - 1;
+        evas_gl_common_context_free(gw->gl_context);
+     }
+
+   eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE, 
+                  EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+   if (gw->egl_context[0] != context)
+     eglDestroyContext(gw->egl_disp, gw->egl_context[0]);
+
+   if (gw->egl_surface[0] != EGL_NO_SURFACE)
+     eglDestroySurface(gw->egl_disp, gw->egl_surface[0]);
+
+   if (gw->win) wl_egl_window_destroy(gw->win);
+
+   if (ref == 0)
+     {
+        if (context) eglDestroyContext(gw->egl_disp, context);
+        eglTerminate(gw->egl_disp);
+        context = EGL_NO_CONTEXT;
+     }
+
+   free(gw);
+}
+
+void 
+eng_window_use(Evas_GL_Wl_Window *gw)
+{
+   Eina_Bool force = EINA_FALSE;
+
+   if (_evas_gl_wl_window)
+     {
+        if ((eglGetCurrentContext() != 
+             _evas_gl_wl_window->egl_context[0]) ||
+            (eglGetCurrentSurface(EGL_READ) != 
+                _evas_gl_wl_window->egl_surface[0]) ||
+            (eglGetCurrentSurface(EGL_DRAW) != 
+                _evas_gl_wl_window->egl_surface[0]))
+          force = EINA_TRUE;
+     }
+
+   if ((_evas_gl_wl_window != gw) || (force))
+     {
+        if (_evas_gl_wl_window)
+          {
+             evas_gl_common_context_use(_evas_gl_wl_window->gl_context);
+             evas_gl_common_context_flush(_evas_gl_wl_window->gl_context);
+          }
+
+        _evas_gl_wl_window = gw;
+
+        if (gw)
+          {
+             if (gw->egl_surface[0] != EGL_NO_SURFACE)
+               {
+                  if (eglMakeCurrent(gw->egl_disp, gw->egl_surface[0],
+                                     gw->egl_surface[0],
+                                     gw->egl_context[0]) == EGL_FALSE)
+                    ERR("eglMakeCurrent() failed!");
+               }
+          }
+     }
+
+   if (gw) evas_gl_common_context_use(gw->gl_context);
+}
+
+void 
+eng_window_unsurf(Evas_GL_Wl_Window *gw)
+{
+   if (!gw->surf) return;
+   if (!getenv("EVAS_GL_WIN_RESURF")) return;
+   if (getenv("EVAS_GL_INFO")) printf("unsurf %p\n", gw);
+
+   if (_evas_gl_wl_window)
+      evas_gl_common_context_flush(_evas_gl_wl_window->gl_context);
+   if (_evas_gl_wl_window == gw)
+     {
+        eglMakeCurrent(gw->egl_disp, EGL_NO_SURFACE, 
+                       EGL_NO_SURFACE, EGL_NO_CONTEXT);
+        if (gw->egl_surface[0] != EGL_NO_SURFACE)
+           eglDestroySurface(gw->egl_disp, gw->egl_surface[0]);
+        gw->egl_surface[0] = EGL_NO_SURFACE;
+
+        _evas_gl_wl_window = NULL;
+     }
+
+   gw->surf = EINA_FALSE;
+}
+
+void 
+eng_window_resurf(Evas_GL_Wl_Window *gw)
+{
+   if (gw->surf) return;
+   if (getenv("EVAS_GL_INFO")) printf("resurf %p\n", gw);
+
+   gw->egl_surface[0] = 
+     eglCreateWindowSurface(gw->egl_disp, gw->egl_config,
+                            (EGLNativeWindowType)gw->win, NULL);
+
+   if (gw->egl_surface[0] == EGL_NO_SURFACE)
+     {
+        ERR("eglCreateWindowSurface() fail for %p. code=%#x",
+            gw->win, eglGetError());
+        return;
+     }
+
+   if (eglMakeCurrent(gw->egl_disp, gw->egl_surface[0], gw->egl_surface[0],
+                      gw->egl_context[0]) == EGL_FALSE)
+     ERR("eglMakeCurrent() failed!");
+
+   gw->surf = EINA_TRUE;
+}