diff options
author | Tor Lillqvist <tml@collabora.com> | 2016-05-30 14:20:11 +0300 |
---|---|---|
committer | Tor Lillqvist <tml@collabora.com> | 2016-05-31 16:36:19 +0000 |
commit | 776c124e8797431c8c4eaf6d0550959b05ce69ee (patch) | |
tree | 97160b5ee44d32be1fb32b049a18e50465daf1dd | |
parent | 04892d061398b235e8d4f276a7d2a5669f5ffe58 (diff) |
tdf#100159: On Windows, compile GL shaders in advance, disable GL on failure
If the shader compilation or loading of an already compiled shader
fails, disable OpenGL in the registry and exit with the
EXITHELPER_NORMAL_RESTART status. The wrapper process will thus
run soffice.bin once more, and this time OpenGL will not be used.
Change-Id: I3cc4a615f00a8a1adb584493861e4956c83cec32
Reviewed-on: https://gerrit.libreoffice.org/25675
Reviewed-by: Tor Lillqvist <tml@collabora.com>
Tested-by: Tor Lillqvist <tml@collabora.com>
-rw-r--r-- | vcl/opengl/win/gdiimpl.cxx | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/vcl/opengl/win/gdiimpl.cxx b/vcl/opengl/win/gdiimpl.cxx index cf45a46d2dec..8bc79438ed3e 100644 --- a/vcl/opengl/win/gdiimpl.cxx +++ b/vcl/opengl/win/gdiimpl.cxx @@ -8,6 +8,7 @@ */ #include "opengl/win/gdiimpl.hxx" +#include <desktop/exithelper.h> #include <opengl/zone.hxx> #include <o3tl/lru_map.hxx> #include <win/wincomp.hxx> @@ -349,6 +350,107 @@ bool InitMultisample(const PIXELFORMATDESCRIPTOR& pfd, int& rPixelFormat, return bArbMultisampleSupported; } +namespace +{ + +bool tryShaders(const OUString& rVertexShader, const OUString& rFragmentShader, const OUString& rGeometryShader = "", const OString& rPreamble = "") +{ + GLint nId; + + // Somewhat mysteriously, the OpenGLHelper::LoadShaders() API saves a compiled binary of the + // shader only if you give it the digest of the shaders. We have API to calculate the digest + // only of the combination of vertex and fragment (but not geometry) shader. So if we have a + // geometry shader, we should not save the binary. + if (rGeometryShader.isEmpty()) + { + nId = OpenGLHelper::LoadShaders(rVertexShader, rFragmentShader, rPreamble, OpenGLHelper::GetDigest( rVertexShader, rFragmentShader, rPreamble)); + } + else + { + assert(rPreamble.isEmpty()); + nId = OpenGLHelper::LoadShaders(rVertexShader, rFragmentShader, rGeometryShader); + } + if (!nId) + return false; + glDeleteProgram(nId); + return glGetError() == GL_NO_ERROR; +} + +bool compiledShaderBinariesWork() +{ + static bool bBeenHere = false; + static bool bResult; + + if (bBeenHere) + return bResult; + + bBeenHere = true; + + bResult = + ( +#if 0 // Only look at shaders used by vcl for now + // canvas + tryShaders("dummyVertexShader", "linearMultiColorGradientFragmentShader") && + tryShaders("dummyVertexShader", "linearTwoColorGradientFragmentShader") && + tryShaders("dummyVertexShader", "radialMultiColorGradientFragmentShader") && + tryShaders("dummyVertexShader", "radialTwoColorGradientFragmentShader") && + tryShaders("dummyVertexShader", "rectangularMultiColorGradientFragmentShader") && + tryShaders("dummyVertexShader", "rectangularTwoColorGradientFragmentShader") && + // chart2 + (GLEW_VERSION_3_3 ? + (tryShaders("shape3DVertexShader", "shape3DFragmentShader") && + tryShaders("shape3DVertexShaderBatchScroll", "shape3DFragmentShaderBatchScroll") && + tryShaders("shape3DVertexShaderBatch", "shape3DFragmentShaderBatch") && + tryShaders("textVertexShaderBatch", "textFragmentShaderBatch")) : + (tryShaders("shape3DVertexShaderV300", "shape3DFragmentShaderV300"))) && + tryShaders("textVertexShader", "textFragmentShader") && + tryShaders("screenTextVertexShader", "screenTextFragmentShader") && + tryShaders("commonVertexShader", "commonFragmentShader") && + tryShaders("pickingVertexShader", "pickingFragmentShader") && + tryShaders("backgroundVertexShader", "backgroundFragmentShader") && + tryShaders("symbolVertexShader", "symbolFragmentShader") && + tryShaders("symbolVertexShader", "symbolFragmentShader") && + // slideshow + tryShaders("reflectionVertexShader", "reflectionFragmentShader") && + tryShaders("basicVertexShader", "basicFragmentShader") && + tryShaders("vortexVertexShader", "vortexFragmentShader", "vortexGeometryShader") && + tryShaders("basicVertexShader", "rippleFragmentShader") && + tryShaders("glitterVertexShader", "glitterFragmentShader") && + tryShaders("honeycombVertexShader", "honeycombFragmentShader", "honeycombGeometryShader") && +#endif + // vcl + tryShaders("combinedVertexShader", "combinedFragmentShader") && + tryShaders("dumbVertexShader", "invert50FragmentShader") && + tryShaders("combinedTextureVertexShader", "combinedTextureFragmentShader") && + tryShaders("textureVertexShader", "areaScaleFragmentShader") && + tryShaders("transformedTextureVertexShader", "maskedTextureFragmentShader") && + tryShaders("transformedTextureVertexShader", "areaScaleFastFragmentShader") && + tryShaders("transformedTextureVertexShader", "areaScaleFastFragmentShader", "", "#define MASKED") && + tryShaders("transformedTextureVertexShader", "areaScaleFragmentShader") && + tryShaders("transformedTextureVertexShader", "areaScaleFragmentShader", "", "#define MASKED") && + tryShaders("transformedTextureVertexShader", "textureFragmentShader") && + tryShaders("combinedTextureVertexShader", "combinedTextureFragmentShader") && + tryShaders("combinedTextureVertexShader", "combinedTextureFragmentShader", "", "// flush shader\n") && + tryShaders("textureVertexShader", "linearGradientFragmentShader") && + tryShaders("textureVertexShader", "radialGradientFragmentShader") && + tryShaders("textureVertexShader", "areaHashCRC64TFragmentShader") && + tryShaders("textureVertexShader", "replaceColorFragmentShader") && + tryShaders("textureVertexShader", "greyscaleFragmentShader") && + tryShaders("textureVertexShader", "textureFragmentShader") && + tryShaders("textureVertexShader", "convolutionFragmentShader") && + tryShaders("textureVertexShader", "areaScaleFastFragmentShader")); + + if (!bResult) + { + OpenGLZone::hardDisable(); + TerminateProcess(GetCurrentProcess(), EXITHELPER_NORMAL_RESTART); + } + + return bResult; +} + +} // unnamed namespace + bool WinOpenGLContext::ImplInit() { OpenGLZone aZone; @@ -464,6 +566,13 @@ bool WinOpenGLContext::ImplInit() return false; } + if (!compiledShaderBinariesWork()) + { + wglMakeCurrent(NULL, NULL); + wglDeleteContext(hTempRC); + return false; + } + wglMakeCurrent(NULL, NULL); wglDeleteContext(hTempRC); |