[PATCH v2 0/1] MR10241: opengl32: Recognize more glHint attributes.
And store only present attributes in context_attributes[]. -- v2: opengl32: Recognize more glHint attributes. https://gitlab.winehq.org/wine/wine/-/merge_requests/10241
From: Paul Gofman <pgofman@codeweavers.com> And store only present attributes in context_attributes[]. --- dlls/opengl32/tests/opengl.c | 19 +++++++++++ dlls/opengl32/unix_wgl.c | 66 ++++++++++++++++++++++++++++++------ 2 files changed, 74 insertions(+), 11 deletions(-) diff --git a/dlls/opengl32/tests/opengl.c b/dlls/opengl32/tests/opengl.c index e0fc1ae1426..ca77784b991 100644 --- a/dlls/opengl32/tests/opengl.c +++ b/dlls/opengl32/tests/opengl.c @@ -1166,7 +1166,13 @@ static void test_setpixelformat(HDC winhdc) static void test_sharelists(HDC winhdc) { BOOL res, nvidia, amd, source_current, source_sharing, dest_current, dest_sharing; + const char *extensions = (const char*)glGetString(GL_EXTENSIONS); HGLRC source, dest, other; + BOOL ms_hint_supported; + + ms_hint_supported = gl_extension_supported(extensions, "GL_NV_multisample_filter_hint"); + if (!ms_hint_supported) + skip("GL_NV_multisample_filter_hint is not supported.\n"); res = wglShareLists(NULL, NULL); ok(!res, "Sharing display lists for no contexts passed!\n"); @@ -1211,8 +1217,15 @@ static void test_sharelists(HDC winhdc) glDisable(GL_DITHER); glDepthFunc(GL_LESS); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + glHint(GL_FOG_HINT, GL_NICEST); + if (ms_hint_supported) + glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); glShadeModel(GL_SMOOTH); glClearColor(0.1, 0.2, 0.3, 1.0); + } if (source_sharing) { @@ -1237,6 +1250,12 @@ static void test_sharelists(HDC winhdc) glEnable(GL_DITHER); glDepthFunc(GL_GREATER); glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + glHint(GL_FOG_HINT, GL_NICEST); + if (ms_hint_supported) + glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST); glShadeModel(GL_FLAT); glClearColor(0.3, 0.2, 0.1, 1.0); } diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 1d0c995e7fe..afea88e20a2 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -109,6 +109,11 @@ struct color_buffer_state struct hint_state { GLenum perspective_correction; + GLenum point_smooth; + GLenum line_smooth; + GLenum polygon_smooth; + GLenum fog; + GLenum multisample_nv; }; struct buffers @@ -222,6 +227,7 @@ static struct context *get_current_context( TEB *teb, struct opengl_drawable **d struct context_attribute_desc { + GLenum name; GLbitfield bit; unsigned short offset; unsigned short size; @@ -229,7 +235,7 @@ struct context_attribute_desc static struct context_attribute_desc context_attributes[] = { -#define CONTEXT_ATTRIBUTE_DESC(bit, name, field) [name] = { bit, offsetof(struct context, field), sizeof(((struct context *)0)->field) } +#define CONTEXT_ATTRIBUTE_DESC(bit, name, field) { name, bit, offsetof(struct context, field), sizeof(((struct context *)0)->field) } CONTEXT_ATTRIBUTE_DESC( GL_COLOR_BUFFER_BIT, GL_COLOR_CLEAR_VALUE, color_buffer.clear_color ), CONTEXT_ATTRIBUTE_DESC( GL_DEPTH_BUFFER_BIT, GL_DEPTH_FUNC, depth_buffer.depth_func ), CONTEXT_ATTRIBUTE_DESC( GL_ENABLE_BIT, GL_CULL_FACE, enable.cull_face ), @@ -239,6 +245,11 @@ static struct context_attribute_desc context_attributes[] = CONTEXT_ATTRIBUTE_DESC( GL_ENABLE_BIT, GL_LIGHTING, enable.lighting ), CONTEXT_ATTRIBUTE_DESC( GL_ENABLE_BIT, GL_NORMALIZE, enable.normalize ), CONTEXT_ATTRIBUTE_DESC( GL_HINT_BIT, GL_PERSPECTIVE_CORRECTION_HINT, hint.perspective_correction ), + CONTEXT_ATTRIBUTE_DESC( GL_HINT_BIT, GL_POINT_SMOOTH_HINT, hint.point_smooth ), + CONTEXT_ATTRIBUTE_DESC( GL_HINT_BIT, GL_LINE_SMOOTH_HINT, hint.line_smooth ), + CONTEXT_ATTRIBUTE_DESC( GL_HINT_BIT, GL_POLYGON_SMOOTH_HINT, hint.polygon_smooth ), + CONTEXT_ATTRIBUTE_DESC( GL_HINT_BIT, GL_FOG_HINT, hint.fog ), + CONTEXT_ATTRIBUTE_DESC( GL_HINT_BIT, GL_MULTISAMPLE_FILTER_HINT_NV, hint.multisample_nv ), CONTEXT_ATTRIBUTE_DESC( GL_LIGHTING_BIT, GL_LIGHT_MODEL_AMBIENT, lighting.model.ambient ), CONTEXT_ATTRIBUTE_DESC( GL_LIGHTING_BIT, GL_LIGHT_MODEL_TWO_SIDE, lighting.model.two_side ), CONTEXT_ATTRIBUTE_DESC( GL_LIGHTING_BIT, GL_SHADE_MODEL, lighting.shade_model ), @@ -246,22 +257,49 @@ static struct context_attribute_desc context_attributes[] = #undef CONTEXT_ATTRIBUTE_DESC }; -/* GL constants used as indexes should be small, make sure size is reasonable */ -C_ASSERT( sizeof(context_attributes) <= 64 * 1024 ); +static int compare_context_attributes( const void *v1, const void *v2 ) +{ + const struct context_attribute_desc *a1 = v1, *a2 = v2; + + assert( a1->name != a2->name ); + return (int)a1->name - (int)a2->name; +}; + +static const struct context_attribute_desc *find_context_attribute( GLenum name ) +{ + unsigned int l = 0, r = ARRAY_SIZE(context_attributes), m; + + while (l < r) + { + m = (l + r) /2; + if (context_attributes[m].name == name) return &context_attributes[m]; + if (name < context_attributes[m].name) r = m; + else l = m + 1; + } + return NULL; +} void set_context_attribute( TEB *teb, GLenum name, const void *value, size_t size ) { + const struct context_attribute_desc *desc; struct context *ctx; - GLbitfield bit; if (!(ctx = get_current_context( teb, NULL, NULL ))) return; - if (name >= ARRAY_SIZE(context_attributes) || !(bit = context_attributes[name].bit)) bit = -1 /* unsupported */; - 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\n", ctx ); - ctx->used |= bit; + if ((desc = find_context_attribute( name ))) + { + if (size && size != desc->size) ERR( "Invalid state attrib %#x parameter size %#zx\n", name, size ); + else + { + memcpy( (char *)ctx + desc->offset, value, desc->size ); + ctx->used |= desc->bit; + } + } + else + { + if (ctx->used != -1) WARN( "Unsupported attribute on context %p/%p\n", teb->glCurrentRC, ctx ); + ctx->used |= -1; + } } static BOOL copy_context_attributes( TEB *teb, HGLRC client_dst, struct context *dst, @@ -326,7 +364,12 @@ static BOOL copy_context_attributes( TEB *teb, HGLRC client_dst, struct context } if (mask & GL_HINT_BIT) { - funcs->p_glHint( GL_PERSPECTIVE_CORRECTION_HINT, src->hint.perspective_correction ); + if (src->hint.perspective_correction) funcs->p_glHint( GL_PERSPECTIVE_CORRECTION_HINT, src->hint.perspective_correction ); + if (src->hint.point_smooth) funcs->p_glHint( GL_POINT_SMOOTH_HINT, src->hint.perspective_correction ); + if (src->hint.line_smooth) funcs->p_glHint( GL_LINE_SMOOTH_HINT, src->hint.perspective_correction ); + if (src->hint.polygon_smooth) funcs->p_glHint( GL_POLYGON_SMOOTH_HINT, src->hint.perspective_correction ); + if (src->hint.fog) funcs->p_glHint( GL_FOG_HINT, src->hint.perspective_correction ); + if (src->hint.multisample_nv) funcs->p_glHint( GL_MULTISAMPLE_FILTER_HINT_NV, src->hint.multisample_nv ); dst->hint = src->hint; } if (mask & GL_LIGHTING_BIT) @@ -2022,6 +2065,7 @@ NTSTATUS process_attach( void *args ) zero_bits = (ULONG_PTR)info.HighestUserAddress | 0x7fffffff; } + qsort( context_attributes, ARRAY_SIZE(context_attributes), sizeof(*context_attributes), compare_context_attributes ); return STATUS_SUCCESS; } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10241
On Wed Mar 4 08:53:12 2026 +0000, Rémi Bernon wrote:
Why not use bsearch as we already have everything we need from qsort? Well, to reuse the same search function (after deleting the assert) we'll need to define and fill name in context_attribute_desc for the key. And while saving about ~5 lines we will loose the comparison inlining in favour of calls to comparison function from bsearch(). If you feel like that is still better, I can change that.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10241#note_131268
v2: - add new attributes to the test. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10241#note_131270
On Wed Mar 4 15:06:04 2026 +0000, Paul Gofman wrote:
Well, to reuse the same search function (after deleting the assert) we'll need to define and fill name in context_attribute_desc for the key. And while saving about ~5 lines we will loose the comparison inlining in favour of calls to comparison function from bsearch(). If you feel like that is still better, I can change that. Ok, looking at std headers, I am probably wrong about that, there is inline version in headers these days. I will update with bsearch.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10241#note_131276
Rémi Bernon (@rbernon) commented about dlls/opengl32/tests/opengl.c:
ok(floats[0] == 0.1f, "got %f\n", floats[0]); ok(floats[1] == 0.2f, "got %f\n", floats[1]); ok(floats[2] == 0.3f, "got %f\n", floats[2]); ok(floats[3] == 1.0f, "got %f\n", floats[3]);
Would be nice to check that the hints are preserved here and below for dest context. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10241#note_131277
participants (3)
-
Paul Gofman -
Paul Gofman (@gofman) -
Rémi Bernon (@rbernon)