It is expected that capture might fail, like when a window is minimized.
In these cases we dont want the log to be spammed by X11 errors so
install a noop error handler while we try to import.
The original PR missed assigning the `idx` variable in unregister. When
compiled without asserts this would silently not delete sources. Instead
correctly assign idx and skip unregistration if the source doesnt appear
registered.
fixes#6532
When running on EGL we can use the new create_texture_from_pixmap
functions to implement xcomposite capture.
This removes the texture indirection previously implemented for GLX due
to not using the spriting functionality in the built in shaders. Now
that we texture directly from the pixmap we can remove the red/blue swap
workarounds.
Generally moves all the plugin code into xcomposite-input.cpp and
removes all C++ dependencies.
Migrate as much as possible to xcb from Xlib to enable us to handle
errors and attribute them to the correct callers. This caused many other
knock on issues such as wrongly attributed errors and cleanup code
working incorrectly.
That allows us to use the xcursor-xcb implementation and delete the pure
Xlib implementation. We also add the missing functionality from the Xlib
implementation to the xcb implementation.
Capture glXCreatePixmap errors which occur most commonly on
nvidia+gnome due to nvidia's driver being unable to allocate more than 1
pixmap per window and gnome being the only compositor to read window
data via glx pixmaps.
Fix cleanup after failed glXCreatePixmap that might have leaked pixmaps
and prevented later captures on nvidia drivers for the same reason.
Status output related to OBS configuration is prefixed with the string
"OBS" and added padding for enabled and disabled features. This padding
was not aligned between platforms.
By moving the padding and prefix decoration into its own function,
both elements are controlled in a single place. CMake scripts were
changed to use this new function `obs_status` instead of using CMake's
`message` function directly.
Commit a3a6710 introduced the obs_pipewire_save() function in the
PipeWire code, but only set it to the monitor capture source. This
was an oversight, it should have been set to the window capture
source as well.
Set the .save vfunc of the window capture source as well.
Closesobsproject/obs-studio#5906
NVIDIA drivers appears to have a bug where binding would be excessively
slow. Apply a workaround similar to what [KWin] does to prevent the issue.
Also performs a refactor so that the code paths with and without the
workaround can be shared.
[KWin]: 4f2c3a00c4/src/libkwineffects/kwinglplatform.cpp
Fixes: 316f858c6 ("linux-capture: Fix capturing on software rasterization setups")
Closes: https://github.com/obsproject/obs-studio/issues/5685
Tested-By: univrsal <uni@vrsal.xyz>
We've been listing the supported formats in place whenever we
needed so far, but now we're doing it in too many different
places, which is getting confusing.
Move all these sparsely written rules into one single table
of formats, and adjust the code to lookup data on it.
Choice pods are built with the first element being the
preferred choice, followed by a list of possible choices.
We add the preferred choice inside the loop, which makes
the code slightly harder to follow.
Factor this out of the loop, into a separate step.
Ubuntu 21.10 provides PipeWire 0.3.32 which is missing the
`SPA_POD_PROP_FLAG_DONT_FIXATE` required for proper DMA-BUF negotiation.
Since this isn't implemented in the DE's of this Ubuntu version just
defining this flag won't have any impact.
Revert after support for Ubuntu 21.10 ended.
Proper DMA-BUF format and modifier negotiation is possible with PipeWire
0.3.40. This commit adds checks for older versions and allows to build
against them.
These are classified as follows:
* PipeWire server older than 0.3.24: Restrict to SHM only
* PipeWire server between 0.3.24 (incl.) and 0.3.40: Announce modifiers
along with the old method. On failed import drop all modifiers.
* PipeWire server 0.3.40 and newer: Announce modifiers along with the
old method. On failed import drop only a single modifier.
We require PipeWire 0.3.33 or later to make use of the introduces flags
`SPA_POD_PROP_FLAG_MANDATORY` and `SPA_POD_PROP_FLAG_DONT_FIXATE`,
which are required for the negotiation process introduced in the
following commits.
It was naive to add these defines here to avoid a direct include when
the entire platform already depends on the DRM subsystem. Just include
it and let it provide the image formats.
The GLX_EXT_texture_from_pixmap spec says:
The contents of the texture after the drawable has been bound are defined
as the result of all rendering that has completed before the call to
glXBindTexImageEXT. In other words, the results of any operation which
has caused damage on the drawable prior to the glXBindTexImageEXT call
will be represented in the texture.
Rendering to the drawable while it is bound to a texture will leave the
contents of the texture in an undefined state. However, no
synchronization between rendering and texturing is done by GLX. It is
the application's responsibility to implement any synchronization
required.
In practice, on most systems with a GPU this kept a directly binding to
the framebuffer, which made it work with the previous code. However,
on software rasterization setups using llvmpipe, a blit was done inside
the call to glXBindTexImageEXT. This was the cause of a notoriously
ignored bug where the captured image would "freeze" until the source
was reconfigured.
If you don't have a xdg-desktop-portal backend then pipewire wont init,
however on exit we unconditionally deinit which can crash in pipewire
which does not handle this gracefully.
PipeWire server versions older than 0.3.24 can be incompatible with
clients build against a newer library version with respect to DMA-BUF
sharing. So we want to fallback to SHM transfer. This commit adds
checks for older versions.
These are classified as follows:
* PipeWire components older than 0.3.24: Restrict to SHM only
* PipeWire components with version 0.3.24 and newer: Announce DMA-BUF
support via `SPA_PARAM_BUFFERS_dataType`
With the version 4 of the screencast portal, it is now possible
to request and use restore tokens [1] so that apps can restore a
previously configured screencast session without user interaction.
Add the corresponding code to linux-capture's PipeWire source.
Store the restore token in the source data, since each restore
token corresponds to an OBS source, and use it as soon as we try
to create a new session. Implement the obs_source_info.save vfunc,
and save the restore token when it's received by the Start()
response using obs_source_save().
[1] https://github.com/flatpak/xdg-desktop-portal/pull/638
We require libdrm for its header so add the cmake module and header path
to the build. We don't need to link libdrm though so we dont add it to
libraries.
DRM_FORMAT_MOD_INVALID is a token for implicit modifier. When importing
a DMA-BUF with implicit modifier we should call
gs_texture_create_from_dmabuf() without modifier.
g_variant_lookup() obligatorily receives the type of the variant to
lookup. This function is used when retrieving the session handle
from the portal's response, and the variant type passed is "s" (a
string).
However, xdg-desktop-portal had a bug: the documentation explicitly
mentions that the session handle is an object path (of variant type
"o"), but it passed a string (of variant type "s"). This mismatch
was fixed in the xdg-desktop-portal release 1.10 [1], but that broke
the PipeWire capture code, which was passing specifically the "s"
value to the variant lookup.
Fix this by not checking the variant type at all. Object paths ("o")
are simply strings with a few extra checks, and we don't actually need
to perform these checks.
This change probably broke other apps, and that makes me extremely sad :(
[1] https://github.com/flatpak/xdg-desktop-portal/pull/609
The gs_texture_create_from_dmabuf function is able to create textures
from multiplanar DMA-BUF data. However, the only in-tree consumer of
this function - the PipeWire capture - does not use that.
Make PipeWire create textures from multiplanar buffers.
Unlike Xcomposite, the XSHM plugin does not use GLX code, and thus
can be used on when EGL renderer is used. It still is X11-specific
though, and shouldn't be used on Wayland.
Rework the obs_module_load() function of linux-capture to use a
switch statement, and load XSHM both on EGL/X11 and GLX/X11.
Fixes https://github.com/obsproject/obs-studio/issues/5122
The gs_draw_sprite_subregion() function is used when a cropping
rectangle is received from PipeWire. It is usually used by
compositors to implement window screencast - where a large and
mostly empty frame is sent, the window contents are only a small
part of it, and the crop rectangle tells us that.
Recently the wlroots implementation of portals started to use it
to implement cropping, and it exposed a bug in the PipeWire code
in OBS Studio. The gs_draw_sprite_subregion() function takes a pair
of integers representing position (x, y) and a pair of integers
representing size (width, height). The PipeWire code, however,
passes a second pair of positions (x2, y2) instead of sizes, and
it causes overrendering the crop area.
This bug wasn't hit yet because both GNOME and KDE implementations
always send (0, 0) as position, which practically never trigger
this condition.
Pass only width and height to gs_draw_sprite_subregion(), instead
of adding x and y to them.
Fixes https://github.com/obsproject/obs-studio/issues/4982
Intead of creating one pair of GDBusConnection + GDBusProxy objects
for each PipeWire capture, be it window or desktop, use the global
ones managed by portal.c.
Even if g_bus_get_sync() ends up reusing the same object under the
hood, it's still a net gain, since it has to perform some thread
synchronization routines that aren't necessary here. Creating the
proxy object was a worse offender, because despite being asynchronous,
it would still incur in a few socket messages + a cancellable fd +
thread synchronization.
Reuse these objects from portal.c. The biggest code change here is
that create_proxy() and on_proxy_created_cb() were merged into
init_obs_pipewire().
Right now we just assume that every compositor and portal implementation
exposes both window and monitor captures, but that's not true, and in fact
the Desktop portal provides a simple mechanism to check which source types
are available: a D-Bus property called "AvailableSourceTypes".
Read this D-Bus property, and use it to conditionally register the desktop
and the window captures.
Related: https://github.com/obsproject/obs-studio/issues/4815
The cursor bitmap is centered on the hotspot, so not accounting
for it means PipeWire captures were positioning the cursor sprite
slightly off.
Properly account for the hotspot by subtracting it from the cursor
position.
Related: https://github.com/obsproject/obs-studio/issues/4766