use crate::{RenderError, Shared};
#[derive(Clone, Debug)]
pub struct RenderedTexture {
pub(crate) size: RenderSize,
pub(crate) format: wgpu::TextureFormat,
pub(crate) texture: wgpu::Texture,
view: wgpu::TextureView,
_recycle: Option<Shared<RecycleGuard>>,
}
#[derive(Debug)]
struct RecycleGuard {
texture: wgpu::Texture,
view: wgpu::TextureView,
token: Option<crate::pool::RecycleToken>,
}
impl Drop for RecycleGuard {
fn drop(&mut self) {
if let Some(token) = self.token.take() {
token.recycle(self.texture.clone(), self.view.clone());
}
}
}
impl RenderedTexture {
#[cfg(test)]
pub(crate) fn owned(
size: RenderSize,
format: wgpu::TextureFormat,
texture: wgpu::Texture,
) -> Self {
let view = crate::pool::default_view(&texture);
Self {
size,
format,
texture,
view,
_recycle: None,
}
}
#[must_use]
pub const fn size(&self) -> RenderSize {
self.size
}
#[cfg_attr(not(feature = "wgpu-interop"), doc(hidden))]
#[must_use]
pub const fn format(&self) -> wgpu::TextureFormat {
self.format
}
#[cfg_attr(not(feature = "wgpu-interop"), doc(hidden))]
#[must_use]
pub const fn texture(&self) -> &wgpu::Texture {
&self.texture
}
#[cfg_attr(not(feature = "wgpu-interop"), doc(hidden))]
#[must_use]
pub const fn view(&self) -> &wgpu::TextureView {
&self.view
}
pub(crate) fn pooled(
size: RenderSize,
format: wgpu::TextureFormat,
lease: crate::pool::TextureLease,
) -> Self {
let (texture, view, recycle) = lease.into_parts();
Self {
size,
format,
texture: texture.clone(),
view: view.clone(),
_recycle: Some(Shared::new(RecycleGuard {
texture,
view,
token: Some(recycle),
})),
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct SourceView<'a> {
kind: SourceKind<'a>,
}
#[derive(Clone, Copy, Debug)]
pub(crate) enum SourceKind<'a> {
Gpu(&'a wgpu::TextureView),
Cpu(&'a crate::CpuSource),
}
impl<'a> SourceView<'a> {
#[cfg_attr(not(feature = "wgpu-interop"), doc(hidden))]
#[must_use]
pub const fn from_wgpu(view: &'a wgpu::TextureView) -> Self {
Self {
kind: SourceKind::Gpu(view),
}
}
#[must_use]
pub const fn cpu(source: &'a crate::CpuSource) -> Self {
Self {
kind: SourceKind::Cpu(source),
}
}
#[cfg_attr(not(feature = "wgpu-interop"), doc(hidden))]
#[must_use]
pub const fn wgpu_view(self) -> Option<&'a wgpu::TextureView> {
match self.kind {
SourceKind::Gpu(view) => Some(view),
SourceKind::Cpu(_) => None,
}
}
#[must_use]
pub const fn cpu_source(self) -> Option<&'a crate::CpuSource> {
match self.kind {
SourceKind::Cpu(source) => Some(source),
SourceKind::Gpu(_) => None,
}
}
}
impl<'a> From<&'a RenderedTexture> for SourceView<'a> {
fn from(texture: &'a RenderedTexture) -> Self {
Self::from_wgpu(&texture.view)
}
}
impl<'a> From<&'a crate::UploadTexture> for SourceView<'a> {
fn from(texture: &'a crate::UploadTexture) -> Self {
Self::from_wgpu(texture.view())
}
}
impl<'a> From<&'a crate::CpuSource> for SourceView<'a> {
fn from(source: &'a crate::CpuSource) -> Self {
Self::cpu(source)
}
}
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub struct RenderSize {
pub width: u32,
pub height: u32,
}
impl RenderSize {
pub const MAX_DIMENSION: u32 = alpha2_media::MAX_FRAME_DIMENSION;
pub const MAX_PIXELS: u64 = alpha2_media::MAX_FRAME_PIXELS;
pub const fn new(width: u32, height: u32) -> Result<Self, RenderError> {
if width == 0 || height == 0 {
Err(RenderError::ZeroDimension)
} else if width > Self::MAX_DIMENSION
|| height > Self::MAX_DIMENSION
|| (width as u64) * (height as u64) > Self::MAX_PIXELS
{
Err(RenderError::DimensionTooLarge)
} else {
Ok(Self { width, height })
}
}
}