swapchain: handle buffer conversion for the user
+use std::convert::TryInto;
use std::sync::{Arc, atomic::{AtomicBool, Ordering}};
use std::ops::Deref;
@@ -5,14 +6,15 @@ use crate::backend::allocator::{Allocator, Buffer, Format};
pub const SLOT_CAP: usize = 3;
-pub struct Swapchain<A: Allocator<B>, B: Buffer> {
+pub struct Swapchain<A: Allocator<B>, B: Buffer + TryInto<B>, D: Buffer = B> {
allocator: A,
+ _original_buffer_format: std::marker::PhantomData<B>,
width: u32,
height: u32,
format: Format,
- slots: [Slot<B>; SLOT_CAP],
+ slots: [Slot<D>; SLOT_CAP],
}
pub struct Slot<B: Buffer> {
@@ -51,10 +53,30 @@ impl<B: Buffer> Drop for Slot<B> {
}
}
-impl<A: Allocator<B>, B: Buffer> Swapchain<A, B> {
- pub fn new(allocator: A, width: u32, height: u32, format: Format) -> Swapchain<A, B> {
+#[derive(Debug, thiserror::Error)]
+pub enum SwapchainError<E1, E2>
+where
+ E1: std::error::Error + 'static,
+ E2: std::error::Error + 'static,
+{
+ #[error("Failed to allocate a new buffer: {0}")]
+ AllocationError(#[source] E1),
+ #[error("Failed to convert a new buffer: {0}")]
+ ConversionError(#[source] E2),
+}
+
+impl<A, B, D, E1, E2> Swapchain<A, B, D>
+where
+ A: Allocator<B, Error=E1>,
+ B: Buffer + TryInto<D, Error=E2>,
+ D: Buffer,
+ E1: std::error::Error + 'static,
+ E2: std::error::Error + 'static,
+{
+ pub fn new(allocator: A, width: u32, height: u32, format: Format) -> Swapchain<A, B, D> {
Swapchain {
allocator,
+ _original_buffer_format: std::marker::PhantomData,
width,
height,
format,
@@ -62,10 +84,14 @@ impl<A: Allocator<B>, B: Buffer> Swapchain<A, B> {
}
}
- pub fn acquire(&mut self) -> Result<Option<Slot<B>>, A::Error> {
+ pub fn acquire(&mut self) -> Result<Option<Slot<D>>, SwapchainError<E1, E2>> {
if let Some(free_slot) = self.slots.iter_mut().filter(|s| !s.acquired.load(Ordering::SeqCst)).next() {
if free_slot.buffer.is_none() {
- free_slot.buffer = Arc::new(Some(self.allocator.create_buffer(self.width, self.height, self.format)?));
+ free_slot.buffer = Arc::new(Some(
+ self.allocator
+ .create_buffer(self.width, self.height, self.format).map_err(SwapchainError::AllocationError)?
+ .try_into().map_err(SwapchainError::ConversionError)?
+ ));
}
assert!(!free_slot.buffer.is_some());
