mirror of
https://github.com/roytam1/UXP.git
synced 2026-05-26 05:38:39 +00:00
Merge remote-tracking branch 'origin/tracking' into custom
This commit is contained in:
+2
-2
@@ -1802,11 +1802,11 @@ URL::CanParse(const GlobalObject& aGlobal, const nsAString& aURL,
|
||||
return true;
|
||||
}
|
||||
|
||||
URLSearchParams*
|
||||
already_AddRefed<URLSearchParams>
|
||||
URL::SearchParams()
|
||||
{
|
||||
CreateSearchParamsIfNeeded();
|
||||
return mSearchParams;
|
||||
return do_AddRef(mSearchParams);
|
||||
}
|
||||
|
||||
bool IsChromeURI(nsIURI* aURI)
|
||||
|
||||
+1
-1
@@ -149,7 +149,7 @@ public:
|
||||
virtual void
|
||||
SetSearch(const nsAString& aSearch, ErrorResult& aRv);
|
||||
|
||||
URLSearchParams* SearchParams();
|
||||
already_AddRefed<URLSearchParams> SearchParams();
|
||||
|
||||
virtual void
|
||||
GetHash(nsAString& aHost, ErrorResult& aRv) const = 0;
|
||||
|
||||
@@ -940,7 +940,7 @@ bool State::removeReadFramebufferBinding(GLuint framebuffer)
|
||||
|
||||
bool State::removeDrawFramebufferBinding(GLuint framebuffer)
|
||||
{
|
||||
if (mReadFramebuffer != nullptr &&
|
||||
if (mDrawFramebuffer != nullptr &&
|
||||
mDrawFramebuffer->id() == framebuffer)
|
||||
{
|
||||
setDrawFramebufferBinding(nullptr);
|
||||
|
||||
@@ -711,7 +711,8 @@ gl::ErrorOrResult<Buffer11::BufferStorage *> Buffer11::getConstantBufferRangeSto
|
||||
return a.second.lruCount < b.second.lruCount;
|
||||
});
|
||||
|
||||
ASSERT(iter->second.storage != newStorage);
|
||||
if (iter->second.storage == newStorage)
|
||||
break;
|
||||
ASSERT(mConstantBufferStorageAdditionalSize >= iter->second.storage->getSize());
|
||||
|
||||
mConstantBufferStorageAdditionalSize -= iter->second.storage->getSize();
|
||||
@@ -1140,8 +1141,15 @@ gl::ErrorOrResult<ID3D11Buffer *> Buffer11::EmulatedIndexedStorage::getNativeSto
|
||||
ANGLE_TRY_RESULT(attribute.computeOffset(startVertex), offset);
|
||||
|
||||
// Expand the memory storage upon request and cache the results.
|
||||
unsigned int expandedDataSize =
|
||||
static_cast<unsigned int>((indexInfo->srcCount * attribute.stride) + offset);
|
||||
angle::CheckedNumeric<unsigned int> checkedExpandedDataSize(indexInfo->srcCount);
|
||||
checkedExpandedDataSize *= attribute.stride;
|
||||
checkedExpandedDataSize += offset;
|
||||
if (!checkedExpandedDataSize.IsValid()) {
|
||||
return gl::Error(
|
||||
GL_OUT_OF_MEMORY,
|
||||
"Error resizing buffer in Buffer11::EmulatedIndexedStorage::getNativeStorage");
|
||||
}
|
||||
unsigned int expandedDataSize = checkedExpandedDataSize.ValueOrDie();
|
||||
MemoryBuffer expandedData;
|
||||
if (!expandedData.resize(expandedDataSize))
|
||||
{
|
||||
|
||||
@@ -1743,7 +1743,8 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
|
||||
unsigned long alpha_size;
|
||||
uint32_t *pixel32;
|
||||
uint8_t *pixel8;
|
||||
int i, x, y;
|
||||
int x, y;
|
||||
unsigned long i;
|
||||
cairo_bool_t opaque;
|
||||
uint8_t a;
|
||||
|
||||
@@ -1755,10 +1756,10 @@ _cairo_pdf_surface_emit_smask (cairo_pdf_surface_t *surface,
|
||||
stream_ret->id = 0;
|
||||
|
||||
if (image->format == CAIRO_FORMAT_A1) {
|
||||
alpha_size = (image->width + 7) / 8 * image->height;
|
||||
alpha_size = (unsigned long) ((image->width + 7) / 8) * image->height;
|
||||
alpha = _cairo_malloc_ab ((image->width+7) / 8, image->height);
|
||||
} else {
|
||||
alpha_size = image->height * image->width;
|
||||
alpha_size = (unsigned long) image->height * image->width;
|
||||
alpha = _cairo_malloc_ab (image->height, image->width);
|
||||
}
|
||||
|
||||
@@ -1841,7 +1842,8 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
|
||||
char *rgb;
|
||||
unsigned long rgb_size;
|
||||
uint32_t *pixel;
|
||||
int i, x, y;
|
||||
int x, y;
|
||||
unsigned long i;
|
||||
cairo_pdf_resource_t smask = {0}; /* squelch bogus compiler warning */
|
||||
cairo_bool_t need_smask;
|
||||
const char *interpolate = "true";
|
||||
@@ -1856,7 +1858,7 @@ _cairo_pdf_surface_emit_image (cairo_pdf_surface_t *surface,
|
||||
image->format == CAIRO_FORMAT_A8 ||
|
||||
image->format == CAIRO_FORMAT_A1);
|
||||
|
||||
rgb_size = image->height * image->width * 3;
|
||||
rgb_size = (unsigned long) image->height * image->width * 3;
|
||||
rgb = _cairo_malloc_abc (image->width, image->height, 3);
|
||||
if (unlikely (rgb == NULL)) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
|
||||
#include "nsSize.h" // for gfx::IntSize (needed by GLContextProviderImpl.h below)
|
||||
|
||||
#if defined(MOZ_X11)
|
||||
#include "GLContextProviderX11.h"
|
||||
#endif
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
@@ -45,13 +49,15 @@ namespace gl {
|
||||
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderGLX
|
||||
#include "GLContextProviderImpl.h"
|
||||
#undef GL_CONTEXT_PROVIDER_NAME
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderGLX
|
||||
#endif
|
||||
|
||||
#define GL_CONTEXT_PROVIDER_NAME GLContextProviderEGL
|
||||
#include "GLContextProviderImpl.h"
|
||||
#undef GL_CONTEXT_PROVIDER_NAME
|
||||
#ifndef GL_CONTEXT_PROVIDER_DEFAULT
|
||||
|
||||
#if defined(MOZ_X11)
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderX11
|
||||
#elif !defined(GL_CONTEXT_PROVIDER_DEFAULT)
|
||||
#define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEGL
|
||||
#endif
|
||||
|
||||
|
||||
@@ -13,13 +13,23 @@
|
||||
|
||||
#if defined(XP_UNIX)
|
||||
|
||||
#define GLES2_LIB "libGLESv2.so"
|
||||
#define GLES2_LIB2 "libGLESv2.so.2"
|
||||
#if defined(MOZ_X11)
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
#define EGL_OPENGL_LIB "libGL.so"
|
||||
#define EGL_OPENGL_LIB2 "libGL.so.1"
|
||||
#else
|
||||
#define EGL_OPENGL_LIB "libGL.so.1"
|
||||
#define EGL_OPENGL_LIB2 "libGL.so"
|
||||
#endif
|
||||
#else
|
||||
#define EGL_OPENGL_LIB "libGLESv2.so"
|
||||
#define EGL_OPENGL_LIB2 "libGLESv2.so.2"
|
||||
#endif
|
||||
|
||||
#elif defined(XP_WIN)
|
||||
#include "nsIFile.h"
|
||||
|
||||
#define GLES2_LIB "libGLESv2.dll"
|
||||
#define EGL_OPENGL_LIB "libGLESv2.dll"
|
||||
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
@@ -102,6 +112,45 @@ using namespace mozilla::widget;
|
||||
static bool
|
||||
CreateConfig(EGLConfig* aConfig, nsIWidget* aWidget);
|
||||
|
||||
static bool
|
||||
UseDesktopOpenGLForEGL()
|
||||
{
|
||||
#ifdef MOZ_X11
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static EGLint
|
||||
GetEGLRenderableType(CreateContextFlags flags)
|
||||
{
|
||||
if (UseDesktopOpenGLForEGL()) {
|
||||
return LOCAL_EGL_OPENGL_BIT;
|
||||
}
|
||||
|
||||
return bool(flags & CreateContextFlags::PREFER_ES3)
|
||||
? LOCAL_EGL_OPENGL_ES3_BIT_KHR
|
||||
: LOCAL_EGL_OPENGL_ES2_BIT;
|
||||
}
|
||||
|
||||
static bool
|
||||
BindContextAPI(nsACString* const out_failureId)
|
||||
{
|
||||
const EGLenum api = UseDesktopOpenGLForEGL()
|
||||
? LOCAL_EGL_OPENGL_API
|
||||
: LOCAL_EGL_OPENGL_ES_API;
|
||||
if (sEGLLibrary.fBindAPI(api) == LOCAL_EGL_FALSE) {
|
||||
*out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_BIND_API");
|
||||
NS_WARNING(UseDesktopOpenGLForEGL()
|
||||
? "Failed to bind API to OpenGL!"
|
||||
: "Failed to bind API to GLES!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// append three zeros at the end of attribs list to work around
|
||||
// EGL implementation bugs that iterate until they find 0, instead of
|
||||
// EGL_NONE. See bug 948406.
|
||||
@@ -172,8 +221,12 @@ GLContextEGL::GLContextEGL(CreateContextFlags flags, const SurfaceCaps& caps,
|
||||
, mShareWithEGLImage(false)
|
||||
, mOwnsContext(true)
|
||||
{
|
||||
// any EGL contexts will always be GLESv2
|
||||
SetProfileVersion(ContextProfile::OpenGLES, 200);
|
||||
// X11 uses desktop OpenGL-over-EGL. Other EGL paths still use GLES/ANGLE.
|
||||
if (UseDesktopOpenGLForEGL()) {
|
||||
SetProfileVersion(ContextProfile::OpenGLCompatibility, 200);
|
||||
} else {
|
||||
SetProfileVersion(ContextProfile::OpenGLES, 200);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf_stderr("Initializing context %p surface %p on display %p\n", mContext, mSurface, EGL_DISPLAY());
|
||||
@@ -202,10 +255,10 @@ GLContextEGL::~GLContextEGL()
|
||||
bool
|
||||
GLContextEGL::Init()
|
||||
{
|
||||
if (!OpenLibrary(GLES2_LIB)) {
|
||||
if (!OpenLibrary(EGL_OPENGL_LIB)) {
|
||||
#if defined(XP_UNIX)
|
||||
if (!OpenLibrary(GLES2_LIB2)) {
|
||||
NS_WARNING("Couldn't load GLES2 LIB.");
|
||||
if (!OpenLibrary(EGL_OPENGL_LIB2)) {
|
||||
NS_WARNING("Couldn't load EGL GL library.");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -451,9 +504,7 @@ GLContextEGL::CreateGLContext(CreateContextFlags flags,
|
||||
EGLSurface surface,
|
||||
nsACString* const out_failureId)
|
||||
{
|
||||
if (sEGLLibrary.fBindAPI(LOCAL_EGL_OPENGL_ES_API) == LOCAL_EGL_FALSE) {
|
||||
*out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_EGL_ES");
|
||||
NS_WARNING("Failed to bind API to GLES!");
|
||||
if (!BindContextAPI(out_failureId)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -462,11 +513,14 @@ GLContextEGL::CreateGLContext(CreateContextFlags flags,
|
||||
|
||||
nsTArray<EGLint> contextAttribs;
|
||||
|
||||
contextAttribs.AppendElement(LOCAL_EGL_CONTEXT_CLIENT_VERSION);
|
||||
if (flags & CreateContextFlags::PREFER_ES3)
|
||||
contextAttribs.AppendElement(3);
|
||||
else
|
||||
contextAttribs.AppendElement(2);
|
||||
if (!UseDesktopOpenGLForEGL()) {
|
||||
contextAttribs.AppendElement(LOCAL_EGL_CONTEXT_CLIENT_VERSION);
|
||||
if (flags & CreateContextFlags::PREFER_ES3) {
|
||||
contextAttribs.AppendElement(3);
|
||||
} else {
|
||||
contextAttribs.AppendElement(2);
|
||||
}
|
||||
}
|
||||
|
||||
if (sEGLLibrary.HasRobustness()) {
|
||||
// contextAttribs.AppendElement(LOCAL_EGL_CONTEXT_ROBUST_ACCESS_EXT);
|
||||
@@ -550,70 +604,52 @@ TRY_AGAIN_POWER_OF_TWO:
|
||||
return surface;
|
||||
}
|
||||
|
||||
static const EGLint kEGLConfigAttribsOffscreenPBuffer[] = {
|
||||
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_PBUFFER_BIT,
|
||||
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
|
||||
// Old versions of llvmpipe seem to need this to properly create the pbuffer (bug 981856)
|
||||
LOCAL_EGL_RED_SIZE, 8,
|
||||
LOCAL_EGL_GREEN_SIZE, 8,
|
||||
LOCAL_EGL_BLUE_SIZE, 8,
|
||||
LOCAL_EGL_ALPHA_SIZE, 0,
|
||||
EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
|
||||
};
|
||||
static void
|
||||
AppendWindowConfigAttribs(int32_t depth, nsTArray<EGLint>* out)
|
||||
{
|
||||
out->AppendElement(LOCAL_EGL_SURFACE_TYPE);
|
||||
out->AppendElement(LOCAL_EGL_WINDOW_BIT);
|
||||
|
||||
static const EGLint kEGLConfigAttribsRGB16[] = {
|
||||
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_WINDOW_BIT,
|
||||
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
|
||||
LOCAL_EGL_RED_SIZE, 5,
|
||||
LOCAL_EGL_GREEN_SIZE, 6,
|
||||
LOCAL_EGL_BLUE_SIZE, 5,
|
||||
LOCAL_EGL_ALPHA_SIZE, 0,
|
||||
EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
|
||||
};
|
||||
out->AppendElement(LOCAL_EGL_RENDERABLE_TYPE);
|
||||
out->AppendElement(GetEGLRenderableType(CreateContextFlags::NONE));
|
||||
|
||||
static const EGLint kEGLConfigAttribsRGB24[] = {
|
||||
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_WINDOW_BIT,
|
||||
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
|
||||
LOCAL_EGL_RED_SIZE, 8,
|
||||
LOCAL_EGL_GREEN_SIZE, 8,
|
||||
LOCAL_EGL_BLUE_SIZE, 8,
|
||||
LOCAL_EGL_ALPHA_SIZE, 0,
|
||||
EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
|
||||
};
|
||||
out->AppendElement(LOCAL_EGL_RED_SIZE);
|
||||
out->AppendElement(depth == 16 ? 5 : 8);
|
||||
|
||||
static const EGLint kEGLConfigAttribsRGBA32[] = {
|
||||
LOCAL_EGL_SURFACE_TYPE, LOCAL_EGL_WINDOW_BIT,
|
||||
LOCAL_EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT,
|
||||
LOCAL_EGL_RED_SIZE, 8,
|
||||
LOCAL_EGL_GREEN_SIZE, 8,
|
||||
LOCAL_EGL_BLUE_SIZE, 8,
|
||||
LOCAL_EGL_ALPHA_SIZE, 8,
|
||||
EGL_ATTRIBS_LIST_SAFE_TERMINATION_WORKING_AROUND_BUGS
|
||||
};
|
||||
out->AppendElement(LOCAL_EGL_GREEN_SIZE);
|
||||
out->AppendElement(depth == 16 ? 6 : 8);
|
||||
|
||||
out->AppendElement(LOCAL_EGL_BLUE_SIZE);
|
||||
out->AppendElement(depth == 16 ? 5 : 8);
|
||||
|
||||
out->AppendElement(LOCAL_EGL_ALPHA_SIZE);
|
||||
out->AppendElement(depth == 32 ? 8 : 0);
|
||||
|
||||
for (size_t i = 0; i < MOZ_ARRAY_LENGTH(gTerminationAttribs); ++i) {
|
||||
out->AppendElement(gTerminationAttribs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
CreateConfig(EGLConfig* aConfig, int32_t depth, nsIWidget* aWidget)
|
||||
{
|
||||
EGLConfig configs[64];
|
||||
const EGLint* attribs;
|
||||
EGLint ncfg = ArrayLength(configs);
|
||||
nsTArray<EGLint> attribs;
|
||||
|
||||
switch (depth) {
|
||||
case 16:
|
||||
attribs = kEGLConfigAttribsRGB16;
|
||||
break;
|
||||
case 24:
|
||||
attribs = kEGLConfigAttribsRGB24;
|
||||
break;
|
||||
case 32:
|
||||
attribs = kEGLConfigAttribsRGBA32;
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("Unknown pixel depth");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sEGLLibrary.fChooseConfig(EGL_DISPLAY(), attribs,
|
||||
AppendWindowConfigAttribs(depth, &attribs);
|
||||
|
||||
if (!sEGLLibrary.fChooseConfig(EGL_DISPLAY(), attribs.Elements(),
|
||||
configs, ncfg, &ncfg) ||
|
||||
ncfg < 1) {
|
||||
return false;
|
||||
@@ -727,17 +763,13 @@ GLContextProviderEGL::CreateForWindow(nsIWidget* aWidget, bool aForceAccelerated
|
||||
|
||||
static void
|
||||
FillContextAttribs(bool alpha, bool depth, bool stencil, bool bpp16,
|
||||
bool es3, nsTArray<EGLint>* out)
|
||||
CreateContextFlags flags, nsTArray<EGLint>* out)
|
||||
{
|
||||
out->AppendElement(LOCAL_EGL_SURFACE_TYPE);
|
||||
out->AppendElement(LOCAL_EGL_PBUFFER_BIT);
|
||||
|
||||
out->AppendElement(LOCAL_EGL_RENDERABLE_TYPE);
|
||||
if (es3) {
|
||||
out->AppendElement(LOCAL_EGL_OPENGL_ES3_BIT_KHR);
|
||||
} else {
|
||||
out->AppendElement(LOCAL_EGL_OPENGL_ES2_BIT);
|
||||
}
|
||||
out->AppendElement(GetEGLRenderableType(flags));
|
||||
|
||||
out->AppendElement(LOCAL_EGL_RED_SIZE);
|
||||
if (bpp16) {
|
||||
@@ -797,7 +829,7 @@ ChooseConfig(GLLibraryEGL* egl, CreateContextFlags flags, const SurfaceCaps& min
|
||||
{
|
||||
nsTArray<EGLint> configAttribList;
|
||||
FillContextAttribs(minCaps.alpha, minCaps.depth, minCaps.stencil, minCaps.bpp16,
|
||||
bool(flags & CreateContextFlags::PREFER_ES3), &configAttribList);
|
||||
flags, &configAttribList);
|
||||
|
||||
const EGLint* configAttribs = configAttribList.Elements();
|
||||
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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 "GLContextProviderX11.h"
|
||||
|
||||
#include "GLContextProvider.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsString.h"
|
||||
#include "plstr.h"
|
||||
#include "prenv.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace gl {
|
||||
|
||||
namespace {
|
||||
|
||||
enum class X11ProviderKind : uint8_t {
|
||||
Unresolved,
|
||||
EGL,
|
||||
GLX
|
||||
};
|
||||
|
||||
enum class X11ProviderSelection : uint8_t {
|
||||
Auto,
|
||||
EGL,
|
||||
GLX
|
||||
};
|
||||
|
||||
StaticMutex sProviderMutex;
|
||||
X11ProviderKind sProviderKind = X11ProviderKind::Unresolved;
|
||||
|
||||
static X11ProviderSelection
|
||||
ParseProviderSelection(const char* aValue)
|
||||
{
|
||||
if (!aValue || !*aValue) {
|
||||
return X11ProviderSelection::Auto;
|
||||
}
|
||||
|
||||
if (!PL_strcasecmp(aValue, "egl")) {
|
||||
return X11ProviderSelection::EGL;
|
||||
}
|
||||
|
||||
if (!PL_strcasecmp(aValue, "glx")) {
|
||||
return X11ProviderSelection::GLX;
|
||||
}
|
||||
|
||||
return X11ProviderSelection::Auto;
|
||||
}
|
||||
|
||||
static X11ProviderSelection
|
||||
GetProviderSelection()
|
||||
{
|
||||
const char* envValue = PR_GetEnv("MOZ_X11_GL_PROVIDER");
|
||||
if (envValue && *envValue) {
|
||||
return ParseProviderSelection(envValue);
|
||||
}
|
||||
|
||||
nsAdoptingCString prefValue =
|
||||
Preferences::GetCString("gfx.x11.gl-provider");
|
||||
if (prefValue && !prefValue.IsEmpty()) {
|
||||
return ParseProviderSelection(prefValue.get());
|
||||
}
|
||||
|
||||
return X11ProviderSelection::Auto;
|
||||
}
|
||||
|
||||
template<typename EGLFn, typename GLXFn>
|
||||
static already_AddRefed<GLContext>
|
||||
CreateWithFallback(const char* aOperation,
|
||||
EGLFn&& aCreateEGL,
|
||||
GLXFn&& aCreateGLX)
|
||||
{
|
||||
RefPtr<GLContext> context;
|
||||
X11ProviderSelection selection = GetProviderSelection();
|
||||
|
||||
{
|
||||
StaticMutexAutoLock lock(sProviderMutex);
|
||||
if (selection == X11ProviderSelection::GLX ||
|
||||
sProviderKind == X11ProviderKind::GLX)
|
||||
{
|
||||
sProviderKind = X11ProviderKind::GLX;
|
||||
context = aCreateGLX();
|
||||
return context.forget();
|
||||
}
|
||||
}
|
||||
|
||||
context = aCreateEGL();
|
||||
if (context) {
|
||||
StaticMutexAutoLock lock(sProviderMutex);
|
||||
sProviderKind = X11ProviderKind::EGL;
|
||||
return context.forget();
|
||||
}
|
||||
|
||||
if (selection == X11ProviderSelection::EGL) {
|
||||
printf_stderr("GLContextProviderX11: EGL %s failed with provider forced to EGL.\n",
|
||||
aOperation);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
printf_stderr("GLContextProviderX11: EGL %s failed, falling back to GLX.\n",
|
||||
aOperation);
|
||||
|
||||
{
|
||||
StaticMutexAutoLock lock(sProviderMutex);
|
||||
sProviderKind = X11ProviderKind::GLX;
|
||||
}
|
||||
|
||||
context = aCreateGLX();
|
||||
return context.forget();
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderX11::CreateForCompositorWidget(widget::CompositorWidget* aCompositorWidget,
|
||||
bool aForceAccelerated)
|
||||
{
|
||||
return CreateWithFallback(
|
||||
"CreateForCompositorWidget",
|
||||
[&]() {
|
||||
return RefPtr<GLContext>(
|
||||
GLContextProviderEGL::CreateForCompositorWidget(aCompositorWidget,
|
||||
aForceAccelerated));
|
||||
},
|
||||
[&]() {
|
||||
return RefPtr<GLContext>(
|
||||
GLContextProviderGLX::CreateForCompositorWidget(aCompositorWidget,
|
||||
aForceAccelerated));
|
||||
});
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderX11::CreateForWindow(nsIWidget* aWidget, bool aForceAccelerated)
|
||||
{
|
||||
return CreateWithFallback(
|
||||
"CreateForWindow",
|
||||
[&]() {
|
||||
return RefPtr<GLContext>(
|
||||
GLContextProviderEGL::CreateForWindow(aWidget, aForceAccelerated));
|
||||
},
|
||||
[&]() {
|
||||
return RefPtr<GLContext>(
|
||||
GLContextProviderGLX::CreateForWindow(aWidget, aForceAccelerated));
|
||||
});
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderX11::CreateOffscreen(const gfx::IntSize& aSize,
|
||||
const SurfaceCaps& aMinCaps,
|
||||
CreateContextFlags aFlags,
|
||||
nsACString* const aOutFailureId)
|
||||
{
|
||||
return CreateWithFallback(
|
||||
"CreateOffscreen",
|
||||
[&]() {
|
||||
nsAutoCString eglFailureId;
|
||||
RefPtr<GLContext> context =
|
||||
GLContextProviderEGL::CreateOffscreen(aSize, aMinCaps, aFlags,
|
||||
&eglFailureId);
|
||||
if (!context && aOutFailureId) {
|
||||
aOutFailureId->Assign(eglFailureId);
|
||||
}
|
||||
return context;
|
||||
},
|
||||
[&]() {
|
||||
return RefPtr<GLContext>(
|
||||
GLContextProviderGLX::CreateOffscreen(aSize, aMinCaps, aFlags,
|
||||
aOutFailureId));
|
||||
});
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderX11::CreateHeadless(CreateContextFlags aFlags,
|
||||
nsACString* const aOutFailureId)
|
||||
{
|
||||
return CreateWithFallback(
|
||||
"CreateHeadless",
|
||||
[&]() {
|
||||
nsAutoCString eglFailureId;
|
||||
RefPtr<GLContext> context =
|
||||
GLContextProviderEGL::CreateHeadless(aFlags, &eglFailureId);
|
||||
if (!context && aOutFailureId) {
|
||||
aOutFailureId->Assign(eglFailureId);
|
||||
}
|
||||
return context;
|
||||
},
|
||||
[&]() {
|
||||
return RefPtr<GLContext>(
|
||||
GLContextProviderGLX::CreateHeadless(aFlags, aOutFailureId));
|
||||
});
|
||||
}
|
||||
|
||||
already_AddRefed<GLContext>
|
||||
GLContextProviderX11::CreateWrappingExisting(void* aContext, void* aSurface)
|
||||
{
|
||||
return CreateWithFallback(
|
||||
"CreateWrappingExisting",
|
||||
[&]() {
|
||||
return RefPtr<GLContext>(
|
||||
GLContextProviderEGL::CreateWrappingExisting(aContext, aSurface));
|
||||
},
|
||||
[&]() {
|
||||
return RefPtr<GLContext>(
|
||||
GLContextProviderGLX::CreateWrappingExisting(aContext, aSurface));
|
||||
});
|
||||
}
|
||||
|
||||
GLContext*
|
||||
GLContextProviderX11::GetGlobalContext()
|
||||
{
|
||||
X11ProviderSelection selection = GetProviderSelection();
|
||||
|
||||
{
|
||||
StaticMutexAutoLock lock(sProviderMutex);
|
||||
if (selection == X11ProviderSelection::GLX ||
|
||||
sProviderKind == X11ProviderKind::GLX)
|
||||
{
|
||||
sProviderKind = X11ProviderKind::GLX;
|
||||
return GLContextProviderGLX::GetGlobalContext();
|
||||
}
|
||||
}
|
||||
|
||||
GLContext* context = GLContextProviderEGL::GetGlobalContext();
|
||||
if (context) {
|
||||
StaticMutexAutoLock lock(sProviderMutex);
|
||||
sProviderKind = X11ProviderKind::EGL;
|
||||
return context;
|
||||
}
|
||||
|
||||
if (selection == X11ProviderSelection::EGL) {
|
||||
printf_stderr("GLContextProviderX11: EGL GetGlobalContext failed with provider forced to EGL.\n");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
printf_stderr("GLContextProviderX11: EGL GetGlobalContext failed, falling back to GLX.\n");
|
||||
|
||||
{
|
||||
StaticMutexAutoLock lock(sProviderMutex);
|
||||
sProviderKind = X11ProviderKind::GLX;
|
||||
}
|
||||
|
||||
return GLContextProviderGLX::GetGlobalContext();
|
||||
}
|
||||
|
||||
void
|
||||
GLContextProviderX11::Shutdown()
|
||||
{
|
||||
{
|
||||
StaticMutexAutoLock lock(sProviderMutex);
|
||||
sProviderKind = X11ProviderKind::Unresolved;
|
||||
}
|
||||
|
||||
GLContextProviderEGL::Shutdown();
|
||||
GLContextProviderGLX::Shutdown();
|
||||
}
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mozilla
|
||||
@@ -0,0 +1,54 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* 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 GLCONTEXTPROVIDER_X11_H_
|
||||
#define GLCONTEXTPROVIDER_X11_H_
|
||||
|
||||
#include "GLContextTypes.h"
|
||||
#include "SurfaceTypes.h"
|
||||
#include "nsSize.h"
|
||||
|
||||
class nsIWidget;
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
class CompositorWidget;
|
||||
}
|
||||
namespace gl {
|
||||
|
||||
class GLContextProviderX11
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<GLContext>
|
||||
CreateForCompositorWidget(widget::CompositorWidget* aCompositorWidget,
|
||||
bool aForceAccelerated);
|
||||
|
||||
static already_AddRefed<GLContext>
|
||||
CreateForWindow(nsIWidget* aWidget, bool aForceAccelerated);
|
||||
|
||||
static already_AddRefed<GLContext>
|
||||
CreateOffscreen(const gfx::IntSize& aSize,
|
||||
const SurfaceCaps& aMinCaps,
|
||||
CreateContextFlags aFlags,
|
||||
nsACString* const aOutFailureId);
|
||||
|
||||
static already_AddRefed<GLContext>
|
||||
CreateHeadless(CreateContextFlags aFlags,
|
||||
nsACString* const aOutFailureId);
|
||||
|
||||
static already_AddRefed<GLContext>
|
||||
CreateWrappingExisting(void* aContext, void* aSurface);
|
||||
|
||||
static GLContext*
|
||||
GetGlobalContext();
|
||||
|
||||
static void
|
||||
Shutdown();
|
||||
};
|
||||
|
||||
} // namespace gl
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* GLCONTEXTPROVIDER_X11_H_ */
|
||||
@@ -312,7 +312,6 @@ GLLibraryEGL::EnsureInitialized(bool forceAccel, nsACString* const out_failureId
|
||||
// libEGL.so and libEGL.so.1 in that order.
|
||||
|
||||
if (!mEGLLibrary) {
|
||||
printf_stderr("Attempting load of libEGL.so\n");
|
||||
mEGLLibrary = PR_LoadLibrary("libEGL.so");
|
||||
}
|
||||
#if defined(XP_UNIX)
|
||||
@@ -705,4 +704,3 @@ GLLibraryEGL::AfterGLCall(const char* glFunction)
|
||||
|
||||
} /* namespace gl */
|
||||
} /* namespace mozilla */
|
||||
|
||||
|
||||
+12
-4
@@ -53,8 +53,19 @@ EXPORTS += [
|
||||
if CONFIG['MOZ_X11']:
|
||||
EXPORTS += [
|
||||
'GLContextGLX.h',
|
||||
'GLContextProviderX11.h',
|
||||
'GLXLibrary.h',
|
||||
]
|
||||
# GLContextProviderX11.cpp falls back to GLX, so keep the GLX provider
|
||||
# available on all X11 builds even when EGL is the preferred provider.
|
||||
# GLContextProviderGLX.cpp must stay out of UNIFIED_SOURCES because it
|
||||
# includes X11 headers that cause conflicts there.
|
||||
SOURCES += [
|
||||
'GLContextProviderGLX.cpp',
|
||||
]
|
||||
UNIFIED_SOURCES += [
|
||||
'GLContextProviderX11.cpp',
|
||||
]
|
||||
|
||||
# Win32 is a special snowflake, for ANGLE
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
@@ -103,11 +114,8 @@ elif gl_provider == 'EAGL':
|
||||
'GLContextEAGL.h',
|
||||
]
|
||||
|
||||
elif gl_provider == 'GLX':
|
||||
# GLContextProviderGLX.cpp needs to be kept out of UNIFIED_SOURCES
|
||||
# as it includes X11 headers which cause conflicts.
|
||||
if CONFIG['MOZ_X11'] and gl_provider == 'GLX':
|
||||
SOURCES += [
|
||||
'GLContextProviderGLX.cpp',
|
||||
'SharedSurfaceGLX.cpp'
|
||||
]
|
||||
EXPORTS += [
|
||||
|
||||
@@ -7242,7 +7242,7 @@ nsTextFrame::GetCharacterOffsetAtFramePointInternal(nsPoint aPoint,
|
||||
gfxFontUtils::IsRegionalIndicator
|
||||
(SURROGATE_TO_UCS4(frag->CharAt(offs), frag->CharAt(offs + 1)))) {
|
||||
allowSplitLigature = false;
|
||||
if (extraCluster.GetSkippedOffset() > 1 &&
|
||||
if (extraCluster.GetSkippedOffset() >= skippedRange.start + 2 &&
|
||||
!mTextRun->IsLigatureGroupStart(extraCluster.GetSkippedOffset())) {
|
||||
// CountCharsFit() left us in the middle of the flag; back up over the
|
||||
// first character of the ligature, and adjust fitWidth accordingly.
|
||||
|
||||
@@ -4458,6 +4458,10 @@ pref("layers.acceleration.enabled", true);
|
||||
// This requires layers.acceleration.enabled to be set to true
|
||||
pref("layers.acceleration.force", false);
|
||||
|
||||
// Preferred X11 GL context provider. "auto" prefers EGL and falls back to GLX,
|
||||
// "egl" forces EGL, and "glx" forces the legacy GLX path. Restart required.
|
||||
pref("gfx.x11.gl-provider", "auto");
|
||||
|
||||
// Preference that when switched at runtime will run a series of benchmarks
|
||||
// and output the result to stderr.
|
||||
pref("layers.bench.enabled", false);
|
||||
|
||||
+311
-15
@@ -13,14 +13,17 @@
|
||||
// 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
|
||||
// mozilla::widget::glxtest_pipe global variable, forks, and runs that X11 GL probe in the child process,
|
||||
// which runs the glxtest() static function. This creates a X connection, a GL context, calls glGetString, and writes that
|
||||
// to the 'write' end of the pipe.
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
#include <strings.h>
|
||||
#include "nscore.h"
|
||||
#include <fcntl.h>
|
||||
#include "stdint.h"
|
||||
@@ -36,8 +39,18 @@
|
||||
#include "X11/Xlib.h"
|
||||
#include "X11/Xutil.h"
|
||||
|
||||
#include "EGL/egl.h"
|
||||
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
# define LIBGL_FILENAME "libGL.so"
|
||||
# define LIBGL_FILENAME_FALLBACK "libGL.so.1"
|
||||
#else
|
||||
# define LIBGL_FILENAME "libGL.so.1"
|
||||
# define LIBGL_FILENAME_FALLBACK "libGL.so"
|
||||
#endif
|
||||
|
||||
// stuff from glx.h
|
||||
typedef struct __GLXcontextRec *GLXContext;
|
||||
typedef XID GLXPixmap;
|
||||
@@ -71,6 +84,7 @@ extern pid_t glxtest_pid;
|
||||
|
||||
// the write end of the pipe, which we're going to write to
|
||||
static int write_end_of_the_pipe = -1;
|
||||
static std::string sAutoFallbackMessage;
|
||||
|
||||
#if MOZ_WIDGET_GTK == 2
|
||||
static int gtk_write_end_of_the_pipe = -1;
|
||||
@@ -88,28 +102,300 @@ static func_ptr_type cast(void *ptr)
|
||||
);
|
||||
}
|
||||
|
||||
static void
|
||||
write_to_pipe(const char* str, size_t len)
|
||||
{
|
||||
if (str && len) {
|
||||
mozilla::Unused << write(write_end_of_the_pipe, str, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
write_to_pipe(const std::string& str)
|
||||
{
|
||||
write_to_pipe(str.c_str(), str.size());
|
||||
}
|
||||
|
||||
static void fatal_error(const char *str)
|
||||
{
|
||||
mozilla::Unused << write(write_end_of_the_pipe, str, strlen(str));
|
||||
mozilla::Unused << write(write_end_of_the_pipe, "\n", 1);
|
||||
if (!sAutoFallbackMessage.empty()) {
|
||||
write_to_pipe(sAutoFallbackMessage);
|
||||
}
|
||||
write_to_pipe(str, strlen(str));
|
||||
write_to_pipe("\n", 1);
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
enum class ProbeMode {
|
||||
Auto,
|
||||
EGL,
|
||||
GLX
|
||||
};
|
||||
|
||||
static ProbeMode
|
||||
get_probe_mode()
|
||||
{
|
||||
const char* envValue = getenv("MOZ_X11_GL_PROVIDER");
|
||||
if (!envValue || !*envValue) {
|
||||
return ProbeMode::Auto;
|
||||
}
|
||||
|
||||
if (!strcasecmp(envValue, "egl")) {
|
||||
return ProbeMode::EGL;
|
||||
}
|
||||
|
||||
if (!strcasecmp(envValue, "glx")) {
|
||||
return ProbeMode::GLX;
|
||||
}
|
||||
|
||||
return ProbeMode::Auto;
|
||||
}
|
||||
|
||||
static bool
|
||||
load_library(const char* aPrimary,
|
||||
const char* aSecondary,
|
||||
void** aOutLibrary,
|
||||
std::string* aError)
|
||||
{
|
||||
*aOutLibrary = dlopen(aPrimary, RTLD_LAZY);
|
||||
if (!*aOutLibrary && aSecondary) {
|
||||
*aOutLibrary = dlopen(aSecondary, RTLD_LAZY);
|
||||
}
|
||||
|
||||
if (*aOutLibrary) {
|
||||
return true;
|
||||
}
|
||||
|
||||
*aError = std::string("Unable to load ") + aPrimary;
|
||||
if (aSecondary) {
|
||||
*aError += " or ";
|
||||
*aError += aSecondary;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
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",
|
||||
"X error occurred in X11 GL probe, error_code=%d, request_code=%d, minor_code=%d\n",
|
||||
ev->error_code,
|
||||
ev->request_code,
|
||||
ev->minor_code);
|
||||
mozilla::Unused << write(write_end_of_the_pipe, buf, length);
|
||||
if (!sAutoFallbackMessage.empty()) {
|
||||
write_to_pipe(sAutoFallbackMessage);
|
||||
}
|
||||
write_to_pipe(buf, length);
|
||||
_exit(EXIT_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool
|
||||
try_egltest(std::string* aError)
|
||||
{
|
||||
static const EGLint configAttribs[] = {
|
||||
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_ALPHA_SIZE, 0,
|
||||
EGL_NONE
|
||||
};
|
||||
static const EGLint surfaceAttribs[] = {
|
||||
EGL_WIDTH, 16,
|
||||
EGL_HEIGHT, 16,
|
||||
EGL_NONE
|
||||
};
|
||||
static const EGLint contextAttribs[] = {
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
void* libegl = nullptr;
|
||||
if (!load_library("libEGL.so", "libEGL.so.1", &libegl, aError)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void* libgl = nullptr;
|
||||
if (!load_library(LIBGL_FILENAME, LIBGL_FILENAME_FALLBACK, &libgl, aError)) {
|
||||
dlclose(libegl);
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef EGLDisplay (* PFNEGLGETDISPLAY)(EGLNativeDisplayType);
|
||||
typedef EGLBoolean (* PFNEGLINITIALIZE)(EGLDisplay, EGLint*, EGLint*);
|
||||
typedef EGLBoolean (* PFNEGLBINDAPI)(EGLenum);
|
||||
typedef EGLBoolean (* PFNEGLCHOOSECONFIG)(EGLDisplay, const EGLint*, EGLConfig*, EGLint, EGLint*);
|
||||
typedef EGLContext (* PFNEGLCREATECONTEXT)(EGLDisplay, EGLConfig, EGLContext, const EGLint*);
|
||||
typedef EGLSurface (* PFNEGLCREATEPBUFFERSURFACE)(EGLDisplay, EGLConfig, const EGLint*);
|
||||
typedef EGLBoolean (* PFNEGLMAKECURRENT)(EGLDisplay, EGLSurface, EGLSurface, EGLContext);
|
||||
typedef EGLBoolean (* PFNEGLDESTROYCONTEXT)(EGLDisplay, EGLContext);
|
||||
typedef EGLBoolean (* PFNEGLDESTROYSURFACE)(EGLDisplay, EGLSurface);
|
||||
typedef EGLBoolean (* PFNEGLTERMINATE)(EGLDisplay);
|
||||
typedef EGLint (* PFNEGLGETERROR)(void);
|
||||
typedef const GLubyte* (* PFNGLGETSTRING)(GLenum);
|
||||
|
||||
PFNEGLGETDISPLAY eglGetDisplay = cast<PFNEGLGETDISPLAY>(dlsym(libegl, "eglGetDisplay"));
|
||||
PFNEGLINITIALIZE eglInitialize = cast<PFNEGLINITIALIZE>(dlsym(libegl, "eglInitialize"));
|
||||
PFNEGLBINDAPI eglBindAPI = cast<PFNEGLBINDAPI>(dlsym(libegl, "eglBindAPI"));
|
||||
PFNEGLCHOOSECONFIG eglChooseConfig = cast<PFNEGLCHOOSECONFIG>(dlsym(libegl, "eglChooseConfig"));
|
||||
PFNEGLCREATECONTEXT eglCreateContext = cast<PFNEGLCREATECONTEXT>(dlsym(libegl, "eglCreateContext"));
|
||||
PFNEGLCREATEPBUFFERSURFACE eglCreatePbufferSurface =
|
||||
cast<PFNEGLCREATEPBUFFERSURFACE>(dlsym(libegl, "eglCreatePbufferSurface"));
|
||||
PFNEGLMAKECURRENT eglMakeCurrent = cast<PFNEGLMAKECURRENT>(dlsym(libegl, "eglMakeCurrent"));
|
||||
PFNEGLDESTROYCONTEXT eglDestroyContext = cast<PFNEGLDESTROYCONTEXT>(dlsym(libegl, "eglDestroyContext"));
|
||||
PFNEGLDESTROYSURFACE eglDestroySurface = cast<PFNEGLDESTROYSURFACE>(dlsym(libegl, "eglDestroySurface"));
|
||||
PFNEGLTERMINATE eglTerminate = cast<PFNEGLTERMINATE>(dlsym(libegl, "eglTerminate"));
|
||||
PFNEGLGETERROR eglGetError = cast<PFNEGLGETERROR>(dlsym(libegl, "eglGetError"));
|
||||
PFNGLGETSTRING glGetString = cast<PFNGLGETSTRING>(dlsym(libgl, "glGetString"));
|
||||
|
||||
if (!eglGetDisplay ||
|
||||
!eglInitialize ||
|
||||
!eglBindAPI ||
|
||||
!eglChooseConfig ||
|
||||
!eglCreateContext ||
|
||||
!eglCreatePbufferSurface ||
|
||||
!eglMakeCurrent ||
|
||||
!eglDestroyContext ||
|
||||
!eglDestroySurface ||
|
||||
!eglTerminate ||
|
||||
!eglGetError ||
|
||||
!glGetString)
|
||||
{
|
||||
*aError = "EGL probe couldn't find required EGL/OpenGL symbols";
|
||||
dlclose(libgl);
|
||||
dlclose(libegl);
|
||||
return false;
|
||||
}
|
||||
|
||||
Display* dpy = XOpenDisplay(nullptr);
|
||||
if (!dpy) {
|
||||
*aError = "Unable to open a connection to the X server";
|
||||
dlclose(libgl);
|
||||
dlclose(libegl);
|
||||
return false;
|
||||
}
|
||||
|
||||
EGLDisplay eglDisplay = EGL_NO_DISPLAY;
|
||||
EGLSurface surface = EGL_NO_SURFACE;
|
||||
EGLContext context = EGL_NO_CONTEXT;
|
||||
EGLConfig config = nullptr;
|
||||
EGLint major = 0;
|
||||
EGLint minor = 0;
|
||||
EGLint configCount = 0;
|
||||
const GLubyte* vendorString = nullptr;
|
||||
const GLubyte* rendererString = nullptr;
|
||||
const GLubyte* versionString = nullptr;
|
||||
enum { bufsize = 1024 };
|
||||
char buf[bufsize];
|
||||
int length = 0;
|
||||
|
||||
eglDisplay = eglGetDisplay((EGLNativeDisplayType)dpy);
|
||||
if (eglDisplay == EGL_NO_DISPLAY) {
|
||||
*aError = "EGL probe could not get an EGL display";
|
||||
goto egltest_error;
|
||||
}
|
||||
|
||||
if (!eglInitialize(eglDisplay, &major, &minor)) {
|
||||
*aError = "EGL probe could not initialize EGL";
|
||||
goto egltest_error;
|
||||
}
|
||||
|
||||
if (!eglBindAPI(EGL_OPENGL_API)) {
|
||||
*aError = "EGL probe could not bind the OpenGL API";
|
||||
goto egltest_error;
|
||||
}
|
||||
|
||||
if (!eglChooseConfig(eglDisplay, configAttribs, &config, 1, &configCount) ||
|
||||
configCount < 1)
|
||||
{
|
||||
*aError = "EGL probe could not find a suitable EGLConfig";
|
||||
goto egltest_error;
|
||||
}
|
||||
|
||||
surface = eglCreatePbufferSurface(eglDisplay, config, surfaceAttribs);
|
||||
if (surface == EGL_NO_SURFACE) {
|
||||
*aError = "EGL probe could not create a pbuffer surface";
|
||||
goto egltest_error;
|
||||
}
|
||||
|
||||
context = eglCreateContext(eglDisplay, config, EGL_NO_CONTEXT, contextAttribs);
|
||||
if (context == EGL_NO_CONTEXT) {
|
||||
eglDestroySurface(eglDisplay, surface);
|
||||
*aError = "EGL probe could not create an EGL context";
|
||||
goto egltest_error;
|
||||
}
|
||||
|
||||
if (!eglMakeCurrent(eglDisplay, surface, surface, context)) {
|
||||
eglDestroyContext(eglDisplay, context);
|
||||
eglDestroySurface(eglDisplay, surface);
|
||||
*aError = "EGL probe could not make the EGL context current";
|
||||
goto egltest_error;
|
||||
}
|
||||
|
||||
vendorString = glGetString(GL_VENDOR);
|
||||
rendererString = glGetString(GL_RENDERER);
|
||||
versionString = glGetString(GL_VERSION);
|
||||
|
||||
if (!vendorString || !rendererString || !versionString) {
|
||||
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglDestroyContext(eglDisplay, context);
|
||||
eglDestroySurface(eglDisplay, surface);
|
||||
*aError = "EGL probe glGetString returned null";
|
||||
goto egltest_error;
|
||||
}
|
||||
|
||||
length = snprintf(buf, bufsize,
|
||||
"PROVIDER\nEGL\nVENDOR\n%s\nRENDERER\n%s\nVERSION\n%s\nTFP\nFALSE\n",
|
||||
vendorString,
|
||||
rendererString,
|
||||
versionString);
|
||||
if (length >= bufsize) {
|
||||
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglDestroyContext(eglDisplay, context);
|
||||
eglDestroySurface(eglDisplay, surface);
|
||||
*aError = "EGL probe GL strings length too large for buffer size";
|
||||
goto egltest_error;
|
||||
}
|
||||
|
||||
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
eglDestroyContext(eglDisplay, context);
|
||||
eglDestroySurface(eglDisplay, surface);
|
||||
eglTerminate(eglDisplay);
|
||||
|
||||
#ifdef NS_FREE_PERMANENT_DATA
|
||||
XCloseDisplay(dpy);
|
||||
#else
|
||||
XSync(dpy, False);
|
||||
#endif
|
||||
|
||||
dlclose(libgl);
|
||||
dlclose(libegl);
|
||||
|
||||
write_to_pipe(buf, length);
|
||||
return true;
|
||||
|
||||
egltest_error:
|
||||
if (!aError->empty() && eglGetError) {
|
||||
char eglErrorBuf[128];
|
||||
int length = snprintf(eglErrorBuf, sizeof(eglErrorBuf),
|
||||
" (EGL error 0x%04x)", eglGetError());
|
||||
if (length > 0 && size_t(length) < sizeof(eglErrorBuf)) {
|
||||
aError->append(eglErrorBuf);
|
||||
}
|
||||
}
|
||||
#ifdef NS_FREE_PERMANENT_DATA
|
||||
XCloseDisplay(dpy);
|
||||
#else
|
||||
XSync(dpy, False);
|
||||
#endif
|
||||
dlclose(libgl);
|
||||
dlclose(libegl);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// glxtest is declared inside extern "C" so that the name is not mangled.
|
||||
// The name is used in build/valgrind/x86_64-redhat-linux-gnu.sup to suppress
|
||||
@@ -160,15 +446,25 @@ void glxtest()
|
||||
if (getenv("MOZ_AVOID_OPENGL_ALTOGETHER"))
|
||||
fatal_error("The MOZ_AVOID_OPENGL_ALTOGETHER environment variable is defined");
|
||||
|
||||
ProbeMode probeMode = get_probe_mode();
|
||||
if (probeMode != ProbeMode::GLX) {
|
||||
std::string eglError;
|
||||
if (try_egltest(&eglError)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (probeMode == ProbeMode::EGL) {
|
||||
fatal_error(eglError.c_str());
|
||||
}
|
||||
|
||||
sAutoFallbackMessage = "EGL probe failed, falling back to GLX: " + eglError + "\n";
|
||||
}
|
||||
|
||||
///// Open libGL and load needed symbols /////
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
#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);
|
||||
void* libgl = nullptr;
|
||||
std::string libglError;
|
||||
if (!load_library(LIBGL_FILENAME, LIBGL_FILENAME_FALLBACK, &libgl, &libglError))
|
||||
fatal_error(libglError.c_str());
|
||||
|
||||
typedef void* (* PFNGLXGETPROCADDRESS) (const char *);
|
||||
PFNGLXGETPROCADDRESS glXGetProcAddress = cast<PFNGLXGETPROCADDRESS>(dlsym(libgl, "glXGetProcAddress"));
|
||||
@@ -260,7 +556,7 @@ void glxtest()
|
||||
fatal_error("glGetString returned null");
|
||||
|
||||
int length = snprintf(buf, bufsize,
|
||||
"VENDOR\n%s\nRENDERER\n%s\nVERSION\n%s\nTFP\n%s\n",
|
||||
"PROVIDER\nGLX\nVENDOR\n%s\nRENDERER\n%s\nVERSION\n%s\nTFP\n%s\n",
|
||||
vendorString,
|
||||
rendererString,
|
||||
versionString,
|
||||
|
||||
+10
-7
@@ -43,7 +43,10 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
|
||||
|
||||
if CONFIG['MOZ_X11']:
|
||||
EXPORTS += ['nsX11ErrorHandler.h']
|
||||
UNIFIED_SOURCES += ['nsX11ErrorHandler.cpp']
|
||||
UNIFIED_SOURCES += [
|
||||
'glxtest.cpp',
|
||||
'nsX11ErrorHandler.cpp',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'CreateAppData.cpp',
|
||||
@@ -62,11 +65,6 @@ SOURCES += [
|
||||
'ProfileReset.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_GL_DEFAULT_PROVIDER'] == 'GLX':
|
||||
UNIFIED_SOURCES += [
|
||||
'glxtest.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_INSTRUMENT_EVENT_LOOP']:
|
||||
UNIFIED_SOURCES += [
|
||||
'EventTracer.cpp',
|
||||
@@ -82,7 +80,7 @@ include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
if CONFIG['MOZ_GL_DEFAULT_PROVIDER'] == 'GLX':
|
||||
if CONFIG['MOZ_X11']:
|
||||
DEFINES['USE_GLX_TEST'] = True
|
||||
|
||||
for var in ('MOZ_APP_NAME',
|
||||
@@ -132,6 +130,11 @@ if CONFIG['MOZ_ENABLE_XREMOTE']:
|
||||
'/widget/xremoteclient',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_X11']:
|
||||
LOCAL_INCLUDES += [
|
||||
'/gfx/angle/include',
|
||||
]
|
||||
|
||||
CXXFLAGS += CONFIG['TK_CFLAGS']
|
||||
CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
|
||||
|
||||
|
||||
+23
-4
@@ -6,6 +6,7 @@
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <sys/utsname.h>
|
||||
#include "nsCRTGlue.h"
|
||||
@@ -27,6 +28,7 @@ pid_t glxtest_pid = 0;
|
||||
nsresult
|
||||
GfxInfo::Init()
|
||||
{
|
||||
mGLImplementation.Truncate();
|
||||
mGLMajorVersion = 0;
|
||||
mMajorVersion = 0;
|
||||
mMinorVersion = 0;
|
||||
@@ -111,6 +113,8 @@ GfxInfo::GetData()
|
||||
stringToFill->Assign(line);
|
||||
stringToFill = nullptr;
|
||||
}
|
||||
else if(!strcmp(line, "PROVIDER"))
|
||||
stringToFill = &mGLImplementation;
|
||||
else if(!strcmp(line, "VENDOR"))
|
||||
stringToFill = &mVendor;
|
||||
else if(!strcmp(line, "RENDERER"))
|
||||
@@ -125,6 +129,10 @@ GfxInfo::GetData()
|
||||
if (!strcmp(textureFromPixmap.get(), "TRUE"))
|
||||
mHasTextureFromPixmap = true;
|
||||
|
||||
if (mGLImplementation.IsEmpty()) {
|
||||
mGLImplementation.AssignLiteral("GLX");
|
||||
}
|
||||
|
||||
// only useful for Linux kernel version check for FGLRX driver.
|
||||
// assumes X client == X server, which is sad.
|
||||
struct utsname unameobj;
|
||||
@@ -151,13 +159,14 @@ GfxInfo::GetData()
|
||||
mOSRelease.Assign(spoofedOSRelease);
|
||||
|
||||
if (error ||
|
||||
mGLImplementation.IsEmpty() ||
|
||||
mVendor.IsEmpty() ||
|
||||
mRenderer.IsEmpty() ||
|
||||
mVersion.IsEmpty() ||
|
||||
mOS.IsEmpty() ||
|
||||
mOSRelease.IsEmpty())
|
||||
{
|
||||
mAdapterDescription.AppendLiteral("GLXtest process failed");
|
||||
mAdapterDescription.AppendLiteral("X11 GL probe 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)
|
||||
@@ -175,9 +184,14 @@ GfxInfo::GetData()
|
||||
mAdapterDescription.Append(mVendor);
|
||||
mAdapterDescription.AppendLiteral(" -- ");
|
||||
mAdapterDescription.Append(mRenderer);
|
||||
mAdapterDescription.AppendLiteral(" (");
|
||||
mAdapterDescription.Append(mGLImplementation);
|
||||
mAdapterDescription.Append(')');
|
||||
|
||||
nsAutoCString note;
|
||||
note.AppendLiteral("OpenGL: ");
|
||||
note.AppendLiteral("OpenGL (");
|
||||
note.Append(mGLImplementation);
|
||||
note.AppendLiteral("): ");
|
||||
note.Append(mAdapterDescription);
|
||||
note.AppendLiteral(" -- ");
|
||||
note.Append(mVersion);
|
||||
@@ -194,8 +208,13 @@ GfxInfo::GetData()
|
||||
#define strcasestr PL_strcasestr
|
||||
#endif
|
||||
|
||||
// determine the major OpenGL version. That's the first integer in the version string.
|
||||
mGLMajorVersion = strtol(mVersion.get(), 0, 10);
|
||||
// Determine the major GL version from the first digit sequence in the
|
||||
// version string. EGL/GLES strings commonly begin with "OpenGL ES ".
|
||||
const char* versionString = mVersion.get();
|
||||
while (*versionString && !isdigit(*versionString)) {
|
||||
versionString++;
|
||||
}
|
||||
mGLMajorVersion = strtol(versionString, nullptr, 10);
|
||||
|
||||
// determine driver type (vendor) and where in the version string
|
||||
// the actual driver version numbers should be expected to be found (whereToReadVersionNumbers)
|
||||
|
||||
@@ -64,6 +64,7 @@ protected:
|
||||
virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() override;
|
||||
|
||||
private:
|
||||
nsCString mGLImplementation;
|
||||
nsCString mVendor;
|
||||
nsCString mRenderer;
|
||||
nsCString mVersion;
|
||||
|
||||
Reference in New Issue
Block a user