diff --git a/CHANGELOG.md b/CHANGELOG.md index bbf6942..5915bfa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ - `KeyState`, `MouseButton`, `ButtonState` and `Axis` in `backend::input` now derive `Hash`. - New `DrmNode` type in drm backend. This is primarily for use a backend which needs to run as client inside another session. - The button code for a `PointerButtonEvent` may now be obtained using `PointerButtonEvent::button_code`. +- `Renderer` now allows texture filtering methods to be set. ### Bugfixes diff --git a/src/backend/renderer/gles2/mod.rs b/src/backend/renderer/gles2/mod.rs index 5be1a90..5a32fd2 100644 --- a/src/backend/renderer/gles2/mod.rs +++ b/src/backend/renderer/gles2/mod.rs @@ -16,7 +16,7 @@ use cgmath::{prelude::*, Matrix3, Vector2}; mod shaders; mod version; -use super::{Bind, Frame, Renderer, Texture, Transform, Unbind}; +use super::{Bind, Frame, Renderer, Texture, TextureFilter, Transform, Unbind}; use crate::backend::allocator::{ dmabuf::{Dmabuf, WeakDmabuf}, Format, @@ -420,6 +420,7 @@ impl Gles2Renderer { /// - This renderer has no default framebuffer, use `Bind::bind` before rendering. /// - Binding a new target, while another one is already bound, will replace the current target. /// - Shm buffers can be released after a successful import, without the texture handle becoming invalid. + /// - Texture filtering starts with Nearest-downscaling and Linear-upscaling pub unsafe fn new(context: EGLContext, logger: L) -> Result where L: Into>, @@ -495,7 +496,7 @@ impl Gles2Renderer { ]; let (tx, rx) = channel(); - let renderer = Gles2Renderer { + let mut renderer = Gles2Renderer { id: RENDERER_COUNTER.fetch_add(1, Ordering::SeqCst), gl, egl: context, @@ -514,6 +515,8 @@ impl Gles2Renderer { logger: log, _not_send: std::ptr::null_mut(), }; + renderer.downscale_filter(TextureFilter::Nearest); + renderer.upscale_filter(TextureFilter::Linear); renderer.egl.unbind()?; Ok(renderer) } @@ -1006,6 +1009,28 @@ impl Renderer for Gles2Renderer { type Error = Gles2Error; type TextureId = Gles2Texture; type Frame = Gles2Frame; + + fn downscale_filter(&mut self, filter: TextureFilter) -> Result<(), Self::Error> { + self.make_current()?; + unsafe { + self.gl.TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_MIN_FILTER, match filter { + TextureFilter::Nearest => ffi::NEAREST as i32, + TextureFilter::Linear => ffi::LINEAR as i32, + }); + } + Ok(()) + } + fn upscale_filter(&mut self, filter: TextureFilter) -> Result<(), Self::Error> { + self.make_current()?; + unsafe { + self.gl.TexParameteri(ffi::TEXTURE_2D, ffi::TEXTURE_MAG_FILTER, match filter { + TextureFilter::Nearest => ffi::NEAREST as i32, + TextureFilter::Linear => ffi::LINEAR as i32, + }); + } + Ok(()) + } + fn render( &mut self, diff --git a/src/backend/renderer/mod.rs b/src/backend/renderer/mod.rs index f664d84..a5c7441 100644 --- a/src/backend/renderer/mod.rs +++ b/src/backend/renderer/mod.rs @@ -53,6 +53,15 @@ pub enum Transform { Flipped270, } +#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)] +/// Texture filtering methods +pub enum TextureFilter { + /// Returns the value of the texture element that is nearest (in Manhattan distance) to the center of the pixel being textured. + Linear, + /// Returns the weighted average of the four texture elements that are closest to the center of the pixel being textured. + Nearest, +} + impl Transform { /// A projection matrix to apply this transformation pub fn matrix(&self) -> Matrix3 { @@ -255,6 +264,11 @@ pub trait Renderer { /// Type representing a currently in-progress frame during the [`Renderer::render`]-call type Frame: Frame; + /// Set the filter method to be used when rendering a texture into a smaller area than its size + fn downscale_filter(&mut self, filter: TextureFilter) -> Result<(), Self::Error>; + /// Set the filter method to be used when rendering a texture into a larger area than its size + fn upscale_filter(&mut self, filter: TextureFilter) -> Result<(), Self::Error>; + /// Initialize a rendering context on the current rendering target with given dimensions and transformation. /// /// This function *may* error, if: