Skip to content

Commit

Permalink
backend: add auto renderer
Browse files Browse the repository at this point in the history
  • Loading branch information
cmeissl committed Mar 2, 2025
1 parent 31e4d48 commit 974143e
Show file tree
Hide file tree
Showing 14 changed files with 1,270 additions and 1 deletion.
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ pkg-config = { version = "0.3.17", optional = true }
cc = { version = "1.0.79", optional = true }

[features]
default = ["backend_drm", "backend_gbm", "backend_libinput", "backend_udev", "backend_session_libseat", "backend_x11", "backend_winit", "desktop", "renderer_gl", "renderer_pixman", "renderer_multi", "xwayland", "wayland_frontend", "backend_vulkan"]
default = ["backend_drm", "backend_gbm", "backend_libinput", "backend_udev", "backend_session_libseat", "backend_x11", "backend_winit", "desktop", "renderer_gl", "renderer_pixman", "renderer_auto", "renderer_multi", "xwayland", "wayland_frontend", "backend_vulkan"]
backend_winit = ["winit", "backend_egl", "wayland-client", "wayland-cursor", "wayland-egl", "renderer_gl"]
backend_x11 = ["x11rb", "x11rb/dri3", "x11rb/xfixes", "x11rb/xinput", "x11rb/present", "x11rb_event_source", "backend_gbm", "backend_drm", "backend_egl"]
backend_drm = ["drm", "drm-ffi"]
Expand All @@ -102,6 +102,7 @@ renderer_gl = ["gl_generator", "backend_egl"]
renderer_glow = ["renderer_gl", "glow"]
renderer_multi = ["backend_drm", "aliasable"]
renderer_pixman = ["pixman"]
renderer_auto = []
renderer_test = []
use_system_lib = ["wayland_frontend", "wayland-backend/server_system", "wayland-sys", "gbm?/import-wayland"]
use_bindgen = ["drm-ffi/use_bindgen", "gbm/use_bindgen", "input/use_bindgen"]
Expand Down
118 changes: 118 additions & 0 deletions src/backend/renderer/auto/bind.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
use crate::backend::{
allocator::{dmabuf::Dmabuf, format::FormatSet},
renderer::Bind,
};

#[cfg(feature = "renderer_gl")]
use crate::backend::{
egl::EGLSurface,
renderer::gles::{GlesRenderbuffer, GlesTexture},
};

#[cfg(feature = "renderer_pixman")]
use pixman::Image;

use super::{AutoRenderer, AutoRendererError, AutoRendererTarget};

impl Bind<Dmabuf> for AutoRenderer {
fn bind<'a>(&mut self, target: &'a mut Dmabuf) -> Result<Self::Framebuffer<'a>, Self::Error> {
match self {
#[cfg(feature = "renderer_gl")]
AutoRenderer::Gles(renderer) => Bind::<Dmabuf>::bind(renderer, target)
.map(AutoRendererTarget::from)
.map_err(AutoRendererError::from),
#[cfg(feature = "renderer_pixman")]
AutoRenderer::Pixman(renderer) => Bind::<Dmabuf>::bind(renderer, target)
.map(AutoRendererTarget::from)
.map_err(AutoRendererError::from),
}
}

fn supported_formats(&self) -> Option<FormatSet> {
match self {
#[cfg(feature = "renderer_gl")]
AutoRenderer::Gles(renderer) => Bind::<Dmabuf>::supported_formats(renderer),
#[cfg(feature = "renderer_pixman")]
AutoRenderer::Pixman(renderer) => Bind::<Dmabuf>::supported_formats(renderer),
}
}
}

#[cfg(feature = "renderer_gl")]
impl Bind<EGLSurface> for AutoRenderer {
fn bind<'a>(&mut self, target: &'a mut EGLSurface) -> Result<Self::Framebuffer<'a>, Self::Error> {
let AutoRenderer::Gles(renderer) = self else {
return Err(AutoRendererError::Unsupported);
};
Bind::<EGLSurface>::bind(renderer, target)
.map(AutoRendererTarget::from)
.map_err(AutoRendererError::from)
}

fn supported_formats(&self) -> Option<FormatSet> {
let AutoRenderer::Gles(renderer) = self else {
return None;
};
Bind::<Dmabuf>::supported_formats(renderer)
}
}

