summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--core/src/image.rs32
-rw-r--r--tiny_skia/src/raster.rs7
-rw-r--r--wgpu/src/image.rs69
-rw-r--r--widget/src/image.rs2
4 files changed, 84 insertions, 26 deletions
diff --git a/core/src/image.rs b/core/src/image.rs
index 85d9d475..9a6011a3 100644
--- a/core/src/image.rs
+++ b/core/src/image.rs
@@ -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 {
@@ -56,6 +76,7 @@ impl Handle {
Handle {
id: hasher.finish(),
data,
+ filter: TextureFilter::default(),
}
}
@@ -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
diff --git a/tiny_skia/src/raster.rs b/tiny_skia/src/raster.rs
index d13b1167..95f74ad1 100644
--- a/tiny_skia/src/raster.rs
+++ b/tiny_skia/src/raster.rs
@@ -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,
diff --git a/wgpu/src/image.rs b/wgpu/src/image.rs
index 553ba330..a0fe7e83 100644
--- a/wgpu/src/image.rs
+++ b/wgpu/src/image.rs
@@ -7,6 +7,7 @@ mod raster;
mod vector;
use atlas::Atlas;
+use iced_graphics::core::image::{TextureFilter, FilterMethod};
use crate::core::{Rectangle, Size};
use crate::graphics::Transformation;
@@ -14,6 +15,7 @@ use crate::layer;
use crate::Buffer;
use std::cell::RefCell;
+use std::collections::HashMap;
use std::mem;
use bytemuck::{Pod, Zeroable};
@@ -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,
@@ -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 {
@@ -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();
@@ -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()),
);
}
}
@@ -405,7 +424,7 @@ impl Pipeline {
[bounds.x, bounds.y],
size,
atlas_entry,
- instances,
+ instances.entry(TextureFilter::default()).or_insert(Vec::new()),
);
}
}
@@ -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>(
diff --git a/widget/src/image.rs b/widget/src/image.rs
index a0e89920..9f0b16b7 100644
--- a/widget/src/image.rs
+++ b/widget/src/image.rs
@@ -13,7 +13,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> {