Skip to content

Commit 0a65b16

Browse files
authored
Merge branch 'master' into feat/pdf-export
2 parents d5b6668 + a3f88b0 commit 0a65b16

22 files changed

Lines changed: 246 additions & 110 deletions

File tree

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,5 @@ debug = true
240240
# Force cargo to use only one version of the dpi crate (vendoring breaks without this)
241241
dpi = { git = "https://github.com/rust-windowing/winit.git" }
242242
download-cef = { git = "https://github.com/timon-schelling/cef-rs.git", branch = "graphite" }
243+
vello = { git = "https://github.com/Keavon/vello.git", branch = "0.7.0-fix-images-rendering-blurry" }
244+
vello_encoding = { git = "https://github.com/Keavon/vello.git", branch = "0.7.0-fix-images-rendering-blurry" }

desktop/src/app.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::persist::PersistentData;
2121
use crate::preferences;
2222
use crate::render::{RenderError, RenderState};
2323
use crate::window::Window;
24-
use crate::wrapper::messages::{DesktopFrontendMessage, DesktopWrapperMessage, InputMessage, MouseKeys, MouseState};
24+
use crate::wrapper::messages::{DesktopFrontendMessage, DesktopWrapperMessage, InputMessage, MouseKeys, MouseState, Preferences};
2525
use crate::wrapper::{DesktopWrapper, NodeGraphExecutionResult, WgpuContext, serialize_frontend_messages};
2626

