renderer: Support cropping and scaling
This commit is contained in:
parent
b67688e1c8
commit
8bd17d71d2
|
@ -155,7 +155,7 @@ where
|
||||||
let mut location = *location;
|
let mut location = *location;
|
||||||
if let Some(ref data) = states.data_map.get::<RefCell<SurfaceData>>() {
|
if let Some(ref data) = states.data_map.get::<RefCell<SurfaceData>>() {
|
||||||
let mut data = data.borrow_mut();
|
let mut data = data.borrow_mut();
|
||||||
let buffer_scale = data.buffer_scale as f32;
|
let buffer_scale = data.buffer_scale;
|
||||||
if let Some(texture) = data
|
if let Some(texture) = data
|
||||||
.texture
|
.texture
|
||||||
.as_mut()
|
.as_mut()
|
||||||
|
@ -167,12 +167,12 @@ where
|
||||||
let current = states.cached_state.current::<SubsurfaceCachedState>();
|
let current = states.cached_state.current::<SubsurfaceCachedState>();
|
||||||
location += current.location;
|
location += current.location;
|
||||||
}
|
}
|
||||||
let render_scale = output_scale as f32 / buffer_scale;
|
|
||||||
if let Err(err) = frame.render_texture_at(
|
if let Err(err) = frame.render_texture_at(
|
||||||
&texture.texture,
|
&texture.texture,
|
||||||
location.to_f64().to_physical(output_scale as f64).to_i32_round(),
|
location.to_f64().to_physical(output_scale as f64).to_i32_round(),
|
||||||
|
buffer_scale,
|
||||||
|
output_scale as f64,
|
||||||
Transform::Normal, /* TODO */
|
Transform::Normal, /* TODO */
|
||||||
render_scale,
|
|
||||||
1.0,
|
1.0,
|
||||||
) {
|
) {
|
||||||
result = Err(err.into());
|
result = Err(err.into());
|
||||||
|
|
|
@ -755,8 +755,9 @@ fn render_surface(
|
||||||
.to_f64()
|
.to_f64()
|
||||||
.to_physical(output_scale as f64)
|
.to_physical(output_scale as f64)
|
||||||
.to_i32_round(),
|
.to_i32_round(),
|
||||||
|
1,
|
||||||
|
output_scale as f64,
|
||||||
Transform::Normal,
|
Transform::Normal,
|
||||||
output_scale,
|
|
||||||
1.0,
|
1.0,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ use std::sync::{
|
||||||
};
|
};
|
||||||
use std::{collections::HashSet, os::raw::c_char};
|
use std::{collections::HashSet, os::raw::c_char};
|
||||||
|
|
||||||
use cgmath::{prelude::*, Matrix3};
|
use cgmath::{prelude::*, Matrix3, Vector2};
|
||||||
|
|
||||||
mod shaders;
|
mod shaders;
|
||||||
mod version;
|
mod version;
|
||||||
|
@ -76,7 +76,9 @@ impl Gles2Texture {
|
||||||
///
|
///
|
||||||
/// Ownership over the texture is taken by the renderer, you should not free the texture yourself.
|
/// Ownership over the texture is taken by the renderer, you should not free the texture yourself.
|
||||||
///
|
///
|
||||||
/// *Safety*: The renderer cannot make sure `tex` is a valid texture id.
|
/// # Safety
|
||||||
|
///
|
||||||
|
/// The renderer cannot make sure `tex` is a valid texture id.
|
||||||
pub unsafe fn from_raw(
|
pub unsafe fn from_raw(
|
||||||
renderer: &Gles2Renderer,
|
renderer: &Gles2Renderer,
|
||||||
tex: ffi::types::GLuint,
|
tex: ffi::types::GLuint,
|
||||||
|
@ -979,20 +981,6 @@ impl Drop for Gles2Renderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static VERTS: [ffi::types::GLfloat; 8] = [
|
|
||||||
1.0, 0.0, // top right
|
|
||||||
0.0, 0.0, // top left
|
|
||||||
1.0, 1.0, // bottom right
|
|
||||||
0.0, 1.0, // bottom left
|
|
||||||
];
|
|
||||||
|
|
||||||
static TEX_COORDS: [ffi::types::GLfloat; 8] = [
|
|
||||||
1.0, 0.0, // top right
|
|
||||||
0.0, 0.0, // top left
|
|
||||||
1.0, 1.0, // bottom right
|
|
||||||
0.0, 1.0, // bottom left
|
|
||||||
];
|
|
||||||
|
|
||||||
impl Gles2Renderer {
|
impl Gles2Renderer {
|
||||||
/// Run custom code in the GL context owned by this renderer.
|
/// Run custom code in the GL context owned by this renderer.
|
||||||
///
|
///
|
||||||
|
@ -1085,6 +1073,13 @@ impl Renderer for Gles2Renderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VERTS: [ffi::types::GLfloat; 8] = [
|
||||||
|
1.0, 0.0, // top right
|
||||||
|
0.0, 0.0, // top left
|
||||||
|
1.0, 1.0, // bottom right
|
||||||
|
0.0, 1.0, // bottom left
|
||||||
|
];
|
||||||
|
|
||||||
impl Frame for Gles2Frame {
|
impl Frame for Gles2Frame {
|
||||||
type Error = Gles2Error;
|
type Error = Gles2Error;
|
||||||
type TextureId = Gles2Texture;
|
type TextureId = Gles2Texture;
|
||||||
|
@ -1102,6 +1097,7 @@ impl Frame for Gles2Frame {
|
||||||
&mut self,
|
&mut self,
|
||||||
tex: &Self::TextureId,
|
tex: &Self::TextureId,
|
||||||
mut matrix: Matrix3<f32>,
|
mut matrix: Matrix3<f32>,
|
||||||
|
tex_coords: [Vector2<f32>; 4],
|
||||||
alpha: f32,
|
alpha: f32,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
//apply output transformation
|
//apply output transformation
|
||||||
|
@ -1150,7 +1146,7 @@ impl Frame for Gles2Frame {
|
||||||
ffi::FLOAT,
|
ffi::FLOAT,
|
||||||
ffi::FALSE,
|
ffi::FALSE,
|
||||||
0,
|
0,
|
||||||
TEX_COORDS.as_ptr() as *const _,
|
tex_coords.as_ptr() as *const _, // cgmath::Vector2 is marked as repr(C), this cast should be safe
|
||||||
);
|
);
|
||||||
|
|
||||||
self.gl
|
self.gl
|
||||||
|
|
|
@ -10,16 +10,18 @@
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use crate::utils::{Physical, Point, Size};
|
use crate::utils::{Buffer, Physical, Point, Rectangle, Size};
|
||||||
|
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
use crate::{utils::Rectangle, wayland::compositor::SurfaceData};
|
use crate::wayland::compositor::SurfaceData;
|
||||||
use cgmath::{prelude::*, Matrix3, Vector2};
|
use cgmath::{prelude::*, Matrix3, Vector2, Vector3};
|
||||||
#[cfg(feature = "wayland_frontend")]
|
#[cfg(feature = "wayland_frontend")]
|
||||||
use wayland_server::protocol::{wl_buffer, wl_shm};
|
use wayland_server::protocol::{wl_buffer, wl_shm};
|
||||||
|
|
||||||
#[cfg(feature = "renderer_gl")]
|
#[cfg(feature = "renderer_gl")]
|
||||||
pub mod gles2;
|
pub mod gles2;
|
||||||
|
#[cfg(feature = "wayland_frontend")]
|
||||||
|
use crate::backend::allocator::{dmabuf::Dmabuf, Format};
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
feature = "wayland_frontend",
|
feature = "wayland_frontend",
|
||||||
feature = "backend_egl",
|
feature = "backend_egl",
|
||||||
|
@ -29,11 +31,6 @@ use crate::backend::egl::{
|
||||||
display::{EGLBufferReader, BUFFER_READER},
|
display::{EGLBufferReader, BUFFER_READER},
|
||||||
Error as EglError,
|
Error as EglError,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "wayland_frontend")]
|
|
||||||
use crate::{
|
|
||||||
backend::allocator::{dmabuf::Dmabuf, Format},
|
|
||||||
utils::Buffer,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||||
/// Possible transformations to two-dimensional planes
|
/// Possible transformations to two-dimensional planes
|
||||||
|
@ -142,9 +139,9 @@ pub trait Unbind: Renderer {
|
||||||
|
|
||||||
/// A two dimensional texture
|
/// A two dimensional texture
|
||||||
pub trait Texture {
|
pub trait Texture {
|
||||||
/// Size of the texture plane (w x h)
|
/// Size of the texture plane
|
||||||
fn size(&self) -> (u32, u32) {
|
fn size(&self) -> Size<i32, Buffer> {
|
||||||
(self.width(), self.height())
|
Size::from((self.width() as i32, self.height() as i32))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Width of the texture plane
|
/// Width of the texture plane
|
||||||
|
@ -166,34 +163,57 @@ pub trait Frame {
|
||||||
/// If called outside this operation may error-out, do nothing or modify future rendering results in any way.
|
/// 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>;
|
fn clear(&mut self, color: [f32; 4]) -> Result<(), Self::Error>;
|
||||||
/// Render a texture to the current target using given projection matrix and alpha.
|
/// Render a texture to the current target using given projection matrix and alpha.
|
||||||
///
|
/// The given verticies are used to source the texture. This is mostly useful for cropping the texture.
|
||||||
/// 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 render_texture(
|
fn render_texture(
|
||||||
&mut self,
|
&mut self,
|
||||||
texture: &Self::TextureId,
|
texture: &Self::TextureId,
|
||||||
matrix: Matrix3<f32>,
|
matrix: Matrix3<f32>,
|
||||||
|
tex_coords: [Vector2<f32>; 4],
|
||||||
alpha: f32,
|
alpha: f32,
|
||||||
) -> Result<(), Self::Error>;
|
) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
/// Render a texture to the current target as a flat 2d-plane at a given
|
/// Render a texture to the current target as a flat 2d-plane at a given
|
||||||
/// position, applying the given transformation with the given alpha value.
|
/// position and applying the given transformation with the given alpha value.
|
||||||
///
|
|
||||||
/// 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 render_texture_at(
|
fn render_texture_at(
|
||||||
&mut self,
|
&mut self,
|
||||||
texture: &Self::TextureId,
|
texture: &Self::TextureId,
|
||||||
pos: Point<i32, Physical>,
|
pos: Point<f64, Physical>,
|
||||||
|
texture_scale: i32,
|
||||||
|
output_scale: f64,
|
||||||
|
transform: Transform,
|
||||||
|
alpha: f32,
|
||||||
|
) -> Result<(), Self::Error> {
|
||||||
|
self.render_texture_from_to(
|
||||||
|
texture,
|
||||||
|
Rectangle::from_loc_and_size(Point::<i32, Buffer>::from((0, 0)), texture.size()),
|
||||||
|
Rectangle::from_loc_and_size(
|
||||||
|
pos,
|
||||||
|
texture
|
||||||
|
.size()
|
||||||
|
.to_logical(texture_scale)
|
||||||
|
.to_f64()
|
||||||
|
.to_physical(output_scale),
|
||||||
|
),
|
||||||
|
transform,
|
||||||
|
alpha,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Render part of a texture as given by src to the current target into the rectangle described by dest
|
||||||
|
/// as a flat 2d-plane after applying the given transformations.
|
||||||
|
fn render_texture_from_to(
|
||||||
|
&mut self,
|
||||||
|
texture: &Self::TextureId,
|
||||||
|
src: Rectangle<i32, Buffer>,
|
||||||
|
dest: Rectangle<f64, Physical>,
|
||||||
transform: Transform,
|
transform: Transform,
|
||||||
scale: f32,
|
|
||||||
alpha: f32,
|
alpha: f32,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
let mut mat = Matrix3::<f32>::identity();
|
let mut mat = Matrix3::<f32>::identity();
|
||||||
|
|
||||||
// position and scale
|
// position and scale
|
||||||
let size = texture.size();
|
mat = mat * Matrix3::from_translation(Vector2::new(dest.loc.x as f32, dest.loc.y as f32));
|
||||||
mat = mat * Matrix3::from_translation(Vector2::new(pos.x as f32, pos.y as f32));
|
mat = mat * Matrix3::from_nonuniform_scale(dest.size.w as f32, dest.size.h as f32);
|
||||||
mat = mat * Matrix3::from_nonuniform_scale(size.0 as f32 * scale, size.1 as f32 * scale);
|
|
||||||
|
|
||||||
//apply surface transformation
|
//apply surface transformation
|
||||||
mat = mat * Matrix3::from_translation(Vector2::new(0.5, 0.5));
|
mat = mat * Matrix3::from_translation(Vector2::new(0.5, 0.5));
|
||||||
|
@ -204,7 +224,24 @@ pub trait Frame {
|
||||||
mat = mat * transform.invert().matrix();
|
mat = mat * transform.invert().matrix();
|
||||||
mat = mat * Matrix3::from_translation(Vector2::new(-0.5, -0.5));
|
mat = mat * Matrix3::from_translation(Vector2::new(-0.5, -0.5));
|
||||||
|
|
||||||
self.render_texture(texture, mat, alpha)
|
// 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue