From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=58001 --- dlls/opengl32/make_opengl | 21 ++++++++- dlls/opengl32/unix_thunks.c | 21 +++++---- dlls/opengl32/unix_wgl.c | 88 ++++++++++++++++++++++++++++++++++++- 3 files changed, 119 insertions(+), 11 deletions(-)
diff --git a/dlls/opengl32/make_opengl b/dlls/opengl32/make_opengl index 442f29611b4..0001ffe28f3 100755 --- a/dlls/opengl32/make_opengl +++ b/dlls/opengl32/make_opengl @@ -272,6 +272,18 @@ my %pointer_is_offset = "glGetVertexAttribPointerv" => "pointer", "glGetVertexAttribPointervARB" => "pointer", ); +my %state_attrib_funcs = + ( + "glViewport" => "GL_VIEWPORT, ¶ms->x, 2 * sizeof(GLint) + 2 * sizeof(GLsizei)", + "glEnable" => "params->cap, &const_true, sizeof(const_true)", + "glDisable" => "params->cap, &const_false, sizeof(const_false)", + "glHint" => "params->target, ¶ms->mode, sizeof(params->mode)", + "glDepthFunc" => "GL_DEPTH_FUNC, ¶ms->func, sizeof(params->func)", + "glShadeModel" => "GL_SHADE_MODEL, ¶ms->mode, sizeof(params->mode)", + "glClearColor" => "GL_COLOR_CLEAR_VALUE, ¶ms->red, 4 * sizeof(GLfloat)", + "glLightModelfv" => "params->pname, params->params, 0 /* variable size */", + "glLightModeli" => "params->pname, ¶ms->param, sizeof(params->param)", + );
# # Used to convert some types @@ -399,7 +411,11 @@ sub generate_unix_thunk($$$) $ret .= "funcs->p_$name($call_args);\n"; } $ret .= " pthread_mutex_unlock( &wgl_lock );\n" if $need_lock; - if ($name !~ /^wgl|^glGet|^glIs[A-Z]|^glAre[A-Z]/) + if (defined $state_attrib_funcs{$name}) + { + $ret .= " set_context_attribute( params->teb, $state_attrib_funcs{$name} );\n"; + } + elsif ($name !~ /^wgl|^glGet|^glIs[A-Z]|^glAre[A-Z]/) { $ret .= " set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 );\n"; } @@ -1271,6 +1287,9 @@ print OUT "#include "wine/debug.h"\n\n";
print OUT "WINE_DEFAULT_DEBUG_CHANNEL(opengl);\n\n";
+print OUT "static GLboolean const_false;\n"; +print OUT "static GLboolean const_true = 1;\n\n"; + foreach (sort keys %wgl_functions) { next if defined $manual_win_functions{$_}; diff --git a/dlls/opengl32/unix_thunks.c b/dlls/opengl32/unix_thunks.c index ea778e8865a..9a306e0609b 100644 --- a/dlls/opengl32/unix_thunks.c +++ b/dlls/opengl32/unix_thunks.c @@ -20,6 +20,9 @@
WINE_DEFAULT_DEBUG_CHANNEL(opengl);
+static GLboolean const_false; +static GLboolean const_true = 1; + static NTSTATUS wgl_wglCopyContext( void *args ) { struct wglCopyContext_params *params = args; @@ -213,7 +216,7 @@ static NTSTATUS gl_glClearColor( void *args ) struct glClearColor_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; funcs->p_glClearColor( params->red, params->green, params->blue, params->alpha ); - set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); + set_context_attribute( params->teb, GL_COLOR_CLEAR_VALUE, ¶ms->red, 4 * sizeof(float) ); return STATUS_SUCCESS; }
@@ -645,7 +648,7 @@ static NTSTATUS gl_glDepthFunc( void *args ) struct glDepthFunc_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; funcs->p_glDepthFunc( params->func ); - set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); + set_context_attribute( params->teb, GL_DEPTH_FUNC, ¶ms->func, sizeof(params->func) ); return STATUS_SUCCESS; }
@@ -672,7 +675,7 @@ static NTSTATUS gl_glDisable( void *args ) struct glDisable_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; funcs->p_glDisable( params->cap ); - set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); + set_context_attribute( params->teb, params->cap, &const_false, sizeof(const_false) ); return STATUS_SUCCESS; }
@@ -753,7 +756,7 @@ static NTSTATUS gl_glEnable( void *args ) struct glEnable_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; funcs->p_glEnable( params->cap ); - set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); + set_context_attribute( params->teb, params->cap, &const_true, sizeof(const_true) ); return STATUS_SUCCESS; }
@@ -1226,7 +1229,7 @@ static NTSTATUS gl_glHint( void *args ) struct glHint_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; funcs->p_glHint( params->target, params->mode ); - set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); + set_context_attribute( params->teb, params->target, ¶ms->mode, sizeof(params->mode) ); return STATUS_SUCCESS; }
@@ -1394,7 +1397,7 @@ static NTSTATUS gl_glLightModelfv( void *args ) struct glLightModelfv_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; funcs->p_glLightModelfv( params->pname, params->params ); - set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); + set_context_attribute( params->teb, params->pname, params->params, 0 /* variable size */ ); return STATUS_SUCCESS; }
@@ -1403,7 +1406,7 @@ static NTSTATUS gl_glLightModeli( void *args ) struct glLightModeli_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; funcs->p_glLightModeli( params->pname, params->param ); - set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); + set_context_attribute( params->teb, params->pname, ¶ms->param, sizeof(params->param) ); return STATUS_SUCCESS; }
@@ -2348,7 +2351,7 @@ static NTSTATUS gl_glShadeModel( void *args ) struct glShadeModel_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; funcs->p_glShadeModel( params->mode ); - set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); + set_context_attribute( params->teb, GL_SHADE_MODEL, ¶ms->mode, sizeof(params->mode) ); return STATUS_SUCCESS; }
@@ -3086,7 +3089,7 @@ static NTSTATUS gl_glViewport( void *args ) struct glViewport_params *params = args; const struct opengl_funcs *funcs = params->teb->glTable; funcs->p_glViewport( params->x, params->y, params->width, params->height ); - set_context_attribute( params->teb, -1 /* unsupported */, NULL, 0 ); + set_context_attribute( params->teb, GL_VIEWPORT, ¶ms->x, 4 * sizeof(float) ); return STATUS_SUCCESS; }
diff --git a/dlls/opengl32/unix_wgl.c b/dlls/opengl32/unix_wgl.c index 48c7f2b99e7..42f19e4b325 100644 --- a/dlls/opengl32/unix_wgl.c +++ b/dlls/opengl32/unix_wgl.c @@ -63,6 +63,53 @@ enum wgl_handle_type HANDLE_TYPE_MASK = 15 << 12, };
+/* context state management */ + +struct light_model_state +{ + GLfloat ambient[4]; + GLint two_side; +}; + +struct lighting_state +{ + struct light_model_state model; + GLenum shade_model; +}; + +struct depth_buffer_state +{ + GLenum depth_func; +}; + +struct viewport_state +{ + GLint x; + GLint y; + GLsizei w; + GLsizei h; +}; + +struct enable_state +{ + GLboolean cull_face; + GLboolean depth_test; + GLboolean dither; + GLboolean fog; + GLboolean lighting; + GLboolean normalize; +}; + +struct color_buffer_state +{ + GLfloat clear_color[4]; +}; + +struct hint_state +{ + GLenum perspective_correction; +}; + struct opengl_context { HDC hdc; /* context creation DC */ @@ -78,6 +125,12 @@ struct opengl_context
/* semi-stub state tracker for wglCopyContext */ GLbitfield used; /* context state used bits */ + struct lighting_state lighting; /* GL_LIGHTING_BIT */ + struct depth_buffer_state depth_buffer; /* GL_DEPTH_BUFFER_BIT */ + struct viewport_state viewport; /* GL_VIEWPORT_BIT */ + struct enable_state enable; /* GL_ENABLE_BIT */ + struct color_buffer_state color_buffer; /* GL_COLOR_BUFFER_BIT */ + struct hint_state hint; /* GL_HINT_BIT */ };
struct wgl_handle @@ -124,13 +177,46 @@ static struct wgl_handle *get_handle_ptr( HANDLE handle ) return NULL; }
+struct context_attribute_desc +{ + GLbitfield bit; + unsigned short offset; + unsigned short size; +}; + +static struct context_attribute_desc context_attributes[] = +{ +#define CONTEXT_ATTRIBUTE_DESC(bit, name, field) [name] = { bit, offsetof(struct opengl_context, field), sizeof(((struct opengl_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 ), + CONTEXT_ATTRIBUTE_DESC( GL_ENABLE_BIT, GL_DEPTH_TEST, enable.depth_test ), + CONTEXT_ATTRIBUTE_DESC( GL_ENABLE_BIT, GL_DITHER, enable.dither ), + CONTEXT_ATTRIBUTE_DESC( GL_ENABLE_BIT, GL_FOG, enable.fog ), + 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_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 ), + CONTEXT_ATTRIBUTE_DESC( GL_VIEWPORT_BIT, GL_VIEWPORT, viewport ), +#undef CONTEXT_ATTRIBUTE_DESC +}; + +/* GL constants used as indexes should be small, make sure size is reasonable */ +C_ASSERT( sizeof(context_attributes) <= 64 * 1024 ); + void set_context_attribute( TEB *teb, GLenum name, const void *value, size_t size ) { struct opengl_context *ctx = get_current_context( teb ); - GLbitfield bit = -1; + GLbitfield bit;
if (!(ctx = get_current_context( teb ))) 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/%p\n", teb->glCurrentRC, ctx ); ctx->used |= bit; }