From e9b9dca2caf51d6dd14858b624c0d5e749df2b92 Mon Sep 17 00:00:00 2001 From: whitequark Date: Thu, 23 May 2019 10:58:31 +0000 Subject: [PATCH] Win32: use native OpenGL drivers, if available. After this commit, if the target system does have modern OpenGL drivers installed, ANGLE is configured to use them, bypassing most translation (shaders still have to be translated from ESSL to GLSL). If there are no OpenGL drivers, such as if the graphics drivers were installed via Windows Update, DirectX translation is still used. This results in a very noticeable startup delay and minor performance degradation. In addition it is no longer necessary to build with -DOPENGL=1 to be able to run the binary in wine; everything works out of the box. Before, wine's incomplete HLSL translator would crash. This change required renaming the variable `texture` in shaders, since it shadows the Core GLSL function with the same name, and ANGLE translates texture2D() calls to texture() calls. --- CMakeLists.txt | 6 +++--- res/shaders/imesh.frag | 4 ++-- res/shaders/imesh_tex.frag | 4 ++-- res/shaders/imesh_texa.frag | 4 ++-- res/shaders/mesh_fill.frag | 4 ++-- src/platform/guiwin.cpp | 38 +++++++++++++++++++++++++++++++------ src/render/gl3shader.cpp | 13 ++++++++++--- 7 files changed, 53 insertions(+), 20 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 81694681..6367874f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -187,9 +187,9 @@ if(ENABLE_GUI) set(ANGLE_STATIC ON CACHE INTERNAL "") set(ANGLE_ENABLE_D3D9 ON CACHE INTERNAL "") set(ANGLE_ENABLE_D3D11 ON CACHE INTERNAL "") - set(ANGLE_ENABLE_OPENGL OFF CACHE INTERNAL "") - set(ANGLE_ENABLE_ESSL OFF CACHE INTERNAL "") - set(ANGLE_ENABLE_GLSL OFF CACHE INTERNAL "") + set(ANGLE_ENABLE_OPENGL ON CACHE INTERNAL "") + set(ANGLE_ENABLE_ESSL ON CACHE INTERNAL "") + set(ANGLE_ENABLE_GLSL ON CACHE INTERNAL "") set(ANGLE_ENABLE_HLSL ON CACHE INTERNAL "") add_vendored_subdirectory(extlib/angle) set(OPENGL_LIBRARIES EGL GLESv2) diff --git a/res/shaders/imesh.frag b/res/shaders/imesh.frag index 4fa0713c..1e7a74b7 100644 --- a/res/shaders/imesh.frag +++ b/res/shaders/imesh.frag @@ -4,9 +4,9 @@ // Copyright 2016 Aleksey Egorov //----------------------------------------------------------------------------- uniform vec4 color; -uniform sampler2D texture; +uniform sampler2D texture_; void main() { - if(texture2D(texture, gl_FragCoord.xy / 32.0).a < 0.5) discard; + if(texture2D(texture_, gl_FragCoord.xy / 32.0).a < 0.5) discard; gl_FragColor = color; } diff --git a/res/shaders/imesh_tex.frag b/res/shaders/imesh_tex.frag index a6514f0b..d3b32355 100644 --- a/res/shaders/imesh_tex.frag +++ b/res/shaders/imesh_tex.frag @@ -4,12 +4,12 @@ // Copyright 2016 Aleksey Egorov //----------------------------------------------------------------------------- uniform vec4 color; -uniform sampler2D texture; +uniform sampler2D texture_; varying vec2 fragTex; void main() { - vec4 texColor = texture2D(texture, fragTex); + vec4 texColor = texture2D(texture_, fragTex); if(texColor.a == 0.0) discard; gl_FragColor = texColor * color; } diff --git a/res/shaders/imesh_texa.frag b/res/shaders/imesh_texa.frag index ed21a86d..89a124c4 100644 --- a/res/shaders/imesh_texa.frag +++ b/res/shaders/imesh_texa.frag @@ -4,10 +4,10 @@ // Copyright 2016 Aleksey Egorov //----------------------------------------------------------------------------- uniform vec4 color; -uniform sampler2D texture; +uniform sampler2D texture_; varying vec2 fragTex; void main() { - gl_FragColor = vec4(color.rgb, color.a * texture2D(texture, fragTex).TEX_ALPHA); + gl_FragColor = vec4(color.rgb, color.a * texture2D(texture_, fragTex).TEX_ALPHA); } diff --git a/res/shaders/mesh_fill.frag b/res/shaders/mesh_fill.frag index 74b38603..c8b3d37b 100644 --- a/res/shaders/mesh_fill.frag +++ b/res/shaders/mesh_fill.frag @@ -4,9 +4,9 @@ // Copyright 2016 Aleksey Egorov //----------------------------------------------------------------------------- uniform vec4 color; -uniform sampler2D texture; +uniform sampler2D texture_; void main() { - if(texture2D(texture, gl_FragCoord.xy / 32.0).TEX_ALPHA < 0.5) discard; + if(texture2D(texture_, gl_FragCoord.xy / 32.0).TEX_ALPHA < 0.5) discard; gl_FragColor = color; } diff --git a/src/platform/guiwin.cpp b/src/platform/guiwin.cpp index 8fb788f7..ba0a3a1e 100644 --- a/src/platform/guiwin.cpp +++ b/src/platform/guiwin.cpp @@ -22,7 +22,9 @@ #if HAVE_OPENGL == 3 # define EGLAPI /*static linkage*/ +# define EGL_EGLEXT_PROTOTYPES # include +# include #endif #if defined(HAVE_SPACEWARE) @@ -498,9 +500,9 @@ public: #if HAVE_OPENGL == 1 HGLRC hGlRc = NULL; #elif HAVE_OPENGL == 3 - EGLDisplay eglDisplay = NULL; - EGLSurface eglSurface = NULL; - EGLContext eglContext = NULL; + static EGLDisplay eglDisplay; + EGLSurface eglSurface = EGL_NO_SURFACE; + EGLContext eglContext = EGL_NO_CONTEXT; #endif WINDOWPLACEMENT placement = {}; @@ -603,10 +605,32 @@ public: sscheck(hGlRc = wglCreateContext(hDc)); #elif HAVE_OPENGL == 3 - ssassert(eglBindAPI(EGL_OPENGL_ES_API), "Cannot bind EGL API"); + if(eglDisplay == EGL_NO_DISPLAY) { + ssassert(eglBindAPI(EGL_OPENGL_ES_API), "Cannot bind EGL API"); - eglDisplay = eglGetDisplay(hDc); - ssassert(eglInitialize(eglDisplay, NULL, NULL), "Cannot initialize EGL"); + EGLBoolean initialized = EGL_FALSE; + for(auto &platformType : { + // Try platform types from least to most amount of software translation required. + std::make_pair("OpenGL ES", EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE), + std::make_pair("OpenGL", EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE), + std::make_pair("Direct3D 11", EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE), + std::make_pair("Direct3D 9", EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE), + }) { + dbp("Initializing ANGLE with %s backend", platformType.first); + EGLint displayAttributes[] = { + EGL_PLATFORM_ANGLE_TYPE_ANGLE, platformType.second, + EGL_NONE + }; + eglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, hDc, + displayAttributes); + if(eglDisplay != EGL_NO_DISPLAY) { + initialized = eglInitialize(eglDisplay, NULL, NULL); + if(initialized) break; + eglTerminate(eglDisplay); + } + } + ssassert(initialized, "Cannot find a suitable EGL display"); + } EGLint configAttributes[] = { EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER, @@ -1324,6 +1348,8 @@ public: } }; +EGLDisplay WindowImplWin32::eglDisplay = EGL_NO_DISPLAY; + WindowRef CreateWindow(Window::Kind kind, WindowRef parentWindow) { return std::make_shared(kind, std::static_pointer_cast(parentWindow)); diff --git a/src/render/gl3shader.cpp b/src/render/gl3shader.cpp index 7d5ab101..4d4bac36 100644 --- a/src/render/gl3shader.cpp +++ b/src/render/gl3shader.cpp @@ -118,6 +118,13 @@ precision highp float; GLint compiled; glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); + if(!compiled) { + dbp("Failed to compile shader:\n" + "----8<----8<----8<----8<----8<----\n" + "%s\n" + "----8<----8<----8<----8<----8<----\n", + src.c_str()); + } ssassert(compiled, "Cannot compile shader"); return shader; @@ -220,7 +227,7 @@ void MeshRenderer::Init() { { ATTRIB_POS, "pos" }, } ); - fillShader.SetUniformTextureUnit("texture", 0); + fillShader.SetUniformTextureUnit("texture_", 0); selectedShader = &lightShader; } @@ -957,8 +964,8 @@ void IndexedMeshRenderer::Init() { } ); - texShader.SetUniformTextureUnit("texture", 0); - texaShader.SetUniformTextureUnit("texture", 0); + texShader.SetUniformTextureUnit("texture_", 0); + texaShader.SetUniformTextureUnit("texture_", 0); selectedShader = &colShader; }