Bug 1650583 [Linux/EGL] Implement GLContextEGL::FindVisual(), r=jgilbert

Implement GLContextEGL::FindVisual() as a EGL counterpart of GLContextGLX::FindVisual() used
by GLX.

We need to make sure that GdkWindow uses the same visual as GL framebuffer we use for it.
That was already implemented for GLX backend (Bug 1478454).

The visual match is implemented by visual parameter at CreateConfig()/CreateConfigScreen() routines and when it's non-zero,
try to find exact match based on visual ID.

Differential Revision: https://phabricator.services.mozilla.com/D87636
This commit is contained in:
stransky 2020-09-03 09:02:44 +00:00
Родитель 1b305cb7c0
Коммит 3468f83483
2 изменённых файлов: 81 добавлений и 8 удалений

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

@ -117,6 +117,11 @@ class GLContextEGL final : public GLContext {
static EGLSurface CreateEGLSurfaceForCompositorWidget(
widget::CompositorWidget* aCompositorWidget, const EGLConfig aConfig);
#ifdef MOZ_X11
static bool FindVisual(bool aUseWebRender, bool useAlpha,
int* const out_visualId);
#endif
protected:
friend class GLContextProviderEGL;
friend class GLContextEGLFactory;
@ -156,9 +161,10 @@ class GLContextEGL final : public GLContext {
};
// -
// aVisual is used in Linux only to exactly match window and framebuffer
// visuals on NVIDIA drivers (Bug 1478454).
bool CreateConfig(EglDisplay&, EGLConfig* aConfig, int32_t depth,
bool aEnableDepthBuffer, bool aUseGles);
bool aEnableDepthBuffer, bool aUseGles, int aVisual = 0);
} // namespace gl
} // namespace mozilla

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

@ -92,6 +92,15 @@ inline bool IsWaylandDisplay() {
#endif
}
inline bool IsX11Display() {
#ifdef MOZ_WIDGET_GTK
return gdk_display_get_default() &&
GDK_IS_X11_DISPLAY(gdk_display_get_default());
#else
return false;
#endif
}
struct wl_egl_window;
using namespace mozilla::gfx;
@ -130,7 +139,7 @@ void DeleteWaylandGLSurface(EGLSurface surface) {
static bool CreateConfigScreen(EglDisplay&, EGLConfig* const aConfig,
const bool aEnableDepthBuffer,
const bool aUseGles);
const bool aUseGles, int aVisual = 0);
// append three zeros at the end of attribs list to work around
// EGL implementation bugs that iterate until they find 0, instead of
@ -256,6 +265,22 @@ already_AddRefed<GLContext> GLContextEGLFactory::CreateImpl(
return nullptr;
}
int visualID = 0;
if (IsX11Display()) {
#ifdef MOZ_X11
GdkDisplay* gdkDisplay = gdk_display_get_default();
auto display = gdkDisplay ? GDK_DISPLAY_XDISPLAY(gdkDisplay) : nullptr;
if (display) {
XWindowAttributes windowAttrs;
if (!XGetWindowAttributes(display, (Window)aWindow, &windowAttrs)) {
NS_WARNING("[EGL] XGetWindowAttributes() failed");
return nullptr;
}
visualID = XVisualIDFromVisual(windowAttrs.visual);
}
#endif
}
bool doubleBuffered = true;
EGLConfig config;
@ -270,14 +295,16 @@ already_AddRefed<GLContext> GLContextEGLFactory::CreateImpl(
}
} else {
if (aDepth) {
if (!CreateConfig(*egl, &config, aDepth, aWebRender, aUseGles)) {
if (!CreateConfig(*egl, &config, aDepth, aWebRender, aUseGles,
visualID)) {
gfxCriticalNote
<< "Failed to create EGLConfig for WebRender with depth!";
return nullptr;
}
} else {
if (!CreateConfigScreen(*egl, &config,
/* aEnableDepthBuffer */ aWebRender, aUseGles)) {
/* aEnableDepthBuffer */ aWebRender, aUseGles,
visualID)) {
gfxCriticalNote << "Failed to create EGLConfig!";
return nullptr;
}
@ -287,6 +314,9 @@ already_AddRefed<GLContext> GLContextEGLFactory::CreateImpl(
EGLSurface surface = EGL_NO_SURFACE;
if (aWindow) {
surface = mozilla::gl::CreateSurfaceFromNativeWindow(*egl, aWindow, config);
if (!surface) {
return nullptr;
}
}
CreateContextFlags flags = CreateContextFlags::NONE;
@ -835,7 +865,7 @@ static const EGLint kEGLConfigAttribsRGBA32[] = {
LOCAL_EGL_ALPHA_SIZE, 8};
bool CreateConfig(EglDisplay& egl, EGLConfig* aConfig, int32_t depth,
bool aEnableDepthBuffer, bool aUseGles) {
bool aEnableDepthBuffer, bool aUseGles, int aVisual) {
EGLConfig configs[64];
std::vector<EGLint> attribs;
EGLint ncfg = ArrayLength(configs);
@ -890,6 +920,15 @@ bool CreateConfig(EglDisplay& egl, EGLConfig* aConfig, int32_t depth,
continue;
}
}
#if defined(MOZ_X11)
if (aVisual) {
int vis;
if (!egl.fGetConfigAttrib(config, LOCAL_EGL_NATIVE_VISUAL_ID, &vis) ||
aVisual != vis) {
continue;
}
}
#endif
*aConfig = config;
return true;
}
@ -902,11 +941,13 @@ bool CreateConfig(EglDisplay& egl, EGLConfig* aConfig, int32_t depth,
//
// NB: It's entirely legal for the returned EGLConfig to be valid yet
// have the value null.
// aVisual is used in Linux only.
static bool CreateConfigScreen(EglDisplay& egl, EGLConfig* const aConfig,
const bool aEnableDepthBuffer,
const bool aUseGles) {
const bool aUseGles, int aVisual) {
int32_t depth = gfxVars::ScreenDepth();
if (CreateConfig(egl, aConfig, depth, aEnableDepthBuffer, aUseGles)) {
if (CreateConfig(egl, aConfig, depth, aEnableDepthBuffer, aUseGles,
aVisual)) {
return true;
}
#ifdef MOZ_WIDGET_ANDROID
@ -1045,6 +1086,32 @@ static EGLConfig ChooseConfig(EglDisplay& egl, const GLContextCreateDesc& desc,
return config;
}
#ifdef MOZ_X11
/* static */
bool GLContextEGL::FindVisual(bool aUseWebRender, bool useAlpha,
int* const out_visualId) {
nsCString discardFailureId;
const auto egl = DefaultEglDisplay(&discardFailureId);
if (!egl) {
gfxCriticalNote
<< "GLContextEGL::FindVisual(): Failed to load EGL library!";
return false;
}
EGLConfig config;
const int bpp = useAlpha ? 32 : 24;
if (!CreateConfig(*egl, &config, bpp, aUseWebRender, /* aUseGles */ false)) {
gfxCriticalNote
<< "GLContextEGL::FindVisual(): Failed to create EGLConfig!";
return false;
}
if (egl->fGetConfigAttrib(config, LOCAL_EGL_NATIVE_VISUAL_ID, out_visualId)) {
return true;
}
return false;
}
#endif
/*static*/
RefPtr<GLContextEGL> GLContextEGL::CreateEGLPBufferOffscreenContextImpl(
const std::shared_ptr<EglDisplay> egl, const GLContextCreateDesc& desc,