Merge remote-tracking branch 'origin/tracking' into custom

This commit is contained in:
2026-05-08 06:46:05 +08:00
17 changed files with 807 additions and 114 deletions
+2 -2
View File
@@ -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
View File
@@ -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;
+1 -1
View File
@@ -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))
{
+7 -5
View File
@@ -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);
+8 -2
View File
@@ -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
+99 -67
View File
@@ -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();
+262
View File
@@ -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
+54
View File
@@ -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_ */
-2
View File
@@ -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
View File
@@ -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 += [
+1 -1
View File
@@ -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.
+4
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+1
View File
@@ -64,6 +64,7 @@ protected:
virtual const nsTArray<GfxDriverInfo>& GetGfxDriverInfo() override;
private:
nsCString mGLImplementation;
nsCString mVendor;
nsCString mRenderer;
nsCString mVersion;