Specify deifferent minification and magnification filters (#2224)
* Specify deifferent minification and magnification filters * Fixes * Update changelogs * Doctest fixes * Add deprecation notice for RetainedImage::with_texture_filter
This commit is contained in:
parent
8e79a5a8ae
commit
34e6e12f00
19 changed files with 147 additions and 97 deletions
|
@ -12,6 +12,7 @@ NOTE: [`epaint`](crates/epaint/CHANGELOG.md), [`eframe`](crates/eframe/CHANGELOG
|
|||
* Added `Context::os/Context::set_os` to query/set what operating system egui believes it is running on ([#2202](https://github.com/emilk/egui/pull/2202)).
|
||||
* Added `Button::shortcut_text` for showing keyboard shortcuts in menu buttons ([#2202](https://github.com/emilk/egui/pull/2202)).
|
||||
* Added `egui::KeyboardShortcut` for showing keyboard shortcuts in menu buttons ([#2202](https://github.com/emilk/egui/pull/2202)).
|
||||
* Texture loading now takes a `TexureOptions` with minification and magnification filters ([#2224](https://github.com/emilk/egui/pull/2224)).
|
||||
|
||||
### Fixed 🐛
|
||||
* ⚠️ BREAKING: Fix text being too small ([#2069](https://github.com/emilk/egui/pull/2069)).
|
||||
|
|
|
@ -136,7 +136,7 @@ pub struct Renderer {
|
|||
/// sampler.
|
||||
textures: HashMap<egui::TextureId, (Option<wgpu::Texture>, wgpu::BindGroup)>,
|
||||
next_user_texture_id: u64,
|
||||
samplers: HashMap<egui::TextureFilter, wgpu::Sampler>,
|
||||
samplers: HashMap<egui::TextureOptions, wgpu::Sampler>,
|
||||
|
||||
/// Storage for use by [`egui::PaintCallback`]'s that need to store resources such as render
|
||||
/// pipelines that must have the lifetime of the renderpass.
|
||||
|
@ -530,8 +530,8 @@ impl Renderer {
|
|||
});
|
||||
let sampler = self
|
||||
.samplers
|
||||
.entry(image_delta.filter)
|
||||
.or_insert_with(|| create_sampler(image_delta.filter, device));
|
||||
.entry(image_delta.options)
|
||||
.or_insert_with(|| create_sampler(image_delta.options, device));
|
||||
let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
|
||||
label,
|
||||
layout: &self.texture_bind_group_layout,
|
||||
|
@ -790,15 +790,22 @@ impl Renderer {
|
|||
}
|
||||
}
|
||||
|
||||
fn create_sampler(filter: egui::TextureFilter, device: &wgpu::Device) -> wgpu::Sampler {
|
||||
let wgpu_filter = match filter {
|
||||
fn create_sampler(options: egui::TextureOptions, device: &wgpu::Device) -> wgpu::Sampler {
|
||||
let mag_filter = match options.magnification {
|
||||
egui::TextureFilter::Nearest => wgpu::FilterMode::Nearest,
|
||||
egui::TextureFilter::Linear => wgpu::FilterMode::Linear,
|
||||
};
|
||||
let min_filter = match options.minification {
|
||||
egui::TextureFilter::Nearest => wgpu::FilterMode::Nearest,
|
||||
egui::TextureFilter::Linear => wgpu::FilterMode::Linear,
|
||||
};
|
||||
device.create_sampler(&wgpu::SamplerDescriptor {
|
||||
label: Some(&format!("egui sampler ({:?})", filter)),
|
||||
mag_filter: wgpu_filter,
|
||||
min_filter: wgpu_filter,
|
||||
label: Some(&format!(
|
||||
"egui sampler (mag: {:?}, min {:?})",
|
||||
mag_filter, min_filter
|
||||
)),
|
||||
mag_filter,
|
||||
min_filter,
|
||||
..Default::default()
|
||||
})
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
|||
input_state::*, layers::GraphicLayers, memory::Options, os::OperatingSystem,
|
||||
output::FullOutput, TextureHandle, *,
|
||||
};
|
||||
use epaint::{mutex::*, stats::*, text::Fonts, textures::TextureFilter, TessellationOptions, *};
|
||||
use epaint::{mutex::*, stats::*, text::Fonts, TessellationOptions, *};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
@ -800,7 +800,7 @@ impl Context {
|
|||
/// ui.ctx().load_texture(
|
||||
/// "my-image",
|
||||
/// egui::ColorImage::example(),
|
||||
/// egui::TextureFilter::Linear
|
||||
/// Default::default()
|
||||
/// )
|
||||
/// });
|
||||
///
|
||||
|
@ -815,7 +815,7 @@ impl Context {
|
|||
&self,
|
||||
name: impl Into<String>,
|
||||
image: impl Into<ImageData>,
|
||||
filter: TextureFilter,
|
||||
options: TextureOptions,
|
||||
) -> TextureHandle {
|
||||
let name = name.into();
|
||||
let image = image.into();
|
||||
|
@ -829,7 +829,7 @@ impl Context {
|
|||
max_texture_side
|
||||
);
|
||||
let tex_mngr = self.tex_manager();
|
||||
let tex_id = tex_mngr.write().alloc(name, image, filter);
|
||||
let tex_id = tex_mngr.write().alloc(name, image, options);
|
||||
TextureHandle::new(tex_mngr, tex_id)
|
||||
}
|
||||
|
||||
|
|
|
@ -332,7 +332,7 @@ pub use epaint::hex_color;
|
|||
pub use epaint::{
|
||||
color, mutex,
|
||||
text::{FontData, FontDefinitions, FontFamily, FontId, FontTweak},
|
||||
textures::{TextureFilter, TexturesDelta},
|
||||
textures::{TextureFilter, TextureOptions, TexturesDelta},
|
||||
ClippedPrimitive, Color32, ColorImage, FontImage, ImageData, Mesh, PaintCallback,
|
||||
PaintCallbackInfo, Rgba, Rounding, Shape, Stroke, TextureHandle, TextureId,
|
||||
};
|
||||
|
|
|
@ -1553,7 +1553,7 @@ impl Ui {
|
|||
/// ui.ctx().load_texture(
|
||||
/// "my-image",
|
||||
/// egui::ColorImage::example(),
|
||||
/// egui::TextureFilter::Linear
|
||||
/// Default::default()
|
||||
/// )
|
||||
/// });
|
||||
///
|
||||
|
|
|
@ -18,7 +18,7 @@ use emath::Rot2;
|
|||
/// ui.ctx().load_texture(
|
||||
/// "my-image",
|
||||
/// egui::ColorImage::example(),
|
||||
/// egui::TextureFilter::Linear
|
||||
/// Default::default()
|
||||
/// )
|
||||
/// });
|
||||
///
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use egui::{color::*, widgets::color_picker::show_color, TextureFilter, *};
|
||||
use egui::{color::*, widgets::color_picker::show_color, TextureOptions, *};
|
||||
|
||||
const GRADIENT_SIZE: Vec2 = vec2(256.0, 18.0);
|
||||
|
||||
|
@ -372,7 +372,7 @@ impl TextureManager {
|
|||
size: [width, height],
|
||||
pixels,
|
||||
},
|
||||
TextureFilter::Linear,
|
||||
TextureOptions::LINEAR,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -596,11 +596,8 @@ impl ItemsDemo {
|
|||
};
|
||||
|
||||
let texture: &egui::TextureHandle = self.texture.get_or_insert_with(|| {
|
||||
ui.ctx().load_texture(
|
||||
"plot_demo",
|
||||
egui::ColorImage::example(),
|
||||
egui::TextureFilter::Linear,
|
||||
)
|
||||
ui.ctx()
|
||||
.load_texture("plot_demo", egui::ColorImage::example(), Default::default())
|
||||
});
|
||||
let image = PlotImage::new(
|
||||
texture,
|
||||
|
|
|
@ -115,11 +115,8 @@ impl WidgetGallery {
|
|||
} = self;
|
||||
|
||||
let texture: &egui::TextureHandle = texture.get_or_insert_with(|| {
|
||||
ui.ctx().load_texture(
|
||||
"example",
|
||||
egui::ColorImage::example(),
|
||||
egui::TextureFilter::Linear,
|
||||
)
|
||||
ui.ctx()
|
||||
.load_texture("example", egui::ColorImage::example(), Default::default())
|
||||
});
|
||||
|
||||
ui.add(doc_link_label("Label", "label,heading"));
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use egui::mutex::Mutex;
|
||||
use egui::TextureFilter;
|
||||
use egui::{mutex::Mutex, TextureFilter, TextureOptions};
|
||||
|
||||
/// An image to be shown in egui.
|
||||
///
|
||||
|
@ -13,7 +12,7 @@ pub struct RetainedImage {
|
|||
image: Mutex<egui::ColorImage>,
|
||||
/// Lazily loaded when we have an egui context.
|
||||
texture: Mutex<Option<egui::TextureHandle>>,
|
||||
filter: TextureFilter,
|
||||
options: TextureOptions,
|
||||
}
|
||||
|
||||
impl RetainedImage {
|
||||
|
@ -23,7 +22,7 @@ impl RetainedImage {
|
|||
size: image.size,
|
||||
image: Mutex::new(image),
|
||||
texture: Default::default(),
|
||||
filter: Default::default(),
|
||||
options: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,7 +67,7 @@ impl RetainedImage {
|
|||
Self::from_svg_bytes(debug_name, svg_str.as_bytes())
|
||||
}
|
||||
|
||||
/// Set the texture filter to use for the image.
|
||||
/// Set the texture filters to use for the image.
|
||||
///
|
||||
/// **Note:** If the texture has already been uploaded to the GPU, this will require
|
||||
/// re-uploading the texture with the updated filter.
|
||||
|
@ -76,7 +75,7 @@ impl RetainedImage {
|
|||
/// # Example
|
||||
/// ```rust
|
||||
/// # use egui_extras::RetainedImage;
|
||||
/// # use egui::{Color32, epaint::{ColorImage, textures::TextureFilter}};
|
||||
/// # use egui::{Color32, epaint::{ColorImage, textures::TextureOptions}};
|
||||
/// # let pixels = vec![Color32::BLACK];
|
||||
/// # let color_image = ColorImage {
|
||||
/// # size: [1, 1],
|
||||
|
@ -85,10 +84,10 @@ impl RetainedImage {
|
|||
/// #
|
||||
/// // Upload a pixel art image without it getting blurry when resized
|
||||
/// let image = RetainedImage::from_color_image("my_image", color_image)
|
||||
/// .with_texture_filter(TextureFilter::Nearest);
|
||||
/// .with_options(TextureOptions::NEAREST);
|
||||
/// ```
|
||||
pub fn with_texture_filter(mut self, filter: TextureFilter) -> Self {
|
||||
self.filter = filter;
|
||||
pub fn with_options(mut self, options: TextureOptions) -> Self {
|
||||
self.options = options;
|
||||
|
||||
// If the texture has already been uploaded, this will force it to be re-uploaded with the
|
||||
// updated filter.
|
||||
|
@ -97,6 +96,14 @@ impl RetainedImage {
|
|||
self
|
||||
}
|
||||
|
||||
#[deprecated = "Use with_options instead"]
|
||||
pub fn with_texture_filter(self, filter: TextureFilter) -> Self {
|
||||
self.with_options(TextureOptions {
|
||||
magnification: filter,
|
||||
minification: filter,
|
||||
})
|
||||
}
|
||||
|
||||
/// The size of the image data (number of pixels wide/high).
|
||||
pub fn size(&self) -> [usize; 2] {
|
||||
self.size
|
||||
|
@ -130,7 +137,7 @@ impl RetainedImage {
|
|||
.get_or_insert_with(|| {
|
||||
let image: &mut ColorImage = &mut self.image.lock();
|
||||
let image = std::mem::take(image);
|
||||
ctx.load_texture(&self.debug_name, image, self.filter)
|
||||
ctx.load_texture(&self.debug_name, image, self.options)
|
||||
})
|
||||
.id()
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ fn main() {
|
|||
// Allocate egui's texture id for GL texture
|
||||
let texture_id = egui_glium
|
||||
.painter
|
||||
.register_native_texture(glium_texture, egui::TextureFilter::Linear);
|
||||
.register_native_texture(glium_texture, Default::default());
|
||||
// Setup button image size for reasonable image size for button container.
|
||||
let button_image_size = egui::vec2(32_f32, 32_f32);
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#![allow(deprecated)] // legacy implement_vertex macro
|
||||
#![allow(semicolon_in_expressions_from_macros)] // glium::program! macro
|
||||
|
||||
use egui::{epaint::Primitive, TextureFilter};
|
||||
use egui::{
|
||||
epaint::{textures::TextureFilter, Primitive},
|
||||
TextureOptions,
|
||||
};
|
||||
|
||||
use {
|
||||
egui::{emath::Rect, epaint::Mesh},
|
||||
|
@ -10,7 +13,7 @@ use {
|
|||
index::PrimitiveType,
|
||||
texture::{self, srgb_texture2d::SrgbTexture2d},
|
||||
uniform,
|
||||
uniforms::{MagnifySamplerFilter, SamplerWrapFunction},
|
||||
uniforms::{MagnifySamplerFilter, MinifySamplerFilter, SamplerWrapFunction},
|
||||
},
|
||||
std::rc::Rc,
|
||||
};
|
||||
|
@ -191,14 +194,25 @@ impl Painter {
|
|||
|
||||
if let Some(texture) = self.texture(mesh.texture_id) {
|
||||
// The texture coordinates for text are so that both nearest and linear should work with the egui font texture.
|
||||
let filter = match texture.filter {
|
||||
let mag_filter = match texture.options.magnification {
|
||||
TextureFilter::Nearest => MagnifySamplerFilter::Nearest,
|
||||
TextureFilter::Linear => MagnifySamplerFilter::Linear,
|
||||
};
|
||||
let min_filter = match texture.options.minification {
|
||||
TextureFilter::Nearest => MinifySamplerFilter::Nearest,
|
||||
TextureFilter::Linear => MinifySamplerFilter::Linear,
|
||||
};
|
||||
|
||||
let sampler = texture
|
||||
.glium_texture
|
||||
.sampled()
|
||||
.magnify_filter(mag_filter)
|
||||
.minify_filter(min_filter)
|
||||
.wrap_function(SamplerWrapFunction::Clamp);
|
||||
|
||||
let uniforms = uniform! {
|
||||
u_screen_size: [width_in_points, height_in_points],
|
||||
u_sampler: texture.glium_texture.sampled().magnify_filter(filter).wrap_function(SamplerWrapFunction::Clamp),
|
||||
u_sampler: sampler,
|
||||
};
|
||||
|
||||
// egui outputs colors with premultiplied alpha:
|
||||
|
@ -309,13 +323,13 @@ impl Painter {
|
|||
.main_level()
|
||||
.write(rect, glium_image);
|
||||
|
||||
user_texture.filter = delta.filter;
|
||||
user_texture.options = delta.options;
|
||||
}
|
||||
} else {
|
||||
let gl_texture =
|
||||
SrgbTexture2d::with_format(facade, glium_image, format, mipmaps).unwrap();
|
||||
|
||||
let user_texture = EguiTexture::new(gl_texture.into(), delta.filter);
|
||||
let user_texture = EguiTexture::new(gl_texture.into(), delta.options);
|
||||
self.textures.insert(tex_id, user_texture);
|
||||
}
|
||||
}
|
||||
|
@ -331,12 +345,12 @@ impl Painter {
|
|||
pub fn register_native_texture(
|
||||
&mut self,
|
||||
native: Rc<SrgbTexture2d>,
|
||||
filter: TextureFilter,
|
||||
options: TextureOptions,
|
||||
) -> egui::TextureId {
|
||||
let id = egui::TextureId::User(self.next_native_tex_id);
|
||||
self.next_native_tex_id += 1;
|
||||
|
||||
let texture = EguiTexture::new(native, filter);
|
||||
let texture = EguiTexture::new(native, options);
|
||||
self.textures.insert(id, texture);
|
||||
id
|
||||
}
|
||||
|
@ -345,23 +359,23 @@ impl Painter {
|
|||
&mut self,
|
||||
id: egui::TextureId,
|
||||
replacing: Rc<SrgbTexture2d>,
|
||||
filter: TextureFilter,
|
||||
options: TextureOptions,
|
||||
) {
|
||||
let texture = EguiTexture::new(replacing, filter);
|
||||
let texture = EguiTexture::new(replacing, options);
|
||||
self.textures.insert(id, texture);
|
||||
}
|
||||
}
|
||||
|
||||
struct EguiTexture {
|
||||
glium_texture: Rc<SrgbTexture2d>,
|
||||
filter: TextureFilter,
|
||||
options: TextureOptions,
|
||||
}
|
||||
|
||||
impl EguiTexture {
|
||||
fn new(glium_texture: Rc<SrgbTexture2d>, filter: TextureFilter) -> Self {
|
||||
fn new(glium_texture: Rc<SrgbTexture2d>, options: TextureOptions) -> Self {
|
||||
Self {
|
||||
glium_texture,
|
||||
filter,
|
||||
options,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,17 +20,15 @@ pub use glow::Context;
|
|||
const VERT_SRC: &str = include_str!("shader/vertex.glsl");
|
||||
const FRAG_SRC: &str = include_str!("shader/fragment.glsl");
|
||||
|
||||
pub type TextureFilter = egui::TextureFilter;
|
||||
|
||||
trait TextureFilterExt {
|
||||
fn glow_code(&self) -> u32;
|
||||
}
|
||||
|
||||
impl TextureFilterExt for TextureFilter {
|
||||
impl TextureFilterExt for egui::TextureFilter {
|
||||
fn glow_code(&self) -> u32 {
|
||||
match self {
|
||||
TextureFilter::Linear => glow::LINEAR,
|
||||
TextureFilter::Nearest => glow::NEAREST,
|
||||
egui::TextureFilter::Linear => glow::LINEAR,
|
||||
egui::TextureFilter::Nearest => glow::NEAREST,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -469,7 +467,7 @@ impl Painter {
|
|||
|
||||
let data: &[u8] = bytemuck::cast_slice(image.pixels.as_ref());
|
||||
|
||||
self.upload_texture_srgb(delta.pos, image.size, delta.filter, data);
|
||||
self.upload_texture_srgb(delta.pos, image.size, delta.options, data);
|
||||
}
|
||||
egui::ImageData::Font(image) => {
|
||||
assert_eq!(
|
||||
|
@ -483,7 +481,7 @@ impl Painter {
|
|||
.flat_map(|a| a.to_array())
|
||||
.collect();
|
||||
|
||||
self.upload_texture_srgb(delta.pos, image.size, delta.filter, &data);
|
||||
self.upload_texture_srgb(delta.pos, image.size, delta.options, &data);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -492,7 +490,7 @@ impl Painter {
|
|||
&mut self,
|
||||
pos: Option<[usize; 2]>,
|
||||
[w, h]: [usize; 2],
|
||||
texture_filter: TextureFilter,
|
||||
options: egui::TextureOptions,
|
||||
data: &[u8],
|
||||
) {
|
||||
assert_eq!(data.len(), w * h * 4);
|
||||
|
@ -508,12 +506,12 @@ impl Painter {
|
|||
self.gl.tex_parameter_i32(
|
||||
glow::TEXTURE_2D,
|
||||
glow::TEXTURE_MAG_FILTER,
|
||||
texture_filter.glow_code() as i32,
|
||||
options.magnification.glow_code() as i32,
|
||||
);
|
||||
self.gl.tex_parameter_i32(
|
||||
glow::TEXTURE_2D,
|
||||
glow::TEXTURE_MIN_FILTER,
|
||||
texture_filter.glow_code() as i32,
|
||||
options.minification.glow_code() as i32,
|
||||
);
|
||||
|
||||
self.gl.tex_parameter_i32(
|
||||
|
|
|
@ -13,6 +13,7 @@ All notable changes to the epaint crate will be documented in this file.
|
|||
* Added `epaint::hex_color!` to create `Color32`'s from hex strings under the `color-hex` feature ([#1596](https://github.com/emilk/egui/pull/1596)).
|
||||
* Optimize tessellation of filled circles by 10x or more ([#1616](https://github.com/emilk/egui/pull/1616)).
|
||||
* Added opt-in feature `deadlock_detection` to detect double-lock of mutexes on the same thread ([#1619](https://github.com/emilk/egui/pull/1619)).
|
||||
* Texture loading now takes a `TexureOptions` with minification and magnification filters ([#2224](https://github.com/emilk/egui/pull/2224)).
|
||||
|
||||
|
||||
## 0.18.1 - 2022-05-01
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{textures::TextureFilter, Color32};
|
||||
use crate::{textures::TextureOptions, Color32};
|
||||
|
||||
/// An image stored in RAM.
|
||||
///
|
||||
|
@ -291,7 +291,7 @@ pub struct ImageDelta {
|
|||
/// If [`Self::pos`] is `Some`, this describes a patch of the whole image starting at [`Self::pos`].
|
||||
pub image: ImageData,
|
||||
|
||||
pub filter: TextureFilter,
|
||||
pub options: TextureOptions,
|
||||
|
||||
/// If `None`, set the whole texture to [`Self::image`].
|
||||
///
|
||||
|
@ -301,19 +301,19 @@ pub struct ImageDelta {
|
|||
|
||||
impl ImageDelta {
|
||||
/// Update the whole texture.
|
||||
pub fn full(image: impl Into<ImageData>, filter: TextureFilter) -> Self {
|
||||
pub fn full(image: impl Into<ImageData>, options: TextureOptions) -> Self {
|
||||
Self {
|
||||
image: image.into(),
|
||||
filter,
|
||||
options,
|
||||
pos: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Update a sub-region of an existing texture.
|
||||
pub fn partial(pos: [usize; 2], image: impl Into<ImageData>, filter: TextureFilter) -> Self {
|
||||
pub fn partial(pos: [usize; 2], image: impl Into<ImageData>, options: TextureOptions) -> Self {
|
||||
Self {
|
||||
image: image.into(),
|
||||
filter,
|
||||
options,
|
||||
pos: Some(pos),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use emath::{remap_clamp, Rect};
|
||||
|
||||
use crate::{textures::TextureFilter, FontImage, ImageDelta};
|
||||
use crate::{FontImage, ImageDelta};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
struct Rectu {
|
||||
|
@ -174,16 +174,18 @@ impl TextureAtlas {
|
|||
|
||||
/// Call to get the change to the image since last call.
|
||||
pub fn take_delta(&mut self) -> Option<ImageDelta> {
|
||||
let texture_options = crate::textures::TextureOptions::LINEAR;
|
||||
|
||||
let dirty = std::mem::replace(&mut self.dirty, Rectu::NOTHING);
|
||||
if dirty == Rectu::NOTHING {
|
||||
None
|
||||
} else if dirty == Rectu::EVERYTHING {
|
||||
Some(ImageDelta::full(self.image.clone(), TextureFilter::Linear))
|
||||
Some(ImageDelta::full(self.image.clone(), texture_options))
|
||||
} else {
|
||||
let pos = [dirty.min_x, dirty.min_y];
|
||||
let size = [dirty.max_x - dirty.min_x, dirty.max_y - dirty.min_y];
|
||||
let region = self.image.region(pos, size);
|
||||
Some(ImageDelta::partial(pos, region, TextureFilter::Linear))
|
||||
Some(ImageDelta::partial(pos, region, texture_options))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
emath::NumExt, mutex::RwLock, textures::TextureFilter, ImageData, ImageDelta, TextureId,
|
||||
emath::NumExt, mutex::RwLock, textures::TextureOptions, ImageData, ImageDelta, TextureId,
|
||||
TextureManager,
|
||||
};
|
||||
|
||||
|
@ -66,10 +66,10 @@ impl TextureHandle {
|
|||
}
|
||||
|
||||
/// Assign a new image to an existing texture.
|
||||
pub fn set(&mut self, image: impl Into<ImageData>, filter: TextureFilter) {
|
||||
pub fn set(&mut self, image: impl Into<ImageData>, options: TextureOptions) {
|
||||
self.tex_mngr
|
||||
.write()
|
||||
.set(self.id, ImageDelta::full(image.into(), filter));
|
||||
.set(self.id, ImageDelta::full(image.into(), options));
|
||||
}
|
||||
|
||||
/// Assign a new image to a subregion of the whole texture.
|
||||
|
@ -77,11 +77,11 @@ impl TextureHandle {
|
|||
&mut self,
|
||||
pos: [usize; 2],
|
||||
image: impl Into<ImageData>,
|
||||
filter: TextureFilter,
|
||||
options: TextureOptions,
|
||||
) {
|
||||
self.tex_mngr
|
||||
.write()
|
||||
.set(self.id, ImageDelta::partial(pos, image.into(), filter));
|
||||
.set(self.id, ImageDelta::partial(pos, image.into(), options));
|
||||
}
|
||||
|
||||
/// width x height
|
||||
|
|
|
@ -26,7 +26,7 @@ impl TextureManager {
|
|||
/// MUST have a white pixel at (0,0) ([`crate::WHITE_UV`]).
|
||||
///
|
||||
/// The texture is given a retain-count of `1`, requiring one call to [`Self::free`] to free it.
|
||||
pub fn alloc(&mut self, name: String, image: ImageData, filter: TextureFilter) -> TextureId {
|
||||
pub fn alloc(&mut self, name: String, image: ImageData, options: TextureOptions) -> TextureId {
|
||||
let id = TextureId::Managed(self.next_id);
|
||||
self.next_id += 1;
|
||||
|
||||
|
@ -35,10 +35,10 @@ impl TextureManager {
|
|||
size: image.size(),
|
||||
bytes_per_pixel: image.bytes_per_pixel(),
|
||||
retain_count: 1,
|
||||
filter,
|
||||
options,
|
||||
});
|
||||
|
||||
self.delta.set.push((id, ImageDelta::full(image, filter)));
|
||||
self.delta.set.push((id, ImageDelta::full(image, options)));
|
||||
id
|
||||
}
|
||||
|
||||
|
@ -131,8 +131,50 @@ pub struct TextureMeta {
|
|||
/// Free when this reaches zero.
|
||||
pub retain_count: usize,
|
||||
|
||||
/// The texture filtering mode to use when rendering
|
||||
pub filter: TextureFilter,
|
||||
/// The texture filtering mode to use when rendering.
|
||||
pub options: TextureOptions,
|
||||
}
|
||||
|
||||
impl TextureMeta {
|
||||
/// Size in bytes.
|
||||
/// width x height x [`Self::bytes_per_pixel`].
|
||||
pub fn bytes_used(&self) -> usize {
|
||||
self.size[0] * self.size[1] * self.bytes_per_pixel
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// How the texture texels are filtered.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct TextureOptions {
|
||||
/// How to filter when magnifying (when texels are larger than pixels).
|
||||
pub magnification: TextureFilter,
|
||||
|
||||
/// How to filter when minifying (when texels are smaller than pixels).
|
||||
pub minification: TextureFilter,
|
||||
}
|
||||
|
||||
impl TextureOptions {
|
||||
/// Linear magnification and minification.
|
||||
pub const LINEAR: Self = Self {
|
||||
magnification: TextureFilter::Linear,
|
||||
minification: TextureFilter::Linear,
|
||||
};
|
||||
|
||||
/// Nearest magnification and minification.
|
||||
pub const NEAREST: Self = Self {
|
||||
magnification: TextureFilter::Nearest,
|
||||
minification: TextureFilter::Nearest,
|
||||
};
|
||||
}
|
||||
|
||||
impl Default for TextureOptions {
|
||||
/// The default is linear for both magnification and minification.
|
||||
fn default() -> Self {
|
||||
Self::LINEAR
|
||||
}
|
||||
}
|
||||
|
||||
/// How the texture texels are filtered.
|
||||
|
@ -146,25 +188,9 @@ pub enum TextureFilter {
|
|||
Nearest,
|
||||
|
||||
/// Linearly interpolate the nearest neighbors, creating a smoother look when zooming in and out.
|
||||
///
|
||||
/// This is the default.
|
||||
Linear,
|
||||
}
|
||||
|
||||
impl Default for TextureFilter {
|
||||
fn default() -> Self {
|
||||
Self::Linear
|
||||
}
|
||||
}
|
||||
|
||||
impl TextureMeta {
|
||||
/// Size in bytes.
|
||||
/// width x height x [`Self::bytes_per_pixel`].
|
||||
pub fn bytes_used(&self) -> usize {
|
||||
self.size[0] * self.size[1] * self.bytes_per_pixel
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/// What has been allocated and freed during the last period.
|
||||
|
|
|
@ -30,7 +30,7 @@ impl eframe::App for MyApp {
|
|||
self.texture = Some(ui.ctx().load_texture(
|
||||
"screenshot",
|
||||
screenshot,
|
||||
egui::TextureFilter::Linear,
|
||||
Default::default(),
|
||||
));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue