From: Matteo Bruni Subject: [PATCH 5/5] wined3d: Add a setting for requesting OpenGL core profile usage. Message-Id: <1434665262-354-5-git-send-email-mbruni@codeweavers.com> Date: Fri, 19 Jun 2015 00:07:42 +0200 --- A lot of stuff is still missing so core profile doesn't work at the moment (it's going to crash if you enable the option, actually). Still I need something like this to avoid adding dead code moving forward. I'm adding a 'legacy_gl' flag to gl_info with this patch. The idea down the line is to also support GLES and for the most part that matches with GL core profiles. There are still some parts which are just different in GLES so probably there will be a 'gles' flag too. dlls/wined3d/context.c | 28 ++++++++++-- dlls/wined3d/directx.c | 101 +++++++++++++++++++++++++++++++++-------- dlls/wined3d/wined3d_main.c | 9 ++++ dlls/wined3d/wined3d_private.h | 5 +- 4 files changed, 115 insertions(+), 28 deletions(-) diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 9cc7c11..a38e4da 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -1558,20 +1558,38 @@ struct wined3d_context *context_create(struct wined3d_swapchain *swapchain, if (gl_info->p_wglCreateContextAttribsARB) { unsigned int ctx_attrib_idx = 0; - GLint ctx_attribs[3]; + GLint ctx_attribs[7], ctx_flags = 0; if (context_debug_output_enabled(gl_info)) + ctx_flags = WGL_CONTEXT_DEBUG_BIT_ARB; + if (wined3d_settings.use_core) + { + TRACE("Creating an OpenGL core profile context.\n"); + ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_MAJOR_VERSION_ARB; + ctx_attribs[ctx_attrib_idx++] = 3; + ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_MINOR_VERSION_ARB; + ctx_attribs[ctx_attrib_idx++] = 2; + ctx_flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + } + if (ctx_flags) { ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_FLAGS_ARB; - ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_DEBUG_BIT_ARB; + ctx_attribs[ctx_attrib_idx++] = ctx_flags; } ctx_attribs[ctx_attrib_idx] = 0; if (!(ctx = gl_info->p_wglCreateContextAttribsARB(hdc, share_ctx, ctx_attribs))) { - ERR("Failed to create a WGL context.\n"); - context_release(ret); - goto out; + if (wined3d_settings.use_core) + { + ctx_attribs[ctx_attrib_idx - 1] &= ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + if (!(ctx = gl_info->p_wglCreateContextAttribsARB(hdc, share_ctx, ctx_attribs))) + { + ERR("Failed to create a WGL context.\n"); + context_release(ret); + goto out; + } + } } } else diff --git a/dlls/wined3d/directx.c b/dlls/wined3d/directx.c index 243f5ae..647400a 100644 --- a/dlls/wined3d/directx.c +++ b/dlls/wined3d/directx.c @@ -279,19 +279,19 @@ static void wined3d_caps_gl_ctx_destroy(const struct wined3d_caps_gl_ctx *ctx) ERR("Failed to restore previous GL context.\n"); } -static void wined3d_caps_gl_ctx_create_attribs(struct wined3d_caps_gl_ctx *caps_gl_ctx, +static BOOL wined3d_caps_gl_ctx_create_attribs(struct wined3d_caps_gl_ctx *caps_gl_ctx, struct wined3d_gl_info *gl_info, const GLint *ctx_attribs) { HGLRC new_ctx; if (!(gl_info->p_wglCreateContextAttribsARB = (void *)wglGetProcAddress("wglCreateContextAttribsARB"))) - return; + return TRUE; if (!(new_ctx = gl_info->p_wglCreateContextAttribsARB(caps_gl_ctx->dc, NULL, ctx_attribs))) { ERR("Failed to create a context using wglCreateContextAttribsARB(), last error %#x.\n", GetLastError()); gl_info->p_wglCreateContextAttribsARB = NULL; - return; + return FALSE; } if (!wglMakeCurrent(caps_gl_ctx->dc, new_ctx)) @@ -300,12 +300,14 @@ static void wined3d_caps_gl_ctx_create_attribs(struct wined3d_caps_gl_ctx *caps_ if (!wglDeleteContext(new_ctx)) ERR("Failed to delete new context, last error %#x.\n", GetLastError()); gl_info->p_wglCreateContextAttribsARB = NULL; - return; + return TRUE; } if (!wglDeleteContext(caps_gl_ctx->gl_ctx)) ERR("Failed to delete old context, last error %#x.\n", GetLastError()); caps_gl_ctx->gl_ctx = new_ctx; + + return TRUE; } static BOOL wined3d_caps_gl_ctx_create(struct wined3d_caps_gl_ctx *ctx) @@ -2420,6 +2422,30 @@ static void parse_extension_string(struct wined3d_gl_info *gl_info, const char * } } +static void enumerate_gl_extensions(struct wined3d_gl_info *gl_info, + const struct wined3d_extension_map *map, unsigned int map_entries_count) +{ + const char *gl_extension_name; + unsigned int i, j; + GLint extensions_count; + + glGetIntegerv(GL_NUM_EXTENSIONS, &extensions_count); + for (i = 0; i < extensions_count; ++i) + { + gl_extension_name = (const char *)GL_EXTCALL(glGetStringi(GL_EXTENSIONS, i)); + TRACE("GL extension %s reported.\n", gl_extension_name); + for (j = 0; j < map_entries_count; ++j) + { + if (!strcmp(gl_extension_name, map[j].extension_string)) + { + TRACE("FOUND: %s support.\n", map[j].extension_string); + gl_info->supported[map[j].extension] = TRUE; + break; + } + } + } +} + static void load_gl_funcs(struct wined3d_gl_info *gl_info) { #define USE_GL_FUNC(pfn) gl_info->gl_ops.ext.p_##pfn = (void *)wglGetProcAddress(#pfn); @@ -2912,6 +2938,7 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info) USE_GL_FUNC(glGetShaderInfoLog) /* OpenGL 2.0 */ USE_GL_FUNC(glGetShaderiv) /* OpenGL 2.0 */ USE_GL_FUNC(glGetShaderSource) /* OpenGL 2.0 */ + USE_GL_FUNC(glGetStringi) /* OpenGL 3.0 */ USE_GL_FUNC(glGetUniformfv) /* OpenGL 2.0 */ USE_GL_FUNC(glGetUniformiv) /* OpenGL 2.0 */ USE_GL_FUNC(glGetUniformLocation) /* OpenGL 2.0 */ @@ -3324,12 +3351,12 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter) struct fragment_caps fragment_caps; struct shader_caps shader_caps; const char *WGL_Extensions = NULL; - const char *GL_Extensions = NULL; enum wined3d_gl_vendor gl_vendor; enum wined3d_pci_device device; DWORD gl_version; HDC hdc; unsigned int i; + GLint context_profile; TRACE("adapter %p.\n", adapter); @@ -3359,23 +3386,38 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter) } gl_version = wined3d_parse_gl_version(gl_version_str); - /* Parse the gl supported features, in theory enabling parts of our code appropriately. */ - GL_Extensions = (const char *)gl_info->gl_ops.gl.p_glGetString(GL_EXTENSIONS); - if (!GL_Extensions) - { - ERR("Received a NULL GL_EXTENSIONS.\n"); - return FALSE; - } + glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &context_profile); + if (glGetError() != GL_NO_ERROR) + context_profile = 0; + if (context_profile & GL_CONTEXT_CORE_PROFILE_BIT) + TRACE("Got a core profile context.\n"); + else + gl_info->legacy_gl = TRUE; + + load_gl_funcs(gl_info); + /* Parse the gl supported features, in theory enabling parts of our code appropriately. */ memset(gl_info->supported, 0, sizeof(gl_info->supported)); gl_info->supported[WINED3D_GL_EXT_NONE] = TRUE; - TRACE("GL extensions reported:\n"); - parse_extension_string(gl_info, GL_Extensions, gl_extension_map, - sizeof(gl_extension_map) / sizeof(*gl_extension_map)); + if (gl_info->legacy_gl) + { + const char *GL_Extensions = (const char *)gl_info->gl_ops.gl.p_glGetString(GL_EXTENSIONS); - /* Now work out what GL support this card really has. */ - load_gl_funcs( gl_info ); + if (!GL_Extensions) + { + ERR("Received a NULL GL_EXTENSIONS.\n"); + return FALSE; + } + TRACE("GL extensions reported:\n"); + parse_extension_string(gl_info, GL_Extensions, gl_extension_map, + sizeof(gl_extension_map) / sizeof(*gl_extension_map)); + } + else + { + enumerate_gl_extensions(gl_info, gl_extension_map, + sizeof(gl_extension_map) / sizeof(*gl_extension_map)); + } hdc = wglGetCurrentDC(); /* Not all GL drivers might offer WGL extensions e.g. VirtualBox. */ @@ -5659,7 +5701,7 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal) struct wined3d_caps_gl_ctx caps_gl_ctx = {0}; unsigned int ctx_attrib_idx = 0; DISPLAY_DEVICEW display_device; - GLint ctx_attribs[3]; + GLint ctx_attribs[7], ctx_flags = 0; TRACE("adapter %p, ordinal %u.\n", adapter, ordinal); @@ -5706,12 +5748,31 @@ static BOOL wined3d_adapter_init(struct wined3d_adapter *adapter, UINT ordinal) } if (context_debug_output_enabled(gl_info)) + ctx_flags = WGL_CONTEXT_DEBUG_BIT_ARB; + if (wined3d_settings.use_core) + { + /* WGL can return a version equal or above the requested one (as long as + * the newer version doesn't remove any feature in the requested + * version). For example, Mesa gladly returns the newest acceptable + * version, AMD on Windows always returns exactly the requested version. */ + ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_MAJOR_VERSION_ARB; + ctx_attribs[ctx_attrib_idx++] = 3; + ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_MINOR_VERSION_ARB; + ctx_attribs[ctx_attrib_idx++] = 2; + ctx_flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + } + if (ctx_flags) { ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_FLAGS_ARB; - ctx_attribs[ctx_attrib_idx++] = WGL_CONTEXT_DEBUG_BIT_ARB; + ctx_attribs[ctx_attrib_idx++] = ctx_flags; } ctx_attribs[ctx_attrib_idx] = 0; - wined3d_caps_gl_ctx_create_attribs(&caps_gl_ctx, gl_info, ctx_attribs); + if (!wined3d_caps_gl_ctx_create_attribs(&caps_gl_ctx, gl_info, ctx_attribs) + && wined3d_settings.use_core) + { + ctx_attribs[ctx_attrib_idx - 1] &= ~WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + wined3d_caps_gl_ctx_create_attribs(&caps_gl_ctx, gl_info, ctx_attribs); + } if (!wined3d_adapter_init_gl_caps(adapter)) { diff --git a/dlls/wined3d/wined3d_main.c b/dlls/wined3d/wined3d_main.c index 758ba43..be24944 100644 --- a/dlls/wined3d/wined3d_main.c +++ b/dlls/wined3d/wined3d_main.c @@ -72,6 +72,7 @@ static CRITICAL_SECTION wined3d_wndproc_cs = {&wined3d_wndproc_cs_debug, -1, 0, * where appropriate. */ struct wined3d_settings wined3d_settings = { + FALSE, /* Use of OpenGL core profile disabled by default */ TRUE, /* Use of GLSL enabled by default */ ORM_FBO, /* Use FBOs to do offscreen rendering */ PCI_VENDOR_NONE,/* PCI Vendor ID */ @@ -199,6 +200,14 @@ static BOOL wined3d_dll_init(HINSTANCE hInstDLL) if (hkey || appkey) { + if (!get_config_key( hkey, appkey, "UseCore", buffer, size)) + { + if (!strcmp(buffer,"enabled")) + { + TRACE("Requested OpenGL Core profile.\n"); + wined3d_settings.use_core = TRUE; + } + } if ( !get_config_key( hkey, appkey, "UseGLSL", buffer, size) ) { if (!strcmp(buffer,"disabled")) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index c184b72..f65f166 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -261,9 +261,7 @@ static inline float float_24_to_32(DWORD in) * values in wined3d_main.c as well. */ struct wined3d_settings { - /* Ideally, we don't want the user to have to request GLSL. If the - * hardware supports GLSL, we should use it. However, until it's fully - * implemented, we'll leave it as a registry setting for developers. */ + BOOL use_core; BOOL glslRequested; int offscreen_rendering_mode; unsigned short pci_vendor_id; @@ -1711,6 +1709,7 @@ struct wined3d_gl_limits struct wined3d_gl_info { + BOOL legacy_gl; DWORD glsl_version; struct wined3d_gl_limits limits; DWORD reserved_glsl_constants, reserved_arb_constants; -- 2.3.6