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 index 0000000000..9ef76705b6 --- /dev/null +++ b/src/modules/evas/engines/wayland_egl/evas_wl_main.c @@ -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; +}