зеркало из 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:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextGLX, override)
|
||||
static already_AddRefed<GLContextGLX> CreateGLContext(
|
||||
const GLContextDesc&, Display* display, GLXDrawable drawable,
|
||||
GLXFBConfig cfg, bool deleteDrawable, gfxXlibSurface* pixmap);
|
||||
const GLContextDesc&, std::shared_ptr<gfx::XlibDisplay> display,
|
||||
GLXDrawable drawable, GLXFBConfig cfg, bool deleteDrawable,
|
||||
gfxXlibSurface* pixmap);
|
||||
|
||||
static bool FindVisual(Display* display, int screen, bool useWebRender,
|
||||
bool useAlpha, int* const out_visualId);
|
||||
|
@ -67,12 +68,12 @@ class GLContextGLX : public GLContext {
|
|||
private:
|
||||
friend class GLContextProviderGLX;
|
||||
|
||||
GLContextGLX(const GLContextDesc&, Display* aDisplay, GLXDrawable aDrawable,
|
||||
GLXContext aContext, bool aDeleteDrawable, bool aDoubleBuffered,
|
||||
gfxXlibSurface* aPixmap);
|
||||
GLContextGLX(const GLContextDesc&, std::shared_ptr<gfx::XlibDisplay> aDisplay,
|
||||
GLXDrawable aDrawable, GLXContext aContext, bool aDeleteDrawable,
|
||||
bool aDoubleBuffered, gfxXlibSurface* aPixmap);
|
||||
|
||||
const GLXContext mContext;
|
||||
Display* const mDisplay;
|
||||
const std::shared_ptr<gfx::XlibDisplay> mDisplay;
|
||||
const GLXDrawable mDrawable;
|
||||
const bool mDeleteDrawable;
|
||||
const bool mDoubleBuffered;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "mozilla/layers/CompositorOptions.h"
|
||||
#include "mozilla/Range.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
#include "mozilla/StaticPrefs_gfx.h"
|
||||
#include "mozilla/StaticPrefs_layout.h"
|
||||
#include "mozilla/widget/CompositorWidget.h"
|
||||
|
@ -59,7 +60,7 @@ static inline bool HasExtension(const char* aExtensions,
|
|||
reinterpret_cast<const GLubyte*>(aExtensions), aRequiredExtension);
|
||||
}
|
||||
|
||||
bool GLXLibrary::EnsureInitialized() {
|
||||
bool GLXLibrary::EnsureInitialized(Display* aDisplay) {
|
||||
if (mInitialized) {
|
||||
return true;
|
||||
}
|
||||
|
@ -70,6 +71,11 @@ bool GLXLibrary::EnsureInitialized() {
|
|||
}
|
||||
mTriedInitializing = true;
|
||||
|
||||
MOZ_ASSERT(aDisplay);
|
||||
if (!aDisplay) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Force enabling s3 texture compression. (Bug 774134)
|
||||
PR_SetEnv("force_s3tc_enable=true");
|
||||
|
||||
|
@ -148,12 +154,11 @@ bool GLXLibrary::EnsureInitialized() {
|
|||
}
|
||||
const SymbolLoader pfnLoader(mSymbols.fGetProcAddress);
|
||||
|
||||
Display* display = DefaultXDisplay();
|
||||
int screen = DefaultScreen(display);
|
||||
int screen = DefaultScreen(aDisplay);
|
||||
|
||||
{
|
||||
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)");
|
||||
return false;
|
||||
}
|
||||
|
@ -181,10 +186,10 @@ bool GLXLibrary::EnsureInitialized() {
|
|||
return false;
|
||||
};
|
||||
|
||||
const char* clientVendor = fGetClientString(display, LOCAL_GLX_VENDOR);
|
||||
const char* clientVendor = fGetClientString(aDisplay, LOCAL_GLX_VENDOR);
|
||||
const char* serverVendor =
|
||||
fQueryServerString(display, screen, LOCAL_GLX_VENDOR);
|
||||
const char* extensionsStr = fQueryExtensionsString(display, screen);
|
||||
fQueryServerString(aDisplay, screen, LOCAL_GLX_VENDOR);
|
||||
const char* extensionsStr = fQueryExtensionsString(aDisplay, screen);
|
||||
|
||||
if (HasExtension(extensionsStr, "GLX_EXT_texture_from_pixmap") &&
|
||||
fnLoadSymbols(symbols_texturefrompixmap)) {
|
||||
|
@ -240,19 +245,20 @@ bool GLXLibrary::EnsureInitialized() {
|
|||
}
|
||||
|
||||
bool GLXLibrary::SupportsTextureFromPixmap(gfxASurface* aSurface) {
|
||||
if (!EnsureInitialized()) {
|
||||
if (aSurface->GetType() != gfxSurfaceType::Xlib) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aSurface->GetType() != gfxSurfaceType::Xlib || !mUseTextureFromPixmap) {
|
||||
gfxXlibSurface* xs = static_cast<gfxXlibSurface*>(aSurface);
|
||||
if (!EnsureInitialized(xs->XDisplay())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return mUseTextureFromPixmap;
|
||||
}
|
||||
|
||||
bool GLXLibrary::SupportsVideoSync() {
|
||||
if (!EnsureInitialized()) {
|
||||
bool GLXLibrary::SupportsVideoSync(Display* aDisplay) {
|
||||
if (!EnsureInitialized(aDisplay)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -450,8 +456,9 @@ static int GLXErrorHandler(Display* display, XErrorEvent* ev) {
|
|||
}
|
||||
|
||||
GLXLibrary::WrapperScope::WrapperScope(const GLXLibrary& glx,
|
||||
const char* const funcName)
|
||||
: mGlx(glx), mFuncName(funcName) {
|
||||
const char* const funcName,
|
||||
Display* aDisplay)
|
||||
: mGlx(glx), mFuncName(funcName), mDisplay(aDisplay) {
|
||||
if (mGlx.mDebug) {
|
||||
sOldErrorHandler = XSetErrorHandler(GLXErrorHandler);
|
||||
}
|
||||
|
@ -459,11 +466,17 @@ GLXLibrary::WrapperScope::WrapperScope(const GLXLibrary& glx,
|
|||
|
||||
GLXLibrary::WrapperScope::~WrapperScope() {
|
||||
if (mGlx.mDebug) {
|
||||
FinishX(DefaultXDisplay());
|
||||
if (mDisplay) {
|
||||
FinishX(mDisplay);
|
||||
}
|
||||
if (sErrorEvent.mError.error_code) {
|
||||
char buffer[100] = {};
|
||||
XGetErrorText(DefaultXDisplay(), sErrorEvent.mError.error_code, buffer,
|
||||
sizeof(buffer));
|
||||
if (mDisplay) {
|
||||
XGetErrorText(mDisplay, sErrorEvent.mError.error_code, buffer,
|
||||
sizeof(buffer));
|
||||
} else {
|
||||
SprintfLiteral(buffer, "%d", sErrorEvent.mError.error_code);
|
||||
}
|
||||
printf_stderr("X ERROR after %s: %s (%i) - Request: %i.%i, Serial: %lu",
|
||||
mFuncName, buffer, sErrorEvent.mError.error_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(
|
||||
const GLContextDesc& desc, Display* display, GLXDrawable drawable,
|
||||
GLXFBConfig cfg, bool deleteDrawable, gfxXlibSurface* pixmap) {
|
||||
const GLContextDesc& desc, std::shared_ptr<XlibDisplay> display,
|
||||
GLXDrawable drawable, GLXFBConfig cfg, bool deleteDrawable,
|
||||
gfxXlibSurface* pixmap) {
|
||||
GLXLibrary& glx = sGLXLibrary;
|
||||
|
||||
int isDoubleBuffered = 0;
|
||||
int err = glx.fGetFBConfigAttrib(display, cfg, LOCAL_GLX_DOUBLEBUFFER,
|
||||
int err = glx.fGetFBConfigAttrib(*display, cfg, LOCAL_GLX_DOUBLEBUFFER,
|
||||
&isDoubleBuffered);
|
||||
if (LOCAL_GLX_BAD_ATTRIBUTE != err) {
|
||||
if (ShouldSpew()) {
|
||||
|
@ -507,15 +552,15 @@ already_AddRefed<GLContextGLX> GLContextGLX::CreateGLContext(
|
|||
// we should not try to use such contexts. (Errors may come from the
|
||||
// distant server, or something)
|
||||
const auto glxContext = glx.fCreateContextAttribs(
|
||||
display, cfg, nullptr, X11True, terminated.data());
|
||||
*display, cfg, nullptr, X11True, terminated.data());
|
||||
if (!glxContext) return nullptr;
|
||||
const RefPtr<GLContextGLX> ret =
|
||||
new GLContextGLX(desc, display, drawable, glxContext, deleteDrawable,
|
||||
isDoubleBuffered, pixmap);
|
||||
if (handler.SyncAndGetError(display)) return nullptr;
|
||||
if (handler.SyncAndGetError(*display)) return nullptr;
|
||||
|
||||
if (!ret->Init()) return nullptr;
|
||||
if (handler.SyncAndGetError(display)) return nullptr;
|
||||
if (handler.SyncAndGetError(*display)) return nullptr;
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
@ -602,15 +647,15 @@ GLContextGLX::~GLContextGLX() {
|
|||
#ifdef DEBUG
|
||||
bool success =
|
||||
#endif
|
||||
mGLX->fMakeCurrent(mDisplay, X11None, nullptr);
|
||||
mGLX->fMakeCurrent(*mDisplay, X11None, nullptr);
|
||||
MOZ_ASSERT(success,
|
||||
"glXMakeCurrent failed to release GL context before we call "
|
||||
"glXDestroyContext!");
|
||||
|
||||
mGLX->fDestroyContext(mDisplay, mContext);
|
||||
mGLX->fDestroyContext(*mDisplay, mContext);
|
||||
|
||||
if (mDeleteDrawable) {
|
||||
mGLX->fDestroyPixmap(mDisplay, mDrawable);
|
||||
mGLX->fDestroyPixmap(*mDisplay, mDrawable);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -632,10 +677,10 @@ bool GLContextGLX::MakeCurrentImpl() const {
|
|||
if (mGLX->IsMesa()) {
|
||||
// Read into the event queue to ensure that Mesa receives a
|
||||
// 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!");
|
||||
|
||||
if (!IsOffscreen() && mGLX->SupportsSwapControl()) {
|
||||
|
@ -643,7 +688,7 @@ bool GLContextGLX::MakeCurrentImpl() const {
|
|||
// VBlank when calling glXSwapBuffers. We want to run unthrottled
|
||||
// in ASAP mode. See bug 1280744.
|
||||
const bool isASAP = (StaticPrefs::layout_frame_rate() == 0);
|
||||
mGLX->fSwapInterval(mDisplay, mDrawable, isASAP ? 0 : 1);
|
||||
mGLX->fSwapInterval(*mDisplay, mDrawable, isASAP ? 0 : 1);
|
||||
}
|
||||
return succeeded;
|
||||
}
|
||||
|
@ -661,7 +706,7 @@ bool GLContextGLX::IsDoubleBuffered() const { return mDoubleBuffered; }
|
|||
|
||||
bool GLContextGLX::SwapBuffers() {
|
||||
if (!mDoubleBuffered) return false;
|
||||
mGLX->fSwapBuffers(mDisplay, mDrawable);
|
||||
mGLX->fSwapBuffers(*mDisplay, mDrawable);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -671,7 +716,7 @@ GLint GLContextGLX::GetBufferAge() const {
|
|||
}
|
||||
|
||||
GLuint result = 0;
|
||||
mGLX->fQueryDrawable(mDisplay, mDrawable, LOCAL_GLX_BACK_BUFFER_AGE_EXT,
|
||||
mGLX->fQueryDrawable(*mDisplay, mDrawable, LOCAL_GLX_BACK_BUFFER_AGE_EXT,
|
||||
&result);
|
||||
if (result > INT32_MAX) {
|
||||
// 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 {
|
||||
Display* display = DefaultXDisplay();
|
||||
int screen = DefaultScreen(display);
|
||||
int screen = DefaultScreen(mDisplay->get());
|
||||
|
||||
int majorVersion, minorVersion;
|
||||
sGLXLibrary.fQueryVersion(display, &majorVersion, &minorVersion);
|
||||
sGLXLibrary.fQueryVersion(*mDisplay, &majorVersion, &minorVersion);
|
||||
|
||||
out->Append(nsPrintfCString("GLX %u.%u", majorVersion, minorVersion));
|
||||
|
||||
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->Append(
|
||||
sGLXLibrary.fQueryServerString(display, screen, LOCAL_GLX_VENDOR));
|
||||
sGLXLibrary.fQueryServerString(*mDisplay, screen, LOCAL_GLX_VENDOR));
|
||||
|
||||
out->AppendLiteral("\nExtensions: ");
|
||||
out->Append(sGLXLibrary.fQueryExtensionsString(display, screen));
|
||||
out->Append(sGLXLibrary.fQueryExtensionsString(*mDisplay, screen));
|
||||
}
|
||||
|
||||
bool GLContextGLX::OverrideDrawable(GLXDrawable drawable) {
|
||||
return mGLX->fMakeCurrent(mDisplay, drawable, mContext);
|
||||
return mGLX->fMakeCurrent(*mDisplay, drawable, mContext);
|
||||
}
|
||||
|
||||
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,
|
||||
bool aDeleteDrawable, bool aDoubleBuffered,
|
||||
gfxXlibSurface* aPixmap)
|
||||
|
@ -741,7 +786,7 @@ static bool AreCompatibleVisuals(Visual* one, Visual* two) {
|
|||
already_AddRefed<GLContext> CreateForWidget(Display* aXDisplay, Window aXWindow,
|
||||
bool aHardwareWebRender,
|
||||
bool aForceAccelerated) {
|
||||
if (!sGLXLibrary.EnsureInitialized()) {
|
||||
if (!sGLXLibrary.EnsureInitialized(aXDisplay)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -774,7 +819,8 @@ already_AddRefed<GLContext> CreateForWidget(Display* aXDisplay, Window aXWindow,
|
|||
} else {
|
||||
flags = CreateContextFlags::REQUIRE_COMPAT_PROFILE;
|
||||
}
|
||||
return GLContextGLX::CreateGLContext({{flags}, false}, aXDisplay, aXWindow,
|
||||
return GLContextGLX::CreateGLContext({{flags}, false},
|
||||
XlibDisplay::Borrow(aXDisplay), aXWindow,
|
||||
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 useAlpha, int* const out_visualId) {
|
||||
if (!sGLXLibrary.EnsureInitialized()) {
|
||||
if (!sGLXLibrary.EnsureInitialized(display)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1005,31 +1051,32 @@ static already_AddRefed<GLContextGLX> CreateOffscreenPixmapContext(
|
|||
const GLContextCreateDesc& desc, const IntSize& size,
|
||||
nsACString* const out_failureId) {
|
||||
GLXLibrary* glx = &sGLXLibrary;
|
||||
if (!glx->EnsureInitialized()) return nullptr;
|
||||
auto display = glx->GetDisplay();
|
||||
|
||||
Display* display = DefaultXDisplay();
|
||||
int screen = DefaultScreen(display);
|
||||
if (!display || !glx->EnsureInitialized(*display)) return nullptr;
|
||||
|
||||
int screen = DefaultScreen(display->get());
|
||||
|
||||
ScopedXFree<GLXFBConfig> scopedConfigArr;
|
||||
GLXFBConfig config;
|
||||
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.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Visual* visual;
|
||||
int depth;
|
||||
FindVisualAndDepth(display, visid, &visual, &depth);
|
||||
FindVisualAndDepth(*display, visid, &visual, &depth);
|
||||
|
||||
OffMainThreadScopedXErrorHandler xErrorHandler;
|
||||
bool error = false;
|
||||
|
||||
gfx::IntSize dummySize(16, 16);
|
||||
RefPtr<gfxXlibSurface> surface = gfxXlibSurface::Create(
|
||||
DefaultScreenOfDisplay(display), visual, dummySize);
|
||||
display, DefaultScreenOfDisplay(display->get()), visual, dummySize);
|
||||
if (surface->CairoStatus() != 0) {
|
||||
mozilla::Unused << xErrorHandler.SyncAndGetError(display);
|
||||
mozilla::Unused << xErrorHandler.SyncAndGetError(*display);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1037,12 +1084,12 @@ static already_AddRefed<GLContextGLX> CreateOffscreenPixmapContext(
|
|||
// its pre-GLX-1.3 extension equivalent (though given the ABI, we
|
||||
// might not need to).
|
||||
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) {
|
||||
error = true;
|
||||
}
|
||||
|
||||
bool serverError = xErrorHandler.SyncAndGetError(display);
|
||||
bool serverError = xErrorHandler.SyncAndGetError(*display);
|
||||
if (error || serverError) return nullptr;
|
||||
|
||||
auto fullDesc = GLContextDesc{desc};
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include "GLContextTypes.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/DataMutex.h"
|
||||
#include "mozilla/gfx/XlibDisplay.h"
|
||||
#include "prlink.h"
|
||||
typedef realGLboolean GLboolean;
|
||||
|
||||
|
@ -33,172 +35,174 @@ class GLContextGLX;
|
|||
|
||||
class GLXLibrary final {
|
||||
public:
|
||||
bool EnsureInitialized();
|
||||
bool EnsureInitialized(Display* aDisplay);
|
||||
|
||||
private:
|
||||
class WrapperScope final {
|
||||
const GLXLibrary& mGlx;
|
||||
const char* const mFuncName;
|
||||
Display* const mDisplay;
|
||||
|
||||
public:
|
||||
WrapperScope(const GLXLibrary& glx, const char* const funcName);
|
||||
WrapperScope(const GLXLibrary& glx, const char* const funcName,
|
||||
Display* aDisplay);
|
||||
~WrapperScope();
|
||||
};
|
||||
|
||||
public:
|
||||
#ifdef DEBUG
|
||||
# define DECL_WRAPPER_SCOPE const WrapperScope wrapperScope(*this, __func__);
|
||||
# define DECL_WRAPPER_SCOPE(display) \
|
||||
const WrapperScope wrapperScope(*this, __func__, display);
|
||||
#else
|
||||
# define DECL_WRAPPER_SCOPE
|
||||
# define DECL_WRAPPER_SCOPE(display)
|
||||
#endif
|
||||
|
||||
void fDestroyContext(Display* display, GLXContext context) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fDestroyContext(display, context);
|
||||
}
|
||||
|
||||
Bool fMakeCurrent(Display* display, GLXDrawable drawable,
|
||||
GLXContext context) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fMakeCurrent(display, drawable, context);
|
||||
}
|
||||
|
||||
XVisualInfo* fGetConfig(Display* display, XVisualInfo* info, int attrib,
|
||||
int* value) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fGetConfig(display, info, attrib, value);
|
||||
}
|
||||
|
||||
GLXContext fGetCurrentContext() const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(nullptr)
|
||||
return mSymbols.fGetCurrentContext();
|
||||
}
|
||||
|
||||
GLXFBConfig* fChooseFBConfig(Display* display, int screen,
|
||||
const int* attrib_list, int* nelements) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fChooseFBConfig(display, screen, attrib_list, nelements);
|
||||
}
|
||||
|
||||
XVisualInfo* fChooseVisual(Display* display, int screen,
|
||||
int* attrib_list) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fChooseVisual(display, screen, attrib_list);
|
||||
}
|
||||
|
||||
GLXFBConfig* fGetFBConfigs(Display* display, int screen,
|
||||
int* nelements) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fGetFBConfigs(display, screen, nelements);
|
||||
}
|
||||
|
||||
GLXContext fCreateNewContext(Display* display, GLXFBConfig config,
|
||||
int render_type, GLXContext share_list,
|
||||
Bool direct) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fCreateNewContext(display, config, render_type, share_list,
|
||||
direct);
|
||||
}
|
||||
|
||||
int fGetFBConfigAttrib(Display* display, GLXFBConfig config, int attribute,
|
||||
int* value) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fGetFBConfigAttrib(display, config, attribute, value);
|
||||
}
|
||||
|
||||
void fSwapBuffers(Display* display, GLXDrawable drawable) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fSwapBuffers(display, drawable);
|
||||
}
|
||||
|
||||
const char* fQueryExtensionsString(Display* display, int screen) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fQueryExtensionsString(display, screen);
|
||||
}
|
||||
|
||||
const char* fGetClientString(Display* display, int screen) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fGetClientString(display, screen);
|
||||
}
|
||||
|
||||
const char* fQueryServerString(Display* display, int screen, int name) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fQueryServerString(display, screen, name);
|
||||
}
|
||||
|
||||
GLXPixmap fCreatePixmap(Display* display, GLXFBConfig config, Pixmap pixmap,
|
||||
const int* attrib_list) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fCreatePixmap(display, config, pixmap, attrib_list);
|
||||
}
|
||||
|
||||
GLXPixmap fCreateGLXPixmapWithConfig(Display* display, GLXFBConfig config,
|
||||
Pixmap pixmap) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fCreateGLXPixmapWithConfig(display, config, pixmap);
|
||||
}
|
||||
|
||||
void fDestroyPixmap(Display* display, GLXPixmap pixmap) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fDestroyPixmap(display, pixmap);
|
||||
}
|
||||
|
||||
Bool fQueryVersion(Display* display, int* major, int* minor) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fQueryVersion(display, major, minor);
|
||||
}
|
||||
|
||||
void fBindTexImage(Display* display, GLXDrawable drawable, int buffer,
|
||||
const int* attrib_list) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fBindTexImageEXT(display, drawable, buffer, attrib_list);
|
||||
}
|
||||
|
||||
void fReleaseTexImage(Display* display, GLXDrawable drawable,
|
||||
int buffer) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fReleaseTexImageEXT(display, drawable, buffer);
|
||||
}
|
||||
|
||||
void fWaitGL() const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(nullptr)
|
||||
return mSymbols.fWaitGL();
|
||||
}
|
||||
|
||||
void fWaitX() const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(nullptr)
|
||||
return mSymbols.fWaitX();
|
||||
}
|
||||
|
||||
GLXContext fCreateContextAttribs(Display* display, GLXFBConfig config,
|
||||
GLXContext share_list, Bool direct,
|
||||
const int* attrib_list) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(display)
|
||||
return mSymbols.fCreateContextAttribsARB(display, config, share_list,
|
||||
direct, attrib_list);
|
||||
}
|
||||
|
||||
int fGetVideoSync(unsigned int* count) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(nullptr)
|
||||
return mSymbols.fGetVideoSyncSGI(count);
|
||||
}
|
||||
|
||||
int fWaitVideoSync(int divisor, int remainder, unsigned int* count) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(nullptr)
|
||||
return mSymbols.fWaitVideoSyncSGI(divisor, remainder, count);
|
||||
}
|
||||
|
||||
void fSwapInterval(Display* dpy, GLXDrawable drawable, int interval) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(dpy)
|
||||
return mSymbols.fSwapIntervalEXT(dpy, drawable, interval);
|
||||
}
|
||||
|
||||
int fQueryDrawable(Display* dpy, GLXDrawable drawable, int attribute,
|
||||
unsigned int* value) const {
|
||||
DECL_WRAPPER_SCOPE
|
||||
DECL_WRAPPER_SCOPE(dpy)
|
||||
return mSymbols.fQueryDrawable(dpy, drawable, attribute, value);
|
||||
}
|
||||
|
||||
#undef DECL_WRAPPER_SCOPE
|
||||
|
||||
////
|
||||
|
@ -216,7 +220,7 @@ class GLXLibrary final {
|
|||
bool HasVideoMemoryPurge() { return mHasVideoMemoryPurge; }
|
||||
bool HasCreateContextAttribs() { return mHasCreateContextAttribs; }
|
||||
bool SupportsTextureFromPixmap(gfxASurface* aSurface);
|
||||
bool SupportsVideoSync();
|
||||
bool SupportsVideoSync(Display* aDisplay);
|
||||
bool SupportsSwapControl() const { return bool(mSymbols.fSwapIntervalEXT); }
|
||||
bool SupportsBufferAge() const {
|
||||
MOZ_ASSERT(mInitialized);
|
||||
|
@ -227,6 +231,8 @@ class GLXLibrary final {
|
|||
|
||||
auto GetGetProcAddress() const { return mSymbols.fGetProcAddress; }
|
||||
|
||||
std::shared_ptr<gfx::XlibDisplay> GetDisplay();
|
||||
|
||||
private:
|
||||
struct {
|
||||
void(GLAPIENTRY* fDestroyContext)(Display*, GLXContext);
|
||||
|
@ -276,6 +282,8 @@ class GLXLibrary final {
|
|||
bool mIsNVIDIA = false;
|
||||
bool mClientIsMesa = false;
|
||||
PRLibrary* mOGLLibrary = nullptr;
|
||||
StaticDataMutex<std::weak_ptr<gfx::XlibDisplay>> mOwnDisplay{
|
||||
"GLXLibrary::mOwnDisplay"};
|
||||
};
|
||||
|
||||
// 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/gfx/2D.h"
|
||||
#include "mozilla/gfx/Logging.h"
|
||||
#include "mozilla/gfx/XlibDisplay.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/StaticPrefs_gfx.h"
|
||||
|
@ -686,8 +687,9 @@ class GtkVsyncSource final : public VsyncSource {
|
|||
return;
|
||||
}
|
||||
|
||||
mGLContext = gl::GLContextGLX::CreateGLContext({}, mXDisplay, root,
|
||||
config, false, nullptr);
|
||||
mGLContext = gl::GLContextGLX::CreateGLContext(
|
||||
{}, gfx::XlibDisplay::Borrow(mXDisplay), root, config, false,
|
||||
nullptr);
|
||||
|
||||
if (!mGLContext) {
|
||||
lock.NotifyAll();
|
||||
|
@ -831,7 +833,7 @@ already_AddRefed<gfx::VsyncSource> gfxPlatformGtk::CreateHardwareVsyncSource() {
|
|||
}
|
||||
# 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
|
||||
// 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.
|
||||
if (!gfxVars::UseEGL() || (adapterDriverVendor.Find("mesa") != -1)) {
|
||||
useGlxVsync = gl::sGLXLibrary.SupportsVideoSync();
|
||||
useGlxVsync = gl::sGLXLibrary.SupportsVideoSync(DefaultXDisplay());
|
||||
}
|
||||
if (useGlxVsync) {
|
||||
RefPtr<VsyncSource> vsyncSource = new GtkVsyncSource();
|
||||
|
|
|
@ -25,7 +25,7 @@ using namespace mozilla::gfx;
|
|||
|
||||
gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual)
|
||||
: mPixmapTaken(false),
|
||||
mDisplay(dpy),
|
||||
mDisplay(XlibDisplay::Borrow(dpy)),
|
||||
mDrawable(drawable),
|
||||
mGLXPixmap(X11None) {
|
||||
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,
|
||||
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),
|
||||
mDisplay(dpy),
|
||||
mDrawable(drawable),
|
||||
|
@ -43,8 +48,8 @@ gfxXlibSurface::gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual,
|
|||
NS_ASSERTION(Factory::CheckSurfaceSize(size, XLIB_IMAGE_SIDE_SIZE_LIMIT),
|
||||
"Bad size");
|
||||
|
||||
cairo_surface_t* surf =
|
||||
cairo_xlib_surface_create(dpy, drawable, visual, size.width, size.height);
|
||||
cairo_surface_t* surf = cairo_xlib_surface_create(*dpy, drawable, visual,
|
||||
size.width, size.height);
|
||||
Init(surf);
|
||||
}
|
||||
|
||||
|
@ -52,14 +57,14 @@ gfxXlibSurface::gfxXlibSurface(Screen* screen, Drawable drawable,
|
|||
XRenderPictFormat* format,
|
||||
const gfx::IntSize& size)
|
||||
: mPixmapTaken(false),
|
||||
mDisplay(DisplayOfScreen(screen)),
|
||||
mDisplay(XlibDisplay::Borrow(DisplayOfScreen(screen))),
|
||||
mDrawable(drawable),
|
||||
mGLXPixmap(X11None) {
|
||||
NS_ASSERTION(Factory::CheckSurfaceSize(size, XLIB_IMAGE_SIDE_SIZE_LIMIT),
|
||||
"Bad Size");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -69,7 +74,7 @@ gfxXlibSurface::gfxXlibSurface(cairo_surface_t* csurf)
|
|||
"Not expecting an error surface");
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -78,9 +83,9 @@ gfxXlibSurface::~gfxXlibSurface() {
|
|||
// gfxASurface's destructor calls RecordMemoryFreed().
|
||||
if (mPixmapTaken) {
|
||||
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(
|
||||
Screen* screen, Visual* visual, const gfx::IntSize& size,
|
||||
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),
|
||||
relatedDrawable);
|
||||
if (!drawable) return nullptr;
|
||||
|
||||
RefPtr<gfxXlibSurface> result =
|
||||
new gfxXlibSurface(DisplayOfScreen(screen), drawable, visual, size);
|
||||
new gfxXlibSurface(display, drawable, visual, size);
|
||||
result->TakePixmap();
|
||||
|
||||
if (result->CairoStatus() != 0) return nullptr;
|
||||
|
@ -218,7 +233,7 @@ already_AddRefed<gfxASurface> gfxXlibSurface::CreateSimilarSurface(
|
|||
static bool force24bpp = GetForce24bppPref();
|
||||
if (force24bpp && cairo_xlib_surface_get_depth(CairoSurface()) != 24) {
|
||||
XRenderPictFormat* format =
|
||||
XRenderFindStandardFormat(mDisplay, PictStandardRGB24);
|
||||
XRenderFindStandardFormat(*mDisplay, PictStandardRGB24);
|
||||
if (format) {
|
||||
// Cairo only performs simple self-copies as desired if it
|
||||
// knows that this is a Pixmap surface. It only knows that
|
||||
|
@ -240,7 +255,7 @@ already_AddRefed<gfxASurface> gfxXlibSurface::CreateSimilarSurface(
|
|||
|
||||
void gfxXlibSurface::Finish() {
|
||||
if (mPixmapTaken && mGLXPixmap) {
|
||||
gl::sGLXLibrary.DestroyPixmap(mDisplay, mGLXPixmap);
|
||||
gl::sGLXLibrary.DestroyPixmap(*mDisplay, mGLXPixmap);
|
||||
mGLXPixmap = X11None;
|
||||
}
|
||||
gfxASurface::Finish();
|
||||
|
@ -259,7 +274,7 @@ const gfx::IntSize gfxXlibSurface::DoSizeQuery() {
|
|||
int x_ignore, y_ignore;
|
||||
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);
|
||||
|
||||
return gfx::IntSize(width, height);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "X11UndefineNone.h"
|
||||
|
||||
#include "GLXLibrary.h"
|
||||
#include "mozilla/gfx/XlibDisplay.h"
|
||||
|
||||
#include "nsSize.h"
|
||||
|
||||
|
@ -31,6 +32,9 @@ class gfxXlibSurface final : public gfxASurface {
|
|||
// and known width/height.
|
||||
gfxXlibSurface(Display* dpy, Drawable drawable, Visual* visual,
|
||||
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,
|
||||
// and known width/height.
|
||||
|
@ -46,6 +50,10 @@ class gfxXlibSurface final : public gfxASurface {
|
|||
static already_AddRefed<gfxXlibSurface> Create(
|
||||
::Screen* screen, Visual* visual, const mozilla::gfx::IntSize& size,
|
||||
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(
|
||||
::Screen* screen, Visual* visual, const mozilla::gfx::IntSize& size,
|
||||
Drawable relatedDrawable = X11None);
|
||||
|
@ -61,7 +69,7 @@ class gfxXlibSurface final : public gfxASurface {
|
|||
|
||||
const mozilla::gfx::IntSize GetSize() const override;
|
||||
|
||||
Display* XDisplay() { return mDisplay; }
|
||||
Display* XDisplay() { return *mDisplay; }
|
||||
::Screen* XScreen();
|
||||
Drawable XDrawable() { return mDrawable; }
|
||||
XRenderPictFormat* XRenderFormat();
|
||||
|
@ -98,15 +106,15 @@ class gfxXlibSurface final : public gfxASurface {
|
|||
bool IsPadSlow() {
|
||||
// The test here matches that for buggy_pad_reflect in
|
||||
// _cairo_xlib_device_create.
|
||||
return VendorRelease(mDisplay) >= 60700000 ||
|
||||
VendorRelease(mDisplay) < 10699000;
|
||||
return VendorRelease(mDisplay->get()) >= 60700000 ||
|
||||
VendorRelease(mDisplay->get()) < 10699000;
|
||||
}
|
||||
|
||||
protected:
|
||||
// if TakePixmap() has been called on this
|
||||
bool mPixmapTaken;
|
||||
|
||||
Display* mDisplay;
|
||||
std::shared_ptr<mozilla::gfx::XlibDisplay> mDisplay;
|
||||
Drawable mDrawable;
|
||||
|
||||
const mozilla::gfx::IntSize DoSizeQuery();
|
||||
|
|
|
@ -135,9 +135,13 @@ elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk":
|
|||
"gfxXlibNativeRenderer.h",
|
||||
"gfxXlibSurface.h",
|
||||
]
|
||||
EXPORTS.mozilla.gfx += [
|
||||
"XlibDisplay.h",
|
||||
]
|
||||
SOURCES += [
|
||||
"gfxXlibNativeRenderer.cpp",
|
||||
"gfxXlibSurface.cpp",
|
||||
"XlibDisplay.cpp",
|
||||
]
|
||||
|
||||
elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "windows":
|
||||
|
|
Загрузка…
Ссылка в новой задаче