Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HiDPI support #40

Merged
merged 7 commits into from
Nov 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions core/src/rectangle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,16 @@ impl Rectangle<f32> {
&& point.y <= self.y + self.height
}
}

impl std::ops::Mul<f32> for Rectangle<u32> {
type Output = Self;

fn mul(self, scale: f32) -> Self {
Self {
x: (self.x as f32 * scale).round() as u32,
y: (self.y as f32 * scale).round() as u32,
width: (self.width as f32 * scale).round() as u32,
height: (self.height as f32 * scale).round() as u32,
}
}
}
9 changes: 8 additions & 1 deletion native/src/renderer/windowed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,15 @@ pub trait Target {
window: &W,
width: u16,
height: u16,
dpi: f32,
renderer: &Self::Renderer,
) -> Self;

fn resize(&mut self, width: u16, height: u16, renderer: &Self::Renderer);
fn resize(
&mut self,
width: u16,
height: u16,
dpi: f32,
renderer: &Self::Renderer,
);
}
58 changes: 43 additions & 15 deletions wgpu/src/quad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::mem;
pub struct Pipeline {
pipeline: wgpu::RenderPipeline,
constants: wgpu::BindGroup,
transform: wgpu::Buffer,
constants_buffer: wgpu::Buffer,
vertices: wgpu::Buffer,
indices: wgpu::Buffer,
instances: wgpu::Buffer,
Expand All @@ -23,20 +23,20 @@ impl Pipeline {
}],
});

let transform = device
let constants_buffer = device
.create_buffer_mapped(
16,
1,
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
)
.fill_from_slice(Transformation::identity().as_ref());
.fill_from_slice(&[Uniforms::default()]);

