diff --git a/src/backends/metal/video.rs b/src/backends/metal/video.rs index 55e8e70a..6cbb2387 100644 --- a/src/backends/metal/video.rs +++ b/src/backends/metal/video.rs @@ -360,7 +360,7 @@ impl MetalConnector { if let Some(node) = self.state.root.outputs.get(&self.connector_id) { let mut rr = self.render_result.borrow_mut(); let render_fb = buffer.render_fb(); - render_fb.render( + render_fb.render_node( &*node, &self.state, Some(node.global.pos.get()), diff --git a/src/backends/x.rs b/src/backends/x.rs index 3b62ab10..52c26291 100644 --- a/src/backends/x.rs +++ b/src/backends/x.rs @@ -723,7 +723,7 @@ impl XBackend { if let Some(node) = self.state.root.outputs.get(&output.id) { let mut rr = self.render_result.borrow_mut(); let fb = image.fb.get(); - fb.render( + fb.render_node( &*node, &self.state, Some(node.global.pos.get()), diff --git a/src/gfx_api.rs b/src/gfx_api.rs index 1f03625c..9dc04234 100644 --- a/src/gfx_api.rs +++ b/src/gfx_api.rs @@ -1,9 +1,10 @@ use { crate::{ cursor::Cursor, - format::Format, + fixed::Fixed, + format::{Format, ARGB8888, XRGB8888}, rect::Rect, - renderer::{renderer_base::RendererBase, RenderResult}, + renderer::{renderer_base::RendererBase, RenderResult, Renderer}, scale::Scale, state::State, theme::Color, @@ -115,18 +116,9 @@ pub trait GfxFramebuffer: Debug { fn take_render_ops(&self) -> Vec; - fn clear(&self); + fn size(&self) -> (i32, i32); - fn clear_with(&self, r: f32, g: f32, b: f32, a: f32); - - fn copy_texture( - &self, - state: &State, - texture: &Rc, - x: i32, - y: i32, - alpha: bool, - ); + fn render(&self, ops: Vec, clear: Option<&Color>); fn copy_to_shm( &self, @@ -137,10 +129,65 @@ pub trait GfxFramebuffer: Debug { format: &Format, shm: &[Cell], ); +} - fn render_custom(&self, scale: Scale, f: &mut dyn FnMut(&mut RendererBase)); +impl dyn GfxFramebuffer { + pub fn clear(&self) { + self.clear_with(0.0, 0.0, 0.0, 0.0); + } - fn render( + pub fn clear_with(&self, r: f32, g: f32, b: f32, a: f32) { + let ops = self.take_render_ops(); + self.render(ops, Some(&Color { r, g, b, a })); + } + + pub fn copy_texture( + &self, + state: &State, + texture: &Rc, + x: i32, + y: i32, + alpha: bool, + ) { + let mut ops = self.take_render_ops(); + let scale = Scale::from_int(1); + let (width, height) = self.size(); + let extents = Rect::new_sized(0, 0, width, height).unwrap(); + let mut renderer = Renderer { + base: RendererBase { + ops: &mut ops, + scaled: false, + scale, + scalef: 1.0, + }, + state, + result: None, + logical_extents: extents, + physical_extents: extents, + }; + let (format, clear) = match alpha { + true => (ARGB8888, Some(&Color::TRANSPARENT)), + false => (XRGB8888, None), + }; + renderer + .base + .render_texture(texture, x, y, format, None, None, scale, i32::MAX, i32::MAX); + self.render(ops, clear); + } + + pub fn render_custom(&self, scale: Scale, f: &mut dyn FnMut(&mut RendererBase)) { + let mut ops = self.take_render_ops(); + let mut renderer = RendererBase { + ops: &mut ops, + scaled: scale != 1, + scale, + scalef: scale.to_f64(), + }; + f(&mut renderer); + self.render(ops, None); + } + + pub fn render_node( &self, node: &dyn Node, state: &State, @@ -148,9 +195,68 @@ pub trait GfxFramebuffer: Debug { result: Option<&mut RenderResult>, scale: Scale, render_hardware_cursor: bool, - ); + ) { + let mut ops = self.take_render_ops(); + let (width, height) = self.size(); + let mut renderer = Renderer { + base: RendererBase { + ops: &mut ops, + scaled: scale != 1, + scale, + scalef: scale.to_f64(), + }, + state, + result, + logical_extents: node.node_absolute_position().at_point(0, 0), + physical_extents: Rect::new(0, 0, width, 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 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); + } + } + if render_hardware_cursor || !seat.hardware_cursor() { + cursor.tick(); + x -= Fixed::from_int(rect.x1()); + y -= Fixed::from_int(rect.y1()); + cursor.render(&mut renderer, x, y); + } + } + } + } + let c = state.theme.colors.background.get(); + self.render(ops, Some(&c)); + } - fn render_hardware_cursor(&self, cursor: &dyn Cursor, state: &State, scale: Scale); + pub fn render_hardware_cursor(&self, cursor: &dyn Cursor, state: &State, scale: Scale) { + let mut ops = self.take_render_ops(); + let (width, height) = self.size(); + let mut renderer = Renderer { + base: RendererBase { + ops: &mut ops, + scaled: scale != 1, + scale, + scalef: scale.to_f64(), + }, + state, + result: None, + logical_extents: Rect::new_empty(0, 0), + physical_extents: Rect::new(0, 0, width, height).unwrap(), + }; + cursor.render_hardware_cursor(&mut renderer); + self.render(ops, Some(&Color::TRANSPARENT)); + } } pub trait GfxImage { diff --git a/src/gfx_apis/gl/renderer/framebuffer.rs b/src/gfx_apis/gl/renderer/framebuffer.rs index c0e3e978..43ea6cea 100644 --- a/src/gfx_apis/gl/renderer/framebuffer.rs +++ b/src/gfx_apis/gl/renderer/framebuffer.rs @@ -1,9 +1,7 @@ use { crate::{ - cursor::Cursor, - fixed::Fixed, - format::{Format, ARGB8888, XRGB8888}, - gfx_api::{GfxApiOpt, GfxFramebuffer, GfxTexture}, + format::Format, + gfx_api::{GfxApiOpt, GfxFramebuffer}, gfx_apis::gl::{ gl::{ frame_buffer::GlFrameBuffer, @@ -16,11 +14,7 @@ use { run_ops, sys::{glBlendFunc, glFlush, glReadnPixels, GL_ONE, GL_ONE_MINUS_SRC_ALPHA}, }, - rect::Rect, - renderer::{renderer_base::RendererBase, RenderResult, Renderer}, - scale::Scale, - state::State, - tree::Node, + theme::Color, }, std::{ any::Any, @@ -43,71 +37,6 @@ impl Debug for Framebuffer { } impl Framebuffer { - pub fn clear(&self) { - self.clear_with(0.0, 0.0, 0.0, 0.0); - } - - pub fn clear_with(&self, r: f32, g: f32, b: f32, a: f32) { - let _ = self.ctx.ctx.with_current(|| { - unsafe { - glBindFramebuffer(GL_FRAMEBUFFER, self.gl.fbo); - glViewport(0, 0, self.gl.width, self.gl.height); - glClearColor(r, g, b, a); - glClear(GL_COLOR_BUFFER_BIT); - } - Ok(()) - }); - } - - 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, - result: None, - 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); - glViewport(0, 0, self.gl.width, self.gl.height); - if alpha { - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - } - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } - run_ops(self, &ops); - unsafe { - glFlush(); - } - Ok(()) - }); - } - pub fn copy_to_shm( &self, x: i32, @@ -137,117 +66,15 @@ impl Framebuffer { }); } - pub fn render_custom(&self, scale: Scale, f: &mut dyn FnMut(&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); + pub fn render(&self, ops: Vec, clear: Option<&Color>) { 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); - } - run_ops(self, &ops); - unsafe { - glFlush(); - } - Ok(()) - }); - } - - pub fn render( - &self, - node: &dyn Node, - state: &State, - cursor_rect: Option, - result: Option<&mut RenderResult>, - 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, - 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 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); - } - } - if render_hardware_cursor || !seat.hardware_cursor() { - cursor.tick(); - x -= Fixed::from_int(rect.x1()); - y -= Fixed::from_int(rect.y1()); - cursor.render(&mut renderer, x, y); - } + if let Some(c) = clear { + glClearColor(c.r, c.g, c.b, c.a); + glClear(GL_COLOR_BUFFER_BIT); } - } - } - let _ = self.ctx.ctx.with_current(|| { - let c = state.theme.colors.background.get(); - unsafe { - glBindFramebuffer(GL_FRAMEBUFFER, self.gl.fbo); - glViewport(0, 0, self.gl.width, self.gl.height); - glClearColor(c.r, c.g, c.b, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); - } - run_ops(self, &ops); - unsafe { - glFlush(); - } - Ok(()) - }); - } - - 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 renderer = Renderer { - base: RendererBase { - ops: &mut ops, - scaled: scale != 1, - scale, - scalef: scale.to_f64(), - }, - state, - result: None, - 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); - glViewport(0, 0, self.gl.width, self.gl.height); - glClearColor(0.0, 0.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); } run_ops(self, &ops); @@ -256,6 +83,7 @@ impl Framebuffer { } Ok(()) }); + *self.ctx.gfx_ops.borrow_mut() = ops; } } @@ -265,26 +93,17 @@ impl GfxFramebuffer for Framebuffer { } fn take_render_ops(&self) -> Vec { - mem::take(&mut self.ctx.gfx_ops.borrow_mut()) + let mut ops = mem::take(&mut *self.ctx.gfx_ops.borrow_mut()); + ops.clear(); + ops } - fn clear(&self) { - self.clear() + fn size(&self) -> (i32, i32) { + (self.gl.width, self.gl.height) } - fn clear_with(&self, r: f32, g: f32, b: f32, a: f32) { - self.clear_with(r, g, b, a) - } - - fn copy_texture( - &self, - state: &State, - texture: &Rc, - x: i32, - y: i32, - alpha: bool, - ) { - self.copy_texture(state, texture, x, y, alpha) + fn render(&self, ops: Vec, clear: Option<&Color>) { + self.render(ops, clear); } fn copy_to_shm( @@ -298,31 +117,4 @@ impl GfxFramebuffer for Framebuffer { ) { self.copy_to_shm(x, y, width, height, format, shm) } - - fn render_custom(&self, scale: Scale, f: &mut dyn FnMut(&mut RendererBase)) { - self.render_custom(scale, f) - } - - fn render( - &self, - node: &dyn Node, - state: &State, - cursor_rect: Option, - result: Option<&mut RenderResult>, - scale: Scale, - render_hardware_cursor: bool, - ) { - self.render( - node, - state, - cursor_rect, - result, - scale, - render_hardware_cursor, - ) - } - - fn render_hardware_cursor(&self, cursor: &dyn Cursor, state: &State, scale: Scale) { - self.render_hardware_cursor(cursor, state, scale) - } } diff --git a/src/screenshoter.rs b/src/screenshoter.rs index 793303a4..b42c7a15 100644 --- a/src/screenshoter.rs +++ b/src/screenshoter.rs @@ -55,7 +55,7 @@ pub fn take_screenshot(state: &State) -> Result GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR, )?; let fb = ctx.clone().dmabuf_fb(bo.dmabuf())?; - fb.render( + fb.render_node( state.root.deref(), state, Some(state.root.extents.get()), diff --git a/src/theme.rs b/src/theme.rs index 575be67b..cac2deaa 100644 --- a/src/theme.rs +++ b/src/theme.rs @@ -38,6 +38,13 @@ fn to_u8(c: f32) -> u8 { } impl Color { + pub const TRANSPARENT: Self = Self { + r: 0.0, + g: 0.0, + b: 0.0, + a: 0.0, + }; + pub fn from_gray(g: u8) -> Self { Self::from_rgb(g, g, g) }