author | Iris Hsiao <ihsiao@mozilla.com> |
Wed, 21 Sep 2016 14:24:26 +0800 | |
changeset 314690 | e2d2897e4a7449759267bf168e6b37f7b8c3a94b |
parent 314689 | 016f24cec86ee68e1323a9d350a9788519d3f175 |
child 314718 | aab7170a601df4f1d62e0c3357d6b62201d507f8 |
child 314797 | b81f295675f89c940a27bc5207d6fe63ecfb7a3c |
push id | 81947 |
push user | cbook@mozilla.com |
push date | Wed, 21 Sep 2016 10:08:07 +0000 |
treeherder | mozilla-inbound@a1bbdaf0f9ca [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 1294232 |
milestone | 52.0a1 |
backs out | cf43cacdb26279b1c258ac9b06517f93ebb58056 |
first release with | nightly linux32
e2d2897e4a74
/
52.0a1
/
20160921030221
/
files
nightly linux64
e2d2897e4a74
/
52.0a1
/
20160921030221
/
files
nightly mac
e2d2897e4a74
/
52.0a1
/
20160921030221
/
files
nightly win32
e2d2897e4a74
/
52.0a1
/
20160921030221
/
files
nightly win64
e2d2897e4a74
/
52.0a1
/
20160921030221
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
52.0a1
/
20160921030221
/
pushlog to previous
nightly linux64
52.0a1
/
20160921030221
/
pushlog to previous
nightly mac
52.0a1
/
20160921030221
/
pushlog to previous
nightly win32
52.0a1
/
20160921030221
/
pushlog to previous
nightly win64
52.0a1
/
20160921030221
/
pushlog to previous
|
--- a/toolkit/xre/glxtest.cpp +++ b/toolkit/xre/glxtest.cpp @@ -57,30 +57,16 @@ typedef XID GLXPbuffer; // stuff from gl.h typedef uint8_t GLubyte; typedef uint32_t GLenum; #define GL_VENDOR 0x1F00 #define GL_RENDERER 0x1F01 #define GL_VERSION 0x1F02 -// GLX_MESA_query_renderer -#define GLX_RENDERER_VENDOR_ID_MESA 0x8183 -#define GLX_RENDERER_DEVICE_ID_MESA 0x8184 -#define GLX_RENDERER_VERSION_MESA 0x8185 -#define GLX_RENDERER_ACCELERATED_MESA 0x8186 -#define GLX_RENDERER_VIDEO_MEMORY_MESA 0x8187 -#define GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA 0x8188 -#define GLX_RENDERER_PREFERRED_PROFILE_MESA 0x8189 -#define GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA 0x818A -#define GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA 0x818B -#define GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA 0x818C -#define GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA 0x818D -#define GLX_RENDERER_ID_MESA 0x818E - namespace mozilla { namespace widget { // the read end of the pipe, which will be used by GfxInfo extern int glxtest_pipe; // the PID of the glxtest process, to pass to waitpid() extern pid_t glxtest_pid; } } @@ -261,75 +247,34 @@ void glxtest() ///// 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 = 2048 }; + enum { bufsize = 1024 }; char buf[bufsize]; + const GLubyte *vendorString = glGetString(GL_VENDOR); + const GLubyte *rendererString = glGetString(GL_RENDERER); + const GLubyte *versionString = glGetString(GL_VERSION); - const GLubyte* versionString = glGetString(GL_VERSION); - const GLubyte* vendorString = glGetString(GL_VENDOR); - const GLubyte* rendererString = glGetString(GL_RENDERER); - - if (!versionString || !vendorString || !rendererString) + 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"); - // If GLX_MESA_query_renderer is available, populate additional data. - typedef Bool (*PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC) (int attribute, unsigned int* value); - PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC glXQueryCurrentRendererIntegerMESAProc = - cast<PFNGLXQUERYCURRENTRENDERERINTEGERMESAPROC>(glXGetProcAddress("glXQueryCurrentRendererIntegerMESA")); - if (glXQueryCurrentRendererIntegerMESAProc) { - unsigned int vendorId, deviceId, accelerated, videoMemoryMB; - glXQueryCurrentRendererIntegerMESAProc(GLX_RENDERER_VENDOR_ID_MESA, &vendorId); - glXQueryCurrentRendererIntegerMESAProc(GLX_RENDERER_DEVICE_ID_MESA, &deviceId); - glXQueryCurrentRendererIntegerMESAProc(GLX_RENDERER_ACCELERATED_MESA, &accelerated); - glXQueryCurrentRendererIntegerMESAProc(GLX_RENDERER_VIDEO_MEMORY_MESA, &videoMemoryMB); - - // Truncate IDs to 4 digits- that's all PCI IDs are. - vendorId &= 0xFFFF; - deviceId &= 0xFFFF; - - length += snprintf(buf + length, bufsize, - "MESA_VENDOR_ID\n0x%04x\n" - "MESA_DEVICE_ID\n0x%04x\n" - "MESA_ACCELERATED\n%s\n" - "MESA_VRAM\n%dMB\n", - vendorId, deviceId, accelerated ? "TRUE" : "FALSE", - videoMemoryMB); - - if (length >= bufsize) - fatal_error("GL strings length too large for buffer size"); - } - - // From Mesa's GL/internal/dri_interface.h, to be used by DRI clients. - typedef const char * (* PFNGLXGETSCREENDRIVERPROC) (Display *dpy, int scrNum); - PFNGLXGETSCREENDRIVERPROC glXGetScreenDriverProc = - cast<PFNGLXGETSCREENDRIVERPROC>(glXGetProcAddress("glXGetScreenDriver")); - if (glXGetScreenDriverProc) { - const char* driDriver = glXGetScreenDriverProc(dpy, DefaultScreen(dpy)); - if (driDriver) { - length += snprintf(buf + length, bufsize, "DRI_DRIVER\n%s\n", driDriver); - 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);
--- a/widget/GfxDriverInfo.cpp +++ b/widget/GfxDriverInfo.cpp @@ -301,19 +301,14 @@ const nsAString& GfxDriverInfo::GetDevic switch (id) { DECLARE_VENDOR_ID(VendorAll, ""); DECLARE_VENDOR_ID(VendorIntel, "0x8086"); DECLARE_VENDOR_ID(VendorNVIDIA, "0x10de"); DECLARE_VENDOR_ID(VendorAMD, "0x1022"); DECLARE_VENDOR_ID(VendorATI, "0x1002"); DECLARE_VENDOR_ID(VendorMicrosoft, "0x1414"); - DECLARE_VENDOR_ID(VendorMesaAll, "mesa/all"); - DECLARE_VENDOR_ID(VendorMesaLLVMPipe, "mesa/llvmpipe"); - DECLARE_VENDOR_ID(VendorMesaSoftPipe, "mesa/softpipe"); - DECLARE_VENDOR_ID(VendorMesaSWRast, "mesa/swrast"); - DECLARE_VENDOR_ID(VendorMesaUnknown, "mesa/unknown"); // Suppress a warning. DECLARE_VENDOR_ID(DeviceVendorMax, ""); } return *mDeviceVendors[id]; }
--- a/widget/GfxDriverInfo.h +++ b/widget/GfxDriverInfo.h @@ -101,28 +101,16 @@ enum DeviceFamily { enum DeviceVendor { VendorAll, VendorIntel, VendorNVIDIA, VendorAMD, VendorATI, VendorMicrosoft, - - // Wildcard for all Mesa drivers. - VendorMesaAll, - // Note that the following list of Mesa drivers is not comprehensive; we pull - // the DRI driver at runtime. These drivers are provided for convenience when - // populating the local blocklist. - VendorMesaLLVMPipe, - VendorMesaSoftPipe, - VendorMesaSWRast, - // A generic ID to be provided when we can't determine the DRI driver on Mesa. - VendorMesaUnknown, - DeviceVendorMax }; /* Array of devices to match, or an empty array for all devices */ typedef nsTArray<nsString> GfxDeviceFamily; struct GfxDriverInfo { @@ -266,17 +254,17 @@ inline void PadDriverDecimal(char *aStri aString[4] = 0; } inline bool ParseDriverVersion(const nsAString& aVersion, uint64_t *aNumericVersion) { *aNumericVersion = 0; -#if defined(XP_WIN) || defined(MOZ_X11) +#if defined(XP_WIN) int a, b, c, d; char aStr[8], bStr[8], cStr[8], dStr[8]; /* honestly, why do I even bother */ if (!SplitDriverVersion(NS_LossyConvertUTF16toASCII(aVersion).get(), aStr, bStr, cStr, dStr)) return false; PadDriverDecimal(bStr); PadDriverDecimal(cStr);
--- a/widget/GfxInfoBase.cpp +++ b/widget/GfxInfoBase.cpp @@ -689,22 +689,23 @@ GfxInfoBase::FindBlocklistedDeviceInList if (NS_FAILED(GetAdapterVendorID(adapterVendorID)) || NS_FAILED(GetAdapterDeviceID(adapterDeviceID)) || NS_FAILED(GetAdapterDriverVersion(adapterDriverVersionString))) { return 0; } } -#if defined(XP_WIN) || defined(ANDROID) || defined(MOZ_X11) +#if defined(XP_WIN) || defined(ANDROID) uint64_t driverVersion; ParseDriverVersion(adapterDriverVersionString, &driverVersion); #endif - if (!DoesVendorMatch(info[i].mAdapterVendor, adapterVendorID)) { + if (!info[i].mAdapterVendor.Equals(GfxDriverInfo::GetDeviceVendor(VendorAll), nsCaseInsensitiveStringComparator()) && + !info[i].mAdapterVendor.Equals(adapterVendorID, nsCaseInsensitiveStringComparator())) { continue; } if (info[i].mDevices != GfxDriverInfo::allDevices && info[i].mDevices->Length()) { bool deviceMatches = false; for (uint32_t j = 0; j < info[i].mDevices->Length(); j++) { if ((*info[i].mDevices)[j].Equals(adapterDeviceID, nsCaseInsensitiveStringComparator())) { deviceMatches = true; @@ -727,17 +728,17 @@ GfxInfoBase::FindBlocklistedDeviceInList } if (!info[i].mProduct.IsEmpty() && !info[i].mProduct.Equals(Product())) { continue; } if (!info[i].mManufacturer.IsEmpty() && !info[i].mManufacturer.Equals(Manufacturer())) { continue; } -#if defined(XP_WIN) || defined(ANDROID) || defined(MOZ_X11) +#if defined(XP_WIN) || defined(ANDROID) switch (info[i].mComparisonOp) { case DRIVER_LESS_THAN: match = driverVersion < info[i].mDriverVersion; break; case DRIVER_BUILD_ID_LESS_THAN: match = (driverVersion & 0xFFFF) < info[i].mDriverVersion; break; case DRIVER_LESS_THAN_OR_EQUAL: @@ -834,24 +835,16 @@ GfxInfoBase::FindBlocklistedDeviceInList (info[i].mDriverVersion & 0x000000000000ffff)); } } #endif return status; } -bool -GfxInfoBase::DoesVendorMatch(const nsAString& aBlocklistVendor, - const nsAString& aAdapterVendor) -{ - return aBlocklistVendor.Equals(aAdapterVendor, nsCaseInsensitiveStringComparator()) || - aBlocklistVendor.Equals(GfxDriverInfo::GetDeviceVendor(VendorAll), nsCaseInsensitiveStringComparator()); -} - nsresult GfxInfoBase::GetFeatureStatusImpl(int32_t aFeature, int32_t* aStatus, nsAString& aSuggestedVersion, const nsTArray<GfxDriverInfo>& aDriverInfo, nsACString& aFailureId, OperatingSystem* aOS /* = nullptr */) {
--- a/widget/GfxInfoBase.h +++ b/widget/GfxInfoBase.h @@ -101,20 +101,16 @@ protected: nsACString& aFailureId, OperatingSystem* aOS = nullptr); // Gets the driver info table. Used by GfxInfoBase to check for general cases // (while subclasses check for more specific ones). virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() = 0; virtual void DescribeFeatures(JSContext* aCx, JS::Handle<JSObject*> obj); - - virtual bool DoesVendorMatch(const nsAString& aBlocklistVendor, - const nsAString& aAdapterVendor); - bool InitFeatureObject( JSContext* aCx, JS::Handle<JSObject*> aContainer, const char* aName, int32_t aFeature, Maybe<mozilla::gfx::FeatureStatus> aKnownStatus, JS::MutableHandle<JSObject*> aOutObj);
--- a/widget/GfxInfoX11.cpp +++ b/widget/GfxInfoX11.cpp @@ -7,18 +7,16 @@ #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> #include <errno.h> #include <sys/utsname.h> #include "nsCRTGlue.h" #include "prenv.h" -#include "nsPrintfCString.h" -#include "nsWhitespaceTokenizer.h" #include "GfxInfoX11.h" #ifdef MOZ_CRASHREPORTER #include "nsExceptionHandler.h" #include "nsICrashReporter.h" #endif @@ -32,20 +30,27 @@ NS_IMPL_ISUPPORTS_INHERITED(GfxInfo, Gfx // these global variables will be set when firing the glxtest process int glxtest_pipe = 0; pid_t glxtest_pid = 0; nsresult GfxInfo::Init() { mGLMajorVersion = 0; - mGLMinorVersion = 0; + mMajorVersion = 0; + mMinorVersion = 0; + mRevisionVersion = 0; + mIsMesa = false; + mIsNVIDIA = false; + mIsFGLRX = false; + mIsNouveau = false; + mIsIntel = false; + mIsOldSwrast = false; + mIsLlvmpipe = false; mHasTextureFromPixmap = false; - mIsMesa = false; - mIsAccelerated = true; return GfxInfoBase::Init(); } void GfxInfo::GetData() { // to understand this function, see bug 639842. We retrieve the OpenGL driver information in a // separate process to protect against bad drivers. @@ -96,57 +101,36 @@ GfxInfo::GetData() 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; - nsCString glVendor; - nsCString glRenderer; - nsCString glVersion; - nsCString textureFromPixmap; - - // Available if GLX_MESA_query_renderer is supported. - nsCString mesaVendor; - nsCString mesaDevice; - nsCString mesaAccelerated; - // Available if using a DRI-based libGL stack. - nsCString driDriver; - + nsCString textureFromPixmap; nsCString *stringToFill = nullptr; char *bufptr = buf; if (!error) { while(true) { char *line = NS_strtok("\n", &bufptr); if (!line) break; if (stringToFill) { stringToFill->Assign(line); stringToFill = nullptr; } else if(!strcmp(line, "VENDOR")) - stringToFill = &glVendor; + stringToFill = &mVendor; else if(!strcmp(line, "RENDERER")) - stringToFill = &glRenderer; + stringToFill = &mRenderer; else if(!strcmp(line, "VERSION")) - stringToFill = &glVersion; + stringToFill = &mVersion; else if(!strcmp(line, "TFP")) stringToFill = &textureFromPixmap; - else if(!strcmp(line, "MESA_VENDOR_ID")) - stringToFill = &mesaVendor; - else if(!strcmp(line, "MESA_DEVICE_ID")) - stringToFill = &mesaDevice; - else if(!strcmp(line, "MESA_ACCELERATED")) - stringToFill = &mesaAccelerated; - else if(!strcmp(line, "MESA_VRAM")) - stringToFill = &mAdapterRAM; - else if(!strcmp(line, "DRI_DRIVER")) - stringToFill = &driDriver; } } if (!strcmp(textureFromPixmap.get(), "TRUE")) mHasTextureFromPixmap = true; // only useful for Linux kernel version check for FGLRX driver. // assumes X client == X server, which is sad. @@ -154,34 +138,34 @@ GfxInfo::GetData() if (!uname(&unameobj)) { mOS.Assign(unameobj.sysname); mOSRelease.Assign(unameobj.release); } const char *spoofedVendor = PR_GetEnv("MOZ_GFX_SPOOF_GL_VENDOR"); if (spoofedVendor) - glVendor.Assign(spoofedVendor); + mVendor.Assign(spoofedVendor); const char *spoofedRenderer = PR_GetEnv("MOZ_GFX_SPOOF_GL_RENDERER"); if (spoofedRenderer) - glRenderer.Assign(spoofedRenderer); + mRenderer.Assign(spoofedRenderer); const char *spoofedVersion = PR_GetEnv("MOZ_GFX_SPOOF_GL_VERSION"); if (spoofedVersion) - glVersion.Assign(spoofedVersion); + mVersion.Assign(spoofedVersion); const char *spoofedOS = PR_GetEnv("MOZ_GFX_SPOOF_OS"); if (spoofedOS) mOS.Assign(spoofedOS); const char *spoofedOSRelease = PR_GetEnv("MOZ_GFX_SPOOF_OS_RELEASE"); if (spoofedOSRelease) mOSRelease.Assign(spoofedOSRelease); if (error || - glVendor.IsEmpty() || - glRenderer.IsEmpty() || - glVersion.IsEmpty() || + mVendor.IsEmpty() || + mRenderer.IsEmpty() || + mVersion.IsEmpty() || mOS.IsEmpty() || mOSRelease.IsEmpty()) { mAdapterDescription.AppendLiteral("GLXtest process failed"); if (waiting_for_glxtest_process_failed) mAdapterDescription.AppendPrintf(" (waitpid failed with errno=%d for pid %d)", waitpid_errno, glxtest_pid); if (exited_with_error_code) mAdapterDescription.AppendPrintf(" (exited with status %d)", WEXITSTATUS(glxtest_status)); @@ -193,145 +177,104 @@ GfxInfo::GetData() mAdapterDescription.Append('\n'); } #ifdef MOZ_CRASHREPORTER CrashReporter::AppendAppNotesToCrashReport(mAdapterDescription); #endif return; } - // Scan the GL_VERSION string for the GL and driver versions. - nsCWhitespaceTokenizer tokenizer(glVersion); - while (tokenizer.hasMoreTokens()) { - nsCString token(tokenizer.nextToken()); - unsigned int major = 0, minor = 0, revision = 0, patch = 0; - if (sscanf(token.get(), "%u.%u.%u.%u", - &major, &minor, &revision, &patch) >= 2) - { - // A survey of GL_VENDOR strings indicates that the first version is - // always the GL version, the second is usually the driver version. - if (mGLMajorVersion == 0) { - mGLMajorVersion = major; - mGLMinorVersion = minor; - } else { - mDriverVersion = nsPrintfCString("%u.%u.%u.%u", major, minor, revision, patch); - } - } - } - - if (mGLMajorVersion == 0) { - NS_WARNING("Failed to parse GL version!"); - return; - } - - // Mesa always exposes itself in the GL_VERSION string, but not always the - // GL_VENDOR string. - mIsMesa = glVersion.Find("Mesa") != -1; - - // We need to use custom vendor IDs for mesa so we can treat them - // differently than the proprietary drivers. - if (mIsMesa) { - mIsAccelerated = !mesaAccelerated.Equals("FALSE"); - // Process software rasterizers before the DRI driver string; we may be - // forcing software rasterization on a DRI-accelerated X server by using - // LIBGL_ALWAYS_SOFTWARE or a similar restriction. - if (strcasestr(glRenderer.get(), "llvmpipe")) { - CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(VendorMesaLLVMPipe), mVendorId); - mIsAccelerated = false; - } else if (strcasestr(glRenderer.get(), "softpipe")) { - CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(VendorMesaSoftPipe), mVendorId); - mIsAccelerated = false; - } else if (strcasestr(glRenderer.get(), "software rasterizer") || - !mIsAccelerated) { - // Fallback to reporting swrast if GLX_MESA_query_renderer tells us - // we're using an unaccelerated context. - CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(VendorMesaSWRast), mVendorId); - mIsAccelerated = false; - } else if (!driDriver.IsEmpty()) { - mVendorId = nsPrintfCString("mesa/%s", driDriver.get()); - } else { - // Some other mesa configuration where we couldn't get enough info. - NS_WARNING("Failed to detect Mesa driver being used!"); - CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(VendorMesaUnknown), mVendorId); - } - - if (!mesaDevice.IsEmpty()) { - mDeviceId = mesaDevice; - } else { - NS_WARNING("Failed to get Mesa device ID! GLX_MESA_query_renderer unsupported?"); - } - } else if (glVendor.EqualsLiteral("NVIDIA Corporation")) { - CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), mVendorId); - // TODO: Use NV-CONTROL X11 extension to query Device ID and VRAM. - } else if (glVendor.EqualsLiteral("ATI Technologies Inc.")) { - CopyUTF16toUTF8(GfxDriverInfo::GetDeviceVendor(VendorATI), mVendorId); - // TODO: Look into ways to find the device ID on FGLRX. - } else { - NS_WARNING("Failed to detect GL vendor!"); - } - - // Fallback to GL_VENDOR and GL_RENDERER. - if (mVendorId.IsEmpty()) - mVendorId.Assign(glVendor.get()); - if (mDeviceId.IsEmpty()) - mDeviceId.Assign(glRenderer.get()); - - mAdapterDescription.Assign(glRenderer); + mAdapterDescription.Append(mVendor); + mAdapterDescription.AppendLiteral(" -- "); + mAdapterDescription.Append(mRenderer); nsAutoCString note; - note.AppendLiteral("\nOpenGL: "); - note.Append(glRenderer); + note.AppendLiteral("OpenGL: "); + note.Append(mAdapterDescription); note.AppendLiteral(" -- "); - note.Append(glVersion); + note.Append(mVersion); if (mHasTextureFromPixmap) note.AppendLiteral(" -- texture_from_pixmap"); note.Append('\n'); #ifdef MOZ_CRASHREPORTER CrashReporter::AppendAppNotesToCrashReport(note); #endif + + // determine the major OpenGL version. That's the first integer in the version string. + mGLMajorVersion = strtol(mVersion.get(), 0, 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(mVersion.get(), "Mesa"); + if (Mesa_in_version_string) { + mIsMesa = 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(mVendor.get(), "nouveau")) + mIsNouveau = true; + if (strcasestr(mRenderer.get(), "intel")) // yes, intel is in the renderer string + mIsIntel = true; + if (strcasestr(mRenderer.get(), "llvmpipe")) + mIsLlvmpipe = true; + if (strcasestr(mRenderer.get(), "software rasterizer")) + mIsOldSwrast = true; + } else if (strstr(mVendor.get(), "NVIDIA Corporation")) { + mIsNVIDIA = 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(mVersion.get(), "NVIDIA"); + if (NVIDIA_in_version_string) + whereToReadVersionNumbers = NVIDIA_in_version_string + strlen("NVIDIA"); + } else if (strstr(mVendor.get(), "ATI Technologies Inc")) { + mIsFGLRX = true; + // with the FGLRX driver, the version string only gives a OpenGL version :/ so let's return that. + // that can at least give a rough idea of how old the driver is. + whereToReadVersionNumbers = mVersion.get(); + } + + // read major.minor version numbers of the driver (not to be confused with the OpenGL version) + if (whereToReadVersionNumbers) { + // copy into writable buffer, for tokenization + strncpy(buf, whereToReadVersionNumbers, buf_size); + 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 = NS_strtok(".", &bufptr); + if (token) { + mMajorVersion = strtol(token, 0, 10); + token = NS_strtok(".", &bufptr); + if (token) { + mMinorVersion = strtol(token, 0, 10); + token = NS_strtok(".", &bufptr); + if (token) + mRevisionVersion = strtol(token, 0, 10); + } + } + } +} + +static inline 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); } const nsTArray<GfxDriverInfo>& GfxInfo::GetGfxDriverInfo() { - if (!mDriverInfo->Length()) { - // Mesa 10.0 provides the GLX_MESA_query_renderer extension, which allows us - // to query device IDs backing a GL context for blacklisting. - APPEND_TO_DRIVER_BLOCKLIST(OperatingSystem::Linux, - (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorMesaAll), GfxDriverInfo::allDevices, - GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, - DRIVER_LESS_THAN, V(10,0,0,0), "FEATURE_FAILURE_OLD_MESA", "Mesa 10.0"); - - // NVIDIA baseline (ported from old blocklist) - APPEND_TO_DRIVER_BLOCKLIST(OperatingSystem::Linux, - (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices, - GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, - DRIVER_LESS_THAN, V(257,21,0,0), "FEATURE_FAILURE_OLD_NVIDIA", "NVIDIA 257.21"); - - // fglrx baseline (chosen arbitrarily as 2013-07-22 release). - APPEND_TO_DRIVER_BLOCKLIST(OperatingSystem::Linux, - (nsAString&) GfxDriverInfo::GetDeviceVendor(VendorATI), GfxDriverInfo::allDevices, - GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, - DRIVER_LESS_THAN, V(13,15,100,1), "FEATURE_FAILURE_OLD_FGLRX", "fglrx 13.15.100.1"); - } + // Nothing here yet. + //if (!mDriverInfo->Length()) { + // + //} return *mDriverInfo; } -bool -GfxInfo::DoesVendorMatch(const nsAString& aBlocklistVendor, - const nsAString& aAdapterVendor) -{ - if (mIsMesa && aBlocklistVendor.Equals(GfxDriverInfo::GetDeviceVendor(VendorMesaAll), - nsCaseInsensitiveStringComparator())) - { - return true; - } - return GfxInfoBase::DoesVendorMatch(aBlocklistVendor, aAdapterVendor); -} - nsresult GfxInfo::GetFeatureStatusImpl(int32_t aFeature, int32_t *aStatus, nsAString & aSuggestedDriverVersion, const nsTArray<GfxDriverInfo>& aDriverInfo, nsACString& aFailureId, OperatingSystem* aOS /* = nullptr */) @@ -340,41 +283,114 @@ GfxInfo::GetFeatureStatusImpl(int32_t aF NS_ENSURE_ARG_POINTER(aStatus); *aStatus = nsIGfxInfo::FEATURE_STATUS_UNKNOWN; aSuggestedDriverVersion.SetIsVoid(true); OperatingSystem os = OperatingSystem::Linux; if (aOS) *aOS = os; - if (mGLMajorVersion == 0) { - // If we failed to get a GL version, glxtest failed. - *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; - aFailureId = "FEATURE_FAILURE_GLXTEST_FAILED"; - return NS_OK; - } - if (mGLMajorVersion == 1) { // We're on OpenGL 1. In most cases that indicates really old hardware. // We better block them, rather than rely on them to fail gracefully, because they don't! // see bug 696636 *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; aFailureId = "FEATURE_FAILURE_OPENGL_1"; return NS_OK; } - // Blacklist software GL implementations from using layers acceleration. - // On the test infrastructure, we'll force-enable layers acceleration. - if (aFeature == nsIGfxInfo::FEATURE_OPENGL_LAYERS && - !mIsAccelerated && - !PR_GetEnv("MOZ_LAYERS_ALLOW_SOFTWARE_GL")) - { - *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; - aFailureId = "FEATURE_FAILURE_SOFTWARE_GL"; - return NS_OK; + // Don't evaluate any special cases if we're checking the downloaded blocklist. + if (!aDriverInfo.Length()) { + // Blacklist software GL implementations from using layers acceleration. + // On the test infrastructure, we'll force-enable layers acceleration. + if (aFeature == nsIGfxInfo::FEATURE_OPENGL_LAYERS && + (mIsLlvmpipe || mIsOldSwrast) && + !PR_GetEnv("MOZ_LAYERS_ALLOW_SOFTWARE_GL")) + { + *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; + aFailureId = "FEATURE_FAILURE_SOFTWARE_GL"; + return NS_OK; + } + + // Only check features relevant to Linux. + if (aFeature == nsIGfxInfo::FEATURE_OPENGL_LAYERS || + aFeature == nsIGfxInfo::FEATURE_WEBGL_OPENGL || + aFeature == nsIGfxInfo::FEATURE_WEBGL_MSAA) { + + // whitelist the linux test slaves' current configuration. + // this is necessary as they're still using the slightly outdated 190.42 driver. + // this isn't a huge risk, as at least this is the exact setting in which we do continuous testing, + // and this only affects GeForce 9400 cards on linux on this precise driver version, which is very few users. + // We do the same thing on Windows XP, see in widget/windows/GfxInfo.cpp + if (mIsNVIDIA && + !strcmp(mRenderer.get(), "GeForce 9400/PCI/SSE2") && + !strcmp(mVersion.get(), "3.2.0 NVIDIA 190.42")) + { + *aStatus = nsIGfxInfo::FEATURE_STATUS_OK; + return NS_OK; + } + + if (mIsMesa) { + if (mIsNouveau && version(mMajorVersion, mMinorVersion) < version(8,0)) { + *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION; + aFailureId = "FEATURE_FAILURE_MESA_1"; + aSuggestedDriverVersion.AssignLiteral("Mesa 8.0"); + } + else if (version(mMajorVersion, mMinorVersion, mRevisionVersion) < version(7,10,3)) { + *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION; + aFailureId = "FEATURE_FAILURE_MESA_2"; + aSuggestedDriverVersion.AssignLiteral("Mesa 7.10.3"); + } + else if (mIsOldSwrast) { + *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION; + aFailureId = "FEATURE_FAILURE_SW_RAST"; + } + else if (mIsLlvmpipe && version(mMajorVersion, mMinorVersion) < version(9, 1)) { + // bug 791905, Mesa bug 57733, fixed in Mesa 9.1 according to + // https://bugs.freedesktop.org/show_bug.cgi?id=57733#c3 + *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION; + aFailureId = "FEATURE_FAILURE_MESA_3"; + } + else if (aFeature == nsIGfxInfo::FEATURE_WEBGL_MSAA) + { + if (mIsIntel && version(mMajorVersion, mMinorVersion) < version(8,1)) { + *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION; + aFailureId = "FEATURE_FAILURE_MESA_4"; + aSuggestedDriverVersion.AssignLiteral("Mesa 8.1"); + } + } + + } else if (mIsNVIDIA) { + if (version(mMajorVersion, mMinorVersion, mRevisionVersion) < version(257,21)) { + *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION; + aFailureId = "FEATURE_FAILURE_OLD_NV"; + aSuggestedDriverVersion.AssignLiteral("NVIDIA 257.21"); + } + } else if (mIsFGLRX) { + // 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(mMajorVersion, mMinorVersion, mRevisionVersion) < version(3, 0)) { + *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION; + aFailureId = "FEATURE_FAILURE_OLD_FGLRX"; + aSuggestedDriverVersion.AssignLiteral("<Something recent>"); + } + // Bug 724640: FGLRX + Linux 2.6.32 is a crashy combo + bool unknownOS = mOS.IsEmpty() || mOSRelease.IsEmpty(); + bool badOS = mOS.Find("Linux", true) != -1 && + mOSRelease.Find("2.6.32") != -1; + if (unknownOS || badOS) { + *aStatus = nsIGfxInfo::FEATURE_BLOCKED_OS_VERSION; + aFailureId = "FEATURE_FAILURE_OLD_OS"; + } + } 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. + *aStatus = nsIGfxInfo::FEATURE_BLOCKED_DEVICE; + } + } } return GfxInfoBase::GetFeatureStatusImpl(aFeature, aStatus, aSuggestedDriverVersion, aDriverInfo, aFailureId, &os); } NS_IMETHODIMP GfxInfo::GetD2DEnabled(bool *aEnabled) @@ -412,18 +428,17 @@ NS_IMETHODIMP GfxInfo::GetAdapterDescription2(nsAString & aAdapterDescription) { return NS_ERROR_FAILURE; } NS_IMETHODIMP GfxInfo::GetAdapterRAM(nsAString & aAdapterRAM) { - GetData(); - CopyUTF8toUTF16(mAdapterRAM, aAdapterRAM); + aAdapterRAM.Truncate(); return NS_OK; } NS_IMETHODIMP GfxInfo::GetAdapterRAM2(nsAString & aAdapterRAM) { return NS_ERROR_FAILURE; } @@ -440,17 +455,17 @@ GfxInfo::GetAdapterDriver2(nsAString & a { return NS_ERROR_FAILURE; } NS_IMETHODIMP GfxInfo::GetAdapterDriverVersion(nsAString & aAdapterDriverVersion) { GetData(); - CopyUTF8toUTF16(mDriverVersion, aAdapterDriverVersion); + CopyASCIItoUTF16(mVersion, aAdapterDriverVersion); return NS_OK; } NS_IMETHODIMP GfxInfo::GetAdapterDriverVersion2(nsAString & aAdapterDriverVersion) { return NS_ERROR_FAILURE; } @@ -467,31 +482,31 @@ GfxInfo::GetAdapterDriverDate2(nsAString { return NS_ERROR_FAILURE; } NS_IMETHODIMP GfxInfo::GetAdapterVendorID(nsAString & aAdapterVendorID) { GetData(); - CopyUTF8toUTF16(mVendorId, aAdapterVendorID); + CopyUTF8toUTF16(mVendor, aAdapterVendorID); return NS_OK; } NS_IMETHODIMP GfxInfo::GetAdapterVendorID2(nsAString & aAdapterVendorID) { return NS_ERROR_FAILURE; } NS_IMETHODIMP GfxInfo::GetAdapterDeviceID(nsAString & aAdapterDeviceID) { GetData(); - CopyUTF8toUTF16(mDeviceId, aAdapterDeviceID); + CopyUTF8toUTF16(mRenderer, aAdapterDeviceID); return NS_OK; } NS_IMETHODIMP GfxInfo::GetAdapterDeviceID2(nsAString & aAdapterDeviceID) { return NS_ERROR_FAILURE; } @@ -516,29 +531,29 @@ GfxInfo::GetIsGPU2Active(bool* aIsGPU2Ac #ifdef DEBUG // Implement nsIGfxInfoDebug // We don't support spoofing anything on Linux NS_IMETHODIMP GfxInfo::SpoofVendorID(const nsAString & aVendorID) { - CopyUTF16toUTF8(aVendorID, mVendorId); + CopyUTF16toUTF8(aVendorID, mVendor); return NS_OK; } NS_IMETHODIMP GfxInfo::SpoofDeviceID(const nsAString & aDeviceID) { - CopyUTF16toUTF8(aDeviceID, mDeviceId); + CopyUTF16toUTF8(aDeviceID, mRenderer); return NS_OK; } NS_IMETHODIMP GfxInfo::SpoofDriverVersion(const nsAString & aDriverVersion) { - CopyUTF16toUTF8(aDriverVersion, mDriverVersion); + CopyUTF16toUTF8(aDriverVersion, mVersion); return NS_OK; } NS_IMETHODIMP GfxInfo::SpoofOSVersion(uint32_t aVersion) { // We don't support OS versioning on Linux. There's just "Linux". return NS_OK; }
--- a/widget/GfxInfoX11.h +++ b/widget/GfxInfoX11.h @@ -4,17 +4,16 @@ * 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 __GfxInfoX11_h__ #define __GfxInfoX11_h__ #include "GfxInfoBase.h" -#include "nsString.h" namespace mozilla { namespace widget { class GfxInfo final : public GfxInfoBase { public: @@ -60,32 +59,26 @@ protected: virtual nsresult GetFeatureStatusImpl(int32_t aFeature, int32_t *aStatus, nsAString & aSuggestedDriverVersion, const nsTArray<GfxDriverInfo>& aDriverInfo, nsACString& aFailureId, OperatingSystem* aOS = nullptr) override; virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() override; -protected: - virtual bool DoesVendorMatch(const nsAString& aBlocklistVendor, - const nsAString& aAdapterVendor) override; - private: - nsCString mVendorId; - nsCString mDeviceId; - nsCString mDriverVersion; + nsCString mVendor; + nsCString mRenderer; + nsCString mVersion; nsCString mAdapterDescription; - nsCString mAdapterRAM; nsCString mOS; nsCString mOSRelease; + bool mIsMesa, mIsNVIDIA, mIsFGLRX, mIsNouveau, mIsIntel, mIsOldSwrast, mIsLlvmpipe; bool mHasTextureFromPixmap; - unsigned int mGLMajorVersion, mGLMinorVersion; - bool mIsMesa; - bool mIsAccelerated; + int mGLMajorVersion, mMajorVersion, mMinorVersion, mRevisionVersion; void AddCrashReportAnnotations(); }; } // namespace widget } // namespace mozilla #endif /* __GfxInfoX11_h__ */