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

Add hardware accel support under Linux #453

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 44 additions & 3 deletions browser-client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
#include <IOSurface/IOSurface.h>
#endif

#if !defined(_WIN32) && !defined(__APPLE__)
#include <obs-nix-platform.h>

#include "drm-format.hpp"
#endif

inline bool BrowserClient::valid() const
{
return !!bs && !bs->destroying;
Expand Down Expand Up @@ -352,6 +358,37 @@ void BrowserClient::OnAcceleratedPaint(CefRefPtr<CefBrowser>, 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;
Expand Down Expand Up @@ -381,17 +418,21 @@ void BrowserClient::OnAcceleratedPaint(CefRefPtr<CefBrowser>, 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
}
Expand Down
4 changes: 4 additions & 0 deletions cef-headers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<CefFrame> mainFrame = browser->GetMainFrame(); \
if (mainFrame) { \
Expand Down
8 changes: 7 additions & 1 deletion cmake/os-linux.cmake
Original file line number Diff line number Diff line change
@@ -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_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)

Expand Down
59 changes: 59 additions & 0 deletions drm-format.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
#include "drm-format.hpp"

#include <util/util.hpp>

#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<uint32_t> 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
21 changes: 21 additions & 0 deletions drm-format.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include <graphics/graphics.h>
#include <libdrm/drm_fourcc.h>

#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
31 changes: 31 additions & 0 deletions obs-browser-plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@
#include <QThread>
#endif

#if !defined(_WIN32) && !defined(__APPLE__)
#include <glad/glad.h>
#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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -692,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)
{
Expand Down
8 changes: 8 additions & 0 deletions obs-browser-source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
#include <QThread>
#endif

#if !defined(_WIN32) && !defined(__APPLE__)
#include "drm-format.hpp"
#endif

using namespace std;

extern bool QueueCEFTask(std::function<void()> task);
Expand Down Expand Up @@ -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
Expand Down