let constants = device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &constant_layout,
bindings: &[wgpu::Binding {
binding: 0,
resource: wgpu::BindingResource::Buffer {
buffer: &transform,
range: 0..64,
buffer: &constants_buffer,
range: 0..std::mem::size_of::<Uniforms>() as u64,
},
}],
});
Expand Down Expand Up @@ -124,7 +124,7 @@ impl Pipeline {
},
wgpu::VertexAttributeDescriptor {
shader_location: 4,
format: wgpu::VertexFormat::Uint,
format: wgpu::VertexFormat::Float,
offset: 4 * (2 + 2 + 4),
},
],
Expand All @@ -151,7 +151,7 @@ impl Pipeline {
Pipeline {
pipeline,
constants,
transform,
constants_buffer,
vertices,
indices,
instances,
Expand All @@ -164,19 +164,22 @@ impl Pipeline {
encoder: &mut wgpu::CommandEncoder,
instances: &[Quad],
transformation: Transformation,
scale: f32,
bounds: Rectangle<u32>,
target: &wgpu::TextureView,
) {
let transform_buffer = device
.create_buffer_mapped(16, wgpu::BufferUsage::COPY_SRC)
.fill_from_slice(transformation.as_ref());
let uniforms = Uniforms::new(transformation, scale);

let constants_buffer = device
.create_buffer_mapped(1, wgpu::BufferUsage::COPY_SRC)
.fill_from_slice(&[uniforms]);

encoder.copy_buffer_to_buffer(
&transform_buffer,
&constants_buffer,
0,
&self.transform,
&self.constants_buffer,
0,
16 * 4,
std::mem::size_of::<Uniforms>() as u64,
);

let mut i = 0;
Expand Down Expand Up @@ -271,9 +274,34 @@ pub struct Quad {
pub position: [f32; 2],
pub scale: [f32; 2],
pub color: [f32; 4],
pub border_radius: u32,
pub border_radius: f32,
}

impl Quad {
const MAX: usize = 100_000;
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
struct Uniforms {
transform: [f32; 16],
scale: f32,
}

impl Uniforms {
fn new(transformation: Transformation, scale: f32) -> Uniforms {
Self {
transform: *transformation.as_ref(),
scale,
}
}
}

impl Default for Uniforms {
fn default() -> Self {
Self {
transform: *Transformation::identity().as_ref(),
scale: 1.0,
}
}
}
56 changes: 40 additions & 16 deletions wgpu/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ impl Renderer {
log::debug!("Drawing");

let (width, height) = target.dimensions();
let dpi = target.dpi();
let transformation = target.transformation();
let frame = target.next_frame();

Expand Down Expand Up @@ -137,7 +138,7 @@ impl Renderer {
self.draw_overlay(overlay, &mut layers);

for layer in layers {
self.flush(transformation, &layer, &mut encoder, &frame.view);
self.flush(dpi, transformation, &layer, &mut encoder, &frame.view);
}

self.queue.submit(&[encoder.finish()]);
Expand Down Expand Up @@ -190,7 +191,10 @@ impl Renderer {

layer.text.push(Section {
text: &content,
screen_position: (x, y),
screen_position: (
x - layer.offset.x as f32,
y - layer.offset.y as f32,
),
bounds: (bounds.width, bounds.height),
scale: wgpu_glyph::Scale { x: *size, y: *size },
color: color.into_linear(),
Expand Down Expand Up @@ -225,6 +229,7 @@ impl Renderer {
background,
border_radius,
} => {
// TODO: Move some of this computations to the GPU (?)
layer.quads.push(Quad {
position: [
bounds.x - layer.offset.x as f32,
Expand All @@ -234,7 +239,7 @@ impl Renderer {
color: match background {
Background::Color(color) => color.into_linear(),
},
border_radius: u32::from(*border_radius),
border_radius: *border_radius as f32,
});
}
Primitive::Image { path, bounds } => {
Expand Down Expand Up @@ -308,35 +313,40 @@ impl Renderer {

fn flush(
&mut self,
dpi: f32,
transformation: Transformation,
layer: &Layer,
encoder: &mut wgpu::CommandEncoder,
target: &wgpu::TextureView,
) {
let translated = transformation
* Transformation::translate(
-(layer.offset.x as f32),
-(layer.offset.y as f32),
);
let bounds = layer.bounds * dpi;

if layer.quads.len() > 0 {
self.quad_pipeline.draw(
&mut self.device,
encoder,
&layer.quads,
transformation,
layer.bounds,
dpi,
bounds,
target,
);
}

if layer.images.len() > 0 {
let translated_and_scaled = transformation
* Transformation::scale(dpi, dpi)
* Transformation::translate(
-(layer.offset.x as f32),
-(layer.offset.y as f32),
);

self.image_pipeline.draw(
&mut self.device,
encoder,
&layer.images,
translated,
layer.bounds,
translated_and_scaled,
bounds,
target,
);
}
Expand All @@ -345,6 +355,20 @@ impl Renderer {
let mut glyph_brush = self.glyph_brush.borrow_mut();

for text in layer.text.iter() {
// Target physical coordinates directly to avoid blurry text
let text = Section {
screen_position: (
text.screen_position.0 * dpi,
text.screen_position.1 * dpi,
),
bounds: (text.bounds.0 * dpi, text.bounds.1 * dpi),
scale: wgpu_glyph::Scale {
x: text.scale.x * dpi,
y: text.scale.y * dpi,
},
..*text
};

glyph_brush.queue(text);
}

Expand All @@ -353,12 +377,12 @@ impl Renderer {
&mut self.device,
encoder,
target,
translated.into(),
transformation.into(),
wgpu_glyph::Region {
x: layer.bounds.x,
y: layer.bounds.y,
width: layer.bounds.width,
height: layer.bounds.height,
x: bounds.x,
y: bounds.y,
width: bounds.width,
height: bounds.height,
},
)
.expect("Draw text");
Expand Down
16 changes: 15 additions & 1 deletion wgpu/src/renderer/target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub struct Target {
surface: wgpu::Surface,
width: u16,
height: u16,
dpi: f32,
transformation: Transformation,
swap_chain: wgpu::SwapChain,
}
Expand All @@ -15,6 +16,10 @@ impl Target {
(self.width, self.height)
}

pub fn dpi(&self) -> f32 {
self.dpi
}

pub fn transformation(&self) -> Transformation {
self.transformation
}
Expand All @@ -31,6 +36,7 @@ impl iced_native::renderer::Target for Target {
window: &W,
width: u16,
height: u16,
dpi: f32,
renderer: &Renderer,
) -> Target {
let surface = wgpu::Surface::create(window);
Expand All @@ -41,14 +47,22 @@ impl iced_native::renderer::Target for Target {
surface,
width,
height,
dpi,
transformation: Transformation::orthographic(width, height),
swap_chain,
}
}

fn resize(&mut self, width: u16, height: u16, renderer: &Renderer) {
fn resize(
&mut self,
width: u16,
height: u16,
dpi: f32,
renderer: &Renderer,
) {
self.width = width;
self.height = height;
self.dpi = dpi;
self.transformation = Transformation::orthographic(width, height);
self.swap_chain =
new_swap_chain(&self.surface, width, height, &renderer.device);
Expand Down
2 changes: 1 addition & 1 deletion wgpu/src/renderer/widget/checkbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ impl checkbox::Renderer for Renderer {
a: 1.0,
}
}),
border_radius: 6,
border_radius: 5,
},
);

Expand Down
7 changes: 5 additions & 2 deletions wgpu/src/renderer/widget/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ use wgpu_glyph::{GlyphCruncher, Section};
use std::cell::RefCell;
use std::f32;

// TODO: Obtain from renderer configuration
const DEFAULT_TEXT_SIZE: f32 = 20.0;

impl text::Renderer for Renderer {
fn node(&self, text: &Text) -> Node {
let glyph_brush = self.glyph_brush.clone();
Expand All @@ -18,7 +21,7 @@ impl text::Renderer for Renderer {
// I noticed that the first measure is the one that matters in
// practice. Here, we use a RefCell to store the cached measurement.
let measure = RefCell::new(None);
let size = text.size.map(f32::from).unwrap_or(20.0);
let size = text.size.map(f32::from).unwrap_or(DEFAULT_TEXT_SIZE);

let style = Style::default().width(text.width);

Expand Down Expand Up @@ -71,7 +74,7 @@ impl text::Renderer for Renderer {
(
Primitive::Text {
content: text.content.clone(),
size: f32::from(text.size.unwrap_or(20)),
size: text.size.map(f32::from).unwrap_or(DEFAULT_TEXT_SIZE),
bounds: layout.bounds(),
color: text.color.unwrap_or(Color::BLACK),
horizontal_alignment: text.horizontal_alignment,
Expand Down
8 changes: 2 additions & 6 deletions wgpu/src/shader/quad.frag
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
layout(location = 0) in vec4 v_Color;
layout(location = 1) in vec2 v_Pos;
layout(location = 2) in vec2 v_Scale;
layout(location = 3) in flat uint v_BorderRadius;
layout(location = 3) in float v_BorderRadius;

layout(location = 0) out vec4 o_Color;

Expand All @@ -27,11 +27,7 @@ float rounded(in vec2 frag_coord, in vec2 position, in vec2 size, float radius,
}

void main() {
float radius_alpha = 1.0;

if(v_BorderRadius > 0.0) {
radius_alpha = rounded(gl_FragCoord.xy, v_Pos, v_Scale, v_BorderRadius, 0.5);
}
float radius_alpha = rounded(gl_FragCoord.xy, v_Pos, v_Scale, v_BorderRadius, 0.5);

o_Color = vec4(v_Color.xyz, v_Color.w * radius_alpha);
}
Binary file modified wgpu/src/shader/quad.frag.spv
Binary file not shown.
Loading