diff --git a/CHANGELOG.md b/CHANGELOG.md index 5915bfa..a90b011 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - All winit backend internal event types now use `WinitInput` as the backend type. - `WinitEventLoop::dispatch_new_events` is now used to receive some `WinitEvent`s. - Added `TabletToolType::Unknown` as an option for tablet events +- `render_texture` was removed from `Frame`, use `render_texture_at` or `render_texture_from_to` instead or use `Gles2Renderer::render_texture` as a direct replacement. ### Additions diff --git a/src/backend/renderer/gles2/mod.rs b/src/backend/renderer/gles2/mod.rs index 5a32fd2..3a8c49b 100644 --- a/src/backend/renderer/gles2/mod.rs +++ b/src/backend/renderer/gles2/mod.rs @@ -11,7 +11,7 @@ use std::sync::{ }; use std::{collections::HashSet, os::raw::c_char}; -use cgmath::{prelude::*, Matrix3, Vector2}; +use cgmath::{prelude::*, Matrix3, Vector2, Vector3}; mod shaders; mod version; @@ -26,7 +26,7 @@ use crate::backend::egl::{ EGLContext, EGLSurface, MakeCurrentError, }; use crate::backend::SwapBuffersError; -use crate::utils::{Buffer, Physical, Size}; +use crate::utils::{Buffer, Physical, Rectangle, Size}; #[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))] use super::ImportEgl; @@ -35,8 +35,6 @@ use super::{ImportDma, ImportShm}; #[cfg(all(feature = "wayland_frontend", feature = "use_system_lib"))] use crate::backend::egl::{display::EGLBufferReader, Format as EGLFormat}; #[cfg(feature = "wayland_frontend")] -use crate::utils::Rectangle; -#[cfg(feature = "wayland_frontend")] use wayland_server::protocol::{wl_buffer, wl_shm}; use slog::{debug, error, info, o, trace, warn}; @@ -515,8 +513,8 @@ impl Gles2Renderer { logger: log, _not_send: std::ptr::null_mut(), }; - renderer.downscale_filter(TextureFilter::Nearest); - renderer.upscale_filter(TextureFilter::Linear); + renderer.downscale_filter(TextureFilter::Nearest)?; + renderer.upscale_filter(TextureFilter::Linear)?; renderer.egl.unbind()?; Ok(renderer) } @@ -1009,29 +1007,36 @@ 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, - }); + 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, - }); + 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, size: Size, @@ -1125,13 +1130,60 @@ impl Frame for Gles2Frame { Ok(()) } - fn render_texture( + fn render_texture_from_to( &mut self, - tex: &Self::TextureId, + texture: &Self::TextureId, + src: Rectangle, + dest: Rectangle, + transform: Transform, + alpha: f32, + ) -> Result<(), Self::Error> { + let mut mat = Matrix3::::identity(); + + // position and scale + mat = mat * Matrix3::from_translation(Vector2::new(dest.loc.x as f32, dest.loc.y as f32)); + mat = mat * Matrix3::from_nonuniform_scale(dest.size.w as f32, dest.size.h as f32); + + //apply surface transformation + mat = mat * Matrix3::from_translation(Vector2::new(0.5, 0.5)); + if transform == Transform::Normal { + assert_eq!(mat, mat * transform.invert().matrix()); + assert_eq!(transform.matrix(), Matrix3::::identity()); + } + mat = mat * transform.invert().matrix(); + mat = mat * Matrix3::from_translation(Vector2::new(-0.5, -0.5)); + + // this matrix should be regular, we can expect invert to succeed + let tex_size = texture.size(); + let texture_mat = Matrix3::from_nonuniform_scale(tex_size.w as f32, tex_size.h as f32) + .invert() + .unwrap(); + let verts = [ + (texture_mat * Vector3::new((src.loc.x + src.size.w) as f32, src.loc.y as f32, 0.0)).truncate(), // top-right + (texture_mat * Vector3::new(src.loc.x as f32, src.loc.y as f32, 0.0)).truncate(), // top-left + (texture_mat + * Vector3::new( + (src.loc.x + src.size.w) as f32, + (src.loc.y + src.size.h) as f32, + 0.0, + )) + .truncate(), // bottom-right + (texture_mat * Vector3::new(src.loc.x as f32, (src.loc.y + src.size.h) as f32, 0.0)).truncate(), // bottom-left + ]; + self.render_texture(texture, mat, verts, alpha) + } +} + +impl Gles2Frame { + /// Render a texture to the current target using given projection matrix and alpha. + /// The given vertices are used to source the texture. This is mostly useful for cropping the texture. + pub fn render_texture( + &mut self, + tex: &Gles2Texture, mut matrix: Matrix3, tex_coords: [Vector2; 4], alpha: f32, - ) -> Result<(), Self::Error> { + ) -> Result<(), Gles2Error> { //apply output transformation matrix = self.current_projection * matrix; diff --git a/src/backend/renderer/mod.rs b/src/backend/renderer/mod.rs index a5c7441..8a2b3a6 100644 --- a/src/backend/renderer/mod.rs +++ b/src/backend/renderer/mod.rs @@ -14,7 +14,7 @@ use crate::utils::{Buffer, Physical, Point, Rectangle, Size}; #[cfg(feature = "wayland_frontend")] use crate::wayland::compositor::SurfaceData; -use cgmath::{prelude::*, Matrix3, Vector2, Vector3}; +use cgmath::Matrix3; #[cfg(feature = "wayland_frontend")] use wayland_server::protocol::{wl_buffer, wl_shm}; @@ -172,15 +172,6 @@ pub trait Frame { /// This operation is only valid in between a `begin` and `finish`-call. /// If called outside this operation may error-out, do nothing or modify future rendering results in any way. fn clear(&mut self, color: [f32; 4]) -> Result<(), Self::Error>; - /// Render a texture to the current target using given projection matrix and alpha. - /// The given vertices are used to source the texture. This is mostly useful for cropping the texture. - fn render_texture( - &mut self, - texture: &Self::TextureId, - matrix: Matrix3, - tex_coords: [Vector2; 4], - alpha: f32, - ) -> Result<(), Self::Error>; /// Render a texture to the current target as a flat 2d-plane at a given /// position and applying the given transformation with the given alpha value. @@ -218,41 +209,7 @@ pub trait Frame { dest: Rectangle, transform: Transform, alpha: f32, - ) -> Result<(), Self::Error> { - let mut mat = Matrix3::::identity(); - - // position and scale - mat = mat * Matrix3::from_translation(Vector2::new(dest.loc.x as f32, dest.loc.y as f32)); - mat = mat * Matrix3::from_nonuniform_scale(dest.size.w as f32, dest.size.h as f32); - - //apply surface transformation - mat = mat * Matrix3::from_translation(Vector2::new(0.5, 0.5)); - if transform == Transform::Normal { - assert_eq!(mat, mat * transform.invert().matrix()); - assert_eq!(transform.matrix(), Matrix3::::identity()); - } - mat = mat * transform.invert().matrix(); - mat = mat * Matrix3::from_translation(Vector2::new(-0.5, -0.5)); - - // this matrix should be regular, we can expect invert to succeed - let tex_size = texture.size(); - let texture_mat = Matrix3::from_nonuniform_scale(tex_size.w as f32, tex_size.h as f32) - .invert() - .unwrap(); - let verts = [ - (texture_mat * Vector3::new((src.loc.x + src.size.w) as f32, src.loc.y as f32, 0.0)).truncate(), // top-right - (texture_mat * Vector3::new(src.loc.x as f32, src.loc.y as f32, 0.0)).truncate(), // top-left - (texture_mat - * Vector3::new( - (src.loc.x + src.size.w) as f32, - (src.loc.y + src.size.h) as f32, - 0.0, - )) - .truncate(), // bottom-right - (texture_mat * Vector3::new(src.loc.x as f32, (src.loc.y + src.size.h) as f32, 0.0)).truncate(), // bottom-left - ]; - self.render_texture(texture, mat, verts, alpha) - } + ) -> Result<(), Self::Error>; } /// Abstraction of commonly used rendering operations for compositors.