2727
pub(crate) struct App {
@@ -46,6 +46,8 @@ pub(crate) struct App {
4646
web_communication_initialized: bool,
4747
web_communication_startup_buffer: Vec<Vec<u8>>,
4848
persistent_data: PersistentData,
49+
#[cfg_attr(not(target_os = "macos"), expect(unused))]
50+
preferences: Preferences,
4951
cli: Cli,
5052
startup_time: Option<Instant>,
5153
exiting: Arc<AtomicBool>,
@@ -63,6 +65,7 @@ impl App {
6365
wgpu_context: WgpuContext,
6466
app_event_receiver: Receiver<AppEvent>,
6567
app_event_scheduler: AppEventScheduler,
68+
preferences: Preferences,
6669
cli: Cli,
6770
) -> Self {
6871
let ctrlc_app_event_scheduler = app_event_scheduler.clone();
@@ -116,6 +119,7 @@ impl App {
116119
web_communication_initialized: false,
117120
web_communication_startup_buffer: Vec::new(),
118121
persistent_data,
122+
preferences,
119123
cli,
120124
startup_time: None,
121125
exiting,
@@ -516,7 +520,12 @@ impl ApplicationHandler for App {
516520
let window = Window::new(event_loop, self.app_event_scheduler.clone());
517521
self.window = Some(window);
518522

519-
let render_state = RenderState::new(self.window.as_ref().unwrap(), self.wgpu_context.clone());
523+
#[cfg(not(target_os = "macos"))]
524+
let present_mode = None;
525+
#[cfg(target_os = "macos")]
526+
let present_mode = if !self.preferences.vsync { Some(wgpu::PresentMode::Immediate) } else { None };
527+
528+
let render_state = RenderState::new(self.window.as_ref().unwrap(), self.wgpu_context.clone(), present_mode);
520529
self.render_state = Some(render_state);
521530

522531
if let Some(window) = &self.window.as_ref() {

desktop/src/lib.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ pub fn start() {
6262
}
6363
};
6464

65+
let prefs = preferences::read();
66+
6567
// Must be called before event loop initialization or native window integrations will break
6668
App::init();
6769

@@ -73,7 +75,7 @@ pub fn start() {
7375

7476
let (cef_view_info_sender, cef_view_info_receiver) = std::sync::mpsc::channel();
7577

76-
let disable_ui_acceleration = preferences::read().disable_ui_acceleration || cli.disable_ui_acceleration;
78+
let disable_ui_acceleration = prefs.disable_ui_acceleration || cli.disable_ui_acceleration;
7779
if disable_ui_acceleration {
7880
println!("UI acceleration is disabled");
7981
}
@@ -95,7 +97,7 @@ pub fn start() {
9597
}
9698
};
9799

98-
let app = App::new(Box::new(cef_context), cef_view_info_sender, wgpu_context, app_event_receiver, app_event_scheduler, cli);
100+
let app = App::new(Box::new(cef_context), cef_view_info_sender, wgpu_context, app_event_receiver, app_event_scheduler, prefs, cli);
99101

100102
let exit_reason = app.run(event_loop);
101103

@@ -111,15 +113,15 @@ pub fn start() {
111113
drop(lock);
112114

113115
match exit_reason {
114-
#[cfg(target_os = "linux")]
115116
app::ExitReason::Restart | app::ExitReason::UiAccelerationFailure => {
116117
tracing::error!("Restarting application");
117118
let mut command = std::process::Command::new(std::env::current_exe().unwrap());
118119
#[cfg(target_family = "unix")]
119120
let _ = std::os::unix::process::CommandExt::exec(&mut command);
121+
#[cfg(target_family = "unix")]
122+
tracing::error!("Failed to restart application");
120123
#[cfg(not(target_family = "unix"))]
121124
let _ = command.spawn();
122-
tracing::error!("Failed to restart application");
123125
}
124126
_ => {}
125127
}

desktop/src/render/state.rs

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::borrow::Cow;
2+
use wgpu::PresentMode;
23

34
use crate::window::Window;
45
use crate::wrapper::{TargetTexture, WgpuContext, WgpuExecutor};
@@ -11,13 +12,13 @@ pub(crate) struct RenderState {
1112
executor: WgpuExecutor,
1213
config: wgpu::SurfaceConfiguration,
1314
render_pipeline: wgpu::RenderPipeline,
14-
transparent_texture: wgpu::Texture,
15+
transparent_texture: std::sync::Arc<wgpu::Texture>,
1516
sampler: wgpu::Sampler,
1617
desired_width: u32,
1718
desired_height: u32,
1819
viewport_scale: [f32; 2],
1920
viewport_offset: [f32; 2],
20-
viewport_texture: Option<wgpu::Texture>,
21+
viewport_texture: Option<std::sync::Arc<wgpu::Texture>>,
2122
overlays_texture: Option<TargetTexture>,
2223
ui_texture: Option<wgpu::Texture>,
2324
bind_group: Option<wgpu::BindGroup>,
@@ -27,7 +28,7 @@ pub(crate) struct RenderState {
2728
}
2829

2930
impl RenderState {
30-
pub(crate) fn new(window: &Window, context: WgpuContext) -> Self {
31+
pub(crate) fn new(window: &Window, context: WgpuContext, present_mode: Option<PresentMode>) -> Self {
3132
let size = window.surface_size();
3233
let surface = window.create_surface(context.instance.clone());
3334

@@ -39,18 +40,15 @@ impl RenderState {
3940
format: surface_format,
4041
width: size.width,
4142
height: size.height,
42-
#[cfg(not(target_os = "macos"))]
43-
present_mode: surface_caps.present_modes[0],
44-
#[cfg(target_os = "macos")]
45-
present_mode: wgpu::PresentMode::Immediate,
43+
present_mode: present_mode.unwrap_or(surface_caps.present_modes[0]),
4644
alpha_mode: surface_caps.alpha_modes[0],
4745
view_formats: vec![],
4846
desired_maximum_frame_latency: 1,
4947
};
5048

5149
surface.configure(&context.device, &config);
5250

53-
let transparent_texture = context.device.create_texture(&wgpu::TextureDescriptor {
51+
let transparent_texture = std::sync::Arc::new(context.device.create_texture(&wgpu::TextureDescriptor {
5452
label: Some("Transparent Texture"),
5553
size: wgpu::Extent3d {
5654
width: 1,
@@ -63,7 +61,7 @@ impl RenderState {
6361
format: wgpu::TextureFormat::Bgra8UnormSrgb,
6462
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
6563
view_formats: &[],
66-
});
64+
}));
6765

6866
// Create shader module
6967
let shader = context.device.create_shader_module(wgpu::include_wgsl!("composite_shader.wgsl"));
@@ -207,7 +205,7 @@ impl RenderState {
207205
}
208206
}
209207

210-
pub(crate) fn bind_viewport_texture(&mut self, viewport_texture: wgpu::Texture) {
208+
pub(crate) fn bind_viewport_texture(&mut self, viewport_texture: std::sync::Arc<wgpu::Texture>) {
211209
self.viewport_texture = Some(viewport_texture);
212210
self.update_bindgroup();
213211
}

desktop/src/window/mac/menu.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ fn menu_items_from_wrapper(entries: Vec<WrapperMenuItem>) -> Vec<MenuItemKind> {
7777
}
7878
WrapperMenuItem::SubMenu { text: name, items, .. } => {
7979
let items = menu_items_from_wrapper(items);
80-
let items = items.iter().map(|item| menu_item_kind_to_dyn(item)).collect::<Vec<&dyn IsMenuItem>>();
80+
let items = items.iter().map(menu_item_kind_to_dyn).collect::<Vec<&dyn IsMenuItem>>();
8181
let submenu = Submenu::with_items(name, true, &items).unwrap();
8282
menu_items.push(MenuItemKind::Submenu(submenu));
8383
}
@@ -106,7 +106,7 @@ fn replace_children<'a, T: Into<MenuContainer<'a>>>(menu: T, new_items: Vec<Menu
106106
for item in items.iter() {
107107
menu.remove(menu_item_kind_to_dyn(item)).unwrap();
108108
}
109-
let items = new_items.iter().map(|item| menu_item_kind_to_dyn(item)).collect::<Vec<&dyn IsMenuItem>>();
109+
let items = new_items.iter().map(menu_item_kind_to_dyn).collect::<Vec<&dyn IsMenuItem>>();
110110
menu.append_items(items.as_ref()).unwrap();
111111
}
112112

desktop/wrapper/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ impl DesktopWrapper {
5858
}
5959

6060
pub enum NodeGraphExecutionResult {
61-
HasRun(Option<wgpu::Texture>),
61+
HasRun(Option<std::sync::Arc<wgpu::Texture>>),
6262
NotRun,
6363
}
6464

desktop/wrapper/src/utils.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub(crate) mod menu {
1919
panic!("Menu bar layout group is supposed to be a row");
2020
};
2121
widgets
22-
.into_iter()
22+
.iter()
2323
.map(|widget| {
2424
let text_button = match widget.widget.as_ref() {
2525
Widget::TextButton(text_button) => text_button,
@@ -79,7 +79,7 @@ pub(crate) mod menu {
7979
let enabled = !*disabled;
8080

8181
if !children.is_empty() {
82-
let items = convert_menu_bar_entry_children_to_menu_items(&children, root_widget_id, path.clone());
82+
let items = convert_menu_bar_entry_children_to_menu_items(children, root_widget_id, path.clone());
8383
return MenuItem::SubMenu { id, text, enabled, items };
8484
}
8585

editor/src/messages/dialog/preferences_dialog/preferences_dialog_message_handler.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -387,9 +387,44 @@ impl PreferencesDialogMessageHandler {
387387

388388
rows.push(ui_acceleration);
389389
}
390+
391+
#[cfg(target_os = "macos")]
392+
{
393+
let vsync_description = "
394+
Render frames with vertical synchronization (v-sync) to prevent visual tearing within Graphite and the operating system compositor. This introduces increased input latency which is more noticeable on lower refresh rate displays. Future versions of Graphite will aim to reduce the macOS-specific latency without tearing artifacts.\n\
395+
\n\
396+
The application will restart for this change to take effect.\n\
397+
\n\
398+
*Default: Off.*
399+
"
400+
.trim();
401+
402+
let checkbox_id = CheckboxId::new();
403+
let vsync_checked = preferences.vsync;
404+
405+
let vsync = vec![
406+
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
407+
Separator::new(SeparatorStyle::Unrelated).widget_instance(),
408+
CheckboxInput::new(vsync_checked)
409+
.tooltip_label("Enable V-Sync")
410+
.tooltip_description(vsync_description)
411+
.on_update(|checkbox_input: &CheckboxInput| Message::Batched {
412+
messages: Box::new([PreferencesDialogMessage::MayRequireRestart.into(), PreferencesMessage::VSync { vsync: checkbox_input.checked }.into()]),
413+
})
414+
.for_label(checkbox_id)
415+
.widget_instance(),
416+
TextLabel::new("Enable V-Sync")
417+
.tooltip_label("Enable V-Sync")
418+
.tooltip_description(vsync_description)
419+
.for_checkbox(checkbox_id)
420+
.widget_instance(),
421+
];
422+
423+
rows.push(vsync);
424+
}
390425
}
391426

392-
Layout(rows.into_iter().map(|r| LayoutGroup::row(r)).collect())
427+
Layout(rows.into_iter().map(LayoutGroup::row).collect())
393428
}
394429

395430
pub fn send_layout(&self, responses: &mut VecDeque<Message>, layout_target: LayoutTarget, preferences: &PreferencesMessageHandler) {

editor/src/messages/portfolio/portfolio_message_handler.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1057,7 +1057,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
10571057
}
10581058
PortfolioMessage::RequestStatusBarInfoLayout => {
10591059
#[cfg(not(target_family = "wasm"))]
1060-
let widgets = vec![TextLabel::new("Graphite 1.0.0-RC3").disabled(true).widget_instance()]; // TODO: After the RCs, call this "Graphite (beta) x.y.z"
1060+
let widgets = vec![TextLabel::new("Graphite 1.0.0-RC4").disabled(true).widget_instance()]; // TODO: After the RCs, call this "Graphite (beta) x.y.z"
10611061
#[cfg(target_family = "wasm")]
10621062
let widgets = vec![];
10631063

@@ -1191,7 +1191,6 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
11911191
Ok(message) => responses.add_front(message),
11921192
}
11931193
}
1194-
#[cfg(not(target_family = "wasm"))]
11951194
PortfolioMessage::SubmitEyedropperPreviewRender => {
11961195
use crate::consts::EYEDROPPER_PREVIEW_AREA_RESOLUTION;
11971196

@@ -1223,10 +1222,6 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
12231222
Ok(message) => responses.add_front(message),
12241223
}
12251224
}
1226-
#[cfg(target_family = "wasm")]
1227-
PortfolioMessage::SubmitEyedropperPreviewRender => {
1228-
// TODO: Currently for Wasm, this is implemented through SVG rendering but the Eyedropper tool doesn't work at all when Vello is enabled as the renderer
1229-
}
12301225
PortfolioMessage::ToggleFocusDocument => {
12311226
self.focus_document = !self.focus_document;
12321227
responses.add(MenuBarMessage::SendLayout);

editor/src/messages/preferences/preferences_message.rs

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,38 @@ use crate::messages::prelude::*;
66
#[derive(PartialEq, Clone, Debug, serde::Serialize, serde::Deserialize)]
77
pub enum PreferencesMessage {
88
// Management messages
9-
Load { preferences: PreferencesMessageHandler },
9+
Load {
10+
preferences: PreferencesMessageHandler,
11+
},
1012
ResetToDefaults,
1113

1214
// Per-preference messages
13-
SelectionMode { selection_mode: SelectionMode },
14-
BrushTool { enabled: bool },
15-
ModifyLayout { zoom_with_scroll: bool },
16-
GraphWireStyle { style: GraphWireStyle },
17-
ViewportZoomWheelRate { rate: f64 },
18-
UIScale { scale: f64 },
19-
DisableUIAcceleration { disable_ui_acceleration: bool },
20-
MaxRenderRegionSize { size: u32 },
15+
SelectionMode {
16+
selection_mode: SelectionMode,
17+
},
18+
BrushTool {
19+
enabled: bool,
20+
},
21+
ModifyLayout {
22+
zoom_with_scroll: bool,
23+
},
24+
GraphWireStyle {
25+
style: GraphWireStyle,
26+
},
27+
ViewportZoomWheelRate {
28+
rate: f64,
29+
},
30+
UIScale {
31+
scale: f64,
32+
},
33+
MaxRenderRegionSize {
34+
size: u32,
35+
},
36+
DisableUIAcceleration {
37+
disable_ui_acceleration: bool,
38+
},
39+
#[cfg(target_os = "macos")]
40+
VSync {
41+
vsync: bool,
42+
},
2143
}

0 commit comments

Comments
 (0)