[feat] add OpenGL NV12 underlay rendering for Slint on Linux

This commit is contained in:
dijunkun
2026-08-25 10:26:05 +08:00
parent 3e63675787
commit 21eec76008
11 changed files with 315 additions and 188 deletions
+9 -9
View File
@@ -11,8 +11,8 @@
#include "display_stream_id.h"
#include "localization.h"
#include "platform.h"
#if defined(_WIN32)
#include "platform/windows_opengl_video_renderer.h"
#if defined(_WIN32) || defined(__linux__)
#include "platform/opengl_video_renderer.h"
#endif
#ifdef __APPLE__
#include "platform/metal_video_renderer.h"
@@ -229,7 +229,7 @@ void GuiRuntime::CloseRemoteSession(std::shared_ptr<RemoteSession> props) {
frame_snapshot = props->front_frame_;
video_width = props->video_width_;
video_height = props->video_height_;
#if defined(__APPLE__) || defined(_WIN32)
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
if ((!frame_snapshot || frame_snapshot->empty()) &&
props->thumbnail_frame_ && !props->thumbnail_frame_->empty()) {
frame_snapshot = props->thumbnail_frame_;
@@ -238,11 +238,11 @@ void GuiRuntime::CloseRemoteSession(std::shared_ptr<RemoteSession> props) {
}
#endif
}
#if defined(__APPLE__) || defined(_WIN32)
#if defined(_WIN32)
auto* native_renderer = windows_opengl_video_renderer_.get();
#else
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
#if defined(__APPLE__)
auto* native_renderer = mac_metal_video_renderer_.get();
#else
auto* native_renderer = opengl_video_renderer_.get();
#endif
if ((!frame_snapshot || frame_snapshot->empty()) && native_renderer) {
auto native_snapshot = std::make_shared<std::vector<unsigned char>>();
@@ -276,7 +276,7 @@ void GuiRuntime::CloseRemoteSession(std::shared_ptr<RemoteSession> props) {
}
}
#if defined(__APPLE__) || defined(_WIN32)
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
if (native_renderer) {
native_renderer->DiscardStream(props->remote_id_);
video_frame_dirty_.store(true, std::memory_order_release);
@@ -343,7 +343,7 @@ void GuiRuntime::ResetRemoteSessionResources(
std::lock_guard<std::mutex> lock(props->video_frame_mutex_);
props->front_frame_.reset();
props->back_frame_.reset();
#if defined(__APPLE__) || defined(_WIN32)
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
props->thumbnail_frame_.reset();
props->thumbnail_width_ = 0;
props->thumbnail_height_ = 0;
+2 -2
View File
@@ -12,8 +12,8 @@
#include "display_stream_id.h"
#include "localization.h"
#if defined(_WIN32)
#include "platform/windows_opengl_video_renderer.h"
#if defined(_WIN32) || defined(__linux__)
#include "platform/opengl_video_renderer.h"
#endif
#ifdef __APPLE__
#include "platform/metal_video_renderer.h"
+4 -4
View File
@@ -15,8 +15,8 @@
namespace crossdesk {
#if defined(_WIN32)
class WindowsOpenGlVideoRenderer;
#if defined(_WIN32) || defined(__linux__)
class OpenGlVideoRenderer;
#endif
#ifdef __APPLE__
class MacMetalVideoRenderer;
@@ -90,8 +90,8 @@ class GuiRuntime : protected gui_detail::GuiState {
KeyboardController keyboard_;
PeerEventHandler peer_events_;
std::atomic<bool> video_frame_dirty_{false};
#if defined(_WIN32)
std::unique_ptr<WindowsOpenGlVideoRenderer> windows_opengl_video_renderer_;
#if defined(_WIN32) || defined(__linux__)
std::unique_ptr<OpenGlVideoRenderer> opengl_video_renderer_;
#endif
#ifdef __APPLE__
std::unique_ptr<MacMetalVideoRenderer> mac_metal_video_renderer_;
+11 -12
View File
@@ -16,8 +16,8 @@
#include "file_transfer.h"
#include "localization.h"
#include "platform.h"
#if defined(_WIN32)
#include "platform/windows_opengl_video_renderer.h"
#if defined(_WIN32) || defined(__linux__)
#include "platform/opengl_video_renderer.h"
#endif
#ifdef __APPLE__
#include "platform/metal_video_renderer.h"
@@ -319,7 +319,7 @@ void PeerEventHandler::OnConnectionStatus(ConnectionStatus status,
props->enable_mouse_control_ = false;
runtime->ResetRemoteServiceStatus(*props);
#if defined(__APPLE__) || defined(_WIN32)
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
std::shared_ptr<std::vector<unsigned char>> native_snapshot;
int native_snapshot_width = 0;
int native_snapshot_height = 0;
@@ -330,11 +330,10 @@ void PeerEventHandler::OnConnectionStatus(ConnectionStatus status,
props->thumbnail_frame_->empty();
}
if (needs_native_snapshot) {
#if defined(_WIN32)
auto* native_renderer =
runtime->windows_opengl_video_renderer_.get();
#else
#if defined(__APPLE__)
auto* native_renderer = runtime->mac_metal_video_renderer_.get();
#else
auto* native_renderer = runtime->opengl_video_renderer_.get();
#endif
auto snapshot = std::make_shared<std::vector<unsigned char>>();
if (native_renderer && native_renderer->CopyLatestNv12(
@@ -349,7 +348,7 @@ void PeerEventHandler::OnConnectionStatus(ConnectionStatus status,
std::lock_guard<std::mutex> lock(props->video_frame_mutex_);
props->front_frame_.reset();
props->back_frame_.reset();
#if defined(__APPLE__) || defined(_WIN32)
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
if (native_snapshot &&
(!props->thumbnail_frame_ || props->thumbnail_frame_->empty())) {
props->thumbnail_frame_ = std::move(native_snapshot);
@@ -363,11 +362,11 @@ void PeerEventHandler::OnConnectionStatus(ConnectionStatus status,
props->render_rect_dirty_ = true;
props->stream_cleanup_pending_ = true;
}
#if defined(__APPLE__) || defined(_WIN32)
#if defined(_WIN32)
auto* native_renderer = runtime->windows_opengl_video_renderer_.get();
#else
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
#if defined(__APPLE__)
auto* native_renderer = runtime->mac_metal_video_renderer_.get();
#else
auto* native_renderer = runtime->opengl_video_renderer_.get();
#endif
if (native_renderer) {
native_renderer->DiscardStream(remote_id);
+13 -13
View File
@@ -7,18 +7,18 @@
#include <vector>
#include "runtime/gui_runtime.h"
#if defined(__APPLE__) || defined(_WIN32)
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
#include <chrono>
#if defined(_WIN32)
#include "platform/windows_opengl_video_renderer.h"
#else
#if defined(__APPLE__)
#include "platform/metal_video_renderer.h"
#else
#include "platform/opengl_video_renderer.h"
#endif
#endif
namespace crossdesk {
#if defined(__APPLE__) || defined(_WIN32)
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
namespace {
constexpr auto kBackgroundSnapshotInterval = std::chrono::seconds(1);
@@ -45,14 +45,14 @@ void PeerEventHandler::OnReceiveVideoBuffer(
runtime->remote_sessions_.find(remote_id)->second.get();
if (props->connection_established_) {
#if defined(__APPLE__) || defined(_WIN32)
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
bool background_snapshot_only = false;
#if defined(_WIN32)
auto* native_renderer = runtime->windows_opengl_video_renderer_.get();
using NativeVideoRenderer = WindowsOpenGlVideoRenderer;
#else
#if defined(__APPLE__)
auto* native_renderer = runtime->mac_metal_video_renderer_.get();
using NativeVideoRenderer = MacMetalVideoRenderer;
#else
auto* native_renderer = runtime->opengl_video_renderer_.get();
using NativeVideoRenderer = OpenGlVideoRenderer;
#endif
if (native_renderer && native_renderer->IsReady()
#if defined(__APPLE__)
@@ -101,7 +101,7 @@ void PeerEventHandler::OnReceiveVideoBuffer(
#endif
{
std::lock_guard<std::mutex> lock(props->video_frame_mutex_);
#if defined(__APPLE__) || defined(_WIN32)
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
const auto now = std::chrono::steady_clock::now();
if (background_snapshot_only && props->thumbnail_frame_ &&
!props->thumbnail_frame_->empty() &&
@@ -137,7 +137,7 @@ void PeerEventHandler::OnReceiveVideoBuffer(
props->video_size_ = video_frame->size;
props->front_frame_.swap(props->back_frame_);
#if defined(__APPLE__) || defined(_WIN32)
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
props->thumbnail_frame_ = props->front_frame_;
props->thumbnail_width_ = video_frame->width;
props->thumbnail_height_ = video_frame->height;
@@ -149,7 +149,7 @@ void PeerEventHandler::OnReceiveVideoBuffer(
}
props->streaming_ = true;
#if defined(__APPLE__) || defined(_WIN32)
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
if (background_snapshot_only) {
return;
}
+1 -1
View File
@@ -110,7 +110,7 @@ struct RemoteSession {
std::mutex video_frame_mutex_;
std::shared_ptr<std::vector<unsigned char>> front_frame_;
std::shared_ptr<std::vector<unsigned char>> back_frame_;
#if defined(__APPLE__) || defined(_WIN32)
#if defined(__APPLE__) || defined(_WIN32) || defined(__linux__)
// Retains the most recent background CPU frame across disconnect cleanup
// so closing an unselected tab can still update its recent-item thumbnail.
std::shared_ptr<std::vector<unsigned char>> thumbnail_frame_;