Skip to content

Commit 3ce88dc

Browse files
committed
Upload frame buffer directly to gpu texture
1 parent 1839f72 commit 3ce88dc

5 files changed

Lines changed: 174 additions & 111 deletions

File tree

desktop/src/app.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::CustomEvent;
22
use crate::FrameBuffer;
33
use crate::WindowSize;
44
use crate::render::GraphicsState;
5+
use crate::render::WgpuContext;
56
use std::sync::Arc;
67
use std::sync::mpsc::Sender;
78
use std::time::Duration;
@@ -27,10 +28,11 @@ pub(crate) struct WinitApp {
2728
_viewport_frame_buffer: Option<FrameBuffer>,
2829
graphics_state: Option<GraphicsState>,
2930
event_loop_proxy: EventLoopProxy<CustomEvent>,
31+
wgpu_context: WgpuContext,
3032
}
3133

3234
impl WinitApp {
33-
pub(crate) fn new(cef_context: cef::Context<cef::Initialized>, window_size_sender: Sender<WindowSize>, event_loop_proxy: EventLoopProxy<CustomEvent>) -> Self {
35+
pub(crate) fn new(cef_context: cef::Context<cef::Initialized>, window_size_sender: Sender<WindowSize>, event_loop_proxy: EventLoopProxy<CustomEvent>, wgpu_context: WgpuContext) -> Self {
3436
Self {
3537
cef_context,
3638
window: None,
@@ -40,6 +42,7 @@ impl WinitApp {
4042
graphics_state: None,
4143
window_size_sender,
4244
event_loop_proxy,
45+
wgpu_context,
4346
}
4447
}
4548
}
@@ -73,7 +76,7 @@ impl ApplicationHandler<CustomEvent> for WinitApp {
7376
)
7477
.unwrap(),
7578
);
76-
let graphics_state = pollster::block_on(GraphicsState::new(window.clone()));
79+
let graphics_state = GraphicsState::new(window.clone(), self.wgpu_context.clone());
7780

7881
self.window = Some(window);
7982
self.graphics_state = Some(graphics_state);
@@ -83,11 +86,12 @@ impl ApplicationHandler<CustomEvent> for WinitApp {
8386

8487
fn user_event(&mut self, _: &ActiveEventLoop, event: CustomEvent) {
8588
match event {
86-
CustomEvent::UiUpdate(frame_buffer) => {
89+
CustomEvent::UiUpdate((texture, width, height)) => {
8790
if let Some(graphics_state) = self.graphics_state.as_mut() {
88-
graphics_state.update_texture(&frame_buffer);
91+
graphics_state.bind_texture(&texture);
92+
graphics_state.resize(width, height);
8993
}
90-
self.ui_frame_buffer = Some(frame_buffer);
94+
// self.ui_frame_buffer = Some(frame_buffer);
9195
if let Some(window) = &self.window {
9296
window.request_redraw();
9397
}
@@ -115,9 +119,6 @@ impl ApplicationHandler<CustomEvent> for WinitApp {
115119
}
116120
WindowEvent::Resized(PhysicalSize { width, height }) => {
117121
let _ = self.window_size_sender.send(WindowSize::new(width as usize, height as usize));
118-
if let Some(ref mut graphics_state) = self.graphics_state {
119-
graphics_state.resize(width, height);
120-
}
121122
self.cef_context.notify_of_resize();
122123
}
123124

desktop/src/cef.rs

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use crate::{CustomEvent, FrameBuffer};
1+
use crate::{
2+
CustomEvent, FrameBuffer, WgpuContext,
3+
render::{FrameBufferRef, GraphicsState},
4+
};
25
use std::{
36
sync::{Arc, Mutex, mpsc::Receiver},
47
time::Instant,
@@ -14,7 +17,7 @@ use winit::event_loop::EventLoopProxy;
1417

1518
pub(crate) trait CefEventHandler: Clone {
1619
fn window_size(&self) -> WindowSize;
17-
fn draw(&self, frame_buffer: FrameBuffer);
20+
fn draw<'a>(&self, frame_buffer: FrameBufferRef<'a>);
1821
/// Scheudule the main event loop to run the cef event loop after the timeout
1922
/// [`_cef_browser_process_handler_t::on_schedule_message_pump_work`] for more documentation.
2023
fn schedule_cef_message_loop_work(&self, scheduled_time: Instant);
@@ -36,6 +39,7 @@ impl WindowSize {
3639
pub(crate) struct CefHandler {
3740
window_size_receiver: Arc<Mutex<WindowSizeReceiver>>,
3841
event_loop_proxy: EventLoopProxy<CustomEvent>,
42+
wgpu_context: WgpuContext,
3943
}
4044
struct WindowSizeReceiver {
4145
receiver: Receiver<WindowSize>,
@@ -50,10 +54,11 @@ impl WindowSizeReceiver {
5054
}
5155
}
5256
impl CefHandler {
53-
pub(crate) fn new(window_size_receiver: Receiver<WindowSize>, event_loop_proxy: EventLoopProxy<CustomEvent>) -> Self {
57+
pub(crate) fn new(window_size_receiver: Receiver<WindowSize>, event_loop_proxy: EventLoopProxy<CustomEvent>, wgpu_context: WgpuContext) -> Self {
5458
Self {
5559
window_size_receiver: Arc::new(Mutex::new(WindowSizeReceiver::new(window_size_receiver))),
5660
event_loop_proxy,
61+
wgpu_context,
5762
}
5863
}
5964
}
@@ -70,8 +75,44 @@ impl CefEventHandler for CefHandler {
7075
}
7176
*window_size
7277
}
73-
fn draw(&self, frame_buffer: FrameBuffer) {
74-
let _ = self.event_loop_proxy.send_event(CustomEvent::UiUpdate(frame_buffer));
78+
fn draw<'a>(&self, frame_buffer: FrameBufferRef<'a>) {
79+
let width = frame_buffer.width() as u32;
80+
let height = frame_buffer.height() as u32;
81+
let texture = self.wgpu_context.device.create_texture(&wgpu::TextureDescriptor {
82+
label: Some("CEF Texture"),
83+
size: wgpu::Extent3d {
84+
width,
85+
height,
86+
depth_or_array_layers: 1,
87+
},
88+
mip_level_count: 1,
89+
sample_count: 1,
90+
dimension: wgpu::TextureDimension::D2,
91+
format: wgpu::TextureFormat::Bgra8UnormSrgb,
92+
usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
93+
view_formats: &[],
94+
});
95+
self.wgpu_context.queue.write_texture(
96+
wgpu::TexelCopyTextureInfo {
97+
texture: &texture,
98+
mip_level: 0,
99+
origin: wgpu::Origin3d::ZERO,
100+
aspect: wgpu::TextureAspect::All,
101+
},
102+
frame_buffer.buffer(),
103+
wgpu::TexelCopyBufferLayout {
104+
offset: 0,
105+
bytes_per_row: Some(4 * width),
106+
rows_per_image: Some(height),
107+
},
108+
wgpu::Extent3d {
109+
width,
110+
height,
111+
depth_or_array_layers: 1,
112+
},
113+
);
114+
115+
let _ = self.event_loop_proxy.send_event(CustomEvent::UiUpdate((texture, width, height)));
75116
}
76117

77118
fn schedule_cef_message_loop_work(&self, scheduled_time: std::time::Instant) {

desktop/src/cef/internal/render_handler.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use cef::{Browser, ImplRenderHandler, PaintElementType, Rect, WrapRenderHandler}
44

55
use crate::FrameBuffer;
66
use crate::cef::CefEventHandler;
7+
use crate::render::FrameBufferRef;
78

89
pub(crate) struct RenderHandlerImpl<H: CefEventHandler> {
910
object: *mut RcImpl<_cef_render_handler_t, Self>,
@@ -42,7 +43,7 @@ impl<H: CefEventHandler> ImplRenderHandler for RenderHandlerImpl<H> {
4243
) {
4344
let buffer_size = (width * height * 4) as usize;
4445
let buffer_slice = unsafe { std::slice::from_raw_parts(buffer, buffer_size) };
45-
let frame_buffer = FrameBuffer::new(buffer_slice.to_vec(), width as usize, height as usize).expect("Failed to create frame buffer");
46+
let frame_buffer = FrameBufferRef::new(buffer_slice, width as usize, height as usize).expect("Failed to create frame buffer");
4647

4748
self.event_handler.draw(frame_buffer)
4849
}

desktop/src/main.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ mod cef;
99
use cef::{Setup, WindowSize};
1010

1111
mod render;
12-
use render::FrameBuffer;
12+
use render::{FrameBuffer, WgpuContext};
1313

1414
mod app;
1515
use app::WinitApp;
1616

1717
#[derive(Debug)]
1818
pub(crate) enum CustomEvent {
19-
UiUpdate(FrameBuffer),
19+
UiUpdate((wgpu::Texture, u32, u32)),
2020
ScheduleBrowserWork(Instant),
2121
}
2222

@@ -36,7 +36,8 @@ fn main() {
3636

3737
let (send, recv) = std::sync::mpsc::channel();
3838

39-
let cef_context = match cef_context.init(cef::CefHandler::new(recv, event_loop.create_proxy())) {
39+
let wgpu_context = pollster::block_on(WgpuContext::new());
40+
let cef_context = match cef_context.init(cef::CefHandler::new(recv, event_loop.create_proxy(), wgpu_context.clone())) {
4041
Ok(c) => c,
4142
Err(cef::InitError::InitializationFailed) => {
4243
tracing::error!("Cef initialization failed");
@@ -46,7 +47,7 @@ fn main() {
4647

4748
tracing::info!("Cef initialized successfully");
4849

49-
let mut winit_app = WinitApp::new(cef_context, send, event_loop.create_proxy());
50+
let mut winit_app = WinitApp::new(cef_context, send, event_loop.create_proxy(), wgpu_context);
5051

5152
event_loop.run_app(&mut winit_app).unwrap();
5253
}

0 commit comments

Comments
 (0)