From: Rémi Bernon rbernon@codeweavers.com
--- dlls/opengl32/tests/opengl.c | 4 +- dlls/win32u/opengl.c | 256 ++++++++++++++++++++++++++--------- include/wine/opengl_driver.h | 6 +- 3 files changed, 198 insertions(+), 68 deletions(-)
diff --git a/dlls/opengl32/tests/opengl.c b/dlls/opengl32/tests/opengl.c index 868cb41ee70..deecc5c67e8 100644 --- a/dlls/opengl32/tests/opengl.c +++ b/dlls/opengl32/tests/opengl.c @@ -1409,7 +1409,7 @@ static void test_bitmap_rendering( BOOL use_dib ) /* cannot create a GL context without a pixel format */
hglrc = wglCreateContext( hdc ); - todo_wine ok( !hglrc, "wglCreateContext succeeded\n" ); + ok( !hglrc, "wglCreateContext succeeded\n" ); if (hglrc) wglDeleteContext( hglrc );
/* cannot set pixel format twice */ @@ -1695,7 +1695,7 @@ static void test_d3dkmt_rendering(void) /* cannot create a GL context without a pixel format */
hglrc = wglCreateContext( desc.hDc ); - todo_wine ok( !hglrc, "wglCreateContext succeeded\n" ); + ok( !hglrc, "wglCreateContext succeeded\n" ); if (hglrc) wglDeleteContext( hglrc );
/* cannot set pixel format twice */ diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index 4fad50fadcc..35665b25add 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -39,6 +39,13 @@
WINE_DEFAULT_DEBUG_CHANNEL(wgl);
+struct wgl_context +{ + const struct opengl_driver_funcs *driver_funcs; + struct opengl_funcs *funcs; + void *driver_private; +}; + struct wgl_pbuffer { const struct opengl_driver_funcs *driver_funcs; @@ -168,7 +175,7 @@ static void register_extension( char *list, size_t size, const char *name )
typedef struct osmesa_context *OSMesaContext;
-struct wgl_context +struct osmesa_context { OSMesaContext context; UINT format; @@ -184,6 +191,7 @@ static void * (*pOSMesaGetProcAddress)( const char *funcName ); static GLboolean (*pOSMesaMakeCurrent)( OSMesaContext ctx, void *buffer, GLenum type, GLsizei width, GLsizei height ); static void (*pOSMesaPixelStore)( GLint pname, GLint value ); +static void describe_pixel_format( int fmt, PIXELFORMATDESCRIPTOR *descr );
static struct opengl_funcs *osmesa_get_wgl_driver( const struct opengl_driver_funcs **driver_funcs ) { @@ -237,12 +245,18 @@ static BOOL osmesa_set_pixel_format( HWND hwnd, int old_format, int new_format, return TRUE; }
-static struct wgl_context *osmesa_create_context( HDC hdc, int format ) +static BOOL osmesa_context_create( HDC hdc, int format, void *shared, const int *attribs, void **private ) { + struct osmesa_context *context; PIXELFORMATDESCRIPTOR descr; - struct wgl_context *context; UINT gl_format;
+ if (attribs) + { + ERR( "attribs not supported\n" ); + return FALSE; + } + describe_pixel_format( format, &descr );
switch (descr.cColorBits) @@ -271,11 +285,13 @@ static struct wgl_context *osmesa_create_context( HDC hdc, int format ) return FALSE; }
- return context; + *private = context; + return TRUE; }
-static BOOL osmesa_delete_context( struct wgl_context *context ) +static BOOL osmesa_context_destroy( void *private ) { + struct osmesa_context *context = private; pOSMesaDestroyContext( context->context ); free( context ); return TRUE; @@ -286,68 +302,50 @@ static PROC osmesa_get_proc_address( const char *proc ) return (PROC)pOSMesaGetProcAddress( proc ); }
-static BOOL osmesa_make_current( struct wgl_context *context, void *bits, - int width, int height, int bpp, int stride ) -{ - BOOL ret; - GLenum type; - - if (!context) - { - pOSMesaMakeCurrent( NULL, NULL, GL_UNSIGNED_BYTE, 0, 0 ); - return TRUE; - } - - type = context->format == OSMESA_RGB_565 ? GL_UNSIGNED_SHORT_5_6_5 : GL_UNSIGNED_BYTE; - ret = pOSMesaMakeCurrent( context->context, bits, type, width, height ); - if (ret) - { - pOSMesaPixelStore( OSMESA_ROW_LENGTH, abs( stride ) * 8 / bpp ); - pOSMesaPixelStore( OSMESA_Y_UP, 1 ); /* Windows seems to assume bottom-up */ - } - return ret; -} - -static BOOL osmesa_wglCopyContext( struct wgl_context *src, struct wgl_context *dst, UINT mask ) +static PROC osmesa_wglGetProcAddress( const char *proc ) { - FIXME( "not supported yet\n" ); - return FALSE; + if (!strncmp( proc, "wgl", 3 )) return NULL; + return osmesa_get_proc_address( proc ); }
-static BOOL osmesa_wglDeleteContext( struct wgl_context *context ) +static BOOL osmesa_wglSwapBuffers( HDC hdc ) { - return osmesa_delete_context( context ); + return TRUE; }
-static struct wgl_context *osmesa_wglCreateContext( HDC hdc ) +static BOOL osmesa_context_copy( void *src_private, void *dst_private, UINT mask ) { - PIXELFORMATDESCRIPTOR descr; - struct opengl_funcs *funcs; - int format; - - if (!(funcs = get_dc_funcs( hdc, NULL ))) return NULL; - if (!(format = funcs->p_wglGetPixelFormat( hdc ))) format = 1; - describe_pixel_format( format, &descr ); - - return osmesa_create_context( hdc, format ); + FIXME( "not supported yet\n" ); + return FALSE; }
-static PROC osmesa_wglGetProcAddress( const char *proc ) +static BOOL osmesa_context_share( void *src_private, void *dst_private ) { - if (!strncmp( proc, "wgl", 3 )) return NULL; - return osmesa_get_proc_address( proc ); + FIXME( "not supported yet\n" ); + return FALSE; }
-static BOOL osmesa_wglMakeCurrent( HDC hdc, struct wgl_context *context ) +static BOOL osmesa_context_make_current( HDC draw_hdc, HDC read_hdc, void *private ) { + struct osmesa_context *context = private; HBITMAP bitmap; BITMAPOBJ *bmp; dib_info dib; BOOL ret = FALSE;
- if (!context) return osmesa_make_current( NULL, NULL, 0, 0, 0, 0 ); + if (!private) + { + pOSMesaMakeCurrent( NULL, NULL, GL_UNSIGNED_BYTE, 0, 0 ); + return TRUE; + } + + if (draw_hdc != read_hdc) + { + ERR( "read != draw not supported\n" ); + return FALSE; + }
- bitmap = NtGdiGetDCObject( hdc, NTGDI_OBJ_SURF ); + bitmap = NtGdiGetDCObject( draw_hdc, NTGDI_OBJ_SURF ); bmp = GDI_GetObjPtr( bitmap, NTGDI_OBJ_BITMAP ); if (!bmp) return FALSE;
@@ -356,6 +354,7 @@ static BOOL osmesa_wglMakeCurrent( HDC hdc, struct wgl_context *context ) char *bits; int width = dib.rect.right - dib.rect.left; int height = dib.rect.bottom - dib.rect.top; + GLenum type;
if (dib.stride < 0) bits = (char *)dib.bits.ptr + (dib.rect.bottom - 1) * dib.stride; else bits = (char *)dib.bits.ptr + dib.rect.top * dib.stride; @@ -363,23 +362,18 @@ static BOOL osmesa_wglMakeCurrent( HDC hdc, struct wgl_context *context )
TRACE( "context %p bits %p size %ux%u\n", context, bits, width, height );
- ret = osmesa_make_current( context, bits, width, height, dib.bit_count, dib.stride ); + type = context->format == OSMESA_RGB_565 ? GL_UNSIGNED_SHORT_5_6_5 : GL_UNSIGNED_BYTE; + ret = pOSMesaMakeCurrent( context->context, bits, type, width, height ); + if (ret) + { + pOSMesaPixelStore( OSMESA_ROW_LENGTH, abs( dib.stride ) * 8 / dib.bit_count ); + pOSMesaPixelStore( OSMESA_Y_UP, 1 ); /* Windows seems to assume bottom-up */ + } } GDI_ReleaseObj( bitmap ); return ret; }
-static BOOL osmesa_wglShareLists( struct wgl_context *org, struct wgl_context *dest ) -{ - FIXME( "not supported yet\n" ); - return FALSE; -} - -static BOOL osmesa_wglSwapBuffers( HDC hdc ) -{ - return TRUE; -} - static void osmesa_get_pixel_formats( struct wgl_pixel_format *formats, UINT max_formats, UINT *num_formats, UINT *num_onscreen_formats ) { @@ -393,12 +387,7 @@ static void osmesa_get_pixel_formats( struct wgl_pixel_format *formats, UINT max
static struct opengl_funcs osmesa_opengl_funcs = { - .p_wglCopyContext = osmesa_wglCopyContext, - .p_wglCreateContext = osmesa_wglCreateContext, - .p_wglDeleteContext = osmesa_wglDeleteContext, .p_wglGetProcAddress = osmesa_wglGetProcAddress, - .p_wglMakeCurrent = osmesa_wglMakeCurrent, - .p_wglShareLists = osmesa_wglShareLists, .p_wglSwapBuffers = osmesa_wglSwapBuffers, .p_get_pixel_formats = osmesa_get_pixel_formats, }; @@ -407,6 +396,11 @@ static const struct opengl_driver_funcs osmesa_driver_funcs = { .p_init_wgl_extensions = osmesa_init_wgl_extensions, .p_set_pixel_format = osmesa_set_pixel_format, + .p_context_create = osmesa_context_create, + .p_context_destroy = osmesa_context_destroy, + .p_context_copy = osmesa_context_copy, + .p_context_share = osmesa_context_share, + .p_context_make_current = osmesa_context_make_current, };
#else /* SONAME_LIBOSMESA */ @@ -570,6 +564,114 @@ static void win32u_display_get_pixel_formats( struct wgl_pixel_format *formats, *num_onscreen_formats = onscreen_count; }
+static struct wgl_context *context_create( HDC hdc, struct wgl_context *shared, const int *attribs ) +{ + void *shared_private = shared ? shared->driver_private : NULL; + const struct opengl_driver_funcs *driver_funcs; + struct wgl_context *context; + struct opengl_funcs *funcs; + int format; + + TRACE( "hdc %p, shared %p, attribs %p\n", hdc, shared, attribs ); + + if (!(format = win32u_wglGetPixelFormat( hdc ))) + { + RtlSetLastWin32Error( ERROR_INVALID_PIXEL_FORMAT ); + return NULL; + } + + if (!(funcs = get_dc_funcs( hdc, NULL ))) return NULL; + driver_funcs = funcs == display_funcs ? display_driver_funcs : memory_driver_funcs; + + if (!(context = calloc( 1, sizeof(*context) ))) return NULL; + context->driver_funcs = driver_funcs; + context->funcs = funcs; + + if (!driver_funcs->p_context_create( hdc, format, shared_private, attribs, &context->driver_private )) + { + free( context ); + return NULL; + } + + TRACE( "created context %p for driver context %p\n", context, context->driver_private ); + return context; +} + +static struct wgl_context *win32u_wglCreateContextAttribsARB( HDC hdc, struct wgl_context *shared, const int *attribs ) +{ + static const int empty_attribs = {0}; + + TRACE( "hdc %p, shared %p, attribs %p\n", hdc, shared, attribs ); + + if (!attribs) attribs = &empty_attribs; + return context_create( hdc, shared, attribs ); +} + +static struct wgl_context *win32u_wglCreateContext( HDC hdc ) +{ + TRACE( "hdc %p\n", hdc ); + return context_create( hdc, NULL, NULL ); +} + +static BOOL win32u_wglDeleteContext( struct wgl_context *context ) +{ + const struct opengl_driver_funcs *funcs = context->driver_funcs; + BOOL ret; + + TRACE( "context %p\n", context ); + + ret = funcs->p_context_destroy( context->driver_private ); + free( context ); + + return ret; +} + +static BOOL win32u_wglCopyContext( struct wgl_context *src, struct wgl_context *dst, UINT mask ) +{ + const struct opengl_driver_funcs *funcs = src->driver_funcs; + + TRACE( "src %p, dst %p, mask %#x\n", src, dst, mask ); + + if (funcs != dst->driver_funcs) return FALSE; + return funcs->p_context_copy( src->driver_private, dst->driver_private, mask ); +} + +static BOOL win32u_wglShareLists( struct wgl_context *src, struct wgl_context *dst ) +{ + const struct opengl_driver_funcs *funcs = src->driver_funcs; + + TRACE( "src %p, dst %p\n", src, dst ); + + if (funcs != dst->driver_funcs) return FALSE; + return funcs->p_context_share( src->driver_private, dst->driver_private ); +} + +static BOOL win32u_wglMakeContextCurrentARB( HDC draw_hdc, HDC read_hdc, struct wgl_context *context ) +{ + const struct opengl_driver_funcs *funcs; + + TRACE( "draw_hdc %p, read_hdc %p, context %p\n", draw_hdc, read_hdc, context ); + + if (!context) + { + if (!(context = NtCurrentTeb()->glContext)) return TRUE; + funcs = context->driver_funcs; + if (!funcs->p_context_make_current( NULL, NULL, NULL )) return FALSE; + NtCurrentTeb()->glContext = NULL; + return TRUE; + } + + funcs = context->driver_funcs; + if (!funcs->p_context_make_current( draw_hdc, read_hdc, context->driver_private )) return FALSE; + NtCurrentTeb()->glContext = context; + return TRUE; +} + +static BOOL win32u_wglMakeCurrent( HDC hdc, struct wgl_context *context ) +{ + return win32u_wglMakeContextCurrentARB( hdc, hdc, context ); +} + static struct wgl_pbuffer *win32u_wglCreatePbufferARB( HDC hdc, int format, int width, int height, const int *attribs ) { @@ -991,6 +1093,12 @@ static void memory_funcs_init(void)
memory_funcs->p_wglGetPixelFormat = win32u_wglGetPixelFormat; memory_funcs->p_wglSetPixelFormat = win32u_wglSetPixelFormat; + + memory_funcs->p_wglCreateContext = win32u_wglCreateContext; + memory_funcs->p_wglDeleteContext = win32u_wglDeleteContext; + memory_funcs->p_wglCopyContext = win32u_wglCopyContext; + memory_funcs->p_wglShareLists = win32u_wglShareLists; + memory_funcs->p_wglMakeCurrent = win32u_wglMakeCurrent; }
static void display_funcs_init(void) @@ -1029,6 +1137,24 @@ static void display_funcs_init(void) display_funcs->p_wglGetPixelFormatAttribfvARB = (void *)1; /* never called */ display_funcs->p_wglGetPixelFormatAttribivARB = (void *)1; /* never called */
+ if (display_driver_funcs->p_context_create) + { + display_funcs->p_wglCreateContext = win32u_wglCreateContext; + display_funcs->p_wglDeleteContext = win32u_wglDeleteContext; + display_funcs->p_wglCopyContext = win32u_wglCopyContext; + display_funcs->p_wglShareLists = win32u_wglShareLists; + display_funcs->p_wglMakeCurrent = win32u_wglMakeCurrent; + + register_extension( wgl_extensions, ARRAY_SIZE(wgl_extensions), "WGL_ARB_create_context" ); + register_extension( wgl_extensions, ARRAY_SIZE(wgl_extensions), "WGL_ARB_create_context_no_error" ); + register_extension( wgl_extensions, ARRAY_SIZE(wgl_extensions), "WGL_ARB_create_context_profile" ); + display_funcs->p_wglCreateContextAttribsARB = win32u_wglCreateContextAttribsARB; + + register_extension( wgl_extensions, ARRAY_SIZE(wgl_extensions), "WGL_ARB_make_current_read" ); + display_funcs->p_wglGetCurrentReadDCARB = (void *)1; /* never called */ + display_funcs->p_wglMakeContextCurrentARB = win32u_wglMakeContextCurrentARB; + } + register_extension( wgl_extensions, ARRAY_SIZE(wgl_extensions), "WGL_ARB_pbuffer" ); display_funcs->p_wglCreatePbufferARB = win32u_wglCreatePbufferARB; display_funcs->p_wglDestroyPbufferARB = win32u_wglDestroyPbufferARB; diff --git a/include/wine/opengl_driver.h b/include/wine/opengl_driver.h index 1d78ac09b1c..2a760e98020 100644 --- a/include/wine/opengl_driver.h +++ b/include/wine/opengl_driver.h @@ -117,7 +117,11 @@ struct opengl_driver_funcs BOOL (*p_describe_pixel_format)(int,struct wgl_pixel_format*); const char *(*p_init_wgl_extensions)(void); BOOL (*p_set_pixel_format)(HWND,int,int,BOOL); - + BOOL (*p_context_create)(HDC,int,void*,const int*,void**); + BOOL (*p_context_destroy)(void*); + BOOL (*p_context_copy)(void*,void*,UINT); + BOOL (*p_context_share)(void*,void*); + BOOL (*p_context_make_current)(HDC,HDC,void*); BOOL (*p_pbuffer_create)(HDC,int,BOOL,GLenum,GLenum,GLint,GLsizei*,GLsizei*,void **); BOOL (*p_pbuffer_destroy)(HDC,void*); BOOL (*p_pbuffer_updated)(HDC,void*,GLenum,GLint);