diff --git a/src/backend.rs b/src/backend.rs index 9372e1fe..6666cedf 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -2,7 +2,7 @@ use { crate::{ async_engine::SpawnedFuture, fixed::Fixed, - gfx_apis::gl::Framebuffer, + gfx_api::GfxFramebuffer, ifs::wl_seat::wl_pointer::{CONTINUOUS, FINGER, HORIZONTAL_SCROLL, VERTICAL_SCROLL, WHEEL}, video::drm::{ConnectorType, DrmError, DrmVersion}, }, @@ -95,7 +95,7 @@ pub enum ConnectorEvent { pub trait HardwareCursor: Debug { fn set_enabled(&self, enabled: bool); - fn get_buffer(&self) -> Rc; + fn get_buffer(&self) -> Rc; fn set_position(&self, x: i32, y: i32); fn swap_buffer(&self); fn commit(&self); diff --git a/src/backends/metal.rs b/src/backends/metal.rs index a63e7441..58cd22b9 100644 --- a/src/backends/metal.rs +++ b/src/backends/metal.rs @@ -11,7 +11,7 @@ use { }, backends::metal::video::{MetalDrmDeviceData, MetalRenderContext, PendingDrmDevice}, dbus::{DbusError, SignalHandler}, - gfx_apis::gl::RenderError, + gfx_api::GfxError, libinput::{ consts::{ AccelProfile, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE, @@ -75,7 +75,7 @@ pub enum MetalError { #[error("Could not update the drm properties")] UpdateProperties(#[source] DrmError), #[error("Could not create a render context")] - CreateRenderContex(#[source] RenderError), + CreateRenderContex(#[source] GfxError), #[error("Cannot initialize connector because no CRTC is available")] NoCrtcForConnector, #[error("Cannot initialize connector because no primary plane is available")] @@ -86,12 +86,12 @@ pub enum MetalError { ScanoutBuffer(#[source] GbmError), #[error("addfb2 failed")] Framebuffer(#[source] DrmError), - #[error("Could not import a framebuffer into EGL")] - ImportFb(#[source] RenderError), - #[error("Could not import a texture into EGL")] - ImportTexture(#[source] RenderError), - #[error("Could not import an image into EGL")] - ImportImage(#[source] RenderError), + #[error("Could not import a framebuffer into the graphics API")] + ImportFb(#[source] GfxError), + #[error("Could not import a texture into the graphics API")] + ImportTexture(#[source] GfxError), + #[error("Could not import an image into the graphics API")] + ImportImage(#[source] GfxError), #[error("Could not perform modeset")] Modeset(#[source] DrmError), #[error("Could not enable atomic modesetting")] diff --git a/src/backends/metal/video.rs b/src/backends/metal/video.rs index 97eb5320..978a5c9f 100644 --- a/src/backends/metal/video.rs +++ b/src/backends/metal/video.rs @@ -8,7 +8,8 @@ use { backends::metal::{MetalBackend, MetalError}, edid::Descriptor, format::{Format, ARGB8888, XRGB8888}, - gfx_apis::gl::{Framebuffer, RenderContext, Texture}, + gfx_api::{GfxContext, GfxFramebuffer, GfxTexture}, + gfx_apis::create_gfx_context, ifs::wp_presentation_feedback::{KIND_HW_COMPLETION, KIND_VSYNC}, renderer::RenderResult, state::State, @@ -52,7 +53,7 @@ pub struct PendingDrmDevice { #[derive(Debug)] pub struct MetalRenderContext { pub dev_id: DrmDeviceId, - pub egl: Rc, + pub gfx: Rc, } #[derive(Debug)] @@ -214,7 +215,7 @@ impl HardwareCursor for MetalHardwareCursor { } } - fn get_buffer(&self) -> Rc { + fn get_buffer(&self) -> Rc { let buffer = (self.connector.cursor_front_buffer.get() + 1) % 2; self.cursor_buffers[buffer].render_fb() } @@ -375,7 +376,7 @@ impl MetalConnector { fr.send_done(); let _ = fr.client.remove_obj(&*fr); } - node.perform_screencopies(&render_fb, &buffer.render_tex); + node.perform_screencopies(&*render_fb, &buffer.render_tex); } changes.change_object(plane.id, |c| { c.change(plane.fb_id, buffer.drm.id().0 as _); @@ -883,9 +884,9 @@ impl MetalBackend { None => return false, }; if let Some(r) = ctx - .egl + .gfx .reset_status() - .or_else(|| dev.ctx.egl.reset_status()) + .or_else(|| dev.ctx.gfx.reset_status()) { fatal!("EGL context has been reset: {:?}", r); } @@ -1090,13 +1091,13 @@ impl MetalBackend { } } - let egl = match RenderContext::from_drm_device(master) { - Ok(r) => Rc::new(r), + let gfx = match create_gfx_context(master) { + Ok(r) => r, Err(e) => return Err(MetalError::CreateRenderContex(e)), }; let ctx = Rc::new(MetalRenderContext { dev_id: pending.id, - egl, + gfx, }); let gbm = match GbmDevice::new(master) { @@ -1421,7 +1422,7 @@ impl MetalBackend { return true; } } - self.state.set_render_ctx(Some(&dev.ctx.egl)); + self.state.set_render_ctx(Some(dev.ctx.gfx.clone())); self.ctx.set(Some(dev.ctx.clone())); let mut preserve = Preserve::default(); for dev in self.device_holder.drm_devices.lock().values() { @@ -1601,11 +1602,11 @@ impl MetalBackend { Ok(fb) => Rc::new(fb), Err(e) => return Err(MetalError::Framebuffer(e)), }; - let dev_img = match dev.ctx.egl.dmabuf_img(dev_bo.dmabuf()) { + let dev_img = match dev.ctx.gfx.clone().dmabuf_img(dev_bo.dmabuf()) { Ok(img) => img, Err(e) => return Err(MetalError::ImportImage(e)), }; - let dev_fb = match dev_img.to_framebuffer() { + let dev_fb = match dev_img.clone().to_framebuffer() { Ok(fb) => fb, Err(e) => return Err(MetalError::ImportFb(e)), }; @@ -1619,16 +1620,16 @@ impl MetalBackend { } else { // Create a _bridge_ BO in the render device usage = GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR; - let render_bo = render_ctx.egl.gbm.create_bo(width, height, format, usage); + let render_bo = render_ctx.gfx.gbm().create_bo(width, height, format, usage); let render_bo = match render_bo { Ok(b) => b, Err(e) => return Err(MetalError::ScanoutBuffer(e)), }; - let render_img = match render_ctx.egl.dmabuf_img(render_bo.dmabuf()) { + let render_img = match render_ctx.gfx.clone().dmabuf_img(render_bo.dmabuf()) { Ok(img) => img, Err(e) => return Err(MetalError::ImportImage(e)), }; - let render_fb = match render_img.to_framebuffer() { + let render_fb = match render_img.clone().to_framebuffer() { Ok(fb) => fb, Err(e) => return Err(MetalError::ImportFb(e)), }; @@ -1639,7 +1640,7 @@ impl MetalBackend { }; // Import the bridge BO into the current device - let dev_img = match dev.ctx.egl.dmabuf_img(render_bo.dmabuf()) { + let dev_img = match dev.ctx.gfx.clone().dmabuf_img(render_bo.dmabuf()) { Ok(img) => img, Err(e) => return Err(MetalError::ImportImage(e)), }; @@ -1833,20 +1834,20 @@ pub struct RenderBuffer { drm: Rc, // ctx = dev // buffer location = dev - dev_fb: Rc, + dev_fb: Rc, // ctx = dev // buffer location = render - dev_tex: Option>, + dev_tex: Option>, // ctx = render // buffer location = render - render_tex: Rc, + render_tex: Rc, // ctx = render // buffer location = render - render_fb: Option>, + render_fb: Option>, } impl RenderBuffer { - fn render_fb(&self) -> Rc { + fn render_fb(&self) -> Rc { self.render_fb .clone() .unwrap_or_else(|| self.dev_fb.clone()) diff --git a/src/backends/x.rs b/src/backends/x.rs index a8f15661..db9943ff 100644 --- a/src/backends/x.rs +++ b/src/backends/x.rs @@ -9,7 +9,8 @@ use { }, fixed::Fixed, format::XRGB8888, - gfx_apis::gl::{Framebuffer, RenderContext, RenderError, Texture}, + gfx_api::{GfxContext, GfxError, GfxFramebuffer, GfxTexture}, + gfx_apis::create_gfx_context, renderer::RenderResult, state::State, time::now_usec, @@ -89,14 +90,14 @@ pub enum XBackendError { GbmError(#[from] GbmError), #[error("Could not import a dma-buf")] ImportBuffer(#[source] XconError), - #[error("Could not create an EGL context")] - CreateEgl(#[source] RenderError), - #[error("Could not create an EGL image from a dma-buf")] - CreateImage(#[source] RenderError), - #[error("Could not create a framebuffer from an EGL image")] - CreateFramebuffer(#[source] RenderError), - #[error("Could not create a texture from an EGL image")] - CreateTexture(#[source] RenderError), + #[error("Could not create a graphics API context")] + CreateEgl(#[source] GfxError), + #[error("Could not create an graphics API image from a dma-buf")] + CreateImage(#[source] GfxError), + #[error("Could not create a framebuffer from a graphics API image")] + CreateFramebuffer(#[source] GfxError), + #[error("Could not create a texture from an graphics API image")] + CreateTexture(#[source] GfxError), #[error("Could not select input events")] CannotSelectInputEvents(#[source] XconError), #[error("Could not select present events")] @@ -178,8 +179,8 @@ pub async fn create(state: &Rc) -> Result, XBackendError> { Err(e) => return Err(XBackendError::DrmDeviceFstat(e)), }; let gbm = GbmDevice::new(&drm)?; - let ctx = match RenderContext::from_drm_device(&drm) { - Ok(r) => Rc::new(r), + let ctx = match create_gfx_context(&drm) { + Ok(r) => r, Err(e) => return Err(XBackendError::CreateEgl(e)), }; let cursor = { @@ -266,7 +267,7 @@ pub struct XBackend { outputs: CopyHashMap>, seats: CopyHashMap>, mouse_seats: CopyHashMap>, - ctx: Rc, + ctx: Rc, gbm: GbmDevice, cursor: u32, root: u32, @@ -288,7 +289,7 @@ impl XBackend { .eng .spawn2(Phase::Present, self.clone().present_handler()); - self.state.set_render_ctx(Some(&self.ctx)); + self.state.set_render_ctx(Some(self.ctx.clone())); self.state .backend_events .push(BackendEvent::NewDrmDevice(Rc::new(XDrmDevice { @@ -388,11 +389,11 @@ impl XBackend { assert!(dma.planes.len() == 1); let plane = dma.planes.first().unwrap(); let size = plane.stride * dma.height as u32; - let img = match self.ctx.dmabuf_img(dma) { + let img = match self.ctx.clone().dmabuf_img(dma) { Ok(f) => f, Err(e) => return Err(XBackendError::CreateImage(e)), }; - let fb = match img.to_framebuffer() { + let fb = match img.clone().to_framebuffer() { Ok(f) => f, Err(e) => return Err(XBackendError::CreateFramebuffer(e)), }; @@ -735,7 +736,7 @@ impl XBackend { fr.send_done(); let _ = fr.client.remove_obj(&*fr); } - node.perform_screencopies(&fb, &image.tex.get()); + node.perform_screencopies(&*fb, &image.tex.get()); } let pp = PresentPixmap { @@ -989,8 +990,8 @@ struct XOutput { struct XImage { pixmap: Cell, - fb: CloneCell>, - tex: CloneCell>, + fb: CloneCell>, + tex: CloneCell>, idle: Cell, render_on_idle: Cell, last_serial: Cell, diff --git a/src/compositor.rs b/src/compositor.rs index 1d7c2f51..d201ba7d 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -15,7 +15,6 @@ use { config::ConfigProxy, dbus::Dbus, forker, - gfx_apis::gl::{self, RenderError}, globals::Globals, ifs::{wl_output::WlOutputGlobal, wl_surface::NoneSurfaceExt}, io_uring::{IoUring, IoUringError}, @@ -86,8 +85,6 @@ pub enum CompositorError { ClientmemError(#[from] ClientMemError), #[error("The timer subsystem caused an error")] WheelError(#[from] WheelError), - #[error("The render backend caused an error")] - RenderError(#[from] RenderError), #[error("Could not create an io-uring")] IoUringError(#[from] IoUringError), } @@ -112,7 +109,6 @@ fn start_compositor2( log::info!("pid = {}", uapi::getpid()); init_fd_limit(); leaks::init(); - gl::init()?; clientmem::init()?; let xkb_ctx = XkbContext::new().unwrap(); let xkb_keymap = xkb_ctx.keymap_from_str(include_str!("keymap.xkb")).unwrap(); diff --git a/src/cursor.rs b/src/cursor.rs index 8c0b3764..9c3dd279 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -2,7 +2,7 @@ use { crate::{ fixed::Fixed, format::ARGB8888, - gfx_apis::gl::{RenderContext, RenderError, Texture}, + gfx_api::{GfxContext, GfxError, GfxTexture}, rect::Rect, renderer::Renderer, scale::Scale, @@ -87,7 +87,7 @@ pub enum KnownCursor { } impl ServerCursors { - pub fn load(ctx: &Rc, state: &State) -> Result, CursorError> { + pub fn load(ctx: &Rc, state: &State) -> Result, CursorError> { let paths = find_cursor_paths(); log::debug!("Trying to load cursors from paths {:?}", paths); let sizes = state.cursor_sizes.to_vec(); @@ -135,7 +135,7 @@ impl ServerCursorTemplate { scales: &[Scale], sizes: &[u32], paths: &[BString], - ctx: &Rc, + ctx: &Rc, ) -> Result { match open_cursor(name, theme, scales, sizes, paths) { Ok(cs) => { @@ -215,7 +215,7 @@ impl ServerCursorTemplate { struct CursorImageScaled { extents: Rect, - tex: Rc, + tex: Rc, } struct CursorImage { @@ -230,7 +230,7 @@ struct InstantiatedCursorImage { impl CursorImageScaled { fn from_bytes( - ctx: &Rc, + ctx: &Rc, data: &[Cell], width: i32, height: i32, @@ -239,7 +239,9 @@ impl CursorImageScaled { ) -> Result, CursorError> { Ok(Rc::new(Self { extents: Rect::new_sized(-xhot, -yhot, width, height).unwrap(), - tex: ctx.shmem_texture(data, ARGB8888, width, height, width * 4)?, + tex: ctx + .clone() + .shmem_texture(data, ARGB8888, width, height, width * 4)?, })) } } @@ -536,7 +538,7 @@ pub enum CursorError { #[error("The requested cursor could not be found")] NotFound, #[error("Could not import the cursor as a texture")] - ImportError(#[from] RenderError), + ImportError(#[from] GfxError), } #[derive(Default, Clone)] diff --git a/src/gfx_api.rs b/src/gfx_api.rs index 73277553..00e8971f 100644 --- a/src/gfx_api.rs +++ b/src/gfx_api.rs @@ -1,6 +1,25 @@ use { - crate::{format::Format, gfx_apis::gl::Texture, theme::Color}, - std::rc::Rc, + crate::{ + cursor::Cursor, + format::Format, + rect::Rect, + renderer::{renderer_base::RendererBase, RenderResult}, + scale::Scale, + state::State, + theme::Color, + tree::Node, + video::{dmabuf::DmaBuf, gbm::GbmDevice}, + }, + ahash::AHashMap, + std::{ + any::Any, + cell::Cell, + error::Error, + ffi::CString, + fmt::{Debug, Formatter}, + rc::Rc, + }, + thiserror::Error, }; pub enum GfxApiOpt { @@ -77,8 +96,123 @@ pub struct FillRect { } pub struct CopyTexture { - pub tex: Rc, + pub tex: Rc, pub format: &'static Format, pub source: BufferPoints, pub target: AbsoluteRect, } + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum ResetStatus { + Guilty, + Innocent, + Unknown, + Other(u32), +} + +pub trait GfxFramebuffer: Debug { + fn as_any(&self) -> &dyn Any; + + fn clear(&self); + + 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 copy_to_shm( + &self, + x: i32, + y: i32, + width: i32, + height: i32, + format: &Format, + shm: &[Cell], + ); + + fn render_custom(&self, scale: Scale, f: &mut dyn FnMut(&mut RendererBase)); + + fn render( + &self, + node: &dyn Node, + state: &State, + cursor_rect: Option, + on_output: bool, + result: &mut RenderResult, + scale: Scale, + render_hardware_cursor: bool, + ); + + fn render_hardware_cursor(&self, cursor: &dyn Cursor, state: &State, scale: Scale); +} + +pub trait GfxImage { + fn to_framebuffer(self: Rc) -> Result, GfxError>; + + fn to_texture(self: Rc) -> Result, GfxError>; + + fn width(&self) -> i32; + fn height(&self) -> i32; +} + +pub trait GfxTexture: Debug { + fn width(&self) -> i32; + fn height(&self) -> i32; + fn as_any(&self) -> &dyn Any; +} + +pub trait GfxContext: Debug { + fn take_render_ops(&self) -> Vec; + + fn reset_status(&self) -> Option; + + fn supports_external_texture(&self) -> bool; + + fn render_node(&self) -> Rc; + + fn formats(&self) -> Rc>; + + fn dmabuf_fb(self: Rc, buf: &DmaBuf) -> Result, GfxError>; + + fn dmabuf_img(self: Rc, buf: &DmaBuf) -> Result, GfxError>; + + fn shmem_texture( + self: Rc, + data: &[Cell], + format: &'static Format, + width: i32, + height: i32, + stride: i32, + ) -> Result, GfxError>; + + fn gbm(&self) -> &GbmDevice; +} + +#[derive(Debug)] +pub struct GfxFormat { + pub format: &'static Format, + pub implicit_external_only: bool, + pub modifiers: AHashMap, +} + +#[derive(Debug)] +pub struct GfxModifier { + pub modifier: u64, + pub external_only: bool, +} + +#[derive(Error)] +#[error(transparent)] +pub struct GfxError(pub Box); + +impl Debug for GfxError { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + Debug::fmt(&self.0, f) + } +} diff --git a/src/gfx_apis.rs b/src/gfx_apis.rs index a1367e79..d6450911 100644 --- a/src/gfx_apis.rs +++ b/src/gfx_apis.rs @@ -1 +1,13 @@ +use { + crate::{ + gfx_api::{GfxContext, GfxError}, + video::drm::Drm, + }, + std::rc::Rc, +}; + pub mod gl; + +pub fn create_gfx_context(drm: &Drm) -> Result, GfxError> { + gl::create_gfx_context(drm) +} diff --git a/src/gfx_apis/gl.rs b/src/gfx_apis/gl.rs index eecb0325..f8423ead 100644 --- a/src/gfx_apis/gl.rs +++ b/src/gfx_apis/gl.rs @@ -18,13 +18,15 @@ macro_rules! egl_transparent { }; } -pub use renderer::*; use { crate::{ format::Format, - gfx_api::{BufferPoints, CopyTexture, FillRect, GfxApiOpt}, + gfx_api::{ + BufferPoints, CopyTexture, FillRect, GfxApiOpt, GfxContext, GfxError, GfxTexture, + }, gfx_apis::gl::{ gl::texture::image_target, + renderer::{context::GlRenderContext, framebuffer::Framebuffer, texture::Texture}, sys::{ glActiveTexture, glBindTexture, glClear, glClearColor, glDisable, glDisableVertexAttribArray, glDrawArrays, glEnable, glEnableVertexAttribArray, @@ -35,10 +37,14 @@ use { }, theme::Color, utils::{rc_eq::rc_eq, vecstorage::VecStorage}, - video::{drm::DrmError, gbm::GbmError}, + video::{ + drm::{Drm, DrmError}, + gbm::GbmError, + }, }, isnt::std_1::vec::IsntVecExt, - std::cell::RefCell, + once_cell::sync::Lazy, + std::{cell::RefCell, rc::Rc, sync::Arc}, thiserror::Error, }; @@ -52,12 +58,19 @@ pub mod sys { pub use super::{egl::sys::*, gl::sys::*}; } -pub fn init() -> Result<(), RenderError> { - egl::init() +static INIT: Lazy>> = Lazy::new(|| egl::init().map_err(Arc::new)); + +pub(super) fn create_gfx_context(drm: &Drm) -> Result, GfxError> { + if let Err(e) = &*INIT { + return Err(GfxError(Box::new(e.clone()))); + } + GlRenderContext::from_drm_device(drm) + .map(|v| Rc::new(v) as Rc) + .map_err(|e| e.into()) } #[derive(Debug, Error)] -pub enum RenderError { +enum RenderError { #[error("EGL library does not support `EGL_EXT_platform_base`")] ExtPlatformBase, #[error("Could not compile a shader")] @@ -117,13 +130,13 @@ pub enum RenderError { } #[derive(Default)] -pub struct GfxGlState { +struct GfxGlState { triangles: RefCell>, fill_rect: VecStorage<&'static FillRect>, copy_tex: VecStorage<&'static CopyTexture>, } -pub fn run_ops(fb: &Framebuffer, ops: &[GfxApiOpt]) { +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(); @@ -207,7 +220,16 @@ pub fn run_ops(fb: &Framebuffer, ops: &[GfxApiOpt]) { 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) + render_texture( + &fb.ctx, + &tex.tex.as_gl(), + tex.format, + x1, + y1, + x2, + y2, + &tex.source, + ) } } } @@ -219,7 +241,7 @@ fn clear(c: &Color) { } } -fn fill_boxes3(ctx: &RenderContext, boxes: &[f32], color: &Color) { +fn fill_boxes3(ctx: &GlRenderContext, boxes: &[f32], color: &Color) { unsafe { glUseProgram(ctx.fill_prog.prog); glUniform4f(ctx.fill_prog_color, color.r, color.g, color.b, color.a); @@ -238,7 +260,7 @@ fn fill_boxes3(ctx: &RenderContext, boxes: &[f32], color: &Color) { } fn render_texture( - ctx: &RenderContext, + ctx: &GlRenderContext, texture: &Texture, format: &Format, x1: f32, @@ -320,3 +342,17 @@ fn render_texture( glBindTexture(target, 0); } } + +impl dyn GfxTexture { + fn as_gl(&self) -> &Texture { + self.as_any() + .downcast_ref() + .expect("Non-gl texture passed into gl") + } +} + +impl From for GfxError { + fn from(value: RenderError) -> Self { + Self(Box::new(value)) + } +} diff --git a/src/gfx_apis/gl/egl.rs b/src/gfx_apis/gl/egl.rs index 7cff9d16..a24affc5 100644 --- a/src/gfx_apis/gl/egl.rs +++ b/src/gfx_apis/gl/egl.rs @@ -31,7 +31,7 @@ pub(crate) static PROCS: Lazy = Lazy::new(ExtProc::load); pub(crate) static EXTS: Lazy = Lazy::new(get_client_ext); -pub fn init() -> Result<(), RenderError> { +pub(in crate::gfx_apis::gl) fn init() -> Result<(), RenderError> { if !EXTS.contains(ClientExt::EXT_PLATFORM_BASE) { return Err(RenderError::ExtPlatformBase); } diff --git a/src/gfx_apis/gl/egl/context.rs b/src/gfx_apis/gl/egl/context.rs index 097fa7be..c71f7176 100644 --- a/src/gfx_apis/gl/egl/context.rs +++ b/src/gfx_apis/gl/egl/context.rs @@ -1,16 +1,21 @@ use { - crate::gfx_apis::gl::{ - egl::{ - display::EglDisplay, - sys::{eglDestroyContext, eglMakeCurrent, EGLContext, EGLSurface, EGL_FALSE, EGL_TRUE}, - PROCS, + crate::{ + gfx_api::ResetStatus, + gfx_apis::gl::{ + egl::{ + display::EglDisplay, + sys::{ + eglDestroyContext, eglMakeCurrent, EGLContext, EGLSurface, EGL_FALSE, EGL_TRUE, + }, + PROCS, + }, + ext::{DisplayExt, GlExt}, + sys::{ + GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB, + GL_UNKNOWN_CONTEXT_RESET_ARB, + }, + RenderError, }, - ext::{DisplayExt, GlExt}, - sys::{ - GL_GUILTY_CONTEXT_RESET_ARB, GL_INNOCENT_CONTEXT_RESET_ARB, - GL_UNKNOWN_CONTEXT_RESET_ARB, - }, - RenderError, ResetStatus, }, std::rc::Rc, }; @@ -58,7 +63,7 @@ impl EglContext { } #[inline] - pub fn with_current Result>( + pub(in crate::gfx_apis::gl) fn with_current Result>( &self, f: F, ) -> Result { diff --git a/src/gfx_apis/gl/egl/display.rs b/src/gfx_apis/gl/egl/display.rs index c85bd1c6..95681b63 100644 --- a/src/gfx_apis/gl/egl/display.rs +++ b/src/gfx_apis/gl/egl/display.rs @@ -1,6 +1,7 @@ use { crate::{ format::{formats, Format}, + gfx_api::{GfxFormat, GfxModifier}, gfx_apis::gl::{ egl::{ context::EglContext, @@ -35,29 +36,16 @@ use { std::{ptr, rc::Rc}, }; -#[derive(Debug)] -pub struct EglFormat { - pub format: &'static Format, - pub implicit_external_only: bool, - pub modifiers: AHashMap, -} - -#[derive(Debug)] -pub struct EglModifier { - pub modifier: u64, - pub external_only: bool, -} - #[derive(Debug)] pub struct EglDisplay { pub exts: DisplayExt, - pub formats: Rc>, + pub formats: Rc>, pub gbm: Rc, pub dpy: EGLDisplay, } impl EglDisplay { - pub fn create(drm: &Drm) -> Result, RenderError> { + pub(in crate::gfx_apis::gl) fn create(drm: &Drm) -> Result, RenderError> { unsafe { let gbm = match GbmDevice::new(drm) { Ok(gbm) => gbm, @@ -107,7 +95,9 @@ impl EglDisplay { } } - pub fn create_context(self: &Rc) -> Result, RenderError> { + pub(in crate::gfx_apis::gl) fn create_context( + self: &Rc, + ) -> Result, RenderError> { let mut attrib = vec![EGL_CONTEXT_CLIENT_VERSION, 2]; if self .exts @@ -142,7 +132,10 @@ impl EglDisplay { } } - pub fn import_dmabuf(self: &Rc, buf: &DmaBuf) -> Result, RenderError> { + pub(in crate::gfx_apis::gl) fn import_dmabuf( + self: &Rc, + buf: &DmaBuf, + ) -> Result, RenderError> { let format = match self.formats.get(&buf.format.drm) { Some(fmt) => match fmt.modifiers.get(&buf.modifier) { Some(fmt) => fmt, @@ -235,7 +228,7 @@ impl Drop for EglDisplay { } } -unsafe fn query_formats(dpy: EGLDisplay) -> Result, RenderError> { +unsafe fn query_formats(dpy: EGLDisplay) -> Result, RenderError> { let mut vec = vec![]; let mut num = 0; let res = PROCS.eglQueryDmaBufFormatsEXT(dpy, num, ptr::null_mut(), &mut num); @@ -255,7 +248,7 @@ unsafe fn query_formats(dpy: EGLDisplay) -> Result, Ren let (modifiers, external_only) = query_modifiers(dpy, fmt, format)?; res.insert( format.drm, - EglFormat { + GfxFormat { format, implicit_external_only: external_only, modifiers, @@ -270,7 +263,7 @@ unsafe fn query_modifiers( dpy: EGLDisplay, gl_format: EGLint, format: &'static Format, -) -> Result<(AHashMap, bool), RenderError> { +) -> Result<(AHashMap, bool), RenderError> { let mut mods = vec![]; let mut ext_only = vec![]; let mut num = 0; @@ -304,7 +297,7 @@ unsafe fn query_modifiers( for (modifier, ext_only) in mods.iter().copied().zip(ext_only.iter().copied()) { res.insert( modifier as _, - EglModifier { + GfxModifier { modifier: modifier as _, external_only: ext_only == EGL_TRUE, }, @@ -316,7 +309,7 @@ unsafe fn query_modifiers( } res.insert( INVALID_MODIFIER, - EglModifier { + GfxModifier { modifier: INVALID_MODIFIER, external_only, }, diff --git a/src/gfx_apis/gl/gl/program.rs b/src/gfx_apis/gl/gl/program.rs index 6d683130..a2c523f8 100644 --- a/src/gfx_apis/gl/gl/program.rs +++ b/src/gfx_apis/gl/gl/program.rs @@ -21,7 +21,7 @@ pub struct GlProgram { } impl GlProgram { - pub unsafe fn from_shaders( + pub(in crate::gfx_apis::gl) unsafe fn from_shaders( ctx: &Rc, vert: &str, frag: &str, @@ -31,7 +31,10 @@ impl GlProgram { Self::link(&vert, &frag) } - pub unsafe fn link(vert: &GlShader, frag: &GlShader) -> Result { + pub(in crate::gfx_apis::gl) unsafe fn link( + vert: &GlShader, + frag: &GlShader, + ) -> Result { let res = GlProgram { _ctx: vert.ctx.clone(), prog: glCreateProgram(), diff --git a/src/gfx_apis/gl/gl/render_buffer.rs b/src/gfx_apis/gl/gl/render_buffer.rs index ff4ad15c..a1cee485 100644 --- a/src/gfx_apis/gl/gl/render_buffer.rs +++ b/src/gfx_apis/gl/gl/render_buffer.rs @@ -22,7 +22,7 @@ pub struct GlRenderBuffer { } impl GlRenderBuffer { - pub unsafe fn from_image( + pub(in crate::gfx_apis::gl) unsafe fn from_image( img: &Rc, ctx: &Rc, ) -> Result, RenderError> { @@ -41,7 +41,9 @@ impl GlRenderBuffer { })) } - pub unsafe fn create_framebuffer(self: &Rc) -> Result { + pub(in crate::gfx_apis::gl) unsafe fn create_framebuffer( + self: &Rc, + ) -> Result { let mut fbo = 0; glGenFramebuffers(1, &mut fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); diff --git a/src/gfx_apis/gl/gl/shader.rs b/src/gfx_apis/gl/gl/shader.rs index 6a8db473..40386ea1 100644 --- a/src/gfx_apis/gl/gl/shader.rs +++ b/src/gfx_apis/gl/gl/shader.rs @@ -17,7 +17,7 @@ pub struct GlShader { } impl GlShader { - pub unsafe fn compile( + pub(in crate::gfx_apis::gl) unsafe fn compile( ctx: &Rc, ty: GLenum, src: &str, diff --git a/src/gfx_apis/gl/gl/texture.rs b/src/gfx_apis/gl/gl/texture.rs index 3031b395..58db32d6 100644 --- a/src/gfx_apis/gl/gl/texture.rs +++ b/src/gfx_apis/gl/gl/texture.rs @@ -33,7 +33,10 @@ pub fn image_target(external_only: bool) -> GLenum { } impl GlTexture { - pub fn import_img(ctx: &Rc, img: &Rc) -> Result { + pub(in crate::gfx_apis::gl) fn import_img( + ctx: &Rc, + img: &Rc, + ) -> Result { if !ctx.ext.contains(GlExt::GL_OES_EGL_IMAGE_EXTERNAL) { return Err(RenderError::ExternalUnsupported); } @@ -58,7 +61,7 @@ impl GlTexture { }) } - pub fn import_shm( + pub(in crate::gfx_apis::gl) fn import_shm( ctx: &Rc, data: &[Cell], format: &'static Format, diff --git a/src/gfx_apis/gl/renderer.rs b/src/gfx_apis/gl/renderer.rs index 98e14562..eaa9bc1d 100644 --- a/src/gfx_apis/gl/renderer.rs +++ b/src/gfx_apis/gl/renderer.rs @@ -1,6 +1,4 @@ -pub use {context::*, framebuffer::*, image::*, texture::*}; - -mod context; -mod framebuffer; -mod image; -mod texture; +pub(super) mod context; +pub(super) mod framebuffer; +pub(super) mod image; +pub(super) mod texture; diff --git a/src/gfx_apis/gl/renderer/context.rs b/src/gfx_apis/gl/renderer/context.rs index ddde507f..55674b08 100644 --- a/src/gfx_apis/gl/renderer/context.rs +++ b/src/gfx_apis/gl/renderer/context.rs @@ -1,12 +1,12 @@ use { crate::{ format::{Format, XRGB8888}, - gfx_api::GfxApiOpt, + gfx_api::{ + GfxApiOpt, GfxContext, GfxError, GfxFormat, GfxFramebuffer, GfxImage, GfxTexture, + ResetStatus, + }, gfx_apis::gl::{ - egl::{ - context::EglContext, - display::{EglDisplay, EglFormat}, - }, + egl::{context::EglContext, display::EglDisplay}, ext::GlExt, gl::{ program::GlProgram, render_buffer::GlRenderBuffer, sys::GLint, texture::GlTexture, @@ -25,6 +25,7 @@ use { cell::{Cell, RefCell}, ffi::CString, fmt::{Debug, Formatter}, + mem, rc::Rc, }, uapi::ustr, @@ -53,7 +54,7 @@ pub(crate) struct TexProgs { pub solid: TexProg, } -pub struct RenderContext { +pub(in crate::gfx_apis::gl) struct GlRenderContext { pub(crate) ctx: Rc, pub gbm: Rc, @@ -67,24 +68,16 @@ pub struct RenderContext { pub(crate) fill_prog_color: GLint, pub(crate) gfx_ops: RefCell>, - pub(crate) gl_state: RefCell, + pub(in crate::gfx_apis::gl) gl_state: RefCell, } -impl Debug for RenderContext { +impl Debug for GlRenderContext { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { f.debug_struct("RenderContext").finish_non_exhaustive() } } -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub enum ResetStatus { - Guilty, - Innocent, - Unknown, - Other(u32), -} - -impl RenderContext { +impl GlRenderContext { pub fn reset_status(&self) -> Option { self.ctx.reset_status() } @@ -93,7 +86,7 @@ impl RenderContext { self.ctx.ext.contains(GlExt::GL_OES_EGL_IMAGE_EXTERNAL) } - pub fn from_drm_device(drm: &Drm) -> Result { + pub(in crate::gfx_apis::gl) fn from_drm_device(drm: &Drm) -> Result { let nodes = drm.get_nodes()?; let node = match nodes .get(&NodeType::Render) @@ -167,11 +160,11 @@ impl RenderContext { self.render_node.clone() } - pub fn formats(&self) -> Rc> { + pub fn formats(&self) -> Rc> { self.ctx.dpy.formats.clone() } - pub fn dmabuf_fb(self: &Rc, buf: &DmaBuf) -> Result, RenderError> { + fn dmabuf_fb(self: &Rc, buf: &DmaBuf) -> Result, RenderError> { self.ctx.with_current(|| unsafe { let img = self.ctx.dpy.import_dmabuf(buf)?; let rb = GlRenderBuffer::from_image(&img, &self.ctx)?; @@ -183,7 +176,7 @@ impl RenderContext { }) } - pub fn dmabuf_img(self: &Rc, buf: &DmaBuf) -> Result, RenderError> { + fn dmabuf_img(self: &Rc, buf: &DmaBuf) -> Result, RenderError> { self.ctx.with_current(|| { let img = self.ctx.dpy.import_dmabuf(buf)?; Ok(Rc::new(Image { @@ -193,7 +186,7 @@ impl RenderContext { }) } - pub fn shmem_texture( + fn shmem_texture( self: &Rc, data: &[Cell], format: &'static Format, @@ -208,3 +201,57 @@ impl RenderContext { })) } } + +impl GfxContext for GlRenderContext { + fn take_render_ops(&self) -> Vec { + mem::take(&mut self.gfx_ops.borrow_mut()) + } + + fn reset_status(&self) -> Option { + self.reset_status() + } + + fn supports_external_texture(&self) -> bool { + self.supports_external_texture() + } + + fn render_node(&self) -> Rc { + self.render_node() + } + + fn formats(&self) -> Rc> { + self.formats() + } + + fn dmabuf_fb(self: Rc, buf: &DmaBuf) -> Result, GfxError> { + (&self) + .dmabuf_fb(buf) + .map(|w| w as Rc) + .map_err(|e| e.into()) + } + + fn dmabuf_img(self: Rc, buf: &DmaBuf) -> Result, GfxError> { + (&self) + .dmabuf_img(buf) + .map(|w| w as Rc) + .map_err(|e| e.into()) + } + + fn shmem_texture( + self: Rc, + data: &[Cell], + format: &'static Format, + width: i32, + height: i32, + stride: i32, + ) -> Result, GfxError> { + (&self) + .shmem_texture(data, format, width, height, stride) + .map(|w| w as Rc) + .map_err(|e| e.into()) + } + + fn gbm(&self) -> &GbmDevice { + &self.gbm + } +} diff --git a/src/gfx_apis/gl/renderer/framebuffer.rs b/src/gfx_apis/gl/renderer/framebuffer.rs index 94bb069f..8ffb32a0 100644 --- a/src/gfx_apis/gl/renderer/framebuffer.rs +++ b/src/gfx_apis/gl/renderer/framebuffer.rs @@ -3,6 +3,7 @@ use { cursor::Cursor, fixed::Fixed, format::{Format, ARGB8888, XRGB8888}, + gfx_api::{GfxFramebuffer, GfxTexture}, gfx_apis::gl::{ gl::{ frame_buffer::GlFrameBuffer, @@ -11,10 +12,9 @@ use { GL_FRAMEBUFFER, }, }, - renderer::context::RenderContext, + renderer::context::GlRenderContext, run_ops, sys::{glBlendFunc, glFlush, glReadnPixels, GL_ONE, GL_ONE_MINUS_SRC_ALPHA}, - Texture, }, rect::Rect, renderer::{renderer_base::RendererBase, RenderResult, Renderer}, @@ -23,6 +23,7 @@ use { tree::Node, }, std::{ + any::Any, cell::Cell, fmt::{Debug, Formatter}, rc::Rc, @@ -30,8 +31,8 @@ use { }; pub struct Framebuffer { - pub(crate) ctx: Rc, - pub(crate) gl: GlFrameBuffer, + pub(in crate::gfx_apis::gl) ctx: Rc, + pub(in crate::gfx_apis::gl) gl: GlFrameBuffer, } impl Debug for Framebuffer { @@ -57,7 +58,14 @@ impl Framebuffer { }); } - pub fn copy_texture(&self, state: &State, texture: &Rc, 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); @@ -129,7 +137,7 @@ impl Framebuffer { }); } - pub fn render_custom(&self, scale: Scale, f: impl FnOnce(&mut RendererBase)) { + 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 { @@ -255,3 +263,69 @@ impl Framebuffer { }); } } + +impl GfxFramebuffer for Framebuffer { + fn as_any(&self) -> &dyn Any { + self + } + + fn clear(&self) { + self.clear() + } + + 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 copy_to_shm( + &self, + x: i32, + y: i32, + width: i32, + height: i32, + format: &Format, + shm: &[Cell], + ) { + 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, + on_output: bool, + result: &mut RenderResult, + scale: Scale, + render_hardware_cursor: bool, + ) { + self.render( + node, + state, + cursor_rect, + on_output, + 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/gfx_apis/gl/renderer/image.rs b/src/gfx_apis/gl/renderer/image.rs index aef63a71..a586f271 100644 --- a/src/gfx_apis/gl/renderer/image.rs +++ b/src/gfx_apis/gl/renderer/image.rs @@ -1,15 +1,18 @@ use { - crate::gfx_apis::gl::{ - egl::image::EglImage, - gl::{render_buffer::GlRenderBuffer, texture::GlTexture}, - Framebuffer, RenderContext, RenderError, Texture, + crate::{ + gfx_api::{GfxError, GfxFramebuffer, GfxImage, GfxTexture}, + gfx_apis::gl::{ + egl::image::EglImage, + gl::{render_buffer::GlRenderBuffer, texture::GlTexture}, + Framebuffer, GlRenderContext, RenderError, Texture, + }, }, std::rc::Rc, }; pub struct Image { - pub(crate) ctx: Rc, - pub(crate) gl: Rc, + pub(in crate::gfx_apis::gl) ctx: Rc, + pub(in crate::gfx_apis::gl) gl: Rc, } impl Image { @@ -21,14 +24,14 @@ impl Image { self.gl.height } - pub fn to_texture(self: &Rc) -> Result, RenderError> { + fn to_texture(self: &Rc) -> Result, RenderError> { Ok(Rc::new(Texture { ctx: self.ctx.clone(), gl: GlTexture::import_img(&self.ctx.ctx, &self.gl)?, })) } - pub fn to_framebuffer(&self) -> Result, RenderError> { + fn to_framebuffer(&self) -> Result, RenderError> { self.ctx.ctx.with_current(|| unsafe { let rb = GlRenderBuffer::from_image(&self.gl, &self.ctx.ctx)?; let fb = rb.create_framebuffer()?; @@ -39,3 +42,27 @@ impl Image { }) } } + +impl GfxImage for Image { + fn to_framebuffer(self: Rc) -> Result, GfxError> { + (*self) + .to_framebuffer() + .map(|v| v as Rc) + .map_err(|e| e.into()) + } + + fn to_texture(self: Rc) -> Result, GfxError> { + (&self) + .to_texture() + .map(|v| v as Rc) + .map_err(|e| e.into()) + } + + fn width(&self) -> i32 { + self.width() + } + + fn height(&self) -> i32 { + self.height() + } +} diff --git a/src/gfx_apis/gl/renderer/texture.rs b/src/gfx_apis/gl/renderer/texture.rs index b6b21d55..0eb73dd8 100644 --- a/src/gfx_apis/gl/renderer/texture.rs +++ b/src/gfx_apis/gl/renderer/texture.rs @@ -1,14 +1,18 @@ use { - crate::gfx_apis::gl::{gl::texture::GlTexture, renderer::context::RenderContext}, + crate::{ + gfx_api::GfxTexture, + gfx_apis::gl::{gl::texture::GlTexture, renderer::context::GlRenderContext}, + }, std::{ + any::Any, fmt::{Debug, Formatter}, rc::Rc, }, }; pub struct Texture { - pub(crate) ctx: Rc, - pub(crate) gl: GlTexture, + pub(in crate::gfx_apis::gl) ctx: Rc, + pub(in crate::gfx_apis::gl) gl: GlTexture, } impl Debug for Texture { @@ -26,3 +30,17 @@ impl Texture { self.gl.height } } + +impl GfxTexture for Texture { + fn width(&self) -> i32 { + self.width() + } + + fn height(&self) -> i32 { + self.height() + } + + fn as_any(&self) -> &dyn Any { + self + } +} diff --git a/src/ifs/jay_compositor.rs b/src/ifs/jay_compositor.rs index 87a446d6..2794d7e2 100644 --- a/src/ifs/jay_compositor.rs +++ b/src/ifs/jay_compositor.rs @@ -277,7 +277,7 @@ impl JayCompositor { .render_ctx_watchers .set((self.client.id, req.id), ctx.clone()); let rctx = self.client.state.render_ctx.get(); - ctx.send_render_ctx(rctx.as_ref()); + ctx.send_render_ctx(rctx); Ok(()) } diff --git a/src/ifs/jay_render_ctx.rs b/src/ifs/jay_render_ctx.rs index 0f2d980b..3b58c2a0 100644 --- a/src/ifs/jay_render_ctx.rs +++ b/src/ifs/jay_render_ctx.rs @@ -1,7 +1,7 @@ use { crate::{ client::{Client, ClientError}, - gfx_apis::gl::RenderContext, + gfx_api::GfxContext, leaks::Tracker, object::Object, utils::{ @@ -21,10 +21,10 @@ pub struct JayRenderCtx { } impl JayRenderCtx { - pub fn send_render_ctx(&self, ctx: Option<&Rc>) { + pub fn send_render_ctx(&self, ctx: Option>) { let mut fd = None; if let Some(ctx) = ctx { - match ctx.gbm.drm.dup_render() { + match ctx.gbm().drm.dup_render() { Ok(d) => fd = Some(d.fd().clone()), Err(e) => { log::error!("Could not dup drm fd: {}", ErrorFmt(e)); diff --git a/src/ifs/jay_screencast.rs b/src/ifs/jay_screencast.rs index a7edec67..951a12c4 100644 --- a/src/ifs/jay_screencast.rs +++ b/src/ifs/jay_screencast.rs @@ -2,7 +2,7 @@ use { crate::{ client::{Client, ClientError}, format::XRGB8888, - gfx_apis::gl::{Framebuffer, RenderContext, RenderError, Texture}, + gfx_api::{GfxContext, GfxError, GfxFramebuffer, GfxTexture}, ifs::jay_output::JayOutput, leaks::Tracker, object::Object, @@ -60,7 +60,7 @@ struct Pending { struct ScreencastBuffer { dmabuf: DmaBuf, - fb: Rc, + fb: Rc, free: bool, } @@ -147,7 +147,7 @@ impl JayScreencast { }); } - pub fn copy_texture(&self, on: &OutputNode, texture: &Rc) { + pub fn copy_texture(&self, on: &OutputNode, texture: &Rc) { if !self.running.get() { return; } @@ -193,7 +193,7 @@ impl JayScreencast { self.client.event(Destroyed { self_id: self.id }); } - pub fn realloc(&self, ctx: &Rc) -> Result<(), JayScreencastError> { + pub fn realloc(&self, ctx: &Rc) -> Result<(), JayScreencastError> { let mut buffers = vec![]; if let Some(output) = self.output.get() { let mode = output.global.mode.get(); @@ -207,8 +207,10 @@ impl JayScreencast { if self.linear.get() { flags |= GBM_BO_USE_LINEAR; } - let buffer = ctx.gbm.create_bo(mode.width, mode.height, &format, flags)?; - let fb = ctx.dmabuf_img(buffer.dmabuf())?.to_framebuffer()?; + let buffer = ctx + .gbm() + .create_bo(mode.width, mode.height, &format, flags)?; + let fb = ctx.clone().dmabuf_img(buffer.dmabuf())?.to_framebuffer()?; buffers.push(ScreencastBuffer { dmabuf: buffer.dmabuf().clone(), fb, @@ -444,7 +446,7 @@ pub enum JayScreencastError { #[error(transparent)] GbmError(#[from] GbmError), #[error(transparent)] - RenderError(#[from] RenderError), + GfxError(#[from] GfxError), } efrom!(JayScreencastError, MsgParserError); efrom!(JayScreencastError, ClientError); diff --git a/src/ifs/wl_buffer.rs b/src/ifs/wl_buffer.rs index 870feaaf..0e4c7139 100644 --- a/src/ifs/wl_buffer.rs +++ b/src/ifs/wl_buffer.rs @@ -3,7 +3,7 @@ use { client::{Client, ClientError}, clientmem::{ClientMem, ClientMemError, ClientMemOffset}, format::Format, - gfx_apis::gl::{Framebuffer, Image, RenderError, Texture}, + gfx_api::{GfxError, GfxFramebuffer, GfxImage, GfxTexture}, leaks::Tracker, object::Object, rect::Rect, @@ -25,7 +25,7 @@ use { pub enum WlBufferStorage { Shm { mem: ClientMemOffset, stride: i32 }, - Dmabuf(Rc), + Dmabuf(Rc), } pub struct WlBuffer { @@ -37,8 +37,8 @@ pub struct WlBuffer { dmabuf: Option, render_ctx_version: Cell, pub storage: RefCell>, - pub texture: CloneCell>>, - pub famebuffer: CloneCell>>, + pub texture: CloneCell>>, + pub famebuffer: CloneCell>>, width: i32, height: i32, pub tracker: Tracker, @@ -55,7 +55,7 @@ impl WlBuffer { client: &Rc, format: &'static Format, dmabuf: DmaBuf, - img: &Rc, + img: &Rc, ) -> Self { let width = img.width(); let height = img.height(); @@ -165,7 +165,7 @@ impl WlBuffer { } WlBufferStorage::Dmabuf(img) => { if self.texture.get().is_none() { - self.texture.set(Some(img.to_texture()?)); + self.texture.set(Some(img.clone().to_texture()?)); } } } @@ -184,7 +184,7 @@ impl WlBuffer { } WlBufferStorage::Dmabuf(img) => { if self.famebuffer.get().is_none() { - self.famebuffer.set(Some(img.to_framebuffer()?)); + self.famebuffer.set(Some(img.clone().to_framebuffer()?)); } } } @@ -225,14 +225,13 @@ pub enum WlBufferError { StrideTooSmall, #[error("Could not access the client memory")] ClientMemError(#[source] Box), - #[error("GLES could not import the client image")] - RenderError(#[source] Box), + #[error("The graphics library could not import the client image")] + GfxError(#[from] GfxError), #[error("Parsing failed")] MsgParserError(#[source] Box), #[error(transparent)] ClientError(Box), } efrom!(WlBufferError, ClientMemError); -efrom!(WlBufferError, RenderError); efrom!(WlBufferError, MsgParserError); efrom!(WlBufferError, ClientError); diff --git a/src/ifs/wl_drm.rs b/src/ifs/wl_drm.rs index 379eb33a..bc791506 100644 --- a/src/ifs/wl_drm.rs +++ b/src/ifs/wl_drm.rs @@ -1,7 +1,7 @@ use { crate::{ client::{Client, ClientError}, - gfx_apis::gl::RenderError, + gfx_api::GfxError, globals::{Global, GlobalName}, ifs::wl_buffer::WlBuffer, leaks::Tracker, @@ -190,7 +190,7 @@ pub enum WlDrmError { #[error("The format {0} is not supported")] InvalidFormat(u32), #[error("Could not import the buffer")] - ImportError(#[from] RenderError), + ImportError(#[from] GfxError), } efrom!(WlDrmError, ClientError); efrom!(WlDrmError, MsgParserError); diff --git a/src/ifs/wl_output.rs b/src/ifs/wl_output.rs index c866d8d1..9085f62b 100644 --- a/src/ifs/wl_output.rs +++ b/src/ifs/wl_output.rs @@ -3,7 +3,7 @@ use { backend, client::{Client, ClientError, ClientId}, format::XRGB8888, - gfx_apis::gl::{Framebuffer, Texture}, + gfx_api::{GfxFramebuffer, GfxTexture}, globals::{Global, GlobalName}, ifs::{ wl_buffer::WlBufferStorage, wl_surface::WlSurface, @@ -199,7 +199,7 @@ impl WlOutputGlobal { Ok(()) } - pub fn perform_screencopies(&self, fb: &Framebuffer, tex: &Rc) { + pub fn perform_screencopies(&self, fb: &dyn GfxFramebuffer, tex: &Rc) { if self.pending_captures.is_empty() { return; } diff --git a/src/ifs/zwp_linux_buffer_params_v1.rs b/src/ifs/zwp_linux_buffer_params_v1.rs index 52c05e32..f75d66d0 100644 --- a/src/ifs/zwp_linux_buffer_params_v1.rs +++ b/src/ifs/zwp_linux_buffer_params_v1.rs @@ -1,7 +1,7 @@ use { crate::{ client::ClientError, - gfx_apis::gl::RenderError, + gfx_api::GfxError, ifs::{wl_buffer::WlBuffer, zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1}, leaks::Tracker, object::Object, @@ -228,7 +228,7 @@ pub enum ZwpLinuxBufferParamsV1Error { #[error("Plane {0} was not set")] MissingPlane(usize), #[error("Could not import the buffer")] - ImportError(#[from] RenderError), + ImportError(#[from] GfxError), } efrom!(ZwpLinuxBufferParamsV1Error, ClientError); efrom!(ZwpLinuxBufferParamsV1Error, MsgParserError); diff --git a/src/portal/ptl_display.rs b/src/portal/ptl_display.rs index 3756a677..d1cd8861 100644 --- a/src/portal/ptl_display.rs +++ b/src/portal/ptl_display.rs @@ -1,6 +1,6 @@ use { crate::{ - gfx_apis::gl::RenderContext, + gfx_apis::create_gfx_context, ifs::wl_seat::POINTER, portal::{ ptl_render_ctx::PortalRenderCtx, ptl_screencast::ScreencastSession, @@ -169,7 +169,7 @@ impl UsrJayRenderCtxOwner for PortalDisplay { } if self.render_ctx.get().is_none() { let drm = Drm::open_existing(fd); - let ctx = match RenderContext::from_drm_device(&drm) { + let ctx = match create_gfx_context(&drm) { Ok(c) => c, Err(e) => { log::error!( @@ -179,10 +179,7 @@ impl UsrJayRenderCtxOwner for PortalDisplay { return; } }; - let ctx = Rc::new(PortalRenderCtx { - dev_id, - ctx: Rc::new(ctx), - }); + let ctx = Rc::new(PortalRenderCtx { dev_id, ctx }); self.render_ctx.set(Some(ctx.clone())); self.state.render_ctxs.set(dev_id, Rc::downgrade(&ctx)); } diff --git a/src/portal/ptl_render_ctx.rs b/src/portal/ptl_render_ctx.rs index 885c36cb..03fd115a 100644 --- a/src/portal/ptl_render_ctx.rs +++ b/src/portal/ptl_render_ctx.rs @@ -1,6 +1,6 @@ -use {crate::gfx_apis::gl::RenderContext, std::rc::Rc, uapi::c}; +use {crate::gfx_api::GfxContext, std::rc::Rc, uapi::c}; pub struct PortalRenderCtx { pub dev_id: c::dev_t, - pub ctx: Rc, + pub ctx: Rc, } diff --git a/src/portal/ptr_gui.rs b/src/portal/ptr_gui.rs index 5afff008..b97cdd77 100644 --- a/src/portal/ptr_gui.rs +++ b/src/portal/ptr_gui.rs @@ -4,7 +4,7 @@ use { cursor::KnownCursor, fixed::Fixed, format::ARGB8888, - gfx_apis::gl::{Framebuffer, RenderContext, Texture}, + gfx_api::{GfxContext, GfxFramebuffer, GfxTexture}, ifs::zwlr_layer_shell_v1::OVERLAY, portal::ptl_display::{PortalDisplay, PortalOutput, PortalSeat}, renderer::renderer_base::RendererBase, @@ -50,7 +50,7 @@ pub trait GuiElement { fn data(&self) -> &GuiElementData; fn layout( &self, - ctx: &Rc, + ctx: &Rc, scale: f32, max_width: f32, max_height: f32, @@ -118,7 +118,7 @@ pub struct Button { pub bg_hover_color: Cell, pub text: RefCell, pub font: RefCell>, - pub tex: CloneCell>>, + pub tex: CloneCell>>, pub owner: CloneCell>>, } @@ -157,7 +157,7 @@ impl GuiElement for Button { fn layout( &self, - ctx: &Rc, + ctx: &Rc, scale: f32, _max_width: f32, _max_height: f32, @@ -260,7 +260,7 @@ pub struct Label { pub data: GuiElementData, pub font: RefCell>, pub text: RefCell, - pub tex: CloneCell>>, + pub tex: CloneCell>>, } impl Default for Label { @@ -281,7 +281,7 @@ impl GuiElement for Label { fn layout( &self, - ctx: &Rc, + ctx: &Rc, scale: f32, _max_width: f32, _max_height: f32, @@ -364,7 +364,7 @@ impl GuiElement for Flow { fn layout( &self, - ctx: &Rc, + ctx: &Rc, scale: f32, max_width: f32, max_height: f32, @@ -638,7 +638,7 @@ impl WindowData { self.have_frame.set(false); buf.free.set(false); - buf.fb.render_custom(self.scale.get(), |r| { + buf.fb.render_custom(self.scale.get(), &mut |r| { r.clear(&Color::from_gray(0)); if let Some(content) = self.content.get() { content.render_at(r, 0.0, 0.0) @@ -700,7 +700,7 @@ impl WindowData { }; let bo = match ctx .ctx - .gbm + .gbm() .create_bo(width, height, &format, GBM_BO_USE_RENDERING) { Ok(b) => b, @@ -709,7 +709,7 @@ impl WindowData { return; } }; - let img = match ctx.ctx.dmabuf_img(bo.dmabuf()) { + let img = match ctx.ctx.clone().dmabuf_img(bo.dmabuf()) { Ok(b) => b, Err(e) => { log::error!("Could not import dmabuf into EGL: {}", ErrorFmt(e)); @@ -814,14 +814,14 @@ impl WindowData { pub struct GuiBuffer { pub wl: Rc, pub window: Rc, - pub fb: Rc, + pub fb: Rc, pub free: Cell, pub size: (i32, i32), } struct GuiBufferPending { pub window: Rc, - pub fb: Rc, + pub fb: Rc, pub params: Rc, pub size: (i32, i32), } diff --git a/src/renderer/renderer_base.rs b/src/renderer/renderer_base.rs index 0fc1fad1..6d022d30 100644 --- a/src/renderer/renderer_base.rs +++ b/src/renderer/renderer_base.rs @@ -3,8 +3,8 @@ use { format::Format, gfx_api::{ AbsoluteRect, BufferPoint, BufferPoints, Clear, CopyTexture, FillRect, GfxApiOpt, + GfxTexture, }, - gfx_apis::gl::Texture, rect::Rect, scale::Scale, theme::Color, @@ -120,7 +120,7 @@ impl RendererBase<'_> { pub fn render_texture( &mut self, - texture: &Rc, + texture: &Rc, x: i32, y: i32, format: &'static Format, diff --git a/src/screenshoter.rs b/src/screenshoter.rs index 42f40edb..2fea0a97 100644 --- a/src/screenshoter.rs +++ b/src/screenshoter.rs @@ -1,7 +1,7 @@ use { crate::{ format::XRGB8888, - gfx_apis::gl::RenderError, + gfx_api::GfxError, scale::Scale, state::State, video::{ @@ -24,7 +24,7 @@ pub enum ScreenshooterError { #[error(transparent)] GbmError(#[from] GbmError), #[error(transparent)] - RenderError(#[from] RenderError), + RenderError(#[from] GfxError), #[error(transparent)] DrmError(#[from] DrmError), } @@ -47,13 +47,14 @@ pub fn take_screenshot(state: &State) -> Result format: XRGB8888, modifier: INVALID_MODIFIER, }; - let bo = ctx.gbm.create_bo( + let gbm = ctx.gbm(); + let bo = gbm.create_bo( extents.width(), extents.height(), &format, GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR, )?; - let fb = ctx.dmabuf_fb(bo.dmabuf())?; + let fb = ctx.clone().dmabuf_fb(bo.dmabuf())?; fb.render( state.root.deref(), state, @@ -63,6 +64,6 @@ pub fn take_screenshot(state: &State) -> Result Scale::from_int(1), true, ); - let drm = ctx.gbm.drm.dup_render()?.fd().clone(); + let drm = gbm.drm.dup_render()?.fd().clone(); Ok(Screenshot { drm, bo }) } diff --git a/src/state.rs b/src/state.rs index 24815f58..da830015 100644 --- a/src/state.rs +++ b/src/state.rs @@ -13,7 +13,7 @@ use { cursor::{Cursor, ServerCursors}, dbus::Dbus, forker::ForkerProxy, - gfx_apis::gl::RenderContext, + gfx_api::GfxContext, globals::{Globals, GlobalsError, WaylandGlobal}, ifs::{ ext_session_lock_v1::ExtSessionLockV1, @@ -69,7 +69,7 @@ pub struct State { pub forker: CloneCell>>, pub default_keymap: Rc, pub eng: Rc, - pub render_ctx: CloneCell>>, + pub render_ctx: CloneCell>>, pub render_ctx_version: NumCell, pub render_ctx_ever_initialized: Cell, pub cursors: CloneCell>>, @@ -305,8 +305,8 @@ impl State { } } - pub fn set_render_ctx(&self, ctx: Option<&Rc>) { - self.render_ctx.set(ctx.cloned()); + pub fn set_render_ctx(&self, ctx: Option>) { + self.render_ctx.set(ctx.clone()); self.render_ctx_version.fetch_add(1); self.cursors.set(None); @@ -364,7 +364,7 @@ impl State { } for watcher in self.render_ctx_watchers.lock().values() { - watcher.send_render_ctx(ctx); + watcher.send_render_ctx(ctx.clone()); } let mut scs = vec![]; diff --git a/src/text.rs b/src/text.rs index 99a4105e..9913641e 100644 --- a/src/text.rs +++ b/src/text.rs @@ -1,7 +1,7 @@ use { crate::{ format::ARGB8888, - gfx_apis::gl::{RenderContext, RenderError, Texture}, + gfx_api::{GfxContext, GfxError, GfxTexture}, pango::{ consts::{ CAIRO_FORMAT_ARGB32, CAIRO_OPERATOR_SOURCE, PANGO_ELLIPSIZE_END, PANGO_SCALE, @@ -27,7 +27,7 @@ pub enum TextError { #[error("Could not create a pango layout")] CreateLayout(#[source] PangoError), #[error("Could not import the rendered text")] - RenderError(#[source] RenderError), + RenderError(#[source] GfxError), #[error("Could not access the cairo image data")] ImageData(#[source] PangoError), } @@ -94,21 +94,21 @@ pub fn measure( } pub fn render( - ctx: &Rc, + ctx: &Rc, width: i32, height: i32, font: &str, text: &str, color: Color, scale: Option, -) -> Result, TextError> { +) -> Result, TextError> { render2( ctx, 1, None, width, height, 1, font, text, color, true, false, scale, ) } fn render2( - ctx: &Rc, + ctx: &Rc, x: i32, y: Option, width: i32, @@ -120,7 +120,7 @@ fn render2( ellipsize: bool, markup: bool, scale: Option, -) -> Result, TextError> { +) -> Result, TextError> { let data = create_data(font, width, height, scale)?; if ellipsize { data.layout @@ -144,21 +144,24 @@ fn render2( Ok(d) => d, Err(e) => return Err(TextError::ImageData(e)), }; - match ctx.shmem_texture(bytes, ARGB8888, width, height, data.image.stride()) { + match ctx + .clone() + .shmem_texture(bytes, ARGB8888, width, height, data.image.stride()) + { Ok(t) => Ok(t), Err(e) => Err(TextError::RenderError(e)), } } pub fn render_fitting( - ctx: &Rc, + ctx: &Rc, height: Option, font: &str, text: &str, color: Color, markup: bool, scale: Option, -) -> Result, TextError> { +) -> Result, TextError> { render_fitting2(ctx, height, font, text, color, markup, scale, false).map(|(a, _)| a) } @@ -170,7 +173,7 @@ pub struct TextMeasurement { } pub fn render_fitting2( - ctx: &Rc, + ctx: &Rc, height: Option, font: &str, text: &str, @@ -178,7 +181,7 @@ pub fn render_fitting2( markup: bool, scale: Option, include_measurements: bool, -) -> Result<(Rc, TextMeasurement), TextError> { +) -> Result<(Rc, TextMeasurement), TextError> { let measurement = measure(font, text, markup, scale, include_measurements)?; let y = match height { Some(_) => None, diff --git a/src/tree/container.rs b/src/tree/container.rs index 5cce364f..eaff7a3c 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -3,7 +3,7 @@ use { backend::KeyState, cursor::KnownCursor, fixed::Fixed, - gfx_apis::gl::Texture, + gfx_api::GfxTexture, ifs::wl_seat::{ collect_kb_foci, collect_kb_foci2, wl_pointer::PendingScroll, NodeSeatState, SeatId, WlSeatGlobal, BTN_LEFT, @@ -77,7 +77,7 @@ tree_id!(ContainerNodeId); pub struct ContainerTitle { pub x: i32, pub y: i32, - pub tex: Rc, + pub tex: Rc, } #[derive(Default)] diff --git a/src/tree/float.rs b/src/tree/float.rs index e4b0fcad..525e6ff6 100644 --- a/src/tree/float.rs +++ b/src/tree/float.rs @@ -3,7 +3,7 @@ use { backend::KeyState, cursor::KnownCursor, fixed::Fixed, - gfx_apis::gl::Texture, + gfx_api::GfxTexture, ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal, BTN_LEFT}, rect::Rect, renderer::Renderer, @@ -44,7 +44,7 @@ pub struct FloatNode { pub layout_scheduled: Cell, pub render_titles_scheduled: Cell, pub title: RefCell, - pub title_textures: CopyHashMap>, + pub title_textures: CopyHashMap>, seats: RefCell>, } diff --git a/src/tree/output.rs b/src/tree/output.rs index 02497da8..53379c43 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -4,7 +4,7 @@ use { client::ClientId, cursor::KnownCursor, fixed::Fixed, - gfx_apis::gl::{Framebuffer, Texture}, + gfx_api::{GfxFramebuffer, GfxTexture}, ifs::{ jay_output::JayOutput, jay_screencast::JayScreencast, @@ -78,7 +78,7 @@ pub async fn output_render_data(state: Rc) { } impl OutputNode { - pub fn perform_screencopies(&self, fb: &Framebuffer, tex: &Rc) { + pub fn perform_screencopies(&self, fb: &dyn GfxFramebuffer, tex: &Rc) { if let Some(workspace) = self.workspace.get() { if !workspace.capture.get() { return; @@ -465,14 +465,14 @@ pub struct OutputTitle { pub x2: i32, pub tex_x: i32, pub tex_y: i32, - pub tex: Rc, + pub tex: Rc, pub ws: Rc, } pub struct OutputStatus { pub tex_x: i32, pub tex_y: i32, - pub tex: Rc, + pub tex: Rc, } #[derive(Copy, Clone)] diff --git a/src/tree/placeholder.rs b/src/tree/placeholder.rs index 37589d7e..72c3635b 100644 --- a/src/tree/placeholder.rs +++ b/src/tree/placeholder.rs @@ -3,7 +3,7 @@ use { client::Client, cursor::KnownCursor, fixed::Fixed, - gfx_apis::gl::Texture, + gfx_api::GfxTexture, ifs::wl_seat::{NodeSeatState, WlSeatGlobal}, rect::Rect, renderer::Renderer, @@ -25,7 +25,7 @@ pub struct PlaceholderNode { id: PlaceholderNodeId, toplevel: ToplevelData, destroyed: Cell, - pub textures: SmallMap, 2>, + pub textures: SmallMap, 2>, } impl PlaceholderNode {