aboutsummaryrefslogtreecommitdiff
path: root/src/render_helpers
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-06-01 12:27:30 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2024-06-10 18:08:00 +0300
commit3c63be6261f3420008366b41b3df6d57b3ec3867 (patch)
treec937af80e68e25d6a0d18aeae9338a4a161d83ab /src/render_helpers
parente3406ac2556c7f68cd00f11b5856222dcce7f680 (diff)
downloadniri-3c63be6261f3420008366b41b3df6d57b3ec3867.tar.gz
niri-3c63be6261f3420008366b41b3df6d57b3ec3867.tar.bz2
niri-3c63be6261f3420008366b41b3df6d57b3ec3867.zip
Implement our own TextureBuffer/RenderElement
Supports fractional texture scale + has some getters.
Diffstat (limited to 'src/render_helpers')
-rw-r--r--src/render_helpers/mod.rs13
-rw-r--r--src/render_helpers/offscreen.rs17
-rw-r--r--src/render_helpers/primary_gpu_texture.rs2
-rw-r--r--src/render_helpers/surface.rs6
-rw-r--r--src/render_helpers/texture.rs207
5 files changed, 229 insertions, 16 deletions
diff --git a/src/render_helpers/mod.rs b/src/render_helpers/mod.rs
index db2d39d7..dcb51e7c 100644
--- a/src/render_helpers/mod.rs
+++ b/src/render_helpers/mod.rs
@@ -4,7 +4,6 @@ use anyhow::{ensure, Context};
use niri_config::BlockOutFrom;
use smithay::backend::allocator::Fourcc;
use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement};
-use smithay::backend::renderer::element::texture::{TextureBuffer, TextureRenderElement};
use smithay::backend::renderer::element::utils::{Relocate, RelocateRenderElement};
use smithay::backend::renderer::element::{Kind, RenderElement};
use smithay::backend::renderer::gles::{GlesMapping, GlesRenderer, GlesTexture};
@@ -16,6 +15,7 @@ use smithay::utils::{Logical, Physical, Point, Rectangle, Scale, Size, Transform
use smithay::wayland::shm;
use self::primary_gpu_texture::PrimaryGpuTextureRenderElement;
+use self::texture::{TextureBuffer, TextureRenderElement};
pub mod border;
pub mod clipped_surface;
@@ -31,6 +31,7 @@ pub mod shader_element;
pub mod shaders;
pub mod snapshot;
pub mod surface;
+pub mod texture;
/// What we're rendering for.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -117,16 +118,16 @@ impl ToRenderElement for BakedBuffer<TextureBuffer<GlesTexture>> {
fn to_render_element(
&self,
location: Point<i32, Logical>,
- scale: Scale<f64>,
+ _scale: Scale<f64>,
alpha: f32,
kind: Kind,
) -> Self::RenderElement {
let elem = TextureRenderElement::from_texture_buffer(
- (location + self.location).to_physical_precise_round(scale),
- &self.buffer,
- Some(alpha),
+ self.buffer.clone(),
+ (location + self.location).to_f64(),
+ alpha,
self.src,
- self.dst,
+ self.dst.map(|dst| dst.to_f64()),
kind,
);
PrimaryGpuTextureRenderElement(elem)
diff --git a/src/render_helpers/offscreen.rs b/src/render_helpers/offscreen.rs
index 7c563b9b..a7df69c1 100644
--- a/src/render_helpers/offscreen.rs
+++ b/src/render_helpers/offscreen.rs
@@ -1,6 +1,5 @@
use smithay::backend::allocator::Fourcc;
use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement};
-use smithay::backend::renderer::element::texture::{TextureBuffer, TextureRenderElement};
use smithay::backend::renderer::element::utils::{Relocate, RelocateRenderElement};
use smithay::backend::renderer::element::{Element, Id, Kind, RenderElement, UnderlyingStorage};
use smithay::backend::renderer::gles::{GlesError, GlesFrame, GlesRenderer};
@@ -10,6 +9,7 @@ use smithay::utils::{Buffer, Physical, Rectangle, Scale, Transform};
use super::primary_gpu_texture::PrimaryGpuTextureRenderElement;
use super::render_to_texture;
use super::renderer::AsGlesFrame;
+use super::texture::{TextureBuffer, TextureRenderElement};
use crate::backend::tty::{TtyFrame, TtyRenderer, TtyRendererError};
/// Renders elements into an off-screen buffer.
@@ -59,12 +59,17 @@ impl OffscreenRenderElement {
elements,
) {
Ok((texture, _sync_point)) => {
- let buffer =
- TextureBuffer::from_texture(renderer, texture, scale, Transform::Normal, None);
+ let buffer = TextureBuffer::from_texture(
+ renderer,
+ texture,
+ scale as f64,
+ Transform::Normal,
+ Vec::new(),
+ );
let element = TextureRenderElement::from_texture_buffer(
- geo.loc.to_f64(),
- &buffer,
- Some(result_alpha),
+ buffer,
+ geo.loc.to_f64().to_logical(scale as f64),
+ result_alpha,
None,
None,
Kind::Unspecified,
diff --git a/src/render_helpers/primary_gpu_texture.rs b/src/render_helpers/primary_gpu_texture.rs
index 54046f59..9f4e38d1 100644
--- a/src/render_helpers/primary_gpu_texture.rs
+++ b/src/render_helpers/primary_gpu_texture.rs
@@ -1,10 +1,10 @@
-use smithay::backend::renderer::element::texture::TextureRenderElement;
use smithay::backend::renderer::element::{Element, Id, Kind, RenderElement, UnderlyingStorage};
use smithay::backend::renderer::gles::{GlesError, GlesFrame, GlesRenderer, GlesTexture};
use smithay::backend::renderer::utils::{CommitCounter, DamageSet, OpaqueRegions};
use smithay::utils::{Buffer, Physical, Rectangle, Scale, Transform};
use super::renderer::AsGlesFrame;
+use super::texture::TextureRenderElement;
use crate::backend::tty::{TtyFrame, TtyRenderer, TtyRendererError};
/// Wrapper for a texture from the primary GPU for rendering with the primary GPU.
diff --git a/src/render_helpers/surface.rs b/src/render_helpers/surface.rs
index 21141b30..859be85f 100644
--- a/src/render_helpers/surface.rs
+++ b/src/render_helpers/surface.rs
@@ -1,4 +1,3 @@
-use smithay::backend::renderer::element::texture::TextureBuffer;
use smithay::backend::renderer::gles::{GlesRenderer, GlesTexture};
use smithay::backend::renderer::utils::{import_surface, RendererSurfaceStateUserData};
use smithay::backend::renderer::Renderer as _;
@@ -6,6 +5,7 @@ use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
use smithay::utils::{Logical, Point};
use smithay::wayland::compositor::{with_surface_tree_downward, TraversalAction};
+use super::texture::TextureBuffer;
use super::BakedBuffer;
/// Renders elements from a surface tree as textures into `storage`.
@@ -62,9 +62,9 @@ pub fn render_snapshot_from_surface_tree(
let buffer = TextureBuffer::from_texture(
renderer,
texture.clone(),
- data.buffer_scale(),
+ f64::from(data.buffer_scale()),
data.buffer_transform(),
- None,
+ Vec::new(),
);
let baked = BakedBuffer {
diff --git a/src/render_helpers/texture.rs b/src/render_helpers/texture.rs
new file mode 100644
index 00000000..c1eec367
--- /dev/null
+++ b/src/render_helpers/texture.rs
@@ -0,0 +1,207 @@
+use smithay::backend::allocator::Fourcc;
+use smithay::backend::renderer::element::{Element, Id, Kind, RenderElement, UnderlyingStorage};
+use smithay::backend::renderer::utils::{CommitCounter, OpaqueRegions};
+use smithay::backend::renderer::{Frame as _, ImportMem, Renderer, Texture};
+use smithay::utils::{Buffer, Logical, Physical, Point, Rectangle, Scale, Size, Transform};
+
+/// Smithay's texture buffer, but with fractional scale.
+#[derive(Debug, Clone)]
+pub struct TextureBuffer<T> {
+ id: Id,
+ commit_counter: CommitCounter,
+ renderer_id: usize,
+ texture: T,
+ scale: Scale<f64>,
+ transform: Transform,
+ opaque_regions: Vec<Rectangle<i32, Buffer>>,
+}
+
+/// Render element for a [`TextureBuffer`].
+#[derive(Debug)]
+pub struct TextureRenderElement<T> {
+ buffer: TextureBuffer<T>,
+ location: Point<f64, Logical>,
+ alpha: f32,
+ src: Option<Rectangle<f64, Logical>>,
+ size: Option<Size<f64, Logical>>,
+ kind: Kind,
+}
+
+impl<T> TextureBuffer<T> {
+ pub fn from_texture<R: Renderer<TextureId = T>>(
+ renderer: &R,
+ texture: T,
+ scale: impl Into<Scale<f64>>,
+ transform: Transform,
+ opaque_regions: Vec<Rectangle<i32, Buffer>>,
+ ) -> Self {
+ TextureBuffer {
+ id: Id::new(),
+ commit_counter: CommitCounter::default(),
+ renderer_id: renderer.id(),
+ texture,
+ scale: scale.into(),
+ transform,
+ opaque_regions,
+ }
+ }
+
+ #[allow(clippy::too_many_arguments)]
+ pub fn from_memory<R: Renderer<TextureId = T> + ImportMem>(
+ renderer: &mut R,
+ data: &[u8],
+ format: Fourcc,
+ size: impl Into<Size<i32, Buffer>>,
+ flipped: bool,
+ scale: impl Into<Scale<f64>>,
+ transform: Transform,
+ opaque_regions: Vec<Rectangle<i32, Buffer>>,
+ ) -> Result<Self, <R as Renderer>::Error> {
+ let texture = renderer.import_memory(data, format, size.into(), flipped)?;
+ Ok(TextureBuffer::from_texture(
+ renderer,
+ texture,
+ scale,
+ transform,
+ opaque_regions,
+ ))
+ }
+
+ pub fn texture(&self) -> &T {
+ &self.texture
+ }
+
+ pub fn texture_scale(&self) -> Scale<f64> {
+ self.scale
+ }
+}
+
+impl<T: Texture> TextureBuffer<T> {
+ pub fn logical_size(&self) -> Size<f64, Logical> {
+ self.texture
+ .size()
+ .to_f64()
+ .to_logical(self.scale, self.transform)
+ }
+}
+
+impl<T> TextureRenderElement<T> {
+ pub fn from_texture_buffer(
+ buffer: TextureBuffer<T>,
+ location: impl Into<Point<f64, Logical>>,
+ alpha: f32,
+ src: Option<Rectangle<f64, Logical>>,
+ size: Option<Size<f64, Logical>>,
+ kind: Kind,
+ ) -> Self {
+ TextureRenderElement {
+ buffer,
+ location: location.into(),
+ alpha,
+ src,
+ size,
+ kind,
+ }
+ }
+}
+
+impl<T: Texture> TextureRenderElement<T> {
+ pub fn logical_size(&self) -> Size<f64, Logical> {
+ self.size
+ .or_else(|| self.src.map(|src| src.size))
+ .unwrap_or_else(|| self.buffer.logical_size())
+ }
+}
+
+impl<T: Texture> Element for TextureRenderElement<T> {
+ fn id(&self) -> &Id {
+ &self.buffer.id
+ }
+
+ fn current_commit(&self) -> CommitCounter {
+ self.buffer.commit_counter
+ }
+
+ fn geometry(&self, scale: Scale<f64>) -> Rectangle<i32, Physical> {
+ let logical_geo = Rectangle::from_loc_and_size(self.location, self.logical_size());
+ logical_geo.to_physical_precise_round(scale)
+ }
+
+ fn transform(&self) -> Transform {
+ self.buffer.transform
+ }
+
+ fn src(&self) -> Rectangle<f64, Buffer> {
+ self.src
+ .map(|src| {
+ src.to_buffer(
+ self.buffer.scale,
+ self.buffer.transform,
+ &self.buffer.logical_size(),
+ )
+ })
+ .unwrap_or_else(|| {
+ Rectangle::from_loc_and_size((0, 0), self.buffer.texture.size()).to_f64()
+ })
+ }
+
+ fn opaque_regions(&self, scale: Scale<f64>) -> OpaqueRegions<i32, Physical> {
+ let texture_size = self.buffer.texture.size().to_f64();
+ let src = self.src();
+
+ self.buffer
+ .opaque_regions
+ .iter()
+ .filter_map(|region| {
+ let mut region = region.to_f64().intersection(src)?;
+
+ region.loc -= src.loc;
+ region.upscale(texture_size / src.size);
+
+ let logical =
+ region.to_logical(self.buffer.scale, self.buffer.transform, &src.size);
+ Some(logical.to_physical_precise_down(scale))
+ })
+ .collect()
+ }
+
+ fn alpha(&self) -> f32 {
+ self.alpha
+ }
+
+ fn kind(&self) -> Kind {
+ self.kind
+ }
+}
+
+impl<R, T> RenderElement<R> for TextureRenderElement<T>
+where
+ R: Renderer<TextureId = T>,
+ T: Texture,
+{
+ fn draw(
+ &self,
+ frame: &mut <R as Renderer>::Frame<'_>,
+ src: Rectangle<f64, Buffer>,
+ dest: Rectangle<i32, Physical>,
+ damage: &[Rectangle<i32, Physical>],
+ ) -> Result<(), <R as Renderer>::Error> {
+ if frame.id() != self.buffer.renderer_id {
+ warn!("trying to render texture from different renderer");
+ return Ok(());
+ }
+
+ frame.render_texture_from_to(
+ &self.buffer.texture,
+ src,
+ dest,
+ damage,
+ self.buffer.transform,
+ self.alpha,
+ )
+ }
+
+ fn underlying_storage(&self, _renderer: &mut R) -> Option<UnderlyingStorage<'_>> {
+ None
+ }
+}