diff --git a/src/cursor.rs b/src/cursor.rs index 2bcd8651..9eb4b98b 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -295,6 +295,8 @@ fn render_img(image: &InstantiatedCursorImage, renderer: &mut Renderer, x: Fixed None, None, scale, + i32::MAX, + i32::MAX, ); } } @@ -306,9 +308,17 @@ impl Cursor for StaticCursor { fn render_hardware_cursor(&self, renderer: &mut Renderer) { if let Some(img) = self.image.scales.get(&renderer.scale()) { - renderer - .base - .render_texture(&img.tex, 0, 0, ARGB8888, None, None, renderer.scale()); + renderer.base.render_texture( + &img.tex, + 0, + 0, + ARGB8888, + None, + None, + renderer.scale(), + i32::MAX, + i32::MAX, + ); } } @@ -336,9 +346,17 @@ impl Cursor for AnimatedCursor { fn render_hardware_cursor(&self, renderer: &mut Renderer) { let img = &self.images[self.idx.get()]; if let Some(img) = img.scales.get(&renderer.scale()) { - renderer - .base - .render_texture(&img.tex, 0, 0, ARGB8888, None, None, renderer.scale()); + renderer.base.render_texture( + &img.tex, + 0, + 0, + ARGB8888, + None, + None, + renderer.scale(), + i32::MAX, + i32::MAX, + ); } } diff --git a/src/ifs/jay_screencast.rs b/src/ifs/jay_screencast.rs index dc368237..589ac7d4 100644 --- a/src/ifs/jay_screencast.rs +++ b/src/ifs/jay_screencast.rs @@ -147,7 +147,7 @@ impl JayScreencast { }); } - pub fn copy_texture(&self, on: &OutputNode, texture: &Texture) { + pub fn copy_texture(&self, on: &OutputNode, texture: &Rc) { if !self.running.get() { return; } diff --git a/src/ifs/wl_output.rs b/src/ifs/wl_output.rs index efa9c4a6..0b9a0282 100644 --- a/src/ifs/wl_output.rs +++ b/src/ifs/wl_output.rs @@ -199,7 +199,7 @@ impl WlOutputGlobal { Ok(()) } - pub fn perform_screencopies(&self, fb: &Framebuffer, tex: &Texture) { + pub fn perform_screencopies(&self, fb: &Framebuffer, tex: &Rc) { if self.pending_captures.is_empty() { return; } diff --git a/src/ifs/wl_surface.rs b/src/ifs/wl_surface.rs index ce7b85e1..77ff4692 100644 --- a/src/ifs/wl_surface.rs +++ b/src/ifs/wl_surface.rs @@ -38,7 +38,10 @@ use { leaks::Tracker, object::Object, rect::{Rect, Region}, - render::Renderer, + render::{ + gfx_api::{BufferPoint, BufferPoints}, + Renderer, + }, tree::{ FindTreeResult, FoundNode, Node, NodeId, NodeVisitor, NodeVisitorBase, OutputNode, ToplevelNode, @@ -101,20 +104,6 @@ impl Transform { } } -#[derive(Default, Debug)] -struct BufferPoint { - x: f32, - y: f32, -} - -#[derive(Default, Debug)] -struct BufferPoints { - top_right: BufferPoint, - top_left: BufferPoint, - bottom_right: BufferPoint, - bottom_left: BufferPoint, -} - impl Transform { fn apply_inv_sized(self, x1: f32, y1: f32, width: f32, height: f32) -> BufferPoints { let x2 = x1 + width; @@ -237,7 +226,7 @@ pub struct WlSurface { input_region: Cell>>, opaque_region: Cell>>, buffer_points: RefCell, - pub buffer_points_norm: RefCell<[f32; 8]>, + pub buffer_points_norm: RefCell, buffer_transform: Cell, buffer_scale: Cell, src_rect: Cell>, @@ -817,35 +806,12 @@ impl WlSurface { .buffer_transform .get() .apply_inv_sized(0.0, 0.0, 1.0, 1.0); - let points = &*buffer_points; - *buffer_points_norm = [ - points.top_right.x, - points.top_right.y, - points.top_left.x, - points.top_left.y, - points.bottom_right.x, - points.bottom_right.y, - points.bottom_left.x, - points.bottom_left.y, - ]; + *buffer_points_norm = *buffer_points; } else { - let width = buffer.rect.width() as f32; - let height = buffer.rect.height() as f32; - let points = &*buffer_points; - *buffer_points_norm = [ - points.top_right.x / width, - points.top_right.y / height, - points.top_left.x / width, - points.top_left.y / height, - points.bottom_right.x / width, - points.bottom_right.y / height, - points.bottom_left.x / width, - points.bottom_left.y / height, - ]; - for &v in buffer_points_norm.iter() { - if v > 1.0 { - return Err(WlSurfaceError::ViewportOutsideBuffer); - } + *buffer_points_norm = buffer_points + .norm(buffer.rect.width() as f32, buffer.rect.height() as f32); + if !buffer_points_norm.is_leq_1() { + return Err(WlSurfaceError::ViewportOutsideBuffer); } } } @@ -1134,8 +1100,15 @@ impl Node for WlSurface { } } - fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { - renderer.render_surface(self, x, y); + fn node_render( + &self, + renderer: &mut Renderer, + x: i32, + y: i32, + max_width: i32, + max_height: i32, + ) { + renderer.render_surface(self, x, y, max_width, max_height); } fn node_client(&self) -> Option> { diff --git a/src/ifs/wl_surface/cursor.rs b/src/ifs/wl_surface/cursor.rs index f42d8d0c..888a21d3 100644 --- a/src/ifs/wl_surface/cursor.rs +++ b/src/ifs/wl_surface/cursor.rs @@ -76,16 +76,28 @@ impl Cursor for CursorSurface { let (hot_x, hot_y) = (Fixed::from_int(hot_x), Fixed::from_int(hot_y)); let x = ((x - hot_x).to_f64() * scale).round() as _; let y = ((y - hot_y).to_f64() * scale).round() as _; - renderer.render_surface_scaled(&self.surface, x, y, None); + renderer.render_surface_scaled(&self.surface, x, y, None, i32::MAX, i32::MAX); } else { - renderer.render_surface(&self.surface, x_int - hot_x, y_int - hot_y); + renderer.render_surface( + &self.surface, + x_int - hot_x, + y_int - hot_y, + i32::MAX, + i32::MAX, + ); } } } fn render_hardware_cursor(&self, renderer: &mut Renderer) { let extents = self.surface.extents.get(); - renderer.render_surface(&self.surface, -extents.x1(), -extents.y1()); + renderer.render_surface( + &self.surface, + -extents.x1(), + -extents.y1(), + i32::MAX, + i32::MAX, + ); struct FrameRequests; impl NodeVisitorBase for FrameRequests { diff --git a/src/ifs/wl_surface/x_surface/xwindow.rs b/src/ifs/wl_surface/x_surface/xwindow.rs index 256b086b..e5851249 100644 --- a/src/ifs/wl_surface/x_surface/xwindow.rs +++ b/src/ifs/wl_surface/x_surface/xwindow.rs @@ -334,8 +334,15 @@ impl Node for Xwindow { FindTreeResult::Other } - fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { - renderer.render_surface(&self.x.surface, x, y) + fn node_render( + &self, + renderer: &mut Renderer, + x: i32, + y: i32, + max_width: i32, + max_height: i32, + ) { + renderer.render_surface(&self.x.surface, x, y, max_width, max_height) } fn node_client(&self) -> Option> { diff --git a/src/ifs/wl_surface/xdg_surface/xdg_popup.rs b/src/ifs/wl_surface/xdg_surface/xdg_popup.rs index 29380b4a..993fb30a 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_popup.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_popup.rs @@ -308,8 +308,15 @@ impl Node for XdgPopup { self.xdg.find_tree_at(x, y, tree) } - fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { - renderer.render_xdg_surface(&self.xdg, x, y) + fn node_render( + &self, + renderer: &mut Renderer, + x: i32, + y: i32, + max_width: i32, + max_height: i32, + ) { + renderer.render_xdg_surface(&self.xdg, x, y, max_width, max_height) } fn node_client(&self) -> Option> { diff --git a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs index 0965db63..ad013aea 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs @@ -425,8 +425,15 @@ impl Node for XdgToplevel { self.xdg.find_tree_at(x, y, tree) } - fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { - renderer.render_xdg_surface(&self.xdg, x, y) + fn node_render( + &self, + renderer: &mut Renderer, + x: i32, + y: i32, + max_width: i32, + max_height: i32, + ) { + renderer.render_xdg_surface(&self.xdg, x, y, max_width, max_height) } fn node_client(&self) -> Option> { diff --git a/src/ifs/wl_surface/zwlr_layer_surface_v1.rs b/src/ifs/wl_surface/zwlr_layer_surface_v1.rs index ecedd8ee..34f158e1 100644 --- a/src/ifs/wl_surface/zwlr_layer_surface_v1.rs +++ b/src/ifs/wl_surface/zwlr_layer_surface_v1.rs @@ -394,7 +394,14 @@ impl Node for ZwlrLayerSurfaceV1 { self.surface.find_tree_at_(x, y, tree) } - fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { + fn node_render( + &self, + renderer: &mut Renderer, + x: i32, + y: i32, + _max_width: i32, + _max_height: i32, + ) { renderer.render_layer_surface(self, x, y); } } diff --git a/src/portal/ptr_gui.rs b/src/portal/ptr_gui.rs index 19f4a9bf..9a5f2c24 100644 --- a/src/portal/ptr_gui.rs +++ b/src/portal/ptr_gui.rs @@ -219,6 +219,8 @@ impl GuiElement for Button { None, None, r.scale(), + i32::MAX, + i32::MAX, ); } } @@ -315,6 +317,8 @@ impl GuiElement for Label { None, None, r.scale(), + i32::MAX, + i32::MAX, ); } } diff --git a/src/render/gl/frame_buffer.rs b/src/render/gl/frame_buffer.rs index 7c5cad83..edfa62bf 100644 --- a/src/render/gl/frame_buffer.rs +++ b/src/render/gl/frame_buffer.rs @@ -1,18 +1,13 @@ use { - crate::{ - rect::Rect, - render::{ - egl::context::EglContext, - gl::{ - render_buffer::GlRenderBuffer, - sys::{glDeleteFramebuffers, GLuint}, - texture::GlTexture, - }, - sys::{glDisable, glEnable, glScissor, GL_SCISSOR_TEST}, + crate::render::{ + egl::context::EglContext, + gl::{ + render_buffer::GlRenderBuffer, + sys::{glDeleteFramebuffers, GLuint}, + texture::GlTexture, }, - utils::ptr_ext::PtrExt, }, - std::{ptr, rc::Rc}, + std::rc::Rc, }; pub struct GlFrameBuffer { @@ -34,29 +29,3 @@ impl Drop for GlFrameBuffer { }); } } - -pub unsafe fn with_scissor T>(scissor: &Rect, f: F) -> T { - #[thread_local] - static mut SCISSOR: *const Rect = ptr::null(); - - let prev = SCISSOR; - if prev.is_null() { - glEnable(GL_SCISSOR_TEST); - } - glScissor( - scissor.x1(), - scissor.y1(), - scissor.width(), - scissor.height(), - ); - SCISSOR = scissor; - let res = f(); - if prev.is_null() { - glDisable(GL_SCISSOR_TEST); - } else { - let prev = prev.deref(); - glScissor(prev.x1(), prev.y1(), prev.width(), prev.height()); - } - SCISSOR = prev; - res -} diff --git a/src/render/gl/sys.rs b/src/render/gl/sys.rs index 7c04973e..54bf0754 100644 --- a/src/render/gl/sys.rs +++ b/src/render/gl/sys.rs @@ -28,7 +28,6 @@ pub const GL_FRAMEBUFFER: GLenum = 0x8D40; pub const GL_LINEAR: GLint = 0x2601; pub const GL_LINK_STATUS: GLenum = 0x8B82; pub const GL_RENDERBUFFER: GLenum = 0x8D41; -pub const GL_SCISSOR_TEST: GLenum = 0x0C11; pub const GL_TEXTURE0: GLenum = 0x84C0; pub const GL_TEXTURE_2D: GLenum = 0x0DE1; pub const GL_TEXTURE_EXTERNAL_OES: GLenum = 0x8D65; @@ -106,7 +105,6 @@ extern "C" { pixels: *const c::c_void, ); - pub fn glScissor(x: GLint, y: GLint, width: GLsizei, height: GLsizei); pub fn glEnable(cap: GLenum); pub fn glDisable(cap: GLenum); pub fn glViewport(x: GLint, y: GLint, width: GLsizei, height: GLsizei); diff --git a/src/render/renderer.rs b/src/render/renderer.rs index e399a8e4..62d302ca 100644 --- a/src/render/renderer.rs +++ b/src/render/renderer.rs @@ -2,6 +2,7 @@ pub use {context::*, framebuffer::*, image::*, renderer::*, renderer_base::*, te mod context; mod framebuffer; +pub mod gfx_api; mod gfx_apis; mod image; mod renderer; diff --git a/src/render/renderer/context.rs b/src/render/renderer/context.rs index 0be13b30..50f6ba07 100644 --- a/src/render/renderer/context.rs +++ b/src/render/renderer/context.rs @@ -7,10 +7,11 @@ use { display::{EglDisplay, EglFormat}, }, ext::GlExt, + gfx_api::GfxApiOpt, gl::{ program::GlProgram, render_buffer::GlRenderBuffer, sys::GLint, texture::GlTexture, }, - renderer::{framebuffer::Framebuffer, image::Image}, + renderer::{framebuffer::Framebuffer, gfx_apis::gl::GfxGlState, image::Image}, RenderError, Texture, }, video::{ @@ -21,7 +22,7 @@ use { }, ahash::AHashMap, std::{ - cell::Cell, + cell::{Cell, RefCell}, ffi::CString, fmt::{Debug, Formatter}, rc::Rc, @@ -64,6 +65,9 @@ pub struct RenderContext { pub(super) fill_prog: GlProgram, pub(super) fill_prog_pos: GLint, pub(super) fill_prog_color: GLint, + + pub(super) gfx_ops: RefCell>, + pub(super) gl_state: RefCell, } impl Debug for RenderContext { @@ -153,6 +157,9 @@ impl RenderContext { fill_prog_pos: fill_prog.get_attrib_location(ustr!("pos")), fill_prog_color: fill_prog.get_uniform_location(ustr!("color")), fill_prog, + + gfx_ops: Default::default(), + gl_state: Default::default(), }) } diff --git a/src/render/renderer/framebuffer.rs b/src/render/renderer/framebuffer.rs index af163016..999f5677 100644 --- a/src/render/renderer/framebuffer.rs +++ b/src/render/renderer/framebuffer.rs @@ -12,7 +12,10 @@ use { GL_FRAMEBUFFER, }, }, - renderer::{context::RenderContext, renderer::Renderer, renderer_base::RendererBase}, + renderer::{ + context::RenderContext, gfx_apis::gl::run_ops, renderer::Renderer, + renderer_base::RendererBase, + }, sys::{glBlendFunc, glFlush, glReadnPixels, GL_ONE, GL_ONE_MINUS_SRC_ALPHA}, RenderResult, Texture, }, @@ -55,7 +58,31 @@ impl Framebuffer { }); } - pub fn copy_texture(&self, state: &State, texture: &Texture, x: i32, y: i32, alpha: bool) { + pub fn copy_texture(&self, state: &State, texture: &Rc, x: i32, y: i32, alpha: bool) { + let mut ops = self.ctx.gfx_ops.borrow_mut(); + ops.clear(); + let scale = Scale::from_int(1); + let extents = Rect::new_sized(0, 0, self.gl.width, self.gl.height).unwrap(); + let mut renderer = Renderer { + base: RendererBase { + ops: &mut ops, + scaled: false, + scale, + scalef: 1.0, + }, + state, + on_output: false, + result: &mut RenderResult::default(), + logical_extents: extents, + physical_extents: extents, + }; + let format = match alpha { + true => ARGB8888, + false => XRGB8888, + }; + renderer + .base + .render_texture(texture, x, y, format, None, None, scale, i32::MAX, i32::MAX); let _ = self.ctx.ctx.with_current(|| { unsafe { glBindFramebuffer(GL_FRAMEBUFFER, self.gl.fbo); @@ -66,27 +93,7 @@ impl Framebuffer { } glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } - let scale = Scale::from_int(1); - let mut renderer = Renderer { - base: RendererBase { - ctx: &self.ctx, - fb: &self.gl, - scaled: false, - scale, - scalef: 1.0, - }, - state, - on_output: false, - result: &mut RenderResult::default(), - logical_extents: Rect::new_sized(0, 0, self.gl.width, self.gl.height).unwrap(), - }; - let format = match alpha { - true => ARGB8888, - false => XRGB8888, - }; - renderer - .base - .render_texture(texture, x, y, format, None, None, scale); + run_ops(self, &ops); unsafe { glFlush(); } @@ -124,20 +131,22 @@ impl Framebuffer { } pub fn render_custom(&self, scale: Scale, f: impl FnOnce(&mut RendererBase)) { + let mut ops = self.ctx.gfx_ops.borrow_mut(); + ops.clear(); + let mut renderer = RendererBase { + ops: &mut ops, + scaled: scale != 1, + scale, + scalef: scale.to_f64(), + }; + f(&mut renderer); let _ = self.ctx.ctx.with_current(|| { unsafe { glBindFramebuffer(GL_FRAMEBUFFER, self.gl.fbo); glViewport(0, 0, self.gl.width, self.gl.height); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } - let mut renderer = RendererBase { - ctx: &self.ctx, - fb: &self.gl, - scaled: scale != 1, - scale, - scalef: scale.to_f64(), - }; - f(&mut renderer); + run_ops(self, &ops); unsafe { glFlush(); } @@ -155,6 +164,47 @@ impl Framebuffer { scale: Scale, render_hardware_cursor: bool, ) { + let mut ops = self.ctx.gfx_ops.borrow_mut(); + ops.clear(); + let mut renderer = Renderer { + base: RendererBase { + ops: &mut ops, + scaled: scale != 1, + scale, + scalef: scale.to_f64(), + }, + state, + on_output, + result, + logical_extents: node.node_absolute_position().at_point(0, 0), + physical_extents: Rect::new(0, 0, self.gl.width, self.gl.height).unwrap(), + }; + node.node_render(&mut renderer, 0, 0, i32::MAX, i32::MAX); + if let Some(rect) = cursor_rect { + let seats = state.globals.lock_seats(); + for seat in seats.values() { + if !render_hardware_cursor && seat.hardware_cursor() { + continue; + } + if let Some(cursor) = seat.get_cursor() { + let (mut x, mut y) = seat.get_position(); + if let Some(dnd_icon) = seat.dnd_icon() { + let extents = dnd_icon.extents.get().move_( + x.round_down() + dnd_icon.buf_x.get(), + y.round_down() + dnd_icon.buf_y.get(), + ); + if extents.intersects(&rect) { + let (x, y) = rect.translate(extents.x1(), extents.y1()); + renderer.render_surface(&dnd_icon, x, y, i32::MAX, i32::MAX); + } + } + cursor.tick(); + x -= Fixed::from_int(rect.x1()); + y -= Fixed::from_int(rect.y1()); + cursor.render(&mut renderer, x, y); + } + } + } let _ = self.ctx.ctx.with_current(|| { let c = state.theme.colors.background.get(); unsafe { @@ -164,45 +214,7 @@ impl Framebuffer { glClear(GL_COLOR_BUFFER_BIT); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } - let mut renderer = Renderer { - base: RendererBase { - ctx: &self.ctx, - fb: &self.gl, - scaled: scale != 1, - scale, - scalef: scale.to_f64(), - }, - state, - on_output, - result, - logical_extents: node.node_absolute_position().at_point(0, 0), - }; - node.node_render(&mut renderer, 0, 0); - if let Some(rect) = cursor_rect { - let seats = state.globals.lock_seats(); - for seat in seats.values() { - if !render_hardware_cursor && seat.hardware_cursor() { - continue; - } - if let Some(cursor) = seat.get_cursor() { - let (mut x, mut y) = seat.get_position(); - if let Some(dnd_icon) = seat.dnd_icon() { - let extents = dnd_icon.extents.get().move_( - x.round_down() + dnd_icon.buf_x.get(), - y.round_down() + dnd_icon.buf_y.get(), - ); - if extents.intersects(&rect) { - let (x, y) = rect.translate(extents.x1(), extents.y1()); - renderer.render_surface(&dnd_icon, x, y); - } - } - cursor.tick(); - x -= Fixed::from_int(rect.x1()); - y -= Fixed::from_int(rect.y1()); - cursor.render(&mut renderer, x, y); - } - } - } + run_ops(self, &ops); unsafe { glFlush(); } @@ -211,6 +223,23 @@ impl Framebuffer { } pub fn render_hardware_cursor(&self, cursor: &dyn Cursor, state: &State, scale: Scale) { + let mut ops = self.ctx.gfx_ops.borrow_mut(); + ops.clear(); + let mut res = RenderResult::default(); + let mut renderer = Renderer { + base: RendererBase { + ops: &mut ops, + scaled: scale != 1, + scale, + scalef: scale.to_f64(), + }, + state, + on_output: false, + result: &mut res, + logical_extents: Rect::new_empty(0, 0), + physical_extents: Rect::new(0, 0, self.gl.width, self.gl.height).unwrap(), + }; + cursor.render_hardware_cursor(&mut renderer); let _ = self.ctx.ctx.with_current(|| { unsafe { glBindFramebuffer(GL_FRAMEBUFFER, self.gl.fbo); @@ -219,21 +248,7 @@ impl Framebuffer { glClear(GL_COLOR_BUFFER_BIT); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } - let mut res = RenderResult::default(); - let mut renderer = Renderer { - base: RendererBase { - ctx: &self.ctx, - fb: &self.gl, - scaled: scale != 1, - scale, - scalef: scale.to_f64(), - }, - state, - on_output: false, - result: &mut res, - logical_extents: Rect::new_empty(0, 0), - }; - cursor.render_hardware_cursor(&mut renderer); + run_ops(self, &ops); unsafe { glFlush(); } diff --git a/src/render/renderer/gfx_api.rs b/src/render/renderer/gfx_api.rs new file mode 100644 index 00000000..2790cb7b --- /dev/null +++ b/src/render/renderer/gfx_api.rs @@ -0,0 +1,84 @@ +use { + crate::{format::Format, render::Texture, theme::Color}, + std::rc::Rc, +}; + +pub enum GfxApiOpt { + Sync, + Clear(Clear), + FillRect(FillRect), + CopyTexture(CopyTexture), +} + +#[derive(Default, Debug, Copy, Clone)] +pub struct BufferPoint { + pub x: f32, + pub y: f32, +} + +impl BufferPoint { + pub fn is_leq_1(&self) -> bool { + self.x <= 1.0 && self.y <= 1.0 + } +} + +#[derive(Default, Debug, Copy, Clone)] +pub struct BufferPoints { + pub top_left: BufferPoint, + pub top_right: BufferPoint, + pub bottom_left: BufferPoint, + pub bottom_right: BufferPoint, +} + +impl BufferPoints { + pub fn norm(&self, width: f32, height: f32) -> Self { + Self { + top_left: BufferPoint { + x: self.top_left.x / width, + y: self.top_left.y / height, + }, + top_right: BufferPoint { + x: self.top_right.x / width, + y: self.top_right.y / height, + }, + bottom_left: BufferPoint { + x: self.bottom_left.x / width, + y: self.bottom_left.y / height, + }, + bottom_right: BufferPoint { + x: self.bottom_right.x / width, + y: self.bottom_right.y / height, + }, + } + } + + pub fn is_leq_1(&self) -> bool { + self.top_left.is_leq_1() + && self.top_right.is_leq_1() + && self.bottom_left.is_leq_1() + && self.bottom_right.is_leq_1() + } +} + +pub struct AbsoluteRect { + pub x1: f32, + pub x2: f32, + pub y1: f32, + pub y2: f32, +} + +pub struct Clear { + pub color: Color, +} + +pub struct FillRect { + pub rect: AbsoluteRect, + pub color: Color, +} + +pub struct CopyTexture { + pub tex: Rc, + pub format: &'static Format, + pub source: BufferPoints, + pub target: AbsoluteRect, +} diff --git a/src/render/renderer/gfx_apis/gl.rs b/src/render/renderer/gfx_apis/gl.rs index 6b258374..f774cec7 100644 --- a/src/render/renderer/gfx_apis/gl.rs +++ b/src/render/renderer/gfx_apis/gl.rs @@ -1,29 +1,129 @@ -use crate::{ - format::Format, - render::{ - gl::{frame_buffer::GlFrameBuffer, texture::image_target}, - sys::{ - glActiveTexture, glBindTexture, glClear, glClearColor, glDisable, - glDisableVertexAttribArray, glDrawArrays, glEnable, glEnableVertexAttribArray, - glTexParameteri, glUniform1i, glUniform4f, glUseProgram, glVertexAttribPointer, - GL_BLEND, GL_COLOR_BUFFER_BIT, GL_FALSE, GL_FLOAT, GL_LINEAR, GL_TEXTURE0, - GL_TEXTURE_MIN_FILTER, GL_TRIANGLES, GL_TRIANGLE_STRIP, +use { + crate::{ + format::Format, + render::{ + gfx_api::{BufferPoints, CopyTexture, FillRect, GfxApiOpt}, + gl::texture::image_target, + sys::{ + glActiveTexture, glBindTexture, glClear, glClearColor, glDisable, + glDisableVertexAttribArray, glDrawArrays, glEnable, glEnableVertexAttribArray, + glTexParameteri, glUniform1i, glUniform4f, glUseProgram, glVertexAttribPointer, + GL_BLEND, GL_COLOR_BUFFER_BIT, GL_FALSE, GL_FLOAT, GL_LINEAR, GL_TEXTURE0, + GL_TEXTURE_MIN_FILTER, GL_TRIANGLES, GL_TRIANGLE_STRIP, + }, + Framebuffer, RenderContext, Texture, }, - RenderContext, Texture, + theme::Color, + utils::{rc_eq::rc_eq, vecstorage::VecStorage}, }, - scale::Scale, - theme::Color, - utils::rc_eq::rc_eq, + isnt::std_1::vec::IsntVecExt, + std::cell::RefCell, }; -pub fn clear(c: &Color) { +#[derive(Default)] +pub struct GfxGlState { + triangles: RefCell>, + fill_rect: VecStorage<&'static FillRect>, + copy_tex: VecStorage<&'static CopyTexture>, +} + +pub fn run_ops(fb: &Framebuffer, ops: &[GfxApiOpt]) { + let mut state = fb.ctx.gl_state.borrow_mut(); + let state = &mut *state; + let mut fill_rect = state.fill_rect.take(); + let fill_rect = &mut *fill_rect; + let mut copy_tex = state.copy_tex.take(); + let copy_tex = &mut *copy_tex; + let mut triangles = state.triangles.borrow_mut(); + let triangles = &mut *triangles; + let width = fb.gl.width as f32; + let height = fb.gl.height as f32; + let mut i = 0; + while i < ops.len() { + macro_rules! has_ops { + () => { + fill_rect.is_not_empty() || copy_tex.is_not_empty() + }; + } + fill_rect.clear(); + copy_tex.clear(); + while i < ops.len() { + match &ops[i] { + GfxApiOpt::Sync => { + i += 1; + if has_ops!() { + break; + } + } + GfxApiOpt::Clear(c) => { + if has_ops!() { + break; + } + clear(&c.color); + i += 1; + } + GfxApiOpt::FillRect(f) => { + fill_rect.push(f); + i += 1; + } + GfxApiOpt::CopyTexture(c) => { + copy_tex.push(c); + i += 1; + } + } + } + if fill_rect.is_not_empty() { + fill_rect.sort_unstable_by_key(|f| f.color); + let mut i = 0; + while i < fill_rect.len() { + triangles.clear(); + let mut color = None; + while i < fill_rect.len() { + let fr = fill_rect[i]; + match color { + None => color = Some(fr.color), + Some(c) if c == fr.color => {} + _ => break, + } + let x1 = 2.0 * (fr.rect.x1 / width) - 1.0; + let x2 = 2.0 * (fr.rect.x2 / width) - 1.0; + let y1 = 2.0 * (fr.rect.y1 / height) - 1.0; + let y2 = 2.0 * (fr.rect.y2 / height) - 1.0; + triangles.extend_from_slice(&[ + // triangle 1 + x2, y1, // top right + x1, y1, // top left + x1, y2, // bottom left + // triangle 2 + x2, y1, // top right + x1, y2, // bottom left + x2, y2, // bottom right + ]); + i += 1; + } + if let Some(color) = color { + fill_boxes3(&fb.ctx, triangles, &color); + } + } + } + for tex in &*copy_tex { + let x1 = 2.0 * (tex.target.x1 / width) - 1.0; + let y1 = 2.0 * (tex.target.y1 / height) - 1.0; + let x2 = 2.0 * (tex.target.x2 / width) - 1.0; + let y2 = 2.0 * (tex.target.y2 / height) - 1.0; + render_texture(&fb.ctx, &tex.tex, tex.format, x1, y1, x2, y2, &tex.source) + } + } +} + +fn clear(c: &Color) { unsafe { glClearColor(c.r, c.g, c.b, c.a); glClear(GL_COLOR_BUFFER_BIT); } } -pub fn fill_boxes3(ctx: &RenderContext, boxes: &[f32], color: &Color) { +fn fill_boxes3(ctx: &RenderContext, boxes: &[f32], color: &Color) { unsafe { glUseProgram(ctx.fill_prog.prog); glUniform4f(ctx.fill_prog_color, color.r, color.g, color.b, color.a); @@ -41,18 +141,15 @@ pub fn fill_boxes3(ctx: &RenderContext, boxes: &[f32], color: &Color) { } } -pub fn render_texture( +fn render_texture( ctx: &RenderContext, - fb: &GlFrameBuffer, texture: &Texture, - x: i32, - y: i32, format: &Format, - tpoints: Option<&[f32; 8]>, - tsize: Option<(i32, i32)>, - tscale: Scale, - scale: Scale, - scalef: f64, + x1: f32, + y1: f32, + x2: f32, + y2: f32, + src: &BufferPoints, ) { assert!(rc_eq(&ctx.ctx, &texture.ctx.ctx)); unsafe { @@ -88,34 +185,18 @@ pub fn render_texture( glUniform1i(prog.tex, 0); - static DEFAULT_TEXCOORD: [f32; 8] = [1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0]; + let texcoord = [ + src.top_right.x, + src.top_right.y, + src.top_left.x, + src.top_left.y, + src.bottom_right.x, + src.bottom_right.y, + src.bottom_left.x, + src.bottom_left.y, + ]; - let texcoord: &[f32; 8] = match tpoints { - None => &DEFAULT_TEXCOORD, - Some(tp) => tp, - }; - - let f_width = fb.width as f32; - let f_height = fb.height as f32; - - let (twidth, theight) = if let Some(size) = tsize { - size - } else { - let (mut w, mut h) = (texture.gl.width, texture.gl.height); - if tscale != scale { - let tscale = tscale.to_f64(); - w = (w as f64 * scalef / tscale).round() as _; - h = (h as f64 * scalef / tscale).round() as _; - } - (w, h) - }; - - let x1 = 2.0 * (x as f32 / f_width) - 1.0; - let y1 = 2.0 * (y as f32 / f_height) - 1.0; - let x2 = 2.0 * ((x + twidth) as f32 / f_width) - 1.0; - let y2 = 2.0 * ((y + theight) as f32 / f_height) - 1.0; - - let pos: [f32; 8] = [ + let pos = [ x2, y1, // top right x1, y1, // top left x2, y2, // bottom right diff --git a/src/render/renderer/renderer.rs b/src/render/renderer/renderer.rs index 2a29e6e6..35f4a67e 100644 --- a/src/render/renderer/renderer.rs +++ b/src/render/renderer/renderer.rs @@ -10,7 +10,10 @@ use { wp_presentation_feedback::WpPresentationFeedback, }, rect::Rect, - render::{gl::frame_buffer::with_scissor, renderer::renderer_base::RendererBase}, + render::{ + gfx_api::GfxApiOpt, + renderer::{gfx_api::BufferPoints, renderer_base::RendererBase}, + }, scale::Scale, state::State, theme::Color, @@ -45,6 +48,7 @@ pub struct Renderer<'a> { pub(super) on_output: bool, pub(super) result: &'a mut RenderResult, pub(super) logical_extents: Rect, + pub(super) physical_extents: Rect, } impl Renderer<'_> { @@ -53,7 +57,7 @@ impl Renderer<'_> { } pub fn physical_extents(&self) -> Rect { - self.base.physical_extents() + self.physical_extents } pub fn logical_extents(&self) -> Rect { @@ -74,7 +78,7 @@ impl Renderer<'_> { if self.state.lock.locked.get() { if let Some(surface) = output.lock_surface.get() { if surface.surface.buffer.get().is_some() { - self.render_surface(&surface.surface, x, y); + self.render_surface(&surface.surface, x, y, i32::MAX, i32::MAX); } } return; @@ -94,7 +98,7 @@ impl Renderer<'_> { } if let Some(ws) = output.workspace.get() { if let Some(fs) = ws.fullscreen.get() { - fs.tl_as_node().node_render(self, x, y); + fs.tl_as_node().node_render(self, x, y, i32::MAX, i32::MAX); render_layer!(output.layers[2]); render_layer!(output.layers[3]); return; @@ -136,13 +140,31 @@ impl Renderer<'_> { let scale = output.preferred_scale.get(); for title in &rd.titles { let (x, y) = self.base.scale_point(x + title.tex_x, y + title.tex_y); - self.base - .render_texture(&title.tex, x, y, ARGB8888, None, None, scale); + self.base.render_texture( + &title.tex, + x, + y, + ARGB8888, + None, + None, + scale, + i32::MAX, + i32::MAX, + ); } if let Some(status) = &rd.status { let (x, y) = self.base.scale_point(x + status.tex_x, y + status.tex_y); - self.base - .render_texture(&status.tex, x, y, ARGB8888, None, None, scale); + self.base.render_texture( + &status.tex, + x, + y, + ARGB8888, + None, + None, + scale, + i32::MAX, + i32::MAX, + ); } } if let Some(ws) = output.workspace.get() { @@ -150,10 +172,11 @@ impl Renderer<'_> { } for stacked in self.state.root.stacked.iter() { if stacked.node_visible() { + self.base.ops.push(GfxApiOpt::Sync); let pos = stacked.node_absolute_position(); if pos.intersects(&opos) { let (x, y) = opos.translate(pos.x1(), pos.y1()); - stacked.node_render(self, x, y); + stacked.node_render(self, x, y, i32::MAX, i32::MAX); } } } @@ -176,8 +199,17 @@ impl Renderer<'_> { if let Some(tex) = placeholder.textures.get(&self.base.scale) { let x = x + (pos.width() - tex.width()) / 2; let y = y + (pos.height() - tex.height()) / 2; - self.base - .render_texture(&tex, x, y, ARGB8888, None, None, self.base.scale); + self.base.render_texture( + &tex, + x, + y, + ARGB8888, + None, + None, + self.base.scale, + i32::MAX, + i32::MAX, + ); } } @@ -212,21 +244,23 @@ impl Renderer<'_> { None, None, self.base.scale, + i32::MAX, + i32::MAX, ); } } } if let Some(child) = container.mono_child.get() { - unsafe { - let body = container.mono_body.get().move_(x, y); - let body = self.base.scale_rect(body); - with_scissor(&body, || { - let content = container.mono_content.get(); - child - .node - .node_render(self, x + content.x1(), y + content.y1()); - }); - } + let body = container.mono_body.get().move_(x, y); + let body = self.base.scale_rect(body); + let content = container.mono_content.get(); + child.node.node_render( + self, + x + content.x1(), + y + content.y1(), + body.width(), + body.height(), + ); } else { for child in container.children.iter() { let body = child.body.get(); @@ -235,31 +269,45 @@ impl Renderer<'_> { } let body = body.move_(x, y); let body = self.base.scale_rect(body); - unsafe { - with_scissor(&body, || { - let content = child.content.get(); - child - .node - .node_render(self, x + content.x1(), y + content.y1()); - }); - } + let content = child.content.get(); + child.node.node_render( + self, + x + content.x1(), + y + content.y1(), + body.width(), + body.height(), + ); } } } - pub fn render_xdg_surface(&mut self, xdg: &XdgSurface, mut x: i32, mut y: i32) { + pub fn render_xdg_surface( + &mut self, + xdg: &XdgSurface, + mut x: i32, + mut y: i32, + max_width: i32, + max_height: i32, + ) { let surface = &xdg.surface; if let Some(geo) = xdg.geometry() { let (xt, yt) = geo.translate(x, y); x = xt; y = yt; } - self.render_surface(surface, x, y); + self.render_surface(surface, x, y, max_width, max_height); } - pub fn render_surface(&mut self, surface: &WlSurface, x: i32, y: i32) { + pub fn render_surface( + &mut self, + surface: &WlSurface, + x: i32, + y: i32, + max_width: i32, + max_height: i32, + ) { let (x, y) = self.base.scale_point(x, y); - self.render_surface_scaled(surface, x, y, None); + self.render_surface_scaled(surface, x, y, None, max_width, max_height); } pub fn render_surface_scaled( @@ -268,6 +316,8 @@ impl Renderer<'_> { x: i32, y: i32, pos_rel: Option<(i32, i32)>, + max_width: i32, + max_height: i32, ) { let children = surface.children.borrow(); let buffer = match surface.buffer.get() { @@ -302,15 +352,17 @@ impl Renderer<'_> { x + x1, y + y1, Some((pos.x1(), pos.y1())), + max_width, + max_height, ); } }; } render!(&children.below); - self.render_buffer(&buffer, x, y, &tpoints, size); + self.render_buffer(&buffer, x, y, *tpoints, size, max_width, max_height); render!(&children.above); } else { - self.render_buffer(&buffer, x, y, &tpoints, size); + self.render_buffer(&buffer, x, y, *tpoints, size, max_width, max_height); } if self.on_output { { @@ -329,8 +381,10 @@ impl Renderer<'_> { buffer: &WlBuffer, x: i32, y: i32, - tpoints: &[f32; 8], + tpoints: BufferPoints, tsize: (i32, i32), + max_width: i32, + max_height: i32, ) { if let Some(tex) = buffer.texture.get() { self.base.render_texture( @@ -341,6 +395,8 @@ impl Renderer<'_> { Some(tpoints), Some(tsize), self.base.scale, + max_width, + max_height, ); } } @@ -374,8 +430,17 @@ impl Renderer<'_> { self.base.fill_boxes(&title_underline, &uc); if let Some(title) = floating.title_textures.get(&self.base.scale) { let (x, y) = self.base.scale_point(x + bw, y + bw); - self.base - .render_texture(&title, x, y, ARGB8888, None, None, self.base.scale); + self.base.render_texture( + &title, + x, + y, + ARGB8888, + None, + None, + self.base.scale, + i32::MAX, + i32::MAX, + ); } let body = Rect::new_sized( x + bw, @@ -385,20 +450,18 @@ impl Renderer<'_> { ) .unwrap(); let scissor_body = self.base.scale_rect(body); - unsafe { - with_scissor(&scissor_body, || { - child.node_render(self, body.x1(), body.y1()); - }); - } + child.node_render( + self, + body.x1(), + body.y1(), + scissor_body.width(), + scissor_body.height(), + ); } pub fn render_layer_surface(&mut self, surface: &ZwlrLayerSurfaceV1, x: i32, y: i32) { - unsafe { - let body = surface.position().at_point(x, y); - let body = self.base.scale_rect(body); - with_scissor(&body, || { - self.render_surface(&surface.surface, x, y); - }); - } + let body = surface.position().at_point(x, y); + let body = self.base.scale_rect(body); + self.render_surface(&surface.surface, x, y, body.width(), body.height()); } } diff --git a/src/render/renderer/renderer_base.rs b/src/render/renderer/renderer_base.rs index b2da03f7..0b751370 100644 --- a/src/render/renderer/renderer_base.rs +++ b/src/render/renderer/renderer_base.rs @@ -3,8 +3,10 @@ use { format::Format, rect::Rect, render::{ - gl::frame_buffer::GlFrameBuffer, - renderer::{context::RenderContext, gfx_apis::gl}, + gfx_api::Clear, + renderer::gfx_api::{ + AbsoluteRect, BufferPoint, BufferPoints, CopyTexture, FillRect, GfxApiOpt, + }, Texture, }, scale::Scale, @@ -14,8 +16,7 @@ use { }; pub struct RendererBase<'a> { - pub(super) ctx: &'a Rc, - pub(super) fb: &'a GlFrameBuffer, + pub(super) ops: &'a mut Vec, pub(super) scaled: bool, pub(super) scale: Scale, pub(super) scalef: f64, @@ -26,10 +27,6 @@ impl RendererBase<'_> { self.scale } - pub fn physical_extents(&self) -> Rect { - Rect::new_sized(0, 0, self.fb.width, self.fb.height).unwrap() - } - pub fn scale_point(&self, mut x: i32, mut y: i32) -> (i32, i32) { if self.scaled { x = (x as f64 * self.scalef).round() as _; @@ -68,112 +65,138 @@ impl RendererBase<'_> { rect } - fn xf_to_f(&self, x: f32) -> f32 { - 2.0 * (x / self.fb.width as f32) - 1.0 + pub fn clear(&mut self, c: &Color) { + self.ops.push(GfxApiOpt::Clear(Clear { color: *c })) } - fn yf_to_f(&self, y: f32) -> f32 { - 2.0 * (y / self.fb.height as f32) - 1.0 - } - - fn x_to_f(&self, x: i32) -> f32 { - 2.0 * (x as f32 / self.fb.width as f32) - 1.0 - } - - fn y_to_f(&self, y: i32) -> f32 { - 2.0 * (y as f32 / self.fb.height as f32) - 1.0 - } - - pub fn clear(&self, c: &Color) { - gl::clear(c); - } - - pub fn fill_boxes(&self, boxes: &[Rect], color: &Color) { + pub fn fill_boxes(&mut self, boxes: &[Rect], color: &Color) { self.fill_boxes2(boxes, color, 0, 0); } - pub fn fill_boxes2(&self, boxes: &[Rect], color: &Color, dx: i32, dy: i32) { + pub fn fill_boxes2(&mut self, boxes: &[Rect], color: &Color, dx: i32, dy: i32) { if boxes.is_empty() { return; } let (dx, dy) = self.scale_point(dx, dy); - let mut pos = Vec::with_capacity(boxes.len() * 12); for bx in boxes { let bx = self.scale_rect(*bx); - let x1 = self.x_to_f(bx.x1() + dx); - let y1 = self.y_to_f(bx.y1() + dy); - let x2 = self.x_to_f(bx.x2() + dx); - let y2 = self.y_to_f(bx.y2() + dy); - pos.extend_from_slice(&[ - // triangle 1 - x2, y1, // top right - x1, y1, // top left - x1, y2, // bottom left - // triangle 2 - x2, y1, // top right - x1, y2, // bottom left - x2, y2, // bottom right - ]); + self.ops.push(GfxApiOpt::FillRect(FillRect { + rect: AbsoluteRect { + x1: (bx.x1() + dx) as f32, + y1: (bx.y1() + dy) as f32, + x2: (bx.x2() + dx) as f32, + y2: (bx.y2() + dy) as f32, + }, + color: *color, + })); } - self.fill_boxes3(&pos, color) } - pub fn fill_boxes_f(&self, boxes: &[(f32, f32, f32, f32)], color: &Color) { + pub fn fill_boxes_f(&mut self, boxes: &[(f32, f32, f32, f32)], color: &Color) { self.fill_boxes2_f(boxes, color, 0.0, 0.0); } - pub fn fill_boxes2_f(&self, boxes: &[(f32, f32, f32, f32)], color: &Color, dx: f32, dy: f32) { + pub fn fill_boxes2_f( + &mut self, + boxes: &[(f32, f32, f32, f32)], + color: &Color, + dx: f32, + dy: f32, + ) { if boxes.is_empty() { return; } let (dx, dy) = self.scale_point_f(dx, dy); - let mut pos = Vec::with_capacity(boxes.len() * 12); for bx in boxes { let (x1, y1, x2, y2) = self.scale_rect_f(*bx); - let x1 = self.xf_to_f(x1 + dx); - let y1 = self.yf_to_f(y1 + dy); - let x2 = self.xf_to_f(x2 + dx); - let y2 = self.yf_to_f(y2 + dy); - pos.extend_from_slice(&[ - // triangle 1 - x2, y1, // top right - x1, y1, // top left - x1, y2, // bottom left - // triangle 2 - x2, y1, // top right - x1, y2, // bottom left - x2, y2, // bottom right - ]); + self.ops.push(GfxApiOpt::FillRect(FillRect { + rect: AbsoluteRect { + x1: x1 + dx, + y1: y1 + dy, + x2: x2 + dx, + y2: y2 + dy, + }, + color: *color, + })); } - self.fill_boxes3(&pos, color) - } - - fn fill_boxes3(&self, boxes: &[f32], color: &Color) { - gl::fill_boxes3(&self.ctx, boxes, color); } pub fn render_texture( &mut self, - texture: &Texture, + texture: &Rc, x: i32, y: i32, - format: &Format, - tpoints: Option<&[f32; 8]>, + format: &'static Format, + tpoints: Option, tsize: Option<(i32, i32)>, tscale: Scale, + max_width: i32, + max_height: i32, ) { - gl::render_texture( - &self.ctx, - &self.fb, - texture, - x, - y, + let mut texcoord = tpoints.unwrap_or(BufferPoints { + top_left: BufferPoint { x: 0.0, y: 0.0 }, + top_right: BufferPoint { x: 1.0, y: 0.0 }, + bottom_left: BufferPoint { x: 0.0, y: 1.0 }, + bottom_right: BufferPoint { x: 1.0, y: 1.0 }, + }); + + let (twidth, theight) = if let Some(size) = tsize { + size + } else { + let (mut w, mut h) = (texture.gl.width, texture.gl.height); + if tscale != self.scale { + let tscale = tscale.to_f64(); + w = (w as f64 * self.scalef / tscale).round() as _; + h = (h as f64 * self.scalef / tscale).round() as _; + } + (w, h) + }; + + macro_rules! clamp { + ($desired:ident, $max:ident, $([$far:ident, $near:ident]),*) => { + if $desired > $max { + let $desired = $desired as f32; + let $max = $max as f32; + let factor = $max / $desired; + $( + let dx = (texcoord.$far.x - texcoord.$near.x) * factor; + texcoord.$far.x = texcoord.$near.x + dx; + let dy = (texcoord.$far.y - texcoord.$near.y) * factor; + texcoord.$far.y = texcoord.$near.y + dy; + )* + $max + } else { + $desired as f32 + } + }; + } + + let twidth = clamp!( + twidth, + max_width, + [top_right, top_left], + [bottom_right, bottom_left] + ); + let theight = clamp!( + theight, + max_height, + [bottom_left, top_left], + [bottom_right, top_right] + ); + + let x = x as f32; + let y = y as f32; + + self.ops.push(GfxApiOpt::CopyTexture(CopyTexture { + tex: texture.clone(), format, - tpoints, - tsize, - tscale, - self.scale, - self.scalef, - ) + source: texcoord, + target: AbsoluteRect { + x1: x, + y1: y, + x2: x + twidth, + y2: y + theight, + }, + })); } } diff --git a/src/theme.rs b/src/theme.rs index 8df6861f..f018cf63 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -1,6 +1,9 @@ -use std::cell::{Cell, RefCell}; +use std::{ + cell::{Cell, RefCell}, + cmp::Ordering, +}; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, PartialEq)] pub struct Color { pub r: f32, pub g: f32, @@ -8,6 +11,24 @@ pub struct Color { pub a: f32, } +impl Eq for Color {} + +impl Ord for Color { + fn cmp(&self, other: &Self) -> Ordering { + self.r + .total_cmp(&other.r) + .then_with(|| self.g.total_cmp(&other.g)) + .then_with(|| self.b.total_cmp(&other.b)) + .then_with(|| self.a.total_cmp(&other.a)) + } +} + +impl PartialOrd for Color { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + fn to_f32(c: u8) -> f32 { c as f32 / 255f32 } diff --git a/src/tree.rs b/src/tree.rs index 6e31beb6..1cea13d1 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -137,10 +137,19 @@ pub trait Node: 'static { let _ = (child, active, depth); } - fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { + fn node_render( + &self, + renderer: &mut Renderer, + x: i32, + y: i32, + max_width: i32, + max_height: i32, + ) { let _ = renderer; let _ = x; let _ = y; + let _ = max_width; + let _ = max_height; } fn node_client(&self) -> Option> { diff --git a/src/tree/container.rs b/src/tree/container.rs index 3e930bb0..e1e444c4 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -1085,7 +1085,14 @@ impl Node for ContainerNode { .node_child_active_changed(self.deref(), active, depth + 1); } - fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { + fn node_render( + &self, + renderer: &mut Renderer, + x: i32, + y: i32, + _max_width: i32, + _max_height: i32, + ) { renderer.render_container(self, x, y); } diff --git a/src/tree/display.rs b/src/tree/display.rs index ab655681..5b5a3018 100644 --- a/src/tree/display.rs +++ b/src/tree/display.rs @@ -111,7 +111,14 @@ impl Node for DisplayNode { FindTreeResult::AcceptsInput } - fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { + fn node_render( + &self, + renderer: &mut Renderer, + x: i32, + y: i32, + _max_width: i32, + _max_height: i32, + ) { renderer.render_display(self, x, y); } diff --git a/src/tree/float.rs b/src/tree/float.rs index 68c3c282..6e61df6e 100644 --- a/src/tree/float.rs +++ b/src/tree/float.rs @@ -420,7 +420,14 @@ impl Node for FloatNode { } } - fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { + fn node_render( + &self, + renderer: &mut Renderer, + x: i32, + y: i32, + _max_width: i32, + _max_height: i32, + ) { renderer.render_floating(self, x, y) } diff --git a/src/tree/output.rs b/src/tree/output.rs index 3c86881f..42622099 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -77,7 +77,7 @@ pub async fn output_render_data(state: Rc) { } impl OutputNode { - pub fn perform_screencopies(&self, fb: &Framebuffer, tex: &Texture) { + pub fn perform_screencopies(&self, fb: &Framebuffer, tex: &Rc) { if let Some(workspace) = self.workspace.get() { if !workspace.capture.get() { return; @@ -620,7 +620,14 @@ impl Node for OutputNode { FindTreeResult::AcceptsInput } - fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { + fn node_render( + &self, + renderer: &mut Renderer, + x: i32, + y: i32, + _max_width: i32, + _max_height: i32, + ) { renderer.render_output(self, x, y); } diff --git a/src/tree/placeholder.rs b/src/tree/placeholder.rs index bf882ffb..294a6c81 100644 --- a/src/tree/placeholder.rs +++ b/src/tree/placeholder.rs @@ -122,7 +122,14 @@ impl Node for PlaceholderNode { FindTreeResult::AcceptsInput } - fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { + fn node_render( + &self, + renderer: &mut Renderer, + x: i32, + y: i32, + _max_width: i32, + _max_height: i32, + ) { renderer.render_placeholder(self, x, y); } diff --git a/src/tree/workspace.rs b/src/tree/workspace.rs index b3f8cf56..55644d4b 100644 --- a/src/tree/workspace.rs +++ b/src/tree/workspace.rs @@ -170,7 +170,14 @@ impl Node for WorkspaceNode { FindTreeResult::AcceptsInput } - fn node_render(&self, renderer: &mut Renderer, x: i32, y: i32) { + fn node_render( + &self, + renderer: &mut Renderer, + x: i32, + y: i32, + _max_width: i32, + _max_height: i32, + ) { renderer.render_workspace(self, x, y); }