diff options
author | Stephan Bergmann <sbergman@redhat.com> | 2022-03-22 09:54:05 +0100 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2022-03-28 14:31:07 +0200 |
commit | 8a734ba9287f8d25c3c3df50b4efc91b9035127d (patch) | |
tree | 14f9afd88331d88ef809a8c9c8e282a613f0e844 /vcl | |
parent | 6b147d3369ece427e490d3108de6ec9f7448c570 (diff) |
Drop support for OpenGL denylist on X11
...which appears to have become even less relevant with
db89f53c31af997b9bf422b0e784afba8d62a42e "remove OpenGL VCL backend code". And
the vcl/unx/glxtest.cxx machinery that it is based on is (a) known to cause
issues like <https://gitlab.freedesktop.org/mesa/mesa/-/issues/3957>
"LibreOffice's OpenGL version detection code hangs when running inside a flatpak
container with a different mesa version", and (b) is one of the two reasons why
an soffice that uses Wayland nevertheless also requires Xwayland during startup
(the other reason being oosplash). So getting rid of the glxtest machinery is
beneficial.
The remaining two potential uses of OpenGL on X11/Wayland are the obscure
css.rendering.SpriteCanvas.OGL service implementation (about which
db89f53c31af997b9bf422b0e784afba8d62a42e states that "it seems has never been
finished or enabled (or so it most probably should be dumped too)") and some
slideshow transitions. About the latter, Caolán stated on IRC: "I think we
grew this set of stuff to check for dodgy opengl primarily for the case where
vcl used opengl for ordinary UI optimizations; but I think that use is gone now
so I wonder does it make sense to just drop all of that entirely; for just slide
transitions we apparently survived fine without the denylist for ages". (And in
any case there is still the WatchdogThread support with OpenGLZone::hardDisable
in VCLExceptionSignal_impl, vcl/source/app/svmain.cxx, should any OpenGL code
run into problems.)
(The removal of gb_LinkTarget_use_glxtest from gb_LinkTarget_use_vclmain, which
indirectly brought in gb_LinkTarget_use_libraries,*,vcl, revealed that an
explicit use of vcl was missing from various Executables etc., which thus had to
be added now.)
Change-Id: Ifa5220fd09910a4459ca546d9655e479a2e38f1e
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/131943
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/Executable_icontest.mk | 1 | ||||
-rw-r--r-- | vcl/Executable_mtfdemo.mk | 1 | ||||
-rw-r--r-- | vcl/Executable_vcldemo.mk | 1 | ||||
-rw-r--r-- | vcl/Executable_visualbackendtest.mk | 3 | ||||
-rw-r--r-- | vcl/Library_vcl.mk | 9 | ||||
-rw-r--r-- | vcl/Module_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/StaticLibrary_glxtest.mk | 41 | ||||
-rw-r--r-- | vcl/inc/opengl/x11/X11DeviceInfo.hxx | 48 | ||||
-rw-r--r-- | vcl/inc/opengl/x11/glxtest.hxx | 21 | ||||
-rw-r--r-- | vcl/source/opengl/OpenGLHelper.cxx | 11 | ||||
-rw-r--r-- | vcl/source/opengl/x11/X11DeviceInfo.cxx | 363 | ||||
-rw-r--r-- | vcl/source/salmain/salmain.cxx | 2 | ||||
-rw-r--r-- | vcl/unx/glxtest.cxx | 294 |
13 files changed, 7 insertions, 789 deletions
diff --git a/vcl/Executable_icontest.mk b/vcl/Executable_icontest.mk index 630198237907..60a69bc7a156 100644 --- a/vcl/Executable_icontest.mk +++ b/vcl/Executable_icontest.mk @@ -37,6 +37,7 @@ $(eval $(call gb_Executable_use_libraries,icontest,\ sal \ tl \ ucbhelper \ + vcl \ )) $(eval $(call gb_Executable_use_vclmain,icontest)) diff --git a/vcl/Executable_mtfdemo.mk b/vcl/Executable_mtfdemo.mk index 4b192c14533a..31e017f08d18 100644 --- a/vcl/Executable_mtfdemo.mk +++ b/vcl/Executable_mtfdemo.mk @@ -31,6 +31,7 @@ $(eval $(call gb_Executable_use_libraries,mtfdemo,\ drawinglayer \ emfio \ i18nlangtag \ + vcl \ )) $(eval $(call gb_Executable_use_vclmain,mtfdemo)) diff --git a/vcl/Executable_vcldemo.mk b/vcl/Executable_vcldemo.mk index e4076ac08231..beb8809bd7a4 100644 --- a/vcl/Executable_vcldemo.mk +++ b/vcl/Executable_vcldemo.mk @@ -40,6 +40,7 @@ $(eval $(call gb_Executable_use_libraries,vcldemo,\ salhelper \ fwk \ i18nlangtag \ + vcl \ )) $(eval $(call gb_Executable_use_vclmain,vcldemo)) diff --git a/vcl/Executable_visualbackendtest.mk b/vcl/Executable_visualbackendtest.mk index c1db9ce874ec..567399464e0c 100644 --- a/vcl/Executable_visualbackendtest.mk +++ b/vcl/Executable_visualbackendtest.mk @@ -28,9 +28,10 @@ $(eval $(call gb_Executable_use_libraries,visualbackendtest,\ tl \ sal \ salhelper \ + vcl \ )) -$(eval $(call gb_Executable_use_vclmain,visualbackendtest,-lm)) +$(eval $(call gb_Executable_use_vclmain,visualbackendtest)) $(eval $(call gb_Executable_add_exception_objects,visualbackendtest,\ vcl/backendtest/VisualBackendTest \ diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index a0f61992b74b..a141e22348dd 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -584,15 +584,6 @@ $(eval $(call gb_Library_add_libs,vcl,\ -lX11 \ -lXext \ )) - -ifneq (,$(filter LINUX %BSD SOLARIS,$(OS))) -$(eval $(call gb_Library_use_static_libraries,vcl,\ - glxtest \ -)) -$(eval $(call gb_Library_add_exception_objects,vcl,\ - vcl/source/opengl/x11/X11DeviceInfo \ -)) -endif endif # USING_X11 diff --git a/vcl/Module_vcl.mk b/vcl/Module_vcl.mk index 090e517b0d0a..33485fefa52a 100644 --- a/vcl/Module_vcl.mk +++ b/vcl/Module_vcl.mk @@ -70,7 +70,6 @@ ifeq ($(USING_X11),TRUE) $(eval $(call gb_Module_add_targets,vcl,\ $(if $(ENABLE_GEN),Library_vclplug_gen) \ Library_desktop_detector \ - StaticLibrary_glxtest \ Package_fontunxppds \ Package_fontunxpsprint \ )) diff --git a/vcl/StaticLibrary_glxtest.mk b/vcl/StaticLibrary_glxtest.mk deleted file mode 100644 index b082e47e2882..000000000000 --- a/vcl/StaticLibrary_glxtest.mk +++ /dev/null @@ -1,41 +0,0 @@ -# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- -# -# This file is part of the LibreOffice project. -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. -# -# This file incorporates work covered by the following license notice: -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed -# with this work for additional information regarding copyright -# ownership. The ASF licenses this file to you under the Apache -# License, Version 2.0 (the "License"); you may not use this file -# except in compliance with the License. You may obtain a copy of -# the License at http://www.apache.org/licenses/LICENSE-2.0 . -# - -$(eval $(call gb_StaticLibrary_StaticLibrary,glxtest)) - -$(eval $(call gb_StaticLibrary_set_include,glxtest,\ - $$(INCLUDE) \ - -I$(SRCDIR)/vcl/inc \ -)) - -$(eval $(call gb_StaticLibrary_use_api,glxtest,\ - offapi \ - udkapi \ -)) - -$(eval $(call gb_StaticLibrary_add_libs,glxtest,\ - -lm $(UNIX_DLAPI_LIBS) \ - -lX11 \ -)) - -$(eval $(call gb_StaticLibrary_add_exception_objects,glxtest,\ - vcl/unx/glxtest \ -)) - -# vim: set noet sw=4 ts=4: diff --git a/vcl/inc/opengl/x11/X11DeviceInfo.hxx b/vcl/inc/opengl/x11/X11DeviceInfo.hxx deleted file mode 100644 index 91a97d1c150e..000000000000 --- a/vcl/inc/opengl/x11/X11DeviceInfo.hxx +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#ifndef INCLUDED_VCL_INC_OPENGL_X11_X11DEVICEINFO_HXX -#define INCLUDED_VCL_INC_OPENGL_X11_X11DEVICEINFO_HXX - -#include <rtl/string.hxx> - -class X11OpenGLDeviceInfo final -{ -private: - bool mbIsMesa; - bool mbIsNVIDIA; - bool mbIsFGLRX; - bool mbIsNouveau; - bool mbIsIntel; - bool mbIsOldSwrast; - bool mbIsLlvmpipe; - - OString maVendor; - OString maRenderer; - OString maVersion; - OString maOS; - OString maOSRelease; - - size_t mnGLMajorVersion; - size_t mnMajorVersion; - size_t mnMinorVersion; - size_t mnRevisionVersion; - - void GetData(); - -public: - X11OpenGLDeviceInfo(); - - bool isDeviceBlocked(); - -}; - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/inc/opengl/x11/glxtest.hxx b/vcl/inc/opengl/x11/glxtest.hxx deleted file mode 100644 index 5715a6d9fb19..000000000000 --- a/vcl/inc/opengl/x11/glxtest.hxx +++ /dev/null @@ -1,21 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#ifndef INCLUDED_VCL_INC_OPENGL_X11_GLXTEST_HXX -#define INCLUDED_VCL_INC_OPENGL_X11_GLXTEST_HXX - -#include <vcl/dllapi.h> - -VCL_DLLPUBLIC int* getGlxPipe(); - -VCL_DLLPUBLIC pid_t* getGlxPid(); - -#endif - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/opengl/OpenGLHelper.cxx b/vcl/source/opengl/OpenGLHelper.cxx index 5bd10ebf353d..a0dff4a5f567 100644 --- a/vcl/source/opengl/OpenGLHelper.cxx +++ b/vcl/source/opengl/OpenGLHelper.cxx @@ -37,13 +37,10 @@ #include <bitmap/BitmapWriteAccess.hxx> #include <watchdog.hxx> #include <vcl/skia/SkiaHelper.hxx> -#include <vcl/glxtestprocess.hxx> #include <salinst.hxx> #include <svdata.hxx> -#if USING_X11 -#include <opengl/x11/X11DeviceInfo.hxx> -#elif defined (_WIN32) +#if defined (_WIN32) #include <opengl/win/WinDeviceInfo.hxx> #endif @@ -756,11 +753,7 @@ bool OpenGLHelper::isDeviceDenylisted() { OpenGLZone aZone; -#if USING_X11 - X11OpenGLDeviceInfo aInfo; - bDenylisted = aInfo.isDeviceBlocked(); - SAL_INFO("vcl.opengl", "denylisted: " << bDenylisted); -#elif defined( _WIN32 ) +#if defined( _WIN32 ) WinOpenGLDeviceInfo aInfo; bDenylisted = aInfo.isDeviceBlocked(); diff --git a/vcl/source/opengl/x11/X11DeviceInfo.cxx b/vcl/source/opengl/x11/X11DeviceInfo.cxx deleted file mode 100644 index f7c979ef77e6..000000000000 --- a/vcl/source/opengl/x11/X11DeviceInfo.cxx +++ /dev/null @@ -1,363 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* - * This file is part of the LibreOffice project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -#include <opengl/x11/X11DeviceInfo.hxx> -#include <opengl/x11/glxtest.hxx> - -#include <config_features.h> - -#include <rtl/ustring.hxx> -#include <sal/log.hxx> - -#include <unistd.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <errno.h> -#include <sys/utsname.h> - -#include <desktop/crashreport.hxx> - -namespace glx { - -static int glxtest_pipe = 0; - -static pid_t glxtest_pid = 0; - -} - -pid_t* getGlxPid() -{ - return &glx::glxtest_pid; -} - -int* getGlxPipe() -{ - return &glx::glxtest_pipe; -} - -namespace { - -const char* -strspnp_wrapper(const char* aDelims, const char* aStr) -{ - const char* d; - do - { - for (d = aDelims; *d != '\0'; ++d) - { - if (*aStr == *d) - { - ++aStr; - break; - } - } - } while (*d); - - return aStr; -} - -char* strtok_wrapper(const char* aDelims, char** aStr) -{ - if (!*aStr) - { - return nullptr; - } - - char* ret = const_cast<char*>(strspnp_wrapper(aDelims, *aStr)); - - if (!*ret) - { - *aStr = ret; - return nullptr; - } - - char* i = ret; - do - { - for (const char* d = aDelims; *d != '\0'; ++d) - { - if (*i == *d) { - *i = '\0'; - *aStr = ++i; - return ret; - } - } - ++i; - } while (*i); - - *aStr = nullptr; - return ret; -} - -uint64_t version(uint32_t major, uint32_t minor, uint32_t revision = 0) -{ - return (uint64_t(major) << 32) + (uint64_t(minor) << 16) + uint64_t(revision); -} - -} - -X11OpenGLDeviceInfo::X11OpenGLDeviceInfo(): - mbIsMesa(false), - mbIsNVIDIA(false), - mbIsFGLRX(false), - mbIsNouveau(false), - mbIsIntel(false), - mbIsOldSwrast(false), - mbIsLlvmpipe(false), - mnGLMajorVersion(0), - mnMajorVersion(0), - mnMinorVersion(0), - mnRevisionVersion(0) -{ - GetData(); -} - -void X11OpenGLDeviceInfo::GetData() -{ - if (!glx::glxtest_pipe) - return; - - // to understand this function, see bug moz#639842. We retrieve the OpenGL driver information in a - // separate process to protect against bad drivers. - enum { buf_size = 1024 }; - char buf[buf_size]; - ssize_t bytesread = read(glx::glxtest_pipe, - &buf, - buf_size-1); // -1 because we'll append a zero - close(glx::glxtest_pipe); - glx::glxtest_pipe = 0; - - // bytesread < 0 would mean that the above read() call failed. - // This should never happen. If it did, the outcome would be to denylist anyway. - if (bytesread < 0) - bytesread = 0; - - // let buf be a zero-terminated string - buf[bytesread] = 0; - - // Wait for the glxtest process to finish. This serves 2 purposes: - // * avoid having a zombie glxtest process laying around - // * get the glxtest process status info. - int glxtest_status = 0; - bool wait_for_glxtest_process = true; - bool waiting_for_glxtest_process_failed = false; - int waitpid_errno = 0; - while(wait_for_glxtest_process) - { - wait_for_glxtest_process = false; - if (waitpid(glx::glxtest_pid, &glxtest_status, 0) == -1) - { - waitpid_errno = errno; - if (waitpid_errno == EINTR) - { - wait_for_glxtest_process = true; - } - else - { - // Bug moz#718629 - // ECHILD happens when the glxtest process got reaped got reaped after a PR_CreateProcess - // as per bug moz#227246. This shouldn't matter, as we still seem to get the data - // from the pipe, and if we didn't, the outcome would be to denylist anyway. - waiting_for_glxtest_process_failed = (waitpid_errno != ECHILD); - } - } - } - - bool exited_with_error_code = !waiting_for_glxtest_process_failed && - WIFEXITED(glxtest_status) && - WEXITSTATUS(glxtest_status) != EXIT_SUCCESS; - bool received_signal = !waiting_for_glxtest_process_failed && - WIFSIGNALED(glxtest_status); - - bool error = waiting_for_glxtest_process_failed || exited_with_error_code || received_signal; - - OString textureFromPixmap; - OString *stringToFill = nullptr; - char *bufptr = buf; - if (!error) - { - while(true) - { - char *line = strtok_wrapper("\n", &bufptr); - if (!line) - break; - if (stringToFill) { - *stringToFill = OString(line); - stringToFill = nullptr; - } - else if(!strcmp(line, "VENDOR")) - stringToFill = &maVendor; - else if(!strcmp(line, "RENDERER")) - stringToFill = &maRenderer; - else if(!strcmp(line, "VERSION")) - stringToFill = &maVersion; - else if(!strcmp(line, "TFP")) - stringToFill = &textureFromPixmap; - } - } - - // only useful for Linux kernel version check for FGLRX driver. - // assumes X client == X server, which is sad. - struct utsname unameobj; - if (!uname(&unameobj)) - { - maOS = OString(unameobj.sysname); - maOSRelease = OString(unameobj.release); - } - - // determine the major OpenGL version. That's the first integer in the version string. - mnGLMajorVersion = strtol(maVersion.getStr(), nullptr, 10); - - // determine driver type (vendor) and where in the version string - // the actual driver version numbers should be expected to be found (whereToReadVersionNumbers) - const char *whereToReadVersionNumbers = nullptr; - const char *Mesa_in_version_string = strstr(maVersion.getStr(), "Mesa"); - if (Mesa_in_version_string) - { - mbIsMesa = true; - // with Mesa, the version string contains "Mesa major.minor" and that's all the version information we get: - // there is no actual driver version info. - whereToReadVersionNumbers = Mesa_in_version_string + strlen("Mesa"); - if (strcasestr(maVendor.getStr(), "nouveau")) - mbIsNouveau = true; - if (strcasestr(maRenderer.getStr(), "intel")) // yes, intel is in the renderer string - mbIsIntel = true; - if (strcasestr(maRenderer.getStr(), "llvmpipe")) - mbIsLlvmpipe = true; - if (strcasestr(maRenderer.getStr(), "software rasterizer")) - mbIsOldSwrast = true; - } - else if (strstr(maVendor.getStr(), "NVIDIA Corporation")) - { - mbIsNVIDIA = true; - // with the NVIDIA driver, the version string contains "NVIDIA major.minor" - // note that here the vendor and version strings behave differently, that's why we don't put this above - // alongside Mesa_in_version_string. - const char *NVIDIA_in_version_string = strstr(maVersion.getStr(), "NVIDIA"); - if (NVIDIA_in_version_string) - whereToReadVersionNumbers = NVIDIA_in_version_string + strlen("NVIDIA"); - } - else if (strstr(maVendor.getStr(), "ATI Technologies Inc")) - { - mbIsFGLRX = true; - // with the FGLRX driver, the version string only gives an OpenGL version: so let's return that. - // that can at least give a rough idea of how old the driver is. - whereToReadVersionNumbers = maVersion.getStr(); - } - - // read major.minor version numbers of the driver (not to be confused with the OpenGL version) - if (!whereToReadVersionNumbers) - return; - - // copy into writable buffer, for tokenization - strncpy(buf, whereToReadVersionNumbers, buf_size-1); - buf[buf_size-1] = 0; - bufptr = buf; - - // now try to read major.minor version numbers. In case of failure, gracefully exit: these numbers have - // been initialized as 0 anyways - char *token = strtok_wrapper(".", &bufptr); - if (token) - { - mnMajorVersion = strtol(token, nullptr, 10); - token = strtok_wrapper(".", &bufptr); - if (token) - { - mnMinorVersion = strtol(token, nullptr, 10); - token = strtok_wrapper(".", &bufptr); - if (token) - mnRevisionVersion = strtol(token, nullptr, 10); - } - } -} - -bool X11OpenGLDeviceInfo::isDeviceBlocked() -{ - // don't even try to use OpenGL 1.x - if (mnGLMajorVersion == 1) - return true; - - CrashReporter::addKeyValue("AdapterVendorId", OStringToOUString(maVendor, RTL_TEXTENCODING_UTF8), CrashReporter::AddItem); - CrashReporter::addKeyValue("AdapterDeviceId", OStringToOUString(maRenderer, RTL_TEXTENCODING_UTF8), CrashReporter::Write); - - SAL_INFO("vcl.opengl", "Vendor: " << maVendor); - SAL_INFO("vcl.opengl", "Renderer: " << maRenderer); - SAL_INFO("vcl.opengl", "Version: " << maVersion); - SAL_INFO("vcl.opengl", "OS: " << maOS); - SAL_INFO("vcl.opengl", "OSRelease: " << maOSRelease); - - if (mbIsMesa) - { - if (mbIsNouveau && version(mnMajorVersion, mnMinorVersion) < version(8,0)) - { - SAL_WARN("vcl.opengl", "blocked driver version: old nouveau driver (requires mesa 8.0+)"); - return true; - } - else if (version(mnMajorVersion, mnMinorVersion, mnRevisionVersion) < version(7,10,3)) - { - SAL_WARN("vcl.opengl", "blocked driver version: requires at least mesa 7.10.3"); - return true; - } - else if (mbIsIntel && version(mnMajorVersion, mnMinorVersion, mnRevisionVersion) == version(9,0,2)) - { - SAL_WARN("vcl.opengl", "blocked driver version: my broken intel driver Mesa 9.0.2"); - return true; - } - else if (mbIsOldSwrast) - { - SAL_WARN("vcl.opengl", "blocked driver version: software rasterizer"); - return true; - } - else if (mbIsLlvmpipe && version(mnMajorVersion, mnMinorVersion) < version(9, 1)) - { - // bug moz#791905, Mesa bug 57733, fixed in Mesa 9.1 according to - // https://bugs.freedesktop.org/show_bug.cgi?id=57733#c3 - SAL_WARN("vcl.opengl", "blocked driver version: fdo#57733"); - return true; - } - } - else if (mbIsNVIDIA) - { - if (version(mnMajorVersion, mnMinorVersion, mnRevisionVersion) < version(257,21)) - { - SAL_WARN("vcl.opengl", "blocked driver version: nvidia requires at least 257.21"); - return true; - } - } - else if (mbIsFGLRX) - { - // FGLRX does not report a driver version number, so we have the OpenGL version instead. - // by requiring OpenGL 3, we effectively require recent drivers. - if (version(mnMajorVersion, mnMinorVersion, mnRevisionVersion) < version(3, 0)) - { - SAL_WARN("vcl.opengl", "blocked driver version: require at least OpenGL 3 for fglrx"); - return true; - } - // Bug moz#724640: FGLRX + Linux 2.6.32 is a crashy combo - bool unknownOS = maOS.isEmpty() || maOSRelease.isEmpty(); - bool badOS = maOS.indexOf("Linux") != -1 && - maOSRelease.indexOf("2.6.32") != -1; - if (unknownOS || badOS) - { - SAL_WARN("vcl.opengl", "blocked OS version with fglrx"); - return true; - } - } - else - { - // like on windows, let's block unknown vendors. Think of virtual machines. - // Also, this case is hit whenever the GLXtest probe failed to get driver info or crashed. - SAL_WARN("vcl.opengl", "unknown vendor => blocked"); - return true; - } - - return false; -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/salmain/salmain.cxx b/vcl/source/salmain/salmain.cxx index 06349efac5dd..721ae910f10a 100644 --- a/vcl/source/salmain/salmain.cxx +++ b/vcl/source/salmain/salmain.cxx @@ -22,13 +22,11 @@ #include <sal/main.h> #include <tools/extendapplicationenvironment.hxx> -#include <vcl/glxtestprocess.hxx> #include <vcl/vclmain.hxx> #include <vcl/svmain.hxx> SAL_IMPLEMENT_MAIN() { - fire_glxtest_process(); tools::extendApplicationEnvironment(); vclmain::createApplication(); return SVMain(); diff --git a/vcl/unx/glxtest.cxx b/vcl/unx/glxtest.cxx deleted file mode 100644 index b3c6a7521de7..000000000000 --- a/vcl/unx/glxtest.cxx +++ /dev/null @@ -1,294 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: sw=2 ts=8 et : - */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -////////////////////////////////////////////////////////////////////////////// -// -// Explanation: See bug 639842. Safely getting GL driver info on X11 is hard, because the only way to do -// that is to create a GL context and call glGetString(), but with bad drivers, -// just creating a GL context may crash. -// -// This file implements the idea to do that in a separate process. -// -// The only non-static function here is fire_glxtest_process(). It creates a pipe, publishes its 'read' end as the -// mozilla::widget::glxtest_pipe global variable, forks, and runs that GLX probe in the child process, -// which runs the glxtest() static function. This creates a X connection, a GLX context, calls glGetString, and writes that -// to the 'write' end of the pipe. - -#include <cstdio> -#include <cstdlib> -#include <unistd.h> -#include <dlfcn.h> -#include <fcntl.h> -#include <stdint.h> -#include <string.h> -#include <signal.h> - -#include <sys/wait.h> - -#include <opengl/x11/glxtest.hxx> - -#ifdef __SUNPRO_CC -#include <stdio.h> -#endif - -#include <X11/Xlib.h> -#include <X11/Xutil.h> - -#include <sal/log.hxx> -#include <vcl/glxtestprocess.hxx> - -// stuff from glx.h -typedef struct __GLXcontextRec *GLXContext; -typedef XID GLXPixmap; -typedef XID GLXDrawable; -/* GLX 1.3 and later */ -typedef struct __GLXFBConfigRec *GLXFBConfig; -#define GLX_RGBA 4 -#define GLX_RED_SIZE 8 -#define GLX_GREEN_SIZE 9 -#define GLX_BLUE_SIZE 10 - -// stuff from gl.h -typedef uint8_t GLubyte; -typedef uint32_t GLenum; -#define GL_VENDOR 0x1F00 -#define GL_RENDERER 0x1F01 -#define GL_VERSION 0x1F02 - -// the write end of the pipe, which we're going to write to -static int write_end_of_the_pipe = -1; - -// C++ standard collides with C standard in that it doesn't allow casting void* to function pointer types. -// So the work-around is to convert first to size_t. -// http://www.trilithium.com/johan/2004/12/problem-with-dlsym/ -template<typename func_ptr_type> -static func_ptr_type cast(void *ptr) -{ - return reinterpret_cast<func_ptr_type>( - reinterpret_cast<size_t>(ptr) - ); -} - -static void fatal_error(const char *str) -{ - int length = strlen(str); - if (write(write_end_of_the_pipe, str, length) != length - || write(write_end_of_the_pipe, "\n", 1) != 1) - { - /* Cannot write to pipe. Fall through to call _exit */ - } - _exit(EXIT_FAILURE); -} - -static int -x_error_handler(Display *, XErrorEvent *ev) -{ - enum { bufsize = 1024 }; - char buf[bufsize]; - int length = snprintf(buf, bufsize, - "X error occurred in GLX probe, error_code=%d, request_code=%d, minor_code=%d\n", - ev->error_code, - ev->request_code, - ev->minor_code); - if (write(write_end_of_the_pipe, buf, length) != length) - { - /* Cannot write to pipe. Fall through to call _exit */ - } - _exit(EXIT_FAILURE); - return 0; -} - -static void glxtest() -{ - signal(SIGPIPE, SIG_IGN); - // we want to redirect to /dev/null stdout, stderr, and while we're at it, - // any PR logging file descriptors. To that effect, we redirect all positive - // file descriptors up to what open() returns here. In particular, 1 is stdout and 2 is stderr. - int fd = open("/dev/null", O_WRONLY); - if (fd == -1) - fatal_error("could not redirect stdout+stderr"); - for (int i = 1; i < fd; i++) - dup2(fd, i); - close(fd); - - ///// Open libGL and load needed symbols ///// -#ifdef __OpenBSD__ - #define LIBGL_FILENAME "libGL.so" -#else - #define LIBGL_FILENAME "libGL.so.1" -#endif - void *libgl = dlopen(LIBGL_FILENAME, RTLD_LAZY); - if (!libgl) - fatal_error("Unable to load " LIBGL_FILENAME); - - typedef void* (* PFNGLXGETPROCADDRESS) (const char *); - PFNGLXGETPROCADDRESS glXGetProcAddress = cast<PFNGLXGETPROCADDRESS>(dlsym(libgl, "glXGetProcAddress")); - - if (!glXGetProcAddress) - fatal_error("Unable to find glXGetProcAddress in " LIBGL_FILENAME); - - typedef GLXFBConfig* (* PFNGLXQUERYEXTENSION) (Display *, int *, int *); - PFNGLXQUERYEXTENSION glXQueryExtension = cast<PFNGLXQUERYEXTENSION>(glXGetProcAddress("glXQueryExtension")); - - typedef GLXFBConfig* (* PFNGLXQUERYVERSION) (Display *, int *, int *); - PFNGLXQUERYVERSION glXQueryVersion = cast<PFNGLXQUERYVERSION>(dlsym(libgl, "glXQueryVersion")); - - typedef XVisualInfo* (* PFNGLXCHOOSEVISUAL) (Display *, int, int *); - PFNGLXCHOOSEVISUAL glXChooseVisual = cast<PFNGLXCHOOSEVISUAL>(glXGetProcAddress("glXChooseVisual")); - - typedef GLXContext (* PFNGLXCREATECONTEXT) (Display *, XVisualInfo *, GLXContext, Bool); - PFNGLXCREATECONTEXT glXCreateContext = cast<PFNGLXCREATECONTEXT>(glXGetProcAddress("glXCreateContext")); - - typedef Bool (* PFNGLXMAKECURRENT) (Display*, GLXDrawable, GLXContext); - PFNGLXMAKECURRENT glXMakeCurrent = cast<PFNGLXMAKECURRENT>(glXGetProcAddress("glXMakeCurrent")); - - typedef void (* PFNGLXDESTROYCONTEXT) (Display*, GLXContext); - PFNGLXDESTROYCONTEXT glXDestroyContext = cast<PFNGLXDESTROYCONTEXT>(glXGetProcAddress("glXDestroyContext")); - - typedef GLubyte* (* PFNGLGETSTRING) (GLenum); - PFNGLGETSTRING glGetString = cast<PFNGLGETSTRING>(glXGetProcAddress("glGetString")); - - if (!glXQueryExtension || - !glXQueryVersion || - !glXChooseVisual || - !glXCreateContext || - !glXMakeCurrent || - !glXDestroyContext || - !glGetString) - { - fatal_error("glXGetProcAddress couldn't find required functions"); - } - ///// Open a connection to the X server ///// - Display *dpy = XOpenDisplay(nullptr); - if (!dpy) - fatal_error("Unable to open a connection to the X server"); - - ///// Check that the GLX extension is present ///// - if (!glXQueryExtension(dpy, nullptr, nullptr)) - fatal_error("GLX extension missing"); - - XSetErrorHandler(x_error_handler); - - ///// Get a visual ///// - int attribs[] = { - GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - None }; - XVisualInfo *vInfo = glXChooseVisual(dpy, DefaultScreen(dpy), attribs); - if (!vInfo) - fatal_error("No visuals found"); - - // using a X11 Window instead of a GLXPixmap does not crash - // fglrx in indirect rendering. bug 680644 - Window window; - XSetWindowAttributes swa; - swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vInfo->screen), - vInfo->visual, AllocNone); - - swa.border_pixel = 0; - window = XCreateWindow(dpy, RootWindow(dpy, vInfo->screen), - 0, 0, 16, 16, - 0, vInfo->depth, InputOutput, vInfo->visual, - CWBorderPixel | CWColormap, &swa); - - ///// Get a GL context and make it current ////// - GLXContext context = glXCreateContext(dpy, vInfo, nullptr, True); - glXMakeCurrent(dpy, window, context); - - ///// Look for this symbol to determine texture_from_pixmap support ///// - void* glXBindTexImageEXT = glXGetProcAddress("glXBindTexImageEXT"); - - ///// Get GL vendor/renderer/versions strings ///// - enum { bufsize = 1024 }; - char buf[bufsize]; - const GLubyte *vendorString = glGetString(GL_VENDOR); - const GLubyte *rendererString = glGetString(GL_RENDERER); - const GLubyte *versionString = glGetString(GL_VERSION); - - if (!vendorString || !rendererString || !versionString) - fatal_error("glGetString returned null"); - - int length = snprintf(buf, bufsize, - "VENDOR\n%s\nRENDERER\n%s\nVERSION\n%s\nTFP\n%s\n", - vendorString, - rendererString, - versionString, - glXBindTexImageEXT ? "TRUE" : "FALSE"); - if (length >= bufsize) - fatal_error("GL strings length too large for buffer size"); - - ///// Clean up. Indeed, the parent process might fail to kill us (e.g. if it doesn't need to check GL info) - ///// so we might be staying alive for longer than expected, so it's important to consume as little memory as - ///// possible. Also we want to check that we're able to do that too without generating X errors. - glXMakeCurrent(dpy, None, nullptr); // must release the GL context before destroying it - glXDestroyContext(dpy, context); - XDestroyWindow(dpy, window); - XFreeColormap(dpy, swa.colormap); - XFree(vInfo); - -#ifdef NS_FREE_PERMANENT_DATA // conditionally defined in nscore.h, don't forget to #include it above - XCloseDisplay(dpy); -#else - // This XSync call wanted to be instead: - // XCloseDisplay(dpy); - // but this can cause 1-minute stalls on certain setups using Nouveau, see bug 973192 - XSync(dpy, False); -#endif - - dlclose(libgl); - - ///// Finally write data to the pipe - if (write(write_end_of_the_pipe, buf, length) != length) - fatal_error("Could not write to pipe"); -} - -/** \returns true in the child glxtest process, false in the parent process */ -bool fire_glxtest_process() -{ - int pfd[2]; - if (pipe(pfd) == -1) { - perror("pipe"); - return false; - } - pid_t pid = fork(); - if (pid < 0) { - perror("fork"); - close(pfd[0]); - close(pfd[1]); - return false; - } - // The child exits early to avoid running the full shutdown sequence and avoid conflicting with threads - // we have already spawned (like the profiler). - if (pid == 0) { - close(pfd[0]); - write_end_of_the_pipe = pfd[1]; - glxtest(); - close(pfd[1]); - _exit(0); - } - - close(pfd[1]); - int* glxtest_pipe = getGlxPipe(); - *glxtest_pipe = pfd[0]; - pid_t* glxtest_pid = getGlxPid(); - *glxtest_pid = pid; - return true; -} - -void reap_glxtest_process() { - pid_t * pid = getGlxPid(); - if (*pid != 0) { - // Use WNOHANG, as it is probably better to have a (rather harmless) zombie child process - // hanging around for the duration of the calling process, than to potentially block the - // calling process here: - pid_t e = waitpid(*pid, nullptr, WNOHANG); - SAL_INFO_IF( - e <= 0, "vcl.opengl", "waiting for glxtest process " << *pid << " failed with " << e); - } -} |