зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
1b305cb7c0
Коммит
3468f83483
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче