summaryrefslogtreecommitdiff
path: root/vcl/source/opengl
diff options
context:
space:
mode:
authorTor Lillqvist <tml@collabora.com>2016-05-25 15:23:22 +0300
committerMichael Meeks <michael.meeks@collabora.com>2016-05-31 20:45:03 +0000
commit0f2d826394fcbb3f9cfbcc818d46dc15f32b5028 (patch)
treeba18fe9a29c1aeaad7f70bacd4e1d36c07e939fd /vcl/source/opengl
parenta97f9c5790b4751098b0c3f78a387fbff36582a6 (diff)
tdf#100159: On Windows, compile GL shaders in advance, disable GL on failure
This is a combination of multiple commits in master, adapted for this branch as necessary: Don't claim to be reading a file before trying to open it Avoid redundancy: The same information was logged in readProgramBinary() Use VCL_GL_INFO here Failing to open a cached shader binary is a no reason for a SAL_WARN. It is normal that they don't exist when first trying, that is the very nature of a 'cache'. Move exithelper.h to include. We will want to use EXITHELPER_NORMAL_RESTART in vcl, too. 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: I54d92f150975d3fa72d93f3f679b16c90ee38f02 Reviewed-on: https://gerrit.libreoffice.org/25708 Reviewed-by: Jan Holesovsky <kendy@collabora.com> Tested-by: Michael Meeks <michael.meeks@collabora.com>
Diffstat (limited to 'vcl/source/opengl')
-rw-r--r--vcl/source/opengl/OpenGLContext.cxx109
-rw-r--r--vcl/source/opengl/OpenGLHelper.cxx9
2 files changed, 113 insertions, 5 deletions
diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx
index 03d0a5d05811..1ce8ce8e5fca 100644
--- a/vcl/source/opengl/OpenGLContext.cxx
+++ b/vcl/source/opengl/OpenGLContext.cxx
@@ -9,6 +9,7 @@
#include <config_opengl.h>
+#include <desktop/exithelper.h>
#include <vcl/opengl/OpenGLContext.hxx>
#include <vcl/opengl/OpenGLHelper.hxx>
#include <vcl/opengl/OpenGLWrapper.hxx>
@@ -839,6 +840,107 @@ bool OpenGLContext::ImplInit()
#elif defined( _WIN32 )
+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 OpenGLContext::init(HDC hDC, HWND hWnd)
{
if (mbInitialized)
@@ -964,6 +1066,13 @@ bool OpenGLContext::ImplInit()
return false;
}
+ if (!compiledShaderBinariesWork())
+ {
+ wglMakeCurrent(NULL, NULL);
+ wglDeleteContext(hTempRC);
+ return false;
+ }
+
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hTempRC);
diff --git a/vcl/source/opengl/OpenGLHelper.cxx b/vcl/source/opengl/OpenGLHelper.cxx
index 8418706c3784..5892a625300e 100644
--- a/vcl/source/opengl/OpenGLHelper.cxx
+++ b/vcl/source/opengl/OpenGLHelper.cxx
@@ -66,7 +66,6 @@ OString loadShader(const OUString& rFilename)
{
OUString aFileURL = getShaderFolder() + rFilename +".glsl";
osl::File aFile(aFileURL);
- SAL_INFO("vcl.opengl", "Reading " << aFileURL);
if(aFile.open(osl_File_OpenFlag_Read) == osl::FileBase::E_None)
{
sal_uInt64 nSize = 0;
@@ -76,11 +75,12 @@ OString loadShader(const OUString& rFilename)
aFile.read(content.get(), nSize, nBytesRead);
assert(nSize == nBytesRead);
content.get()[nBytesRead] = 0;
+ SAL_INFO("vcl.opengl", "Read " << nBytesRead << " bytes from " << aFileURL);
return OString(content.get());
}
else
{
- SAL_WARN("vcl.opengl", "could not load the file: " << aFileURL);
+ SAL_WARN("vcl.opengl", "Could not open " << aFileURL);
}
return OString();
@@ -289,12 +289,12 @@ namespace
sal_uInt64 nBytesRead = 0;
aFile.read( rBinary.data(), nSize, nBytesRead );
assert( nSize == nBytesRead );
- SAL_INFO("vcl.opengl", "Loading file: '" << rBinaryFileName << "': success" );
+ VCL_GL_INFO("Loading file: '" << rBinaryFileName << "': success" );
return true;
}
else
{
- SAL_WARN("vcl.opengl", "Loading file: '" << rBinaryFileName << "': FAIL");
+ VCL_GL_INFO("Loading file: '" << rBinaryFileName << "': FAIL");
}
return false;
@@ -405,7 +405,6 @@ GLint OpenGLHelper::LoadShaders(const OUString& rVertexShaderName,
OString aFileName =
createFileName(rVertexShaderName, rFragmentShaderName, rGeometryShaderName, rDigest);
bBinaryResult = loadProgramBinary(ProgramID, aFileName);
- VCL_GL_INFO("Load binary shader from '" << aFileName << "'" << bBinaryResult);
CHECK_GL_ERROR();
}