Instead of https://gitlab.winehq.org/wine/wine/-/merge_requests/8496, leaving context sharing for later.
-- v3: win32u: Remove now unnecessary opengl_drawable hdc member. winewayland: Use a distinct wayland_pbuffer struct for pbuffers. win32u: Implement generic EGL driver pbuffer surface. win32u: Avoid releasing opengl drawable within drawables_lock. win32u: Avoid calling detach, flush or swap on pbuffer drawables. winemac: Remove now unnecessary pbuffer tracking.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winemac.drv/opengl.c | 77 ++++++--------------------------------- 1 file changed, 11 insertions(+), 66 deletions(-)
diff --git a/dlls/winemac.drv/opengl.c b/dlls/winemac.drv/opengl.c index dd3b3e4da59..57b2ed23dd9 100644 --- a/dlls/winemac.drv/opengl.c +++ b/dlls/winemac.drv/opengl.c @@ -93,9 +93,6 @@ static struct gl_drawable *impl_from_opengl_drawable(struct opengl_drawable *bas static struct list context_list = LIST_INIT(context_list); static pthread_mutex_t context_mutex = PTHREAD_MUTEX_INITIALIZER;
-static CFMutableDictionaryRef dc_pbuffers; -static pthread_mutex_t dc_pbuffers_mutex = PTHREAD_MUTEX_INITIALIZER; - static void *opengl_handle; static const struct opengl_funcs *funcs; static const struct opengl_driver_funcs macdrv_driver_funcs; @@ -2370,10 +2367,6 @@ static BOOL macdrv_pbuffer_create(HDC hdc, int format, BOOL largest, GLenum text return FALSE; }
- pthread_mutex_lock(&dc_pbuffers_mutex); - CFDictionarySetValue(dc_pbuffers, hdc, gl->pbuffer); - pthread_mutex_unlock(&dc_pbuffers_mutex); - *drawable = &gl->base; TRACE(" -> %p\n", gl); return TRUE; @@ -2385,10 +2378,6 @@ static void macdrv_pbuffer_destroy(struct opengl_drawable *base)
TRACE("drawable %s\n", debugstr_opengl_drawable(base));
- pthread_mutex_lock(&dc_pbuffers_mutex); - CFDictionaryRemoveValue(dc_pbuffers, gl->pbuffer); - pthread_mutex_unlock(&dc_pbuffers_mutex); - CGLReleasePBuffer(gl->pbuffer); }
@@ -2439,22 +2428,9 @@ static BOOL macdrv_make_current(struct opengl_drawable *draw_base, struct opengl } else { - CGLPBufferObj pbuffer; - - pthread_mutex_lock(&dc_pbuffers_mutex); - pbuffer = (CGLPBufferObj)CFDictionaryGetValue(dc_pbuffers, draw->base.hdc); - if (!pbuffer) - { - WARN("no window or pbuffer for DC\n"); - pthread_mutex_unlock(&dc_pbuffers_mutex); - RtlSetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - context->draw_hwnd = NULL; context->draw_view = NULL; - context->draw_pbuffer = pbuffer; - pthread_mutex_unlock(&dc_pbuffers_mutex); + context->draw_pbuffer = draw->pbuffer; }
context->read_view = NULL; @@ -2476,9 +2452,7 @@ static BOOL macdrv_make_current(struct opengl_drawable *draw_base, struct opengl } else { - pthread_mutex_lock(&dc_pbuffers_mutex); - context->read_pbuffer = (CGLPBufferObj)CFDictionaryGetValue(dc_pbuffers, read->base.hdc); - pthread_mutex_unlock(&dc_pbuffers_mutex); + context->read_pbuffer = read->pbuffer; } }
@@ -2790,13 +2764,6 @@ UINT macdrv_OpenGLInit(UINT version, const struct opengl_funcs *opengl_funcs, co } funcs = opengl_funcs;
- dc_pbuffers = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); - if (!dc_pbuffers) - { - WARN("CFDictionaryCreateMutable failed\n"); - return STATUS_NOT_SUPPORTED; - } - opengl_handle = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY|RTLD_LOCAL|RTLD_NOLOAD); if (!opengl_handle) { @@ -2951,49 +2918,27 @@ static void *macdrv_get_proc_address(const char *name) static BOOL macdrv_surface_swap(struct opengl_drawable *base) { struct macdrv_context *context = NtCurrentTeb()->glReserved2; + struct macdrv_win_data *data; HWND hwnd = base->hwnd; - HDC hdc = base->hdc; BOOL match = FALSE;
- TRACE("hdc %p context %p/%p/%p\n", hdc, context, (context ? context->context : NULL), + TRACE("%s context %p/%p/%p\n", debugstr_opengl_drawable(base), context, (context ? context->context : NULL), (context ? context->cglcontext : NULL));
- if (hwnd) + if (!(data = get_win_data(hwnd))) { - struct macdrv_win_data *data; - - if (!(data = get_win_data(hwnd))) - { - RtlSetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - - if (context && context->draw_view == data->client_cocoa_view) - match = TRUE; - - release_win_data(data); + RtlSetLastWin32Error(ERROR_INVALID_HANDLE); + return FALSE; } - else - { - CGLPBufferObj pbuffer;
- pthread_mutex_lock(&dc_pbuffers_mutex); - pbuffer = (CGLPBufferObj)CFDictionaryGetValue(dc_pbuffers, hdc); - pthread_mutex_unlock(&dc_pbuffers_mutex); + if (context && context->draw_view == data->client_cocoa_view) + match = TRUE;
- if (!pbuffer) - { - RtlSetLastWin32Error(ERROR_INVALID_HANDLE); - return FALSE; - } - - if (context && context->draw_pbuffer == pbuffer) - match = TRUE; - } + release_win_data(data);
if (!match) { - FIXME("current context %p doesn't match hdc %p; can't swap\n", context, hdc); + FIXME("current context %p doesn't match; can't swap\n", context); return FALSE; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/opengl.c | 14 ++++++++++---- dlls/winemac.drv/opengl.c | 16 ---------------- dlls/winex11.drv/opengl.c | 16 ---------------- 3 files changed, 10 insertions(+), 36 deletions(-)
diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index 65318895a65..f89f16c2f48 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -246,9 +246,12 @@ void opengl_drawable_release( struct opengl_drawable *drawable ) const struct opengl_funcs *funcs = &display_funcs; const struct egl_platform *egl = &display_egl;
- pthread_mutex_lock( &drawables_lock ); - opengl_drawable_detach( drawable ); - pthread_mutex_unlock( &drawables_lock ); + if (drawable->hwnd) + { + pthread_mutex_lock( &drawables_lock ); + opengl_drawable_detach( drawable ); + pthread_mutex_unlock( &drawables_lock ); + }
drawable->funcs->destroy( drawable ); if (drawable->surface) funcs->p_eglDestroySurface( egl->display, drawable->surface ); @@ -258,6 +261,8 @@ void opengl_drawable_release( struct opengl_drawable *drawable )
static void opengl_drawable_flush( struct opengl_drawable *drawable, int interval, UINT flags ) { + if (!drawable->hwnd) return; + if (InterlockedCompareExchange( &drawable->updated, 0, 1 )) flags |= GL_FLUSH_UPDATED; if (interval != drawable->interval) { @@ -1658,7 +1663,8 @@ static BOOL win32u_wglSwapBuffers( HDC hdc )
if (!(draw = get_dc_opengl_drawable( draw_hdc, FALSE ))) return FALSE; opengl_drawable_flush( draw, interval, 0 ); - ret = draw->funcs->swap( draw ); + if (!draw->hwnd) ret = FALSE; /* pbuffer, nothing to do */ + else ret = draw->funcs->swap( draw ); opengl_drawable_release( draw );
return ret; diff --git a/dlls/winemac.drv/opengl.c b/dlls/winemac.drv/opengl.c index 57b2ed23dd9..4d9780c7eb3 100644 --- a/dlls/winemac.drv/opengl.c +++ b/dlls/winemac.drv/opengl.c @@ -2381,19 +2381,6 @@ static void macdrv_pbuffer_destroy(struct opengl_drawable *base) CGLReleasePBuffer(gl->pbuffer); }
-static void macdrv_pbuffer_detach(struct opengl_drawable *base) -{ -} - -static void macdrv_pbuffer_flush(struct opengl_drawable *base, UINT flags) -{ -} - -static BOOL macdrv_pbuffer_swap(struct opengl_drawable *base) -{ - return FALSE; -} - static BOOL macdrv_make_current(struct opengl_drawable *draw_base, struct opengl_drawable *read_base, void *private) { struct gl_drawable *draw = impl_from_opengl_drawable(draw_base), *read = impl_from_opengl_drawable(read_base); @@ -2973,7 +2960,4 @@ static const struct opengl_drawable_funcs macdrv_surface_funcs = static const struct opengl_drawable_funcs macdrv_pbuffer_funcs = { .destroy = macdrv_pbuffer_destroy, - .detach = macdrv_pbuffer_detach, - .flush = macdrv_pbuffer_flush, - .swap = macdrv_pbuffer_swap, }; diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 547608aa79f..4d100088030 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -1428,19 +1428,6 @@ static void x11drv_pbuffer_destroy( struct opengl_drawable *base ) if (gl->drawable) pglXDestroyPbuffer( gdi_display, gl->drawable ); }
-static void x11drv_pbuffer_detach( struct opengl_drawable *base ) -{ -} - -static void x11drv_pbuffer_flush( struct opengl_drawable *base, UINT flags ) -{ -} - -static BOOL x11drv_pbuffer_swap( struct opengl_drawable *base ) -{ - return FALSE; -} - static BOOL x11drv_pbuffer_updated( HDC hdc, struct opengl_drawable *base, GLenum cube_face, GLint mipmap_level ) { return GL_TRUE; @@ -1669,9 +1656,6 @@ static const struct opengl_drawable_funcs x11drv_surface_funcs = static const struct opengl_drawable_funcs x11drv_pbuffer_funcs = { .destroy = x11drv_pbuffer_destroy, - .detach = x11drv_pbuffer_detach, - .flush = x11drv_pbuffer_flush, - .swap = x11drv_pbuffer_swap, };
static const struct opengl_drawable_funcs x11drv_egl_surface_funcs =
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/opengl.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-)
diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index f89f16c2f48..1c89b49b483 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -166,16 +166,9 @@ static void register_extension( char *list, size_t size, const char *name ) static pthread_mutex_t drawables_lock = PTHREAD_MUTEX_INITIALIZER; static struct list drawables = LIST_INIT( drawables );
-/* drawables_lock must be held */ -static void opengl_drawable_detach( struct opengl_drawable *drawable ) -{ - drawable->funcs->detach( drawable ); - list_remove( &drawable->entry ); - list_init( &drawable->entry ); -} - void detach_opengl_drawables( HWND hwnd ) { + struct list detached = LIST_INIT( detached ); struct opengl_drawable *drawable, *next;
pthread_mutex_lock( &drawables_lock ); @@ -183,10 +176,22 @@ void detach_opengl_drawables( HWND hwnd ) LIST_FOR_EACH_ENTRY_SAFE( drawable, next, &drawables, struct opengl_drawable, entry ) { if (drawable->hwnd != hwnd) continue; - opengl_drawable_detach( drawable ); + + list_remove( &drawable->entry ); + list_add_tail( &detached, &drawable->entry ); + opengl_drawable_add_ref( drawable ); + + drawable->funcs->detach( drawable ); + drawable->hwnd = NULL; }
pthread_mutex_unlock( &drawables_lock ); + + LIST_FOR_EACH_ENTRY_SAFE( drawable, next, &detached, struct opengl_drawable, entry ) + { + list_remove( &drawable->entry ); + opengl_drawable_release( drawable ); + } }
void update_opengl_drawables( HWND hwnd ) @@ -246,12 +251,13 @@ void opengl_drawable_release( struct opengl_drawable *drawable ) const struct opengl_funcs *funcs = &display_funcs; const struct egl_platform *egl = &display_egl;
+ pthread_mutex_lock( &drawables_lock ); if (drawable->hwnd) { - pthread_mutex_lock( &drawables_lock ); - opengl_drawable_detach( drawable ); - pthread_mutex_unlock( &drawables_lock ); + drawable->funcs->detach( drawable ); + list_remove( &drawable->entry ); } + pthread_mutex_unlock( &drawables_lock );
drawable->funcs->destroy( drawable ); if (drawable->surface) funcs->p_eglDestroySurface( egl->display, drawable->surface );
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/opengl.c | 94 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 88 insertions(+), 6 deletions(-)
diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index 1c89b49b483..f5071657e23 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -281,6 +281,15 @@ static void opengl_drawable_flush( struct opengl_drawable *drawable, int interva
#ifdef SONAME_LIBEGL
+static const struct opengl_drawable_funcs egldrv_pbuffer_funcs; + +static inline EGLConfig egl_config_for_format( const struct egl_platform *egl, 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 void *egldrv_get_proc_address( const char *name ) { return display_funcs.p_eglGetProcAddress( name ); @@ -293,7 +302,6 @@ static UINT egldrv_init_pixel_formats( UINT *onscreen_count ) const EGLint attribs[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE }; EGLConfig *configs; @@ -420,7 +428,9 @@ static BOOL describe_egl_config( EGLConfig config, struct wgl_pixel_format *fmt, } else fmt->pixel_type = -1;
- fmt->draw_to_pbuffer = TRUE; + if ((fmt->draw_to_pbuffer = !!(surface_type & EGL_PBUFFER_BIT))) + pfd->dwFlags |= PFD_DRAW_TO_BITMAP; + /* Use some arbitrary but reasonable limits (4096 is also Mesa's default) */ fmt->max_pbuffer_width = 4096; fmt->max_pbuffer_height = 4096; @@ -489,19 +499,81 @@ static BOOL egldrv_surface_create( HWND hwnd, HDC hdc, int format, struct opengl static BOOL egldrv_pbuffer_create( HDC hdc, int format, BOOL largest, GLenum texture_format, GLenum texture_target, GLint max_level, GLsizei *width, GLsizei *height, struct opengl_drawable **drawable ) { - FIXME( "stub!\n" ); - return FALSE; + const struct opengl_funcs *funcs = &display_funcs; + const struct egl_platform *egl = &display_egl; + EGLint attribs[13], *attrib = attribs; + struct opengl_drawable *gl; + + TRACE( "hdc %p, format %d, largest %u, texture_format %#x, texture_target %#x, max_level %#x, width %d, height %d, drawable %p\n", + hdc, format, largest, texture_format, texture_target, max_level, *width, *height, drawable ); + + *attrib++ = EGL_WIDTH; + *attrib++ = *width; + *attrib++ = EGL_HEIGHT; + *attrib++ = *height; + if (largest) + { + *attrib++ = EGL_LARGEST_PBUFFER; + *attrib++ = 1; + } + switch (texture_format) + { + case 0: break; + case GL_RGB: + *attrib++ = EGL_TEXTURE_FORMAT; + *attrib++ = EGL_TEXTURE_RGB; + break; + case GL_RGBA: + *attrib++ = EGL_TEXTURE_FORMAT; + *attrib++ = EGL_TEXTURE_RGBA; + break; + default: + FIXME( "Unsupported format %#x\n", texture_format ); + *attrib++ = EGL_TEXTURE_FORMAT; + *attrib++ = EGL_TEXTURE_RGBA; + break; + } + switch (texture_target) + { + case 0: break; + case GL_TEXTURE_2D: + *attrib++ = EGL_TEXTURE_TARGET; + *attrib++ = EGL_TEXTURE_2D; + break; + default: + FIXME( "Unsupported target %#x\n", texture_target ); + *attrib++ = EGL_TEXTURE_TARGET; + *attrib++ = EGL_TEXTURE_2D; + break; + } + if (max_level) + { + *attrib++ = EGL_MIPMAP_TEXTURE; + *attrib++ = GL_TRUE; + } + *attrib++ = EGL_NONE; + + if (!(gl = opengl_drawable_create( sizeof(*gl), &egldrv_pbuffer_funcs, format, 0, hdc ))) return FALSE; + if (!(gl->surface = funcs->p_eglCreatePbufferSurface( egl->display, egl_config_for_format( egl, gl->format ), attribs ))) + { + opengl_drawable_release( gl ); + return FALSE; + } + + funcs->p_eglQuerySurface( egl->display, gl->surface, EGL_WIDTH, width ); + funcs->p_eglQuerySurface( egl->display, gl->surface, EGL_HEIGHT, height ); + + *drawable = gl; + return TRUE; }
static BOOL egldrv_pbuffer_updated( HDC hdc, struct opengl_drawable *drawable, GLenum cube_face, GLint mipmap_level ) { - FIXME( "stub!\n" ); return GL_TRUE; }
static UINT egldrv_pbuffer_bind( HDC hdc, struct opengl_drawable *drawable, GLenum buffer ) { - FIXME( "stub!\n" ); return -1; /* use default implementation */ }
@@ -596,6 +668,16 @@ static BOOL egldrv_make_current( struct opengl_drawable *draw, struct opengl_dra return funcs->p_eglMakeCurrent( egl->display, context ? draw->surface : EGL_NO_SURFACE, context ? read->surface : EGL_NO_SURFACE, context ); }
+static void egldrv_pbuffer_destroy( struct opengl_drawable *drawable ) +{ + TRACE( "%s\n", debugstr_opengl_drawable( drawable ) ); +} + +static const struct opengl_drawable_funcs egldrv_pbuffer_funcs = +{ + .destroy = egldrv_pbuffer_destroy, +}; + static const struct opengl_driver_funcs egldrv_funcs = { .p_get_proc_address = egldrv_get_proc_address,
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winewayland.drv/opengl.c | 129 ++++++++++++++++++---------------- 1 file changed, 69 insertions(+), 60 deletions(-)
diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index 9f1660a80a6..68795777d3b 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -51,7 +51,6 @@ struct wayland_gl_drawable struct opengl_drawable base; struct wayland_client_surface *client; struct wl_egl_window *wl_egl_window; - BOOL double_buffered; };
static struct wayland_gl_drawable *impl_from_opengl_drawable(struct opengl_drawable *base) @@ -98,56 +97,6 @@ static inline EGLConfig egl_config_for_format(int format) return egl->configs[format - egl->config_count - 1]; }
-static struct wayland_gl_drawable *wayland_gl_drawable_create(HWND hwnd, HDC hdc, int format, int width, int height) -{ - struct wayland_gl_drawable *gl; - EGLint attribs[4], *attrib = attribs; - - TRACE("hwnd=%p format=%d\n", hwnd, format); - - if (!egl->has_EGL_EXT_present_opaque) - WARN("Missing EGL_EXT_present_opaque extension\n"); - else - { - *attrib++ = EGL_PRESENT_OPAQUE_EXT; - *attrib++ = EGL_TRUE; - } - *attrib++ = EGL_NONE; - - if (!(gl = opengl_drawable_create(sizeof(*gl), &wayland_drawable_funcs, format, hwnd, hdc))) return NULL; - - /* 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 (!(gl->client = wayland_client_surface_create(hwnd))) goto err; - set_client_surface(hwnd, gl->client); - - gl->wl_egl_window = wl_egl_window_create(gl->client->wl_surface, width, height); - if (!gl->wl_egl_window) - { - ERR("Failed to create wl_egl_window\n"); - goto err; - } - - gl->base.surface = funcs->p_eglCreateWindowSurface(egl->display, egl_config_for_format(format), - gl->wl_egl_window, attribs); - if (!gl->base.surface) - { - ERR("Failed to create EGL surface\n"); - goto err; - } - - gl->double_buffered = is_onscreen_format(format); - - TRACE("Created drawable %s with egl_surface %p\n", debugstr_opengl_drawable(&gl->base), gl->base.surface); - - return gl; - -err: - opengl_drawable_release(&gl->base); - return NULL; -} - static void wayland_gl_drawable_sync_size(struct wayland_gl_drawable *gl) { int client_width, client_height; @@ -163,20 +112,44 @@ static void wayland_gl_drawable_sync_size(struct wayland_gl_drawable *gl)
static BOOL wayland_opengl_surface_create(HWND hwnd, HDC hdc, int format, struct opengl_drawable **drawable) { + EGLConfig config = egl_config_for_format(format); + EGLint attribs[4], *attrib = attribs; struct opengl_drawable *previous; struct wayland_gl_drawable *gl; RECT rect;
+ TRACE("hwnd=%p format=%d\n", hwnd, format); + if ((previous = *drawable) && previous->format == format) return TRUE;
NtUserGetClientRect(hwnd, &rect, NtUserGetDpiForWindow(hwnd)); if (rect.right == rect.left) rect.right = rect.left + 1; if (rect.bottom == rect.top) rect.bottom = rect.top + 1;
- if (!(gl = wayland_gl_drawable_create(hwnd, 0, format, rect.right - rect.left, rect.bottom - rect.top))) return FALSE; + if (!egl->has_EGL_EXT_present_opaque) + WARN("Missing EGL_EXT_present_opaque extension\n"); + else + { + *attrib++ = EGL_PRESENT_OPAQUE_EXT; + *attrib++ = EGL_TRUE; + } + *attrib++ = EGL_NONE; + + if (!(gl = opengl_drawable_create(sizeof(*gl), &wayland_drawable_funcs, format, hwnd, hdc))) return FALSE; + if (!(gl->client = wayland_client_surface_create(hwnd))) goto err; + if (!(gl->wl_egl_window = wl_egl_window_create(gl->client->wl_surface, rect.right, rect.bottom))) goto err; + if (!(gl->base.surface = funcs->p_eglCreateWindowSurface(egl->display, config, gl->wl_egl_window, attribs))) goto err; + set_client_surface(hwnd, gl->client); + + TRACE("Created drawable %s with egl_surface %p\n", debugstr_opengl_drawable(&gl->base), gl->base.surface); + if (previous) opengl_drawable_release( previous ); *drawable = &gl->base; return TRUE; + +err: + opengl_drawable_release(&gl->base); + return FALSE; }
static EGLenum wayland_init_egl_platform(const struct egl_platform *platform, EGLNativeDisplayType *platform_display) @@ -206,26 +179,62 @@ static BOOL wayland_drawable_swap(struct opengl_drawable *base)
ensure_window_surface_contents(toplevel); set_client_surface(hwnd, gl->client); - - /* Although all the EGL surfaces we create are double-buffered, we want to - * use some as single-buffered, so avoid swapping those. */ - if (gl->double_buffered) funcs->p_eglSwapBuffers(egl->display, gl->base.surface); + funcs->p_eglSwapBuffers(egl->display, gl->base.surface);
return TRUE; }
+struct wayland_pbuffer +{ + struct opengl_drawable base; + struct wl_surface *surface; + struct wl_egl_window *window; +}; + +static struct wayland_pbuffer *pbuffer_from_opengl_drawable(struct opengl_drawable *base) +{ + return CONTAINING_RECORD(base, struct wayland_pbuffer, base); +} + +static void wayland_pbuffer_destroy(struct opengl_drawable *base) +{ + struct wayland_pbuffer *gl = pbuffer_from_opengl_drawable(base); + + TRACE("%s\n", debugstr_opengl_drawable(base)); + + if (gl->window) + wl_egl_window_destroy(gl->window); + if (gl->surface) + wl_surface_destroy(gl->surface); +} + +static const struct opengl_drawable_funcs wayland_pbuffer_funcs = +{ + .destroy = wayland_pbuffer_destroy, +}; + static BOOL wayland_pbuffer_create(HDC hdc, int format, BOOL largest, GLenum texture_format, GLenum texture_target, GLint max_level, GLsizei *width, GLsizei *height, struct opengl_drawable **surface) { - struct wayland_gl_drawable *drawable; + EGLConfig config = egl_config_for_format(format); + struct wayland_pbuffer *gl;
TRACE("hdc %p, format %d, largest %u, texture_format %#x, texture_target %#x, max_level %#x, width %d, height %d, private %p\n", hdc, format, largest, texture_format, texture_target, max_level, *width, *height, surface);
- /* Use an unmapped wayland surface as our offscreen "pbuffer" surface. */ - if (!(drawable = wayland_gl_drawable_create(0, hdc, format, *width, *height))) return FALSE; - *surface = &drawable->base; + if (!(gl = opengl_drawable_create(sizeof(*gl), &wayland_pbuffer_funcs, format, NULL, hdc))) return FALSE; + /* Wayland EGL doesn't support pixmap or pbuffer, create a dummy window surface to act as the target render surface. */ + if (!(gl->surface = wl_compositor_create_surface(process_wayland.wl_compositor))) goto err; + if (!(gl->window = wl_egl_window_create(gl->surface, *width, *height))) goto err; + if (!(gl->base.surface = funcs->p_eglCreateWindowSurface(egl->display, config, gl->window, NULL))) goto err; + + TRACE("Created pbuffer %s with egl_surface %p\n", debugstr_opengl_drawable(&gl->base), gl->base.surface); + *surface = &gl->base; return TRUE; + +err: + opengl_drawable_release(&gl->base); + return FALSE; }
static BOOL wayland_pbuffer_updated(HDC hdc, struct opengl_drawable *base, GLenum cube_face, GLint mipmap_level)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/win32u/opengl.c | 5 ++--- dlls/wineandroid.drv/opengl.c | 3 +-- dlls/winemac.drv/opengl.c | 4 ++-- dlls/winewayland.drv/opengl.c | 4 ++-- dlls/winex11.drv/opengl.c | 17 +++++++++-------- include/wine/opengl_driver.h | 5 ++--- 6 files changed, 18 insertions(+), 20 deletions(-)
diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index f5071657e23..7b1afb7571a 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -210,7 +210,7 @@ void update_opengl_drawables( HWND hwnd ) pthread_mutex_unlock( &drawables_lock ); }
-void *opengl_drawable_create( UINT size, const struct opengl_drawable_funcs *funcs, int format, HWND hwnd, HDC hdc ) +void *opengl_drawable_create( UINT size, const struct opengl_drawable_funcs *funcs, int format, HWND hwnd ) { struct opengl_drawable *drawable;
@@ -221,7 +221,6 @@ void *opengl_drawable_create( UINT size, const struct opengl_drawable_funcs *fun drawable->format = format; drawable->interval = INT_MIN; drawable->hwnd = hwnd; - drawable->hdc = hdc;
if (!hwnd) list_init( &drawable->entry ); /* pbuffer, keep it unlinked */ else @@ -553,7 +552,7 @@ static BOOL egldrv_pbuffer_create( HDC hdc, int format, BOOL largest, GLenum tex } *attrib++ = EGL_NONE;
- if (!(gl = opengl_drawable_create( sizeof(*gl), &egldrv_pbuffer_funcs, format, 0, hdc ))) return FALSE; + if (!(gl = opengl_drawable_create( sizeof(*gl), &egldrv_pbuffer_funcs, format, 0 ))) return FALSE; if (!(gl->surface = funcs->p_eglCreatePbufferSurface( egl->display, egl_config_for_format( egl, gl->format ), attribs ))) { opengl_drawable_release( gl ); diff --git a/dlls/wineandroid.drv/opengl.c b/dlls/wineandroid.drv/opengl.c index ba72dbd4979..fde0e24c02d 100644 --- a/dlls/wineandroid.drv/opengl.c +++ b/dlls/wineandroid.drv/opengl.c @@ -75,7 +75,7 @@ static struct gl_drawable *create_gl_drawable( HWND hwnd, HDC hdc, int format, A static const int attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE }; struct gl_drawable *gl;
- if (!(gl = opengl_drawable_create( sizeof(*gl), &android_drawable_funcs, format, hwnd, hdc ))) return NULL; + if (!(gl = opengl_drawable_create( sizeof(*gl), &android_drawable_funcs, format, hwnd ))) return NULL;
if (!window) gl->window = create_ioctl_window( hwnd, TRUE, 1.0f ); else gl->window = grab_ioctl_window( window ); @@ -134,7 +134,6 @@ static BOOL android_surface_create( HWND hwnd, HDC hdc, int format, struct openg funcs->p_eglGetConfigAttrib( egl->display, egl_config_for_format(format), EGL_NATIVE_VISUAL_ID, &pf ); gl->window->perform( gl->window, NATIVE_WINDOW_SET_BUFFERS_FORMAT, pf ); gl->base.hwnd = hwnd; - gl->base.hdc = hdc; gl->base.format = format;
TRACE( "Updated drawable %s\n", debugstr_opengl_drawable( *drawable ) ); diff --git a/dlls/winemac.drv/opengl.c b/dlls/winemac.drv/opengl.c index 4d9780c7eb3..f48737c1b43 100644 --- a/dlls/winemac.drv/opengl.c +++ b/dlls/winemac.drv/opengl.c @@ -1484,7 +1484,7 @@ static BOOL macdrv_surface_create(HWND hwnd, HDC hdc, int format, struct opengl_ data->pixel_format = format; release_win_data(data);
- if (!(gl = opengl_drawable_create(sizeof(*gl), &macdrv_surface_funcs, format, hwnd, hdc))) return FALSE; + if (!(gl = opengl_drawable_create(sizeof(*gl), &macdrv_surface_funcs, format, hwnd))) return FALSE; *drawable = &gl->base;
return TRUE; @@ -2357,7 +2357,7 @@ static BOOL macdrv_pbuffer_create(HDC hdc, int format, BOOL largest, GLenum text texture_format = GL_RGB; }
- if (!(gl = opengl_drawable_create(sizeof(*gl), &macdrv_pbuffer_funcs, format, 0, hdc))) return FALSE; + if (!(gl = opengl_drawable_create(sizeof(*gl), &macdrv_pbuffer_funcs, format, 0))) return FALSE;
err = CGLCreatePBuffer(*width, *height, texture_target, texture_format, max_level, &gl->pbuffer); if (err != kCGLNoError) diff --git a/dlls/winewayland.drv/opengl.c b/dlls/winewayland.drv/opengl.c index 68795777d3b..a0f9397d73d 100644 --- a/dlls/winewayland.drv/opengl.c +++ b/dlls/winewayland.drv/opengl.c @@ -135,7 +135,7 @@ static BOOL wayland_opengl_surface_create(HWND hwnd, HDC hdc, int format, struct } *attrib++ = EGL_NONE;
- if (!(gl = opengl_drawable_create(sizeof(*gl), &wayland_drawable_funcs, format, hwnd, hdc))) return FALSE; + if (!(gl = opengl_drawable_create(sizeof(*gl), &wayland_drawable_funcs, format, hwnd))) return FALSE; if (!(gl->client = wayland_client_surface_create(hwnd))) goto err; if (!(gl->wl_egl_window = wl_egl_window_create(gl->client->wl_surface, rect.right, rect.bottom))) goto err; if (!(gl->base.surface = funcs->p_eglCreateWindowSurface(egl->display, config, gl->wl_egl_window, attribs))) goto err; @@ -222,7 +222,7 @@ static BOOL wayland_pbuffer_create(HDC hdc, int format, BOOL largest, GLenum tex TRACE("hdc %p, format %d, largest %u, texture_format %#x, texture_target %#x, max_level %#x, width %d, height %d, private %p\n", hdc, format, largest, texture_format, texture_target, max_level, *width, *height, surface);
- if (!(gl = opengl_drawable_create(sizeof(*gl), &wayland_pbuffer_funcs, format, NULL, hdc))) return FALSE; + if (!(gl = opengl_drawable_create(sizeof(*gl), &wayland_pbuffer_funcs, format, NULL))) return FALSE; /* Wayland EGL doesn't support pixmap or pbuffer, create a dummy window surface to act as the target render surface. */ if (!(gl->surface = wl_compositor_create_surface(process_wayland.wl_compositor))) goto err; if (!(gl->window = wl_egl_window_create(gl->surface, *width, *height))) goto err; diff --git a/dlls/winex11.drv/opengl.c b/dlls/winex11.drv/opengl.c index 4d100088030..8581ace0e6d 100644 --- a/dlls/winex11.drv/opengl.c +++ b/dlls/winex11.drv/opengl.c @@ -203,6 +203,7 @@ struct gl_drawable Colormap colormap; /* colormap for the client window */ Pixmap pixmap; /* base pixmap if drawable is a GLXPixmap */ BOOL offscreen; + HDC hdc; HDC hdc_src; HDC hdc_dst; }; @@ -493,16 +494,16 @@ static BOOL x11drv_egl_surface_create( HWND hwnd, HDC hdc, int format, struct op 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; + if (!(gl = opengl_drawable_create( sizeof(*gl), &x11drv_egl_surface_funcs, format, hwnd ))) return FALSE; gl->rect = rect; + gl->hdc = hdc;
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 ); + opengl_drawable_release( &gl->base ); return FALSE; }
@@ -934,8 +935,9 @@ static BOOL x11drv_surface_create( HWND hwnd, HDC hdc, int format, struct opengl if ((previous = *drawable) && previous->format == format) return TRUE; NtUserGetClientRect( hwnd, &rect, NtUserGetDpiForWindow( hwnd ) );
- if (!(gl = opengl_drawable_create( sizeof(*gl), &x11drv_surface_funcs, format, hwnd, hdc ))) return FALSE; + if (!(gl = opengl_drawable_create( sizeof(*gl), &x11drv_surface_funcs, format, hwnd ))) return FALSE; gl->rect = rect; + gl->hdc = hdc;
gl->colormap = XCreateColormap( gdi_display, get_dummy_parent(), fmt->visual->visual, (fmt->visual->class == PseudoColor || fmt->visual->class == GrayScale || @@ -1261,15 +1263,14 @@ static void present_gl_drawable( struct gl_drawable *gl, BOOL flush, BOOL gl_fin { HWND hwnd = gl->base.hwnd, toplevel = NtUserGetAncestor( hwnd, GA_ROOT ); struct x11drv_win_data *data; - HDC hdc = gl->base.hdc; Drawable window; RECT rect_dst, rect; HRGN region;
if (!gl->offscreen) return;
- window = get_dc_drawable( hdc, &rect ); - region = get_dc_monitor_region( hwnd, hdc ); + window = get_dc_drawable( gl->hdc, &rect ); + region = get_dc_monitor_region( hwnd, gl->hdc );
if (gl_finish) funcs->p_glFinish(); if (flush) XFlush( gdi_display ); @@ -1401,7 +1402,7 @@ static BOOL x11drv_pbuffer_create( HDC hdc, int format, BOOL largest, GLenum tex } glx_attribs[count++] = 0;
- if (!(gl = opengl_drawable_create( sizeof(*gl), &x11drv_pbuffer_funcs, format, 0, hdc ))) return FALSE; + if (!(gl = opengl_drawable_create( sizeof(*gl), &x11drv_pbuffer_funcs, format, 0 ))) return FALSE;
gl->drawable = pglXCreatePbuffer( gdi_display, fmt->fbconfig, glx_attribs ); TRACE( "new Pbuffer drawable as %p (%lx)\n", gl, gl->drawable ); diff --git a/include/wine/opengl_driver.h b/include/wine/opengl_driver.h index 188c7b81249..604bd6d6757 100644 --- a/include/wine/opengl_driver.h +++ b/include/wine/opengl_driver.h @@ -154,7 +154,6 @@ struct opengl_drawable int format; /* pixel format of the drawable */ int interval; /* last set surface swap interval */ HWND hwnd; /* window the drawable was created for */ - HDC hdc; /* DC the drawable was created for */ struct list entry; /* entry in win32u managed list */ LONG updated; /* has been moved / resized / reparented */ EGLSurface surface; /* surface for EGL based drivers */ @@ -163,10 +162,10 @@ struct opengl_drawable static inline const char *debugstr_opengl_drawable( struct opengl_drawable *drawable ) { if (!drawable) return "(null)"; - return wine_dbg_sprintf( "%p (format %u, hwnd %p, hdc %p)", drawable, drawable->format, drawable->hwnd, drawable->hdc ); + return wine_dbg_sprintf( "%p (format %u, hwnd %p)", drawable, drawable->format, drawable->hwnd ); }
-W32KAPI void *opengl_drawable_create( UINT size, const struct opengl_drawable_funcs *funcs, int format, HWND hwnd, HDC hdc ); +W32KAPI void *opengl_drawable_create( UINT size, const struct opengl_drawable_funcs *funcs, int format, HWND hwnd ); W32KAPI void opengl_drawable_add_ref( struct opengl_drawable *drawable ); W32KAPI void opengl_drawable_release( struct opengl_drawable *drawable );
v3: Keep winewayland pbuffer backed by wl_surface, split them from window drawables so they don't get in the way of later refactoring.
@afrantzis all they need is a wl_surface and an wl_egl_window right? Could you confirm whether https://gitlab.winehq.org/wine/wine/-/merge_requests/8498/diffs?commit_id=50... would work?