-
Notifications
You must be signed in to change notification settings - Fork 617
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Work in progress for BackendSelector API
- Loading branch information
Showing
18 changed files
with
320 additions
and
221 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
// Copyright © SixtyFPS GmbH <[email protected]> | ||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 | ||
|
||
use i_slint_core::api::PlatformError; | ||
use i_slint_core::graphics::RequestedGraphicsAPI; | ||
|
||
/// Use the BackendSelector to configure one of Slint's built-in backends with a renderer | ||
/// to accomodate specific needs of your application. This is a programmatic substitute for | ||
/// the `SLINT_BACKEND` environment variable. | ||
/// | ||
/// For example, to configure Slint to use a renderer that supports OpenGL ES 3.0, configure | ||
/// the `BackendSelector` as follows: | ||
/// ```rust,no_run | ||
/// # use i_slint_backend_selector::api::BackendSelector; | ||
/// let selector = BackendSelector::new().require_opengl_es_with_version(3, 0); | ||
/// if let Err(err) = selector.select() { | ||
/// eprintln!("Error selecting backend with OpenGL ES support: {err}"); | ||
/// } | ||
/// ``` | ||
pub struct BackendSelector { | ||
requested_graphics_api: Option<RequestedGraphicsAPI>, | ||
backend: Option<String>, | ||
renderer: Option<String>, | ||
} | ||
|
||
impl BackendSelector { | ||
/// Creates a new BackendSelector. | ||
#[must_use] | ||
pub fn new() -> BackendSelector { | ||
BackendSelector { requested_graphics_api: None, backend: None, renderer: None } | ||
} | ||
|
||
/// Adds the requirement to the selector that the backend must render with OpenGL ES | ||
/// and the specified major and minor version. | ||
#[must_use] | ||
pub fn require_opengl_es_with_version(mut self, major: u8, minor: u8) -> Self { | ||
self.requested_graphics_api = Some(RequestedGraphicsAPI::OpenGLES(Some((major, minor)))); | ||
self | ||
} | ||
|
||
/// Adds the requirement to the selector that the backend must render with OpenGL ES. | ||
#[must_use] | ||
pub fn require_opengl_es(mut self) -> Self { | ||
self.requested_graphics_api = Some(RequestedGraphicsAPI::OpenGLES(None)); | ||
self | ||
} | ||
|
||
/// Adds the requirement to the selector that the backend must render with OpenGL. | ||
#[must_use] | ||
pub fn require_opengl(mut self) -> Self { | ||
self.requested_graphics_api = Some(RequestedGraphicsAPI::OpenGL(None)); | ||
self | ||
} | ||
|
||
/// Adds the requirement to the selector that the backend must render with OpenGL | ||
/// and the specified major and minor version. | ||
#[must_use] | ||
pub fn require_opengl_with_version(mut self, major: u8, minor: u8) -> Self { | ||
self.requested_graphics_api = Some(RequestedGraphicsAPI::OpenGL(Some((major, minor)))); | ||
self | ||
} | ||
|
||
/// Adds the requirement to the selector that the backend must render with Apple's Metal framework. | ||
#[must_use] | ||
pub fn require_metal(mut self) -> Self { | ||
self.requested_graphics_api = Some(RequestedGraphicsAPI::Metal); | ||
self | ||
} | ||
|
||
/// Adds the requirement to the selector that the backend must render with Vulkan. | ||
#[must_use] | ||
pub fn require_vulkan(mut self) -> Self { | ||
self.requested_graphics_api = Some(RequestedGraphicsAPI::Vulkan); | ||
self | ||
} | ||
|
||
/// Adds the requirement that the selected renderer must match the given name. This is | ||
/// equivalent to setting the `SLINT_BACKEND=name` environment variable and requires | ||
/// that the corresponding renderer feature is enabled. For example, to select the Skia renderer, | ||
/// enable the `renderer-skia` feature and call this function with `skia` as argument. | ||
#[must_use] | ||
pub fn renderer_name(mut self, name: String) -> Self { | ||
self.renderer = Some(name); | ||
self | ||
} | ||
|
||
/// Adds the requirement that the selected backend must match the given name. This is | ||
/// equivalent to setting the `SLINT_BACKEND=name` environment variable and requires | ||
/// that the corresponding backend feature is enabled. For example, to select the winit backend, | ||
/// enable the `backend-winit` feature and call this function with `winit` as argument. | ||
#[must_use] | ||
pub fn backend_name(mut self, name: String) -> Self { | ||
self.backend = Some(name); | ||
self | ||
} | ||
|
||
/// Completes the backend selection process and tries to combine with specified requirements | ||
/// with the different backends and renderers enabled at compile time. On success, the selected | ||
/// backend is automatically set to be active. Returns an error if the requirements could not be met. | ||
pub fn select(self) -> Result<(), PlatformError> { | ||
let backend_name = self.backend.as_deref().unwrap_or(super::DEFAULT_BACKEND_NAME); | ||
|
||
let backend: Box<dyn i_slint_core::platform::Platform> = match backend_name { | ||
#[cfg(feature = "i-slint-backend-linuxkms")] | ||
"linuxkms" => { | ||
if self.requested_graphics_api.is_some() { | ||
return Err("The linuxkms backend does not implement renderer selection by graphics API".into()); | ||
} | ||
|
||
Box::new(i_slint_backend_linuxkms::Backend::new_with_renderer_by_name( | ||
self.renderer, | ||
)); | ||
} | ||
#[cfg(feature = "i-slint-backend-winit")] | ||
"winit" => { | ||
let builder = i_slint_backend_winit::Backend::builder(); | ||
|
||
let builder = match self.requested_graphics_api { | ||
Some(api) => builder.request_graphics_api(api), | ||
None => builder, | ||
}; | ||
|
||
let builder = match self.renderer { | ||
Some(name) => builder.with_renderer_name(name), | ||
None => builder, | ||
}; | ||
|
||
Box::new(builder.build()?) | ||
} | ||
#[cfg(feature = "i-slint-backend-qt")] | ||
"qt" => { | ||
if self.requested_graphics_api.is_some() { | ||
return Err( | ||
"The qt backend does not implement renderer selection by graphics API" | ||
.into(), | ||
); | ||
} | ||
if self.renderer.is_some() { | ||
return Err( | ||
"The qt backend does not implement renderer selection by name".into() | ||
); | ||
} | ||
Box::new(i_slint_backend_qt::Backend::new()) | ||
} | ||
requested_backend @ _ => { | ||
return Err(format!( | ||
"{requested_backend} backend requested but it is not available" | ||
) | ||
.into()); | ||
} | ||
}; | ||
|
||
i_slint_core::platform::set_platform(backend) | ||
.map_err(|set_platform_error| PlatformError::SetPlatformError(set_platform_error)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.