зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1635451
- Allow GLX to work in headless content processes. r=jgilbert
This follows what we're already doing for EGL: a refcounted object which can own the X connection, where we hold a weak reference from the library object so that multiple contexts opportunistically share the display but we close the connection when the last context is freed/GCed. In a process where GTK is initialized, we borrow its display instead of opening a new one, which preserves the existing behavior. Differential Revision: https://phabricator.services.mozilla.com/D112195
This commit is contained in:
Родитель
a8d8e90b70
Коммит
dc3ae62544
|
@ -20,8 +20,9 @@ class GLContextGLX : public GLContext {
|
||||||
public:
|
public:
|
||||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextGLX, override)
|
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextGLX, override)
|
||||||
static already_AddRefed<GLContextGLX> CreateGLContext(
|
static already_AddRefed<GLContextGLX> CreateGLContext(
|
||||||
const GLContextDesc&, Display* display, GLXDrawable drawable,
|
const GLContextDesc&, std::shared_ptr<gfx::XlibDisplay> display,
|
||||||
GLXFBConfig cfg, bool deleteDrawable, gfxXlibSurface* pixmap);
|
GLXDrawable drawable, GLXFBConfig cfg, bool deleteDrawable,
|
||||||
|
gfxXlibSurface* pixmap);
|
||||||
|
|
||||||
static bool FindVisual(Display* display, int screen, bool useWebRender,
|
static bool FindVisual(Display* display, int screen, bool useWebRender,
|
||||||
bool useAlpha, int* const out_visualId);
|
bool useAlpha, int* const out_visualId);
|
||||||
|
@ -67,12 +68,12 @@ class GLContextGLX : public GLContext {
|
||||||
private:
|
private:
|
||||||
friend class GLContextProviderGLX;
|
friend class GLContextProviderGLX;
|
||||||
|
|
||||||
GLContextGLX(const GLContextDesc&, Display* aDisplay, GLXDrawable aDrawable,
|
GLContextGLX(const GLContextDesc&, std::shared_ptr<gfx::XlibDisplay> aDisplay,
|
||||||
GLXContext aContext, bool aDeleteDrawable, bool aDoubleBuffered,
|
GLXDrawable aDrawable, GLXContext aContext, bool aDeleteDrawable,
|
||||||
gfxXlibSurface* aPixmap);
|
bool aDoubleBuffered, gfxXlibSurface* aPixmap);
|
||||||
|
|
||||||
const GLXContext mContext;
|
const GLXContext mContext;
|
||||||
Display* const mDisplay;
|
const std::shared_ptr<gfx::XlibDisplay> mDisplay;
|
||||||
const GLXDrawable mDrawable;
|
const GLXDrawable mDrawable;
|
||||||
const bool mDeleteDrawable;
|
const bool mDeleteDrawable;
|
||||||
const bool mDoubleBuffered;
|
const bool mDoubleBuffered;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "mozilla/layers/CompositorOptions.h"
|
#include "mozilla/layers/CompositorOptions.h"
|
||||||
#include "mozilla/Range.h"
|
#include "mozilla/Range.h"
|
||||||
#include "mozilla/ScopeExit.h"
|
#include "mozilla/ScopeExit.h"
|
||||||
|
#include "mozilla/Sprintf.h"
|
||||||
#include "mozilla/StaticPrefs_gfx.h"
|
#include "mozilla/StaticPrefs_gfx.h"
|
||||||
#include "mozilla/StaticPrefs_layout.h"
|
#include "mozilla/StaticPrefs_layout.h"
|
||||||
#include "mozilla/widget/CompositorWidget.h"
|
#include "mozilla/widget/CompositorWidget.h"
|
||||||
|
@ -59,7 +60,7 @@ static inline bool HasExtension(const char* aExtensions,
|
||||||
reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension);
|
reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLXLibrary::EnsureInitialized() {
|
bool GLXLibrary::EnsureInitialized(Display* aDisplay) {
|
||||||
if (mInitialized) {
|
if (mInitialized) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +71,11 @@ bool GLXLibrary::EnsureInitialized() {
|
||||||
}
|
}
|
||||||
mTriedInitializing = true;
|
mTriedInitializing = true;
|
||||||
|
|
||||||
|
MOZ_ASSERT(aDisplay);
|
||||||
|
if (!aDisplay) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Force enabling s3 texture compression. (Bug 774134)
|
// Force enabling s3 texture compression. (Bug 774134)
|
||||||
PR_SetEnv("force_s3tc_enable=true");
|
PR_SetEnv("force_s3tc_enable=true");
|
||||||
|
|
||||||
|
@ -148,12 +154,11 @@ bool GLXLibrary::EnsureInitialized() {
|
||||||
}
|
}
|
||||||
const SymbolLoader pfnLoader(mSymbols.fGetProcAddress);
|
const SymbolLoader pfnLoader(mSymbols.fGetProcAddress);
|
||||||
|
|
||||||
Display* display = DefaultXDisplay();
|
int screen = DefaultScreen(aDisplay);
|
||||||
int screen = DefaultScreen(display);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
int major, minor;
|
int major, minor;
|
||||||
if (!fQueryVersion(display, &major, &minor) || major != 1 || minor < 3) {
|
if (!fQueryVersion(aDisplay, &major, &minor) || major != 1 || minor < 3) {
|
||||||
NS_ERROR("GLX version older than 1.3. (released in 1998)");
|
NS_ERROR("GLX version older than 1.3. (released in 1998)");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -181,10 +186,10 @@ bool GLXLibrary::EnsureInitialized() {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* clientVendor = fGetClientString(display, LOCAL_GLX_VENDOR);
|
const char* clientVendor = fGetClientString(aDisplay, LOCAL_GLX_VENDOR);
|
||||||
const char* serverVendor =
|
const char* serverVendor =
|
||||||
fQueryServerString(display, screen, LOCAL_GLX_VENDOR);
|
fQueryServerString(aDisplay, screen, LOCAL_GLX_VENDOR);
|
||||||
const char* extensionsStr = fQueryExtensionsString(display, screen);
|
const char* extensionsStr = fQueryExtensionsString(aDisplay, screen);
|
||||||
|
|
||||||
if (HasExtension(extensionsStr, "GLX_EXT_texture_from_pixmap") &&
|
if (HasExtension(extensionsStr, "GLX_EXT_texture_from_pixmap") &&
|
||||||
fnLoadSymbols(symbols_texturefrompixmap)) {
|
fnLoadSymbols(symbols_texturefrompixmap)) {
|
||||||
|
@ -240,19 +245,20 @@ bool GLXLibrary::EnsureInitialized() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLXLibrary::SupportsTextureFromPixmap(gfxASurface* aSurface) {
|
bool GLXLibrary::SupportsTextureFromPixmap(gfxASurface* aSurface) {
|
||||||
if (!EnsureInitialized()) {
|
if (aSurface->GetType() != gfxSurfaceType::Xlib) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aSurface->GetType() != gfxSurfaceType::Xlib || !mUseTextureFromPixmap) {
|
gfxXlibSurface* xs = static_cast<gfxXlibSurface*>(aSurface);
|
||||||
|
if (!EnsureInitialized(xs->XDisplay())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return mUseTextureFromPixmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLXLibrary::SupportsVideoSync() {
|
bool GLXLibrary::SupportsVideoSync(Display* aDisplay) {
|
||||||
if (!EnsureInitialized()) {
|
if (!EnsureInitialized(aDisplay)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,8 +456,9 @@ static int GLXErrorHandler(Display* display, XErrorEvent* ev) {
|
||||||
}
|
}
|
||||||
|
|
||||||
GLXLibrary::WrapperScope::WrapperScope(const GLXLibrary& glx,
|
GLXLibrary::WrapperScope::WrapperScope(const GLXLibrary& glx,
|
||||||
const char* const funcName)
|
const char* const funcName,
|
||||||
: mGlx(glx), mFuncName(funcName) {
|
Display* aDisplay)
|
||||||
|
: mGlx(glx), mFuncName(funcName), mDisplay(aDisplay) {
|
||||||
if (mGlx.mDebug) {
|
if (mGlx.mDebug) {
|
||||||
sOldErrorHandler = XSetErrorHandler(GLXErrorHandler);
|
sOldErrorHandler = XSetErrorHandler(GLXErrorHandler);
|
||||||
}
|
}
|
||||||
|
@ -459,11 +466,17 @@ GLXLibrary::WrapperScope::WrapperScope(const GLXLibrary& glx,
|
||||||
|
|
||||||
GLXLibrary::WrapperScope::~WrapperScope() {
|
GLXLibrary::WrapperScope::~WrapperScope() {
|
||||||
if (mGlx.mDebug) {
|
if (mGlx.mDebug) {
|
||||||
FinishX(DefaultXDisplay());
|
if (mDisplay) {
|
||||||
|
FinishX(mDisplay);
|
||||||
|
}
|
||||||
if (sErrorEvent.mError.error_code) {
|
if (sErrorEvent.mError.error_code) {
|
||||||
char buffer[100] = {};
|
char buffer[100] = {};
|
||||||
XGetErrorText(DefaultXDisplay(), sErrorEvent.mError.error_code, buffer,
|
if (mDisplay) {
|
||||||
|
XGetErrorText(mDisplay, sErrorEvent.mError.error_code, buffer,
|
||||||
sizeof(buffer));
|
sizeof(buffer));
|
||||||
|
} else {
|
||||||
|
SprintfLiteral(buffer, "%d", sErrorEvent.mError.error_code);
|
||||||
|
}
|
||||||
printf_stderr("X ERROR after %s: %s (%i) - Request: %i.%i, Serial: %lu",
|
printf_stderr("X ERROR after %s: %s (%i) - Request: %i.%i, Serial: %lu",
|
||||||
mFuncName, buffer, sErrorEvent.mError.error_code,
|
mFuncName, buffer, sErrorEvent.mError.error_code,
|
||||||
sErrorEvent.mError.request_code,
|
sErrorEvent.mError.request_code,
|
||||||
|
@ -474,13 +487,45 @@ GLXLibrary::WrapperScope::~WrapperScope() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns the GTK display if available; otherwise, if a display was
|
||||||
|
// previously opened by this method and is still open, returns a
|
||||||
|
// reference to it; otherwise, opens a new connection. (The non-GTK
|
||||||
|
// cases are similar to what we do for EGL.)
|
||||||
|
std::shared_ptr<XlibDisplay> GLXLibrary::GetDisplay() {
|
||||||
|
std::shared_ptr<XlibDisplay> display;
|
||||||
|
|
||||||
|
#ifdef MOZ_WIDGET_GTK
|
||||||
|
static const bool kHaveGtk = !!gdk_display_get_default();
|
||||||
|
if (kHaveGtk) {
|
||||||
|
display = XlibDisplay::Borrow(DefaultXDisplay());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (display) {
|
||||||
|
return display;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ownDisplay = mOwnDisplay.Lock();
|
||||||
|
display = ownDisplay->lock();
|
||||||
|
if (display) {
|
||||||
|
return display;
|
||||||
|
}
|
||||||
|
|
||||||
|
display = XlibDisplay::Open(nullptr);
|
||||||
|
if (NS_WARN_IF(!display)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
*ownDisplay = display;
|
||||||
|
return display;
|
||||||
|
}
|
||||||
|
|
||||||
already_AddRefed<GLContextGLX> GLContextGLX::CreateGLContext(
|
already_AddRefed<GLContextGLX> GLContextGLX::CreateGLContext(
|
||||||
const GLContextDesc& desc, Display* display, GLXDrawable drawable,
|
const GLContextDesc& desc, std::shared_ptr<XlibDisplay> display,
|
||||||
GLXFBConfig cfg, bool deleteDrawable, gfxXlibSurface* pixmap) {
|
GLXDrawable drawable, GLXFBConfig cfg, bool deleteDrawable,
|
||||||
|
gfxXlibSurface* pixmap) {
|
||||||
GLXLibrary& glx = sGLXLibrary;
|
GLXLibrary& glx = sGLXLibrary;
|
||||||
|
|
||||||
int isDoubleBuffered = 0;
|
int isDoubleBuffered = 0;
|
||||||
int err = glx.fGetFBConfigAttrib(display, cfg, LOCAL_GLX_DOUBLEBUFFER,
|
int err = glx.fGetFBConfigAttrib(*display, cfg, LOCAL_GLX_DOUBLEBUFFER,
|
||||||
&isDoubleBuffered);
|
&isDoubleBuffered);
|
||||||
if (LOCAL_GLX_BAD_ATTRIBUTE != err) {
|
if (LOCAL_GLX_BAD_ATTRIBUTE != err) {
|
||||||
if (ShouldSpew()) {
|
if (ShouldSpew()) {
|
||||||
|
@ -507,15 +552,15 @@ already_AddRefed<GLContextGLX> GLContextGLX::CreateGLContext(
|
||||||
// we should not try to use such contexts. (Errors may come from the
|
// we should not try to use such contexts. (Errors may come from the
|
||||||
// distant server, or something)
|
// distant server, or something)
|
||||||
const auto glxContext = glx.fCreateContextAttribs(
|
const auto glxContext = glx.fCreateContextAttribs(
|
||||||
display, cfg, nullptr, X11True, terminated.data());
|
*display, cfg, nullptr, X11True, terminated.data());
|
||||||
if (!glxContext) return nullptr;
|
if (!glxContext) return nullptr;
|
||||||
const RefPtr<GLContextGLX> ret =
|
const RefPtr<GLContextGLX> ret =
|
||||||
new GLContextGLX(desc, display, drawable, glxContext, deleteDrawable,
|
new GLContextGLX(desc, display, drawable, glxContext, deleteDrawable,
|
||||||
isDoubleBuffered, pixmap);
|
isDoubleBuffered, pixmap);
|
||||||
if (handler.SyncAndGetError(display)) return nullptr;
|
if (handler.SyncAndGetError(*display)) return nullptr;
|
||||||
|
|
||||||
if (!ret->Init()) return nullptr;
|
if (!ret->Init()) return nullptr;
|
||||||
if (handler.SyncAndGetError(display)) return nullptr;
|
if (handler.SyncAndGetError(*display)) return nullptr;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
|
@ -602,15 +647,15 @@ GLContextGLX::~GLContextGLX() {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
bool success =
|
bool success =
|
||||||
#endif
|
#endif
|
||||||
mGLX->fMakeCurrent(mDisplay, X11None, nullptr);
|
mGLX->fMakeCurrent(*mDisplay, X11None, nullptr);
|
||||||
MOZ_ASSERT(success,
|
MOZ_ASSERT(success,
|
||||||
"glXMakeCurrent failed to release GL context before we call "
|
"glXMakeCurrent failed to release GL context before we call "
|
||||||
"glXDestroyContext!");
|
"glXDestroyContext!");
|
||||||
|
|
||||||
mGLX->fDestroyContext(mDisplay, mContext);
|
mGLX->fDestroyContext(*mDisplay, mContext);
|
||||||
|
|
||||||
if (mDeleteDrawable) {
|
if (mDeleteDrawable) {
|
||||||
mGLX->fDestroyPixmap(mDisplay, mDrawable);
|
mGLX->fDestroyPixmap(*mDisplay, mDrawable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -632,10 +677,10 @@ bool GLContextGLX::MakeCurrentImpl() const {
|
||||||
if (mGLX->IsMesa()) {
|
if (mGLX->IsMesa()) {
|
||||||
// Read into the event queue to ensure that Mesa receives a
|
// Read into the event queue to ensure that Mesa receives a
|
||||||
// DRI2InvalidateBuffers event before drawing. See bug 1280653.
|
// DRI2InvalidateBuffers event before drawing. See bug 1280653.
|
||||||
Unused << XPending(mDisplay);
|
Unused << XPending(*mDisplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool succeeded = mGLX->fMakeCurrent(mDisplay, mDrawable, mContext);
|
const bool succeeded = mGLX->fMakeCurrent(*mDisplay, mDrawable, mContext);
|
||||||
NS_ASSERTION(succeeded, "Failed to make GL context current!");
|
NS_ASSERTION(succeeded, "Failed to make GL context current!");
|
||||||
|
|
||||||
if (!IsOffscreen() && mGLX->SupportsSwapControl()) {
|
if (!IsOffscreen() && mGLX->SupportsSwapControl()) {
|
||||||
|
@ -643,7 +688,7 @@ bool GLContextGLX::MakeCurrentImpl() const {
|
||||||
// VBlank when calling glXSwapBuffers. We want to run unthrottled
|
// VBlank when calling glXSwapBuffers. We want to run unthrottled
|
||||||
// in ASAP mode. See bug 1280744.
|
// in ASAP mode. See bug 1280744.
|
||||||
const bool isASAP = (StaticPrefs::layout_frame_rate() == 0);
|
const bool isASAP = (StaticPrefs::layout_frame_rate() == 0);
|
||||||
mGLX->fSwapInterval(mDisplay, mDrawable, isASAP ? 0 : 1);
|
mGLX->fSwapInterval(*mDisplay, mDrawable, isASAP ? 0 : 1);
|
||||||
}
|
}
|
||||||
return succeeded;
|
return succeeded;
|
||||||
}
|
}
|
||||||
|
@ -661,7 +706,7 @@ bool GLContextGLX::IsDoubleBuffered() const { return mDoubleBuffered; }
|
||||||
|
|
||||||
bool GLContextGLX::SwapBuffers() {
|
bool GLContextGLX::SwapBuffers() {
|
||||||
if (!mDoubleBuffered) return false;
|
if (!mDoubleBuffered) return false;
|
||||||
mGLX->fSwapBuffers(mDisplay, mDrawable);
|
mGLX->fSwapBuffers(*mDisplay, mDrawable);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -671,7 +716,7 @@ GLint GLContextGLX::GetBufferAge() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint result = 0;
|
GLuint result = 0;
|
||||||
mGLX->fQueryDrawable(mDisplay, mDrawable, LOCAL_GLX_BACK_BUFFER_AGE_EXT,
|
mGLX->fQueryDrawable(*mDisplay, mDrawable, LOCAL_GLX_BACK_BUFFER_AGE_EXT,
|
||||||
&result);
|
&result);
|
||||||
if (result > INT32_MAX) {
|
if (result > INT32_MAX) {
|
||||||
// If the result can't fit, just assume the buffer cannot be reused.
|
// If the result can't fit, just assume the buffer cannot be reused.
|
||||||
|
@ -681,34 +726,34 @@ GLint GLContextGLX::GetBufferAge() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLContextGLX::GetWSIInfo(nsCString* const out) const {
|
void GLContextGLX::GetWSIInfo(nsCString* const out) const {
|
||||||
Display* display = DefaultXDisplay();
|
int screen = DefaultScreen(mDisplay->get());
|
||||||
int screen = DefaultScreen(display);
|
|
||||||
|
|
||||||
int majorVersion, minorVersion;
|
int majorVersion, minorVersion;
|
||||||
sGLXLibrary.fQueryVersion(display, &majorVersion, &minorVersion);
|
sGLXLibrary.fQueryVersion(*mDisplay, &majorVersion, &minorVersion);
|
||||||
|
|
||||||
out->Append(nsPrintfCString("GLX %u.%u", majorVersion, minorVersion));
|
out->Append(nsPrintfCString("GLX %u.%u", majorVersion, minorVersion));
|
||||||
|
|
||||||
out->AppendLiteral("\nGLX_VENDOR(client): ");
|
out->AppendLiteral("\nGLX_VENDOR(client): ");
|
||||||
out->Append(sGLXLibrary.fGetClientString(display, LOCAL_GLX_VENDOR));
|
out->Append(sGLXLibrary.fGetClientString(*mDisplay, LOCAL_GLX_VENDOR));
|
||||||
|
|
||||||
out->AppendLiteral("\nGLX_VENDOR(server): ");
|
out->AppendLiteral("\nGLX_VENDOR(server): ");
|
||||||
out->Append(
|
out->Append(
|
||||||
sGLXLibrary.fQueryServerString(display, screen, LOCAL_GLX_VENDOR));
|
sGLXLibrary.fQueryServerString(*mDisplay, screen, LOCAL_GLX_VENDOR));
|
||||||
|
|
||||||
out->AppendLiteral("\nExtensions: ");
|
out->AppendLiteral("\nExtensions: ");
|
||||||
out->Append(sGLXLibrary.fQueryExtensionsString(display, screen));
|
out->Append(sGLXLibrary.fQueryExtensionsString(*mDisplay, screen));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLContextGLX::OverrideDrawable(GLXDrawable drawable) {
|
bool GLContextGLX::OverrideDrawable(GLXDrawable drawable) {
|
||||||
return mGLX->fMakeCurrent(mDisplay, drawable, mContext);
|
return mGLX->fMakeCurrent(*mDisplay, drawable, mContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GLContextGLX::RestoreDrawable() {
|
bool GLContextGLX::RestoreDrawable() {
|
||||||
return mGLX->fMakeCurrent(mDisplay, mDrawable, mContext);
|
return mGLX->fMakeCurrent(*mDisplay, mDrawable, mContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLContextGLX::GLContextGLX(const GLContextDesc& desc, Display* aDisplay,
|
GLContextGLX::GLContextGLX(const GLContextDesc& desc,
|
||||||
|
std::shared_ptr<XlibDisplay> aDisplay,
|
||||||
GLXDrawable aDrawable, GLXContext aContext,
|
GLXDrawable aDrawable, GLXContext aContext,
|
||||||
bool aDeleteDrawable, bool aDoubleBuffered,
|
bool aDeleteDrawable, bool aDoubleBuffered,
|
||||||
gfxXlibSurface* aPixmap)
|
gfxXlibSurface* aPixmap)
|
||||||
|
@ -741,7 +786,7 @@ static bool AreCompatibleVisuals(Visual* one, Visual* two) {
|
||||||
already_AddRefed<GLContext> CreateForWidget(Display* aXDisplay, Window aXWindow,
|
already_AddRefed<GLContext> CreateForWidget(Display* aXDisplay, Window aXWindow,
|
||||||
bool aHardwareWebRender,
|
bool aHardwareWebRender,
|
||||||
bool aForceAccelerated) {
|
bool aForceAccelerated) {
|
||||||
if (!sGLXLibrary.EnsureInitialized()) {
|
if (!sGLXLibrary.EnsureInitialized(aXDisplay)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -774,7 +819,8 @@ already_AddRefed<GLContext> CreateForWidget(Display* aXDisplay, Window aXWindow,
|
||||||
} else {
|
} else {
|
||||||
flags = CreateContextFlags::REQUIRE_COMPAT_PROFILE;
|
flags = CreateContextFlags::REQUIRE_COMPAT_PROFILE;
|
||||||
}
|
}
|
||||||
return GLContextGLX::CreateGLContext({{flags}, false}, aXDisplay, aXWindow,
|
return GLContextGLX::CreateGLContext({{flags}, false},
|
||||||
|
XlibDisplay::Borrow(aXDisplay), aXWindow,
|
||||||
config, false, nullptr);
|
config, false, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -856,7 +902,7 @@ static bool ChooseConfig(GLXLibrary* glx, Display* display, int screen,
|
||||||
|
|
||||||
bool GLContextGLX::FindVisual(Display* display, int screen, bool useWebRender,
|
bool GLContextGLX::FindVisual(Display* display, int screen, bool useWebRender,
|
||||||
bool useAlpha, int* const out_visualId) {
|
bool useAlpha, int* const out_visualId) {
|
||||||
if (!sGLXLibrary.EnsureInitialized()) {
|
if (!sGLXLibrary.EnsureInitialized(display)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1005,31 +1051,32 @@ static already_AddRefed<GLContextGLX> CreateOffscreenPixmapContext(
|
||||||
const GLContextCreateDesc& desc, const IntSize& size,
|
const GLContextCreateDesc& desc, const IntSize& size,
|
||||||
nsACString* const out_failureId) {
|
nsACString* const out_failureId) {
|
||||||
GLXLibrary* glx = &sGLXLibrary;
|
GLXLibrary* glx = &sGLXLibrary;
|
||||||
if (!glx->EnsureInitialized()) return nullptr;
|
auto display = glx->GetDisplay();
|
||||||
|
|
||||||
Display* display = DefaultXDisplay();
|
if (!display || !glx->EnsureInitialized(*display)) return nullptr;
|
||||||
int screen = DefaultScreen(display);
|
|
||||||
|
int screen = DefaultScreen(display->get());
|
||||||
|
|
||||||
ScopedXFree<GLXFBConfig> scopedConfigArr;
|
ScopedXFree<GLXFBConfig> scopedConfigArr;
|
||||||
GLXFBConfig config;
|
GLXFBConfig config;
|
||||||
int visid;
|
int visid;
|
||||||
if (!ChooseConfig(glx, display, screen, &scopedConfigArr, &config, &visid)) {
|
if (!ChooseConfig(glx, *display, screen, &scopedConfigArr, &config, &visid)) {
|
||||||
NS_WARNING("Failed to find a compatible config.");
|
NS_WARNING("Failed to find a compatible config.");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Visual* visual;
|
Visual* visual;
|
||||||
int depth;
|
int depth;
|
||||||
FindVisualAndDepth(display, visid, &visual, &depth);
|
FindVisualAndDepth(*display, visid, &visual, &depth);
|
||||||
|
|
||||||
OffMainThreadScopedXErrorHandler xErrorHandler;
|
OffMainThreadScopedXErrorHandler xErrorHandler;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
|
|
||||||
gfx::IntSize dummySize(16, 16);
|
gfx::IntSize dummySize(16, 16);
|
||||||
RefPtr<gfxXlibSurface> surface = gfxXlibSurface::Create(
|
RefPtr<gfxXlibSurface> surface = gfxXlibSurface::Create(
|
||||||
DefaultScreenOfDisplay(display), visual, dummySize);
|
display, DefaultScreenOfDisplay(display->get()), visual, dummySize);
|
||||||
if (surface->CairoStatus() != 0) {
|
if (surface->CairoStatus() != 0) {
|
||||||
mozilla::Unused << xErrorHandler.SyncAndGetError(display);
|
mozilla::Unused << xErrorHandler.SyncAndGetError(*display);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1037,12 +1084,12 @@ static already_AddRefed<GLContextGLX> CreateOffscreenPixmapContext(
|
||||||
// its pre-GLX-1.3 extension equivalent (though given the ABI, we
|
// its pre-GLX-1.3 extension equivalent (though given the ABI, we
|
||||||
// might not need to).
|
// might not need to).
|
||||||
const auto drawable = surface->XDrawable();
|
const auto drawable = surface->XDrawable();
|
||||||
const auto pixmap = glx->fCreatePixmap(display, config, drawable, nullptr);
|
const auto pixmap = glx->fCreatePixmap(*display, config, drawable, nullptr);
|
||||||
if (pixmap == 0) {
|
if (pixmap == 0) {
|
||||||
error = true;
|
error = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool serverError = xErrorHandler.SyncAndGetError(display);
|
bool serverError = xErrorHandler.SyncAndGetError(*display);
|
||||||
if (error || serverError) return nullptr;
|
if (error || serverError) return nullptr;
|
||||||
|
|
||||||
auto fullDesc = GLContextDesc{desc};
|
auto fullDesc = GLContextDesc{desc};
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#include "GLContextTypes.h"
|
#include "GLContextTypes.h"
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
|
#include "mozilla/DataMutex.h"
|
||||||
|
#include "mozilla/gfx/XlibDisplay.h"
|
||||||
#include "prlink.h"
|
#include "prlink.h"
|
||||||
typedef realGLboolean GLboolean;
|
typedef realGLboolean GLboolean;
|
||||||
|
|
||||||
|
@ -33,172 +35,174 @@ class GLContextGLX;
|
||||||
|
|
||||||
class GLXLibrary final {
|
class GLXLibrary final {
|
||||||
public:
|
public:
|
||||||
bool EnsureInitialized();
|
bool EnsureInitialized(Display* aDisplay);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class WrapperScope final {
|
class WrapperScope final {
|
||||||
const GLXLibrary& mGlx;
|
const GLXLibrary& mGlx;
|
||||||
const char* const mFuncName;
|
const char* const mFuncName;
|
||||||
|
Display* const mDisplay;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WrapperScope(const GLXLibrary& glx, const char* const funcName);
|
WrapperScope(const GLXLibrary& glx, const char* const funcName,
|
||||||
|
Display* aDisplay);
|
||||||
~WrapperScope();
|
~WrapperScope();
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
# define DECL_WRAPPER_SCOPE const WrapperScope wrapperScope(*this, __func__);
|
# define DECL_WRAPPER_SCOPE(display) \
|
||||||
|
const WrapperScope wrapperScope(*this, __func__, display);
|
||||||
#else
|
#else
|
||||||
# define DECL_WRAPPER_SCOPE
|
# define DECL_WRAPPER_SCOPE(display)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void fDestroyContext(Display* display, GLXContext context) const {
|
void fDestroyContext(Display* display, GLXContext context) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fDestroyContext(display, context);
|
return mSymbols.fDestroyContext(display, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool fMakeCurrent(Display* display, GLXDrawable drawable,
|
Bool fMakeCurrent(Display* display, GLXDrawable drawable,
|
||||||
GLXContext context) const {
|
GLXContext context) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fMakeCurrent(display, drawable, context);
|
return mSymbols.fMakeCurrent(display, drawable, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
XVisualInfo* fGetConfig(Display* display, XVisualInfo* info, int attrib,
|
XVisualInfo* fGetConfig(Display* display, XVisualInfo* info, int attrib,
|
||||||
int* value) const {
|
int* value) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fGetConfig(display, info, attrib, value);
|
return mSymbols.fGetConfig(display, info, attrib, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLXContext fGetCurrentContext() const {
|
GLXContext fGetCurrentContext() const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(nullptr)
|
||||||
return mSymbols.fGetCurrentContext();
|
return mSymbols.fGetCurrentContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
GLXFBConfig* fChooseFBConfig(Display* display, int screen,
|
GLXFBConfig* fChooseFBConfig(Display* display, int screen,
|
||||||
const int* attrib_list, int* nelements) const {
|
const int* attrib_list, int* nelements) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fChooseFBConfig(display, screen, attrib_list, nelements);
|
return mSymbols.fChooseFBConfig(display, screen, attrib_list, nelements);
|
||||||
}
|
}
|
||||||
|
|
||||||
XVisualInfo* fChooseVisual(Display* display, int screen,
|
XVisualInfo* fChooseVisual(Display* display, int screen,
|
||||||
int* attrib_list) const {
|
int* attrib_list) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fChooseVisual(display, screen, attrib_list);
|
return mSymbols.fChooseVisual(display, screen, attrib_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLXFBConfig* fGetFBConfigs(Display* display, int screen,
|
GLXFBConfig* fGetFBConfigs(Display* display, int screen,
|
||||||
int* nelements) const {
|
int* nelements) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fGetFBConfigs(display, screen, nelements);
|
return mSymbols.fGetFBConfigs(display, screen, nelements);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLXContext fCreateNewContext(Display* display, GLXFBConfig config,
|
GLXContext fCreateNewContext(Display* display, GLXFBConfig config,
|
||||||
int render_type, GLXContext share_list,
|
int render_type, GLXContext share_list,
|
||||||
Bool direct) const {
|
Bool direct) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fCreateNewContext(display, config, render_type, share_list,
|
return mSymbols.fCreateNewContext(display, config, render_type, share_list,
|
||||||
direct);
|
direct);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fGetFBConfigAttrib(Display* display, GLXFBConfig config, int attribute,
|
int fGetFBConfigAttrib(Display* display, GLXFBConfig config, int attribute,
|
||||||
int* value) const {
|
int* value) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fGetFBConfigAttrib(display, config, attribute, value);
|
return mSymbols.fGetFBConfigAttrib(display, config, attribute, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fSwapBuffers(Display* display, GLXDrawable drawable) const {
|
void fSwapBuffers(Display* display, GLXDrawable drawable) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fSwapBuffers(display, drawable);
|
return mSymbols.fSwapBuffers(display, drawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* fQueryExtensionsString(Display* display, int screen) const {
|
const char* fQueryExtensionsString(Display* display, int screen) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fQueryExtensionsString(display, screen);
|
return mSymbols.fQueryExtensionsString(display, screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* fGetClientString(Display* display, int screen) const {
|
const char* fGetClientString(Display* display, int screen) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fGetClientString(display, screen);
|
return mSymbols.fGetClientString(display, screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* fQueryServerString(Display* display, int screen, int name) const {
|
const char* fQueryServerString(Display* display, int screen, int name) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fQueryServerString(display, screen, name);
|
return mSymbols.fQueryServerString(display, screen, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLXPixmap fCreatePixmap(Display* display, GLXFBConfig config, Pixmap pixmap,
|
GLXPixmap fCreatePixmap(Display* display, GLXFBConfig config, Pixmap pixmap,
|
||||||
const int* attrib_list) const {
|
const int* attrib_list) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fCreatePixmap(display, config, pixmap, attrib_list);
|
return mSymbols.fCreatePixmap(display, config, pixmap, attrib_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLXPixmap fCreateGLXPixmapWithConfig(Display* display, GLXFBConfig config,
|
GLXPixmap fCreateGLXPixmapWithConfig(Display* display, GLXFBConfig config,
|
||||||
Pixmap pixmap) const {
|
Pixmap pixmap) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fCreateGLXPixmapWithConfig(display, config, pixmap);
|
return mSymbols.fCreateGLXPixmapWithConfig(display, config, pixmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fDestroyPixmap(Display* display, GLXPixmap pixmap) const {
|
void fDestroyPixmap(Display* display, GLXPixmap pixmap) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fDestroyPixmap(display, pixmap);
|
return mSymbols.fDestroyPixmap(display, pixmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bool fQueryVersion(Display* display, int* major, int* minor) const {
|
Bool fQueryVersion(Display* display, int* major, int* minor) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fQueryVersion(display, major, minor);
|
return mSymbols.fQueryVersion(display, major, minor);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fBindTexImage(Display* display, GLXDrawable drawable, int buffer,
|
void fBindTexImage(Display* display, GLXDrawable drawable, int buffer,
|
||||||
const int* attrib_list) const {
|
const int* attrib_list) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fBindTexImageEXT(display, drawable, buffer, attrib_list);
|
return mSymbols.fBindTexImageEXT(display, drawable, buffer, attrib_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fReleaseTexImage(Display* display, GLXDrawable drawable,
|
void fReleaseTexImage(Display* display, GLXDrawable drawable,
|
||||||
int buffer) const {
|
int buffer) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fReleaseTexImageEXT(display, drawable, buffer);
|
return mSymbols.fReleaseTexImageEXT(display, drawable, buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fWaitGL() const {
|
void fWaitGL() const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(nullptr)
|
||||||
return mSymbols.fWaitGL();
|
return mSymbols.fWaitGL();
|
||||||
}
|
}
|
||||||
|
|
||||||
void fWaitX() const {
|
void fWaitX() const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(nullptr)
|
||||||
return mSymbols.fWaitX();
|
return mSymbols.fWaitX();
|
||||||
}
|
}
|
||||||
|
|
||||||
GLXContext fCreateContextAttribs(Display* display, GLXFBConfig config,
|
GLXContext fCreateContextAttribs(Display* display, GLXFBConfig config,
|
||||||
GLXContext share_list, Bool direct,
|
GLXContext share_list, Bool direct,
|
||||||
const int* attrib_list) const {
|
const int* attrib_list) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(display)
|
||||||
return mSymbols.fCreateContextAttribsARB(display, config, share_list,
|
return mSymbols.fCreateContextAttribsARB(display, config, share_list,
|
||||||
direct, attrib_list);
|
direct, attrib_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fGetVideoSync(unsigned int* count) const {
|
int fGetVideoSync(unsigned int* count) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(nullptr)
|
||||||
return mSymbols.fGetVideoSyncSGI(count);
|
return mSymbols.fGetVideoSyncSGI(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fWaitVideoSync(int divisor, int remainder, unsigned int* count) const {
|
int fWaitVideoSync(int divisor, int remainder, unsigned int* count) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(nullptr)
|
||||||
return mSymbols.fWaitVideoSyncSGI(divisor, remainder, count);
|
return mSymbols.fWaitVideoSyncSGI(divisor, remainder, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fSwapInterval(Display* dpy, GLXDrawable drawable, int interval) const {
|
void fSwapInterval(Display* dpy, GLXDrawable drawable, int interval) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(dpy)
|
||||||
return mSymbols.fSwapIntervalEXT(dpy, drawable, interval);
|
return mSymbols.fSwapIntervalEXT(dpy, drawable, interval);
|
||||||
}
|
}
|
||||||
|
|
||||||
int fQueryDrawable(Display* dpy, GLXDrawable drawable, int attribute,
|
int fQueryDrawable(Display* dpy, GLXDrawable drawable, int attribute,
|
||||||
unsigned int* value) const {
|
unsigned int* value) const {
|
||||||
DECL_WRAPPER_SCOPE
|
DECL_WRAPPER_SCOPE(dpy)
|
||||||
return mSymbols.fQueryDrawable(dpy, drawable, attribute, value);
|
return mSymbols.fQueryDrawable(dpy, drawable, attribute, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef DECL_WRAPPER_SCOPE
|
#undef DECL_WRAPPER_SCOPE
|
||||||
|
|
||||||
////
|
////
|
||||||
|
@ -216,7 +220,7 @@ class GLXLibrary final {
|
||||||
bool HasVideoMemoryPurge() { return mHasVideoMemoryPurge; }
|
bool HasVideoMemoryPurge() { return mHasVideoMemoryPurge; }
|
||||||
bool HasCreateContextAttribs() { return mHasCreateContextAttribs; }
|
bool HasCreateContextAttribs() { return mHasCreateContextAttribs; }
|
||||||
bool SupportsTextureFromPixmap(gfxASurface* aSurface);
|
bool SupportsTextureFromPixmap(gfxASurface* aSurface);
|
||||||
bool SupportsVideoSync();
|
bool SupportsVideoSync(Display* aDisplay);
|
||||||
bool SupportsSwapControl() const { return bool(mSymbols.fSwapIntervalEXT); }
|
bool SupportsSwapControl() const { return bool(mSymbols.fSwapIntervalEXT); }
|
||||||
bool SupportsBufferAge() const {
|
bool SupportsBufferAge() const {
|
||||||
MOZ_ASSERT(mInitialized);
|
MOZ_ASSERT(mInitialized);
|
||||||
|
@ -227,6 +231,8 @@ class GLXLibrary final {
|
||||||
|
|
||||||
auto GetGetProcAddress() const { return mSymbols.fGetProcAddress; }
|
auto GetGetProcAddress() const { return mSymbols.fGetProcAddress; }
|
||||||
|
|
||||||
|
std::shared_ptr<gfx::XlibDisplay> GetDisplay();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct {
|
struct {
|
||||||
void(GLAPIENTRY* fDestroyContext)(Display*, GLXContext);
|
void(GLAPIENTRY* fDestroyContext)(Display*, GLXContext);
|
||||||
|
@ -276,6 +282,8 @@ class GLXLibrary final {
|
||||||
bool mIsNVIDIA = false;
|
bool mIsNVIDIA = false;
|
||||||
bool mClientIsMesa = false;
|
bool mClientIsMesa = false;
|
||||||
PRLibrary* mOGLLibrary = nullptr;
|
PRLibrary* mOGLLibrary = nullptr;
|
||||||
|
StaticDataMutex<std::weak_ptr<gfx::XlibDisplay>> mOwnDisplay{
|
||||||
|
"GLXLibrary::mOwnDisplay"};
|
||||||
};
|
};
|
||||||
|
|
||||||
// a global GLXLibrary instance
|
// a global GLXLibrary instance
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
* 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 "XlibDisplay.h"
|
||||||
|
|
||||||
|
#include "mozilla/Assertions.h"
|
||||||
|
|
||||||
|
namespace mozilla::gfx {
|
||||||
|
|
||||||
|
XlibDisplay::XlibDisplay(Display* aDisplay, bool aOwned)
|
||||||
|
: mDisplay(aDisplay), mOwned(aOwned) {
|
||||||
|
MOZ_ASSERT(mDisplay);
|
||||||
|
}
|
||||||
|
|
||||||
|
XlibDisplay::~XlibDisplay() {
|
||||||
|
if (mOwned) {
|
||||||
|
XCloseDisplay(mDisplay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
std::shared_ptr<XlibDisplay> XlibDisplay::Borrow(Display* aDisplay) {
|
||||||
|
if (!aDisplay) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return std::shared_ptr<XlibDisplay>(new XlibDisplay(aDisplay, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
std::shared_ptr<XlibDisplay> XlibDisplay::Open(const char* aDisplayName) {
|
||||||
|
Display* disp = XOpenDisplay(aDisplayName);
|
||||||
|
if (!disp) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return std::shared_ptr<XlibDisplay>(new XlibDisplay(disp, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla::gfx
|
|
@ -0,0 +1,41 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
* 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 GFX_XLIBDISPLAY_H
|
||||||
|
#define GFX_XLIBDISPLAY_H
|
||||||
|
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
#include "X11UndefineNone.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace mozilla::gfx {
|
||||||
|
|
||||||
|
// Represents an X11 display connection which may be either borrowed
|
||||||
|
// (e.g., from GTK) or owned; in the latter case it will be closed
|
||||||
|
// with this object becomes unreferenced. See also the `EglDisplay`
|
||||||
|
// class.
|
||||||
|
class XlibDisplay final {
|
||||||
|
public:
|
||||||
|
~XlibDisplay();
|
||||||
|
|
||||||
|
// Explicit `->get()` may be needed with some `Xlib.h` macros that
|
||||||
|
// expand to C-style pointer casts.
|
||||||
|
Display* get() const { return mDisplay; }
|
||||||
|
operator Display*() const { return mDisplay; }
|
||||||
|
|
||||||
|
static std::shared_ptr<XlibDisplay> Borrow(Display* aDisplay);
|
||||||
|
static std::shared_ptr<XlibDisplay> Open(const char* aDisplayName);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Display* const mDisplay;
|
||||||
|
bool const mOwned;
|
||||||
|
|
||||||
|
XlibDisplay(Display*, bool);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla::gfx
|
||||||
|
|
||||||
|
#endif // GFX_XLIBDISPLAY_H
|
|
@ -30,6 +30,7 @@
|
||||||
#include "mozilla/FontPropertyTypes.h"
|
#include "mozilla/FontPropertyTypes.h"
|
||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
#include "mozilla/gfx/Logging.h"
|
#include "mozilla/gfx/Logging.h"
|
||||||
|
#include "mozilla/gfx/XlibDisplay.h"
|
||||||
#include "mozilla/Monitor.h"
|
#include "mozilla/Monitor.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/StaticPrefs_gfx.h"
|
#include "mozilla/StaticPrefs_gfx.h"
|
||||||
|
@ -686,8 +687,9 @@ class GtkVsyncSource final : public VsyncSource {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mGLContext = gl::GLContextGLX::CreateGLContext({}, mXDisplay, root,
|
mGLContext = gl::GLContextGLX::CreateGLContext(
|
||||||
config, false, nullptr);
|
{}, gfx::XlibDisplay::Borrow(mXDisplay), root, config, false,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
if (!mGLContext) {
|
if (!mGLContext) {
|
||||||
lock.NotifyAll();
|
lock.NotifyAll();
|
||||||
|
@ -831,7 +833,7 @@ already_AddRefed<gfx::VsyncSource> gfxPlatformGtk::CreateHardwareVsyncSource() {
|
||||||
}
|
}
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
// Only use GLX vsync when the OpenGL compositor / WebRedner is being used.
|
// Only use GLX vsync when the OpenGL compositor / WebRender is being used.
|
||||||
// The extra cost of initializing a GLX context while blocking the main
|
// The extra cost of initializing a GLX context while blocking the main
|
||||||
// thread is not worth it when using basic composition.
|
// thread is not worth it when using basic composition.
|
||||||
//
|
//
|
||||||
|
@ -847,7 +849,7 @@ already_AddRefed<gfx::VsyncSource> gfxPlatformGtk::CreateHardwareVsyncSource() {
|
||||||
|
|
||||||
// Nvidia doesn't support GLX at the same time as EGL but Mesa does.
|
// Nvidia doesn't support GLX at the same time as EGL but Mesa does.
|
||||||
if (!gfxVars::UseEGL() || (adapterDriverVendor.Find("mesa") != -1)) {
|
if (!gfxVars::UseEGL() || (adapterDriverVendor.Find("mesa") != -1)) {
|
||||||
useGlxVsync = gl::sGLXLibrary.SupportsVideoSync();
|
useGlxVsync = gl::sGLXLibrary.SupportsVideoSync(DefaultXDisplay());
|
||||||
}
|
}
|
||||||
if (useGlxVsync) {
|
if (useGlxVsync) {
|
||||||
RefPtr<VsyncSource> vsyncSource = new GtkVsyncSource();
|
RefPtr<VsyncSource> vsyncSource = new GtkVsyncSource();
|
||||||
|
|
|
@ -25,7 +25,7 @@ using namespace mozilla::gfx;
|
||||||
|
|
||||||
gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual)
|
gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual)
|
||||||
: mPixmapTaken(false),
|
: mPixmapTaken(false),
|
||||||
mDisplay(dpy),
|
mDisplay(XlibDisplay::Borrow(dpy)),
|
||||||
mDrawable(drawable),
|
mDrawable(drawable),
|
||||||
mGLXPixmap(X11None) {
|
mGLXPixmap(X11None) {
|
||||||
const gfx::IntSize size = DoSizeQuery();
|
const gfx::IntSize size = DoSizeQuery();
|
||||||
|
@ -36,6 +36,11 @@ gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual)
|
||||||
|
|
||||||
gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual,
|
gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual,
|
||||||
const gfx::IntSize& size)
|
const gfx::IntSize& size)
|
||||||
|
: gfxXlibSurface(XlibDisplay::Borrow(dpy), drawable, visual, size) {}
|
||||||
|
|
||||||
|
gfxXlibSurface::gfxXlibSurface(const std::shared_ptr<XlibDisplay>& dpy,
|
||||||
|
Drawable drawable, Visual* visual,
|
||||||
|
const gfx::IntSize& size)
|
||||||
: mPixmapTaken(false),
|
: mPixmapTaken(false),
|
||||||
mDisplay(dpy),
|
mDisplay(dpy),
|
||||||
mDrawable(drawable),
|
mDrawable(drawable),
|
||||||
|
@ -43,8 +48,8 @@ gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual,
|
||||||
NS_ASSERTION(Factory::CheckSurfaceSize(size, XLIB_IMAGE_SIDE_SIZE_LIMIT),
|
NS_ASSERTION(Factory::CheckSurfaceSize(size, XLIB_IMAGE_SIDE_SIZE_LIMIT),
|
||||||
"Bad size");
|
"Bad size");
|
||||||
|
|
||||||
cairo_surface_t* surf =
|
cairo_surface_t* surf = cairo_xlib_surface_create(*dpy, drawable, visual,
|
||||||
cairo_xlib_surface_create(dpy, drawable, visual, size.width, size.height);
|
size.width, size.height);
|
||||||
Init(surf);
|
Init(surf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,14 +57,14 @@ gfxXlibSurface::gfxXlibSurface(Screen* screen, Drawable drawable,
|
||||||
XRenderPictFormat* format,
|
XRenderPictFormat* format,
|
||||||
const gfx::IntSize& size)
|
const gfx::IntSize& size)
|
||||||
: mPixmapTaken(false),
|
: mPixmapTaken(false),
|
||||||
mDisplay(DisplayOfScreen(screen)),
|
mDisplay(XlibDisplay::Borrow(DisplayOfScreen(screen))),
|
||||||
mDrawable(drawable),
|
mDrawable(drawable),
|
||||||
mGLXPixmap(X11None) {
|
mGLXPixmap(X11None) {
|
||||||
NS_ASSERTION(Factory::CheckSurfaceSize(size, XLIB_IMAGE_SIDE_SIZE_LIMIT),
|
NS_ASSERTION(Factory::CheckSurfaceSize(size, XLIB_IMAGE_SIDE_SIZE_LIMIT),
|
||||||
"Bad Size");
|
"Bad Size");
|
||||||
|
|
||||||
cairo_surface_t* surf = cairo_xlib_surface_create_with_xrender_format(
|
cairo_surface_t* surf = cairo_xlib_surface_create_with_xrender_format(
|
||||||
mDisplay, drawable, screen, format, size.width, size.height);
|
*mDisplay, drawable, screen, format, size.width, size.height);
|
||||||
Init(surf);
|
Init(surf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +74,7 @@ gfxXlibSurface::gfxXlibSurface(cairo_surface_t* csurf)
|
||||||
"Not expecting an error surface");
|
"Not expecting an error surface");
|
||||||
|
|
||||||
mDrawable = cairo_xlib_surface_get_drawable(csurf);
|
mDrawable = cairo_xlib_surface_get_drawable(csurf);
|
||||||
mDisplay = cairo_xlib_surface_get_display(csurf);
|
mDisplay = XlibDisplay::Borrow(cairo_xlib_surface_get_display(csurf));
|
||||||
|
|
||||||
Init(csurf, true);
|
Init(csurf, true);
|
||||||
}
|
}
|
||||||
|
@ -78,9 +83,9 @@ gfxXlibSurface::~gfxXlibSurface() {
|
||||||
// gfxASurface's destructor calls RecordMemoryFreed().
|
// gfxASurface's destructor calls RecordMemoryFreed().
|
||||||
if (mPixmapTaken) {
|
if (mPixmapTaken) {
|
||||||
if (mGLXPixmap) {
|
if (mGLXPixmap) {
|
||||||
gl::sGLXLibrary.DestroyPixmap(mDisplay, mGLXPixmap);
|
gl::sGLXLibrary.DestroyPixmap(*mDisplay, mGLXPixmap);
|
||||||
}
|
}
|
||||||
XFreePixmap(mDisplay, mDrawable);
|
XFreePixmap(*mDisplay, mDrawable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,12 +176,22 @@ cairo_surface_t* gfxXlibSurface::CreateCairoSurface(Screen* screen,
|
||||||
already_AddRefed<gfxXlibSurface> gfxXlibSurface::Create(
|
already_AddRefed<gfxXlibSurface> gfxXlibSurface::Create(
|
||||||
Screen* screen, Visual* visual, const gfx::IntSize& size,
|
Screen* screen, Visual* visual, const gfx::IntSize& size,
|
||||||
Drawable relatedDrawable) {
|
Drawable relatedDrawable) {
|
||||||
|
return Create(XlibDisplay::Borrow(DisplayOfScreen(screen)), screen, visual,
|
||||||
|
size, relatedDrawable);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
already_AddRefed<gfxXlibSurface> gfxXlibSurface::Create(
|
||||||
|
const std::shared_ptr<XlibDisplay>& display, Screen* screen, Visual* visual,
|
||||||
|
const gfx::IntSize& size, Drawable relatedDrawable) {
|
||||||
|
MOZ_ASSERT(*display == DisplayOfScreen(screen));
|
||||||
|
|
||||||
Drawable drawable = CreatePixmap(screen, size, DepthOfVisual(screen, visual),
|
Drawable drawable = CreatePixmap(screen, size, DepthOfVisual(screen, visual),
|
||||||
relatedDrawable);
|
relatedDrawable);
|
||||||
if (!drawable) return nullptr;
|
if (!drawable) return nullptr;
|
||||||
|
|
||||||
RefPtr<gfxXlibSurface> result =
|
RefPtr<gfxXlibSurface> result =
|
||||||
new gfxXlibSurface(DisplayOfScreen(screen), drawable, visual, size);
|
new gfxXlibSurface(display, drawable, visual, size);
|
||||||
result->TakePixmap();
|
result->TakePixmap();
|
||||||
|
|
||||||
if (result->CairoStatus() != 0) return nullptr;
|
if (result->CairoStatus() != 0) return nullptr;
|
||||||
|
@ -218,7 +233,7 @@ already_AddRefed<gfxASurface> gfxXlibSurface::CreateSimilarSurface(
|
||||||
static bool force24bpp = GetForce24bppPref();
|
static bool force24bpp = GetForce24bppPref();
|
||||||
if (force24bpp && cairo_xlib_surface_get_depth(CairoSurface()) != 24) {
|
if (force24bpp && cairo_xlib_surface_get_depth(CairoSurface()) != 24) {
|
||||||
XRenderPictFormat* format =
|
XRenderPictFormat* format =
|
||||||
XRenderFindStandardFormat(mDisplay, PictStandardRGB24);
|
XRenderFindStandardFormat(*mDisplay, PictStandardRGB24);
|
||||||
if (format) {
|
if (format) {
|
||||||
// Cairo only performs simple self-copies as desired if it
|
// Cairo only performs simple self-copies as desired if it
|
||||||
// knows that this is a Pixmap surface. It only knows that
|
// knows that this is a Pixmap surface. It only knows that
|
||||||
|
@ -240,7 +255,7 @@ already_AddRefed<gfxASurface> gfxXlibSurface::CreateSimilarSurface(
|
||||||
|
|
||||||
void gfxXlibSurface::Finish() {
|
void gfxXlibSurface::Finish() {
|
||||||
if (mPixmapTaken && mGLXPixmap) {
|
if (mPixmapTaken && mGLXPixmap) {
|
||||||
gl::sGLXLibrary.DestroyPixmap(mDisplay, mGLXPixmap);
|
gl::sGLXLibrary.DestroyPixmap(*mDisplay, mGLXPixmap);
|
||||||
mGLXPixmap = X11None;
|
mGLXPixmap = X11None;
|
||||||
}
|
}
|
||||||
gfxASurface::Finish();
|
gfxASurface::Finish();
|
||||||
|
@ -259,7 +274,7 @@ const gfx::IntSize gfxXlibSurface::DoSizeQuery() {
|
||||||
int x_ignore, y_ignore;
|
int x_ignore, y_ignore;
|
||||||
unsigned int bwidth_ignore, width, height, depth;
|
unsigned int bwidth_ignore, width, height, depth;
|
||||||
|
|
||||||
XGetGeometry(mDisplay, mDrawable, &root_ignore, &x_ignore, &y_ignore, &width,
|
XGetGeometry(*mDisplay, mDrawable, &root_ignore, &x_ignore, &y_ignore, &width,
|
||||||
&height, &bwidth_ignore, &depth);
|
&height, &bwidth_ignore, &depth);
|
||||||
|
|
||||||
return gfx::IntSize(width, height);
|
return gfx::IntSize(width, height);
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "X11UndefineNone.h"
|
#include "X11UndefineNone.h"
|
||||||
|
|
||||||
#include "GLXLibrary.h"
|
#include "GLXLibrary.h"
|
||||||
|
#include "mozilla/gfx/XlibDisplay.h"
|
||||||
|
|
||||||
#include "nsSize.h"
|
#include "nsSize.h"
|
||||||
|
|
||||||
|
@ -31,6 +32,9 @@ class gfxXlibSurface final : public gfxASurface {
|
||||||
// and known width/height.
|
// and known width/height.
|
||||||
gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual,
|
gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual,
|
||||||
const mozilla::gfx::IntSize& size);
|
const mozilla::gfx::IntSize& size);
|
||||||
|
gfxXlibSurface(const std::shared_ptr<mozilla::gfx::XlibDisplay>& dpy,
|
||||||
|
Drawable drawable, Visual* visual,
|
||||||
|
const mozilla::gfx::IntSize& size);
|
||||||
|
|
||||||
// construct a wrapper around the specified drawable with dpy/format,
|
// construct a wrapper around the specified drawable with dpy/format,
|
||||||
// and known width/height.
|
// and known width/height.
|
||||||
|
@ -46,6 +50,10 @@ class gfxXlibSurface final : public gfxASurface {
|
||||||
static already_AddRefed<gfxXlibSurface> Create(
|
static already_AddRefed<gfxXlibSurface> Create(
|
||||||
::Screen* screen, Visual* visual, const mozilla::gfx::IntSize& size,
|
::Screen* screen, Visual* visual, const mozilla::gfx::IntSize& size,
|
||||||
Drawable relatedDrawable = X11None);
|
Drawable relatedDrawable = X11None);
|
||||||
|
static already_AddRefed<gfxXlibSurface> Create(
|
||||||
|
const std::shared_ptr<mozilla::gfx::XlibDisplay>& display,
|
||||||
|
::Screen* screen, Visual* visual, const mozilla::gfx::IntSize& size,
|
||||||
|
Drawable relatedDrawable = X11None);
|
||||||
static cairo_surface_t* CreateCairoSurface(
|
static cairo_surface_t* CreateCairoSurface(
|
||||||
::Screen* screen, Visual* visual, const mozilla::gfx::IntSize& size,
|
::Screen* screen, Visual* visual, const mozilla::gfx::IntSize& size,
|
||||||
Drawable relatedDrawable = X11None);
|
Drawable relatedDrawable = X11None);
|
||||||
|
@ -61,7 +69,7 @@ class gfxXlibSurface final : public gfxASurface {
|
||||||
|
|
||||||
const mozilla::gfx::IntSize GetSize() const override;
|
const mozilla::gfx::IntSize GetSize() const override;
|
||||||
|
|
||||||
Display* XDisplay() { return mDisplay; }
|
Display* XDisplay() { return *mDisplay; }
|
||||||
::Screen* XScreen();
|
::Screen* XScreen();
|
||||||
Drawable XDrawable() { return mDrawable; }
|
Drawable XDrawable() { return mDrawable; }
|
||||||
XRenderPictFormat* XRenderFormat();
|
XRenderPictFormat* XRenderFormat();
|
||||||
|
@ -98,15 +106,15 @@ class gfxXlibSurface final : public gfxASurface {
|
||||||
bool IsPadSlow() {
|
bool IsPadSlow() {
|
||||||
// The test here matches that for buggy_pad_reflect in
|
// The test here matches that for buggy_pad_reflect in
|
||||||
// _cairo_xlib_device_create.
|
// _cairo_xlib_device_create.
|
||||||
return VendorRelease(mDisplay) >= 60700000 ||
|
return VendorRelease(mDisplay->get()) >= 60700000 ||
|
||||||
VendorRelease(mDisplay) < 10699000;
|
VendorRelease(mDisplay->get()) < 10699000;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// if TakePixmap() has been called on this
|
// if TakePixmap() has been called on this
|
||||||
bool mPixmapTaken;
|
bool mPixmapTaken;
|
||||||
|
|
||||||
Display* mDisplay;
|
std::shared_ptr<mozilla::gfx::XlibDisplay> mDisplay;
|
||||||
Drawable mDrawable;
|
Drawable mDrawable;
|
||||||
|
|
||||||
const mozilla::gfx::IntSize DoSizeQuery();
|
const mozilla::gfx::IntSize DoSizeQuery();
|
||||||
|
|
|
@ -135,9 +135,13 @@ elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk":
|
||||||
"gfxXlibNativeRenderer.h",
|
"gfxXlibNativeRenderer.h",
|
||||||
"gfxXlibSurface.h",
|
"gfxXlibSurface.h",
|
||||||
]
|
]
|
||||||
|
EXPORTS.mozilla.gfx += [
|
||||||
|
"XlibDisplay.h",
|
||||||
|
]
|
||||||
SOURCES += [
|
SOURCES += [
|
||||||
"gfxXlibNativeRenderer.cpp",
|
"gfxXlibNativeRenderer.cpp",
|
||||||
"gfxXlibSurface.cpp",
|
"gfxXlibSurface.cpp",
|
||||||
|
"XlibDisplay.cpp",
|
||||||
]
|
]
|
||||||
|
|
||||||
elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
|
elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
|
||||||
|
|
Загрузка…
Ссылка в новой задаче