From: Rémi Bernon <rbernon@codeweavers.com> --- dlls/opengl32/make_opengl | 9 ++++++ dlls/opengl32/private.h | 2 ++ dlls/opengl32/tests/opengl.c | 6 ++-- dlls/opengl32/thunks.c | 35 +++++++++++++++------- dlls/opengl32/wgl.c | 56 +++++++++++++++++++++++++++++------- 5 files changed, 84 insertions(+), 24 deletions(-) diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index d47cf01c6a2..af0fcce4f96 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -692,6 +692,7 @@ sub get_object_type($$$$) return "OBJ_TYPE_BUFFER" if $class eq "buffer"; return "OBJ_TYPE_BUFFER" if $func eq "glDeleteObjectBufferATI" and $pname eq "buffer"; return "OBJ_TYPE_BUFFER" if $func eq "glDrawCommandsNV" and $pname eq "buffer"; + return "OBJ_TYPE_DISPLAY_LIST" if $class eq "display list"; return "OBJ_TYPE_FRAMEBUFFER" if $class eq "framebuffer"; return "OBJ_TYPE_FRAMEBUFFER" if $pname =~ "fbo"; return "OBJ_TYPE_RENDERBUFFER" if $class eq "renderbuffer"; @@ -714,6 +715,7 @@ sub get_object_type($$$$) return 0 if $class eq "vertex array"; return 0 if $class =~ /^Vector/; return 0 if $func eq "glGetActiveAtomicCounterBufferiv" and $pname eq "bufferIndex"; + return 0 if $func eq "glSelectPerfMonitorCountersAMD" and $pname eq "counterList"; return 0 if $func =~ /^glBlend(Equation|Func)/ and $pname eq "buf"; return 0 if $func =~ /^gl(Signal|Wait)Semaphore/ and $pname eq "numBufferBarriers"; return 0 if $func =~ /^gl(Signal|Wait)Semaphore/ and $pname eq "numTextureBarriers"; @@ -733,9 +735,11 @@ sub get_object_type($$$$) return 0 if $pname eq "pathParameterTemplate"; print "Missing possible buffer: $func $ptype $pname $class\n" if lc( $pname ) =~ /buffer/; + print "Missing possible display list: $func $ptype $pname $class\n" if lc( $pname ) =~ /list/; print "Missing possible framebuffer: $func $ptype $pname $class\n" if lc( $pname ) =~ /fbo/; print "Missing possible sampler: $func $ptype $pname $class\n" if lc( $pname ) =~ /sampler/; print "Missing possible texture: $func $ptype $pname $class\n" if lc( $pname ) =~ /texture/; + print "Missing possible list: $func $ptype $pname $class\n" if lc( $pname ) =~ /list/; return 0; } @@ -750,6 +754,7 @@ sub allocate_object_names($) return $ret if $name =~ /^glBindRenderbuffer/; return $ret if $name =~ /^glBindSampler/; return $ret if $name =~ /^glBindTexture/; + return $ret if $name =~ /^glNewList/; return 0; } @@ -837,6 +842,10 @@ sub generate_win_thunk($$) $params .= ", .$pname = $pname"; } } + if (my $map_type = get_object_type( $name, $func_ret, "ret", get_arg_class( $func->[0] ) )) + { + $post_call .= " args.ret = put_context_object_range( $map_type, range, args.ret );\n" if $name =~ /^glGen/; + } $ret .= " struct $name\_params args = {$params };\n"; $ret .= " NTSTATUS status;\n"; $ret .= " int integer;\n" if $get_integer; diff --git a/dlls/opengl32/private.h b/dlls/opengl32/private.h index 6b6e8aa2714..1b0a05dc041 100644 --- a/dlls/opengl32/private.h +++ b/dlls/opengl32/private.h @@ -49,6 +49,7 @@ extern BOOL get_integer( GLenum pname, GLuint index, GLint value, GLint *data ); enum object_type { OBJ_TYPE_BUFFER, + OBJ_TYPE_DISPLAY_LIST, OBJ_TYPE_FRAMEBUFFER, OBJ_TYPE_RENDERBUFFER, OBJ_TYPE_SAMPLER, @@ -65,6 +66,7 @@ static inline GLuint *memdup_objects( UINT n, const GLuint *handles, GLuint *buf } extern void put_context_objects( enum object_type type, UINT n, GLuint *handles ); +extern GLuint put_context_object_range( enum object_type type, UINT n, GLuint base ); extern BOOL alloc_context_objects( enum object_type type, UINT n, const GLuint *handles, BOOL extension ); extern GLuint *del_context_objects( enum object_type type, UINT n, GLuint *handles ); extern GLuint *map_context_objects( enum object_type type, UINT n, GLuint *handles ); diff --git a/dlls/opengl32/tests/opengl.c b/dlls/opengl32/tests/opengl.c index c95e75255b9..d7dfe05cb39 100644 --- a/dlls/opengl32/tests/opengl.c +++ b/dlls/opengl32/tests/opengl.c @@ -2019,7 +2019,7 @@ static void test_sharelists(HDC winhdc) ok_ret( GL_NO_ERROR, glGetError() ); /* cannot overwrite non-empty lists with some other */ - todo_wine_if( i >= 9 ) ok_ret( FALSE, wglShareLists( ctx1, ctx3 ) ); + todo_wine_if( i >= 10 ) ok_ret( FALSE, wglShareLists( ctx1, ctx3 ) ); ok_ret( GL_NO_ERROR, glGetError() ); ok_ret( FALSE, wglShareLists( ctx2, ctx1 ) ); ok_ret( GL_NO_ERROR, glGetError() ); @@ -2067,7 +2067,7 @@ static void test_sharelists(HDC winhdc) ok_ret( GL_NO_ERROR, glGetError() ); ok_ret( TRUE, wglMakeCurrent( winhdc, ctx2 ) ); ok_ret( GL_NO_ERROR, glGetError() ); - todo_wine_if( i >= 9 ) ok_ret( FALSE, test->exists( obj1 ) ); + todo_wine_if( i >= 10 ) ok_ret( FALSE, test->exists( obj1 ) ); ok_ret( GL_NO_ERROR, glGetError() ); ok_ret( FALSE, test->exists( obj2 ) ); ok_ret( GL_NO_ERROR, glGetError() ); @@ -2078,7 +2078,7 @@ static void test_sharelists(HDC winhdc) ok_ret( TRUE, wglDeleteContext( ctx3 ) ); /* objects are still valid after shared context destruction */ - todo_wine_if( i >= 9 ) ok_ret( FALSE, test->exists( obj1 ) ); + todo_wine_if( i >= 10 ) ok_ret( FALSE, test->exists( obj1 ) ); ok_ret( GL_NO_ERROR, glGetError() ); ok_ret( FALSE, test->exists( obj2 ) ); ok_ret( GL_NO_ERROR, glGetError() ); diff --git a/dlls/opengl32/thunks.c b/dlls/opengl32/thunks.c index da932c36526..2ea1feb0742 100644 --- a/dlls/opengl32/thunks.c +++ b/dlls/opengl32/thunks.c @@ -109,9 +109,10 @@ void WINAPI glBlendFunc( GLenum sfactor, GLenum dfactor ) void WINAPI glCallList( GLuint list ) { - struct glCallList_params args = { .teb = NtCurrentTeb(), .list = list }; + struct glCallList_params args = { .teb = NtCurrentTeb() }; NTSTATUS status; TRACE( "list %d\n", list ); + args.list = *map_context_objects( OBJ_TYPE_DISPLAY_LIST, 1, &list ); if ((status = UNIX_CALL( glCallList, &args ))) WARN( "glCallList returned %#lx\n", status ); } @@ -509,9 +510,10 @@ void WINAPI glCullFace( GLenum mode ) void WINAPI glDeleteLists( GLuint list, GLsizei range ) { - struct glDeleteLists_params args = { .teb = NtCurrentTeb(), .list = list, .range = range }; + struct glDeleteLists_params args = { .teb = NtCurrentTeb(), .range = range }; NTSTATUS status; TRACE( "list %d, range %d\n", list, range ); + args.list = *del_context_objects( OBJ_TYPE_DISPLAY_LIST, 1, &list ); if ((status = UNIX_CALL( glDeleteLists, &args ))) WARN( "glDeleteLists returned %#lx\n", status ); } @@ -829,6 +831,7 @@ GLuint WINAPI glGenLists( GLsizei range ) NTSTATUS status; TRACE( "range %d\n", range ); if ((status = UNIX_CALL( glGenLists, &args ))) WARN( "glGenLists returned %#lx\n", status ); + args.ret = put_context_object_range( OBJ_TYPE_DISPLAY_LIST, range, args.ret ); return args.ret; } @@ -1211,9 +1214,10 @@ GLboolean WINAPI glIsEnabled( GLenum cap ) GLboolean WINAPI glIsList( GLuint list ) { - struct glIsList_params args = { .teb = NtCurrentTeb(), .list = list }; + struct glIsList_params args = { .teb = NtCurrentTeb() }; NTSTATUS status; TRACE( "list %d\n", list ); + args.list = *map_context_objects( OBJ_TYPE_DISPLAY_LIST, 1, &list ); if ((status = UNIX_CALL( glIsList, &args ))) WARN( "glIsList returned %#lx\n", status ); return args.ret; } @@ -1310,9 +1314,10 @@ void WINAPI glLineWidth( GLfloat width ) void WINAPI glListBase( GLuint base ) { - struct glListBase_params args = { .teb = NtCurrentTeb(), .base = base }; + struct glListBase_params args = { .teb = NtCurrentTeb() }; NTSTATUS status; TRACE( "base %d\n", base ); + args.base = *map_context_objects( OBJ_TYPE_DISPLAY_LIST, 1, &base ); if ((status = UNIX_CALL( glListBase, &args ))) WARN( "glListBase returned %#lx\n", status ); } @@ -1478,9 +1483,11 @@ void WINAPI glMultMatrixf( const GLfloat *m ) void WINAPI glNewList( GLuint list, GLenum mode ) { - struct glNewList_params args = { .teb = NtCurrentTeb(), .list = list, .mode = mode }; + struct glNewList_params args = { .teb = NtCurrentTeb(), .mode = mode }; NTSTATUS status; TRACE( "list %d, mode %d\n", list, mode ); + if (!alloc_context_objects( OBJ_TYPE_DISPLAY_LIST, 1, &list, FALSE )) return; + args.list = *map_context_objects( OBJ_TYPE_DISPLAY_LIST, 1, &list ); if ((status = UNIX_CALL( glNewList, &args ))) WARN( "glNewList returned %#lx\n", status ); } @@ -9004,17 +9011,19 @@ static void WINAPI glGetLightxv( GLenum light, GLenum pname, GLfixed *params ) static void WINAPI glGetListParameterfvSGIX( GLuint list, GLenum pname, GLfloat *params ) { - struct glGetListParameterfvSGIX_params args = { .teb = NtCurrentTeb(), .list = list, .pname = pname, .params = params }; + struct glGetListParameterfvSGIX_params args = { .teb = NtCurrentTeb(), .pname = pname, .params = params }; NTSTATUS status; TRACE( "list %d, pname %d, params %p\n", list, pname, params ); + args.list = *map_context_objects( OBJ_TYPE_DISPLAY_LIST, 1, &list ); if ((status = UNIX_CALL( glGetListParameterfvSGIX, &args ))) WARN( "glGetListParameterfvSGIX returned %#lx\n", status ); } static void WINAPI glGetListParameterivSGIX( GLuint list, GLenum pname, GLint *params ) { - struct glGetListParameterivSGIX_params args = { .teb = NtCurrentTeb(), .list = list, .pname = pname, .params = params }; + struct glGetListParameterivSGIX_params args = { .teb = NtCurrentTeb(), .pname = pname, .params = params }; NTSTATUS status; TRACE( "list %d, pname %d, params %p\n", list, pname, params ); + args.list = *map_context_objects( OBJ_TYPE_DISPLAY_LIST, 1, &list ); if ((status = UNIX_CALL( glGetListParameterivSGIX, &args ))) WARN( "glGetListParameterivSGIX returned %#lx\n", status ); } @@ -12521,33 +12530,37 @@ static void WINAPI glListDrawCommandsStatesClientNV( GLuint list, GLuint segment static void WINAPI glListParameterfSGIX( GLuint list, GLenum pname, GLfloat param ) { - struct glListParameterfSGIX_params args = { .teb = NtCurrentTeb(), .list = list, .pname = pname, .param = param }; + struct glListParameterfSGIX_params args = { .teb = NtCurrentTeb(), .pname = pname, .param = param }; NTSTATUS status; TRACE( "list %d, pname %d, param %f\n", list, pname, param ); + args.list = *map_context_objects( OBJ_TYPE_DISPLAY_LIST, 1, &list ); if ((status = UNIX_CALL( glListParameterfSGIX, &args ))) WARN( "glListParameterfSGIX returned %#lx\n", status ); } static void WINAPI glListParameterfvSGIX( GLuint list, GLenum pname, const GLfloat *params ) { - struct glListParameterfvSGIX_params args = { .teb = NtCurrentTeb(), .list = list, .pname = pname, .params = params }; + struct glListParameterfvSGIX_params args = { .teb = NtCurrentTeb(), .pname = pname, .params = params }; NTSTATUS status; TRACE( "list %d, pname %d, params %p\n", list, pname, params ); + args.list = *map_context_objects( OBJ_TYPE_DISPLAY_LIST, 1, &list ); if ((status = UNIX_CALL( glListParameterfvSGIX, &args ))) WARN( "glListParameterfvSGIX returned %#lx\n", status ); } static void WINAPI glListParameteriSGIX( GLuint list, GLenum pname, GLint param ) { - struct glListParameteriSGIX_params args = { .teb = NtCurrentTeb(), .list = list, .pname = pname, .param = param }; + struct glListParameteriSGIX_params args = { .teb = NtCurrentTeb(), .pname = pname, .param = param }; NTSTATUS status; TRACE( "list %d, pname %d, param %d\n", list, pname, param ); + args.list = *map_context_objects( OBJ_TYPE_DISPLAY_LIST, 1, &list ); if ((status = UNIX_CALL( glListParameteriSGIX, &args ))) WARN( "glListParameteriSGIX returned %#lx\n", status ); } static void WINAPI glListParameterivSGIX( GLuint list, GLenum pname, const GLint *params ) { - struct glListParameterivSGIX_params args = { .teb = NtCurrentTeb(), .list = list, .pname = pname, .params = params }; + struct glListParameterivSGIX_params args = { .teb = NtCurrentTeb(), .pname = pname, .params = params }; NTSTATUS status; TRACE( "list %d, pname %d, params %p\n", list, pname, params ); + args.list = *map_context_objects( OBJ_TYPE_DISPLAY_LIST, 1, &list ); if ((status = UNIX_CALL( glListParameterivSGIX, &args ))) WARN( "glListParameterivSGIX returned %#lx\n", status ); } diff --git a/dlls/opengl32/wgl.c b/dlls/opengl32/wgl.c index 89bc1d6130f..8801c72753a 100644 --- a/dlls/opengl32/wgl.c +++ b/dlls/opengl32/wgl.c @@ -106,6 +106,7 @@ static const char *debugstr_object_type( enum object_type type ) switch (type) { case OBJ_TYPE_BUFFER: return "buffer"; + case OBJ_TYPE_DISPLAY_LIST: return "display list"; case OBJ_TYPE_FRAMEBUFFER: return "framebuffer"; case OBJ_TYPE_RENDERBUFFER: return "renderbuffer"; case OBJ_TYPE_SAMPLER: return "sampler"; @@ -319,17 +320,17 @@ static void free_object_ids( struct object_table *table, GLuint **ids[L1_COUNT] } } -static GLuint alloc_client_id( struct object_table *table, GLuint host_id ) +static GLuint alloc_client_id( struct object_table *table, GLuint host_id, UINT range ) { /* if we don't need implicit allocations, use the host allocated ids directly */ if (!table->implicit) return host_id; /* otherwise we need to allocate client id ourselves, lookup for a free id */ - for (GLuint id = table->min_free + 1, *ids; id != 0; id++) + for (GLuint id = table->min_free + 1, n = range, *ids; id != 0; id++) { if (!(ids = alloc_object_ids( table->host_ids, id ))) return 0; - if (ids[id % L3_COUNT]) continue; - return table->min_free = id; + if (ids[id % L3_COUNT]) n = range; + else if (!n--) return table->min_free = id - range; } return 0; @@ -390,6 +391,7 @@ static GLuint create_object( enum object_type type ) switch (type) { case OBJ_TYPE_BUFFER: { MAKE_OBJECT_CALL( glGenBuffers, .n = 1, .buffers = &object ); return object; } + case OBJ_TYPE_DISPLAY_LIST: { MAKE_OBJECT_CALL( glGenLists, .range = 1 ); return args.ret; } case OBJ_TYPE_FRAMEBUFFER: { MAKE_OBJECT_CALL( glGenFramebuffers, .n = 1, .framebuffers = &object ); return object; } case OBJ_TYPE_RENDERBUFFER: { MAKE_OBJECT_CALL( glGenRenderbuffers, .n = 1, .renderbuffers = &object ); return object; } case OBJ_TYPE_SAMPLER: { MAKE_OBJECT_CALL( glGenSamplers, .count = 1, .samplers = &object ); return object; } @@ -455,6 +457,8 @@ struct context struct opengl_client_context base; struct handle_table syncs; struct display_lists *lists; + + GLuint list_base; }; static struct context *context_from_opengl_client_context( struct opengl_client_context *base ) @@ -544,10 +548,27 @@ void put_context_objects( enum object_type type, UINT n, GLuint *handles ) if (!(table = get_object_table( ctx, type, TRUE ))) return; AcquireSRWLockExclusive( &table->lock ); - for (UINT i = 0; i < n; i++) handles[i] = handles[i] ? set_object( table, alloc_client_id( table, handles[i] ), handles[i] ) : 0; + for (UINT i = 0; i < n; i++) handles[i] = handles[i] ? set_object( table, alloc_client_id( table, handles[i], 0 ), handles[i] ) : 0; ReleaseSRWLockExclusive( &table->lock ); } +GLuint put_context_object_range( enum object_type type, UINT range, GLuint base ) +{ + struct object_table *table; + struct context *ctx; + GLuint first; + + if (!(ctx = context_from_handle( NtCurrentTeb()->glCurrentRC ))) return base; + if (!(table = get_object_table( ctx, type, TRUE ))) return base; + + AcquireSRWLockExclusive( &table->lock ); + first = alloc_client_id( table, base, range ); + for (UINT i = 0; i < range; i++) set_object( table, first + i, base + i ); + ReleaseSRWLockExclusive( &table->lock ); + + return first; +} + static void alloc_client_objects( struct context *ctx, enum object_type type, UINT n, const GLuint *handles ) { struct object_table *table; @@ -567,7 +588,7 @@ static void alloc_client_objects( struct context *ctx, enum object_type type, UI BOOL alloc_context_objects( enum object_type type, UINT n, const GLuint *handles, BOOL extension ) { - BOOL alloc_client = TRUE, needs_client = FALSE; + BOOL alloc_client, needs_client = FALSE; struct object_table *table; struct context *ctx; @@ -575,10 +596,23 @@ BOOL alloc_context_objects( enum object_type type, UINT n, const GLuint *handles if (!(table = get_object_table( ctx, type, FALSE ))) return TRUE; /* only allow explicit allocation in some cases, use host allocated ids directly in that case */ - if (ctx->base.profile_mask & WGL_CONTEXT_CORE_PROFILE_BIT_ARB) alloc_client = FALSE; - if (type == OBJ_TYPE_FRAMEBUFFER) alloc_client = extension; - if (type == OBJ_TYPE_RENDERBUFFER) alloc_client = extension; - if (type == OBJ_TYPE_SAMPLER) alloc_client = FALSE; + switch (type) + { + case OBJ_TYPE_DISPLAY_LIST: + if (ctx->base.profile_mask & WGL_CONTEXT_CORE_PROFILE_BIT_ARB) return FALSE; + alloc_client = TRUE; + break; + case OBJ_TYPE_FRAMEBUFFER: + case OBJ_TYPE_RENDERBUFFER: + alloc_client = extension; + break; + case OBJ_TYPE_SAMPLER: + alloc_client = FALSE; + break; + default: + alloc_client = !(ctx->base.profile_mask & WGL_CONTEXT_CORE_PROFILE_BIT_ARB); + break; + } AcquireSRWLockShared( &table->lock ); for (UINT i = 0; i < n && !needs_client; i++) @@ -687,6 +721,8 @@ static GLuint get_pname_object_type( GLenum pname ) return OBJ_TYPE_TEXTURE; case GL_SAMPLER_BINDING: return OBJ_TYPE_SAMPLER; + case GL_LIST_INDEX: + return OBJ_TYPE_DISPLAY_LIST; } return OBJ_TYPE_COUNT; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11134