summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2016-05-30 14:20:11 +0300
committerTor Lillqvist <tml@collabora.com>2016-05-31 16:36:19 +0000
commit776c124e8797431c8c4eaf6d0550959b05ce69ee (patch)
tree97160b5ee44d32be1fb32b049a18e50465daf1dd
parent04892d061398b235e8d4f276a7d2a5669f5ffe58 (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.cxx109
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);