From: Rémi Bernon rbernon@codeweavers.com
--- dlls/opengl32/make_opengl | 1 + dlls/winex11.drv/opengl.c | 125 ++++++++++++++++++++++++++++++++- dlls/winex11.drv/x11drv.h | 1 + dlls/winex11.drv/x11drv_main.c | 4 ++ include/wine/wgl.h | 2 + 5 files changed, 131 insertions(+), 2 deletions(-)
diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index 17e44ec824a..4d3cc0562cc 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -775,6 +775,7 @@ my %supported_egl_extensions = "EGL_KHR_no_config_context" => 1, "EGL_KHR_platform_android" => 1, "EGL_KHR_platform_wayland" => 1, + "EGL_KHR_platform_x11" => 1, );
my %supported_apis = diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 9a0c8c69ec2..547608aa79f 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -222,6 +222,7 @@ enum glx_swap_control_method
static struct glx_pixel_format *pixel_formats; static int nb_pixel_formats, nb_onscreen_formats; +static const struct egl_platform *egl;
/* Selects the preferred GLX swap control method for use by wglSwapIntervalEXT */ static enum glx_swap_control_method swap_control_method = GLX_SWAP_CONTROL_NONE; @@ -324,9 +325,10 @@ static const GLubyte *(*pglGetString)(GLenum name);
static void *opengl_handle; static const struct opengl_funcs *funcs; -static const struct opengl_driver_funcs x11drv_driver_funcs; +static struct opengl_driver_funcs x11drv_driver_funcs; static const struct opengl_drawable_funcs x11drv_surface_funcs; static const struct opengl_drawable_funcs x11drv_pbuffer_funcs; +static const struct opengl_drawable_funcs x11drv_egl_surface_funcs;
/* check if the extension is present in the list */ static BOOL has_extension( const char *list, const char *ext ) @@ -468,6 +470,50 @@ done: return ret; }
+static EGLenum x11drv_init_egl_platform( const struct egl_platform *platform, EGLNativeDisplayType *platform_display ) +{ + egl = platform; + *platform_display = gdi_display; + return EGL_PLATFORM_X11_KHR; +} + +static inline 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 BOOL x11drv_egl_surface_create( HWND hwnd, HDC hdc, int format, struct opengl_drawable **drawable ) +{ + struct opengl_drawable *previous; + struct gl_drawable *gl; + RECT rect; + + if ((previous = *drawable) && previous->format == format) return TRUE; + NtUserGetClientRect( hwnd, &rect, NtUserGetDpiForWindow( hwnd ) ); + + if (!(gl = opengl_drawable_create( sizeof(*gl), &x11drv_egl_surface_funcs, format, hwnd, hdc ))) return FALSE; + gl->rect = rect; + + gl->window = create_client_window( hwnd, &default_visual, default_colormap ); + gl->base.surface = funcs->p_eglCreateWindowSurface( egl->display, egl_config_for_format(format), + (void *)gl->window, NULL ); + if (!gl->base.surface) + { + destroy_client_window( hwnd, gl->window ); + free( gl ); + return FALSE; + } + + TRACE( "Created drawable %s with client window %lx\n", debugstr_opengl_drawable( &gl->base ), gl->window ); + XFlush( gdi_display ); + + if (previous) opengl_drawable_release( previous ); + *drawable = &gl->base; + return TRUE; +} + /********************************************************************** * X11DRV_OpenglInit */ @@ -482,6 +528,17 @@ UINT X11DRV_OpenGLInit( UINT version, const struct opengl_funcs *opengl_funcs, c } funcs = opengl_funcs;
+ if (use_egl) + { + if (!opengl_funcs->egl_handle) return STATUS_NOT_SUPPORTED; + WARN( "Using experimental EGL OpenGL backend\n" ); + x11drv_driver_funcs = **driver_funcs; + x11drv_driver_funcs.p_init_egl_platform = x11drv_init_egl_platform; + x11drv_driver_funcs.p_surface_create = x11drv_egl_surface_create; + *driver_funcs = &x11drv_driver_funcs; + return STATUS_SUCCESS; + } + /* No need to load any other libraries as according to the ABI, libGL should be self-sufficient and include all dependencies */ opengl_handle = dlopen( SONAME_LIBGL, RTLD_NOW | RTLD_GLOBAL ); @@ -1530,7 +1587,62 @@ static BOOL x11drv_surface_swap( struct opengl_drawable *base ) return TRUE; }
-static const struct opengl_driver_funcs x11drv_driver_funcs = +static void x11drv_egl_surface_destroy( struct opengl_drawable *base ) +{ + struct gl_drawable *gl = impl_from_opengl_drawable( base ); + + TRACE( "drawable %s\n", debugstr_opengl_drawable( base ) ); + + destroy_client_window( gl->base.hwnd, gl->window ); +} + +static void x11drv_egl_surface_detach( struct opengl_drawable *base ) +{ + TRACE( "%s\n", debugstr_opengl_drawable( base ) ); +} + +static void x11drv_egl_surface_update( struct opengl_drawable *base ) +{ + struct gl_drawable *gl = impl_from_opengl_drawable( base ); + + TRACE( "%s\n", debugstr_opengl_drawable( base ) ); + + update_gl_drawable_size( gl ); + update_gl_drawable_offscreen( gl ); +} + +static void x11drv_egl_surface_flush( struct opengl_drawable *base, UINT flags ) +{ + struct gl_drawable *gl = impl_from_opengl_drawable( base ); + + TRACE( "%s\n", debugstr_opengl_drawable( base ) ); + + if (flags & GL_FLUSH_INTERVAL) funcs->p_eglSwapInterval( egl->display, abs( base->interval ) ); + if (flags & GL_FLUSH_UPDATED) + { + update_gl_drawable_size( gl ); + update_gl_drawable_offscreen( gl ); + } + + present_gl_drawable( gl, TRUE, !(flags & GL_FLUSH_FINISHED) ); +} + +static BOOL x11drv_egl_surface_swap( struct opengl_drawable *base ) +{ + struct gl_drawable *gl = impl_from_opengl_drawable( base ); + + TRACE( "%s\n", debugstr_opengl_drawable( base ) ); + + funcs->p_eglSwapBuffers( egl->display, gl->base.surface ); + + update_gl_drawable_size( gl ); + update_gl_drawable_offscreen( gl ); + + present_gl_drawable( gl, TRUE, FALSE ); + return TRUE; +} + +static struct opengl_driver_funcs x11drv_driver_funcs = { .p_get_proc_address = x11drv_get_proc_address, .p_init_pixel_formats = x11drv_init_pixel_formats, @@ -1562,6 +1674,15 @@ static const struct opengl_drawable_funcs x11drv_pbuffer_funcs = .swap = x11drv_pbuffer_swap, };
+static const struct opengl_drawable_funcs x11drv_egl_surface_funcs = +{ + .destroy = x11drv_egl_surface_destroy, + .detach = x11drv_egl_surface_detach, + .update = x11drv_egl_surface_update, + .flush = x11drv_egl_surface_flush, + .swap = x11drv_egl_surface_swap, +}; + #else /* no OpenGL includes */
/********************************************************************** diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h index e61ced9a25e..dfca33dcc97 100644 --- a/dlls/winex11.drv/x11drv.h +++ b/dlls/winex11.drv/x11drv.h @@ -454,6 +454,7 @@ extern BOOL keyboard_grabbed; extern unsigned int screen_bpp; extern BOOL usexrandr; extern BOOL usexvidmode; +extern BOOL use_egl; extern BOOL use_take_focus; extern BOOL use_primary_selection; extern BOOL use_system_cursors; diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c index c625107dcfa..c97088f09bc 100644 --- a/dlls/winex11.drv/x11drv_main.c +++ b/dlls/winex11.drv/x11drv_main.c @@ -68,6 +68,7 @@ Window root_window; BOOL usexvidmode = TRUE; BOOL usexrandr = TRUE; BOOL usexcomposite = TRUE; +BOOL use_egl = FALSE; BOOL use_take_focus = TRUE; BOOL use_primary_selection = FALSE; BOOL use_system_cursors = TRUE; @@ -450,6 +451,9 @@ static void setup_options(void) if (!get_config_key( hkey, appkey, "Managed", buffer, sizeof(buffer) )) managed_mode = IS_OPTION_TRUE( buffer[0] );
+ if (!get_config_key( hkey, appkey, "UseEGL", buffer, sizeof(buffer) )) + use_egl = IS_OPTION_TRUE( buffer[0] ); + if (!get_config_key( hkey, appkey, "UseXVidMode", buffer, sizeof(buffer) )) usexvidmode = IS_OPTION_TRUE( buffer[0] );
diff --git a/include/wine/wgl.h b/include/wine/wgl.h index 6ba341d11a4..e6b465e360f 100644 --- a/include/wine/wgl.h +++ b/include/wine/wgl.h @@ -268,6 +268,8 @@ typedef unsigned int GLhandleARB; #define EGL_PIXMAP_BIT 0x0002 #define EGL_PLATFORM_ANDROID_KHR 0x3141 #define EGL_PLATFORM_WAYLAND_KHR 0x31D8 +#define EGL_PLATFORM_X11_KHR 0x31D5 +#define EGL_PLATFORM_X11_SCREEN_KHR 0x31D6 #define EGL_PRESENT_OPAQUE_EXT 0x31DF #define EGL_READ 0x305A #define EGL_RED_SIZE 0x3024