Commit cc068e93 by Corentin Wallez Committed by Commit Bot

Add DisplayGL::getDriverVersion and implementation on Linux NVIDIA

Some GPU driver bug workarounds should be active only for specific driver version ranges. This adds NVIDIA Linux driver detection using the XNVCtrl X11 extension. BUG=590870 Change-Id: I8cbf692a0c8a6da7473169f29d720bdc2d07663d Reviewed-on: https://chromium-review.googlesource.com/329637Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
parent bc4c4bc5
...@@ -254,6 +254,13 @@ static_library("libANGLE") { ...@@ -254,6 +254,13 @@ static_library("libANGLE") {
libs = [] libs = []
defines = [ "LIBANGLE_IMPLEMENTATION" ] defines = [ "LIBANGLE_IMPLEMENTATION" ]
deps = [
":angle_common",
":commit_id",
":includes",
":translator_static",
]
# Shared D3D sources. # Shared D3D sources.
if (angle_enable_d3d9 || angle_enable_d3d11) { if (angle_enable_d3d9 || angle_enable_d3d11) {
sources += rebase_path(gles_gypi.libangle_d3d_shared_sources, ".", "src") sources += rebase_path(gles_gypi.libangle_d3d_shared_sources, ".", "src")
...@@ -281,7 +288,14 @@ static_library("libANGLE") { ...@@ -281,7 +288,14 @@ static_library("libANGLE") {
} }
if (use_x11) { if (use_x11) {
sources += rebase_path(gles_gypi.libangle_gl_glx_sources, ".", "src") sources += rebase_path(gles_gypi.libangle_gl_glx_sources, ".", "src")
libs += [ "X11" ] deps += [
"src/third_party/libXNVCtrl:libXNVCtrl"
]
libs += [
"X11",
"Xi",
"Xext",
]
} }
} }
...@@ -298,13 +312,6 @@ static_library("libANGLE") { ...@@ -298,13 +312,6 @@ static_library("libANGLE") {
"//build/config/compiler:no_chromium_code", "//build/config/compiler:no_chromium_code",
] ]
deps = [
":angle_common",
":commit_id",
":includes",
":translator_static",
]
if (is_win) { if (is_win) {
deps += [ ":copy_compiler_dll" ] deps += [ ":copy_compiler_dll" ]
} }
......
...@@ -36,6 +36,8 @@ class DisplayGL : public DisplayImpl ...@@ -36,6 +36,8 @@ class DisplayGL : public DisplayImpl
egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) override; egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) override;
virtual egl::Error getDriverVersion(std::string *version) const = 0;
protected: protected:
RendererGL *getRenderer() const { return mRenderer; }; RendererGL *getRenderer() const { return mRenderer; };
const gl::Version &getMaxSupportedESVersion() const; const gl::Version &getMaxSupportedESVersion() const;
......
...@@ -55,6 +55,8 @@ class DisplayCGL : public DisplayGL ...@@ -55,6 +55,8 @@ class DisplayCGL : public DisplayGL
egl::Surface *drawSurface, egl::Surface *drawSurface,
egl::Surface *readSurface) const override; egl::Surface *readSurface) const override;
egl::Error getDriverVersion(std::string *version) const override;
private: private:
const FunctionsGL *getFunctionsGL() const override; const FunctionsGL *getFunctionsGL() const override;
......
...@@ -269,4 +269,10 @@ egl::Error DisplayCGL::waitNative(EGLint engine, ...@@ -269,4 +269,10 @@ egl::Error DisplayCGL::waitNative(EGLint engine,
// TODO(cwallez) UNIMPLEMENTED() // TODO(cwallez) UNIMPLEMENTED()
return egl::Error(EGL_SUCCESS); return egl::Error(EGL_SUCCESS);
} }
egl::Error DisplayCGL::getDriverVersion(std::string *version) const
{
*version = "";
return egl::Error(EGL_SUCCESS);
}
} }
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#include "libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h" #include "libANGLE/renderer/gl/glx/PbufferSurfaceGLX.h"
#include "libANGLE/renderer/gl/glx/WindowSurfaceGLX.h" #include "libANGLE/renderer/gl/glx/WindowSurfaceGLX.h"
#include "libANGLE/renderer/gl/renderergl_utils.h" #include "libANGLE/renderer/gl/renderergl_utils.h"
#include "third_party/libXNVCtrl/NVCtrl.h"
#include "third_party/libXNVCtrl/NVCtrlLib.h"
namespace rx namespace rx
{ {
...@@ -70,6 +72,7 @@ DisplayGLX::DisplayGLX() ...@@ -70,6 +72,7 @@ DisplayGLX::DisplayGLX()
mMinSwapInterval(0), mMinSwapInterval(0),
mMaxSwapInterval(0), mMaxSwapInterval(0),
mCurrentSwapInterval(-1), mCurrentSwapInterval(-1),
mXDisplay(nullptr),
mEGLDisplay(nullptr) mEGLDisplay(nullptr)
{ {
} }
...@@ -81,24 +84,24 @@ DisplayGLX::~DisplayGLX() ...@@ -81,24 +84,24 @@ DisplayGLX::~DisplayGLX()
egl::Error DisplayGLX::initialize(egl::Display *display) egl::Error DisplayGLX::initialize(egl::Display *display)
{ {
mEGLDisplay = display; mEGLDisplay = display;
Display *xDisplay = display->getNativeDisplayId(); mXDisplay = display->getNativeDisplayId();
const auto &attribMap = display->getAttributeMap(); const auto &attribMap = display->getAttributeMap();
// ANGLE_platform_angle allows the creation of a default display // ANGLE_platform_angle allows the creation of a default display
// using EGL_DEFAULT_DISPLAY (= nullptr). In this case just open // using EGL_DEFAULT_DISPLAY (= nullptr). In this case just open
// the display specified by the DISPLAY environment variable. // the display specified by the DISPLAY environment variable.
if (xDisplay == EGL_DEFAULT_DISPLAY) if (mXDisplay == EGL_DEFAULT_DISPLAY)
{ {
mUsesNewXDisplay = true; mUsesNewXDisplay = true;
xDisplay = XOpenDisplay(NULL); mXDisplay = XOpenDisplay(NULL);
if (!xDisplay) if (!mXDisplay)
{ {
return egl::Error(EGL_NOT_INITIALIZED, "Could not open the default X display."); return egl::Error(EGL_NOT_INITIALIZED, "Could not open the default X display.");
} }
} }
std::string glxInitError; std::string glxInitError;
if (!mGLX.initialize(xDisplay, DefaultScreen(xDisplay), &glxInitError)) if (!mGLX.initialize(mXDisplay, DefaultScreen(mXDisplay), &glxInitError))
{ {
return egl::Error(EGL_NOT_INITIALIZED, glxInitError.c_str()); return egl::Error(EGL_NOT_INITIALIZED, glxInitError.c_str());
} }
...@@ -235,7 +238,8 @@ egl::Error DisplayGLX::initialize(egl::Display *display) ...@@ -235,7 +238,8 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
visualTemplate.visualid = getGLXFBConfigAttrib(mContextConfig, GLX_VISUAL_ID); visualTemplate.visualid = getGLXFBConfigAttrib(mContextConfig, GLX_VISUAL_ID);
int numVisuals = 0; int numVisuals = 0;
XVisualInfo *visuals = XGetVisualInfo(xDisplay, VisualIDMask, &visualTemplate, &numVisuals); XVisualInfo *visuals =
XGetVisualInfo(mXDisplay, VisualIDMask, &visualTemplate, &numVisuals);
if (numVisuals <= 0) if (numVisuals <= 0)
{ {
return egl::Error(EGL_NOT_INITIALIZED, return egl::Error(EGL_NOT_INITIALIZED,
...@@ -301,6 +305,9 @@ egl::Error DisplayGLX::initialize(egl::Display *display) ...@@ -301,6 +305,9 @@ egl::Error DisplayGLX::initialize(egl::Display *display)
reinterpret_cast<const char*>(mFunctionsGL->getString(GL_RENDERER)); reinterpret_cast<const char*>(mFunctionsGL->getString(GL_RENDERER));
mIsMesa = rendererString.find("Mesa") != std::string::npos; mIsMesa = rendererString.find("Mesa") != std::string::npos;
std::string version;
getDriverVersion(&version);
return DisplayGL::initialize(display); return DisplayGL::initialize(display);
} }
...@@ -711,6 +718,20 @@ egl::Error DisplayGLX::waitClient() const ...@@ -711,6 +718,20 @@ egl::Error DisplayGLX::waitClient() const
return egl::Error(EGL_SUCCESS); return egl::Error(EGL_SUCCESS);
} }
egl::Error DisplayGLX::getDriverVersion(std::string *version) const
{
VendorID vendor = GetVendorID(mFunctionsGL);
switch (vendor)
{
case VENDOR_ID_NVIDIA:
return getNVIDIADriverVersion(version);
default:
*version = "";
return egl::Error(EGL_SUCCESS);
}
}
egl::Error DisplayGLX::waitNative(EGLint engine, egl::Error DisplayGLX::waitNative(EGLint engine,
egl::Surface *drawSurface, egl::Surface *drawSurface,
egl::Surface *readSurface) const egl::Surface *readSurface) const
...@@ -859,4 +880,29 @@ egl::Error DisplayGLX::createContextAttribs(glx::FBConfig, ...@@ -859,4 +880,29 @@ egl::Error DisplayGLX::createContextAttribs(glx::FBConfig,
} }
return egl::Error(EGL_SUCCESS); return egl::Error(EGL_SUCCESS);
} }
egl::Error DisplayGLX::getNVIDIADriverVersion(std::string *version) const
{
*version = "";
int eventBase = 0;
int errorBase = 0;
if (XNVCTRLQueryExtension(mXDisplay, &eventBase, &errorBase))
{
int screenCount = ScreenCount(mXDisplay);
for (int screen = 0; screen < screenCount; ++screen)
{
char *buffer = nullptr;
if (XNVCTRLIsNvScreen(mXDisplay, screen) &&
XNVCTRLQueryStringAttribute(mXDisplay, screen, 0,
NV_CTRL_STRING_NVIDIA_DRIVER_VERSION, &buffer))
{
*version = buffer;
XFree(buffer);
}
}
}
return egl::Error(EGL_SUCCESS);
}
} }
...@@ -72,6 +72,8 @@ class DisplayGLX : public DisplayGL ...@@ -72,6 +72,8 @@ class DisplayGLX : public DisplayGL
egl::Surface *drawSurface, egl::Surface *drawSurface,
egl::Surface *readSurface) const override; egl::Surface *readSurface) const override;
egl::Error getDriverVersion(std::string *version) const override;
// Synchronizes with the X server, if the display has been opened by ANGLE. // Synchronizes with the X server, if the display has been opened by ANGLE.
// Calling this is required at the end of every functions that does buffered // Calling this is required at the end of every functions that does buffered
// X calls (not for glX calls) otherwise there might be race conditions // X calls (not for glX calls) otherwise there might be race conditions
...@@ -102,6 +104,8 @@ class DisplayGLX : public DisplayGL ...@@ -102,6 +104,8 @@ class DisplayGLX : public DisplayGL
int profileMask, int profileMask,
glx::Context *context) const; glx::Context *context) const;
egl::Error getNVIDIADriverVersion(std::string *version) const;
FunctionsGL *mFunctionsGL; FunctionsGL *mFunctionsGL;
//TODO(cwallez) yuck, change generateConfigs to be non-const or add a userdata member to egl::Config? //TODO(cwallez) yuck, change generateConfigs to be non-const or add a userdata member to egl::Config?
...@@ -133,6 +137,7 @@ class DisplayGLX : public DisplayGL ...@@ -133,6 +137,7 @@ class DisplayGLX : public DisplayGL
int mCurrentSwapInterval; int mCurrentSwapInterval;
FunctionsGLX mGLX; FunctionsGLX mGLX;
Display *mXDisplay;
egl::Display *mEGLDisplay; egl::Display *mEGLDisplay;
}; };
......
...@@ -30,6 +30,7 @@ class FunctionsGL; ...@@ -30,6 +30,7 @@ class FunctionsGL;
struct WorkaroundsGL; struct WorkaroundsGL;
VendorID GetVendorID(const FunctionsGL *functions); VendorID GetVendorID(const FunctionsGL *functions);
std::string GetDriverVersion(const FunctionsGL *functions);
namespace nativegl_gl namespace nativegl_gl
{ {
......
...@@ -641,6 +641,12 @@ egl::Error DisplayWGL::waitNative(EGLint engine, ...@@ -641,6 +641,12 @@ egl::Error DisplayWGL::waitNative(EGLint engine,
return egl::Error(EGL_SUCCESS); return egl::Error(EGL_SUCCESS);
} }
egl::Error DisplayWGL::getDriverVersion(std::string *version) const
{
*version = "";
return egl::Error(EGL_SUCCESS);
}
egl::Error DisplayWGL::registerD3DDevice(IUnknown *device, HANDLE *outHandle) egl::Error DisplayWGL::registerD3DDevice(IUnknown *device, HANDLE *outHandle)
{ {
ASSERT(device != nullptr); ASSERT(device != nullptr);
......
...@@ -57,6 +57,8 @@ class DisplayWGL : public DisplayGL ...@@ -57,6 +57,8 @@ class DisplayWGL : public DisplayGL
egl::Surface *drawSurface, egl::Surface *drawSurface,
egl::Surface *readSurface) const override; egl::Surface *readSurface) const override;
egl::Error getDriverVersion(std::string *version) const override;
egl::Error registerD3DDevice(IUnknown *device, HANDLE *outHandle); egl::Error registerD3DDevice(IUnknown *device, HANDLE *outHandle);
void releaseD3DDevice(HANDLE handle); void releaseD3DDevice(HANDLE handle);
......
...@@ -613,7 +613,7 @@ ...@@ -613,7 +613,7 @@
'defines': 'defines':
[ [
'ANGLE_USE_X11', 'ANGLE_USE_X11',
] ],
}], }],
], ],
}], }],
...@@ -732,16 +732,20 @@ ...@@ -732,16 +732,20 @@
[ [
'ANGLE_USE_X11', 'ANGLE_USE_X11',
], ],
'dependencies':
[
'<(angle_path)/src/third_party/libXNVCtrl/libXNVCtrl.gyp:libXNVCtrl',
],
'sources': 'sources':
[ [
'<@(libangle_gl_glx_sources)', '<@(libangle_gl_glx_sources)',
], ],
'link_settings': { 'link_settings': {
'ldflags': [ 'ldflags': [
'<!@(<(pkg-config) --libs-only-L --libs-only-other x11 xi)', '<!@(<(pkg-config) --libs-only-L --libs-only-other x11 xi xext)',
], ],
'libraries': [ 'libraries': [
'<!@(<(pkg-config) --libs-only-l x11 xi) -ldl', '<!@(<(pkg-config) --libs-only-l x11 xi xext) -ldl',
], ],
}, },
}], }],
......
# Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
static_library("libXNVCtrl") {
sources = [
"NVCtrl.c",
"NVCtrl.h",
"NVCtrlLib.h",
"nv_control.h",
]
}
/*
* Copyright (c) 2008 NVIDIA, Corporation
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
Name: NVidia Control X Extension Library
Short Name: libXNVCtrl
URL: http://cgit.freedesktop.org/~aplattner/nvidia-settings/
Version: unknown
Date: 2008
License: MIT
Security Critical: no
Description:
This package provides access to NVidia Control X Extension. It is used to determine the version of the NVIDIA driver in use.
The current version is pulled from nvidia-settings-302.17.
Local Modifications:
# Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
{
'targets':
[{
'target_name': 'libXNVCtrl',
'type': 'static_library',
'sources':
[
'NVCtrl.c',
'NVCtrl.h',
'NVCtrlLib.h',
'nv_control.h',
],
}],
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment