1
0
Fork 0
forked from wry/wry

render: hide graphics API behind traits

This commit is contained in:
Julian Orth 2023-10-22 20:00:32 +02:00
parent d650b3375d
commit 24e410a5b5
40 changed files with 601 additions and 246 deletions

View file

@ -2,7 +2,7 @@ use {
crate::{ crate::{
async_engine::SpawnedFuture, async_engine::SpawnedFuture,
fixed::Fixed, fixed::Fixed,
gfx_apis::gl::Framebuffer, gfx_api::GfxFramebuffer,
ifs::wl_seat::wl_pointer::{CONTINUOUS, FINGER, HORIZONTAL_SCROLL, VERTICAL_SCROLL, WHEEL}, ifs::wl_seat::wl_pointer::{CONTINUOUS, FINGER, HORIZONTAL_SCROLL, VERTICAL_SCROLL, WHEEL},
video::drm::{ConnectorType, DrmError, DrmVersion}, video::drm::{ConnectorType, DrmError, DrmVersion},
}, },
@ -95,7 +95,7 @@ pub enum ConnectorEvent {
pub trait HardwareCursor: Debug { pub trait HardwareCursor: Debug {
fn set_enabled(&self, enabled: bool); fn set_enabled(&self, enabled: bool);
fn get_buffer(&self) -> Rc<Framebuffer>; fn get_buffer(&self) -> Rc<dyn GfxFramebuffer>;
fn set_position(&self, x: i32, y: i32); fn set_position(&self, x: i32, y: i32);
fn swap_buffer(&self); fn swap_buffer(&self);
fn commit(&self); fn commit(&self);

View file

@ -11,7 +11,7 @@ use {
}, },
backends::metal::video::{MetalDrmDeviceData, MetalRenderContext, PendingDrmDevice}, backends::metal::video::{MetalDrmDeviceData, MetalRenderContext, PendingDrmDevice},
dbus::{DbusError, SignalHandler}, dbus::{DbusError, SignalHandler},
gfx_apis::gl::RenderError, gfx_api::GfxError,
libinput::{ libinput::{
consts::{ consts::{
AccelProfile, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE, AccelProfile, LIBINPUT_CONFIG_ACCEL_PROFILE_ADAPTIVE,
@ -75,7 +75,7 @@ pub enum MetalError {
#[error("Could not update the drm properties")] #[error("Could not update the drm properties")]
UpdateProperties(#[source] DrmError), UpdateProperties(#[source] DrmError),
#[error("Could not create a render context")] #[error("Could not create a render context")]
CreateRenderContex(#[source] RenderError), CreateRenderContex(#[source] GfxError),
#[error("Cannot initialize connector because no CRTC is available")] #[error("Cannot initialize connector because no CRTC is available")]
NoCrtcForConnector, NoCrtcForConnector,
#[error("Cannot initialize connector because no primary plane is available")] #[error("Cannot initialize connector because no primary plane is available")]
@ -86,12 +86,12 @@ pub enum MetalError {
ScanoutBuffer(#[source] GbmError), ScanoutBuffer(#[source] GbmError),
#[error("addfb2 failed")] #[error("addfb2 failed")]
Framebuffer(#[source] DrmError), Framebuffer(#[source] DrmError),
#[error("Could not import a framebuffer into EGL")] #[error("Could not import a framebuffer into the graphics API")]
ImportFb(#[source] RenderError), ImportFb(#[source] GfxError),
#[error("Could not import a texture into EGL")] #[error("Could not import a texture into the graphics API")]
ImportTexture(#[source] RenderError), ImportTexture(#[source] GfxError),
#[error("Could not import an image into EGL")] #[error("Could not import an image into the graphics API")]
ImportImage(#[source] RenderError), ImportImage(#[source] GfxError),
#[error("Could not perform modeset")] #[error("Could not perform modeset")]
Modeset(#[source] DrmError), Modeset(#[source] DrmError),
#[error("Could not enable atomic modesetting")] #[error("Could not enable atomic modesetting")]

View file

@ -8,7 +8,8 @@ use {
backends::metal::{MetalBackend, MetalError}, backends::metal::{MetalBackend, MetalError},
edid::Descriptor, edid::Descriptor,
format::{Format, ARGB8888, XRGB8888}, 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}, ifs::wp_presentation_feedback::{KIND_HW_COMPLETION, KIND_VSYNC},
renderer::RenderResult, renderer::RenderResult,
state::State, state::State,
@ -52,7 +53,7 @@ pub struct PendingDrmDevice {
#[derive(Debug)] #[derive(Debug)]
pub struct MetalRenderContext { pub struct MetalRenderContext {
pub dev_id: DrmDeviceId, pub dev_id: DrmDeviceId,
pub egl: Rc<RenderContext>, pub gfx: Rc<dyn GfxContext>,
} }
#[derive(Debug)] #[derive(Debug)]
@ -214,7 +215,7 @@ impl HardwareCursor for MetalHardwareCursor {
} }
} }
fn get_buffer(&self) -> Rc<Framebuffer> { fn get_buffer(&self) -> Rc<dyn GfxFramebuffer> {
let buffer = (self.connector.cursor_front_buffer.get() + 1) % 2; let buffer = (self.connector.cursor_front_buffer.get() + 1) % 2;
self.cursor_buffers[buffer].render_fb() self.cursor_buffers[buffer].render_fb()
} }
@ -375,7 +376,7 @@ impl MetalConnector {
fr.send_done(); fr.send_done();
let _ = fr.client.remove_obj(&*fr); 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| { changes.change_object(plane.id, |c| {
c.change(plane.fb_id, buffer.drm.id().0 as _); c.change(plane.fb_id, buffer.drm.id().0 as _);
@ -883,9 +884,9 @@ impl MetalBackend {
None => return false, None => return false,
}; };
if let Some(r) = ctx if let Some(r) = ctx
.egl .gfx
.reset_status() .reset_status()
.or_else(|| dev.ctx.egl.reset_status()) .or_else(|| dev.ctx.gfx.reset_status())
{ {
fatal!("EGL context has been reset: {:?}", r); fatal!("EGL context has been reset: {:?}", r);
} }
@ -1090,13 +1091,13 @@ impl MetalBackend {
} }
} }
let egl = match RenderContext::from_drm_device(master) { let gfx = match create_gfx_context(master) {
Ok(r) => Rc::new(r), Ok(r) => r,
Err(e) => return Err(MetalError::CreateRenderContex(e)), Err(e) => return Err(MetalError::CreateRenderContex(e)),
}; };
let ctx = Rc::new(MetalRenderContext { let ctx = Rc::new(MetalRenderContext {
dev_id: pending.id, dev_id: pending.id,
egl, gfx,
}); });
let gbm = match GbmDevice::new(master) { let gbm = match GbmDevice::new(master) {
@ -1421,7 +1422,7 @@ impl MetalBackend {
return true; 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())); self.ctx.set(Some(dev.ctx.clone()));
let mut preserve = Preserve::default(); let mut preserve = Preserve::default();
for dev in self.device_holder.drm_devices.lock().values() { for dev in self.device_holder.drm_devices.lock().values() {
@ -1601,11 +1602,11 @@ impl MetalBackend {
Ok(fb) => Rc::new(fb), Ok(fb) => Rc::new(fb),
Err(e) => return Err(MetalError::Framebuffer(e)), 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, Ok(img) => img,
Err(e) => return Err(MetalError::ImportImage(e)), 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, Ok(fb) => fb,
Err(e) => return Err(MetalError::ImportFb(e)), Err(e) => return Err(MetalError::ImportFb(e)),
}; };
@ -1619,16 +1620,16 @@ impl MetalBackend {
} else { } else {
// Create a _bridge_ BO in the render device // Create a _bridge_ BO in the render device
usage = GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR; 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 { let render_bo = match render_bo {
Ok(b) => b, Ok(b) => b,
Err(e) => return Err(MetalError::ScanoutBuffer(e)), 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, Ok(img) => img,
Err(e) => return Err(MetalError::ImportImage(e)), 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, Ok(fb) => fb,
Err(e) => return Err(MetalError::ImportFb(e)), Err(e) => return Err(MetalError::ImportFb(e)),
}; };
@ -1639,7 +1640,7 @@ impl MetalBackend {
}; };
// Import the bridge BO into the current device // 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, Ok(img) => img,
Err(e) => return Err(MetalError::ImportImage(e)), Err(e) => return Err(MetalError::ImportImage(e)),
}; };
@ -1833,20 +1834,20 @@ pub struct RenderBuffer {
drm: Rc<DrmFramebuffer>, drm: Rc<DrmFramebuffer>,
// ctx = dev // ctx = dev
// buffer location = dev // buffer location = dev
dev_fb: Rc<Framebuffer>, dev_fb: Rc<dyn GfxFramebuffer>,
// ctx = dev // ctx = dev
// buffer location = render // buffer location = render
dev_tex: Option<Rc<Texture>>, dev_tex: Option<Rc<dyn GfxTexture>>,
// ctx = render // ctx = render
// buffer location = render // buffer location = render
render_tex: Rc<Texture>, render_tex: Rc<dyn GfxTexture>,
// ctx = render // ctx = render
// buffer location = render // buffer location = render
render_fb: Option<Rc<Framebuffer>>, render_fb: Option<Rc<dyn GfxFramebuffer>>,
} }
impl RenderBuffer { impl RenderBuffer {
fn render_fb(&self) -> Rc<Framebuffer> { fn render_fb(&self) -> Rc<dyn GfxFramebuffer> {
self.render_fb self.render_fb
.clone() .clone()
.unwrap_or_else(|| self.dev_fb.clone()) .unwrap_or_else(|| self.dev_fb.clone())

View file

@ -9,7 +9,8 @@ use {
}, },
fixed::Fixed, fixed::Fixed,
format::XRGB8888, format::XRGB8888,
gfx_apis::gl::{Framebuffer, RenderContext, RenderError, Texture}, gfx_api::{GfxContext, GfxError, GfxFramebuffer, GfxTexture},
gfx_apis::create_gfx_context,
renderer::RenderResult, renderer::RenderResult,
state::State, state::State,
time::now_usec, time::now_usec,
@ -89,14 +90,14 @@ pub enum XBackendError {
GbmError(#[from] GbmError), GbmError(#[from] GbmError),
#[error("Could not import a dma-buf")] #[error("Could not import a dma-buf")]
ImportBuffer(#[source] XconError), ImportBuffer(#[source] XconError),
#[error("Could not create an EGL context")] #[error("Could not create a graphics API context")]
CreateEgl(#[source] RenderError), CreateEgl(#[source] GfxError),
#[error("Could not create an EGL image from a dma-buf")] #[error("Could not create an graphics API image from a dma-buf")]
CreateImage(#[source] RenderError), CreateImage(#[source] GfxError),
#[error("Could not create a framebuffer from an EGL image")] #[error("Could not create a framebuffer from a graphics API image")]
CreateFramebuffer(#[source] RenderError), CreateFramebuffer(#[source] GfxError),
#[error("Could not create a texture from an EGL image")] #[error("Could not create a texture from an graphics API image")]
CreateTexture(#[source] RenderError), CreateTexture(#[source] GfxError),
#[error("Could not select input events")] #[error("Could not select input events")]
CannotSelectInputEvents(#[source] XconError), CannotSelectInputEvents(#[source] XconError),
#[error("Could not select present events")] #[error("Could not select present events")]
@ -178,8 +179,8 @@ pub async fn create(state: &Rc<State>) -> Result<Rc<XBackend>, XBackendError> {
Err(e) => return Err(XBackendError::DrmDeviceFstat(e)), Err(e) => return Err(XBackendError::DrmDeviceFstat(e)),
}; };
let gbm = GbmDevice::new(&drm)?; let gbm = GbmDevice::new(&drm)?;
let ctx = match RenderContext::from_drm_device(&drm) { let ctx = match create_gfx_context(&drm) {
Ok(r) => Rc::new(r), Ok(r) => r,
Err(e) => return Err(XBackendError::CreateEgl(e)), Err(e) => return Err(XBackendError::CreateEgl(e)),
}; };
let cursor = { let cursor = {
@ -266,7 +267,7 @@ pub struct XBackend {
outputs: CopyHashMap<u32, Rc<XOutput>>, outputs: CopyHashMap<u32, Rc<XOutput>>,
seats: CopyHashMap<u16, Rc<XSeat>>, seats: CopyHashMap<u16, Rc<XSeat>>,
mouse_seats: CopyHashMap<u16, Rc<XSeat>>, mouse_seats: CopyHashMap<u16, Rc<XSeat>>,
ctx: Rc<RenderContext>, ctx: Rc<dyn GfxContext>,
gbm: GbmDevice, gbm: GbmDevice,
cursor: u32, cursor: u32,
root: u32, root: u32,
@ -288,7 +289,7 @@ impl XBackend {
.eng .eng
.spawn2(Phase::Present, self.clone().present_handler()); .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 self.state
.backend_events .backend_events
.push(BackendEvent::NewDrmDevice(Rc::new(XDrmDevice { .push(BackendEvent::NewDrmDevice(Rc::new(XDrmDevice {
@ -388,11 +389,11 @@ impl XBackend {
assert!(dma.planes.len() == 1); assert!(dma.planes.len() == 1);
let plane = dma.planes.first().unwrap(); let plane = dma.planes.first().unwrap();
let size = plane.stride * dma.height as u32; 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, Ok(f) => f,
Err(e) => return Err(XBackendError::CreateImage(e)), Err(e) => return Err(XBackendError::CreateImage(e)),
}; };
let fb = match img.to_framebuffer() { let fb = match img.clone().to_framebuffer() {
Ok(f) => f, Ok(f) => f,
Err(e) => return Err(XBackendError::CreateFramebuffer(e)), Err(e) => return Err(XBackendError::CreateFramebuffer(e)),
}; };
@ -735,7 +736,7 @@ impl XBackend {
fr.send_done(); fr.send_done();
let _ = fr.client.remove_obj(&*fr); let _ = fr.client.remove_obj(&*fr);
} }
node.perform_screencopies(&fb, &image.tex.get()); node.perform_screencopies(&*fb, &image.tex.get());
} }
let pp = PresentPixmap { let pp = PresentPixmap {
@ -989,8 +990,8 @@ struct XOutput {
struct XImage { struct XImage {
pixmap: Cell<u32>, pixmap: Cell<u32>,
fb: CloneCell<Rc<Framebuffer>>, fb: CloneCell<Rc<dyn GfxFramebuffer>>,
tex: CloneCell<Rc<Texture>>, tex: CloneCell<Rc<dyn GfxTexture>>,
idle: Cell<bool>, idle: Cell<bool>,
render_on_idle: Cell<bool>, render_on_idle: Cell<bool>,
last_serial: Cell<u32>, last_serial: Cell<u32>,

View file

@ -15,7 +15,6 @@ use {
config::ConfigProxy, config::ConfigProxy,
dbus::Dbus, dbus::Dbus,
forker, forker,
gfx_apis::gl::{self, RenderError},
globals::Globals, globals::Globals,
ifs::{wl_output::WlOutputGlobal, wl_surface::NoneSurfaceExt}, ifs::{wl_output::WlOutputGlobal, wl_surface::NoneSurfaceExt},
io_uring::{IoUring, IoUringError}, io_uring::{IoUring, IoUringError},
@ -86,8 +85,6 @@ pub enum CompositorError {
ClientmemError(#[from] ClientMemError), ClientmemError(#[from] ClientMemError),
#[error("The timer subsystem caused an error")] #[error("The timer subsystem caused an error")]
WheelError(#[from] WheelError), WheelError(#[from] WheelError),
#[error("The render backend caused an error")]
RenderError(#[from] RenderError),
#[error("Could not create an io-uring")] #[error("Could not create an io-uring")]
IoUringError(#[from] IoUringError), IoUringError(#[from] IoUringError),
} }
@ -112,7 +109,6 @@ fn start_compositor2(
log::info!("pid = {}", uapi::getpid()); log::info!("pid = {}", uapi::getpid());
init_fd_limit(); init_fd_limit();
leaks::init(); leaks::init();
gl::init()?;
clientmem::init()?; clientmem::init()?;
let xkb_ctx = XkbContext::new().unwrap(); let xkb_ctx = XkbContext::new().unwrap();
let xkb_keymap = xkb_ctx.keymap_from_str(include_str!("keymap.xkb")).unwrap(); let xkb_keymap = xkb_ctx.keymap_from_str(include_str!("keymap.xkb")).unwrap();

View file

@ -2,7 +2,7 @@ use {
crate::{ crate::{
fixed::Fixed, fixed::Fixed,
format::ARGB8888, format::ARGB8888,
gfx_apis::gl::{RenderContext, RenderError, Texture}, gfx_api::{GfxContext, GfxError, GfxTexture},
rect::Rect, rect::Rect,
renderer::Renderer, renderer::Renderer,
scale::Scale, scale::Scale,
@ -87,7 +87,7 @@ pub enum KnownCursor {
} }
impl ServerCursors { impl ServerCursors {
pub fn load(ctx: &Rc<RenderContext>, state: &State) -> Result<Option<Self>, CursorError> { pub fn load(ctx: &Rc<dyn GfxContext>, state: &State) -> Result<Option<Self>, CursorError> {
let paths = find_cursor_paths(); let paths = find_cursor_paths();
log::debug!("Trying to load cursors from paths {:?}", paths); log::debug!("Trying to load cursors from paths {:?}", paths);
let sizes = state.cursor_sizes.to_vec(); let sizes = state.cursor_sizes.to_vec();
@ -135,7 +135,7 @@ impl ServerCursorTemplate {
scales: &[Scale], scales: &[Scale],
sizes: &[u32], sizes: &[u32],
paths: &[BString], paths: &[BString],
ctx: &Rc<RenderContext>, ctx: &Rc<dyn GfxContext>,
) -> Result<Self, CursorError> { ) -> Result<Self, CursorError> {
match open_cursor(name, theme, scales, sizes, paths) { match open_cursor(name, theme, scales, sizes, paths) {
Ok(cs) => { Ok(cs) => {
@ -215,7 +215,7 @@ impl ServerCursorTemplate {
struct CursorImageScaled { struct CursorImageScaled {
extents: Rect, extents: Rect,
tex: Rc<Texture>, tex: Rc<dyn GfxTexture>,
} }
struct CursorImage { struct CursorImage {
@ -230,7 +230,7 @@ struct InstantiatedCursorImage {
impl CursorImageScaled { impl CursorImageScaled {
fn from_bytes( fn from_bytes(
ctx: &Rc<RenderContext>, ctx: &Rc<dyn GfxContext>,
data: &[Cell<u8>], data: &[Cell<u8>],
width: i32, width: i32,
height: i32, height: i32,
@ -239,7 +239,9 @@ impl CursorImageScaled {
) -> Result<Rc<Self>, CursorError> { ) -> Result<Rc<Self>, CursorError> {
Ok(Rc::new(Self { Ok(Rc::new(Self {
extents: Rect::new_sized(-xhot, -yhot, width, height).unwrap(), 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")] #[error("The requested cursor could not be found")]
NotFound, NotFound,
#[error("Could not import the cursor as a texture")] #[error("Could not import the cursor as a texture")]
ImportError(#[from] RenderError), ImportError(#[from] GfxError),
} }
#[derive(Default, Clone)] #[derive(Default, Clone)]

View file

@ -1,6 +1,25 @@
use { use {
crate::{format::Format, gfx_apis::gl::Texture, theme::Color}, crate::{
std::rc::Rc, 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 { pub enum GfxApiOpt {
@ -77,8 +96,123 @@ pub struct FillRect {
} }
pub struct CopyTexture { pub struct CopyTexture {
pub tex: Rc<Texture>, pub tex: Rc<dyn GfxTexture>,
pub format: &'static Format, pub format: &'static Format,
pub source: BufferPoints, pub source: BufferPoints,
pub target: AbsoluteRect, 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<dyn GfxTexture>,
x: i32,
y: i32,
alpha: bool,
);
fn copy_to_shm(
&self,
x: i32,
y: i32,
width: i32,
height: i32,
format: &Format,
shm: &[Cell<u8>],
);
fn render_custom(&self, scale: Scale, f: &mut dyn FnMut(&mut RendererBase));
fn render(
&self,
node: &dyn Node,
state: &State,
cursor_rect: Option<Rect>,
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<Self>) -> Result<Rc<dyn GfxFramebuffer>, GfxError>;
fn to_texture(self: Rc<Self>) -> Result<Rc<dyn GfxTexture>, 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<GfxApiOpt>;
fn reset_status(&self) -> Option<ResetStatus>;
fn supports_external_texture(&self) -> bool;
fn render_node(&self) -> Rc<CString>;
fn formats(&self) -> Rc<AHashMap<u32, GfxFormat>>;
fn dmabuf_fb(self: Rc<Self>, buf: &DmaBuf) -> Result<Rc<dyn GfxFramebuffer>, GfxError>;
fn dmabuf_img(self: Rc<Self>, buf: &DmaBuf) -> Result<Rc<dyn GfxImage>, GfxError>;
fn shmem_texture(
self: Rc<Self>,
data: &[Cell<u8>],
format: &'static Format,
width: i32,
height: i32,
stride: i32,
) -> Result<Rc<dyn GfxTexture>, GfxError>;
fn gbm(&self) -> &GbmDevice;
}
#[derive(Debug)]
pub struct GfxFormat {
pub format: &'static Format,
pub implicit_external_only: bool,
pub modifiers: AHashMap<u64, GfxModifier>,
}
#[derive(Debug)]
pub struct GfxModifier {
pub modifier: u64,
pub external_only: bool,
}
#[derive(Error)]
#[error(transparent)]
pub struct GfxError(pub Box<dyn Error>);
impl Debug for GfxError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
Debug::fmt(&self.0, f)
}
}

View file

@ -1 +1,13 @@
use {
crate::{
gfx_api::{GfxContext, GfxError},
video::drm::Drm,
},
std::rc::Rc,
};
pub mod gl; pub mod gl;
pub fn create_gfx_context(drm: &Drm) -> Result<Rc<dyn GfxContext>, GfxError> {
gl::create_gfx_context(drm)
}

View file

@ -18,13 +18,15 @@ macro_rules! egl_transparent {
}; };
} }
pub use renderer::*;
use { use {
crate::{ crate::{
format::Format, format::Format,
gfx_api::{BufferPoints, CopyTexture, FillRect, GfxApiOpt}, gfx_api::{
BufferPoints, CopyTexture, FillRect, GfxApiOpt, GfxContext, GfxError, GfxTexture,
},
gfx_apis::gl::{ gfx_apis::gl::{
gl::texture::image_target, gl::texture::image_target,
renderer::{context::GlRenderContext, framebuffer::Framebuffer, texture::Texture},
sys::{ sys::{
glActiveTexture, glBindTexture, glClear, glClearColor, glDisable, glActiveTexture, glBindTexture, glClear, glClearColor, glDisable,
glDisableVertexAttribArray, glDrawArrays, glEnable, glEnableVertexAttribArray, glDisableVertexAttribArray, glDrawArrays, glEnable, glEnableVertexAttribArray,
@ -35,10 +37,14 @@ use {
}, },
theme::Color, theme::Color,
utils::{rc_eq::rc_eq, vecstorage::VecStorage}, utils::{rc_eq::rc_eq, vecstorage::VecStorage},
video::{drm::DrmError, gbm::GbmError}, video::{
drm::{Drm, DrmError},
gbm::GbmError,
},
}, },
isnt::std_1::vec::IsntVecExt, isnt::std_1::vec::IsntVecExt,
std::cell::RefCell, once_cell::sync::Lazy,
std::{cell::RefCell, rc::Rc, sync::Arc},
thiserror::Error, thiserror::Error,
}; };
@ -52,12 +58,19 @@ pub mod sys {
pub use super::{egl::sys::*, gl::sys::*}; pub use super::{egl::sys::*, gl::sys::*};
} }
pub fn init() -> Result<(), RenderError> { static INIT: Lazy<Result<(), Arc<RenderError>>> = Lazy::new(|| egl::init().map_err(Arc::new));
egl::init()
pub(super) fn create_gfx_context(drm: &Drm) -> Result<Rc<dyn GfxContext>, 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<dyn GfxContext>)
.map_err(|e| e.into())
} }
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum RenderError { enum RenderError {
#[error("EGL library does not support `EGL_EXT_platform_base`")] #[error("EGL library does not support `EGL_EXT_platform_base`")]
ExtPlatformBase, ExtPlatformBase,
#[error("Could not compile a shader")] #[error("Could not compile a shader")]
@ -117,13 +130,13 @@ pub enum RenderError {
} }
#[derive(Default)] #[derive(Default)]
pub struct GfxGlState { struct GfxGlState {
triangles: RefCell<Vec<f32>>, triangles: RefCell<Vec<f32>>,
fill_rect: VecStorage<&'static FillRect>, fill_rect: VecStorage<&'static FillRect>,
copy_tex: VecStorage<&'static CopyTexture>, 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 mut state = fb.ctx.gl_state.borrow_mut();
let state = &mut *state; let state = &mut *state;
let mut fill_rect = state.fill_rect.take(); 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 y1 = 2.0 * (tex.target.y1 / height) - 1.0;
let x2 = 2.0 * (tex.target.x2 / width) - 1.0; let x2 = 2.0 * (tex.target.x2 / width) - 1.0;
let y2 = 2.0 * (tex.target.y2 / height) - 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 { unsafe {
glUseProgram(ctx.fill_prog.prog); glUseProgram(ctx.fill_prog.prog);
glUniform4f(ctx.fill_prog_color, color.r, color.g, color.b, color.a); 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( fn render_texture(
ctx: &RenderContext, ctx: &GlRenderContext,
texture: &Texture, texture: &Texture,
format: &Format, format: &Format,
x1: f32, x1: f32,
@ -320,3 +342,17 @@ fn render_texture(
glBindTexture(target, 0); 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<RenderError> for GfxError {
fn from(value: RenderError) -> Self {
Self(Box::new(value))
}
}

View file

@ -31,7 +31,7 @@ pub(crate) static PROCS: Lazy<ExtProc> = Lazy::new(ExtProc::load);
pub(crate) static EXTS: Lazy<ClientExt> = Lazy::new(get_client_ext); pub(crate) static EXTS: Lazy<ClientExt> = 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) { if !EXTS.contains(ClientExt::EXT_PLATFORM_BASE) {
return Err(RenderError::ExtPlatformBase); return Err(RenderError::ExtPlatformBase);
} }

View file

@ -1,16 +1,21 @@
use { use {
crate::gfx_apis::gl::{ crate::{
egl::{ gfx_api::ResetStatus,
display::EglDisplay, gfx_apis::gl::{
sys::{eglDestroyContext, eglMakeCurrent, EGLContext, EGLSurface, EGL_FALSE, EGL_TRUE}, egl::{
PROCS, 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, std::rc::Rc,
}; };
@ -58,7 +63,7 @@ impl EglContext {
} }
#[inline] #[inline]
pub fn with_current<T, F: FnOnce() -> Result<T, RenderError>>( pub(in crate::gfx_apis::gl) fn with_current<T, F: FnOnce() -> Result<T, RenderError>>(
&self, &self,
f: F, f: F,
) -> Result<T, RenderError> { ) -> Result<T, RenderError> {

View file

@ -1,6 +1,7 @@
use { use {
crate::{ crate::{
format::{formats, Format}, format::{formats, Format},
gfx_api::{GfxFormat, GfxModifier},
gfx_apis::gl::{ gfx_apis::gl::{
egl::{ egl::{
context::EglContext, context::EglContext,
@ -35,29 +36,16 @@ use {
std::{ptr, rc::Rc}, std::{ptr, rc::Rc},
}; };
#[derive(Debug)]
pub struct EglFormat {
pub format: &'static Format,
pub implicit_external_only: bool,
pub modifiers: AHashMap<u64, EglModifier>,
}
#[derive(Debug)]
pub struct EglModifier {
pub modifier: u64,
pub external_only: bool,
}
#[derive(Debug)] #[derive(Debug)]
pub struct EglDisplay { pub struct EglDisplay {
pub exts: DisplayExt, pub exts: DisplayExt,
pub formats: Rc<AHashMap<u32, EglFormat>>, pub formats: Rc<AHashMap<u32, GfxFormat>>,
pub gbm: Rc<GbmDevice>, pub gbm: Rc<GbmDevice>,
pub dpy: EGLDisplay, pub dpy: EGLDisplay,
} }
impl EglDisplay { impl EglDisplay {
pub fn create(drm: &Drm) -> Result<Rc<Self>, RenderError> { pub(in crate::gfx_apis::gl) fn create(drm: &Drm) -> Result<Rc<Self>, RenderError> {
unsafe { unsafe {
let gbm = match GbmDevice::new(drm) { let gbm = match GbmDevice::new(drm) {
Ok(gbm) => gbm, Ok(gbm) => gbm,
@ -107,7 +95,9 @@ impl EglDisplay {
} }
} }
pub fn create_context(self: &Rc<Self>) -> Result<Rc<EglContext>, RenderError> { pub(in crate::gfx_apis::gl) fn create_context(
self: &Rc<Self>,
) -> Result<Rc<EglContext>, RenderError> {
let mut attrib = vec![EGL_CONTEXT_CLIENT_VERSION, 2]; let mut attrib = vec![EGL_CONTEXT_CLIENT_VERSION, 2];
if self if self
.exts .exts
@ -142,7 +132,10 @@ impl EglDisplay {
} }
} }
pub fn import_dmabuf(self: &Rc<Self>, buf: &DmaBuf) -> Result<Rc<EglImage>, RenderError> { pub(in crate::gfx_apis::gl) fn import_dmabuf(
self: &Rc<Self>,
buf: &DmaBuf,
) -> Result<Rc<EglImage>, RenderError> {
let format = match self.formats.get(&buf.format.drm) { let format = match self.formats.get(&buf.format.drm) {
Some(fmt) => match fmt.modifiers.get(&buf.modifier) { Some(fmt) => match fmt.modifiers.get(&buf.modifier) {
Some(fmt) => fmt, Some(fmt) => fmt,
@ -235,7 +228,7 @@ impl Drop for EglDisplay {
} }
} }
unsafe fn query_formats(dpy: EGLDisplay) -> Result<AHashMap<u32, EglFormat>, RenderError> { unsafe fn query_formats(dpy: EGLDisplay) -> Result<AHashMap<u32, GfxFormat>, RenderError> {
let mut vec = vec![]; let mut vec = vec![];
let mut num = 0; let mut num = 0;
let res = PROCS.eglQueryDmaBufFormatsEXT(dpy, num, ptr::null_mut(), &mut num); let res = PROCS.eglQueryDmaBufFormatsEXT(dpy, num, ptr::null_mut(), &mut num);
@ -255,7 +248,7 @@ unsafe fn query_formats(dpy: EGLDisplay) -> Result<AHashMap<u32, EglFormat>, Ren
let (modifiers, external_only) = query_modifiers(dpy, fmt, format)?; let (modifiers, external_only) = query_modifiers(dpy, fmt, format)?;
res.insert( res.insert(
format.drm, format.drm,
EglFormat { GfxFormat {
format, format,
implicit_external_only: external_only, implicit_external_only: external_only,
modifiers, modifiers,
@ -270,7 +263,7 @@ unsafe fn query_modifiers(
dpy: EGLDisplay, dpy: EGLDisplay,
gl_format: EGLint, gl_format: EGLint,
format: &'static Format, format: &'static Format,
) -> Result<(AHashMap<u64, EglModifier>, bool), RenderError> { ) -> Result<(AHashMap<u64, GfxModifier>, bool), RenderError> {
let mut mods = vec![]; let mut mods = vec![];
let mut ext_only = vec![]; let mut ext_only = vec![];
let mut num = 0; 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()) { for (modifier, ext_only) in mods.iter().copied().zip(ext_only.iter().copied()) {
res.insert( res.insert(
modifier as _, modifier as _,
EglModifier { GfxModifier {
modifier: modifier as _, modifier: modifier as _,
external_only: ext_only == EGL_TRUE, external_only: ext_only == EGL_TRUE,
}, },
@ -316,7 +309,7 @@ unsafe fn query_modifiers(
} }
res.insert( res.insert(
INVALID_MODIFIER, INVALID_MODIFIER,
EglModifier { GfxModifier {
modifier: INVALID_MODIFIER, modifier: INVALID_MODIFIER,
external_only, external_only,
}, },

View file

@ -21,7 +21,7 @@ pub struct GlProgram {
} }
impl GlProgram { impl GlProgram {
pub unsafe fn from_shaders( pub(in crate::gfx_apis::gl) unsafe fn from_shaders(
ctx: &Rc<EglContext>, ctx: &Rc<EglContext>,
vert: &str, vert: &str,
frag: &str, frag: &str,
@ -31,7 +31,10 @@ impl GlProgram {
Self::link(&vert, &frag) Self::link(&vert, &frag)
} }
pub unsafe fn link(vert: &GlShader, frag: &GlShader) -> Result<Self, RenderError> { pub(in crate::gfx_apis::gl) unsafe fn link(
vert: &GlShader,
frag: &GlShader,
) -> Result<Self, RenderError> {
let res = GlProgram { let res = GlProgram {
_ctx: vert.ctx.clone(), _ctx: vert.ctx.clone(),
prog: glCreateProgram(), prog: glCreateProgram(),

View file

@ -22,7 +22,7 @@ pub struct GlRenderBuffer {
} }
impl GlRenderBuffer { impl GlRenderBuffer {
pub unsafe fn from_image( pub(in crate::gfx_apis::gl) unsafe fn from_image(
img: &Rc<EglImage>, img: &Rc<EglImage>,
ctx: &Rc<EglContext>, ctx: &Rc<EglContext>,
) -> Result<Rc<GlRenderBuffer>, RenderError> { ) -> Result<Rc<GlRenderBuffer>, RenderError> {
@ -41,7 +41,9 @@ impl GlRenderBuffer {
})) }))
} }
pub unsafe fn create_framebuffer(self: &Rc<Self>) -> Result<GlFrameBuffer, RenderError> { pub(in crate::gfx_apis::gl) unsafe fn create_framebuffer(
self: &Rc<Self>,
) -> Result<GlFrameBuffer, RenderError> {
let mut fbo = 0; let mut fbo = 0;
glGenFramebuffers(1, &mut fbo); glGenFramebuffers(1, &mut fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo);

View file

@ -17,7 +17,7 @@ pub struct GlShader {
} }
impl GlShader { impl GlShader {
pub unsafe fn compile( pub(in crate::gfx_apis::gl) unsafe fn compile(
ctx: &Rc<EglContext>, ctx: &Rc<EglContext>,
ty: GLenum, ty: GLenum,
src: &str, src: &str,

View file

@ -33,7 +33,10 @@ pub fn image_target(external_only: bool) -> GLenum {
} }
impl GlTexture { impl GlTexture {
pub fn import_img(ctx: &Rc<EglContext>, img: &Rc<EglImage>) -> Result<GlTexture, RenderError> { pub(in crate::gfx_apis::gl) fn import_img(
ctx: &Rc<EglContext>,
img: &Rc<EglImage>,
) -> Result<GlTexture, RenderError> {
if !ctx.ext.contains(GlExt::GL_OES_EGL_IMAGE_EXTERNAL) { if !ctx.ext.contains(GlExt::GL_OES_EGL_IMAGE_EXTERNAL) {
return Err(RenderError::ExternalUnsupported); 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<EglContext>, ctx: &Rc<EglContext>,
data: &[Cell<u8>], data: &[Cell<u8>],
format: &'static Format, format: &'static Format,

View file

@ -1,6 +1,4 @@
pub use {context::*, framebuffer::*, image::*, texture::*}; pub(super) mod context;
pub(super) mod framebuffer;
mod context; pub(super) mod image;
mod framebuffer; pub(super) mod texture;
mod image;
mod texture;

View file

@ -1,12 +1,12 @@
use { use {
crate::{ crate::{
format::{Format, XRGB8888}, format::{Format, XRGB8888},
gfx_api::GfxApiOpt, gfx_api::{
GfxApiOpt, GfxContext, GfxError, GfxFormat, GfxFramebuffer, GfxImage, GfxTexture,
ResetStatus,
},
gfx_apis::gl::{ gfx_apis::gl::{
egl::{ egl::{context::EglContext, display::EglDisplay},
context::EglContext,
display::{EglDisplay, EglFormat},
},
ext::GlExt, ext::GlExt,
gl::{ gl::{
program::GlProgram, render_buffer::GlRenderBuffer, sys::GLint, texture::GlTexture, program::GlProgram, render_buffer::GlRenderBuffer, sys::GLint, texture::GlTexture,
@ -25,6 +25,7 @@ use {
cell::{Cell, RefCell}, cell::{Cell, RefCell},
ffi::CString, ffi::CString,
fmt::{Debug, Formatter}, fmt::{Debug, Formatter},
mem,
rc::Rc, rc::Rc,
}, },
uapi::ustr, uapi::ustr,
@ -53,7 +54,7 @@ pub(crate) struct TexProgs {
pub solid: TexProg, pub solid: TexProg,
} }
pub struct RenderContext { pub(in crate::gfx_apis::gl) struct GlRenderContext {
pub(crate) ctx: Rc<EglContext>, pub(crate) ctx: Rc<EglContext>,
pub gbm: Rc<GbmDevice>, pub gbm: Rc<GbmDevice>,
@ -67,24 +68,16 @@ pub struct RenderContext {
pub(crate) fill_prog_color: GLint, pub(crate) fill_prog_color: GLint,
pub(crate) gfx_ops: RefCell<Vec<GfxApiOpt>>, pub(crate) gfx_ops: RefCell<Vec<GfxApiOpt>>,
pub(crate) gl_state: RefCell<GfxGlState>, pub(in crate::gfx_apis::gl) gl_state: RefCell<GfxGlState>,
} }
impl Debug for RenderContext { impl Debug for GlRenderContext {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("RenderContext").finish_non_exhaustive() f.debug_struct("RenderContext").finish_non_exhaustive()
} }
} }
#[derive(Copy, Clone, Debug, Eq, PartialEq)] impl GlRenderContext {
pub enum ResetStatus {
Guilty,
Innocent,
Unknown,
Other(u32),
}
impl RenderContext {
pub fn reset_status(&self) -> Option<ResetStatus> { pub fn reset_status(&self) -> Option<ResetStatus> {
self.ctx.reset_status() self.ctx.reset_status()
} }
@ -93,7 +86,7 @@ impl RenderContext {
self.ctx.ext.contains(GlExt::GL_OES_EGL_IMAGE_EXTERNAL) self.ctx.ext.contains(GlExt::GL_OES_EGL_IMAGE_EXTERNAL)
} }
pub fn from_drm_device(drm: &Drm) -> Result<Self, RenderError> { pub(in crate::gfx_apis::gl) fn from_drm_device(drm: &Drm) -> Result<Self, RenderError> {
let nodes = drm.get_nodes()?; let nodes = drm.get_nodes()?;
let node = match nodes let node = match nodes
.get(&NodeType::Render) .get(&NodeType::Render)
@ -167,11 +160,11 @@ impl RenderContext {
self.render_node.clone() self.render_node.clone()
} }
pub fn formats(&self) -> Rc<AHashMap<u32, EglFormat>> { pub fn formats(&self) -> Rc<AHashMap<u32, GfxFormat>> {
self.ctx.dpy.formats.clone() self.ctx.dpy.formats.clone()
} }
pub fn dmabuf_fb(self: &Rc<Self>, buf: &DmaBuf) -> Result<Rc<Framebuffer>, RenderError> { fn dmabuf_fb(self: &Rc<Self>, buf: &DmaBuf) -> Result<Rc<Framebuffer>, RenderError> {
self.ctx.with_current(|| unsafe { self.ctx.with_current(|| unsafe {
let img = self.ctx.dpy.import_dmabuf(buf)?; let img = self.ctx.dpy.import_dmabuf(buf)?;
let rb = GlRenderBuffer::from_image(&img, &self.ctx)?; let rb = GlRenderBuffer::from_image(&img, &self.ctx)?;
@ -183,7 +176,7 @@ impl RenderContext {
}) })
} }
pub fn dmabuf_img(self: &Rc<Self>, buf: &DmaBuf) -> Result<Rc<Image>, RenderError> { fn dmabuf_img(self: &Rc<Self>, buf: &DmaBuf) -> Result<Rc<Image>, RenderError> {
self.ctx.with_current(|| { self.ctx.with_current(|| {
let img = self.ctx.dpy.import_dmabuf(buf)?; let img = self.ctx.dpy.import_dmabuf(buf)?;
Ok(Rc::new(Image { Ok(Rc::new(Image {
@ -193,7 +186,7 @@ impl RenderContext {
}) })
} }
pub fn shmem_texture( fn shmem_texture(
self: &Rc<Self>, self: &Rc<Self>,
data: &[Cell<u8>], data: &[Cell<u8>],
format: &'static Format, format: &'static Format,
@ -208,3 +201,57 @@ impl RenderContext {
})) }))
} }
} }
impl GfxContext for GlRenderContext {
fn take_render_ops(&self) -> Vec<GfxApiOpt> {
mem::take(&mut self.gfx_ops.borrow_mut())
}
fn reset_status(&self) -> Option<ResetStatus> {
self.reset_status()
}
fn supports_external_texture(&self) -> bool {
self.supports_external_texture()
}
fn render_node(&self) -> Rc<CString> {
self.render_node()
}
fn formats(&self) -> Rc<AHashMap<u32, GfxFormat>> {
self.formats()
}
fn dmabuf_fb(self: Rc<Self>, buf: &DmaBuf) -> Result<Rc<dyn GfxFramebuffer>, GfxError> {
(&self)
.dmabuf_fb(buf)
.map(|w| w as Rc<dyn GfxFramebuffer>)
.map_err(|e| e.into())
}
fn dmabuf_img(self: Rc<Self>, buf: &DmaBuf) -> Result<Rc<dyn GfxImage>, GfxError> {
(&self)
.dmabuf_img(buf)
.map(|w| w as Rc<dyn GfxImage>)
.map_err(|e| e.into())
}
fn shmem_texture(
self: Rc<Self>,
data: &[Cell<u8>],
format: &'static Format,
width: i32,
height: i32,
stride: i32,
) -> Result<Rc<dyn GfxTexture>, GfxError> {
(&self)
.shmem_texture(data, format, width, height, stride)
.map(|w| w as Rc<dyn GfxTexture>)
.map_err(|e| e.into())
}
fn gbm(&self) -> &GbmDevice {
&self.gbm
}
}

View file

@ -3,6 +3,7 @@ use {
cursor::Cursor, cursor::Cursor,
fixed::Fixed, fixed::Fixed,
format::{Format, ARGB8888, XRGB8888}, format::{Format, ARGB8888, XRGB8888},
gfx_api::{GfxFramebuffer, GfxTexture},
gfx_apis::gl::{ gfx_apis::gl::{
gl::{ gl::{
frame_buffer::GlFrameBuffer, frame_buffer::GlFrameBuffer,
@ -11,10 +12,9 @@ use {
GL_FRAMEBUFFER, GL_FRAMEBUFFER,
}, },
}, },
renderer::context::RenderContext, renderer::context::GlRenderContext,
run_ops, run_ops,
sys::{glBlendFunc, glFlush, glReadnPixels, GL_ONE, GL_ONE_MINUS_SRC_ALPHA}, sys::{glBlendFunc, glFlush, glReadnPixels, GL_ONE, GL_ONE_MINUS_SRC_ALPHA},
Texture,
}, },
rect::Rect, rect::Rect,
renderer::{renderer_base::RendererBase, RenderResult, Renderer}, renderer::{renderer_base::RendererBase, RenderResult, Renderer},
@ -23,6 +23,7 @@ use {
tree::Node, tree::Node,
}, },
std::{ std::{
any::Any,
cell::Cell, cell::Cell,
fmt::{Debug, Formatter}, fmt::{Debug, Formatter},
rc::Rc, rc::Rc,
@ -30,8 +31,8 @@ use {
}; };
pub struct Framebuffer { pub struct Framebuffer {
pub(crate) ctx: Rc<RenderContext>, pub(in crate::gfx_apis::gl) ctx: Rc<GlRenderContext>,
pub(crate) gl: GlFrameBuffer, pub(in crate::gfx_apis::gl) gl: GlFrameBuffer,
} }
impl Debug for Framebuffer { impl Debug for Framebuffer {
@ -57,7 +58,14 @@ impl Framebuffer {
}); });
} }
pub fn copy_texture(&self, state: &State, texture: &Rc<Texture>, x: i32, y: i32, alpha: bool) { pub fn copy_texture(
&self,
state: &State,
texture: &Rc<dyn GfxTexture>,
x: i32,
y: i32,
alpha: bool,
) {
let mut ops = self.ctx.gfx_ops.borrow_mut(); let mut ops = self.ctx.gfx_ops.borrow_mut();
ops.clear(); ops.clear();
let scale = Scale::from_int(1); 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(); let mut ops = self.ctx.gfx_ops.borrow_mut();
ops.clear(); ops.clear();
let mut renderer = RendererBase { 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<dyn GfxTexture>,
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<u8>],
) {
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<Rect>,
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)
}
}

View file

@ -1,15 +1,18 @@
use { use {
crate::gfx_apis::gl::{ crate::{
egl::image::EglImage, gfx_api::{GfxError, GfxFramebuffer, GfxImage, GfxTexture},
gl::{render_buffer::GlRenderBuffer, texture::GlTexture}, gfx_apis::gl::{
Framebuffer, RenderContext, RenderError, Texture, egl::image::EglImage,
gl::{render_buffer::GlRenderBuffer, texture::GlTexture},
Framebuffer, GlRenderContext, RenderError, Texture,
},
}, },
std::rc::Rc, std::rc::Rc,
}; };
pub struct Image { pub struct Image {
pub(crate) ctx: Rc<RenderContext>, pub(in crate::gfx_apis::gl) ctx: Rc<GlRenderContext>,
pub(crate) gl: Rc<EglImage>, pub(in crate::gfx_apis::gl) gl: Rc<EglImage>,
} }
impl Image { impl Image {
@ -21,14 +24,14 @@ impl Image {
self.gl.height self.gl.height
} }
pub fn to_texture(self: &Rc<Self>) -> Result<Rc<Texture>, RenderError> { fn to_texture(self: &Rc<Self>) -> Result<Rc<Texture>, RenderError> {
Ok(Rc::new(Texture { Ok(Rc::new(Texture {
ctx: self.ctx.clone(), ctx: self.ctx.clone(),
gl: GlTexture::import_img(&self.ctx.ctx, &self.gl)?, gl: GlTexture::import_img(&self.ctx.ctx, &self.gl)?,
})) }))
} }
pub fn to_framebuffer(&self) -> Result<Rc<Framebuffer>, RenderError> { fn to_framebuffer(&self) -> Result<Rc<Framebuffer>, RenderError> {
self.ctx.ctx.with_current(|| unsafe { self.ctx.ctx.with_current(|| unsafe {
let rb = GlRenderBuffer::from_image(&self.gl, &self.ctx.ctx)?; let rb = GlRenderBuffer::from_image(&self.gl, &self.ctx.ctx)?;
let fb = rb.create_framebuffer()?; let fb = rb.create_framebuffer()?;
@ -39,3 +42,27 @@ impl Image {
}) })
} }
} }
impl GfxImage for Image {
fn to_framebuffer(self: Rc<Self>) -> Result<Rc<dyn GfxFramebuffer>, GfxError> {
(*self)
.to_framebuffer()
.map(|v| v as Rc<dyn GfxFramebuffer>)
.map_err(|e| e.into())
}
fn to_texture(self: Rc<Self>) -> Result<Rc<dyn GfxTexture>, GfxError> {
(&self)
.to_texture()
.map(|v| v as Rc<dyn GfxTexture>)
.map_err(|e| e.into())
}
fn width(&self) -> i32 {
self.width()
}
fn height(&self) -> i32 {
self.height()
}
}

View file

@ -1,14 +1,18 @@
use { 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::{ std::{
any::Any,
fmt::{Debug, Formatter}, fmt::{Debug, Formatter},
rc::Rc, rc::Rc,
}, },
}; };
pub struct Texture { pub struct Texture {
pub(crate) ctx: Rc<RenderContext>, pub(in crate::gfx_apis::gl) ctx: Rc<GlRenderContext>,
pub(crate) gl: GlTexture, pub(in crate::gfx_apis::gl) gl: GlTexture,
} }
impl Debug for Texture { impl Debug for Texture {
@ -26,3 +30,17 @@ impl Texture {
self.gl.height 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
}
}

View file

@ -277,7 +277,7 @@ impl JayCompositor {
.render_ctx_watchers .render_ctx_watchers
.set((self.client.id, req.id), ctx.clone()); .set((self.client.id, req.id), ctx.clone());
let rctx = self.client.state.render_ctx.get(); let rctx = self.client.state.render_ctx.get();
ctx.send_render_ctx(rctx.as_ref()); ctx.send_render_ctx(rctx);
Ok(()) Ok(())
} }

View file

@ -1,7 +1,7 @@
use { use {
crate::{ crate::{
client::{Client, ClientError}, client::{Client, ClientError},
gfx_apis::gl::RenderContext, gfx_api::GfxContext,
leaks::Tracker, leaks::Tracker,
object::Object, object::Object,
utils::{ utils::{
@ -21,10 +21,10 @@ pub struct JayRenderCtx {
} }
impl JayRenderCtx { impl JayRenderCtx {
pub fn send_render_ctx(&self, ctx: Option<&Rc<RenderContext>>) { pub fn send_render_ctx(&self, ctx: Option<Rc<dyn GfxContext>>) {
let mut fd = None; let mut fd = None;
if let Some(ctx) = ctx { if let Some(ctx) = ctx {
match ctx.gbm.drm.dup_render() { match ctx.gbm().drm.dup_render() {
Ok(d) => fd = Some(d.fd().clone()), Ok(d) => fd = Some(d.fd().clone()),
Err(e) => { Err(e) => {
log::error!("Could not dup drm fd: {}", ErrorFmt(e)); log::error!("Could not dup drm fd: {}", ErrorFmt(e));

View file

@ -2,7 +2,7 @@ use {
crate::{ crate::{
client::{Client, ClientError}, client::{Client, ClientError},
format::XRGB8888, format::XRGB8888,
gfx_apis::gl::{Framebuffer, RenderContext, RenderError, Texture}, gfx_api::{GfxContext, GfxError, GfxFramebuffer, GfxTexture},
ifs::jay_output::JayOutput, ifs::jay_output::JayOutput,
leaks::Tracker, leaks::Tracker,
object::Object, object::Object,
@ -60,7 +60,7 @@ struct Pending {
struct ScreencastBuffer { struct ScreencastBuffer {
dmabuf: DmaBuf, dmabuf: DmaBuf,
fb: Rc<Framebuffer>, fb: Rc<dyn GfxFramebuffer>,
free: bool, free: bool,
} }
@ -147,7 +147,7 @@ impl JayScreencast {
}); });
} }
pub fn copy_texture(&self, on: &OutputNode, texture: &Rc<Texture>) { pub fn copy_texture(&self, on: &OutputNode, texture: &Rc<dyn GfxTexture>) {
if !self.running.get() { if !self.running.get() {
return; return;
} }
@ -193,7 +193,7 @@ impl JayScreencast {
self.client.event(Destroyed { self_id: self.id }); self.client.event(Destroyed { self_id: self.id });
} }
pub fn realloc(&self, ctx: &Rc<RenderContext>) -> Result<(), JayScreencastError> { pub fn realloc(&self, ctx: &Rc<dyn GfxContext>) -> Result<(), JayScreencastError> {
let mut buffers = vec![]; let mut buffers = vec![];
if let Some(output) = self.output.get() { if let Some(output) = self.output.get() {
let mode = output.global.mode.get(); let mode = output.global.mode.get();
@ -207,8 +207,10 @@ impl JayScreencast {
if self.linear.get() { if self.linear.get() {
flags |= GBM_BO_USE_LINEAR; flags |= GBM_BO_USE_LINEAR;
} }
let buffer = ctx.gbm.create_bo(mode.width, mode.height, &format, flags)?; let buffer = ctx
let fb = ctx.dmabuf_img(buffer.dmabuf())?.to_framebuffer()?; .gbm()
.create_bo(mode.width, mode.height, &format, flags)?;
let fb = ctx.clone().dmabuf_img(buffer.dmabuf())?.to_framebuffer()?;
buffers.push(ScreencastBuffer { buffers.push(ScreencastBuffer {
dmabuf: buffer.dmabuf().clone(), dmabuf: buffer.dmabuf().clone(),
fb, fb,
@ -444,7 +446,7 @@ pub enum JayScreencastError {
#[error(transparent)] #[error(transparent)]
GbmError(#[from] GbmError), GbmError(#[from] GbmError),
#[error(transparent)] #[error(transparent)]
RenderError(#[from] RenderError), GfxError(#[from] GfxError),
} }
efrom!(JayScreencastError, MsgParserError); efrom!(JayScreencastError, MsgParserError);
efrom!(JayScreencastError, ClientError); efrom!(JayScreencastError, ClientError);

View file

@ -3,7 +3,7 @@ use {
client::{Client, ClientError}, client::{Client, ClientError},
clientmem::{ClientMem, ClientMemError, ClientMemOffset}, clientmem::{ClientMem, ClientMemError, ClientMemOffset},
format::Format, format::Format,
gfx_apis::gl::{Framebuffer, Image, RenderError, Texture}, gfx_api::{GfxError, GfxFramebuffer, GfxImage, GfxTexture},
leaks::Tracker, leaks::Tracker,
object::Object, object::Object,
rect::Rect, rect::Rect,
@ -25,7 +25,7 @@ use {
pub enum WlBufferStorage { pub enum WlBufferStorage {
Shm { mem: ClientMemOffset, stride: i32 }, Shm { mem: ClientMemOffset, stride: i32 },
Dmabuf(Rc<Image>), Dmabuf(Rc<dyn GfxImage>),
} }
pub struct WlBuffer { pub struct WlBuffer {
@ -37,8 +37,8 @@ pub struct WlBuffer {
dmabuf: Option<DmaBuf>, dmabuf: Option<DmaBuf>,
render_ctx_version: Cell<u32>, render_ctx_version: Cell<u32>,
pub storage: RefCell<Option<WlBufferStorage>>, pub storage: RefCell<Option<WlBufferStorage>>,
pub texture: CloneCell<Option<Rc<Texture>>>, pub texture: CloneCell<Option<Rc<dyn GfxTexture>>>,
pub famebuffer: CloneCell<Option<Rc<Framebuffer>>>, pub famebuffer: CloneCell<Option<Rc<dyn GfxFramebuffer>>>,
width: i32, width: i32,
height: i32, height: i32,
pub tracker: Tracker<Self>, pub tracker: Tracker<Self>,
@ -55,7 +55,7 @@ impl WlBuffer {
client: &Rc<Client>, client: &Rc<Client>,
format: &'static Format, format: &'static Format,
dmabuf: DmaBuf, dmabuf: DmaBuf,
img: &Rc<Image>, img: &Rc<dyn GfxImage>,
) -> Self { ) -> Self {
let width = img.width(); let width = img.width();
let height = img.height(); let height = img.height();
@ -165,7 +165,7 @@ impl WlBuffer {
} }
WlBufferStorage::Dmabuf(img) => { WlBufferStorage::Dmabuf(img) => {
if self.texture.get().is_none() { 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) => { WlBufferStorage::Dmabuf(img) => {
if self.famebuffer.get().is_none() { 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, StrideTooSmall,
#[error("Could not access the client memory")] #[error("Could not access the client memory")]
ClientMemError(#[source] Box<ClientMemError>), ClientMemError(#[source] Box<ClientMemError>),
#[error("GLES could not import the client image")] #[error("The graphics library could not import the client image")]
RenderError(#[source] Box<RenderError>), GfxError(#[from] GfxError),
#[error("Parsing failed")] #[error("Parsing failed")]
MsgParserError(#[source] Box<MsgParserError>), MsgParserError(#[source] Box<MsgParserError>),
#[error(transparent)] #[error(transparent)]
ClientError(Box<ClientError>), ClientError(Box<ClientError>),
} }
efrom!(WlBufferError, ClientMemError); efrom!(WlBufferError, ClientMemError);
efrom!(WlBufferError, RenderError);
efrom!(WlBufferError, MsgParserError); efrom!(WlBufferError, MsgParserError);
efrom!(WlBufferError, ClientError); efrom!(WlBufferError, ClientError);

View file

@ -1,7 +1,7 @@
use { use {
crate::{ crate::{
client::{Client, ClientError}, client::{Client, ClientError},
gfx_apis::gl::RenderError, gfx_api::GfxError,
globals::{Global, GlobalName}, globals::{Global, GlobalName},
ifs::wl_buffer::WlBuffer, ifs::wl_buffer::WlBuffer,
leaks::Tracker, leaks::Tracker,
@ -190,7 +190,7 @@ pub enum WlDrmError {
#[error("The format {0} is not supported")] #[error("The format {0} is not supported")]
InvalidFormat(u32), InvalidFormat(u32),
#[error("Could not import the buffer")] #[error("Could not import the buffer")]
ImportError(#[from] RenderError), ImportError(#[from] GfxError),
} }
efrom!(WlDrmError, ClientError); efrom!(WlDrmError, ClientError);
efrom!(WlDrmError, MsgParserError); efrom!(WlDrmError, MsgParserError);

View file

@ -3,7 +3,7 @@ use {
backend, backend,
client::{Client, ClientError, ClientId}, client::{Client, ClientError, ClientId},
format::XRGB8888, format::XRGB8888,
gfx_apis::gl::{Framebuffer, Texture}, gfx_api::{GfxFramebuffer, GfxTexture},
globals::{Global, GlobalName}, globals::{Global, GlobalName},
ifs::{ ifs::{
wl_buffer::WlBufferStorage, wl_surface::WlSurface, wl_buffer::WlBufferStorage, wl_surface::WlSurface,
@ -199,7 +199,7 @@ impl WlOutputGlobal {
Ok(()) Ok(())
} }
pub fn perform_screencopies(&self, fb: &Framebuffer, tex: &Rc<Texture>) { pub fn perform_screencopies(&self, fb: &dyn GfxFramebuffer, tex: &Rc<dyn GfxTexture>) {
if self.pending_captures.is_empty() { if self.pending_captures.is_empty() {
return; return;
} }

View file

@ -1,7 +1,7 @@
use { use {
crate::{ crate::{
client::ClientError, client::ClientError,
gfx_apis::gl::RenderError, gfx_api::GfxError,
ifs::{wl_buffer::WlBuffer, zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1}, ifs::{wl_buffer::WlBuffer, zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1},
leaks::Tracker, leaks::Tracker,
object::Object, object::Object,
@ -228,7 +228,7 @@ pub enum ZwpLinuxBufferParamsV1Error {
#[error("Plane {0} was not set")] #[error("Plane {0} was not set")]
MissingPlane(usize), MissingPlane(usize),
#[error("Could not import the buffer")] #[error("Could not import the buffer")]
ImportError(#[from] RenderError), ImportError(#[from] GfxError),
} }
efrom!(ZwpLinuxBufferParamsV1Error, ClientError); efrom!(ZwpLinuxBufferParamsV1Error, ClientError);
efrom!(ZwpLinuxBufferParamsV1Error, MsgParserError); efrom!(ZwpLinuxBufferParamsV1Error, MsgParserError);

View file

@ -9,7 +9,8 @@ use {
}, },
compositor::TestFuture, compositor::TestFuture,
fixed::Fixed, fixed::Fixed,
gfx_apis::gl::{RenderContext, RenderError}, gfx_api::GfxError,
gfx_apis::create_gfx_context,
it::test_error::TestResult, it::test_error::TestResult,
state::State, state::State,
time::now_usec, time::now_usec,
@ -33,7 +34,7 @@ pub enum TestBackendError {
#[error("Could not open drm node {0}")] #[error("Could not open drm node {0}")]
OpenDrmNode(String, #[source] OsError), OpenDrmNode(String, #[source] OsError),
#[error("Could not create a render context")] #[error("Could not create a render context")]
RenderContext(#[source] RenderError), RenderContext(#[source] GfxError),
} }
pub struct TestBackend { pub struct TestBackend {
@ -177,11 +178,11 @@ impl TestBackend {
} }
}; };
let drm = Drm::open_existing(file); let drm = Drm::open_existing(file);
let ctx = match RenderContext::from_drm_device(&drm) { let ctx = match create_gfx_context(&drm) {
Ok(ctx) => ctx, Ok(ctx) => ctx,
Err(e) => return Err(TestBackendError::RenderContext(e)), Err(e) => return Err(TestBackendError::RenderContext(e)),
}; };
self.state.set_render_ctx(Some(&Rc::new(ctx))); self.state.set_render_ctx(Some(ctx));
Ok(()) Ok(())
} }
} }

View file

@ -1,6 +1,6 @@
use { use {
crate::{ crate::{
gfx_apis::gl::RenderContext, gfx_apis::create_gfx_context,
ifs::wl_seat::POINTER, ifs::wl_seat::POINTER,
portal::{ portal::{
ptl_render_ctx::PortalRenderCtx, ptl_screencast::ScreencastSession, ptl_render_ctx::PortalRenderCtx, ptl_screencast::ScreencastSession,
@ -169,7 +169,7 @@ impl UsrJayRenderCtxOwner for PortalDisplay {
} }
if self.render_ctx.get().is_none() { if self.render_ctx.get().is_none() {
let drm = Drm::open_existing(fd); let drm = Drm::open_existing(fd);
let ctx = match RenderContext::from_drm_device(&drm) { let ctx = match create_gfx_context(&drm) {
Ok(c) => c, Ok(c) => c,
Err(e) => { Err(e) => {
log::error!( log::error!(
@ -179,10 +179,7 @@ impl UsrJayRenderCtxOwner for PortalDisplay {
return; return;
} }
}; };
let ctx = Rc::new(PortalRenderCtx { let ctx = Rc::new(PortalRenderCtx { dev_id, ctx });
dev_id,
ctx: Rc::new(ctx),
});
self.render_ctx.set(Some(ctx.clone())); self.render_ctx.set(Some(ctx.clone()));
self.state.render_ctxs.set(dev_id, Rc::downgrade(&ctx)); self.state.render_ctxs.set(dev_id, Rc::downgrade(&ctx));
} }

View file

@ -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 struct PortalRenderCtx {
pub dev_id: c::dev_t, pub dev_id: c::dev_t,
pub ctx: Rc<RenderContext>, pub ctx: Rc<dyn GfxContext>,
} }

View file

@ -4,7 +4,7 @@ use {
cursor::KnownCursor, cursor::KnownCursor,
fixed::Fixed, fixed::Fixed,
format::ARGB8888, format::ARGB8888,
gfx_apis::gl::{Framebuffer, RenderContext, Texture}, gfx_api::{GfxContext, GfxFramebuffer, GfxTexture},
ifs::zwlr_layer_shell_v1::OVERLAY, ifs::zwlr_layer_shell_v1::OVERLAY,
portal::ptl_display::{PortalDisplay, PortalOutput, PortalSeat}, portal::ptl_display::{PortalDisplay, PortalOutput, PortalSeat},
renderer::renderer_base::RendererBase, renderer::renderer_base::RendererBase,
@ -50,7 +50,7 @@ pub trait GuiElement {
fn data(&self) -> &GuiElementData; fn data(&self) -> &GuiElementData;
fn layout( fn layout(
&self, &self,
ctx: &Rc<RenderContext>, ctx: &Rc<dyn GfxContext>,
scale: f32, scale: f32,
max_width: f32, max_width: f32,
max_height: f32, max_height: f32,
@ -118,7 +118,7 @@ pub struct Button {
pub bg_hover_color: Cell<Color>, pub bg_hover_color: Cell<Color>,
pub text: RefCell<String>, pub text: RefCell<String>,
pub font: RefCell<Cow<'static, str>>, pub font: RefCell<Cow<'static, str>>,
pub tex: CloneCell<Option<Rc<Texture>>>, pub tex: CloneCell<Option<Rc<dyn GfxTexture>>>,
pub owner: CloneCell<Option<Rc<dyn ButtonOwner>>>, pub owner: CloneCell<Option<Rc<dyn ButtonOwner>>>,
} }
@ -157,7 +157,7 @@ impl GuiElement for Button {
fn layout( fn layout(
&self, &self,
ctx: &Rc<RenderContext>, ctx: &Rc<dyn GfxContext>,
scale: f32, scale: f32,
_max_width: f32, _max_width: f32,
_max_height: f32, _max_height: f32,
@ -260,7 +260,7 @@ pub struct Label {
pub data: GuiElementData, pub data: GuiElementData,
pub font: RefCell<Cow<'static, str>>, pub font: RefCell<Cow<'static, str>>,
pub text: RefCell<String>, pub text: RefCell<String>,
pub tex: CloneCell<Option<Rc<Texture>>>, pub tex: CloneCell<Option<Rc<dyn GfxTexture>>>,
} }
impl Default for Label { impl Default for Label {
@ -281,7 +281,7 @@ impl GuiElement for Label {
fn layout( fn layout(
&self, &self,
ctx: &Rc<RenderContext>, ctx: &Rc<dyn GfxContext>,
scale: f32, scale: f32,
_max_width: f32, _max_width: f32,
_max_height: f32, _max_height: f32,
@ -364,7 +364,7 @@ impl GuiElement for Flow {
fn layout( fn layout(
&self, &self,
ctx: &Rc<RenderContext>, ctx: &Rc<dyn GfxContext>,
scale: f32, scale: f32,
max_width: f32, max_width: f32,
max_height: f32, max_height: f32,
@ -638,7 +638,7 @@ impl WindowData {
self.have_frame.set(false); self.have_frame.set(false);
buf.free.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)); r.clear(&Color::from_gray(0));
if let Some(content) = self.content.get() { if let Some(content) = self.content.get() {
content.render_at(r, 0.0, 0.0) content.render_at(r, 0.0, 0.0)
@ -700,7 +700,7 @@ impl WindowData {
}; };
let bo = match ctx let bo = match ctx
.ctx .ctx
.gbm .gbm()
.create_bo(width, height, &format, GBM_BO_USE_RENDERING) .create_bo(width, height, &format, GBM_BO_USE_RENDERING)
{ {
Ok(b) => b, Ok(b) => b,
@ -709,7 +709,7 @@ impl WindowData {
return; return;
} }
}; };
let img = match ctx.ctx.dmabuf_img(bo.dmabuf()) { let img = match ctx.ctx.clone().dmabuf_img(bo.dmabuf()) {
Ok(b) => b, Ok(b) => b,
Err(e) => { Err(e) => {
log::error!("Could not import dmabuf into EGL: {}", ErrorFmt(e)); log::error!("Could not import dmabuf into EGL: {}", ErrorFmt(e));
@ -814,14 +814,14 @@ impl WindowData {
pub struct GuiBuffer { pub struct GuiBuffer {
pub wl: Rc<UsrWlBuffer>, pub wl: Rc<UsrWlBuffer>,
pub window: Rc<WindowData>, pub window: Rc<WindowData>,
pub fb: Rc<Framebuffer>, pub fb: Rc<dyn GfxFramebuffer>,
pub free: Cell<bool>, pub free: Cell<bool>,
pub size: (i32, i32), pub size: (i32, i32),
} }
struct GuiBufferPending { struct GuiBufferPending {
pub window: Rc<WindowData>, pub window: Rc<WindowData>,
pub fb: Rc<Framebuffer>, pub fb: Rc<dyn GfxFramebuffer>,
pub params: Rc<UsrLinuxBufferParams>, pub params: Rc<UsrLinuxBufferParams>,
pub size: (i32, i32), pub size: (i32, i32),
} }

View file

@ -3,8 +3,8 @@ use {
format::Format, format::Format,
gfx_api::{ gfx_api::{
AbsoluteRect, BufferPoint, BufferPoints, Clear, CopyTexture, FillRect, GfxApiOpt, AbsoluteRect, BufferPoint, BufferPoints, Clear, CopyTexture, FillRect, GfxApiOpt,
GfxTexture,
}, },
gfx_apis::gl::Texture,
rect::Rect, rect::Rect,
scale::Scale, scale::Scale,
theme::Color, theme::Color,
@ -120,7 +120,7 @@ impl RendererBase<'_> {
pub fn render_texture( pub fn render_texture(
&mut self, &mut self,
texture: &Rc<Texture>, texture: &Rc<dyn GfxTexture>,
x: i32, x: i32,
y: i32, y: i32,
format: &'static Format, format: &'static Format,

View file

@ -1,7 +1,7 @@
use { use {
crate::{ crate::{
format::XRGB8888, format::XRGB8888,
gfx_apis::gl::RenderError, gfx_api::GfxError,
scale::Scale, scale::Scale,
state::State, state::State,
video::{ video::{
@ -24,7 +24,7 @@ pub enum ScreenshooterError {
#[error(transparent)] #[error(transparent)]
GbmError(#[from] GbmError), GbmError(#[from] GbmError),
#[error(transparent)] #[error(transparent)]
RenderError(#[from] RenderError), RenderError(#[from] GfxError),
#[error(transparent)] #[error(transparent)]
DrmError(#[from] DrmError), DrmError(#[from] DrmError),
} }
@ -47,13 +47,14 @@ pub fn take_screenshot(state: &State) -> Result<Screenshot, ScreenshooterError>
format: XRGB8888, format: XRGB8888,
modifier: INVALID_MODIFIER, modifier: INVALID_MODIFIER,
}; };
let bo = ctx.gbm.create_bo( let gbm = ctx.gbm();
let bo = gbm.create_bo(
extents.width(), extents.width(),
extents.height(), extents.height(),
&format, &format,
GBM_BO_USE_RENDERING | GBM_BO_USE_LINEAR, 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( fb.render(
state.root.deref(), state.root.deref(),
state, state,
@ -63,6 +64,6 @@ pub fn take_screenshot(state: &State) -> Result<Screenshot, ScreenshooterError>
Scale::from_int(1), Scale::from_int(1),
true, true,
); );
let drm = ctx.gbm.drm.dup_render()?.fd().clone(); let drm = gbm.drm.dup_render()?.fd().clone();
Ok(Screenshot { drm, bo }) Ok(Screenshot { drm, bo })
} }

View file

@ -13,7 +13,7 @@ use {
cursor::{Cursor, ServerCursors}, cursor::{Cursor, ServerCursors},
dbus::Dbus, dbus::Dbus,
forker::ForkerProxy, forker::ForkerProxy,
gfx_apis::gl::RenderContext, gfx_api::GfxContext,
globals::{Globals, GlobalsError, WaylandGlobal}, globals::{Globals, GlobalsError, WaylandGlobal},
ifs::{ ifs::{
ext_session_lock_v1::ExtSessionLockV1, ext_session_lock_v1::ExtSessionLockV1,
@ -69,7 +69,7 @@ pub struct State {
pub forker: CloneCell<Option<Rc<ForkerProxy>>>, pub forker: CloneCell<Option<Rc<ForkerProxy>>>,
pub default_keymap: Rc<XkbKeymap>, pub default_keymap: Rc<XkbKeymap>,
pub eng: Rc<AsyncEngine>, pub eng: Rc<AsyncEngine>,
pub render_ctx: CloneCell<Option<Rc<RenderContext>>>, pub render_ctx: CloneCell<Option<Rc<dyn GfxContext>>>,
pub render_ctx_version: NumCell<u32>, pub render_ctx_version: NumCell<u32>,
pub render_ctx_ever_initialized: Cell<bool>, pub render_ctx_ever_initialized: Cell<bool>,
pub cursors: CloneCell<Option<Rc<ServerCursors>>>, pub cursors: CloneCell<Option<Rc<ServerCursors>>>,
@ -305,8 +305,8 @@ impl State {
} }
} }
pub fn set_render_ctx(&self, ctx: Option<&Rc<RenderContext>>) { pub fn set_render_ctx(&self, ctx: Option<Rc<dyn GfxContext>>) {
self.render_ctx.set(ctx.cloned()); self.render_ctx.set(ctx.clone());
self.render_ctx_version.fetch_add(1); self.render_ctx_version.fetch_add(1);
self.cursors.set(None); self.cursors.set(None);
@ -364,7 +364,7 @@ impl State {
} }
for watcher in self.render_ctx_watchers.lock().values() { for watcher in self.render_ctx_watchers.lock().values() {
watcher.send_render_ctx(ctx); watcher.send_render_ctx(ctx.clone());
} }
let mut scs = vec![]; let mut scs = vec![];

View file

@ -1,7 +1,7 @@
use { use {
crate::{ crate::{
format::ARGB8888, format::ARGB8888,
gfx_apis::gl::{RenderContext, RenderError, Texture}, gfx_api::{GfxContext, GfxError, GfxTexture},
pango::{ pango::{
consts::{ consts::{
CAIRO_FORMAT_ARGB32, CAIRO_OPERATOR_SOURCE, PANGO_ELLIPSIZE_END, PANGO_SCALE, 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")] #[error("Could not create a pango layout")]
CreateLayout(#[source] PangoError), CreateLayout(#[source] PangoError),
#[error("Could not import the rendered text")] #[error("Could not import the rendered text")]
RenderError(#[source] RenderError), RenderError(#[source] GfxError),
#[error("Could not access the cairo image data")] #[error("Could not access the cairo image data")]
ImageData(#[source] PangoError), ImageData(#[source] PangoError),
} }
@ -94,21 +94,21 @@ pub fn measure(
} }
pub fn render( pub fn render(
ctx: &Rc<RenderContext>, ctx: &Rc<dyn GfxContext>,
width: i32, width: i32,
height: i32, height: i32,
font: &str, font: &str,
text: &str, text: &str,
color: Color, color: Color,
scale: Option<f64>, scale: Option<f64>,
) -> Result<Rc<Texture>, TextError> { ) -> Result<Rc<dyn GfxTexture>, TextError> {
render2( render2(
ctx, 1, None, width, height, 1, font, text, color, true, false, scale, ctx, 1, None, width, height, 1, font, text, color, true, false, scale,
) )
} }
fn render2( fn render2(
ctx: &Rc<RenderContext>, ctx: &Rc<dyn GfxContext>,
x: i32, x: i32,
y: Option<i32>, y: Option<i32>,
width: i32, width: i32,
@ -120,7 +120,7 @@ fn render2(
ellipsize: bool, ellipsize: bool,
markup: bool, markup: bool,
scale: Option<f64>, scale: Option<f64>,
) -> Result<Rc<Texture>, TextError> { ) -> Result<Rc<dyn GfxTexture>, TextError> {
let data = create_data(font, width, height, scale)?; let data = create_data(font, width, height, scale)?;
if ellipsize { if ellipsize {
data.layout data.layout
@ -144,21 +144,24 @@ fn render2(
Ok(d) => d, Ok(d) => d,
Err(e) => return Err(TextError::ImageData(e)), 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), Ok(t) => Ok(t),
Err(e) => Err(TextError::RenderError(e)), Err(e) => Err(TextError::RenderError(e)),
} }
} }
pub fn render_fitting( pub fn render_fitting(
ctx: &Rc<RenderContext>, ctx: &Rc<dyn GfxContext>,
height: Option<i32>, height: Option<i32>,
font: &str, font: &str,
text: &str, text: &str,
color: Color, color: Color,
markup: bool, markup: bool,
scale: Option<f64>, scale: Option<f64>,
) -> Result<Rc<Texture>, TextError> { ) -> Result<Rc<dyn GfxTexture>, TextError> {
render_fitting2(ctx, height, font, text, color, markup, scale, false).map(|(a, _)| a) render_fitting2(ctx, height, font, text, color, markup, scale, false).map(|(a, _)| a)
} }
@ -170,7 +173,7 @@ pub struct TextMeasurement {
} }
pub fn render_fitting2( pub fn render_fitting2(
ctx: &Rc<RenderContext>, ctx: &Rc<dyn GfxContext>,
height: Option<i32>, height: Option<i32>,
font: &str, font: &str,
text: &str, text: &str,
@ -178,7 +181,7 @@ pub fn render_fitting2(
markup: bool, markup: bool,
scale: Option<f64>, scale: Option<f64>,
include_measurements: bool, include_measurements: bool,
) -> Result<(Rc<Texture>, TextMeasurement), TextError> { ) -> Result<(Rc<dyn GfxTexture>, TextMeasurement), TextError> {
let measurement = measure(font, text, markup, scale, include_measurements)?; let measurement = measure(font, text, markup, scale, include_measurements)?;
let y = match height { let y = match height {
Some(_) => None, Some(_) => None,

View file

@ -3,7 +3,7 @@ use {
backend::KeyState, backend::KeyState,
cursor::KnownCursor, cursor::KnownCursor,
fixed::Fixed, fixed::Fixed,
gfx_apis::gl::Texture, gfx_api::GfxTexture,
ifs::wl_seat::{ ifs::wl_seat::{
collect_kb_foci, collect_kb_foci2, wl_pointer::PendingScroll, NodeSeatState, SeatId, collect_kb_foci, collect_kb_foci2, wl_pointer::PendingScroll, NodeSeatState, SeatId,
WlSeatGlobal, BTN_LEFT, WlSeatGlobal, BTN_LEFT,
@ -77,7 +77,7 @@ tree_id!(ContainerNodeId);
pub struct ContainerTitle { pub struct ContainerTitle {
pub x: i32, pub x: i32,
pub y: i32, pub y: i32,
pub tex: Rc<Texture>, pub tex: Rc<dyn GfxTexture>,
} }
#[derive(Default)] #[derive(Default)]

View file

@ -3,7 +3,7 @@ use {
backend::KeyState, backend::KeyState,
cursor::KnownCursor, cursor::KnownCursor,
fixed::Fixed, fixed::Fixed,
gfx_apis::gl::Texture, gfx_api::GfxTexture,
ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal, BTN_LEFT}, ifs::wl_seat::{NodeSeatState, SeatId, WlSeatGlobal, BTN_LEFT},
rect::Rect, rect::Rect,
renderer::Renderer, renderer::Renderer,
@ -44,7 +44,7 @@ pub struct FloatNode {
pub layout_scheduled: Cell<bool>, pub layout_scheduled: Cell<bool>,
pub render_titles_scheduled: Cell<bool>, pub render_titles_scheduled: Cell<bool>,
pub title: RefCell<String>, pub title: RefCell<String>,
pub title_textures: CopyHashMap<Scale, Rc<Texture>>, pub title_textures: CopyHashMap<Scale, Rc<dyn GfxTexture>>,
seats: RefCell<AHashMap<SeatId, SeatState>>, seats: RefCell<AHashMap<SeatId, SeatState>>,
} }

View file

@ -4,7 +4,7 @@ use {
client::ClientId, client::ClientId,
cursor::KnownCursor, cursor::KnownCursor,
fixed::Fixed, fixed::Fixed,
gfx_apis::gl::{Framebuffer, Texture}, gfx_api::{GfxFramebuffer, GfxTexture},
ifs::{ ifs::{
jay_output::JayOutput, jay_output::JayOutput,
jay_screencast::JayScreencast, jay_screencast::JayScreencast,
@ -78,7 +78,7 @@ pub async fn output_render_data(state: Rc<State>) {
} }
impl OutputNode { impl OutputNode {
pub fn perform_screencopies(&self, fb: &Framebuffer, tex: &Rc<Texture>) { pub fn perform_screencopies(&self, fb: &dyn GfxFramebuffer, tex: &Rc<dyn GfxTexture>) {
if let Some(workspace) = self.workspace.get() { if let Some(workspace) = self.workspace.get() {
if !workspace.capture.get() { if !workspace.capture.get() {
return; return;
@ -465,14 +465,14 @@ pub struct OutputTitle {
pub x2: i32, pub x2: i32,
pub tex_x: i32, pub tex_x: i32,
pub tex_y: i32, pub tex_y: i32,
pub tex: Rc<Texture>, pub tex: Rc<dyn GfxTexture>,
pub ws: Rc<WorkspaceNode>, pub ws: Rc<WorkspaceNode>,
} }
pub struct OutputStatus { pub struct OutputStatus {
pub tex_x: i32, pub tex_x: i32,
pub tex_y: i32, pub tex_y: i32,
pub tex: Rc<Texture>, pub tex: Rc<dyn GfxTexture>,
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]

View file

@ -3,7 +3,7 @@ use {
client::Client, client::Client,
cursor::KnownCursor, cursor::KnownCursor,
fixed::Fixed, fixed::Fixed,
gfx_apis::gl::Texture, gfx_api::GfxTexture,
ifs::wl_seat::{NodeSeatState, WlSeatGlobal}, ifs::wl_seat::{NodeSeatState, WlSeatGlobal},
rect::Rect, rect::Rect,
renderer::Renderer, renderer::Renderer,
@ -25,7 +25,7 @@ pub struct PlaceholderNode {
id: PlaceholderNodeId, id: PlaceholderNodeId,
toplevel: ToplevelData, toplevel: ToplevelData,
destroyed: Cell<bool>, destroyed: Cell<bool>,
pub textures: SmallMap<Scale, Rc<Texture>, 2>, pub textures: SmallMap<Scale, Rc<dyn GfxTexture>, 2>,
} }
impl PlaceholderNode { impl PlaceholderNode {