Skip to content

Commit

Permalink
Implement texture filtering options
Browse files Browse the repository at this point in the history
  • Loading branch information
Remmirad committed May 31, 2023
1 parent fcb1b45 commit a12a656
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 26 deletions.
32 changes: 32 additions & 0 deletions core/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,31 @@ use std::hash::{Hash, Hasher as _};
use std::path::PathBuf;
use std::sync::Arc;

/// Image filter method
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FilterMethod {
/// Bilinear interpolation
#[default]
Linear,
/// Nearest Neighbor
Nearest,
}

/// Texture filter settings
#[derive(Default, Debug, Clone, PartialEq, Eq, Hash)]
pub struct TextureFilter {
/// Filter for scaling the image down.
pub min: FilterMethod,
/// Filter for scaling the image up.
pub mag: FilterMethod,
}

/// A handle of some image data.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Handle {
id: u64,
data: Data,
filter: TextureFilter,
}

impl Handle {
Expand Down Expand Up @@ -56,6 +76,7 @@ impl Handle {
Handle {
id: hasher.finish(),
data,
filter: TextureFilter::default(),
}
}

Expand All @@ -68,6 +89,17 @@ impl Handle {
pub fn data(&self) -> &Data {
&self.data
}

/// Returns a reference to the [`TextureFilter`].
pub fn filter(&self) -> &TextureFilter {
&self.filter
}

/// Sets the texture filtering methods.
pub fn set_filter(mut self, filter: TextureFilter) -> Self {
self.filter = filter;
self
}
}

impl<T> From<T> for Handle
Expand Down
7 changes: 6 additions & 1 deletion tiny_skia/src/raster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,17 @@ impl Pipeline {

let transform = transform.pre_scale(width_scale, height_scale);

let quality = match handle.filter().mag {
raster::FilterMethod::Linear => tiny_skia::FilterQuality::Bilinear,
raster::FilterMethod::Nearest => tiny_skia::FilterQuality::Nearest,
};

pixels.draw_pixmap(
(bounds.x / width_scale) as i32,
(bounds.y / height_scale) as i32,
image,
&tiny_skia::PixmapPaint {
quality: tiny_skia::FilterQuality::Bilinear,
quality: quality,
..Default::default()
},
transform,
Expand Down
69 changes: 45 additions & 24 deletions wgpu/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ mod raster;
mod vector;

use atlas::Atlas;
use iced_graphics::core::image::{TextureFilter, FilterMethod};

use crate::core::{Rectangle, Size};
use crate::graphics::Transformation;
use crate::layer;
use crate::Buffer;

use std::cell::RefCell;
use std::collections::HashMap;
use std::mem;

use bytemuck::{Pod, Zeroable};
Expand All @@ -37,7 +39,7 @@ pub struct Pipeline {
pipeline: wgpu::RenderPipeline,
vertices: wgpu::Buffer,
indices: wgpu::Buffer,
sampler: wgpu::Sampler,
sampler: HashMap<TextureFilter,wgpu::Sampler>,
texture: wgpu::BindGroup,
texture_version: usize,
texture_atlas: Atlas,
Expand Down Expand Up @@ -142,15 +144,32 @@ impl Pipeline {
pub fn new(device: &wgpu::Device, format: wgpu::TextureFormat) -> Self {
use wgpu::util::DeviceExt;

let sampler = device.create_sampler(&wgpu::SamplerDescriptor {
address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge,
address_mode_w: wgpu::AddressMode::ClampToEdge,
mag_filter: wgpu::FilterMode::Linear,
min_filter: wgpu::FilterMode::Linear,
mipmap_filter: wgpu::FilterMode::Linear,
..Default::default()
});
let to_wgpu = |method: FilterMethod| {
match method {
FilterMethod::Linear => wgpu::FilterMode::Linear,
FilterMethod::Nearest => wgpu::FilterMode::Nearest,
}
};

let mut sampler = HashMap::new();

let filter = [FilterMethod::Linear, FilterMethod::Nearest];
for min in 0..filter.len() {
for mag in 0..filter.len() {
let _ = sampler.insert(TextureFilter {min: filter[min], mag: filter[mag]},
device.create_sampler(&wgpu::SamplerDescriptor {
address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge,
address_mode_w: wgpu::AddressMode::ClampToEdge,
mag_filter: to_wgpu(filter[mag]),
min_filter: to_wgpu(filter[min]),
mipmap_filter: wgpu::FilterMode::Linear,
..Default::default()
}
));
}
}


let constant_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
Expand Down Expand Up @@ -355,7 +374,7 @@ impl Pipeline {
#[cfg(feature = "tracing")]
let _ = info_span!("Wgpu::Image", "DRAW").entered();

let instances: &mut Vec<Instance> = &mut Vec::new();
let instances: &mut HashMap<TextureFilter,Vec<Instance>> = &mut HashMap::new();

#[cfg(feature = "image")]
let mut raster_cache = self.raster_cache.borrow_mut();
Expand All @@ -377,7 +396,7 @@ impl Pipeline {
[bounds.x, bounds.y],
[bounds.width, bounds.height],
atlas_entry,
instances,
instances.entry(handle.filter().clone()).or_insert(Vec::new()),
);
}
}
Expand Down Expand Up @@ -405,7 +424,7 @@ impl Pipeline {
[bounds.x, bounds.y],
size,
atlas_entry,
instances,
instances.entry(TextureFilter::default()).or_insert(Vec::new()),
);
}
}
Expand Down Expand Up @@ -438,18 +457,20 @@ impl Pipeline {
self.texture_version = texture_version;
}

if self.layers.len() <= self.prepare_layer {
self.layers.push(Layer::new(
device,
&self.constant_layout,
&self.sampler,
));
for (filter, instances) in instances.iter_mut() {
if self.layers.len() <= self.prepare_layer {
self.layers.push(Layer::new(
device,
&self.constant_layout,
&self.sampler.get(filter).expect("Sampler is registered"),
));
}

let layer = &mut self.layers[self.prepare_layer];
layer.prepare(device, queue, &instances, transformation);

self.prepare_layer += 1;
}

let layer = &mut self.layers[self.prepare_layer];
layer.prepare(device, queue, instances, transformation);

self.prepare_layer += 1;
}

pub fn render<'a>(
Expand Down
2 changes: 1 addition & 1 deletion widget/src/image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::core::{

use std::hash::Hash;

pub use image::Handle;
pub use image::{Handle, TextureFilter, FilterMethod};

/// Creates a new [`Viewer`] with the given image `Handle`.
pub fn viewer<Handle>(handle: Handle) -> Viewer<Handle> {
Expand Down

0 comments on commit a12a656

Please sign in to comment.