Skip to content

Commit 4e433c1

Browse files
authored
DPI and color fixes (#122)
1 parent ff82009 commit 4e433c1

12 files changed

Lines changed: 132 additions & 23 deletions

File tree

crates/processing_glfw/src/lib.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ pub struct GlfwContext {
1414
window: PWindow,
1515
events: GlfwReceiver<(f64, WindowEvent)>,
1616
surface: Option<Entity>,
17-
scale_factor: f32,
1817
}
1918

2019
impl GlfwContext {
@@ -31,14 +30,11 @@ impl GlfwContext {
3130
window.set_all_polling(true);
3231
window.show();
3332

34-
let (scale_factor, _) = window.get_content_scale();
35-
3633
Ok(Self {
3734
glfw,
3835
window,
3936
events,
4037
surface: None,
41-
scale_factor,
4238
})
4339
}
4440

@@ -127,8 +123,7 @@ impl GlfwContext {
127123
return false;
128124
}
129125
WindowEvent::CursorPos(x, y) => {
130-
let s = self.scale_factor;
131-
input_set_mouse_move(surface, x as f32 / s, y as f32 / s).unwrap();
126+
input_set_mouse_move(surface, x as f32, y as f32).unwrap();
132127
}
133128
WindowEvent::MouseButton(button, action, _mods) => {
134129
if let Some(btn) = glfw_button_to_bevy(button) {
@@ -182,6 +177,11 @@ impl GlfwContext {
182177
true
183178
}
184179

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

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: 55 additions & 9 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>,
@@ -396,7 +442,7 @@ pub fn begin_draw(In(entity): In<Entity>, mut state_query: Query<&mut RenderStat
396442
let mut state = state_query
397443
.get_mut(entity)
398444
.map_err(|_| ProcessingError::GraphicsNotFound)?;
399-
state.reset();
445+
state.begin_frame();
400446
Ok(())
401447
}
402448

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/render/mesh_builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ impl<'a> MeshBuilder<'a> {
3636
if let Some(VertexAttributeValues::Float32x4(colors)) =
3737
self.mesh.attribute_mut(Mesh::ATTRIBUTE_COLOR)
3838
{
39-
colors.push(self.color.to_srgba().to_f32_array());
39+
colors.push(self.color.to_linear().to_f32_array());
4040
}
4141

4242
if let Some(VertexAttributeValues::Float32x3(normals)) =

crates/processing_render/src/render/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,11 @@ impl RenderState {
122122
self.shape_builder = None;
123123
}
124124

125+
pub fn begin_frame(&mut self) {
126+
self.transform = TransformStack::new();
127+
self.shape_builder = None;
128+
}
129+
125130
pub fn fill_is_transparent(&self) -> bool {
126131
self.fill_color.map(|c| c.alpha() < 1.0).unwrap_or(false)
127132
}

crates/processing_render/src/render/primitive/quad.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ fn simple_quad(
7070
if let Some(VertexAttributeValues::Float32x4(colors)) =
7171
mesh.attribute_mut(Mesh::ATTRIBUTE_COLOR)
7272
{
73-
let color_array = color.to_srgba().to_f32_array();
73+
let color_array = color.to_linear().to_f32_array();
7474
for _ in 0..4 {
7575
colors.push(color_array);
7676
}

crates/processing_render/src/render/primitive/rect.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ fn simple_rect(mesh: &mut Mesh, x: f32, y: f32, w: f32, h: f32, color: Color) {
8787
if let Some(VertexAttributeValues::Float32x4(colors)) =
8888
mesh.attribute_mut(Mesh::ATTRIBUTE_COLOR)
8989
{
90-
let color_array = color.to_srgba().to_f32_array();
90+
let color_array = color.to_linear().to_f32_array();
9191
for _ in 0..4 {
9292
colors.push(color_array);
9393
}

crates/processing_render/src/render/primitive/shape.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ fn push_triangle(
497497
positions.push([x3, y3, 0.0]);
498498
}
499499

500-
let color_array = color.to_srgba().to_f32_array();
500+
let color_array = color.to_linear().to_f32_array();
501501
if let Some(VertexAttributeValues::Float32x4(colors)) =
502502
mesh.attribute_mut(Mesh::ATTRIBUTE_COLOR)
503503
{
@@ -556,7 +556,7 @@ fn push_quad(
556556
positions.push([x4, y4, 0.0]);
557557
}
558558

559-
let color_array = color.to_srgba().to_f32_array();
559+
let color_array = color.to_linear().to_f32_array();
560560
if let Some(VertexAttributeValues::Float32x4(colors)) =
561561
mesh.attribute_mut(Mesh::ATTRIBUTE_COLOR)
562562
{

0 commit comments

Comments
 (0)