@whrvt I think that's what is necessary for EGL to work better on NVIDIA right?
-- v3: winex11: Lookup visual from EGL config EGL_NATIVE_VISUAL_ID. winex11: Use the visual depth when creating the client window. winex11: Move colormap ownership to x11drv_client_surface.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/init.c | 37 ++++++++++++++++++--------- dlls/winex11.drv/opengl.c | 53 ++++++++++++++++++++++----------------- dlls/winex11.drv/vulkan.c | 2 +- dlls/winex11.drv/x11drv.h | 4 ++- 4 files changed, 59 insertions(+), 37 deletions(-)
diff --git a/dlls/winex11.drv/init.c b/dlls/winex11.drv/init.c index 039c4b0fefd..98964430a20 100644 --- a/dlls/winex11.drv/init.c +++ b/dlls/winex11.drv/init.c @@ -261,6 +261,7 @@ static const struct client_surface_funcs x11drv_client_surface_funcs; struct x11drv_client_surface { struct client_surface client; + Colormap colormap; Window window; RECT rect;
@@ -280,6 +281,7 @@ static void x11drv_client_surface_destroy( struct client_surface *client )
TRACE( "%s\n", debugstr_client_surface( client ) );
+ if (surface->colormap != default_colormap) XFreeColormap( gdi_display, surface->colormap ); if (surface->window) destroy_client_window( hwnd, surface->window ); if (surface->hdc_dst) NtGdiDeleteObjectApp( surface->hdc_dst ); if (surface->hdc_src) NtGdiDeleteObjectApp( surface->hdc_src ); @@ -426,25 +428,36 @@ static const struct client_surface_funcs x11drv_client_surface_funcs = .present = X11DRV_client_surface_present, };
-Window x11drv_client_surface_create( HWND hwnd, const XVisualInfo *visual, Colormap colormap, struct client_surface **client ) +static int visual_class_alloc( int class ) +{ + return class == PseudoColor || class == GrayScale || class == DirectColor ? AllocAll : AllocNone; +} + +Window x11drv_client_surface_create( HWND hwnd, int format, struct client_surface **client ) { struct x11drv_client_surface *surface; + XVisualInfo visual = default_visual; + Colormap colormap;
- if (!(surface = client_surface_create( sizeof(*surface), &x11drv_client_surface_funcs, hwnd ))) return None; - if (!(surface->window = create_client_window( hwnd, visual, colormap ))) - { - client_surface_release( &surface->client ); - return None; - } - if (!NtUserGetClientRect( hwnd, &surface->rect, NtUserGetDpiForWindow( hwnd ) )) - { - client_surface_release( &surface->client ); - return None; - } + if (format && !visual_from_pixel_format( format, &visual )) return None; + + if (visual.visualid == default_visual.visualid) colormap = default_colormap; + else colormap = XCreateColormap( gdi_display, get_dummy_parent(), visual.visual, visual_class_alloc( visual.class ) ); + if (!colormap) return None; + + if (!(surface = client_surface_create( sizeof(*surface), &x11drv_client_surface_funcs, hwnd ))) goto failed; + if (!(surface->window = create_client_window( hwnd, &visual, colormap ))) goto failed; + if (!NtUserGetClientRect( hwnd, &surface->rect, NtUserGetDpiForWindow( hwnd ) )) goto failed; + surface->colormap = colormap;
TRACE( "Created %s for client window %lx\n", debugstr_client_surface( &surface->client ), surface->window ); *client = &surface->client; return surface->window; + +failed: + if (surface) client_surface_release( &surface->client ); + XFreeColormap( gdi_display, colormap ); + return None; }
/********************************************************************** diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index b810689ff3d..64640fb798c 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -198,7 +198,6 @@ struct gl_drawable { struct opengl_drawable base; GLXDrawable drawable; /* drawable for rendering with GL */ - Colormap colormap; /* colormap for the client window */ };
static struct gl_drawable *impl_from_opengl_drawable( struct opengl_drawable *base ) @@ -471,13 +470,34 @@ static void x11drv_init_egl_platform( struct egl_platform *platform ) egl = platform; }
-static inline EGLConfig egl_config_for_format(int format) +static EGLConfig egl_config_for_format( int format ) { assert(format > 0 && format <= 2 * egl->config_count); if (format <= egl->config_count) return egl->configs[format - 1]; return egl->configs[format - egl->config_count - 1]; }
+static struct glx_pixel_format *glx_pixel_format_from_format( int format ) +{ + assert( format > 0 && format <= nb_pixel_formats ); + return &pixel_formats[format - 1]; +} + +BOOL visual_from_pixel_format( int format, XVisualInfo *visual ) +{ + if (use_egl) + { + *visual = default_visual; + return TRUE; + } + else + { + struct glx_pixel_format *fmt = glx_pixel_format_from_format( format ); + *visual = *fmt->visual; + return TRUE; + } +} + static BOOL x11drv_egl_surface_create( HWND hwnd, int format, struct opengl_drawable **drawable ) { struct opengl_drawable *previous; @@ -489,7 +509,7 @@ static BOOL x11drv_egl_surface_create( HWND hwnd, int format, struct opengl_draw if ((previous = *drawable) && previous->format == format) return TRUE; NtUserGetClientRect( hwnd, &rect, NtUserGetDpiForWindow( hwnd ) );
- if (!(window = x11drv_client_surface_create( hwnd, &default_visual, default_colormap, &client ))) return FALSE; + if (!(window = x11drv_client_surface_create( hwnd, 0, &client ))) return FALSE; gl = opengl_drawable_create( sizeof(*gl), &x11drv_egl_surface_funcs, format, client ); client_surface_release( client ); if (!gl) return FALSE; @@ -850,12 +870,6 @@ static UINT x11drv_init_pixel_formats( UINT *onscreen_count ) return size; }
-static struct glx_pixel_format *glx_pixel_format_from_format( int format ) -{ - assert( format > 0 && format <= nb_pixel_formats ); - return &pixel_formats[format - 1]; -} - static void x11drv_surface_destroy( struct opengl_drawable *base ) { struct gl_drawable *gl = impl_from_opengl_drawable( base ); @@ -863,7 +877,6 @@ static void x11drv_surface_destroy( struct opengl_drawable *base ) TRACE( "drawable %s\n", debugstr_opengl_drawable( base ) );
if (gl->drawable) pglXDestroyWindow( gdi_display, gl->drawable ); - if (gl->colormap) XFreeColormap( gdi_display, gl->colormap ); }
static BOOL set_swap_interval( struct gl_drawable *gl, int interval ) @@ -923,23 +936,16 @@ static BOOL x11drv_surface_create( HWND hwnd, int format, struct opengl_drawable struct opengl_drawable *previous; struct client_surface *client; struct gl_drawable *gl; - Colormap colormap; Window window; RECT rect;
if ((previous = *drawable) && previous->format == format) return TRUE; NtUserGetClientRect( hwnd, &rect, NtUserGetDpiForWindow( hwnd ) );
- colormap = XCreateColormap( gdi_display, get_dummy_parent(), fmt->visual->visual, - (fmt->visual->class == PseudoColor || fmt->visual->class == GrayScale || - fmt->visual->class == DirectColor) ? AllocAll : AllocNone ); - if (!colormap) return FALSE; - - if (!(window = x11drv_client_surface_create( hwnd, fmt->visual, colormap, &client ))) goto failed; + if (!(window = x11drv_client_surface_create( hwnd, format, &client ))) return FALSE; gl = opengl_drawable_create( sizeof(*gl), &x11drv_surface_funcs, format, client ); client_surface_release( client ); - if (!gl) goto failed; - gl->colormap = colormap; + if (!gl) return FALSE;
if (!(gl->drawable = pglXCreateWindow( gdi_display, fmt->fbconfig, window, NULL ))) { @@ -953,10 +959,6 @@ static BOOL x11drv_surface_create( HWND hwnd, int format, struct opengl_drawable if (previous) opengl_drawable_release( previous ); *drawable = &gl->base; return TRUE; - -failed: - XFreeColormap( gdi_display, colormap ); - return FALSE; }
static BOOL x11drv_describe_pixel_format( int format, struct wgl_pixel_format *pf ) @@ -1547,4 +1549,9 @@ void destroy_gl_drawable( HWND hwnd ) { }
+BOOL visual_from_pixel_format( int format, XVisualInfo *visual ) +{ + return FALSE; +} + #endif /* defined(SONAME_LIBGL) */ diff --git a/dlls/winex11.drv/vulkan.c b/dlls/winex11.drv/vulkan.c index 61e4327e379..54e01759e37 100644 --- a/dlls/winex11.drv/vulkan.c +++ b/dlls/winex11.drv/vulkan.c @@ -58,7 +58,7 @@ static VkResult X11DRV_vulkan_surface_create( HWND hwnd, const struct vulkan_ins
TRACE( "%p %p %p %p\n", hwnd, instance, handle, client );
- if (!(info.window = x11drv_client_surface_create( hwnd, &default_visual, default_colormap, client ))) return VK_ERROR_OUT_OF_HOST_MEMORY; + if (!(info.window = x11drv_client_surface_create( hwnd, 0, client ))) return VK_ERROR_OUT_OF_HOST_MEMORY; if (instance->p_vkCreateXlibSurfaceKHR( instance->host.instance, &info, NULL /* allocator */, handle )) { ERR("Failed to create Xlib surface\n"); diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index c69c83e5dd9..6e909e289ee 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -282,6 +282,8 @@ extern BOOL client_side_with_render; extern BOOL shape_layered_windows; extern const struct gdi_dc_funcs *X11DRV_XRender_Init(void);
+extern BOOL visual_from_pixel_format( int format, XVisualInfo *visual ); + extern UINT X11DRV_OpenGLInit( UINT, const struct opengl_funcs *, const struct opengl_driver_funcs ** ); extern UINT X11DRV_VulkanInit( UINT, void *, const struct vulkan_driver_funcs ** );
@@ -358,7 +360,7 @@ extern BOOL needs_offscreen_rendering( HWND hwnd ); extern void set_dc_drawable( HDC hdc, Drawable drawable, const RECT *rect, int mode ); extern Drawable get_dc_drawable( HDC hdc, RECT *rect ); extern HRGN get_dc_monitor_region( HWND hwnd, HDC hdc ); -extern Window x11drv_client_surface_create( HWND hwnd, const XVisualInfo *visual, Colormap colormap, struct client_surface **client ); +extern Window x11drv_client_surface_create( HWND hwnd, int format, struct client_surface **client );
/************************************************************************** * X11 USER driver
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c index 2e6f13eec53..13387fc9a3b 100644 --- a/dlls/winex11.drv/window.c +++ b/dlls/winex11.drv/window.c @@ -2312,7 +2312,7 @@ Window create_client_window( HWND hwnd, const XVisualInfo *visual, Colormap colo XSync( gdi_display, False ); /* make sure whole_window is known from gdi_display */ ret = data->client_window = XCreateWindow( gdi_display, data->whole_window ? data->whole_window : get_dummy_parent(), - x, y, cx, cy, 0, default_visual.depth, InputOutput, + x, y, cx, cy, 0, visual->depth, InputOutput, visual->visual, CWBitGravity | CWWinGravity | CWBackingStore | CWColormap | CWBorderPixel, &attr ); if (data->client_window)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winex11.drv/opengl.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 64640fb798c..06d105424e0 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -487,7 +487,15 @@ BOOL visual_from_pixel_format( int format, XVisualInfo *visual ) { if (use_egl) { - *visual = default_visual; + EGLConfig config = egl_config_for_format( format ); + XVisualInfo *visuals; + int count; + + memset( visual, 0, sizeof(*visual) ); + funcs->p_eglGetConfigAttrib( egl->display, config, EGL_NATIVE_VISUAL_ID, (EGLint *)&visual->visualid ); + if (!(visuals = XGetVisualInfo( gdi_display, VisualIDMask, visual, &count ))) return FALSE; + *visual = *visuals; + XFree( visuals ); return TRUE; } else @@ -509,7 +517,7 @@ static BOOL x11drv_egl_surface_create( HWND hwnd, int format, struct opengl_draw if ((previous = *drawable) && previous->format == format) return TRUE; NtUserGetClientRect( hwnd, &rect, NtUserGetDpiForWindow( hwnd ) );
- if (!(window = x11drv_client_surface_create( hwnd, 0, &client ))) return FALSE; + if (!(window = x11drv_client_surface_create( hwnd, format, &client ))) return FALSE; gl = opengl_drawable_create( sizeof(*gl), &x11drv_egl_surface_funcs, format, client ); client_surface_release( client ); if (!gl) return FALSE;
On Thu Oct 9 13:40:35 2025 +0000, Rémi Bernon wrote:
Yeah this is weird, seems to also be using a format with an alpha channel, but things work fine here...
I found and fixed some issue(s), we were not passing the pixel format to the client window creation function and the client window didn't respect the visual depth either.
AFAICT it should be working fine now (tested on NVIDIA 580 drivers on XWayland).
This merge request was approved by William Horvath.