#[cfg(feature = "renderer_gl")]
impl Bind<GlesTexture> for AutoRenderer {
fn bind<'a>(&mut self, target: &'a mut GlesTexture) -> Result<Self::Framebuffer<'a>, Self::Error> {
let AutoRenderer::Gles(renderer) = self else {
return Err(AutoRendererError::Unsupported);
};
Bind::<GlesTexture>::bind(renderer, target)
.map(AutoRendererTarget::from)
.map_err(AutoRendererError::from)
}

fn supported_formats(&self) -> Option<FormatSet> {
let AutoRenderer::Gles(renderer) = self else {
return None;
};
Bind::<GlesTexture>::supported_formats(renderer)
}
}

#[cfg(feature = "renderer_gl")]
impl Bind<GlesRenderbuffer> for AutoRenderer {
fn bind<'a>(&mut self, target: &'a mut GlesRenderbuffer) -> Result<Self::Framebuffer<'a>, Self::Error> {
let AutoRenderer::Gles(renderer) = self else {
return Err(AutoRendererError::Unsupported);
};
Bind::<GlesRenderbuffer>::bind(renderer, target)
.map(AutoRendererTarget::from)
.map_err(AutoRendererError::from)
}

fn supported_formats(&self) -> Option<FormatSet> {
let AutoRenderer::Gles(renderer) = self else {
return None;
};
Bind::<GlesRenderbuffer>::supported_formats(renderer)
}
}

#[cfg(feature = "renderer_gl")]
impl Bind<Image<'static, 'static>> for AutoRenderer {
fn bind<'a>(
&mut self,
target: &'a mut Image<'static, 'static>,
) -> Result<Self::Framebuffer<'a>, Self::Error> {
let AutoRenderer::Pixman(renderer) = self else {
return Err(AutoRendererError::Unsupported);
};
Bind::<Image<'static, 'static>>::bind(renderer, target)
.map(AutoRendererTarget::from)
.map_err(AutoRendererError::from)
}

fn supported_formats(&self) -> Option<FormatSet> {
let AutoRenderer::Pixman(renderer) = self else {
return None;
};
Bind::<Image<'static, 'static>>::supported_formats(renderer)
}
}
66 changes: 66 additions & 0 deletions src/backend/renderer/auto/blit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use crate::{
backend::renderer::{Blit, BlitFrame, TextureFilter},
utils::{Physical, Rectangle},
};

#[cfg(feature = "renderer_gl")]
use crate::backend::renderer::gles::GlesTarget;

use super::{AutoRenderer, AutoRendererError, AutoRendererFrame};

impl Blit for AutoRenderer {
fn blit(
&mut self,
from: &Self::Framebuffer<'_>,
to: &mut Self::Framebuffer<'_>,
src: Rectangle<i32, Physical>,
dst: Rectangle<i32, Physical>,
filter: crate::backend::renderer::TextureFilter,
) -> Result<(), Self::Error> {
match self {
#[cfg(feature = "renderer_gl")]
AutoRenderer::Gles(renderer) => {
Blit::blit(renderer, from.try_into()?, to.try_into()?, src, dst, filter)
.map_err(AutoRendererError::from)
}
#[cfg(feature = "renderer_pixman")]
AutoRenderer::Pixman(_) => Err(AutoRendererError::Unsupported),
}
}
}

impl<'buffer> BlitFrame<GlesTarget<'buffer>> for AutoRendererFrame<'_, 'buffer> {
fn blit_to(
&mut self,
to: &mut GlesTarget<'buffer>,
src: Rectangle<i32, Physical>,
dst: Rectangle<i32, Physical>,
filter: TextureFilter,
) -> Result<(), Self::Error> {
match self {
#[cfg(feature = "renderer_gl")]
AutoRendererFrame::Gles(renderer) => {
BlitFrame::blit_to(renderer, to, src, dst, filter).map_err(AutoRendererError::from)
}
#[cfg(feature = "renderer_pixman")]
AutoRendererFrame::Pixman(_) => Err(AutoRendererError::Unsupported),
}
}

fn blit_from(
&mut self,
from: &GlesTarget<'buffer>,
src: Rectangle<i32, Physical>,
dst: Rectangle<i32, Physical>,
filter: TextureFilter,
) -> Result<(), Self::Error> {
match self {
#[cfg(feature = "renderer_gl")]
AutoRendererFrame::Gles(renderer) => {
BlitFrame::blit_from(renderer, from, src, dst, filter).map_err(AutoRendererError::from)
}
#[cfg(feature = "renderer_pixman")]
AutoRendererFrame::Pixman(_) => Err(AutoRendererError::Unsupported),
}
}
}
37 changes: 37 additions & 0 deletions src/backend/renderer/auto/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#[cfg(feature = "renderer_gl")]
use crate::backend::renderer::gles::GlesError;
#[cfg(feature = "renderer_pixman")]
use crate::backend::renderer::pixman::PixmanError;

/// Error for the auto renderer
#[derive(Debug, thiserror::Error)]
pub enum AutoRendererError {
/// Gles error
#[cfg(feature = "renderer_gl")]
#[error(transparent)]
Gles(GlesError),
/// Pixman error
#[cfg(feature = "renderer_pixman")]
#[error(transparent)]
Pixman(PixmanError),
/// Incompatible resource
#[error("An incompatible resource has been passed")]
IncompatibleResource,
/// Unsupported
#[error("The operation is not supported on this particular renderer")]
Unsupported,
}

#[cfg(feature = "renderer_gl")]
impl From<GlesError> for AutoRendererError {
fn from(value: GlesError) -> Self {
Self::Gles(value)
}
}

#[cfg(feature = "renderer_pixman")]
impl From<PixmanError> for AutoRendererError {
fn from(value: PixmanError) -> Self {
Self::Pixman(value)
}
}
83 changes: 83 additions & 0 deletions src/backend/renderer/auto/export.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
use crate::{
backend::renderer::ExportMem,
utils::{Buffer, Rectangle},
};

use super::{AutoRenderer, AutoRendererError, AutoRendererMapping};

impl ExportMem for AutoRenderer {
type TextureMapping = AutoRendererMapping;

fn copy_framebuffer(
&mut self,
target: &Self::Framebuffer<'_>,
region: Rectangle<i32, Buffer>,
format: gbm::Format,
) -> Result<Self::TextureMapping, Self::Error> {
match self {
#[cfg(feature = "renderer_gl")]
AutoRenderer::Gles(renderer) => {
ExportMem::copy_framebuffer(renderer, target.try_into()?, region, format)
.map(AutoRendererMapping::from)
.map_err(AutoRendererError::from)
}
#[cfg(feature = "renderer_pixman")]
AutoRenderer::Pixman(renderer) => {
ExportMem::copy_framebuffer(renderer, target.try_into()?, region, format)
.map(AutoRendererMapping::from)
.map_err(AutoRendererError::from)
}
}
}

fn copy_texture(
&mut self,
texture: &Self::TextureId,
region: Rectangle<i32, Buffer>,
format: gbm::Format,
) -> Result<Self::TextureMapping, Self::Error> {
match self {
#[cfg(feature = "renderer_gl")]
AutoRenderer::Gles(renderer) => {
ExportMem::copy_texture(renderer, texture.try_into()?, region, format)
.map(AutoRendererMapping::from)
.map_err(AutoRendererError::from)
}
#[cfg(feature = "renderer_pixman")]
AutoRenderer::Pixman(renderer) => {
ExportMem::copy_texture(renderer, texture.try_into()?, region, format)
.map(AutoRendererMapping::from)
.map_err(AutoRendererError::from)
}
}
}

fn can_read_texture(&mut self, texture: &Self::TextureId) -> Result<bool, Self::Error> {
match self {
#[cfg(feature = "renderer_gl")]
AutoRenderer::Gles(renderer) => {
ExportMem::can_read_texture(renderer, texture.try_into()?).map_err(AutoRendererError::from)
}
#[cfg(feature = "renderer_pixman")]
AutoRenderer::Pixman(renderer) => {
ExportMem::can_read_texture(renderer, texture.try_into()?).map_err(AutoRendererError::from)
}
}
}

fn map_texture<'a>(
&mut self,
texture_mapping: &'a Self::TextureMapping,
) -> Result<&'a [u8], Self::Error> {
match self {
#[cfg(feature = "renderer_gl")]
AutoRenderer::Gles(renderer) => {
ExportMem::map_texture(renderer, texture_mapping.try_into()?).map_err(AutoRendererError::from)
}
#[cfg(feature = "renderer_pixman")]
AutoRenderer::Pixman(renderer) => {
ExportMem::map_texture(renderer, texture_mapping.try_into()?).map_err(AutoRendererError::from)
}
}
}
}
Loading

0 comments on commit 974143e

Please sign in to comment.