diff --git a/browser-client.cpp b/browser-client.cpp index 951b4ac61..24c2f0f8f 100644 --- a/browser-client.cpp +++ b/browser-client.cpp @@ -30,6 +30,12 @@ #include #endif +#if !defined(_WIN32) && !defined(__APPLE__) +#include + +#include "drm-format.hpp" +#endif + inline bool BrowserClient::valid() const { return !!bs && !bs->destroying; @@ -360,6 +366,37 @@ 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); + uint64_t modifier = info.modifier; + + 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)); + + /* 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]; + + strides[i] = plane->stride; + offsets[i] = plane->offset; + fds[i] = plane->fd; + + modifiers[i] = modifier; + } +#endif + #if !defined(_WIN32) && CHROME_VERSION_BUILD < 6367 if (shared_handle == bs->last_handle) return; @@ -389,17 +426,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, + 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 7c95a9efe..f61933517 100644 --- a/cmake/os-linux.cmake +++ b/cmake/os-linux.cmake @@ -1,8 +1,14 @@ find_package(X11 REQUIRED) +find_package(Libdrm REQUIRED) +get_target_property(libdrm_include_directories Libdrm::Libdrm INTERFACE_INCLUDE_DIRECTORIES) -target_link_libraries(obs-browser PRIVATE CEF::Wrapper CEF::Library X11::X11) +target_include_directories(obs-browser PRIVATE ${libdrm_include_directories}) + +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) + 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..18565663f --- /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", + }, +}; + +constexpr size_t N_SUPPORTED_FORMATS = sizeof(supported_formats) / sizeof(supported_formats[0]); + +bool obs_cef_all_drm_formats_supported(void) +{ + 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..37037e78d --- /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(void); + +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 84a6d4034..a31cd1ab9 100644 --- a/obs-browser-plugin.cpp +++ b/obs-browser-plugin.cpp @@ -55,6 +55,11 @@ #include #endif +#if !defined(_WIN32) && !defined(__APPLE__) +#include +#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 +355,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 @@ -697,6 +706,24 @@ 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) { 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