From 3e8bbabc3ff101317ead1c8ca05992db644bdc92 Mon Sep 17 00:00:00 2001 From: tytan652 Date: Thu, 29 Aug 2024 12:31:59 +0200 Subject: [PATCH 1/3] Add hardware accel support under Linux --- browser-client.cpp | 39 +++++++++++++++++++++++++--- cef-headers.hpp | 4 +++ cmake/os-linux.cmake | 6 +++++ drm-format.cpp | 59 ++++++++++++++++++++++++++++++++++++++++++ drm-format.hpp | 21 +++++++++++++++ obs-browser-plugin.cpp | 8 ++++++ obs-browser-source.cpp | 8 ++++++ 7 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 drm-format.cpp create mode 100644 drm-format.hpp diff --git a/browser-client.cpp b/browser-client.cpp index 5a067dec5..16c66960e 100644 --- a/browser-client.cpp +++ b/browser-client.cpp @@ -30,6 +30,10 @@ #include #endif +#if !defined(_WIN32) && !defined(__APPLE__) +#include "drm-format.hpp" +#endif + inline bool BrowserClient::valid() const { return !!bs && !bs->destroying; @@ -352,6 +356,31 @@ void BrowserClient::OnAcceleratedPaint(CefRefPtr, PaintElementType t return; } +#if !defined(_WIN32) && !defined(__APPLE__) + if (info.plane_count == 0) + return; + + struct obs_cef_video_format format = obs_cef_format_from_cef_type(info.format); + + if (format.gs_format == GS_UNKNOWN) + return; + + uint32_t *strides = (uint32_t *)alloca(info.plane_count * sizeof(uint32_t)); + uint32_t *offsets = (uint32_t *)alloca(info.plane_count * sizeof(uint32_t)); + uint64_t *modifiers = (uint64_t *)alloca(info.plane_count * sizeof(uint64_t)); + int *fds = (int *)alloca(info.plane_count * sizeof(int)); + + for (size_t i = 0; i < kAcceleratedPaintMaxPlanes; i++) { + auto *plane = &info.planes[i]; + + strides[i] = plane->stride; + offsets[i] = plane->offset; + fds[i] = plane->fd; + + modifiers[i] = info.modifier; + } +#endif + #if !defined(_WIN32) && CHROME_VERSION_BUILD < 6367 if (shared_handle == bs->last_handle) return; @@ -381,17 +410,21 @@ void BrowserClient::OnAcceleratedPaint(CefRefPtr, PaintElementType t //if (bs->texture) // gs_texture_acquire_sync(bs->texture, 1, INFINITE); -#else +#elif defined(__WIN32) bs->texture = gs_texture_open_shared((uint32_t)(uintptr_t)shared_handle); +#else + bs->texture = gs_texture_create_from_dmabuf(bs->width, bs->height, format.drm_format, format.gs_format, + info.plane_count, fds, strides, offsets, + info.modifier != DRM_FORMAT_MOD_INVALID ? modifiers : NULL); #endif UpdateExtraTexture(); obs_leave_graphics(); #if defined(__APPLE__) && CHROME_VERSION_BUILD >= 6367 bs->last_handle = info.shared_texture_io_surface; -#elif CHROME_VERSION_BUILD >= 6367 +#elif defined(_WIN32) && CHROME_VERSION_BUILD >= 6367 bs->last_handle = info.shared_texture_handle; -#else +#elif defined(__APPLE__) && defined(_WIN32) bs->last_handle = shared_handle; #endif } diff --git a/cef-headers.hpp b/cef-headers.hpp index 8cc8b667d..f9c208b4a 100644 --- a/cef-headers.hpp +++ b/cef-headers.hpp @@ -47,6 +47,10 @@ #define ENABLE_WASHIDDEN 0 #endif +#if !defined(_WIN32) && !defined(__APPLE__) && CHROME_VERSION_BUILD > 6337 +#define ENABLE_BROWSER_SHARED_TEXTURE +#endif + #define SendBrowserProcessMessage(browser, pid, msg) \ CefRefPtr mainFrame = browser->GetMainFrame(); \ if (mainFrame) { \ diff --git a/cmake/os-linux.cmake b/cmake/os-linux.cmake index d80f9d4ad..e4da2fe95 100644 --- a/cmake/os-linux.cmake +++ b/cmake/os-linux.cmake @@ -1,10 +1,16 @@ find_package(X11 REQUIRED) +find_package(Libdrm REQUIRED) +get_target_property(libdrm_include_directories Libdrm::Libdrm INTERFACE_INCLUDE_DIRECTORIES) target_compile_definitions(obs-browser PRIVATE ENABLE_BROWSER_QT_LOOP) +target_include_directories(obs-browser PRIVATE ${libdrm_include_directories}) + target_link_libraries(obs-browser PRIVATE CEF::Wrapper CEF::Library X11::X11) set_target_properties(obs-browser PROPERTIES BUILD_RPATH "$ORIGIN/" INSTALL_RPATH "$ORIGIN/") +target_sources(obs-browser PRIVATE drm-format.cpp drm-format.hpp) + add_executable(browser-helper) add_executable(OBS::browser-helper ALIAS browser-helper) diff --git a/drm-format.cpp b/drm-format.cpp new file mode 100644 index 000000000..30cbe7590 --- /dev/null +++ b/drm-format.cpp @@ -0,0 +1,59 @@ +#include "drm-format.hpp" + +#include + +#ifdef ENABLE_BROWSER_SHARED_TEXTURE + +static const struct obs_cef_video_format supported_formats[] = { + { + CEF_COLOR_TYPE_RGBA_8888, + DRM_FORMAT_ABGR8888, + GS_RGBA_UNORM, + "RGBA_8888", + }, + { + CEF_COLOR_TYPE_BGRA_8888, + DRM_FORMAT_ARGB8888, + GS_BGRA_UNORM, + "BGRA_8888", + }, +}; + +#define N_SUPPORTED_FORMATS (sizeof(supported_formats) / sizeof(supported_formats[0])) + +bool obs_cef_all_drm_formats_supported() +{ + size_t n_supported = 0; + size_t n_formats = 0; + enum gs_dmabuf_flags dmabuf_flags; + BPtr drm_formats; + + if (!gs_query_dmabuf_capabilities(&dmabuf_flags, &drm_formats, &n_formats)) + return false; + + for (size_t i = 0; i < n_formats; i++) { + for (size_t j = 0; j < N_SUPPORTED_FORMATS; j++) { + if (drm_formats[i] != supported_formats[j].drm_format) + continue; + + blog(LOG_DEBUG, "[obs-browser] CEF color type %s supported ", supported_formats[j].pretty_name); + n_supported++; + } + } + + return n_supported == N_SUPPORTED_FORMATS; +} + +struct obs_cef_video_format obs_cef_format_from_cef_type(cef_color_type_t cef_type) +{ + for (size_t i = 0; i < N_SUPPORTED_FORMATS; i++) { + if (supported_formats[i].cef_type == cef_type) + return supported_formats[i]; + } + + blog(LOG_ERROR, "[obs-browser]: Unsupported CEF color format (%d)", cef_type); + + return {cef_type, DRM_FORMAT_INVALID, GS_UNKNOWN, NULL}; +} + +#endif diff --git a/drm-format.hpp b/drm-format.hpp new file mode 100644 index 000000000..352be1020 --- /dev/null +++ b/drm-format.hpp @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +#include "cef-headers.hpp" + +#ifdef ENABLE_BROWSER_SHARED_TEXTURE + +struct obs_cef_video_format { + cef_color_type_t cef_type; + uint32_t drm_format; + enum gs_color_format gs_format; + const char *pretty_name; +}; + +bool obs_cef_all_drm_formats_supported(); + +struct obs_cef_video_format obs_cef_format_from_cef_type(cef_color_type_t cef_type); + +#endif diff --git a/obs-browser-plugin.cpp b/obs-browser-plugin.cpp index af3195e82..55482da6b 100644 --- a/obs-browser-plugin.cpp +++ b/obs-browser-plugin.cpp @@ -55,6 +55,10 @@ #include #endif +#if !defined(_WIN32) && !defined(__APPLE__) +#include "drm-format.hpp" +#endif + OBS_DECLARE_MODULE() OBS_MODULE_USE_DEFAULT_LOCALE("obs-browser", "en-US") MODULE_EXPORT const char *obs_module_description(void) @@ -350,7 +354,11 @@ static void BrowserInit(void) #ifdef ENABLE_BROWSER_SHARED_TEXTURE if (hwaccel) { obs_enter_graphics(); +#if defined(__APPLE__) || defined(_WIN32) hwaccel = tex_sharing_avail = gs_shared_texture_available(); +#else + hwaccel = tex_sharing_avail = obs_cef_all_drm_formats_supported(); +#endif obs_leave_graphics(); } #endif diff --git a/obs-browser-source.cpp b/obs-browser-source.cpp index f4a1e4d96..87dcc9bb6 100644 --- a/obs-browser-source.cpp +++ b/obs-browser-source.cpp @@ -37,6 +37,10 @@ #include #endif +#if !defined(_WIN32) && !defined(__APPLE__) +#include "drm-format.hpp" +#endif + using namespace std; extern bool QueueCEFTask(std::function task); @@ -181,7 +185,11 @@ bool BrowserSource::CreateBrowser() #ifdef ENABLE_BROWSER_SHARED_TEXTURE if (hwaccel) { obs_enter_graphics(); +#if defined(__APPLE__) || defined(_WIN32) tex_sharing_avail = gs_shared_texture_available(); +#else + tex_sharing_avail = obs_cef_all_drm_formats_supported(); +#endif obs_leave_graphics(); } #else From 7c2b9f298584cb9b0f55c1b219187eb8246ae9ee Mon Sep 17 00:00:00 2001 From: tytan652 Date: Wed, 11 Sep 2024 13:40:30 +0200 Subject: [PATCH 2/3] Add workaround for hardware accel under X11 --- browser-client.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/browser-client.cpp b/browser-client.cpp index 16c66960e..b0979d76a 100644 --- a/browser-client.cpp +++ b/browser-client.cpp @@ -31,6 +31,8 @@ #endif #if !defined(_WIN32) && !defined(__APPLE__) +#include + #include "drm-format.hpp" #endif @@ -361,6 +363,7 @@ void BrowserClient::OnAcceleratedPaint(CefRefPtr, PaintElementType t return; struct obs_cef_video_format format = obs_cef_format_from_cef_type(info.format); + uint64_t modifier = info.modifier; if (format.gs_format == GS_UNKNOWN) return; @@ -370,6 +373,11 @@ void BrowserClient::OnAcceleratedPaint(CefRefPtr, PaintElementType t uint64_t *modifiers = (uint64_t *)alloca(info.plane_count * sizeof(uint64_t)); int *fds = (int *)alloca(info.plane_count * sizeof(int)); + /* NOTE: This a workaround under X11 where the modifier is always + invalid where it can mean "no modifier" in Chromium's code. */ + if (obs_get_nix_platform() == OBS_NIX_PLATFORM_X11_EGL && modifier == DRM_FORMAT_MOD_INVALID) + modifier = DRM_FORMAT_MOD_LINEAR; + for (size_t i = 0; i < kAcceleratedPaintMaxPlanes; i++) { auto *plane = &info.planes[i]; @@ -377,7 +385,7 @@ void BrowserClient::OnAcceleratedPaint(CefRefPtr, PaintElementType t offsets[i] = plane->offset; fds[i] = plane->fd; - modifiers[i] = info.modifier; + modifiers[i] = modifier; } #endif @@ -415,7 +423,7 @@ void BrowserClient::OnAcceleratedPaint(CefRefPtr, PaintElementType t #else bs->texture = gs_texture_create_from_dmabuf(bs->width, bs->height, format.drm_format, format.gs_format, info.plane_count, fds, strides, offsets, - info.modifier != DRM_FORMAT_MOD_INVALID ? modifiers : NULL); + modifier != DRM_FORMAT_MOD_INVALID ? modifiers : NULL); #endif UpdateExtraTexture(); obs_leave_graphics(); From b957a0ad6b5e19a5cbf45b46348862dbc807bffd Mon Sep 17 00:00:00 2001 From: tytan652 Date: Sun, 27 Oct 2024 17:34:03 +0100 Subject: [PATCH 3/3] Blacklist NVIDIA driver for hardware accel under Linux Testers have reported that CEF and NVIDIA driver does not seem to work well together. --- cmake/os-linux.cmake | 2 +- obs-browser-plugin.cpp | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/cmake/os-linux.cmake b/cmake/os-linux.cmake index e4da2fe95..6fd5b776f 100644 --- a/cmake/os-linux.cmake +++ b/cmake/os-linux.cmake @@ -6,7 +6,7 @@ target_compile_definitions(obs-browser PRIVATE ENABLE_BROWSER_QT_LOOP) target_include_directories(obs-browser PRIVATE ${libdrm_include_directories}) -target_link_libraries(obs-browser PRIVATE CEF::Wrapper CEF::Library X11::X11) +target_link_libraries(obs-browser PRIVATE CEF::Wrapper CEF::Library X11::X11 OBS::glad) set_target_properties(obs-browser PROPERTIES BUILD_RPATH "$ORIGIN/" INSTALL_RPATH "$ORIGIN/") target_sources(obs-browser PRIVATE drm-format.cpp drm-format.hpp) diff --git a/obs-browser-plugin.cpp b/obs-browser-plugin.cpp index 55482da6b..e662c41e8 100644 --- a/obs-browser-plugin.cpp +++ b/obs-browser-plugin.cpp @@ -56,6 +56,7 @@ #endif #if !defined(_WIN32) && !defined(__APPLE__) +#include #include "drm-format.hpp" #endif @@ -700,6 +701,28 @@ static void check_hwaccel_support(void) } } } +#elif __linux__ +static void check_hwaccel_support(void) +{ + /* NOTE: GL_VERSION returns a string that contains the driver vendor */ + const char *glVersion = NULL; + + obs_enter_graphics(); + gladLoadGL(); + glVersion = (const char *)glGetString(GL_VERSION); + obs_leave_graphics(); + + if (strstr(glVersion, "NVIDIA") != NULL) { + hwaccel = false; + blog(LOG_INFO, "[obs-browser]: " + "Blacklisted driver " + "detected, " + "disabling browser " + "source hardware " + "acceleration."); + } + return; +} #else static void check_hwaccel_support(void) {