Skip to content

Commit 1787382

Browse files
committed
Fix retina DPI blur and add pixel_density API.
1 parent 930d3b0 commit 1787382

6 files changed

Lines changed: 119 additions & 10 deletions

File tree

crates/processing_glfw/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,11 @@ impl GlfwContext {
177177
true
178178
}
179179

180+
pub fn content_scale(&self) -> f32 {
181+
let (s, _) = self.window.get_content_scale();
182+
s
183+
}
184+
180185
fn sync_cursor(&mut self, surface: Entity) {
181186
use bevy::window::CursorGrabMode;
182187

crates/processing_pyo3/src/graphics.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,19 @@ impl Surface {
146146
None => true, // no-op, offscreen surfaces never close
147147
}
148148
}
149+
150+
#[getter]
151+
pub fn display_density(&self) -> PyResult<f32> {
152+
match &self.glfw_ctx {
153+
Some(ctx) => Ok(ctx.content_scale()),
154+
None => Ok(1.0),
155+
}
156+
}
157+
158+
pub fn set_pixel_density(&self, density: f32) -> PyResult<()> {
159+
surface_set_pixel_density(self.entity, density)
160+
.map_err(|e| PyRuntimeError::new_err(format!("{e}")))
161+
}
149162
}
150163

151164
impl Drop for Surface {

crates/processing_pyo3/src/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1432,4 +1432,18 @@ mod mewnala {
14321432
fn key_just_pressed(key_code: u32) -> PyResult<bool> {
14331433
input::key_just_pressed(key_code)
14341434
}
1435+
1436+
#[pyfunction]
1437+
#[pyo3(pass_module)]
1438+
fn pixel_density(module: &Bound<'_, PyModule>, density: f32) -> PyResult<()> {
1439+
graphics!(module).surface.set_pixel_density(density)
1440+
}
1441+
1442+
#[pyfunction]
1443+
#[pyo3(pass_module)]
1444+
fn display_density(module: &Bound<'_, PyModule>) -> PyResult<f32> {
1445+
let graphics =
1446+
get_graphics(module)?.ok_or_else(|| PyRuntimeError::new_err("call size() first"))?;
1447+
graphics.surface.display_density()
1448+
}
14351449
}

crates/processing_render/src/graphics.rs

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ pub struct GraphicsPlugin;
4040

4141
impl Plugin for GraphicsPlugin {
4242
fn build(&self, app: &mut App) {
43-
app.init_resource::<RenderLayersManager>();
43+
app.init_resource::<RenderLayersManager>()
44+
.add_systems(PostUpdate, sync_to_surface);
4445
}
4546
}
4647

@@ -149,14 +150,26 @@ pub fn create(
149150
mut commands: Commands,
150151
mut layer_manager: ResMut<RenderLayersManager>,
151152
p_images: Query<&Image, With<Surface>>,
153+
windows: Query<&Window, With<Surface>>,
152154
render_device: Res<RenderDevice>,
153155
) -> Result<Entity> {
154156
// find the surface entity, if it is an image, we will render to that image
155157
// otherwise we will render to the window
156-
let target = match p_images.get(surface_entity) {
157-
Ok(p_image) => RenderTarget::Image(ImageRenderTarget::from(p_image.handle.clone())),
158+
let (target, physical_width, physical_height) = match p_images.get(surface_entity) {
159+
Ok(p_image) => (
160+
RenderTarget::Image(ImageRenderTarget::from(p_image.handle.clone())),
161+
p_image.size.width,
162+
p_image.size.height,
163+
),
158164
Err(QueryEntityError::QueryDoesNotMatch(..)) => {
159-
RenderTarget::Window(WindowRef::Entity(surface_entity))
165+
let window = windows
166+
.get(surface_entity)
167+
.map_err(|_| ProcessingError::SurfaceNotFound)?;
168+
(
169+
RenderTarget::Window(WindowRef::Entity(surface_entity)),
170+
window.resolution.physical_width(),
171+
window.resolution.physical_height(),
172+
)
160173
}
161174
Err(_) => return Err(ProcessingError::SurfaceNotFound),
162175
};
@@ -165,14 +178,14 @@ pub fn create(
165178
let render_layer = layer_manager.allocate();
166179

167180
let size = Extent3d {
168-
width,
169-
height,
181+
width: physical_width,
182+
height: physical_height,
170183
depth_or_array_layers: 1,
171184
};
172185
let readback_buffer = create_readback_buffer(
173186
&render_device,
174-
width,
175-
height,
187+
physical_width,
188+
physical_height,
176189
texture_format,
177190
"Graphics Readback Buffer",
178191
)
@@ -241,6 +254,39 @@ pub fn resize(
241254
}
242255
}
243256

257+
pub fn sync_to_surface(
258+
mut graphics_query: Query<(&mut Graphics, &RenderTarget)>,
259+
windows: Query<&Window, (With<Surface>, Changed<Window>)>,
260+
render_device: Res<RenderDevice>,
261+
) {
262+
for (mut graphics, target) in graphics_query.iter_mut() {
263+
let RenderTarget::Window(WindowRef::Entity(surface_entity)) = *target else {
264+
continue;
265+
};
266+
let Ok(window) = windows.get(surface_entity) else {
267+
continue;
268+
};
269+
let physical_w = window.resolution.physical_width();
270+
let physical_h = window.resolution.physical_height();
271+
if graphics.size.width == physical_w && graphics.size.height == physical_h {
272+
continue;
273+
}
274+
graphics.size = Extent3d {
275+
width: physical_w,
276+
height: physical_h,
277+
depth_or_array_layers: 1,
278+
};
279+
graphics.readback_buffer = create_readback_buffer(
280+
&render_device,
281+
physical_w,
282+
physical_h,
283+
graphics.texture_format,
284+
"Graphics Readback Buffer",
285+
)
286+
.expect("Failed to reallocate readback buffer");
287+
}
288+
}
289+
244290
pub fn mode_3d(
245291
In(entity): In<Entity>,
246292
mut projections: Query<&mut Projection>,

crates/processing_render/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,14 @@ pub fn surface_resize(graphics_entity: Entity, width: u32, height: u32) -> error
249249
})
250250
}
251251

252+
pub fn surface_set_pixel_density(entity: Entity, density: f32) -> error::Result<()> {
253+
app_mut(|app| {
254+
app.world_mut()
255+
.run_system_cached_with(surface::set_pixel_density, (entity, density))
256+
.unwrap()
257+
})
258+
}
259+
252260
/// Create a new graphics surface for rendering.
253261
pub fn graphics_create(
254262
surface_entity: Entity,

crates/processing_render/src/surface.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,13 @@ fn spawn_surface(
9494
let window_wrapper = WindowWrapper::new(glfw_window);
9595
let handle_wrapper = RawHandleWrapper::new(&window_wrapper)?;
9696

97+
let physical_width = (width as f32 * scale_factor) as u32;
98+
let physical_height = (height as f32 * scale_factor) as u32;
99+
97100
Ok(commands
98101
.spawn((
99102
Window {
100-
resolution: WindowResolution::new(width, height)
103+
resolution: WindowResolution::new(physical_width, physical_height)
101104
.with_scale_factor_override(scale_factor),
102105
..default()
103106
},
@@ -362,8 +365,28 @@ pub fn resize(
362365
mut windows: Query<&mut Window>,
363366
) -> Result<()> {
364367
if let Ok(mut window) = windows.get_mut(window_entity) {
365-
window.resolution.set_physical_resolution(width, height);
368+
let scale = window.resolution.scale_factor();
369+
let physical_w = (width as f32 * scale) as u32;
370+
let physical_h = (height as f32 * scale) as u32;
371+
window.resolution.set_physical_resolution(physical_w, physical_h);
372+
Ok(())
373+
} else {
374+
Err(error::ProcessingError::SurfaceNotFound)
375+
}
376+
}
366377

378+
pub fn set_pixel_density(
379+
In((window_entity, density)): In<(Entity, f32)>,
380+
mut windows: Query<&mut Window>,
381+
) -> Result<()> {
382+
if let Ok(mut window) = windows.get_mut(window_entity) {
383+
let logical_w = window.resolution.width();
384+
let logical_h = window.resolution.height();
385+
window.resolution.set_scale_factor_override(Some(density));
386+
window.resolution.set_physical_resolution(
387+
(logical_w * density) as u32,
388+
(logical_h * density) as u32,
389+
);
367390
Ok(())
368391
} else {
369392
Err(error::ProcessingError::SurfaceNotFound)

0 commit comments

Comments
 (0)