Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EGL/Wayland (Wayland, pt 3) #2484

Merged
merged 20 commits into from Feb 12, 2021

Conversation

GeorgesStavracas
Copy link
Member

@GeorgesStavracas GeorgesStavracas commented Mar 10, 2020

(This depends on #2478 and #2482 and thus includes its commits)

This pull requests builds on top of @w23 and @cyclopsian's work, and their code (or code heavily inspired by them) is appropriately credited.

Description

Add a new gl-nix-egl-wayland winsys to libobs-opengl, and hook the code to use this winsys when (1) Wayland is enabled, and (2) the current seat is a Wayland session.

A couple of places where the codebase was tied to X11 had to be modified in order to be X11-agnostic.

Motivation and Context

This is the 3rd step of RFC #14.

The goal of this pull request is introduce the EGL/Wayland winsys to libobs-opengl.

How Has This Been Tested?

Under a Wayland desktop environment, run:

$ QT_QPA_PLATFORM=wayland obs

My particular setup is Linux + GNOME + Wayland.

Known Issues

  • Toggling the preview off and on results in a crash
  • The preview widget doesn't scale properly when switching between monitors with different scales
  • The EGL/Wayland code needs an in-depth review

Types of changes

  • New feature (non-breaking change which adds functionality)

Checklist:

  • My code has been run through clang-format.
  • I have read the contributing document.
  • My code is not on the master branch.
  • The code has been tested.
  • All commit messages are properly formatted and commits squashed where appropriate.

@ghost
Copy link

ghost commented Mar 27, 2020

This is looking really good, thanks for doing this.

Copy link
Collaborator

@kkartaltepe kkartaltepe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done reviewing for today. These comments are across this PR because i find little value in the intermediate steps. I hope its not too much trouble to pull the changes into the appropriate commit (i know if you use mercurial there is a neat absorb function that does this)

And thanks a lot for working on this PR and bringing everything together. I really appreciate it.

UI/obs-app.cpp Outdated Show resolved Hide resolved
UI/qt-wrappers.cpp Show resolved Hide resolved
UI/qt-wrappers.cpp Show resolved Hide resolved
cmake/Modules/FindEGL.cmake Outdated Show resolved Hide resolved
cmake/Modules/FindEGL.cmake Outdated Show resolved Hide resolved
libobs/graphics/graphics.h Outdated Show resolved Hide resolved
libobs/obs-nix-wayland.c Show resolved Hide resolved
libobs/obs-nix-wayland.c Outdated Show resolved Hide resolved
libobs/obs-nix-x11.c Show resolved Hide resolved
libobs/obs-platform.h Outdated Show resolved Hide resolved
@kkartaltepe
Copy link
Collaborator

kkartaltepe commented Apr 4, 2020

xcompcap plugins are dependent on GLX. If possible getting them to work with both backends would be nice otherwise we should prevent them from loading/initializing when the EGL platform is being used.

@GeorgesStavracas GeorgesStavracas force-pushed the feaneron/egl-wayland branch 2 times, most recently from 2053fae to e268252 Compare April 9, 2020 03:11
@GeorgesStavracas
Copy link
Member Author

I've investigated using EGL in the linux-capture plugins, but it would be quite complicated. For now, I just went with disabling the linux-capture plugins entirely.

I'm slowly working towards another linux-capture plugin that works both with Wayland and X11.

@GeorgesStavracas GeorgesStavracas marked this pull request as ready for review April 9, 2020 03:17
Copy link
Collaborator

@kkartaltepe kkartaltepe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is all my concerns.

UI/qt-wrappers.cpp Outdated Show resolved Hide resolved
UI/qt-wrappers.cpp Outdated Show resolved Hide resolved
cmake/Modules/FindWayland.cmake Outdated Show resolved Hide resolved
cmake/Modules/FindWayland.cmake Show resolved Hide resolved
deps/glad/CMakeLists.txt Outdated Show resolved Hide resolved
libobs-opengl/gl-x11-egl.c Outdated Show resolved Hide resolved
libobs/CMakeLists.txt Outdated Show resolved Hide resolved
libobs/obs-nix-wayland.c Show resolved Hide resolved
libobs/obs-platform.h Outdated Show resolved Hide resolved
plugins/linux-capture/linux-capture.c Outdated Show resolved Hide resolved
@GeorgesStavracas GeorgesStavracas force-pushed the feaneron/egl-wayland branch 3 times, most recently from c48b435 to 9efe3ec Compare April 12, 2020 03:22
@GeorgesStavracas
Copy link
Member Author

Alright this is the last push. It was missing an include of obs.h. Should be all fine now.

@colemickens
Copy link

I've been building and testing this for a few days. I'm not an extensive OBS user but it's been working well (including dmabuf with wlr-obs). Thank you very much for this!

@GeorgesStavracas
Copy link
Member Author

  • Toggling the preview off and on results in a crash

I've done an extensive debugging session yesterday and today, and I'm 95% confident that this crash is caused by Qt violating the Wayland protocol. Keep in mind that OBS Studio doesn't directly use Wayland APIs, or try to communicate stuff through the Wayland socket. The debug spew that WAYLAND_DEBUG=1 throws shows that Qt is trying to use an object that doesn't exist, and it's not an object that OBS Studio has access to.

@ohthehugemanatee
Copy link

Tried to test this today, but I can't seem to compile on my manjaro system. It fails without explanation on Makefile:172, the make CMakefles/Makefile2 all step. Running it by hand, I get

» make -f CMakeFiles/Makefile2 all
[ 28%] Linking C shared library libobsglad.so
/usr/bin/ld: CMakeFiles/glad.dir/src/glad_glx.c.o:/home/ohthehugemanatee/Projects/personal/obs-studio/deps/glad/src/glad_glx.c:38: multiple definition of `gladGetProcAddressPtr'; CMakeFiles/glad.dir/src/glad.c.o:/home/ohthehugemanatee/Projects/personal/obs-studio/deps/glad/src/glad.c:38: first defined here
collect2: error: ld returned 1 exit status
make[1]: *** [deps/glad/CMakeFiles/glad.dir/build.make:136: deps/glad/libobsglad.so.0] Error 1
make: *** [CMakeFiles/Makefile2:824: deps/glad/CMakeFiles/glad.dir/all] Error 2

I see that this PR does a lot with glad... Any chance this is a problem in the PR? Otherwise, where should I go to get help compiling?

@kkartaltepe
Copy link
Collaborator

Either set -fcommon or rebase over #2864

@ohthehugemanatee
Copy link

Thanks, @kkartaltepe ! That got me unstuck. Playing and testing now on a rebased version.

Everything seems fine at first glance, though there are some anomalies in stdout:

  • info section says "Portable mode: false", which is incorrect.
  • lots of qt.qpa.wayland: Ignoring unexpected wl_surface.enter received for output with id: 14 screen name: "eDP-1" screen model: "0x14A8" This is most likely a bug in the compositor. . I tend to believe the error message that this isn't OBS's fault.
  • Exiting via SIGTERM got me a fatal error and core dump, every time.
wl_display@1: error 0: invalid object 24
The Wayland connection experienced a fatal error: Invalid argument
[1]    271416 abort (core dumped)  ./obs

Full stdOut follows.

» ./obs
qt5ct: using qt5ct plugin
Attempted path: ../../data/obs-studio/locale/en-US.ini
Attempted path: ../../data/obs-studio/locale.ini
Attempted path: ../../data/obs-studio/themes/Dark.qss
info: Platform: Wayland
info: CPU Name: Intel(R) Core(TM) i7-1065G7 CPU @ 1.30GHz
info: CPU Speed: 1681.278MHz
info: Physical Cores: 4, Logical Cores: 8
info: Physical Memory: 31889MB Total, 18269MB Free
info: Kernel Version: Linux 5.6.15-1-MANJARO
info: Distribution: "Manjaro Linux" Unknown
info: Portable mode: false
qt5ct: D-Bus global menu: no
Attempted path: ../../data/obs-studio/themes/Dark/no_sources.svg
QMetaObject::connectSlotsByName: No matching signal for on_advAudioProps_clicked()
QMetaObject::connectSlotsByName: No matching signal for on_advAudioProps_destroyed()
QMetaObject::connectSlotsByName: No matching signal for on_actionGridMode_triggered()
QMetaObject::connectSlotsByName: No matching signal for on_program_customContextMenuRequested(QPoint)
info: OBS 25.0.7-208-g57c2e280-modified (linux)
info: ---------------------------------
info: ---------------------------------
info: audio settings reset:
	samples per sec: 44100
	speakers:        2
info: ---------------------------------
info: Initializing OpenGL...
info: Using EGL/Wayland
info: Initialized EGL 1.5
info: Loading up OpenGL on adapter Intel Mesa Intel(R) Iris(R) Plus Graphics (ICL GT2)
info: OpenGL loaded successfully, version 4.6 (Core Profile) Mesa 20.0.7, shading language 4.60
info: ---------------------------------
info: video settings reset:
	base resolution:   1920x1080
	output resolution: 1280x720
	downscale filter:  Bicubic
	fps:               30/1
	format:            NV12
	YUV mode:          601/Partial
info: NV12 texture support not available
info: Audio monitoring device:
	name: Default
	id: default
info: ---------------------------------
warning: Failed to load 'en-US' text for module: 'decklink-ouput-ui.so'
error: linux-capture cannot run on EGL platforms
warning: Failed to initialize module 'linux-capture.so'
libDeckLinkAPI.so: cannot open shared object file: No such file or directory
warning: A DeckLink iterator could not be created.  The DeckLink drivers may not be installed
info: No blackmagic support
info: [obs-browser]: Version 2.8.4
error: os_dlopen(libnvidia-encode.so.1->libnvidia-encode.so.1): libnvidia-encode.so.1: cannot open shared object file: No such file or directory

info: FFMPEG VAAPI supported
info: VLC found, VLC video source enabled
info: ---------------------------------
info:   Loaded Modules:
info:     vlc-video.so
info:     text-freetype2.so
info:     rtmp-services.so
info:     obs-x264.so
info:     obs-vst.so
info:     obs-transitions.so
info:     obs-outputs.so
info:     obs-libfdk.so
info:     obs-filters.so
info:     obs-ffmpeg.so
info:     obs-browser.so
info:     linux-v4l2.so
info:     linux-pulseaudio.so
info:     linux-jack.so
info:     linux-decklink.so
info:     linux-capture.so
info:     linux-alsa.so
info:     image-source.so
info:     frontend-tools.so
info:     decklink-ouput-ui.so
info: ---------------------------------
error: os_dlopen(../obs-plugins/obs-browser->../obs-plugins/obs-browser.so): ../obs-plugins/obs-browser.so: cannot open shared object file: No such file or directory

info: ==== Startup complete ===============================================
error: Service '' not found
info: All scene data cleared
info: ------------------------------------------------
info: pulse-input: Server name: 'pulseaudio 13.0'
info: pulse-input: Audio format: s16le, 48000 Hz, 2 channels
info: pulse-input: Started recording from 'alsa_output.pci-0000_00_1f.3.analog-stereo.monitor'
info: [Loaded global audio device]: 'Desktop Audio'
info: pulse-input: Server name: 'pulseaudio 13.0'
info: pulse-input: Audio format: s16le, 44100 Hz, 1 channels
info: pulse-input: Started recording from 'alsa_input.usb-SJ-180517-N_1080P_Webcam-02.mono-fallback'
info: [Loaded global audio device]: 'Mic/Aux'
info: v4l2-input: Start capture from /dev/video0
info: v4l2-input: Input: 0
info: v4l2-input: Resolution: 1280x720
info: v4l2-input: Pixelformat: VYUY
info: v4l2-input: Linesize: 2560 Bytes
info: v4l2-input: Framerate: 6,00 fps
info: [Media Source 'Media Source']: settings:
	input:
	input_format:            (null)
	speed:                   100
	is_looping:              no
	is_hw_decoding:          no
	is_clear_on_media_end:   yes
	restart_on_activate:     yes
	close_when_inactive:     no
info: pulse-input: Server name: 'pulseaudio 13.0'
error: pulse-input: An error occurred while getting the source info!
info: Switched to scene 'Scene'
info: ------------------------------------------------
info: Loaded scenes:
info: - scene 'Scene':
info:     - source: 'Media Source' (ffmpeg_source)
info:     - source: 'Video Capture Device (V4L2)' (v4l2_input)
info:     - source: 'Audio Input Capture (PulseAudio)' (pulse_input_capture)
info: ------------------------------------------------
qt5ct: D-Bus system tray: yes
qt5ct: custom style sheet is disabled
Attempted path: ../../data/obs-studio/images/overflow.png
qt.qpa.wayland: Ignoring unexpected wl_surface.enter received for output with id: 14 screen name: "eDP-1" screen model: "0x14A8" This is most likely a bug in the compositor.
qt.qpa.wayland: Ignoring unexpected wl_surface.enter received for output with id: 14 screen name: "eDP-1" screen model: "0x14A8" This is most likely a bug in the compositor.
qt.qpa.wayland: Ignoring unexpected wl_surface.enter received for output with id: 14 screen name: "eDP-1" screen model: "0x14A8" This is most likely a bug in the compositor.
qt.qpa.wayland: Ignoring unexpected wl_surface.enter received for output with id: 14 screen name: "eDP-1" screen model: "0x14A8" This is most likely a bug in the compositor.
qt.qpa.wayland: Ignoring unexpected wl_surface.enter received for output with id: 14 screen name: "eDP-1" screen model: "0x14A8" This is most likely a bug in the compositor.
qt.qpa.wayland: Ignoring unexpected wl_surface.enter received for output with id: 14 screen name: "eDP-1" screen model: "0x14A8" This is most likely a bug in the compositor.
qt.qpa.wayland: Ignoring unexpected wl_surface.enter received for output with id: 14 screen name: "eDP-1" screen model: "0x14A8" This is most likely a bug in the compositor.
qt.qpa.wayland: Ignoring unexpected wl_surface.enter received for output with id: 14 screen name: "eDP-1" screen model: "0x14A8" This is most likely a bug in the compositor.
qt.qpa.wayland: Ignoring unexpected wl_surface.enter received for output with id: 14 screen name: "eDP-1" screen model: "0x14A8" This is most likely a bug in the compositor.
info: adding 46 milliseconds of audio buffering, total audio buffering is now 46 milliseconds (source: Mic/Aux)

Attempted path: ../../data/obs-studio/locale.ini
Attempted path: ../../data/obs-studio/themes/
info: ==== Shutting down ==================================================
info: Switched to scene '(null)'
info: v4l2-input: Stopped capture after 1435 frames
info: pulse-input: Stopped recording from 'alsa_output.pci-0000_00_1f.3.analog-stereo.monitor'
info: pulse-input: Got 62337 packets with 14985524 frames
info: pulse-input: Stopped recording from 'alsa_input.usb-SJ-180517-N_1080P_Webcam-02.mono-fallback'
info: pulse-input: Got 31318 packets with 13846228 frames
info: All scene data cleared
info: ------------------------------------------------
wl_display@1: error 0: invalid object 24
The Wayland connection experienced a fatal error: Invalid argument
[1]    271416 abort (core dumped)  ./obs

@ohthehugemanatee
Copy link

Just got a fatal while browsing the menus:

xdg_wm_base@37: error 2: xdg_popup was destroyed while it was not the topmost popup
The Wayland connection experienced a fatal error: Protocol error
[1]    276765

 abort (core dumped)  ./obs

@danshick
Copy link

danshick commented Feb 2, 2021

I've been using the AUR package of this branch for a while now with sway and wlrobs. Every once in a while, if I'm recording for a long time with obs in a different workspace, it'll crash right when I switch back to the workspace with obs in it. I'll be doing long screencasts each week for the next few months. What is the best way to try to capture logs to see if this is a problem with this PR or with wlrobs or some other component of my setup?

@esden
Copy link
Contributor

esden commented Feb 2, 2021

@danshick I have not tested in a while. But I observed the same issue (and know of others who have it too, I will ping them if they still see the same issue). In my case it was happening every time after running OBS on an invisible sway desktop for a minute or two and then switching back to that said desktop, OBS crashed. Unfortunately I don't have GDB backtraces captured. But that might be the way to find out what is wrong.

@danshick
Copy link

danshick commented Feb 2, 2021

I might still have a coredump lying around, but I forget whether or not I disabled binary stripping in the package. Regardless, I'm sure I can reproduce it and get a coredump. Pairing that with a debug log would hopefully be more helpful.

@kkartaltepe
Copy link
Collaborator

A coredump without your symbols will not be helpful, if you can instead provide a backtrace of all threads (with symbols) that would be the most useful thing.

@alebastr
Copy link

alebastr commented Feb 2, 2021

@danshick this sounds familiar; does it crash or exit with wayland protocol error? In the latter case it might be QTBUG-81504

@danshick
Copy link

danshick commented Feb 2, 2021

@danshick this sounds familiar; does it crash or exit with wayland protocol error? In the latter case it might be QTBUG-81504

I'll have some time to reproduce this later this week (with symbols). I'll post logs and coredumps when able.

@danshick
Copy link

danshick commented Feb 4, 2021

I'll have some time to reproduce this later this week (with symbols). I'll post logs and coredumps when able.

obs.log
obs.bt.txt

... this sounds familiar; does it crash or exit with wayland protocol error? In the latter case it might be QTBUG-81504

I think you're right.

@kamushadenes
Copy link

kamushadenes commented Feb 9, 2021

Amazing work!

I'll be testing this under NixOS + Wayland (Sway/wlroots) in the following days.

(btw, Cobra sends his regards from ETEC ;) )

@GeorgesStavracas
Copy link
Member Author

Cobra sends his regards from ETEC

Long time no see, my friend :)

Introduce the OBS_NIX_PLATFORM_WAYLAND enum value, and try to detect
it when OBS Studio runs by looking into the platform name.
We need to ensure we're running all X11 code on the same display.
Introduce a new Wayland/EGL renderer.
On Wayland, we want to query the window's underlying
platform for the Wayland surface, instead of foolishly
retrieving the X11 display.

Pass QWindow instead of WId directly, and set the surface
as the platform data on Wayland systems.
When a window is made invisible, then visible again, the
obs_display is reused. Turns out, QT destroys the wl_surface
associated with the previewer on Wayland. However, the EGL
surface created on top of this wl_surface is not, and any
attempt to attach a new buffer to it will crash OBS.

Destroy the obs_display when becoming invisible, and when
running as a Wayland client. Also nullify the display
variable on destruction, to avoid subclasses double-freeing
the obs display.
Right after showing the OBSQTDisplay widget, it may happen that a
wl_surface is not yet created and attached to the window. When this
happens, creating the OBS display results in a crash.

Make QTToGSWindow return a boolean, indicating success or failure, and
don't create the OBS display on failure.
The sizeChanged callback is connected to the screenChanged signal,
and evidently the naming doesn't match. Rename the callback to
match the signal name.
This is a dangerous operation on Wayland, and is crashing not only
OBS Studio but also the whole compositor. Let's disable it for now
when running as a native Wayland client.

Some compositors (GNOME Shell, Plasma) still allow setting this
option on the window menu.
This will be used by a new event filter, added only when running as a Wayland
client, to force creating the obs_display instance even when not exposed.
This is a workaround for QWaylandWindow never becoming exposed, or
receiving the QEvent::Expose [1].

[1] https://bugreports.qt.io/browse/QTBUG-86176
@jp9000
Copy link
Member

jp9000 commented Feb 12, 2021

This is arguably one of the most well done pull requests I've ever seen. Excellent work. Thank you so much for your patience with this.

@jp9000 jp9000 merged commit 190ab87 into obsproject:master Feb 12, 2021
@fourstepper
Copy link

Thank you!

@alosarjos
Copy link

I've been giving tests to this (Without the DMA BUF for now). I'm not sure if it's a memory leak or what, but sometimes the streaming starts lagging or stuttering a bit. I don't know what triggers it but I can see it on the OBS preview. In Gnome, going to the notification area, stopping the screen share, and selecting again the origin of the screen on the OBS makes it work well again.

Arch Linux 5.10.16-zen1
AMD 5700XT (FFMPEG VAAPI)
Gnome / Mutter 3.38.3

@alosarjos
Copy link

I could get more or less an example, at some point my recording was like this:

first.mp4

Then all I did was stop screen share on Gnome, select again the origin of the screen source a record

second.mp4

I don't know if it's something related to OBS, Gnome, Mutter or what.

heijligen added a commit to heijligen/nixpkgs that referenced this pull request Mar 18, 2021
obs-studio (git master) has native wayland support.
To build further releases of obs-studio this adds wayland to buildInputs

https://github.com/obsproject/obs-studio/wiki/Install-Instructions#linux-build-directions
obsproject/obs-studio#2484
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement Improvement to existing functionality Linux Affects Linux Seeking Testers Build artifacts on CI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet