Skip to content

Commit 2e44818

Browse files
Desktop: Fix missing resize events causing all-gray window on Mac after launch (#3445)
* okayish solution should be improved at some point but for now it works well enough. * do leftover renames * better solution * less weird resize frames * move surface reconfiguration * fix recent desktop mac breakages * better looking resize on mac * fix background color * Fix blank screen on window initialization * cleanup --------- Co-authored-by: Keavon Chambers <[email protected]>
1 parent 5b472a6 commit 2e44818

File tree

11 files changed

+129
-66
lines changed

11 files changed

+129
-66
lines changed

desktop/bundle/src/win.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::path::{Path, PathBuf};
55
use crate::common::*;
66

77
const PACKAGE: &str = "graphite-desktop-platform-win";
8-
const EXECUTABLE: &str = "graphite-editor.exe";
8+
const EXECUTABLE: &str = "graphite.exe";
99

1010
pub fn main() -> Result<(), Box<dyn Error>> {
1111
let app_bin = build_bin(PACKAGE, None)?;

desktop/src/app.rs

Lines changed: 49 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,22 +18,22 @@ use crate::cef;
1818
use crate::consts::CEF_MESSAGE_LOOP_MAX_ITERATIONS;
1919
use crate::event::{AppEvent, AppEventScheduler};
2020
use crate::persist::PersistentData;
21-
use crate::render::GraphicsState;
21+
use crate::render::{RenderError, RenderState};
2222
use crate::window::Window;
2323
use crate::wrapper::messages::{DesktopFrontendMessage, DesktopWrapperMessage, Platform};
2424
use crate::wrapper::{DesktopWrapper, NodeGraphExecutionResult, WgpuContext, serialize_frontend_messages};
2525

2626
pub(crate) struct App {
27-
cef_context: Box<dyn cef::CefContext>,
27+
render_state: Option<RenderState>,
28+
wgpu_context: WgpuContext,
2829
window: Option<Window>,
2930
window_scale: f64,
30-
cef_schedule: Option<Instant>,
31-
cef_view_info_sender: Sender<cef::ViewInfoUpdate>,
32-
graphics_state: Option<GraphicsState>,
33-
wgpu_context: WgpuContext,
3431
app_event_receiver: Receiver<AppEvent>,
3532
app_event_scheduler: AppEventScheduler,
3633
desktop_wrapper: DesktopWrapper,
34+
cef_context: Box<dyn cef::CefContext>,
35+
cef_schedule: Option<Instant>,
36+
cef_view_info_sender: Sender<cef::ViewInfoUpdate>,
3737
last_ui_update: Instant,
3838
avg_frame_time: f32,
3939
start_render_sender: SyncSender<()>,
@@ -77,17 +77,17 @@ impl App {
7777
persistent_data.load_from_disk();
7878

7979
Self {
80-
cef_context,
81-
window: None,
82-
window_scale: 1.0,
83-
cef_schedule: Some(Instant::now()),
84-
graphics_state: None,
85-
cef_view_info_sender,
80+
render_state: None,
8681
wgpu_context,
82+
window: None,
83+
window_scale: 1.,
8784
app_event_receiver,
8885
app_event_scheduler,
8986
desktop_wrapper: DesktopWrapper::new(),
9087
last_ui_update: Instant::now(),
88+
cef_context,
89+
cef_schedule: Some(Instant::now()),
90+
cef_view_info_sender,
9191
avg_frame_time: 0.,
9292
start_render_sender,
9393
web_communication_initialized: false,
@@ -162,23 +162,23 @@ impl App {
162162
});
163163
}
164164
DesktopFrontendMessage::UpdateViewportPhysicalBounds { x, y, width, height } => {
165-
if let Some(graphics_state) = &mut self.graphics_state
165+
if let Some(render_state) = &mut self.render_state
166166
&& let Some(window) = &self.window
167167
{
168168
let window_size = window.surface_size();
169169

170170
let viewport_offset_x = x / window_size.width as f64;
171171
let viewport_offset_y = y / window_size.height as f64;
172-
graphics_state.set_viewport_offset([viewport_offset_x as f32, viewport_offset_y as f32]);
172+
render_state.set_viewport_offset([viewport_offset_x as f32, viewport_offset_y as f32]);
173173

174174
let viewport_scale_x = if width != 0.0 { window_size.width as f64 / width } else { 1.0 };
175175
let viewport_scale_y = if height != 0.0 { window_size.height as f64 / height } else { 1.0 };
176-
graphics_state.set_viewport_scale([viewport_scale_x as f32, viewport_scale_y as f32]);
176+
render_state.set_viewport_scale([viewport_scale_x as f32, viewport_scale_y as f32]);
177177
}
178178
}
179179
DesktopFrontendMessage::UpdateOverlays(scene) => {
180-
if let Some(graphics_state) = &mut self.graphics_state {
181-
graphics_state.set_overlays_scene(scene);
180+
if let Some(render_state) = &mut self.render_state {
181+
render_state.set_overlays_scene(scene);
182182
}
183183
}
184184
DesktopFrontendMessage::PersistenceWriteDocument { id, document } => {
@@ -331,19 +331,18 @@ impl App {
331331
NodeGraphExecutionResult::HasRun(texture) => {
332332
self.dispatch_desktop_wrapper_message(DesktopWrapperMessage::PollNodeGraphEvaluation);
333333
if let Some(texture) = texture
334-
&& let Some(graphics_state) = self.graphics_state.as_mut()
334+
&& let Some(render_state) = self.render_state.as_mut()
335335
&& let Some(window) = self.window.as_ref()
336336
{
337-
graphics_state.bind_viewport_texture(texture);
337+
render_state.bind_viewport_texture(texture);
338338
window.request_redraw();
339339
}
340340
}
341341
NodeGraphExecutionResult::NotRun => {}
342342
},
343343
AppEvent::UiUpdate(texture) => {
344-
if let Some(graphics_state) = self.graphics_state.as_mut() {
345-
graphics_state.resize(texture.width(), texture.height());
346-
graphics_state.bind_ui_texture(texture);
344+
if let Some(render_state) = self.render_state.as_mut() {
345+
render_state.bind_ui_texture(texture);
347346
let elapsed = self.last_ui_update.elapsed().as_secs_f32();
348347
self.last_ui_update = Instant::now();
349348
if elapsed < 0.5 {
@@ -385,13 +384,18 @@ impl ApplicationHandler for App {
385384

386385
self.window_scale = window.scale_factor();
387386
let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Scale(self.window_scale));
387+
388+
// Ensures the CEF texture does not remain at 1x1 pixels until the window is resized by the user
389+
// Affects only some Mac devices (issue found on 2023 M2 Mac Mini).
390+
let PhysicalSize { width, height } = window.surface_size();
391+
let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Size { width, height });
392+
388393
self.cef_context.notify_view_info_changed();
389394

390395
self.window = Some(window);
391396

392-
let graphics_state = GraphicsState::new(self.window.as_ref().unwrap(), self.wgpu_context.clone());
393-
394-
self.graphics_state = Some(graphics_state);
397+
let render_state = RenderState::new(self.window.as_ref().unwrap(), self.wgpu_context.clone());
398+
self.render_state = Some(render_state);
395399

396400
self.desktop_wrapper.init(self.wgpu_context.clone());
397401

@@ -418,14 +422,18 @@ impl ApplicationHandler for App {
418422
self.app_event_scheduler.schedule(AppEvent::CloseWindow);
419423
}
420424
WindowEvent::SurfaceResized(PhysicalSize { width, height }) => {
421-
let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Size {
422-
width: width as usize,
423-
height: height as usize,
424-
});
425+
let _ = self.cef_view_info_sender.send(cef::ViewInfoUpdate::Size { width, height });
425426
self.cef_context.notify_view_info_changed();
427+
428+
if let Some(render_state) = &mut self.render_state {
429+
render_state.resize(width, height);
430+
}
431+
426432
if let Some(window) = &self.window {
427433
let maximized = window.is_maximized();
428434
self.app_event_scheduler.schedule(AppEvent::DesktopWrapperMessage(DesktopWrapperMessage::UpdateMaximized { maximized }));
435+
436+
window.request_redraw();
429437
}
430438
}
431439
WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
@@ -434,18 +442,24 @@ impl ApplicationHandler for App {
434442
self.cef_context.notify_view_info_changed();
435443
}
436444
WindowEvent::RedrawRequested => {
437-
let Some(ref mut graphics_state) = self.graphics_state else { return };
438-
// Only rerender once we have a new UI texture to display
445+
let Some(render_state) = &mut self.render_state else { return };
439446
if let Some(window) = &self.window {
440-
match graphics_state.render(window) {
447+
let size = window.surface_size();
448+
render_state.resize(size.width, size.height);
449+
450+
match render_state.render(window) {
441451
Ok(_) => {}
442-
Err(wgpu::SurfaceError::Lost) => {
452+
Err(RenderError::OutdatedUITextureError) => {
453+
self.cef_context.notify_view_info_changed();
454+
}
455+
Err(RenderError::SurfaceError(wgpu::SurfaceError::Lost)) => {
443456
tracing::warn!("lost surface");
444457
}
445-
Err(wgpu::SurfaceError::OutOfMemory) => {
458+
Err(RenderError::SurfaceError(wgpu::SurfaceError::OutOfMemory)) => {
459+
tracing::error!("GPU out of memory");
446460
event_loop.exit();
447461
}
448-
Err(e) => tracing::error!("{:?}", e),
462+
Err(RenderError::SurfaceError(e)) => tracing::error!("Render error: {:?}", e),
449463
}
450464
let _ = self.start_render_sender.try_send(());
451465
}

desktop/src/cef.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,8 @@ pub(crate) trait CefEventHandler: Send + Sync + 'static {
5555

5656
#[derive(Clone, Copy)]
5757
pub(crate) struct ViewInfo {
58-
width: usize,
59-
height: usize,
58+
width: u32,
59+
height: u32,
6060
scale: f64,
6161
}
6262
impl ViewInfo {
@@ -78,10 +78,10 @@ impl ViewInfo {
7878
pub(crate) fn zoom(&self) -> f64 {
7979
self.scale.ln() / 1.2_f64.ln()
8080
}
81-
pub(crate) fn width(&self) -> usize {
81+
pub(crate) fn width(&self) -> u32 {
8282
self.width
8383
}
84-
pub(crate) fn height(&self) -> usize {
84+
pub(crate) fn height(&self) -> u32 {
8585
self.height
8686
}
8787
}
@@ -92,7 +92,7 @@ impl Default for ViewInfo {
9292
}
9393

9494
pub(crate) enum ViewInfoUpdate {
95-
Size { width: usize, height: usize },
95+
Size { width: u32, height: u32 },
9696
Scale(f64),
9797
}
9898

desktop/src/cli.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#[derive(clap::Parser)]
2-
#[clap(name = "graphite-editor", version)]
2+
#[clap(name = "graphite", version)]
33
pub struct Cli {
44
#[arg(help = "Files to open on startup")]
55
pub files: Vec<std::path::PathBuf>,

desktop/src/consts.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
pub(crate) const APP_NAME: &str = "Graphite";
2+
#[cfg(target_os = "linux")]
23
pub(crate) const APP_ID: &str = "rs.graphite.Graphite";
34

45
pub(crate) const APP_DIRECTORY_NAME: &str = "graphite";

desktop/src/render.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
mod frame_buffer_ref;
22
pub(crate) use frame_buffer_ref::FrameBufferRef;
33

4-
mod graphics_state;
5-
pub(crate) use graphics_state::GraphicsState;
4+
mod state;
5+
pub(crate) use state::{RenderError, RenderState};

desktop/src/render/composite_shader.wgsl

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ fn vs_main(@builtin(vertex_index) vertex_index: u32) -> VertexOutput {
2323
struct Constants {
2424
viewport_scale: vec2<f32>,
2525
viewport_offset: vec2<f32>,
26+
ui_scale: vec2<f32>,
27+
background_color: vec4<f32>,
2628
};
2729

2830
var<push_constant> constants: Constants;
@@ -38,19 +40,29 @@ var s_diffuse: sampler;
3840

3941
@fragment
4042
fn fs_main(in: VertexOutput) -> @location(0) vec4<f32> {
41-
let ui_linear = srgb_to_linear(textureSample(t_ui, s_diffuse, in.tex_coords));
43+
let ui_coordinate = in.tex_coords * constants.ui_scale;
44+
if (ui_coordinate.x < 0.0 || ui_coordinate.x > 1.0 ||
45+
ui_coordinate.y < 0.0 || ui_coordinate.y > 1.0) {
46+
return srgb_to_linear(constants.background_color);
47+
}
48+
49+
let ui_linear = srgb_to_linear(textureSample(t_ui, s_diffuse, ui_coordinate));
4250
if (ui_linear.a >= 0.999) {
4351
return ui_linear;
4452
}
4553

54+
// UI texture is premultiplied, we need to unpremultiply before blending
55+
let ui_srgb = linear_to_srgb(unpremultiply(ui_linear));
56+
4657
let viewport_coordinate = (in.tex_coords - constants.viewport_offset) * constants.viewport_scale;
58+
if (viewport_coordinate.x < 0.0 || viewport_coordinate.x > 1.0 ||
59+
viewport_coordinate.y < 0.0 || viewport_coordinate.y > 1.0) {
60+
return srgb_to_linear(constants.background_color);
61+
}
4762

4863
let overlay_srgb = textureSample(t_overlays, s_diffuse, viewport_coordinate);
4964
let viewport_srgb = textureSample(t_viewport, s_diffuse, viewport_coordinate);
5065

51-
// UI texture is premultiplied, we need to unpremultiply before blending
52-
let ui_srgb = linear_to_srgb(unpremultiply(ui_linear));
53-
5466
if (overlay_srgb.a < 0.001) {
5567
if (ui_srgb.a < 0.001) {
5668
return srgb_to_linear(viewport_srgb);

0 commit comments

Comments
 (0)