winewayland.drv: Implement wglSetPixelFormat(WINE).
Introduce the internal wayland_gl_drawable object, which associates a window (and its backing Wayland surface) with an EGL surface.
This commit is contained in:
parent
825ec8c597
commit
e7ccb1480a
7 changed files with 290 additions and 6 deletions
90
configure
vendored
90
configure
vendored
|
@ -702,6 +702,8 @@ INOTIFY_LIBS
|
|||
INOTIFY_CFLAGS
|
||||
PCSCLITE_LIBS
|
||||
PCAP_LIBS
|
||||
WAYLAND_EGL_LIBS
|
||||
WAYLAND_EGL_CFLAGS
|
||||
EGL_LIBS
|
||||
EGL_CFLAGS
|
||||
XKBREGISTRY_LIBS
|
||||
|
@ -1807,6 +1809,8 @@ XKBREGISTRY_CFLAGS
|
|||
XKBREGISTRY_LIBS
|
||||
EGL_CFLAGS
|
||||
EGL_LIBS
|
||||
WAYLAND_EGL_CFLAGS
|
||||
WAYLAND_EGL_LIBS
|
||||
INOTIFY_CFLAGS
|
||||
INOTIFY_LIBS
|
||||
DBUS_CFLAGS
|
||||
|
@ -2635,6 +2639,10 @@ Some influential environment variables:
|
|||
Linker flags for xkbregistry, overriding pkg-config
|
||||
EGL_CFLAGS C compiler flags for egl, overriding pkg-config
|
||||
EGL_LIBS Linker flags for egl, overriding pkg-config
|
||||
WAYLAND_EGL_CFLAGS
|
||||
C compiler flags for wayland-egl, overriding pkg-config
|
||||
WAYLAND_EGL_LIBS
|
||||
Linker flags for wayland-egl, overriding pkg-config
|
||||
INOTIFY_CFLAGS
|
||||
C compiler flags for libinotify, overriding pkg-config
|
||||
INOTIFY_LIBS
|
||||
|
@ -16266,11 +16274,89 @@ printf "%s\n" "#define SONAME_LIBEGL \"$ac_cv_lib_soname_EGL\"" >>confdefs.h
|
|||
fi
|
||||
fi
|
||||
|
||||
CPPFLAGS=$ac_save_CPPFLAGS
|
||||
|
||||
rm -f conftest.err
|
||||
if ${WAYLAND_EGL_CFLAGS:+false} :
|
||||
then :
|
||||
if test ${PKG_CONFIG+y}
|
||||
then :
|
||||
WAYLAND_EGL_CFLAGS=`$PKG_CONFIG --cflags wayland-egl 2>conftest.err`
|
||||
fi
|
||||
fi
|
||||
|
||||
if ${WAYLAND_EGL_LIBS:+false} :
|
||||
then :
|
||||
if test ${PKG_CONFIG+y}
|
||||
then :
|
||||
WAYLAND_EGL_LIBS=`$PKG_CONFIG --libs wayland-egl 2>/dev/null`
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: wayland-egl cflags: $WAYLAND_EGL_CFLAGS" >&5
|
||||
printf "%s\n" "$as_me:${as_lineno-$LINENO}: wayland-egl libs: $WAYLAND_EGL_LIBS" >&5
|
||||
if test -s conftest.err; then
|
||||
printf %s "$as_me:${as_lineno-$LINENO}: wayland-egl errors: " >&5
|
||||
cat conftest.err >&5
|
||||
fi
|
||||
rm -f conftest.err
|
||||
ac_save_CPPFLAGS=$CPPFLAGS
|
||||
CPPFLAGS="$CPPFLAGS $WAYLAND_EGL_CFLAGS"
|
||||
ac_fn_c_check_header_compile "$LINENO" "wayland-egl.h" "ac_cv_header_wayland_egl_h" "$ac_includes_default"
|
||||
if test "x$ac_cv_header_wayland_egl_h" = xyes
|
||||
then :
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for wl_egl_window_create in -lwayland-egl" >&5
|
||||
printf %s "checking for wl_egl_window_create in -lwayland-egl... " >&6; }
|
||||
if test ${ac_cv_lib_wayland_egl_wl_egl_window_create+y}
|
||||
then :
|
||||
printf %s "(cached) " >&6
|
||||
else $as_nop
|
||||
ac_check_lib_save_LIBS=$LIBS
|
||||
LIBS="-lwayland-egl $WAYLAND_EGL_LIBS $LIBS"
|
||||
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||
/* end confdefs.h. */
|
||||
|
||||
/* Override any GCC internal prototype to avoid an error.
|
||||
Use char because int might match the return type of a GCC
|
||||
builtin and then its argument prototype would still apply. */
|
||||
char wl_egl_window_create ();
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
return wl_egl_window_create ();
|
||||
;
|
||||
return 0;
|
||||
}
|
||||
_ACEOF
|
||||
if ac_fn_c_try_link "$LINENO"
|
||||
then :
|
||||
ac_cv_lib_wayland_egl_wl_egl_window_create=yes
|
||||
else $as_nop
|
||||
ac_cv_lib_wayland_egl_wl_egl_window_create=no
|
||||
fi
|
||||
rm -f core conftest.err conftest.$ac_objext conftest.beam \
|
||||
conftest$ac_exeext conftest.$ac_ext
|
||||
LIBS=$ac_check_lib_save_LIBS
|
||||
fi
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_wayland_egl_wl_egl_window_create" >&5
|
||||
printf "%s\n" "$ac_cv_lib_wayland_egl_wl_egl_window_create" >&6; }
|
||||
if test "x$ac_cv_lib_wayland_egl_wl_egl_window_create" = xyes
|
||||
then :
|
||||
|
||||
printf "%s\n" "#define HAVE_LIBWAYLAND_EGL 1" >>confdefs.h
|
||||
|
||||
else $as_nop
|
||||
WAYLAND_EGL_LIBS=""
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
CPPFLAGS=$ac_save_CPPFLAGS
|
||||
|
||||
if test "x$with_wayland" != "x"
|
||||
then
|
||||
if test -z "$ac_cv_lib_soname_EGL"
|
||||
if test -z "$ac_cv_lib_soname_EGL" -o -z "$HAVE_LIBWAYLAND_EGL"
|
||||
then :
|
||||
case "x$with_opengl" in
|
||||
x) as_fn_append wine_notices "|EGL ${notice_platform}development files not found, the Wayland driver won't support OpenGL" ;;
|
||||
|
@ -23914,6 +24000,8 @@ XKBREGISTRY_CFLAGS = $XKBREGISTRY_CFLAGS
|
|||
XKBREGISTRY_LIBS = $XKBREGISTRY_LIBS
|
||||
EGL_CFLAGS = $EGL_CFLAGS
|
||||
EGL_LIBS = $EGL_LIBS
|
||||
WAYLAND_EGL_CFLAGS = $WAYLAND_EGL_CFLAGS
|
||||
WAYLAND_EGL_LIBS = $WAYLAND_EGL_LIBS
|
||||
PCAP_LIBS = $PCAP_LIBS
|
||||
PCSCLITE_LIBS = $PCSCLITE_LIBS
|
||||
INOTIFY_CFLAGS = $INOTIFY_CFLAGS
|
||||
|
|
|
@ -1385,9 +1385,14 @@ then
|
|||
WINE_PACKAGE_FLAGS(EGL,[egl],[-lEGL],,,
|
||||
[AC_CHECK_HEADER([EGL/egl.h],
|
||||
[WINE_CHECK_SONAME(EGL,eglGetProcAddress,,,[$EGL_LIBS])])])
|
||||
WINE_PACKAGE_FLAGS(WAYLAND_EGL,[wayland-egl],,,,
|
||||
[AC_CHECK_HEADER([wayland-egl.h],
|
||||
[AC_CHECK_LIB(wayland-egl,wl_egl_window_create,
|
||||
[AC_DEFINE(HAVE_LIBWAYLAND_EGL, 1, [Define if we have the wayland-egl development environment])],
|
||||
[WAYLAND_EGL_LIBS=""],[$WAYLAND_EGL_LIBS])])])
|
||||
if test "x$with_wayland" != "x"
|
||||
then
|
||||
WINE_NOTICE_WITH(opengl, [test -z "$ac_cv_lib_soname_EGL"],
|
||||
WINE_NOTICE_WITH(opengl, [test -z "$ac_cv_lib_soname_EGL" -o -z "$HAVE_LIBWAYLAND_EGL"],
|
||||
[EGL ${notice_platform}development files not found, the Wayland driver won't support OpenGL])
|
||||
fi
|
||||
fi
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
MODULE = winewayland.drv
|
||||
UNIXLIB = winewayland.so
|
||||
UNIX_CFLAGS = $(EGL_CFLAGS) $(WAYLAND_CLIENT_CFLAGS) $(XKBCOMMON_CFLAGS) $(XKBREGISTRY_CFLAGS)
|
||||
UNIX_LIBS = -lwin32u $(WAYLAND_CLIENT_LIBS) $(XKBCOMMON_LIBS) $(XKBREGISTRY_LIBS) $(PTHREAD_LIBS) -lm
|
||||
UNIX_CFLAGS = $(EGL_CFLAGS) $(WAYLAND_CLIENT_CFLAGS) $(WAYLAND_EGL_CFLAGS) $(XKBCOMMON_CFLAGS) $(XKBREGISTRY_CFLAGS)
|
||||
UNIX_LIBS = -lwin32u $(WAYLAND_CLIENT_LIBS) $(WAYLAND_EGL_LIBS) $(XKBCOMMON_LIBS) $(XKBREGISTRY_LIBS) $(PTHREAD_LIBS) -lm
|
||||
|
||||
SOURCES = \
|
||||
display.c \
|
||||
|
|
|
@ -31,11 +31,11 @@
|
|||
#include "waylanddrv.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
#if defined(SONAME_LIBEGL)
|
||||
#if defined(SONAME_LIBEGL) && defined(HAVE_LIBWAYLAND_EGL)
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv);
|
||||
|
||||
#define WL_EGL_PLATFORM 1
|
||||
#include <wayland-egl.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
|
||||
|
@ -55,6 +55,8 @@ static const char *opengl_func_names[] = { ALL_WGL_FUNCS };
|
|||
|
||||
#define DECL_FUNCPTR(f) static typeof(f) * p_##f
|
||||
DECL_FUNCPTR(eglChooseConfig);
|
||||
DECL_FUNCPTR(eglCreateWindowSurface);
|
||||
DECL_FUNCPTR(eglDestroySurface);
|
||||
DECL_FUNCPTR(eglGetConfigAttrib);
|
||||
DECL_FUNCPTR(eglGetError);
|
||||
DECL_FUNCPTR(eglGetPlatformDisplay);
|
||||
|
@ -63,6 +65,156 @@ DECL_FUNCPTR(eglInitialize);
|
|||
DECL_FUNCPTR(eglQueryString);
|
||||
#undef DECL_FUNCPTR
|
||||
|
||||
static pthread_mutex_t gl_object_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static struct list gl_drawables = LIST_INIT(gl_drawables);
|
||||
|
||||
struct wayland_gl_drawable
|
||||
{
|
||||
struct list entry;
|
||||
LONG ref;
|
||||
HWND hwnd;
|
||||
struct wayland_client_surface *client;
|
||||
struct wl_egl_window *wl_egl_window;
|
||||
EGLSurface surface;
|
||||
};
|
||||
|
||||
/* lookup the existing drawable for a window, gl_object_mutex must be held */
|
||||
static struct wayland_gl_drawable *find_drawable_for_hwnd(HWND hwnd)
|
||||
{
|
||||
struct wayland_gl_drawable *gl;
|
||||
LIST_FOR_EACH_ENTRY(gl, &gl_drawables, struct wayland_gl_drawable, entry)
|
||||
if (gl->hwnd == hwnd) return gl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void wayland_gl_drawable_release(struct wayland_gl_drawable *gl)
|
||||
{
|
||||
if (InterlockedDecrement(&gl->ref)) return;
|
||||
if (gl->surface) p_eglDestroySurface(egl_display, gl->surface);
|
||||
if (gl->wl_egl_window) wl_egl_window_destroy(gl->wl_egl_window);
|
||||
if (gl->client)
|
||||
{
|
||||
HWND hwnd = wl_surface_get_user_data(gl->client->wl_surface);
|
||||
struct wayland_surface *wayland_surface = wayland_surface_lock_hwnd(hwnd);
|
||||
|
||||
if (wayland_client_surface_release(gl->client) && wayland_surface)
|
||||
wayland_surface->client = NULL;
|
||||
|
||||
if (wayland_surface) pthread_mutex_unlock(&wayland_surface->mutex);
|
||||
}
|
||||
|
||||
free(gl);
|
||||
}
|
||||
|
||||
static struct wayland_gl_drawable *wayland_gl_drawable_create(HWND hwnd, int format)
|
||||
{
|
||||
struct wayland_gl_drawable *gl;
|
||||
struct wayland_surface *wayland_surface;
|
||||
int client_width = 0, client_height = 0;
|
||||
|
||||
TRACE("hwnd=%p format=%d\n", hwnd, format);
|
||||
|
||||
gl = calloc(1, sizeof(*gl));
|
||||
if (!gl) return NULL;
|
||||
|
||||
gl->ref = 1;
|
||||
gl->hwnd = hwnd;
|
||||
|
||||
/* Get the client surface for the HWND. If don't have a wayland surface
|
||||
* (e.g., HWND_MESSAGE windows) just create a dummy surface to act as the
|
||||
* target render surface. */
|
||||
if ((wayland_surface = wayland_surface_lock_hwnd(hwnd)))
|
||||
{
|
||||
gl->client = wayland_surface_get_client(wayland_surface);
|
||||
client_width = wayland_surface->window.client_rect.right -
|
||||
wayland_surface->window.client_rect.left;
|
||||
client_height = wayland_surface->window.client_rect.bottom -
|
||||
wayland_surface->window.client_rect.top;
|
||||
if (client_width == 0 || client_height == 0)
|
||||
client_width = client_height = 1;
|
||||
pthread_mutex_unlock(&wayland_surface->mutex);
|
||||
}
|
||||
else if ((wayland_surface = wayland_surface_create(0)))
|
||||
{
|
||||
gl->client = wayland_surface_get_client(wayland_surface);
|
||||
client_width = client_height = 1;
|
||||
/* It's fine to destroy the wayland surface, the client surface
|
||||
* can safely outlive it. */
|
||||
wayland_surface_destroy(wayland_surface);
|
||||
}
|
||||
if (!gl->client) goto err;
|
||||
|
||||
gl->wl_egl_window = wl_egl_window_create(gl->client->wl_surface,
|
||||
client_width, client_height);
|
||||
if (!gl->wl_egl_window)
|
||||
{
|
||||
ERR("Failed to create wl_egl_window\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
gl->surface = p_eglCreateWindowSurface(egl_display, egl_configs[format - 1],
|
||||
gl->wl_egl_window, NULL);
|
||||
if (!gl->surface)
|
||||
{
|
||||
ERR("Failed to create EGL surface\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
TRACE("hwnd=%p egl_surface=%p\n", gl->hwnd, gl->surface);
|
||||
|
||||
return gl;
|
||||
|
||||
err:
|
||||
wayland_gl_drawable_release(gl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void wayland_update_gl_drawable(HWND hwnd, struct wayland_gl_drawable *new)
|
||||
{
|
||||
struct wayland_gl_drawable *old;
|
||||
|
||||
pthread_mutex_lock(&gl_object_mutex);
|
||||
|
||||
if ((old = find_drawable_for_hwnd(hwnd))) list_remove(&old->entry);
|
||||
if (new) list_add_head(&gl_drawables, &new->entry);
|
||||
|
||||
pthread_mutex_unlock(&gl_object_mutex);
|
||||
|
||||
if (old) wayland_gl_drawable_release(old);
|
||||
}
|
||||
|
||||
static BOOL set_pixel_format(HDC hdc, int format, BOOL internal)
|
||||
{
|
||||
HWND hwnd = NtUserWindowFromDC(hdc);
|
||||
struct wayland_gl_drawable *gl;
|
||||
int prev = 0;
|
||||
|
||||
if (!hwnd || hwnd == NtUserGetDesktopWindow())
|
||||
{
|
||||
WARN("not a proper window DC %p/%p\n", hdc, hwnd);
|
||||
return FALSE;
|
||||
}
|
||||
if (format < 0 || format >= num_egl_configs)
|
||||
{
|
||||
WARN("Invalid format %d\n", format);
|
||||
return FALSE;
|
||||
}
|
||||
TRACE("%p/%p format %d\n", hdc, hwnd, format);
|
||||
|
||||
/* Even for internal pixel format fail setting it if the app has already set a
|
||||
* different pixel format. Let wined3d create a backup GL context instead.
|
||||
* Switching pixel format involves drawable recreation and is much more expensive
|
||||
* than blitting from backup context. */
|
||||
if ((prev = win32u_get_window_pixel_format(hwnd)))
|
||||
return prev == format;
|
||||
|
||||
if (!(gl = wayland_gl_drawable_create(hwnd, format))) return FALSE;
|
||||
wayland_update_gl_drawable(hwnd, gl);
|
||||
win32u_set_window_pixel_format(hwnd, format, internal);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL has_opengl(void);
|
||||
|
||||
static int wayland_wglDescribePixelFormat(HDC hdc, int fmt, UINT size,
|
||||
|
@ -138,6 +290,17 @@ static PROC wayland_wglGetProcAddress(LPCSTR name)
|
|||
return (PROC)p_eglGetProcAddress(name);
|
||||
}
|
||||
|
||||
static BOOL wayland_wglSetPixelFormat(HDC hdc, int format,
|
||||
const PIXELFORMATDESCRIPTOR *pfd)
|
||||
{
|
||||
return set_pixel_format(hdc, format, FALSE);
|
||||
}
|
||||
|
||||
static BOOL wayland_wglSetPixelFormatWINE(HDC hdc, int format)
|
||||
{
|
||||
return set_pixel_format(hdc, format, TRUE);
|
||||
}
|
||||
|
||||
static BOOL has_extension(const char *list, const char *ext)
|
||||
{
|
||||
size_t len = strlen(ext);
|
||||
|
@ -179,6 +342,9 @@ static BOOL init_opengl_funcs(void)
|
|||
register_extension("WGL_EXT_extensions_string");
|
||||
opengl_funcs.ext.p_wglGetExtensionsStringEXT = wayland_wglGetExtensionsStringEXT;
|
||||
|
||||
register_extension("WGL_WINE_pixel_format_passthrough");
|
||||
opengl_funcs.ext.p_wglSetPixelFormatWINE = wayland_wglSetPixelFormatWINE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -273,6 +439,8 @@ static void init_opengl(void)
|
|||
{ ERR("Failed to load symbol %s\n", #func); goto err; } \
|
||||
} while(0)
|
||||
LOAD_FUNCPTR_EGL(eglChooseConfig);
|
||||
LOAD_FUNCPTR_EGL(eglCreateWindowSurface);
|
||||
LOAD_FUNCPTR_EGL(eglDestroySurface);
|
||||
LOAD_FUNCPTR_EGL(eglGetConfigAttrib);
|
||||
LOAD_FUNCPTR_EGL(eglGetError);
|
||||
LOAD_FUNCPTR_EGL(eglGetPlatformDisplay);
|
||||
|
@ -317,6 +485,7 @@ static struct opengl_funcs opengl_funcs =
|
|||
{
|
||||
.p_wglDescribePixelFormat = wayland_wglDescribePixelFormat,
|
||||
.p_wglGetProcAddress = wayland_wglGetProcAddress,
|
||||
.p_wglSetPixelFormat = wayland_wglSetPixelFormat,
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -335,6 +504,14 @@ struct opengl_funcs *WAYLAND_wine_get_wgl_driver(UINT version)
|
|||
return &opengl_funcs;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* wayland_destroy_gl_drawable
|
||||
*/
|
||||
void wayland_destroy_gl_drawable(HWND hwnd)
|
||||
{
|
||||
wayland_update_gl_drawable(hwnd, NULL);
|
||||
}
|
||||
|
||||
#else /* No GL */
|
||||
|
||||
struct opengl_funcs *WAYLAND_wine_get_wgl_driver(UINT version)
|
||||
|
@ -342,4 +519,8 @@ struct opengl_funcs *WAYLAND_wine_get_wgl_driver(UINT version)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void wayland_destroy_gl_drawable(HWND hwnd)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -292,6 +292,12 @@ void wayland_pointer_init(struct wl_pointer *wl_pointer);
|
|||
void wayland_pointer_deinit(void);
|
||||
void wayland_pointer_clear_constraint(void);
|
||||
|
||||
/**********************************************************************
|
||||
* OpenGL
|
||||
*/
|
||||
|
||||
void wayland_destroy_gl_drawable(HWND hwnd);
|
||||
|
||||
/**********************************************************************
|
||||
* Helpers
|
||||
*/
|
||||
|
|
|
@ -402,6 +402,7 @@ void WAYLAND_DestroyWindow(HWND hwnd)
|
|||
|
||||
if (!(data = wayland_win_data_get(hwnd))) return;
|
||||
wayland_win_data_destroy(data);
|
||||
wayland_destroy_gl_drawable(hwnd);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -132,6 +132,9 @@
|
|||
/* Define to 1 if you have the `unwind' library (-lunwind). */
|
||||
#undef HAVE_LIBUNWIND
|
||||
|
||||
/* Define if we have the wayland-egl development environment */
|
||||
#undef HAVE_LIBWAYLAND_EGL
|
||||
|
||||
/* Define if you have the X Shape extension */
|
||||
#undef HAVE_LIBXSHAPE
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue