Skip to content

Commit

Permalink
Reintroduce backend selection through ICED_BACKEND env var
Browse files Browse the repository at this point in the history
  • Loading branch information
hecrj committed Mar 24, 2024
1 parent 441e923 commit 4f5b63f
Show file tree
Hide file tree
Showing 8 changed files with 198 additions and 85 deletions.
15 changes: 14 additions & 1 deletion graphics/src/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ pub trait Compositor: Sized {
fn new<W: Window + Clone>(
settings: Settings,
compatible_window: W,
) -> impl Future<Output = Result<Self, Error>> {
Self::with_backend(settings, compatible_window, None)
}

/// Creates a new [`Compositor`] with a backend preference.
///
/// If the backend does not match the preference, it will return
/// [`Error::GraphicsAdapterNotFound`].
fn with_backend<W: Window + Clone>(
_settings: Settings,
_compatible_window: W,
_backend: Option<&str>,
) -> impl Future<Output = Result<Self, Error>>;

/// Creates a [`Self::Renderer`] for the [`Compositor`].
Expand Down Expand Up @@ -130,9 +142,10 @@ impl Compositor for () {
type Renderer = ();
type Surface = ();

async fn new<W: Window + Clone>(
async fn with_backend<W: Window + Clone>(
_settings: Settings,
_compatible_window: W,
_preffered_backend: Option<&str>,
) -> Result<Self, Error> {
Ok(())
}
Expand Down
27 changes: 25 additions & 2 deletions graphics/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! See what can go wrong when creating graphical backends.
/// An error that occurred while creating an application's graphical context.
#[derive(Debug, thiserror::Error)]
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum Error {
/// The requested backend version is not supported.
#[error("the requested backend version is not supported")]
Expand All @@ -11,9 +13,30 @@ pub enum Error {

/// A suitable graphics adapter or device could not be found.
#[error("a suitable graphics adapter or device could not be found")]
GraphicsAdapterNotFound,
GraphicsAdapterNotFound {
/// The name of the backend where the error happened
backend: &'static str,
/// The reason why this backend could not be used
reason: Reason,
},

/// An error occurred in the context's internal backend
#[error("an error occurred in the context's internal backend")]
BackendError(String),

/// Multiple errors occurred
#[error("multiple errors occurred: {0:?}")]
List(Vec<Self>),
}

/// The reason why a graphics adapter could not be found
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Reason {
/// The backend did not match the preference
DidNotMatch {
/// The preferred backend
preferred_backend: String,
},
/// The request to create the backend failed
RequestFailed(String),
}
2 changes: 1 addition & 1 deletion graphics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
mod antialiasing;
mod cached;
mod error;
mod primitive;
mod settings;
mod viewport;
Expand All @@ -27,6 +26,7 @@ pub mod backend;
pub mod color;
pub mod compositor;
pub mod damage;
pub mod error;
pub mod gradient;
pub mod mesh;
pub mod renderer;
Expand Down
51 changes: 44 additions & 7 deletions renderer/src/fallback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,18 +204,55 @@ where
type Renderer = Renderer<L::Renderer, R::Renderer>;
type Surface = Surface<L::Surface, R::Surface>;

async fn new<W: compositor::Window + Clone>(
async fn with_backend<W: compositor::Window + Clone>(
settings: graphics::Settings,
compatible_window: W,
backend: Option<&str>,
) -> Result<Self, graphics::Error> {
if let Ok(left) = L::new(settings, compatible_window.clone())
.await
.map(Self::Left)
{
return Ok(left);
use std::env;

let backends = backend
.map(str::to_owned)
.or_else(|| env::var("ICED_BACKEND").ok());

let mut candidates: Vec<_> = backends
.map(|backends| {
backends
.split(',')
.filter(|candidate| !candidate.is_empty())
.map(str::to_owned)
.map(Some)
.collect()
})
.unwrap_or_default();

if candidates.is_empty() {
candidates.push(None);
}

R::new(settings, compatible_window).await.map(Self::Right)
let mut errors = vec![];

for backend in candidates.iter().map(Option::as_deref) {
match L::with_backend(settings, compatible_window.clone(), backend)
.await
{
Ok(compositor) => return Ok(Self::Left(compositor)),
Err(error) => {
errors.push(error);
}
}

match R::with_backend(settings, compatible_window.clone(), backend)
.await
{
Ok(compositor) => return Ok(Self::Right(compositor)),
Err(error) => {
errors.push(error);
}
}
}

Err(graphics::Error::List(errors))
}

fn create_renderer(&self) -> Self::Renderer {
Expand Down
21 changes: 16 additions & 5 deletions tiny_skia/src/window/compositor.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use crate::core::{Color, Rectangle, Size};
use crate::graphics::compositor::{self, Information};
use crate::graphics::damage;
use crate::graphics::{self, Error, Viewport};
use crate::graphics::error::{self, Error};
use crate::graphics::{self, Viewport};
use crate::{Backend, Primitive, Renderer, Settings};

use std::collections::VecDeque;
use std::future::{self, Future};
use std::num::NonZeroU32;

pub struct Compositor {
Expand All @@ -28,11 +28,22 @@ impl crate::graphics::Compositor for Compositor {
type Renderer = Renderer;
type Surface = Surface;

fn new<W: compositor::Window>(
async fn with_backend<W: compositor::Window>(
settings: graphics::Settings,
compatible_window: W,
) -> impl Future<Output = Result<Self, Error>> {
future::ready(Ok(new(settings.into(), compatible_window)))
backend: Option<&str>,
) -> Result<Self, Error> {
match backend {
None | Some("tiny-skia") | Some("tiny_skia") => {
Ok(new(settings.into(), compatible_window))
}
Some(backend) => Err(Error::GraphicsAdapterNotFound {
backend: "tiny-skia",
reason: error::Reason::DidNotMatch {
preferred_backend: backend.to_owned(),
},
}),
}
}

fn create_renderer(&self) -> Self::Renderer {
Expand Down
1 change: 1 addition & 0 deletions wgpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ glyphon.workspace = true
guillotiere.workspace = true
log.workspace = true
once_cell.workspace = true
thiserror.workspace = true
wgpu.workspace = true

lyon.workspace = true
Expand Down
24 changes: 0 additions & 24 deletions wgpu/src/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,30 +29,6 @@ pub struct Settings {
pub antialiasing: Option<Antialiasing>,
}

impl Settings {
/// Creates new [`Settings`] using environment configuration.
///
/// Specifically:
///
/// - The `internal_backend` can be configured using the `WGPU_BACKEND`
/// environment variable. If the variable is not set, the primary backend
/// will be used. The following values are allowed:
/// - `vulkan`
/// - `metal`
/// - `dx12`
/// - `dx11`
/// - `gl`
/// - `webgpu`
/// - `primary`
pub fn from_env() -> Self {
Settings {
internal_backend: wgpu::util::backend_bits_from_env()
.unwrap_or(wgpu::Backends::all()),
..Self::default()
}
}
}

impl Default for Settings {
fn default() -> Settings {
Settings {
Expand Down
Loading

0 comments on commit 4f5b63f

Please sign in to comment.