Desktop: Directly upload frame buffer (#2930)

* Upload frame buffer directly to gpu texture

* Disable cef GPU acceleration to prevent crashes

* Cleanup code

* Address review comments

---------

Co-authored-by: Timon Schelling <me@timon.zip>
This commit is contained in:
Dennis Kobert
2025-07-25 14:04:46 +02:00
committed by GitHub
parent 735d58a647
commit a52ee70e4c
7 changed files with 150 additions and 158 deletions

View File

@@ -1,4 +1,4 @@
use crate::{CustomEvent, FrameBuffer};
use crate::{CustomEvent, WgpuContext, render::FrameBufferRef};
use std::{
sync::{Arc, Mutex, mpsc::Receiver},
time::Instant,
@@ -15,7 +15,7 @@ use winit::event_loop::EventLoopProxy;
pub(crate) trait CefEventHandler: Clone {
fn window_size(&self) -> WindowSize;
fn draw(&self, frame_buffer: FrameBuffer);
fn draw<'a>(&self, frame_buffer: FrameBufferRef<'a>);
/// Scheudule the main event loop to run the cef event loop after the timeout
/// [`_cef_browser_process_handler_t::on_schedule_message_pump_work`] for more documentation.
fn schedule_cef_message_loop_work(&self, scheduled_time: Instant);
@@ -37,6 +37,7 @@ impl WindowSize {
pub(crate) struct CefHandler {
window_size_receiver: Arc<Mutex<WindowSizeReceiver>>,
event_loop_proxy: EventLoopProxy<CustomEvent>,
wgpu_context: WgpuContext,
}
struct WindowSizeReceiver {
receiver: Receiver<WindowSize>,
@@ -51,10 +52,11 @@ impl WindowSizeReceiver {
}
}
impl CefHandler {
pub(crate) fn new(window_size_receiver: Receiver<WindowSize>, event_loop_proxy: EventLoopProxy<CustomEvent>) -> Self {
pub(crate) fn new(window_size_receiver: Receiver<WindowSize>, event_loop_proxy: EventLoopProxy<CustomEvent>, wgpu_context: WgpuContext) -> Self {
Self {
window_size_receiver: Arc::new(Mutex::new(WindowSizeReceiver::new(window_size_receiver))),
event_loop_proxy,
wgpu_context,
}
}
}
@@ -71,8 +73,44 @@ impl CefEventHandler for CefHandler {
}
*window_size
}
fn draw(&self, frame_buffer: FrameBuffer) {
let _ = self.event_loop_proxy.send_event(CustomEvent::UiUpdate(frame_buffer));
fn draw<'a>(&self, frame_buffer: FrameBufferRef<'a>) {
let width = frame_buffer.width() as u32;
let height = frame_buffer.height() as u32;
let texture = self.wgpu_context.device.create_texture(&wgpu::TextureDescriptor {
label: Some("CEF Texture"),
size: wgpu::Extent3d {
width,
height,
depth_or_array_layers: 1,
},
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: wgpu::TextureFormat::Bgra8UnormSrgb,
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
view_formats: &[],
});
self.wgpu_context.queue.write_texture(
wgpu::TexelCopyTextureInfo {
texture: &texture,
mip_level: 0,
origin: wgpu::Origin3d::ZERO,
aspect: wgpu::TextureAspect::All,
},
frame_buffer.buffer(),
wgpu::TexelCopyBufferLayout {
offset: 0,
bytes_per_row: Some(4 * width),
rows_per_image: Some(height),
},
wgpu::Extent3d {
width,
height,
depth_or_array_layers: 1,
},
);
let _ = self.event_loop_proxy.send_event(CustomEvent::UiUpdate(texture));
}
fn schedule_cef_message_loop_work(&self, scheduled_time: std::time::Instant) {