use device;
use format::Format;
use image;
use queue::{Capability, CommandQueue};
use Backend;
use std::iter;
use std::any::Any;
use std::borrow::Borrow;
use std::cmp::{max, min};
use std::ops::Range;
#[derive(Clone, Copy, Debug, Fail, PartialEq, Eq)]
pub enum CreationError {
#[fail(display = "{}", _0)]
OutOfMemory(device::OutOfMemory),
#[fail(display = "{}", _0)]
DeviceLost(device::DeviceLost),
#[fail(display = "{}", _0)]
SurfaceLost(device::SurfaceLost),
#[fail(display = "{}", _0)]
WindowInUse(device::WindowInUse),
}
impl From<device::OutOfMemory> for CreationError {
fn from(error: device::OutOfMemory) -> Self {
CreationError::OutOfMemory(error)
}
}
impl From<device::DeviceLost> for CreationError {
fn from(error: device::DeviceLost) -> Self {
CreationError::DeviceLost(error)
}
}
impl From<device::SurfaceLost> for CreationError {
fn from(error: device::SurfaceLost) -> Self {
CreationError::SurfaceLost(error)
}
}
impl From<device::WindowInUse> for CreationError {
fn from(error: device::WindowInUse) -> Self {
CreationError::WindowInUse(error)
}
}
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Extent2D {
pub width: image::Size,
pub height: image::Size,
}
impl From<image::Extent> for Extent2D {
fn from(ex: image::Extent) -> Self {
Extent2D {
width: ex.width,
height: ex.height,
}
}
}
impl Extent2D {
pub fn to_extent(&self) -> image::Extent {
image::Extent {
width: self.width,
height: self.height,
depth: 1,
}
}
}
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SurfaceCapabilities {
pub image_count: Range<SwapImageIndex>,
pub current_extent: Option<Extent2D>,
pub extents: Range<Extent2D>,
pub max_image_layers: image::Layer,
pub usage: image::Usage,
}
pub trait Surface<B: Backend>: Any + Send + Sync {
fn kind(&self) -> image::Kind;
fn supports_queue_family(&self, family: &B::QueueFamily) -> bool;
fn compatibility(
&self,
physical_device: &B::PhysicalDevice,
) -> (SurfaceCapabilities, Option<Vec<Format>>, Vec<PresentMode>, Vec<CompositeAlpha>);
}
pub type SwapImageIndex = u32;
pub enum FrameSync<'a, B: Backend> {
Semaphore(&'a B::Semaphore),
Fence(&'a B::Fence),
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum PresentMode {
Immediate = 0,
Mailbox = 1,
Fifo = 2,
Relaxed = 3,
}
#[repr(C)]
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
pub enum CompositeAlpha {
Opaque = 0,
PreMultiplied = 1,
PostMultiplied = 2,
Inherit = 3,
}
#[derive(Debug, Clone)]
pub struct SwapchainConfig {
pub present_mode: PresentMode,
pub composite_alpha: CompositeAlpha,
pub format: Format,
pub extent: Extent2D,
pub image_count: SwapImageIndex,
pub image_layers: image::Layer,
pub image_usage: image::Usage,
}
impl SwapchainConfig {
pub fn new(width: u32, height: u32, format: Format, image_count: SwapImageIndex) -> Self {
SwapchainConfig {
present_mode: PresentMode::Fifo,
composite_alpha: CompositeAlpha::Inherit,
format,
extent: Extent2D { width, height },
image_count,
image_layers: 1,
image_usage: image::Usage::COLOR_ATTACHMENT,
}
}
pub fn from_caps(caps: &SurfaceCapabilities, format: Format, default_extent: Extent2D) -> Self {
let clamped_extent = match caps.current_extent {
Some(current) => current,
None => {
let (min_width, max_width) = (caps.extents.start.width, caps.extents.end.width - 1);
let (min_height, max_height) =
(caps.extents.start.height, caps.extents.end.height - 1);
let width = min(max_width, max(default_extent.width, min_width));
let height = min(max_height, max(default_extent.height, min_height));
Extent2D { width, height }
}
};
SwapchainConfig {
present_mode: PresentMode::Fifo,
composite_alpha: CompositeAlpha::Inherit,
format,
extent: clamped_extent,
image_count: caps.image_count.start,
image_layers: 1,
image_usage: image::Usage::COLOR_ATTACHMENT,
}
}
pub fn with_mode(mut self, mode: PresentMode) -> Self {
self.present_mode = mode;
self
}
pub fn with_image_usage(mut self, usage: image::Usage) -> Self {
self.image_usage = usage;
self
}
}
#[derive(Debug)]
pub enum Backbuffer<B: Backend> {
Images(Vec<B::Image>),
Framebuffer(B::Framebuffer),
}
#[derive(Debug)]
pub enum AcquireError {
NotReady,
OutOfDate,
SurfaceLost(device::SurfaceLost),
}
pub trait Swapchain<B: Backend>: Any + Send + Sync {
unsafe fn acquire_image(
&mut self,
timeout_ns: u64,
sync: FrameSync<B>,
) -> Result<SwapImageIndex, AcquireError>;
unsafe fn present<'a, C, S, Iw>(
&'a self,
present_queue: &mut CommandQueue<B, C>,
image_index: SwapImageIndex,
wait_semaphores: Iw,
) -> Result<(), ()>
where
Self: 'a + Sized + Borrow<B::Swapchain>,
C: Capability,
S: 'a + Borrow<B::Semaphore>,
Iw: IntoIterator<Item = &'a S>,
{
present_queue.present(iter::once((self, image_index)), wait_semaphores)
}
unsafe fn present_nosemaphores<'a, C>(
&'a self,
present_queue: &mut CommandQueue<B, C>,
image_index: SwapImageIndex,
) -> Result<(), ()>
where
Self: 'a + Sized + Borrow<B::Swapchain>,
C: Capability,
{
self.present::<_, B::Semaphore, _>(present_queue, image_index, iter::empty())
}
}