aboutsummaryrefslogtreecommitdiff
path: root/src/render_helpers
diff options
context:
space:
mode:
Diffstat (limited to 'src/render_helpers')
-rw-r--r--src/render_helpers/mod.rs81
-rw-r--r--src/render_helpers/surface.rs108
2 files changed, 112 insertions, 77 deletions
diff --git a/src/render_helpers/mod.rs b/src/render_helpers/mod.rs
index c6c9fed1..e780de4e 100644
--- a/src/render_helpers/mod.rs
+++ b/src/render_helpers/mod.rs
@@ -3,15 +3,19 @@ use std::ptr;
use anyhow::{ensure, Context};
use niri_config::BlockOutFrom;
use smithay::backend::allocator::Fourcc;
-use smithay::backend::renderer::element::RenderElement;
+use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement};
+use smithay::backend::renderer::element::texture::{TextureBuffer, TextureRenderElement};
+use smithay::backend::renderer::element::{Kind, RenderElement};
use smithay::backend::renderer::gles::{GlesMapping, GlesRenderer, GlesTexture};
use smithay::backend::renderer::sync::SyncPoint;
use smithay::backend::renderer::{buffer_dimensions, Bind, ExportMem, Frame, Offscreen, Renderer};
use smithay::reexports::wayland_server::protocol::wl_buffer::WlBuffer;
use smithay::reexports::wayland_server::protocol::wl_shm;
-use smithay::utils::{Physical, Rectangle, Scale, Size, Transform};
+use smithay::utils::{Logical, Physical, Point, Rectangle, Scale, Size, Transform};
use smithay::wayland::shm;
+use self::primary_gpu_texture::PrimaryGpuTextureRenderElement;
+
pub mod gradient;
pub mod offscreen;
pub mod primary_gpu_pixel_shader;
@@ -32,20 +36,85 @@ pub enum RenderTarget {
ScreenCapture,
}
+/// Buffer with location, src and dst.
+#[derive(Debug)]
+pub struct BakedBuffer<B> {
+ pub buffer: B,
+ pub location: Point<i32, Logical>,
+ pub src: Option<Rectangle<f64, Logical>>,
+ pub dst: Option<Size<i32, Logical>>,
+}
+
/// Snapshot of a render.
#[derive(Debug)]
-pub struct RenderSnapshot<E> {
+pub struct RenderSnapshot<C, B> {
/// Contents for a normal render.
- pub contents: Vec<E>,
+ pub contents: Vec<C>,
/// Blocked-out contents.
- pub blocked_out_contents: Vec<E>,
+ pub blocked_out_contents: Vec<B>,
/// Where the contents were blocked out from at the time of the snapshot.
pub block_out_from: Option<BlockOutFrom>,
}
-impl<E> Default for RenderSnapshot<E> {
+pub trait ToRenderElement {
+ type RenderElement;
+
+ fn to_render_element(
+ &self,
+ location: Point<i32, Logical>,
+ scale: Scale<f64>,
+ alpha: f32,
+ kind: Kind,
+ ) -> Self::RenderElement;
+}
+
+impl ToRenderElement for BakedBuffer<TextureBuffer<GlesTexture>> {
+ type RenderElement = PrimaryGpuTextureRenderElement;
+
+ fn to_render_element(
+ &self,
+ location: Point<i32, Logical>,
+ 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.src,
+ self.dst,
+ kind,
+ );
+ PrimaryGpuTextureRenderElement(elem)
+ }
+}
+
+impl ToRenderElement for BakedBuffer<SolidColorBuffer> {
+ type RenderElement = SolidColorRenderElement;
+
+ fn to_render_element(
+ &self,
+ location: Point<i32, Logical>,
+ scale: Scale<f64>,
+ alpha: f32,
+ kind: Kind,
+ ) -> Self::RenderElement {
+ SolidColorRenderElement::from_buffer(
+ &self.buffer,
+ (location + self.location)
+ .to_physical_precise_round(scale)
+ .to_i32_round(),
+ scale,
+ alpha,
+ kind,
+ )
+ }
+}
+
+impl<C, B> Default for RenderSnapshot<C, B> {
fn default() -> Self {
Self {
contents: Default::default(),
diff --git a/src/render_helpers/surface.rs b/src/render_helpers/surface.rs
index ae7ffc32..21141b30 100644
--- a/src/render_helpers/surface.rs
+++ b/src/render_helpers/surface.rs
@@ -1,41 +1,25 @@
-use smithay::backend::renderer::element::surface::WaylandSurfaceRenderElement;
-use smithay::backend::renderer::element::texture::{TextureBuffer, TextureRenderElement};
-use smithay::backend::renderer::element::Kind;
-use smithay::backend::renderer::gles::GlesRenderer;
+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 _;
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
-use smithay::utils::{Physical, Point, Scale};
+use smithay::utils::{Logical, Point};
use smithay::wayland::compositor::{with_surface_tree_downward, TraversalAction};
-use super::primary_gpu_texture::PrimaryGpuTextureRenderElement;
-use super::renderer::NiriRenderer;
-use crate::layout::{LayoutElementRenderElement, LayoutElementSnapshotRenderElements};
+use super::BakedBuffer;
-/// Renders elements from a surface tree, as well as saves them as textures into `storage`.
-///
-/// Saved textures are based at (0, 0) to facilitate later offscreening. This is why the location
-/// argument is split into `location` and `offset`: the former is ignored for saved textures, but
-/// the latter isn't (for things like popups).
-#[allow(clippy::too_many_arguments)]
-pub fn render_and_save_from_surface_tree<R: NiriRenderer>(
- renderer: &mut R,
+/// Renders elements from a surface tree as textures into `storage`.
+pub fn render_snapshot_from_surface_tree(
+ renderer: &mut GlesRenderer,
surface: &WlSurface,
- location: Point<f64, Physical>,
- offset: Point<f64, Physical>,
- scale: Scale<f64>,
- alpha: f32,
- kind: Kind,
- elements: &mut Vec<LayoutElementRenderElement<R>>,
- storage: &mut Option<&mut Vec<LayoutElementSnapshotRenderElements>>,
+ location: Point<i32, Logical>,
+ storage: &mut Vec<BakedBuffer<TextureBuffer<GlesTexture>>>,
) {
- let _span = tracy_client::span!("render_and_save_from_surface_tree");
-
- let base_pos = location;
+ let _span = tracy_client::span!("render_snapshot_from_surface_tree");
with_surface_tree_downward(
surface,
- location + offset,
+ location,
|_, states, location| {
let mut location = *location;
let data = states.data_map.get::<RendererSurfaceStateUserData>();
@@ -44,7 +28,7 @@ pub fn render_and_save_from_surface_tree<R: NiriRenderer>(
let data = &*data.borrow();
if let Some(view) = data.view() {
- location += view.offset.to_f64().to_physical(scale);
+ location += view.offset;
TraversalAction::DoChildren(location)
} else {
TraversalAction::SkipChildren
@@ -53,62 +37,44 @@ pub fn render_and_save_from_surface_tree<R: NiriRenderer>(
TraversalAction::SkipChildren
}
},
- |surface, states, location| {
+ |_, states, location| {
let mut location = *location;
let data = states.data_map.get::<RendererSurfaceStateUserData>();
if let Some(data) = data {
if let Some(view) = data.borrow().view() {
- location += view.offset.to_f64().to_physical(scale);
+ location += view.offset;
} else {
return;
}
- let elem = match WaylandSurfaceRenderElement::from_surface(
- renderer, surface, states, location, alpha, kind,
- ) {
- Ok(elem) => elem,
- Err(err) => {
- warn!("failed to import surface: {err:?}");
- return;
- }
- };
-
- elements.push(elem.into());
-
- if let Some(storage) = storage {
- let renderer = renderer.as_gles_renderer();
- // FIXME (possibly in Smithay): this causes a re-upload for shm textures.
- if let Err(err) = import_surface(renderer, states) {
- warn!("failed to import surface: {err:?}");
- return;
- }
+ if let Err(err) = import_surface(renderer, states) {
+ warn!("failed to import surface: {err:?}");
+ return;
+ }
- let data = data.borrow();
- let view = data.view().unwrap();
- let Some(texture) = data.texture::<GlesRenderer>(renderer.id()) else {
- return;
- };
+ let data = data.borrow();
+ let view = data.view().unwrap();
+ let Some(texture) = data.texture::<GlesRenderer>(renderer.id()) else {
+ return;
+ };
- let buffer = TextureBuffer::from_texture(
- renderer,
- texture.clone(),
- data.buffer_scale(),
- data.buffer_transform(),
- None,
- );
+ let buffer = TextureBuffer::from_texture(
+ renderer,
+ texture.clone(),
+ data.buffer_scale(),
+ data.buffer_transform(),
+ None,
+ );
- let elem = TextureRenderElement::from_texture_buffer(
- location - base_pos,
- &buffer,
- Some(alpha),
- Some(view.src),
- Some(view.dst),
- kind,
- );
+ let baked = BakedBuffer {
+ buffer,
+ location,
+ src: Some(view.src),
+ dst: Some(view.dst),
+ };
- storage.push(PrimaryGpuTextureRenderElement(elem).into());
- }
+ storage.push(baked);
}
},
|_, _, _| true,