When an external display is disconnected with a fullscreen projector
attached to it, Qt will trigger a resize of the window twice, which
makes the renderer queue 2 resize event blocks.
At the time when those blocks are run, Qt's window destructor will have
reset all pointers, and the block directly accesses pointers within
structures identified by pointers, which are invalid by that point.
This commit makes a block return early if the associated window has
been destroyed already and also explicitly checks for valid pointers
after.
Previously we would actually initialize a texture memory that would then
also have to be deleted when we bound the EGLImage to the texture during
dmabuf import.
Instead simply do not create the dummy texture memory. One odd thing is
that we must still query the texture to ensure its initialized or
binding the EGLImage will not work. So we leave the TEXTURE_MAX_LEVEL
check.
This makes screencapture up to 100x faster on discrete intel cards and
likely has some performance benefit for amd/integrated cards. Without
this dmabufs are actually slower than shared memory for these intel
cards.
Currently, the X11 display may be leaked when the X11/EGL
platform is destroyed. Fix that by calling XCloseDisplay()
to free it.
Fixes: 2fd8a6df55 ("libobs-opengl: Introduce the X11/EGL winsys")
The platform display is not owned by libobs, it should not
be closed. Doing so results in heap use-after-frees when
Qt components try to use it while trying to show
a message box about the failure:
info: Initializing OpenGL...
error: Failed to initialize EGL: EGL_BAD_ACCESS
error: Failed to create context!
error: device_create (GL) failed
error: Failed to initialize video. Your GPU may not be supported, or your graphics drivers may need to be updated.
=================================================================
==2320345==ERROR: AddressSanitizer: heap-use-after-free on address 0x621000018668 at pc 0x7fcb75e20d6e bp 0x7ffe88d0e910 sp 0x7ffe88d0e900
READ of size 8 at 0x621000018668 thread T0
0 0x7fcb75e20d6d in XInternAtom /.../libx11/src/IntAtom.c:175
1 0x7fcb6bf5edfd in Kvantum::ThemeConfig::getCompositeSpec()
2 0x7fcb6bf0eb19 in Kvantum::Style::setSurfaceFormat(QWidget*) const
3 0x7fcb6bf11bae in Kvantum::Style::styleHint(QStyle::StyleHint, QStyleOption const*, QWidget const*, QStyleHintReturn*) const
4 0x5585cbce70b8 in OBSIgnoreWheelProxyStyle::styleHint(QStyle::StyleHint, QStyleOption const*, QWidget const*, QStyleHintReturn*) const /.../obs-studio/UI/obs-proxy-style.cpp:88
5 0x7fcb85826515 (/usr/lib/libQt6Widgets.so.6+0x226515)
6 0x7fcb859dbf1d (/usr/lib/libQt6Widgets.so.6+0x3dbf1d)
7 0x7fcb859dc5f0 in QMessageBox::QMessageBox(...)
8 0x7fcb859dc6b1 (/usr/lib/libQt6Widgets.so.6+0x3dc6b1)
9 0x5585cbd2fb31 in OBSErrorBoxva /.../obs-studio/UI/qt-wrappers.cpp:48
10 0x5585cbd2fd34 in OBSErrorBox(QWidget*, char const*, ...) /.../obs-studio/UI/qt-wrappers.cpp:55
11 0x5585cbcc3f36 in run_program /.../obs-studio/UI/obs-app.cpp:2475
12 0x5585cbcc52b4 in main /.../obs-studio/UI/obs-app.cpp:3358
13 0x7fcb82e3c28f (/usr/lib/libc.so.6+0x2328f)
14 0x7fcb82e3c349 in __libc_start_main
15 0x5585cbbd2f54 in _start
Fixes: 137966e01f ("libobs-opengl: Try to use the platform display if available")
Previously we passed the wrong display and formats/modifiers could not
be queried. This prevented pipewire sources from negotiating texture
sharing on x11.
Mac was already dropping a most of these when leaving contexts,
this patch brings the same drops to linux and also drops vertex/index
buffers that were noticed as leaking across contexts and resulting in
invalid bindings by later draws. Especially with the new spacing labels.
When using EGL the mesa+nvidia stack are unable to offload 32bit
framebuffers despite having this capability on GLX. In practice the X11
server does not support alpha windows so we dont need the alpha
component in our framebuffer. We previously had alpha specified in our
framebuffer since we do alpha texturing but testing shows this isnt
required for mesa/intel or nvidia drivers and we must pick a 24bit
config for users to enable render offloading for mixed gpu systems.
fixes#6984
Without this we get somewhat misleading errors from later in the
swapchain creation when this fails. This is currently happening for
users attempting to use multi-gpu with prime offloading on nvidia.
Some users stream projectors, so don't let them tear. Use the waitable
object to check the flip queue, and only flip if there's space.
Metal and Vulkan can probably perform similar flip throttling once OBS
starts using them.
Syphon relies on global IOSurfaces which are not officially supported
by macOS anymore. While the core functionality is still available,
`IOSurfaceGetPixelFormat` will not return a valid pixel format.
This function is expected to fail fairly often as it is the tool for
checking if windows are mapped and have a valid pixmap in the linux
capture plugin. So reduce this error to a debug message to avoid
spamming release builds.
This replaces direct OpenGL calls to error handling helpers. Previously
this would cause errors to be misattributed to the next OpenGL functions
called.
Fixes DMA-BUF importing returning a texture on failure on KDE+NVIDIA.
This reverts commit 76f7a0c1c0.
Unfortunately, the performance issue is still present with PBOs even on
Monterey. During the 27.2 beta, macOS users even on Monterey have been
reporting a performance regression, and when the profiler data for those
users was looked at, major performance loss was noted in the
stage_output_texture function. This commit was the only probable cause.
The usual pattern of function signature is "array / n_elements",
but query_dmabuf_formats() does not follow it. Apply this order
to query_dmabuf_formats().
When sharing DMA-BUFs it is required the announce the underlying
hardware capabilities via supported modifiers.
Add new device_query_dmabuf_capabilities vfunc to gs_exports and connect it
to the egl implementation stubs in the supported render platforms. Add a new
public method gs_query_dmabuf_capabilities() that calls the vfunc above.
Add new device_query_dmabuf_modifiers vfunc to gs_exports and connect it
to the egl implementation in the supported render platforms. Add a new
public method gs_query_dmabuf_modifiers() that calls the vfunc above.
This commit ensures that we set the appropriate draw buffer when making
a context current. Mesa drivers enforce opengl ES semantics where the
targets passed to eglMakeCurrent are bound, but nvidia instead ignores
these parameters after the 1st eglMakeCurrent. In obs we make current
with EGL_NO_SURFACE so our draw targets end up as EGL_NONE on nvidia
and previews fail to render.
This also allows us to fail back ignoring NATIVE_RENDERABLE
requirements. Nvidia driver does not report support for this attribute
on any context and after resolving the draw target issues previews
render correctly on nvidia and intel drivers.
Previously glReadPixels was used to stage surfaces because Mac OS X at
that time supported some hardwares that didn't implement glGetTexImage.
However, OBS Studio now requires OpenGL 3.3 so that glGetTexImage on
macOS should work the same as on Linux.
The code using glReadPixels was introduced at 30af7dc. The minimum
requirements of the original OBS Studio for OSX was 10.8, which supports
hardwares with OpenGL 1.4. However, the function glGetTexImage requires
OpenGL >= 2.0.
This adds the drmbuf format as a parameter separate from the obs texture
format that will be used. drmbuf's may have a variety of formats that we
need to pass correctly to get a usable texture which may correspond to
multi-platform texture formats.
Implement device_texture_create_from_dmabuf for EGL/X11 and EGL/Wayland.
The code is shared between them, in a new gl-egl-common.c file.
This is currently limited to a few common RGB(A) formats for now, which
seems to cover most use cases.
DMA-BUF is a widespread Linux buffer sharing mechanism. It is what's
commonly used zero-copy screen sharing by Wayland compositors.
Add a new 'device_texture_create_from_dmabuf' vfunc to gs_exports,
and stub implementations to libobs-opengl. Add a new public method
gs_texture_create_from_dmabuf() that calls this vfunc.