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

Specify different minification and magnification filters #2224

Merged
merged 5 commits into from Nov 2, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -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)).
Expand Down
23 changes: 15 additions & 8 deletions crates/egui-wgpu/src/renderer.rs
Expand Up @@ -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.
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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()
})
}
Expand Down
8 changes: 4 additions & 4 deletions crates/egui/src/context.rs
Expand Up @@ -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, *};

// ----------------------------------------------------------------------------

Expand Down Expand Up @@ -800,7 +800,7 @@ impl Context {
/// ui.ctx().load_texture(
/// "my-image",
/// egui::ColorImage::example(),
/// egui::TextureFilter::Linear
/// Default::default()
/// )
/// });
///
Expand All @@ -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();
Expand All @@ -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)
}

Expand Down
2 changes: 1 addition & 1 deletion crates/egui/src/lib.rs
Expand Up @@ -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,
};
Expand Down
2 changes: 1 addition & 1 deletion crates/egui/src/ui.rs
Expand Up @@ -1553,7 +1553,7 @@ impl Ui {
/// ui.ctx().load_texture(
/// "my-image",
/// egui::ColorImage::example(),
/// egui::TextureFilter::Linear
/// Default::default()
/// )
/// });
///
Expand Down
2 changes: 1 addition & 1 deletion crates/egui/src/widgets/image.rs
Expand Up @@ -18,7 +18,7 @@ use emath::Rot2;
/// ui.ctx().load_texture(
/// "my-image",
/// egui::ColorImage::example(),
/// egui::TextureFilter::Linear
/// Default::default()
/// )
/// });
///
Expand Down
4 changes: 2 additions & 2 deletions crates/egui_demo_lib/src/color_test.rs
@@ -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);

Expand Down Expand Up @@ -372,7 +372,7 @@ impl TextureManager {
size: [width, height],
pixels,
},
TextureFilter::Linear,
TextureOptions::LINEAR,
)
})
}
Expand Down
7 changes: 2 additions & 5 deletions crates/egui_demo_lib/src/demo/plot_demo.rs
Expand Up @@ -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,
Expand Down
7 changes: 2 additions & 5 deletions crates/egui_demo_lib/src/demo/widget_gallery.rs
Expand Up @@ -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"));
Expand Down
27 changes: 17 additions & 10 deletions crates/egui_extras/src/image.rs
@@ -1,5 +1,4 @@
use egui::mutex::Mutex;
use egui::TextureFilter;
use egui::{mutex::Mutex, TextureFilter, TextureOptions};

/// An image to be shown in egui.
///
Expand All @@ -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 {
Expand All @@ -23,7 +22,7 @@ impl RetainedImage {
size: image.size,
image: Mutex::new(image),
texture: Default::default(),
filter: Default::default(),
options: Default::default(),
}
}

Expand Down Expand Up @@ -68,15 +67,15 @@ 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.
///
/// # 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],
Expand All @@ -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.
Expand All @@ -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
Expand Down Expand Up @@ -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()
}
Expand Down
2 changes: 1 addition & 1 deletion crates/egui_glium/examples/native_texture.rs
Expand Up @@ -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);

Expand Down
40 changes: 27 additions & 13 deletions crates/egui_glium/src/painter.rs
@@ -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},
Expand All @@ -10,7 +13,7 @@ use {
index::PrimitiveType,
texture::{self, srgb_texture2d::SrgbTexture2d},
uniform,
uniforms::{MagnifySamplerFilter, SamplerWrapFunction},
uniforms::{MagnifySamplerFilter, MinifySamplerFilter, SamplerWrapFunction},
},
std::rc::Rc,
};
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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);
}
}
Expand All @@ -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
}
Expand All @@ -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,
}
}
}