зеркало из 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:
Родитель
fcbc4fc378
Коммит
90c4b74c25
|
@ -117,6 +117,9 @@ class GLContextEGL final : public GLContext {
|
|||
static EGLSurface CreateEGLSurfaceForCompositorWidget(
|
||||
widget::CompositorWidget* aCompositorWidget, const EGLConfig aConfig);
|
||||
|
||||
static bool FindVisual(bool aUseWebRender, bool useAlpha,
|
||||
int* const out_visualId);
|
||||
|
||||
protected:
|
||||
friend class GLContextProviderEGL;
|
||||
friend class GLContextEGLFactory;
|
||||
|
@ -156,9 +159,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_WIDGET_GTK
|
||||
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_WIDGET_GTK)
|
||||
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,30 @@ static EGLConfig ChooseConfig(EglDisplay& egl, const GLContextCreateDesc& desc,
|
|||
return config;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/*static*/
|
||||
RefPtr<GLContextEGL> GLContextEGL::CreateEGLPBufferOffscreenContextImpl(
|
||||
const std::shared_ptr<EglDisplay> egl, const GLContextCreateDesc& desc,
|
||||
|
|
|
@ -150,6 +150,8 @@ class GLLibraryEGL final {
|
|||
|
||||
bool IsANGLE() const { return mIsANGLE; }
|
||||
|
||||
static bool FindVisual(Display* display, int screen, bool useWebRender,
|
||||
bool useAlpha, int* const out_visualId);
|
||||
// -
|
||||
// PFN wrappers
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче