From: Alexandros Frantzis alexandros.frantzis@collabora.com
Each WGL context is backed by a config-less EGL context. We require the EGL_KHR_no_config_context extension. --- dlls/winewayland.drv/opengl.c | 96 ++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-)
diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index c54deabf8ff..f0db6cbbfd2 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -54,8 +54,11 @@ static const char *opengl_func_names[] = { ALL_WGL_FUNCS }; #undef USE_GL_FUNC
#define DECL_FUNCPTR(f) static __typeof__(f) * p_##f = NULL +DECL_FUNCPTR(eglBindAPI); DECL_FUNCPTR(eglChooseConfig); +DECL_FUNCPTR(eglCreateContext); DECL_FUNCPTR(eglCreateWindowSurface); +DECL_FUNCPTR(eglDestroyContext); DECL_FUNCPTR(eglDestroySurface); DECL_FUNCPTR(eglGetConfigAttrib); DECL_FUNCPTR(eglGetError); @@ -67,6 +70,7 @@ DECL_FUNCPTR(eglQueryString);
static pthread_mutex_t gl_object_mutex = PTHREAD_MUTEX_INITIALIZER; static struct list gl_drawables = LIST_INIT(gl_drawables); +static struct list gl_contexts = LIST_INIT(gl_contexts);
struct wayland_gl_drawable { @@ -78,6 +82,30 @@ struct wayland_gl_drawable EGLSurface surface; };
+struct wgl_context +{ + struct list entry; + EGLConfig config; + EGLContext context; +}; + +static struct wayland_gl_drawable *wayland_gl_drawable_get(HWND hwnd) +{ + struct wayland_gl_drawable *gl, *ret = NULL; + + pthread_mutex_lock(&gl_object_mutex); + LIST_FOR_EACH_ENTRY(gl, &gl_drawables, struct wayland_gl_drawable, entry) + { + if (gl->hwnd != hwnd) continue; + InterlockedIncrement(&gl->ref); + ret = gl; + break; + } + pthread_mutex_unlock(&gl_object_mutex); + + return ret; +} + static void wayland_gl_drawable_release(struct wayland_gl_drawable *gl) { if (InterlockedDecrement(&gl->ref)) return; @@ -212,6 +240,57 @@ static BOOL set_pixel_format(HDC hdc, int format, BOOL internal) return TRUE; }
+static struct wgl_context *create_context(HDC hdc) +{ + struct wayland_gl_drawable *gl; + struct wgl_context *ctx; + + if (!(gl = wayland_gl_drawable_get(NtUserWindowFromDC(hdc)))) return NULL; + + if (!(ctx = calloc(1, sizeof(*ctx)))) + { + ERR("Failed to allocate memory for GL context\n"); + goto out; + } + + ctx->context = p_eglCreateContext(egl_display, EGL_NO_CONFIG_KHR, + EGL_NO_CONTEXT, NULL); + + pthread_mutex_lock(&gl_object_mutex); + list_add_head(&gl_contexts, &ctx->entry); + pthread_mutex_unlock(&gl_object_mutex); + + TRACE("ctx=%p egl_context=%p\n", ctx, ctx->context); + +out: + wayland_gl_drawable_release(gl); + return ctx; +} + +static BOOL wayland_wglCopyContext(struct wgl_context *src, + struct wgl_context *dst, UINT mask) +{ + FIXME("%p -> %p mask %#x unsupported\n", src, dst, mask); + return FALSE; +} + +static struct wgl_context *wayland_wglCreateContext(HDC hdc) +{ + TRACE("hdc=%p\n", hdc); + p_eglBindAPI(EGL_OPENGL_API); + return create_context(hdc); +} + +static BOOL wayland_wglDeleteContext(struct wgl_context *ctx) +{ + pthread_mutex_lock(&gl_object_mutex); + list_remove(&ctx->entry); + pthread_mutex_unlock(&gl_object_mutex); + p_eglDestroyContext(egl_display, ctx->context); + free(ctx); + return TRUE; +} + static BOOL has_opengl(void);
static int wayland_wglDescribePixelFormat(HDC hdc, int fmt, UINT size, @@ -400,7 +479,7 @@ static BOOL init_egl_configs(void) static void init_opengl(void) { EGLint egl_version[2]; - const char *egl_client_exts; + const char *egl_client_exts, *egl_exts;
if (!(egl_handle = dlopen(SONAME_LIBEGL, RTLD_NOW|RTLD_GLOBAL))) { @@ -433,8 +512,11 @@ static void init_opengl(void) if (!(p_##func = (__typeof__(func) *)p_eglGetProcAddress(#func))) \ { ERR("Failed to load symbol %s\n", #func); goto err; } \ } while(0) + LOAD_FUNCPTR_EGL(eglBindAPI); LOAD_FUNCPTR_EGL(eglChooseConfig); + LOAD_FUNCPTR_EGL(eglCreateContext); LOAD_FUNCPTR_EGL(eglCreateWindowSurface); + LOAD_FUNCPTR_EGL(eglDestroyContext); LOAD_FUNCPTR_EGL(eglDestroySurface); LOAD_FUNCPTR_EGL(eglGetConfigAttrib); LOAD_FUNCPTR_EGL(eglGetError); @@ -457,6 +539,15 @@ static void init_opengl(void) } TRACE("EGL version %u.%u\n", egl_version[0], egl_version[1]);
+ egl_exts = p_eglQueryString(egl_display, EGL_EXTENSIONS); +#define REQUIRE_EXT(ext) \ + do { \ + if (!has_extension(egl_exts, #ext)) \ + { ERR("Failed to find required extension %s\n", #ext); goto err; } \ + } while(0) + REQUIRE_EXT(EGL_KHR_no_config_context); +#undef REQUIRE_EXT + if (!init_opengl_funcs()) goto err; if (!init_egl_configs()) goto err;
@@ -478,6 +569,9 @@ static struct opengl_funcs opengl_funcs = { .wgl = { + .p_wglCopyContext = wayland_wglCopyContext, + .p_wglCreateContext = wayland_wglCreateContext, + .p_wglDeleteContext = wayland_wglDeleteContext, .p_wglDescribePixelFormat = wayland_wglDescribePixelFormat, .p_wglGetProcAddress = wayland_wglGetProcAddress, .p_wglSetPixelFormat = wayland_wglSetPixelFormat,