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-30 14:58:02 +0300
commit933a9d9245fdeceefd92fba9a5cb4db6bca92984 (patch)
tree9d4bf20a5545eff843bae8c07897e5cc29686db4
parent64061d8dd687efa1c78e5284ab01f2f16e5817c3 (diff)
On Windows, compile OpenGL shaders in advance and disable on failure
If the shader compilation or loading of an already compiled shader fails, disable OpenGL in the registry and exit with the EXITHELPER_CRASH_WITH_RESTART status. The wrapper process will thus run soffice.bin once more, and this time OpenGL will not be used. Change-Id: I3cc4a615f00a8a1adb584493861e4956c83cec32
-rw-r--r--vcl/opengl/win/gdiimpl.cxx99
1 files changed, 99 insertions, 0 deletions
diff --git a/vcl/opengl/win/gdiimpl.cxx b/vcl/opengl/win/gdiimpl.cxx
index cf45a46d2dec..04ca857917f4 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,97 @@ bool InitMultisample(const PIXELFORMATDESCRIPTOR& pfd, int& rPixelFormat,
return bArbMultisampleSupported;
}
+namespace
+{
+
+bool tryShaders(const OUString& rVertexShader, const OUString& rFragmentShader, const OUString& rGeometryShader = "")
+{
+ 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, rGeometryShader, "", OpenGLHelper::GetDigest( rVertexShader, rFragmentShader, ""));
+ else
+ 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", "areaScaleFragmentShader") &&
+ tryShaders("transformedTextureVertexShader", "textureFragmentShader") &&
+ tryShaders("combinedTextureVertexShader", "combinedTextureFragmentShader") &&
+ tryShaders("textureVertexShader", "linearGradientFragmentShader") &&
+ tryShaders("textureVertexShader", "radialGradientFragmentShader") &&
+ tryShaders("textureVertexShader", "textureFragmentShader") &&
+ tryShaders("textureVertexShader", "convolutionFragmentShader") &&
+ tryShaders("textureVertexShader", "areaScaleFastFragmentShader") &&
+ tryShaders("textureVertexShader", "areaScaleFragmentShader"));
+
+ if (!bResult)
+ {
+ OpenGLZone::hardDisable();
+ TerminateProcess(GetCurrentProcess(), EXITHELPER_CRASH_WITH_RESTART);
+ }
+
+ return bResult;
+}
+
+} // unnamed namespace
+
bool WinOpenGLContext::ImplInit()
{
OpenGLZone aZone;
@@ -464,6 +556,13 @@ bool WinOpenGLContext::ImplInit()
return false;
}
+ if (!compiledShaderBinariesWork())
+ {
+ wglMakeCurrent(NULL, NULL);
+ wglDeleteContext(hTempRC);
+ return false;
+ }
+
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hTempRC);