Skip to content
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
2 changes: 2 additions & 0 deletions src/platform/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,8 @@ namespace platf {
*/
std::string get_host_name();

std::string find_render_node_with_display();

/**
* @brief Gets the supported gamepads for this platform backend.
* @details This may be called prior to `platf::input()`!
Expand Down
55 changes: 55 additions & 0 deletions src/platform/linux/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@
#include <fcntl.h>
#include <unistd.h>

#ifdef SUNSHINE_BUILD_DRM
#include <dirent.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#endif

// local includes
#include "graphics.h"
#include "misc.h"
Expand Down Expand Up @@ -1163,4 +1169,53 @@ namespace platf {
std::unique_ptr<high_precision_timer> create_high_precision_timer() {
return std::make_unique<linux_high_precision_timer>();
}

std::string find_render_node_with_display() {
#ifdef SUNSHINE_BUILD_DRM
auto *dir = opendir("/dev/dri");
if (!dir) {
return {};
}

std::string result;
while (auto *entry = readdir(dir)) {
if (strncmp(entry->d_name, "card", 4) != 0 || !isdigit(entry->d_name[4])) {
continue;
}

std::string path = std::string("/dev/dri/") + entry->d_name;
int fd = open(path.c_str(), O_RDWR);
if (fd < 0) {
continue;
}

auto *res = drmModeGetResources(fd);
if (res) {
for (int i = 0; i < res->count_connectors && result.empty(); i++) {
auto *conn = drmModeGetConnector(fd, res->connectors[i]);
if (conn) {
if (conn->connection == DRM_MODE_CONNECTED) {
char *render = drmGetRenderDeviceNameFromFd(fd);
if (render) {
result = render;
free(render);
}
}
drmModeFreeConnector(conn);
}
}
drmModeFreeResources(res);
}
close(fd);
if (!result.empty()) {
break;
}
}
closedir(dir);
return result;
#else
return {};
#endif
}

} // namespace platf
4 changes: 3 additions & 1 deletion src/platform/linux/vulkan_encode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ namespace vk {

static int create_vulkan_hwdevice(AVBufferRef **hw_device_buf) {
// Resolve render device path to Vulkan device index
if (auto render_path = config::video.adapter_name.empty() ? "/dev/dri/renderD128" : config::video.adapter_name; render_path[0] == '/') {
auto detected = platf::find_render_node_with_display();
auto fallback = detected.empty() ? std::string("/dev/dri/renderD128") : detected;
if (auto render_path = config::video.adapter_name.empty() ? fallback : config::video.adapter_name; render_path[0] == '/') {
if (auto idx = find_vulkan_index_for_render_node(render_path.c_str()); !idx.empty() && av_hwdevice_ctx_create(hw_device_buf, AV_HWDEVICE_TYPE_VULKAN, idx.c_str(), nullptr, 0) >= 0) {
return 0;
}
Expand Down
4 changes: 4 additions & 0 deletions src/platform/macos/misc.mm
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,10 @@ operator bool() override {
std::unique_ptr<high_precision_timer> create_high_precision_timer() {
return std::make_unique<macos_high_precision_timer>();
}

std::string find_render_node_with_display() {
return {};
}
} // namespace platf

namespace dyn {
Expand Down
4 changes: 4 additions & 0 deletions src/platform/windows/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1791,4 +1791,8 @@ namespace platf {

return true;
}

std::string find_render_node_with_display() {
return {};
}
} // namespace platf
6 changes: 4 additions & 2 deletions src/video.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3019,8 +3019,10 @@ namespace video {
return hw_device_buf;
}

// Try render device path first (like VAAPI does), then fallback to device indices
auto render_device = config::video.adapter_name.empty() ? "/dev/dri/renderD128" : config::video.adapter_name.c_str();
// Try render device path first, auto-detecting the GPU with a connected display
auto detected = platf::find_render_node_with_display();
auto fallback = detected.empty() ? std::string("/dev/dri/renderD128") : detected;
auto render_device = config::video.adapter_name.empty() ? fallback.c_str() : config::video.adapter_name.c_str();

auto status = av_hwdevice_ctx_create(&hw_device_buf, AV_HWDEVICE_TYPE_VULKAN, render_device, nullptr, 0);
if (status >= 0) {
Expand Down
Loading