From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/opengl32/make_opengl | 71 +++----- dlls/opengl32/private.h | 1 + dlls/opengl32/thunks.c | 55 +----- dlls/opengl32/unix_private.h | 6 + dlls/opengl32/unix_thunks.c | 58 +++--- dlls/opengl32/unix_thunks.h | 4 +- dlls/opengl32/unix_wgl.c | 334 ++++++++++++++++------------------- dlls/opengl32/wgl.c | 143 +++++++++++++++ dlls/win32u/opengl.c | 7 +- include/wine/opengl_driver.h | 31 +++- include/wine/wgl.h | 19 +- 11 files changed, 401 insertions(+), 328 deletions(-) diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index e592a97b7d5..d71a715e008 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -126,11 +126,6 @@ my %arg_types = "FLOAT" => [ "float", "%f" ], ); -my %remap_types = - ( - "HGLRC" => "struct wgl_context *", - ); - my %khronos_types = ( "double" => "double DECLSPEC_ALIGN(8)", @@ -173,7 +168,10 @@ my %manual_win_thunks = "glGetString" => 1, "glGetStringi" => 1, "wglChoosePixelFormatARB" => 1, + "wglCreateContext" => 1, + "wglCreateContextAttribsARB" => 1, "wglCreatePbufferARB" => 1, + "wglDeleteContext" => 1, "wglDestroyPbufferARB" => 1, "wglGetExtensionsStringARB" => 1, "wglGetExtensionsStringEXT" => 1, @@ -181,6 +179,8 @@ my %manual_win_thunks = "wglGetPixelFormatAttribfvARB" => 1, "wglGetPixelFormatAttribivARB" => 1, "wglGetProcAddress" => 1, + "wglMakeContextCurrentARB" => 1, + "wglMakeCurrent" => 1, "wglQueryCurrentRendererStringWINE" => 1, "wglQueryRendererStringWINE" => 1, "wglSwapBuffers" => 1, @@ -206,16 +206,23 @@ my %manual_unix_thunks = "glGetFramebufferParameterivEXT" => 1, "glGetInteger64v" => 1, "glGetIntegerv" => 1, - "glGetUnsignedBytevEXT" => 1, "glGetString" => 1, "glGetStringi" => 1, + "glGetUnsignedBytevEXT" => 1, "glNamedFramebufferDrawBuffer" => 1, "glNamedFramebufferDrawBuffers" => 1, "glNamedFramebufferReadBuffer" => 1, "glReadBuffer" => 1, "glReadPixels" => 1, "glViewport" => 1, + "wglCopyContext" => 1, + "wglCreateContext" => 1, + "wglCreateContextAttribsARB" => 1, + "wglDeleteContext" => 1, "wglGetProcAddress" => 1, + "wglMakeContextCurrentARB" => 1, + "wglMakeCurrent" => 1, + "wglShareLists" => 1, "wglSwapBuffers" => 1, ); my %hide_default_fbo_thunks = @@ -374,12 +381,6 @@ sub ConvertType($) my $arg = shift; my $ret = $arg->textContent(); my @type = $arg->findnodes("./ptype"); - - if (@type) - { - my $type = $type[0]->textContent(); - $ret =~ s/$type/$remap_types{$type}/ if defined $remap_types{$type}; - } return $ret; } @@ -426,6 +427,7 @@ sub get_func_args($$) $ret .= " " . ($unix ? ConvertType( $arg ) : $arg->textContent()) . ","; } $ret .= " HPBUFFERARB client_pbuffer," if $unix && $func->[0] =~ /HPBUFFERARB/; + $ret .= " HGLRC client_context," if $unix && $func->[0] =~ /HGLRC/ && @{$func->[1]}; $ret =~ s/,$/ /; $ret ||= "void"; return $ret; @@ -445,7 +447,7 @@ sub generate_unix_thunk($$$$) my $func_ret = get_func_ret( $func, 0 ); my $manual_wow64_wrapper = $is_wow64 && defined $manual_wow64_wrappers{$name}; my $need_wrap = $manual_wow64_wrapper || needs_wrapper( $name, $func ); - my $need_lock = $func_ret =~ /HGLRC/; + my $need_lock = 0; my $need_funcs = !$need_wrap || ($prefix eq "ext" && $name !~ /^wgl/); my $teb = $is_wow64 ? "teb" : "params->teb"; my $ret_stat = "return STATUS_SUCCESS;"; @@ -453,17 +455,13 @@ sub generate_unix_thunk($$$$) my $input_conv = ""; my $output_conv = ""; my $use_pbuffer = 0; + my $use_context = 0; my $call_args = ""; my $ret_expr = ""; my $use_dc = 0; my $vars = ""; my $ret = ""; - foreach my $arg (@{$func->[1]}) - { - $need_lock = 1 if $arg->textContent() =~ /HGLRC/; - } - $ret .= "static NTSTATUS "; $ret .= "wow64_" if $is_wow64; $ret .= "$prefix\_$name( void *args )\n"; @@ -472,6 +470,7 @@ sub generate_unix_thunk($$$$) # special case for functions that take an HDC as first parameter $use_dc = @{$func->[1]} && get_arg_type( ${$func->[1]}[0] ) eq "HDC" && $name !~ /wglMake(Context)?Current/; $use_pbuffer = @{$func->[1]} && get_arg_type( ${$func->[1]}[0] ) eq "HPBUFFERARB"; + $use_context = @{$func->[1]} && get_arg_type( ${$func->[1]}[0] ) eq "HGLRC"; $ret_expr = "params->ret = " if !is_void_func( $func ); $call_args .= " $teb," if $need_wrap; @@ -524,7 +523,7 @@ sub generate_unix_thunk($$$$) $need_lock = 1 if $arg_type =~ /GLsync/; } } - $call_args .= " UlongToHandle( params->ret )," if $func_ret =~ /HPBUFFERARB/; + $call_args .= " UlongToHandle( params->ret )," if $func_ret =~ /HPBUFFERARB|HGLRC/; if (!is_void_func($func)) { my $ret_type = get_arg_type( $func->[0] ); @@ -539,7 +538,7 @@ sub generate_unix_thunk($$$$) elsif ($ptype eq "PTR32") { $ret_expr .= "(UINT_PTR)"; - $need_manual_thunk = 1 if $func_ret !~ /HDC|HPBUFFERARB/; + $need_manual_thunk = 1 if $func_ret !~ /HDC|HPBUFFERARB|HGLRC/; } } $ret .= " } *params = args;\n"; @@ -560,7 +559,7 @@ sub generate_unix_thunk($$$$) : " buffer = invalidate_buffer_target( $teb, params->target );\n"; $output_conv .= " if (buffer) free_buffer( funcs, buffer );\n"; } - $ret .= " TEB *teb = get_teb64( params->teb );\n" if $need_wrap || (!$use_dc && !$use_pbuffer); + $ret .= " TEB *teb = get_teb64( params->teb );\n" if $need_wrap || (!$use_dc && !$use_pbuffer && !$use_context); } else { @@ -568,26 +567,20 @@ sub generate_unix_thunk($$$$) { my $ptype = get_arg_type( $arg ); my $pname = get_arg_name( $arg ); - if (!$need_wrap && defined $remap_types{$ptype}) - { - $call_args .= " ($remap_types{$ptype})params->$pname,"; - } - else - { - $call_args .= " params->$pname,"; - } + $call_args .= " params->$pname,"; } - $call_args .= " params->ret," if $func_ret =~ /HPBUFFERARB/; + $call_args .= " params->ret," if $func_ret =~ /HPBUFFERARB|HGLRC/; $ret .= " struct $name\_params *params = args;\n"; } $ret .= $vars; - if ($use_dc || $use_pbuffer) + if ($use_dc || $use_pbuffer || $use_context) { my $param = "params->" . get_arg_name( ${$func->[1]}[0] ); $param = "ULongToPtr($param)" if $is_wow64; $ret .= " const struct opengl_funcs *funcs = "; $ret .= "get_dc_funcs( $param );\n" if $use_dc; $ret .= "get_pbuffer_funcs( $param );\n" if $use_pbuffer; + $ret .= "get_context_funcs( $param );\n" if $use_context; $ret .= " if (!funcs || !funcs->p_$name) return STATUS_NOT_IMPLEMENTED;\n"; } elsif ($need_funcs) @@ -618,7 +611,6 @@ sub generate_unix_thunk($$$$) } else { - $ret .= "($func_ret)" if defined $remap_types{$func_ret}; $ret .= "funcs->p_$name($call_args);\n"; } $ret .= " pthread_mutex_unlock( &wgl_lock );\n" if $need_lock; @@ -670,6 +662,7 @@ sub generate_wrapper_declaration($$$) $ret .= " " . $arg->textContent() . ","; } $ret .= " HPBUFFERARB handle," if $ret_type =~ /HPBUFFERARB/; + $ret .= " HGLRC handle," if $ret_type =~ /HGLRC/; $ret =~ s/,$/ /; $ret .= ");\n"; return $ret; @@ -679,6 +672,7 @@ sub get_handle_function($) { my $ptype = shift; return "get_pbuffer_from_handle" if $ptype =~ /HPBUFFERARB/; + return "get_context_from_handle" if $ptype =~ /HGLRC/; return 0; } @@ -979,19 +973,8 @@ sub is_supported_extension($) sub needs_wrapper($$) { my ($name, $func) = @_; - return 0 if defined $manual_win_functions{$name}; return 1 if defined $manual_unix_thunks{$name}; - - # check if return value needs special handling - (my $type = $func->[0]->textContent()) =~ s/ $//; - return 1 if defined $remap_types{$type}; - # check if one of the arguments needs special handling - foreach (@{$func->[1]}) - { - $type = get_arg_type( $_ ); - return 1 if defined $remap_types{$type}; - } return 0; } @@ -1188,8 +1171,6 @@ print HEADER "#ifndef EGL_CAST\n"; print HEADER "#define EGL_CAST(t,x) ((t)(x))\n"; print HEADER "#endif\n\n"; -print HEADER "struct wgl_context;\n"; - foreach (@gl_types) { my $type = $gl_types{$_}; diff --git a/dlls/opengl32/private.h b/dlls/opengl32/private.h index 3a1dc0cd433..5ee9a0fce2d 100644 --- a/dlls/opengl32/private.h +++ b/dlls/opengl32/private.h @@ -33,5 +33,6 @@ extern const void *extension_procs[]; extern int WINAPI wglDescribePixelFormat( HDC hdc, int ipfd, UINT cjpfd, PIXELFORMATDESCRIPTOR *ppfd ); extern BOOL get_pbuffer_from_handle( HPBUFFERARB handle, HPBUFFERARB *obj ); +extern BOOL get_context_from_handle( HGLRC handle, HGLRC *obj ); #endif /* __WINE_OPENGL32_PRIVATE_H */ diff --git a/dlls/opengl32/thunks.c b/dlls/opengl32/thunks.c index bbf1070feab..437ae70fe9c 100644 --- a/dlls/opengl32/thunks.c +++ b/dlls/opengl32/thunks.c @@ -18,40 +18,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(opengl); BOOL WINAPI wglCopyContext( HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask ) { - struct wglCopyContext_params args = { .teb = NtCurrentTeb(), .hglrcSrc = hglrcSrc, .hglrcDst = hglrcDst, .mask = mask }; + struct wglCopyContext_params args = { .teb = NtCurrentTeb(), .mask = mask }; NTSTATUS status; TRACE( "hglrcSrc %p, hglrcDst %p, mask %u\n", hglrcSrc, hglrcDst, mask ); + if (!get_context_from_handle( hglrcSrc, &args.hglrcSrc )) return 0; + if (!get_context_from_handle( hglrcDst, &args.hglrcDst )) return 0; if ((status = UNIX_CALL( wglCopyContext, &args ))) WARN( "wglCopyContext returned %#lx\n", status ); return args.ret; } -HGLRC WINAPI wglCreateContext( HDC hDc ) -{ - struct wglCreateContext_params args = { .teb = NtCurrentTeb(), .hDc = hDc }; - NTSTATUS status; - TRACE( "hDc %p\n", hDc ); - if ((status = UNIX_CALL( wglCreateContext, &args ))) WARN( "wglCreateContext returned %#lx\n", status ); - return args.ret; -} - -BOOL WINAPI wglDeleteContext( HGLRC oldContext ) -{ - struct wglDeleteContext_params args = { .teb = NtCurrentTeb(), .oldContext = oldContext }; - NTSTATUS status; - TRACE( "oldContext %p\n", oldContext ); - if ((status = UNIX_CALL( wglDeleteContext, &args ))) WARN( "wglDeleteContext returned %#lx\n", status ); - return args.ret; -} - -BOOL WINAPI wglMakeCurrent( HDC hDc, HGLRC newContext ) -{ - struct wglMakeCurrent_params args = { .teb = NtCurrentTeb(), .hDc = hDc, .newContext = newContext }; - NTSTATUS status; - TRACE( "hDc %p, newContext %p\n", hDc, newContext ); - if ((status = UNIX_CALL( wglMakeCurrent, &args ))) WARN( "wglMakeCurrent returned %#lx\n", status ); - return args.ret; -} - BOOL WINAPI wglSetPixelFormat( HDC hdc, int ipfd, const PIXELFORMATDESCRIPTOR *ppfd ) { struct wglSetPixelFormat_params args = { .teb = NtCurrentTeb(), .hdc = hdc, .ipfd = ipfd, .ppfd = ppfd }; @@ -63,9 +38,11 @@ BOOL WINAPI wglSetPixelFormat( HDC hdc, int ipfd, const PIXELFORMATDESCRIPTOR *p BOOL WINAPI wglShareLists( HGLRC hrcSrvShare, HGLRC hrcSrvSource ) { - struct wglShareLists_params args = { .teb = NtCurrentTeb(), .hrcSrvShare = hrcSrvShare, .hrcSrvSource = hrcSrvSource }; + struct wglShareLists_params args = { .teb = NtCurrentTeb() }; NTSTATUS status; TRACE( "hrcSrvShare %p, hrcSrvSource %p\n", hrcSrvShare, hrcSrvSource ); + if (!get_context_from_handle( hrcSrvShare, &args.hrcSrvShare )) return 0; + if (!get_context_from_handle( hrcSrvSource, &args.hrcSrvSource )) return 0; if ((status = UNIX_CALL( wglShareLists, &args ))) WARN( "wglShareLists returned %#lx\n", status ); return args.ret; } @@ -24743,15 +24720,6 @@ static BOOL WINAPI wglBindTexImageARB( HPBUFFERARB hPbuffer, int iBuffer ) return args.ret; } -static HGLRC WINAPI wglCreateContextAttribsARB( HDC hDC, HGLRC hShareContext, const int *attribList ) -{ - struct wglCreateContextAttribsARB_params args = { .teb = NtCurrentTeb(), .hDC = hDC, .hShareContext = hShareContext, .attribList = attribList }; - NTSTATUS status; - TRACE( "hDC %p, hShareContext %p, attribList %p\n", hDC, hShareContext, attribList ); - if ((status = UNIX_CALL( wglCreateContextAttribsARB, &args ))) WARN( "wglCreateContextAttribsARB returned %#lx\n", status ); - return args.ret; -} - static void WINAPI wglFreeMemoryNV( void *pointer ) { struct wglFreeMemoryNV_params args = { .teb = NtCurrentTeb(), .pointer = pointer }; @@ -24779,15 +24747,6 @@ static int WINAPI wglGetSwapIntervalEXT(void) return args.ret; } -static BOOL WINAPI wglMakeContextCurrentARB( HDC hDrawDC, HDC hReadDC, HGLRC hglrc ) -{ - struct wglMakeContextCurrentARB_params args = { .teb = NtCurrentTeb(), .hDrawDC = hDrawDC, .hReadDC = hReadDC, .hglrc = hglrc }; - NTSTATUS status; - TRACE( "hDrawDC %p, hReadDC %p, hglrc %p\n", hDrawDC, hReadDC, hglrc ); - if ((status = UNIX_CALL( wglMakeContextCurrentARB, &args ))) WARN( "wglMakeContextCurrentARB returned %#lx\n", status ); - return args.ret; -} - static BOOL WINAPI wglQueryCurrentRendererIntegerWINE( GLenum attribute, GLuint *value ) { struct wglQueryCurrentRendererIntegerWINE_params args = { .teb = NtCurrentTeb(), .attribute = attribute, .value = value }; @@ -24866,6 +24825,7 @@ static BOOL WINAPI wglSwapIntervalEXT( int interval ) extern const GLubyte * WINAPI glGetStringi( GLenum name, GLuint index ); extern BOOL WINAPI wglChoosePixelFormatARB( HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats ); +extern HGLRC WINAPI wglCreateContextAttribsARB( HDC hDC, HGLRC hShareContext, const int *attribList ); extern HPBUFFERARB WINAPI wglCreatePbufferARB( HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList ); extern BOOL WINAPI wglDestroyPbufferARB( HPBUFFERARB hPbuffer ); extern HDC WINAPI wglGetCurrentReadDCARB(void); @@ -24873,6 +24833,7 @@ extern const char * WINAPI wglGetExtensionsStringARB( HDC hdc ); extern const char * WINAPI wglGetExtensionsStringEXT(void); extern BOOL WINAPI wglGetPixelFormatAttribfvARB( HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues ); extern BOOL WINAPI wglGetPixelFormatAttribivARB( HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues ); +extern BOOL WINAPI wglMakeContextCurrentARB( HDC hDrawDC, HDC hReadDC, HGLRC hglrc ); extern const GLchar * WINAPI wglQueryCurrentRendererStringWINE( GLenum attribute ); extern const GLchar * WINAPI wglQueryRendererStringWINE( HDC dc, GLint renderer, GLenum attribute ); const void *extension_procs[] = diff --git a/dlls/opengl32/unix_private.h b/dlls/opengl32/unix_private.h index a42445a0983..e1076fe7831 100644 --- a/dlls/opengl32/unix_private.h +++ b/dlls/opengl32/unix_private.h @@ -63,6 +63,12 @@ static inline const struct opengl_funcs *get_pbuffer_funcs( HPBUFFERARB client_p return client_pbuffer ? (struct opengl_funcs *)(UINT_PTR)client->unix_funcs : NULL; } +static inline const struct opengl_funcs *get_context_funcs( HGLRC client_context ) +{ + struct opengl_client_context *client = opengl_client_context_from_client( client_context ); + return client_context ? (struct opengl_funcs *)(UINT_PTR)client->unix_funcs : NULL; +} + #ifdef _WIN64 static inline void *copy_wow64_ptr32s( UINT_PTR address, ULONG count ) diff --git a/dlls/opengl32/unix_thunks.c b/dlls/opengl32/unix_thunks.c index 5ef8612bb9a..41ce0f2d5e1 100644 --- a/dlls/opengl32/unix_thunks.c +++ b/dlls/opengl32/unix_thunks.c @@ -26,9 +26,9 @@ static GLboolean const_true = 1; static NTSTATUS wgl_wglCopyContext( void *args ) { struct wglCopyContext_params *params = args; - pthread_mutex_lock( &wgl_lock ); + const struct opengl_funcs *funcs = get_context_funcs( params->hglrcSrc ); + if (!funcs || !funcs->p_wglCopyContext) return STATUS_NOT_IMPLEMENTED; params->ret = wrap_wglCopyContext( params->teb, params->hglrcSrc, params->hglrcDst, params->mask ); - pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; } @@ -37,18 +37,16 @@ static NTSTATUS wgl_wglCreateContext( void *args ) struct wglCreateContext_params *params = args; const struct opengl_funcs *funcs = get_dc_funcs( params->hDc ); if (!funcs || !funcs->p_wglCreateContext) return STATUS_NOT_IMPLEMENTED; - pthread_mutex_lock( &wgl_lock ); - params->ret = wrap_wglCreateContext( params->teb, params->hDc ); - pthread_mutex_unlock( &wgl_lock ); + params->ret = wrap_wglCreateContext( params->teb, params->hDc, params->ret ); return STATUS_SUCCESS; } static NTSTATUS wgl_wglDeleteContext( void *args ) { struct wglDeleteContext_params *params = args; - pthread_mutex_lock( &wgl_lock ); + const struct opengl_funcs *funcs = get_context_funcs( params->oldContext ); + if (!funcs || !funcs->p_wglDeleteContext) return STATUS_NOT_IMPLEMENTED; params->ret = wrap_wglDeleteContext( params->teb, params->oldContext ); - pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; } @@ -71,9 +69,7 @@ static NTSTATUS wgl_wglGetProcAddress( void *args ) static NTSTATUS wgl_wglMakeCurrent( void *args ) { struct wglMakeCurrent_params *params = args; - pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglMakeCurrent( params->teb, params->hDc, params->newContext ); - pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; } @@ -89,9 +85,9 @@ static NTSTATUS wgl_wglSetPixelFormat( void *args ) static NTSTATUS wgl_wglShareLists( void *args ) { struct wglShareLists_params *params = args; - pthread_mutex_lock( &wgl_lock ); + const struct opengl_funcs *funcs = get_context_funcs( params->hrcSrvShare ); + if (!funcs || !funcs->p_wglShareLists) return STATUS_NOT_IMPLEMENTED; params->ret = wrap_wglShareLists( params->teb, params->hrcSrvShare, params->hrcSrvSource ); - pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; } @@ -30319,9 +30315,7 @@ static NTSTATUS ext_wglCreateContextAttribsARB( void *args ) struct wglCreateContextAttribsARB_params *params = args; const struct opengl_funcs *funcs = get_dc_funcs( params->hDC ); if (!funcs || !funcs->p_wglCreateContextAttribsARB) return STATUS_NOT_IMPLEMENTED; - pthread_mutex_lock( &wgl_lock ); - params->ret = wrap_wglCreateContextAttribsARB( params->teb, params->hDC, params->hShareContext, params->attribList ); - pthread_mutex_unlock( &wgl_lock ); + params->ret = wrap_wglCreateContextAttribsARB( params->teb, params->hDC, params->hShareContext, params->attribList, params->ret ); return STATUS_SUCCESS; } @@ -30409,9 +30403,7 @@ static NTSTATUS ext_wglGetSwapIntervalEXT( void *args ) static NTSTATUS ext_wglMakeContextCurrentARB( void *args ) { struct wglMakeContextCurrentARB_params *params = args; - pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglMakeContextCurrentARB( params->teb, params->hDrawDC, params->hReadDC, params->hglrc ); - pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; } @@ -33630,9 +33622,9 @@ static NTSTATUS wow64_wgl_wglCopyContext( void *args ) BOOL ret; } *params = args; TEB *teb = get_teb64( params->teb ); - pthread_mutex_lock( &wgl_lock ); + const struct opengl_funcs *funcs = get_context_funcs( ULongToPtr(params->hglrcSrc) ); + if (!funcs || !funcs->p_wglCopyContext) return STATUS_NOT_IMPLEMENTED; params->ret = wrap_wglCopyContext( teb, ULongToPtr(params->hglrcSrc), ULongToPtr(params->hglrcDst), params->mask ); - pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; } @@ -33647,9 +33639,7 @@ static NTSTATUS wow64_wgl_wglCreateContext( void *args ) TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = get_dc_funcs( ULongToPtr(params->hDc) ); if (!funcs || !funcs->p_wglCreateContext) return STATUS_NOT_IMPLEMENTED; - pthread_mutex_lock( &wgl_lock ); - params->ret = (UINT_PTR)wrap_wglCreateContext( teb, ULongToPtr(params->hDc) ); - pthread_mutex_unlock( &wgl_lock ); + params->ret = (UINT_PTR)wrap_wglCreateContext( teb, ULongToPtr(params->hDc), UlongToHandle( params->ret ) ); return STATUS_SUCCESS; } @@ -33662,9 +33652,9 @@ static NTSTATUS wow64_wgl_wglDeleteContext( void *args ) BOOL ret; } *params = args; TEB *teb = get_teb64( params->teb ); - pthread_mutex_lock( &wgl_lock ); + const struct opengl_funcs *funcs = get_context_funcs( ULongToPtr(params->oldContext) ); + if (!funcs || !funcs->p_wglDeleteContext) return STATUS_NOT_IMPLEMENTED; params->ret = wrap_wglDeleteContext( teb, ULongToPtr(params->oldContext) ); - pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; } @@ -33705,9 +33695,7 @@ static NTSTATUS wow64_wgl_wglMakeCurrent( void *args ) BOOL ret; } *params = args; TEB *teb = get_teb64( params->teb ); - pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglMakeCurrent( teb, ULongToPtr(params->hDc), ULongToPtr(params->newContext) ); - pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; } @@ -33737,9 +33725,9 @@ static NTSTATUS wow64_wgl_wglShareLists( void *args ) BOOL ret; } *params = args; TEB *teb = get_teb64( params->teb ); - pthread_mutex_lock( &wgl_lock ); + const struct opengl_funcs *funcs = get_context_funcs( ULongToPtr(params->hrcSrvShare) ); + if (!funcs || !funcs->p_wglShareLists) return STATUS_NOT_IMPLEMENTED; params->ret = wrap_wglShareLists( teb, ULongToPtr(params->hrcSrvShare), ULongToPtr(params->hrcSrvSource) ); - pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; } @@ -86527,9 +86515,7 @@ static NTSTATUS wow64_ext_wglCreateContextAttribsARB( void *args ) TEB *teb = get_teb64( params->teb ); const struct opengl_funcs *funcs = get_dc_funcs( ULongToPtr(params->hDC) ); if (!funcs || !funcs->p_wglCreateContextAttribsARB) return STATUS_NOT_IMPLEMENTED; - pthread_mutex_lock( &wgl_lock ); - params->ret = (UINT_PTR)wrap_wglCreateContextAttribsARB( teb, ULongToPtr(params->hDC), ULongToPtr(params->hShareContext), ULongToPtr(params->attribList) ); - pthread_mutex_unlock( &wgl_lock ); + params->ret = (UINT_PTR)wrap_wglCreateContextAttribsARB( teb, ULongToPtr(params->hDC), ULongToPtr(params->hShareContext), ULongToPtr(params->attribList), UlongToHandle( params->ret ) ); return STATUS_SUCCESS; } @@ -86686,9 +86672,7 @@ static NTSTATUS wow64_ext_wglMakeContextCurrentARB( void *args ) BOOL ret; } *params = args; TEB *teb = get_teb64( params->teb ); - pthread_mutex_lock( &wgl_lock ); params->ret = wrap_wglMakeContextCurrentARB( teb, ULongToPtr(params->hDrawDC), ULongToPtr(params->hReadDC), ULongToPtr(params->hglrc) ); - pthread_mutex_unlock( &wgl_lock ); return STATUS_SUCCESS; } @@ -89960,17 +89944,17 @@ C_ASSERT(ARRAYSIZE(__wine_unix_call_wow64_funcs) == funcs_count); #endif -static BOOL null_wglCopyContext( struct wgl_context * hglrcSrc, struct wgl_context * hglrcDst, UINT mask ) +static BOOL null_wglCopyContext( HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask ) { WARN( "unsupported\n" ); return 0; } -static struct wgl_context * null_wglCreateContext( HDC hDc ) +static HGLRC null_wglCreateContext( HDC hDc, HGLRC client_context ) { WARN( "unsupported\n" ); return 0; } -static BOOL null_wglDeleteContext( struct wgl_context * oldContext ) +static BOOL null_wglDeleteContext( HGLRC oldContext ) { WARN( "unsupported\n" ); return 0; @@ -89986,7 +89970,7 @@ static PROC null_wglGetProcAddress( LPCSTR lpszProc ) WARN( "unsupported\n" ); return 0; } -static BOOL null_wglMakeCurrent( HDC hDc, struct wgl_context * newContext ) +static BOOL null_wglMakeCurrent( HDC hDc, HGLRC newContext ) { WARN( "unsupported\n" ); return 0; @@ -89996,7 +89980,7 @@ static BOOL null_wglSetPixelFormat( HDC hdc, int ipfd, const PIXELFORMATDESCRIPT WARN( "unsupported\n" ); return 0; } -static BOOL null_wglShareLists( struct wgl_context * hrcSrvShare, struct wgl_context * hrcSrvSource ) +static BOOL null_wglShareLists( HGLRC hrcSrvShare, HGLRC hrcSrvSource ) { WARN( "unsupported\n" ); return 0; diff --git a/dlls/opengl32/unix_thunks.h b/dlls/opengl32/unix_thunks.h index 2d42d73de03..e23c9e9e5bd 100644 --- a/dlls/opengl32/unix_thunks.h +++ b/dlls/opengl32/unix_thunks.h @@ -3,7 +3,7 @@ typedef ULONG PTR32; extern BOOL wrap_wglCopyContext( TEB *teb, HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask ); -extern HGLRC wrap_wglCreateContext( TEB *teb, HDC hDc ); +extern HGLRC wrap_wglCreateContext( TEB *teb, HDC hDc, HGLRC handle ); extern BOOL wrap_wglDeleteContext( TEB *teb, HGLRC oldContext ); extern PROC wrap_wglGetProcAddress( TEB *teb, LPCSTR lpszProc ); extern BOOL wrap_wglMakeCurrent( TEB *teb, HDC hDc, HGLRC newContext ); @@ -37,7 +37,7 @@ extern void wrap_glGetUnsignedBytevEXT( TEB *teb, GLenum pname, GLubyte *data ); extern void wrap_glNamedFramebufferDrawBuffer( TEB *teb, GLuint framebuffer, GLenum buf ); extern void wrap_glNamedFramebufferDrawBuffers( TEB *teb, GLuint framebuffer, GLsizei n, const GLenum *bufs ); extern void wrap_glNamedFramebufferReadBuffer( TEB *teb, GLuint framebuffer, GLenum src ); -extern HGLRC wrap_wglCreateContextAttribsARB( TEB *teb, HDC hDC, HGLRC hShareContext, const int *attribList ); +extern HGLRC wrap_wglCreateContextAttribsARB( TEB *teb, HDC hDC, HGLRC hShareContext, const int *attribList, HGLRC handle ); extern BOOL wrap_wglMakeContextCurrentARB( TEB *teb, HDC hDrawDC, HDC hReadDC, HGLRC hglrc ); #ifdef _WIN64 diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index acb71457bf5..17994a2c324 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -60,7 +60,6 @@ pthread_mutex_t wgl_lock = PTHREAD_MUTEX_INITIALIZER; enum wgl_handle_type { - HANDLE_CONTEXT = 1 << 12, HANDLE_GLSYNC = 2 << 12, HANDLE_TYPE_MASK = 15 << 12, }; @@ -132,6 +131,7 @@ struct context struct wgl_context base; HDC hdc; /* context creation DC */ + HGLRC client; /* client-side context handle */ HGLRC share; /* context to be shared with */ int *attribs; /* creation attributes */ DWORD tid; /* thread that the context is current in */ @@ -195,23 +195,6 @@ struct vk_device PFN_vkUnmapMemory2KHR p_vkUnmapMemory2KHR; }; -struct wgl_handle -{ - UINT handle; - const struct opengl_funcs *funcs; - union - { - struct wgl_context *context; /* for HANDLE_CONTEXT */ - GLsync sync; /* for HANDLE_GLSYNC */ - struct wgl_handle *next; /* for free handles */ - } u; -}; - -#define MAX_WGL_HANDLES 1024 -static struct wgl_handle wgl_handles[MAX_WGL_HANDLES]; -static struct wgl_handle *next_free; -static unsigned int handle_count; - static ULONG_PTR zero_bits; static const struct vulkan_funcs *vk_funcs; @@ -226,39 +209,24 @@ static int vk_device_cmp( const void *key, const struct rb_entry *entry ) struct rb_tree vk_devices = { vk_device_cmp }; -static struct context *context_from_wgl_context( struct wgl_context *context ) +static void opengl_client_context_init( HGLRC client_context, struct context *context, const struct opengl_funcs *funcs ) { - return CONTAINING_RECORD( context, struct context, base ); + struct opengl_client_context *client = opengl_client_context_from_client( client_context ); + client->unix_handle = (UINT_PTR)context; + client->unix_funcs = (UINT_PTR)funcs; } /* the current context is assumed valid and doesn't need locking */ static struct context *get_current_context( TEB *teb, struct opengl_drawable **draw, struct opengl_drawable **read ) { - struct wgl_context *context; - if (!teb->glCurrentRC) return NULL; - if (!(context = wgl_handles[LOWORD(teb->glCurrentRC) & ~HANDLE_TYPE_MASK].u.context)) return NULL; - if (draw) *draw = context->draw; - if (read) *read = context->read; - return context_from_wgl_context( context ); -} - -static inline HANDLE next_handle( struct wgl_handle *ptr, enum wgl_handle_type type ) -{ - WORD generation = HIWORD( ptr->handle ) + 1; - if (!generation) generation++; - ptr->handle = MAKELONG( ptr - wgl_handles, generation ) | type; - return ULongToHandle( ptr->handle ); -} + struct wgl_context *base; + struct context *context; -static struct wgl_handle *get_handle_ptr( HANDLE handle ) -{ - unsigned int index = LOWORD( handle ) & ~HANDLE_TYPE_MASK; - - if (index < handle_count && ULongToHandle(wgl_handles[index].handle) == handle) - return &wgl_handles[index]; - - RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); - return NULL; + if (!(base = teb->glContext)) return NULL; + context = CONTAINING_RECORD( base, struct context, base ); + if (draw) *draw = context->base.draw; + if (read) *read = context->base.read; + return context; } struct context_attribute_desc @@ -301,28 +269,28 @@ void set_context_attribute( TEB *teb, GLenum name, const void *value, size_t siz else if (size && size != context_attributes[name].size) ERR( "Invalid state attrib %#x parameter size %#zx\n", name, size ); else memcpy( (char *)ctx + context_attributes[name].offset, value, context_attributes[name].size ); - if (bit == -1 && ctx->used != -1) WARN( "Unsupported attribute on context %p/%p\n", teb->glCurrentRC, ctx ); + if (bit == -1 && ctx->used != -1) WARN( "Unsupported attribute on context %p\n", ctx ); ctx->used |= bit; } -static BOOL copy_context_attributes( TEB *teb, const struct opengl_funcs *funcs, HGLRC dst_handle, struct context *dst, - HGLRC src_handle, struct context *src, GLbitfield mask ) +static BOOL copy_context_attributes( TEB *teb, HGLRC client_dst, struct context *dst, + HGLRC client_src, struct context *src, GLbitfield mask ) { + struct context *old_ctx = CONTAINING_RECORD( teb->glContext, struct context, base ); HDC draw_hdc = teb->glReserved1[0], read_hdc = teb->glReserved1[1]; - struct context *old_ctx = get_current_context( teb, NULL, NULL ); - const struct opengl_funcs *old_funcs = teb->glTable; + const struct opengl_funcs *old_funcs = teb->glTable, *funcs; - if (dst == old_ctx) + if (dst == old_ctx || !(funcs = get_context_funcs( client_dst ))) { RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); return FALSE; } if (!mask) return TRUE; - if (src->used == -1) FIXME( "Unsupported attributes on context %p/%p\n", src_handle, src ); - if (src != dst && dst->used == -1) FIXME( "Unsupported attributes on context %p/%p\n", dst_handle, dst ); + if (src->used == -1) FIXME( "Unsupported attributes on context %p/%p\n", client_src, src ); + if (src != dst && dst->used == -1) FIXME( "Unsupported attributes on context %p/%p\n", client_dst, dst ); - funcs->p_wglMakeCurrent( dst->hdc, &dst->base ); + funcs->p_wglMakeCurrent( dst->hdc, client_dst ); if (mask & GL_COLOR_BUFFER_BIT) { @@ -371,8 +339,8 @@ static BOOL copy_context_attributes( TEB *teb, const struct opengl_funcs *funcs, dst->used |= (src->used & mask); if (!old_ctx) funcs->p_wglMakeCurrent( NULL, NULL ); - else if (!old_funcs->p_wglMakeContextCurrentARB) old_funcs->p_wglMakeCurrent( draw_hdc, &old_ctx->base ); - else old_funcs->p_wglMakeContextCurrentARB( draw_hdc, read_hdc, &old_ctx->base ); + else if (!old_funcs->p_wglMakeContextCurrentARB) old_funcs->p_wglMakeCurrent( draw_hdc, old_ctx->client ); + else old_funcs->p_wglMakeContextCurrentARB( draw_hdc, read_hdc, old_ctx->client ); return dst->used != -1 && src->used != -1; } @@ -420,82 +388,44 @@ static void release_buffers( const struct opengl_funcs *funcs, struct buffers *b free( buffers ); } -static struct context *opengl_context_from_handle( TEB *teb, HGLRC handle, const struct opengl_funcs **funcs ); +static struct context *context_from_client_context( HGLRC client_context ) +{ + struct wgl_context *base = opengl_context_from_handle( client_context ); + return base ? CONTAINING_RECORD( base, struct context, base ) : NULL; +} + +static struct context *get_updated_context( TEB *teb, HGLRC client_context ); -/* update handle context if it has been re-shared with another one */ -static void update_handle_context( TEB *teb, HGLRC handle, struct wgl_handle *ptr ) +/* update context if it has been re-shared with another one */ +static struct context *update_context( TEB *teb, HGLRC client_context, struct context *ctx ) { - struct context *ctx = context_from_wgl_context( ptr->u.context ), *shared; - const struct opengl_funcs *funcs = ptr->funcs, *share_funcs; + const struct opengl_funcs *funcs = get_context_funcs( client_context ); + struct context *share; - if (ctx->tid) return; /* currently in use */ - if (ctx->share == (HGLRC)-1) return; /* not re-shared */ + if (ctx->tid) return ctx; /* currently in use */ + if (ctx->share == (HGLRC)-1) return ctx; /* not re-shared */ - shared = ctx->share ? opengl_context_from_handle( teb, ctx->share, &share_funcs ) : NULL; - if (!funcs->p_wgl_context_reset( &ctx->base, ctx->hdc, shared ? &shared->base : NULL, ctx->attribs )) + share = ctx->share ? get_updated_context( teb, ctx->share ) : NULL; + if (!funcs->p_wgl_context_reset( &ctx->base, ctx->hdc, share ? &share->base : NULL, ctx->attribs )) { WARN( "Failed to re-create context for wglShareLists\n" ); - return; + return ctx; } - if (shared && shared->buffers) + if (share && share->buffers) { release_buffers( funcs, ctx->buffers ); - ctx->buffers = shared->buffers; + ctx->buffers = share->buffers; ctx->buffers->ref++; } ctx->share = (HGLRC)-1; /* initial shared context */ - copy_context_attributes( teb, funcs, handle, ctx, handle, ctx, ctx->used ); + copy_context_attributes( teb, client_context, ctx, client_context, ctx, ctx->used ); + return ctx; } -static struct context *opengl_context_from_handle( TEB *teb, HGLRC handle, const struct opengl_funcs **funcs ) +static struct context *get_updated_context( TEB *teb, HGLRC client_context ) { - struct wgl_handle *entry; - if (!(entry = get_handle_ptr( handle ))) return NULL; - update_handle_context( teb, handle, entry ); - *funcs = entry->funcs; - return context_from_wgl_context( entry->u.context ); -} - -static HANDLE alloc_handle( enum wgl_handle_type type, const struct opengl_funcs *funcs, void *user_ptr ) -{ - HANDLE handle = 0; - struct wgl_handle *ptr = NULL; - - if ((ptr = next_free)) - next_free = next_free->u.next; - else if (handle_count < MAX_WGL_HANDLES) - ptr = &wgl_handles[handle_count++]; - - if (ptr) - { - ptr->funcs = funcs; - ptr->u.context = user_ptr; - handle = next_handle( ptr, type ); - } - else RtlSetLastWin32Error( ERROR_NOT_ENOUGH_MEMORY ); - return handle; -} - -static void free_handle_ptr( struct wgl_handle *ptr ) -{ - ptr->handle |= 0xffff; - ptr->u.next = next_free; - ptr->funcs = NULL; - next_free = ptr; -} - -static void update_teb32_context( TEB *teb ) -{ -#ifdef _WIN64 - TEB32 *teb32; - - if (!teb->WowTebOffset) return; - teb32 = (TEB32 *)((char *)teb + teb->WowTebOffset); - - teb32->glCurrentRC = (UINT_PTR)teb->glCurrentRC; - teb32->glReserved1[0] = (UINT_PTR)teb->glReserved1[0]; - teb32->glReserved1[1] = (UINT_PTR)teb->glReserved1[1]; -#endif + struct context *context = context_from_client_context( client_context ); + return client_context ? update_context( teb, client_context, context ) : NULL; } static int *memdup_attribs( const int *attribs ) @@ -1032,15 +962,14 @@ PROC wrap_wglGetProcAddress( TEB *teb, LPCSTR name ) return (void *)(UINT_PTR)(found - extension_registry); } -BOOL wrap_wglCopyContext( TEB *teb, HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask ) +BOOL wrap_wglCopyContext( TEB *teb, HGLRC client_src, HGLRC client_dst, UINT mask ) { - const struct opengl_funcs *src_funcs, *dst_funcs; struct context *src, *dst; BOOL ret = FALSE; - if (!(src = opengl_context_from_handle( teb, hglrcSrc, &src_funcs ))) return FALSE; - if (!(dst = opengl_context_from_handle( teb, hglrcDst, &dst_funcs ))) return FALSE; - else ret = copy_context_attributes( teb, dst_funcs, hglrcDst, dst, hglrcSrc, src, mask ); + if (!(src = get_updated_context( teb, client_src ))) return FALSE; + if (!(dst = get_updated_context( teb, client_dst ))) return FALSE; + else ret = copy_context_attributes( teb, client_dst, dst, client_src, src, mask ); return ret; } @@ -1235,7 +1164,7 @@ static BOOL initialize_vk_device( TEB *teb, struct context *ctx ) } static void make_context_current( TEB *teb, const struct opengl_funcs *funcs, HDC draw_hdc, HDC read_hdc, - HGLRC hglrc, struct context *ctx ) + HGLRC client_context, struct context *ctx ) { DWORD tid = HandleToULong(teb->ClientId.UniqueThread); size_t size = ARRAYSIZE(legacy_extensions) - 1, count = 0; @@ -1247,7 +1176,6 @@ static void make_context_current( TEB *teb, const struct opengl_funcs *funcs, HD ctx->tid = tid; teb->glReserved1[0] = draw_hdc; teb->glReserved1[1] = read_hdc; - teb->glCurrentRC = hglrc; teb->glTable = (void *)funcs; pop_default_fbo( teb ); @@ -1350,30 +1278,30 @@ static void make_context_current( TEB *teb, const struct opengl_funcs *funcs, HD if (TRACE_ON(opengl)) for (i = 0; i < count; i++) TRACE( "++ %s\n", extensions[i] ); } -BOOL wrap_wglMakeCurrent( TEB *teb, HDC hdc, HGLRC hglrc ) +BOOL wrap_wglMakeCurrent( TEB *teb, HDC hdc, HGLRC client_context ) { DWORD tid = HandleToULong(teb->ClientId.UniqueThread); struct context *ctx, *prev = get_current_context( teb, NULL, NULL ); - const struct opengl_funcs *funcs = teb->glTable; - if (hglrc) + if (client_context) { - if (!(ctx = opengl_context_from_handle( teb, hglrc, &funcs ))) return FALSE; + const struct opengl_funcs *funcs = get_context_funcs( client_context ); + if (!(ctx = get_updated_context( teb, client_context ))) return FALSE; if (ctx->tid && ctx->tid != tid) { RtlSetLastWin32Error( ERROR_BUSY ); return FALSE; } - if (!funcs->p_wglMakeCurrent( hdc, &ctx->base )) return FALSE; + if (!funcs->p_wglMakeCurrent( hdc, client_context )) return FALSE; if (prev) prev->tid = 0; - make_context_current( teb, funcs, hdc, hdc, hglrc, ctx ); + make_context_current( teb, funcs, hdc, hdc, client_context, ctx ); } else if (prev) { + const struct opengl_funcs *funcs = teb->glTable; if (!funcs->p_wglMakeCurrent( 0, NULL )) return FALSE; prev->tid = 0; - teb->glCurrentRC = 0; teb->glTable = &null_opengl_funcs; } else if (!hdc) @@ -1381,7 +1309,6 @@ BOOL wrap_wglMakeCurrent( TEB *teb, HDC hdc, HGLRC hglrc ) RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); return FALSE; } - update_teb32_context( teb ); return TRUE; } @@ -1394,23 +1321,19 @@ static void free_context( struct context *ctx ) free( ctx ); } -BOOL wrap_wglDeleteContext( TEB *teb, HGLRC hglrc ) +BOOL wrap_wglDeleteContext( TEB *teb, HGLRC client_context ) { - struct wgl_handle *ptr; - struct context *ctx; - DWORD tid = HandleToULong(teb->ClientId.UniqueThread); + const struct opengl_funcs *funcs = get_context_funcs( client_context ); + struct context *ctx = context_from_client_context( client_context ); - if (!(ptr = get_handle_ptr( hglrc ))) return FALSE; - ctx = context_from_wgl_context( ptr->u.context ); - if (ctx->tid && ctx->tid != tid) + if (ctx->tid) { RtlSetLastWin32Error( ERROR_BUSY ); return FALSE; } - if (hglrc == teb->glCurrentRC) wrap_wglMakeCurrent( teb, 0, 0 ); - ptr->funcs->p_wgl_context_reset( &ctx->base, NULL, NULL, NULL ); + + funcs->p_wgl_context_reset( &ctx->base, NULL, NULL, NULL ); free_context( ctx ); - free_handle_ptr( ptr ); return TRUE; } @@ -1552,51 +1475,41 @@ BOOL wrap_wglSwapBuffers( TEB *teb, HDC hdc ) return ret; } -BOOL wrap_wglShareLists( TEB *teb, HGLRC hglrcSrc, HGLRC hglrcDst ) +BOOL wrap_wglShareLists( TEB *teb, HGLRC client_src, HGLRC client_dst ) { - const struct opengl_funcs *src_funcs, *dst_funcs; + const struct opengl_funcs *src_funcs = get_context_funcs( client_src ), *dst_funcs = get_context_funcs( client_dst ); struct context *src, *dst; BOOL ret = FALSE; - if (!(src = opengl_context_from_handle( teb, hglrcSrc, &src_funcs ))) return FALSE; - if (!(dst = opengl_context_from_handle( teb, hglrcDst, &dst_funcs ))) return FALSE; + if (!(src = context_from_client_context( client_src ))) return FALSE; + if (!(dst = context_from_client_context( client_dst ))) return FALSE; if (src_funcs != dst_funcs) RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); - else if ((ret = dst->used != -1)) dst->share = hglrcSrc; - else FIXME( "Unsupported attributes on context %p/%p\n", hglrcDst, dst ); + else if ((ret = dst->used != -1)) dst->share = client_src; + else FIXME( "Unsupported attributes on context %p/%p\n", client_dst, dst ); return ret; } -HGLRC wrap_wglCreateContextAttribsARB( TEB *teb, HDC hdc, HGLRC share, const int *attribs ) +HGLRC wrap_wglCreateContextAttribsARB( TEB *teb, HDC hdc, HGLRC client_shared, const int *attribs, HGLRC client_context ) { - HGLRC ret = 0; - struct context *context, *share_ctx = NULL; - const struct opengl_funcs *funcs = get_dc_funcs( hdc ), *share_funcs; + const struct opengl_funcs *funcs = get_dc_funcs( hdc ); + struct context *context, *shared = get_updated_context( teb, client_shared ); - if (!funcs) - { - RtlSetLastWin32Error( ERROR_DC_NOT_FOUND ); - return 0; - } - if (share && !(share_ctx = opengl_context_from_handle( teb, share, &share_funcs ))) - { - RtlSetLastWin32Error( ERROR_INVALID_OPERATION ); - return 0; - } if (!(context = calloc( 1, sizeof(*context) ))) { RtlSetLastWin32Error( ERROR_OUTOFMEMORY ); return 0; } + context->base.client_context = client_context; context->hdc = hdc; context->share = (HGLRC)-1; /* initial shared context */ context->attribs = memdup_attribs( attribs ); if (is_win64 && is_wow64()) { - if (share_ctx) + if (shared) { - context->buffers = share_ctx->buffers; + context->buffers = shared->buffers; context->buffers->ref++; } else if (!(context->buffers = malloc( sizeof(*context->buffers )))) @@ -1612,29 +1525,31 @@ HGLRC wrap_wglCreateContextAttribsARB( TEB *teb, HDC hdc, HGLRC share, const int } } - if (!(funcs->p_wgl_context_reset( &context->base, hdc, share_ctx ? &share_ctx->base : NULL, attribs ))) free_context( context ); - else if (!(ret = alloc_handle( HANDLE_CONTEXT, funcs, context ))) + if (!(funcs->p_wgl_context_reset( &context->base, hdc, shared ? &shared->base : NULL, attribs ))) { - funcs->p_wgl_context_reset( &context->base, NULL, NULL, NULL ); free_context( context ); + return 0; } - return ret; + + context->client = client_context; + opengl_client_context_init( client_context, context, funcs ); + return client_context; } -HGLRC wrap_wglCreateContext( TEB *teb, HDC hdc ) +HGLRC wrap_wglCreateContext( TEB *teb, HDC hdc, HGLRC client_context ) { - return wrap_wglCreateContextAttribsARB( teb, hdc, NULL, NULL ); + return wrap_wglCreateContextAttribsARB( teb, hdc, NULL, NULL, client_context ); } -BOOL wrap_wglMakeContextCurrentARB( TEB *teb, HDC draw_hdc, HDC read_hdc, HGLRC hglrc ) +BOOL wrap_wglMakeContextCurrentARB( TEB *teb, HDC draw_hdc, HDC read_hdc, HGLRC client_context ) { DWORD tid = HandleToULong(teb->ClientId.UniqueThread); struct context *ctx, *prev = get_current_context( teb, NULL, NULL ); - const struct opengl_funcs *funcs = teb->glTable; - if (hglrc) + if (client_context) { - if (!(ctx = opengl_context_from_handle( teb, hglrc, &funcs ))) return FALSE; + const struct opengl_funcs *funcs = get_context_funcs( client_context ); + if (!(ctx = get_updated_context( teb, client_context ))) return FALSE; if (ctx->tid && ctx->tid != tid) { RtlSetLastWin32Error( ERROR_BUSY ); @@ -1642,18 +1557,17 @@ BOOL wrap_wglMakeContextCurrentARB( TEB *teb, HDC draw_hdc, HDC read_hdc, HGLRC } if (!funcs->p_wglMakeContextCurrentARB) return FALSE; - if (!funcs->p_wglMakeContextCurrentARB( draw_hdc, read_hdc, &ctx->base )) return FALSE; + if (!funcs->p_wglMakeContextCurrentARB( draw_hdc, read_hdc, client_context )) return FALSE; if (prev) prev->tid = 0; - make_context_current( teb, funcs, draw_hdc, read_hdc, hglrc, ctx ); + make_context_current( teb, funcs, draw_hdc, read_hdc, client_context, ctx ); } else if (prev) { + const struct opengl_funcs *funcs = teb->glTable; if (!funcs->p_wglMakeCurrent( 0, NULL )) return FALSE; prev->tid = 0; - teb->glCurrentRC = 0; teb->glTable = &null_opengl_funcs; } - update_teb32_context( teb ); return TRUE; } @@ -2047,8 +1961,8 @@ void wrap_glGetFramebufferParameterivEXT( TEB *teb, GLuint fbo, GLenum pname, GL GLenum wrap_glGetError( TEB *teb ) { const struct opengl_funcs *funcs = teb->glTable; - GLenum error, wrapped; struct wgl_context *ctx; + GLenum error, wrapped; if (!(ctx = &get_current_context( teb, NULL, NULL )->base)) return GL_INVALID_OPERATION; error = funcs->p_glGetError(); @@ -2155,6 +2069,70 @@ NTSTATUS return_wow64_string( const void *str, PTR32 *wow64_str ) return STATUS_BUFFER_TOO_SMALL; } +struct wgl_handle +{ + UINT handle; + const struct opengl_funcs *funcs; + union + { + GLsync sync; /* for HANDLE_GLSYNC */ + struct wgl_handle *next; /* for free handles */ + void *data; + } u; +}; + +#define MAX_WGL_HANDLES 1024 +static struct wgl_handle wgl_handles[MAX_WGL_HANDLES]; +static struct wgl_handle *next_free; +static unsigned int handle_count; + +static HANDLE next_handle( struct wgl_handle *ptr, enum wgl_handle_type type ) +{ + WORD generation = HIWORD( ptr->handle ) + 1; + if (!generation) generation++; + ptr->handle = MAKELONG( ptr - wgl_handles, generation ) | type; + return ULongToHandle( ptr->handle ); +} + +static HANDLE alloc_handle( enum wgl_handle_type type, const struct opengl_funcs *funcs, void *user_ptr ) +{ + HANDLE handle = 0; + struct wgl_handle *ptr = NULL; + + if ((ptr = next_free)) + next_free = next_free->u.next; + else if (handle_count < MAX_WGL_HANDLES) + ptr = &wgl_handles[handle_count++]; + + if (ptr) + { + ptr->funcs = funcs; + ptr->u.data = user_ptr; + handle = next_handle( ptr, type ); + } + else RtlSetLastWin32Error( ERROR_NOT_ENOUGH_MEMORY ); + return handle; +} + +static void free_handle_ptr( struct wgl_handle *ptr ) +{ + ptr->handle |= 0xffff; + ptr->u.next = next_free; + ptr->funcs = NULL; + next_free = ptr; +} + +static struct wgl_handle *get_handle_ptr( HANDLE handle ) +{ + unsigned int index = LOWORD( handle ) & ~HANDLE_TYPE_MASK; + + if (index < handle_count && ULongToHandle(wgl_handles[index].handle) == handle) + return &wgl_handles[index]; + + RtlSetLastWin32Error( ERROR_INVALID_HANDLE ); + return NULL; +} + static struct wgl_handle *get_sync_ptr( TEB *teb, GLsync sync ) { struct wgl_handle *handle = get_handle_ptr( sync ); diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index 40ebed8bebd..de39feb3405 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -103,6 +103,7 @@ struct handle_entry UINT handle; union { + struct opengl_client_context *context; struct opengl_client_pbuffer *pbuffer; struct handle_entry *next_free; void *user_data; @@ -117,6 +118,7 @@ struct handle_table }; static struct handle_table pbuffers; +static struct handle_table contexts; static struct handle_entry *alloc_handle( struct handle_table *table, void *user_data ) { @@ -236,6 +238,147 @@ BOOL WINAPI wglDestroyPbufferARB( HPBUFFERARB handle ) return args.ret; } +static struct opengl_client_context *opengl_client_context_from_handle( HGLRC handle ) +{ + struct handle_entry *ptr; + if (!(ptr = get_handle_ptr( &contexts, handle ))) return NULL; + return ptr->context; +} + +BOOL get_context_from_handle( HGLRC handle, HGLRC *obj ) +{ + struct opengl_client_context *context = opengl_client_context_from_handle( handle ); + *obj = context ? &context->obj : NULL; + return context || !handle; +} + +static struct handle_entry *alloc_client_context(void) +{ + struct opengl_client_context *context; + struct handle_entry *ptr; + + if (!(context = calloc( 1, sizeof(*context) ))) return NULL; + if (!(ptr = alloc_handle( &contexts, context ))) + { + free( context ); + return NULL; + } + + return ptr; +} + +static void free_client_context( struct handle_entry *ptr ) +{ + struct opengl_client_context *context = ptr->context; + free_handle( &contexts, ptr ); + free( context ); +} + +HGLRC WINAPI wglCreateContext( HDC hdc ) +{ + struct wglCreateContext_params args = { .teb = NtCurrentTeb(), .hDc = hdc }; + struct handle_entry *ptr; + NTSTATUS status; + + TRACE( "hdc %p\n", hdc ); + + if (!(ptr = alloc_client_context())) return NULL; + args.ret = &ptr->context->obj; + + if ((status = UNIX_CALL( wglCreateContext, &args ))) WARN( "wglCreateContext returned %#lx\n", status ); + assert( args.ret == &ptr->context->obj || !args.ret ); + + if (!status && args.ret) return UlongToHandle( ptr->handle ); + free_client_context( ptr ); + return NULL; +} + +HGLRC WINAPI wglCreateContextAttribsARB( HDC hdc, HGLRC share, const int *attribs ) +{ + struct wglCreateContextAttribsARB_params args = { .teb = NtCurrentTeb(), .hDC = hdc, .attribList = attribs }; + struct handle_entry *ptr; + NTSTATUS status; + + TRACE( "hdc %p, share %p, attribs %p\n", hdc, share, attribs ); + + if (!get_context_from_handle( share, &args.hShareContext )) + { + SetLastError( ERROR_INVALID_OPERATION ); + return NULL; + } + if (!(ptr = alloc_client_context())) return NULL; + args.ret = &ptr->context->obj; + + if ((status = UNIX_CALL( wglCreateContextAttribsARB, &args ))) WARN( "wglCreateContextAttribsARB returned %#lx\n", status ); + assert( args.ret == &ptr->context->obj || !args.ret ); + + if (!status && args.ret) return UlongToHandle( ptr->handle ); + free_client_context( ptr ); + return NULL; +} + +BOOL WINAPI wglDeleteContext( HGLRC handle ) +{ + TEB *teb = NtCurrentTeb(); + struct wglDeleteContext_params args = {.teb = teb}; + struct handle_entry *ptr; + NTSTATUS status; + + TRACE( "handle %p\n", handle ); + + if (!(ptr = get_handle_ptr( &contexts, handle ))) return FALSE; + args.oldContext = &ptr->context->obj; + + if (handle && handle == teb->glCurrentRC) wglMakeCurrent( NULL, NULL ); + if ((status = UNIX_CALL( wglDeleteContext, &args ))) WARN( "wglDeleteContext returned %#lx\n", status ); + if (status || !args.ret) return FALSE; + + if (handle == teb->glCurrentRC) + { + teb->glCurrentRC = 0; + teb->glReserved1[0] = 0; + teb->glReserved1[1] = 0; + } + free_client_context( ptr ); + return TRUE; +} + +BOOL WINAPI wglMakeCurrent( HDC hdc, HGLRC handle ) +{ + TEB *teb = NtCurrentTeb(); + struct wglMakeCurrent_params args = { .teb = teb, .hDc = hdc }; + NTSTATUS status; + + TRACE( "hdc %p, newContext %p\n", hdc, handle ); + + if (!get_context_from_handle( handle, &args.newContext )) return FALSE; + if ((status = UNIX_CALL( wglMakeCurrent, &args ))) WARN( "wglMakeCurrent returned %#lx\n", status ); + if (status || !args.ret) return FALSE; + + teb->glCurrentRC = handle; + teb->glReserved1[0] = hdc; + teb->glReserved1[1] = hdc; + return TRUE; +} + +BOOL WINAPI wglMakeContextCurrentARB( HDC draw_hdc, HDC read_hdc, HGLRC handle ) +{ + TEB *teb = NtCurrentTeb(); + struct wglMakeContextCurrentARB_params args = { .teb = teb, .hDrawDC = draw_hdc, .hReadDC = read_hdc }; + NTSTATUS status; + + TRACE( "draw_hdc %p, read_hdc %p, handle %p\n", draw_hdc, read_hdc, handle ); + + if (!get_context_from_handle( handle, &args.hglrc )) return FALSE; + if ((status = UNIX_CALL( wglMakeContextCurrentARB, &args ))) WARN( "wglMakeContextCurrentARB returned %#lx\n", status ); + if (status || !args.ret) return FALSE; + + teb->glCurrentRC = handle; + teb->glReserved1[0] = draw_hdc; + teb->glReserved1[1] = read_hdc; + return TRUE; +} + /*********************************************************************** * wglGetCurrentReadDCARB * diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index 779c5bb2153..c41d36f808e 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -1882,8 +1882,9 @@ static void pop_internal_context( struct wgl_context *context ) driver_funcs->p_make_current( context->draw, context->read, context->driver_private ); } -static BOOL win32u_wglMakeContextCurrentARB( HDC draw_hdc, HDC read_hdc, struct wgl_context *context ) +static BOOL win32u_wglMakeContextCurrentARB( HDC draw_hdc, HDC read_hdc, HGLRC client_context ) { + struct wgl_context *context = opengl_context_from_handle( client_context ); struct wgl_context *prev_context = NtCurrentTeb()->glContext; BOOL created; int format; @@ -1930,9 +1931,9 @@ static BOOL win32u_wglMakeContextCurrentARB( HDC draw_hdc, HDC read_hdc, struct return TRUE; } -static BOOL win32u_wglMakeCurrent( HDC hdc, struct wgl_context *context ) +static BOOL win32u_wglMakeCurrent( HDC hdc, HGLRC client_context ) { - return win32u_wglMakeContextCurrentARB( hdc, hdc, context ); + return win32u_wglMakeContextCurrentARB( hdc, hdc, client_context ); } static void opengl_client_pbuffer_init( HPBUFFERARB client_pbuffer, struct pbuffer *pbuffer, const struct opengl_funcs *funcs ) diff --git a/include/wine/opengl_driver.h b/include/wine/opengl_driver.h index e545418258a..47c5195091f 100644 --- a/include/wine/opengl_driver.h +++ b/include/wine/opengl_driver.h @@ -59,6 +59,18 @@ struct wgl_pixel_format int float_components; }; +struct opengl_client_context +{ + struct HGLRC__ obj; /* client object header */ + UINT64 unix_handle; + UINT64 unix_funcs; +}; + +static inline struct opengl_client_context *opengl_client_context_from_client( HGLRC client_context ) +{ + return CONTAINING_RECORD( client_context, struct opengl_client_context, obj ); +} + struct opengl_client_pbuffer { struct HPBUFFERARB__ obj; /* client object header */ @@ -82,14 +94,21 @@ struct opengl_drawable; struct wgl_context { - void *driver_private; /* driver context / private data */ - void *internal_context; /* driver context for win32u internal use */ - int format; /* pixel format of the context */ - struct opengl_drawable *draw; /* currently bound draw surface */ - struct opengl_drawable *read; /* currently bound read surface */ - GLenum error; /* wrapped GL error */ + HGLRC client_context; /* client side context pointer */ + void *driver_private; /* driver context / private data */ + void *internal_context; /* driver context for win32u internal use */ + int format; /* pixel format of the context */ + struct opengl_drawable *draw; /* currently bound draw surface */ + struct opengl_drawable *read; /* currently bound read surface */ + GLenum error; /* wrapped GL error */ }; +static inline struct wgl_context *opengl_context_from_handle( HGLRC client_context ) +{ + struct opengl_client_context *client = opengl_client_context_from_client( client_context ); + return client_context ? (struct wgl_context *)(UINT_PTR)client->unix_handle : NULL; +} + /* interface between opengl32 and win32u */ struct opengl_funcs { diff --git a/include/wine/wgl.h b/include/wine/wgl.h index 90b7be366c4..2c456d1dd8a 100644 --- a/include/wine/wgl.h +++ b/include/wine/wgl.h @@ -24,7 +24,6 @@ #define EGL_CAST(t,x) ((t)(x)) #endif -struct wgl_context; typedef void *EGLNativeDisplayType; typedef void *EGLNativePixmapType; typedef void *EGLNativeWindowType; @@ -6284,23 +6283,23 @@ void GLAPIENTRY glViewport( GLint x, GLint y, GLsizei width, GLsizei heigh #endif typedef int (GLAPIENTRY *PFN_wglChoosePixelFormat)( HDC hDc, const PIXELFORMATDESCRIPTOR *pPfd ); -typedef BOOL (GLAPIENTRY *PFN_wglCopyContext)( struct wgl_context * hglrcSrc, struct wgl_context * hglrcDst, UINT mask ); -typedef struct wgl_context * (GLAPIENTRY *PFN_wglCreateContext)( HDC hDc ); -typedef struct wgl_context * (GLAPIENTRY *PFN_wglCreateLayerContext)( HDC hDc, int level ); -typedef BOOL (GLAPIENTRY *PFN_wglDeleteContext)( struct wgl_context * oldContext ); +typedef BOOL (GLAPIENTRY *PFN_wglCopyContext)( HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask ); +typedef HGLRC (GLAPIENTRY *PFN_wglCreateContext)( HDC hDc, HGLRC client_context ); +typedef HGLRC (GLAPIENTRY *PFN_wglCreateLayerContext)( HDC hDc, int level, HGLRC client_context ); +typedef BOOL (GLAPIENTRY *PFN_wglDeleteContext)( HGLRC oldContext ); typedef BOOL (GLAPIENTRY *PFN_wglDescribeLayerPlane)( HDC hDc, int pixelFormat, int layerPlane, UINT nBytes, LAYERPLANEDESCRIPTOR *plpd ); typedef int (GLAPIENTRY *PFN_wglDescribePixelFormat)( HDC hdc, int ipfd, UINT cjpfd, PIXELFORMATDESCRIPTOR *ppfd ); -typedef struct wgl_context * (GLAPIENTRY *PFN_wglGetCurrentContext)(void); +typedef HGLRC (GLAPIENTRY *PFN_wglGetCurrentContext)(void); typedef HDC (GLAPIENTRY *PFN_wglGetCurrentDC)(void); typedef PROC (GLAPIENTRY *PFN_wglGetDefaultProcAddress)( LPCSTR lpszProc ); typedef int (GLAPIENTRY *PFN_wglGetLayerPaletteEntries)( HDC hdc, int iLayerPlane, int iStart, int cEntries, COLORREF *pcr ); typedef int (GLAPIENTRY *PFN_wglGetPixelFormat)( HDC hdc ); typedef PROC (GLAPIENTRY *PFN_wglGetProcAddress)( LPCSTR lpszProc ); -typedef BOOL (GLAPIENTRY *PFN_wglMakeCurrent)( HDC hDc, struct wgl_context * newContext ); +typedef BOOL (GLAPIENTRY *PFN_wglMakeCurrent)( HDC hDc, HGLRC newContext ); typedef BOOL (GLAPIENTRY *PFN_wglRealizeLayerPalette)( HDC hdc, int iLayerPlane, BOOL bRealize ); typedef int (GLAPIENTRY *PFN_wglSetLayerPaletteEntries)( HDC hdc, int iLayerPlane, int iStart, int cEntries, const COLORREF *pcr ); typedef BOOL (GLAPIENTRY *PFN_wglSetPixelFormat)( HDC hdc, int ipfd, const PIXELFORMATDESCRIPTOR *ppfd ); -typedef BOOL (GLAPIENTRY *PFN_wglShareLists)( struct wgl_context * hrcSrvShare, struct wgl_context * hrcSrvSource ); +typedef BOOL (GLAPIENTRY *PFN_wglShareLists)( HGLRC hrcSrvShare, HGLRC hrcSrvSource ); typedef BOOL (GLAPIENTRY *PFN_wglSwapBuffers)( HDC hdc ); typedef BOOL (GLAPIENTRY *PFN_wglSwapLayerBuffers)( HDC hdc, UINT fuFlags ); typedef BOOL (GLAPIENTRY *PFN_wglUseFontBitmapsA)( HDC hDC, DWORD first, DWORD count, DWORD listBase ); @@ -9519,7 +9518,7 @@ typedef void (GLAPIENTRY *PFN_glWriteMaskEXT)( GLuint res, GLuint in, GLen typedef void * (GLAPIENTRY *PFN_wglAllocateMemoryNV)( GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority ); typedef BOOL (GLAPIENTRY *PFN_wglBindTexImageARB)( HPBUFFERARB hPbuffer, int iBuffer ); typedef BOOL (GLAPIENTRY *PFN_wglChoosePixelFormatARB)( HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats ); -typedef struct wgl_context * (GLAPIENTRY *PFN_wglCreateContextAttribsARB)( HDC hDC, struct wgl_context * hShareContext, const int *attribList ); +typedef HGLRC (GLAPIENTRY *PFN_wglCreateContextAttribsARB)( HDC hDC, HGLRC hShareContext, const int *attribList, HGLRC client_context ); typedef HPBUFFERARB (GLAPIENTRY *PFN_wglCreatePbufferARB)( HDC hDC, int iPixelFormat, int iWidth, int iHeight, const int *piAttribList, HPBUFFERARB client_pbuffer ); typedef BOOL (GLAPIENTRY *PFN_wglDestroyPbufferARB)( HPBUFFERARB hPbuffer ); typedef void (GLAPIENTRY *PFN_wglFreeMemoryNV)( void *pointer ); @@ -9530,7 +9529,7 @@ typedef HDC (GLAPIENTRY *PFN_wglGetPbufferDCARB)( HPBUFFERARB hPbuffer ); typedef BOOL (GLAPIENTRY *PFN_wglGetPixelFormatAttribfvARB)( HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, FLOAT *pfValues ); typedef BOOL (GLAPIENTRY *PFN_wglGetPixelFormatAttribivARB)( HDC hdc, int iPixelFormat, int iLayerPlane, UINT nAttributes, const int *piAttributes, int *piValues ); typedef int (GLAPIENTRY *PFN_wglGetSwapIntervalEXT)(void); -typedef BOOL (GLAPIENTRY *PFN_wglMakeContextCurrentARB)( HDC hDrawDC, HDC hReadDC, struct wgl_context * hglrc ); +typedef BOOL (GLAPIENTRY *PFN_wglMakeContextCurrentARB)( HDC hDrawDC, HDC hReadDC, HGLRC hglrc ); typedef BOOL (GLAPIENTRY *PFN_wglQueryCurrentRendererIntegerWINE)( GLenum attribute, GLuint *value ); typedef const GLchar * (GLAPIENTRY *PFN_wglQueryCurrentRendererStringWINE)( GLenum attribute ); typedef BOOL (GLAPIENTRY *PFN_wglQueryPbufferARB)( HPBUFFERARB hPbuffer, int iAttribute, int *piValue ); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9953