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:
Jed Davis 2021-07-06 07:42:42 +00:00
Родитель a8d8e90b70
Коммит dc3ae62544
9 изменённых файлов: 276 добавлений и 110 удалений

Просмотреть файл

@ -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

41
gfx/thebes/XlibDisplay.h Normal file
Просмотреть файл

@ -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":