1use crate::{RenderError, Shared};
2
3#[derive(Clone, Debug)]
9pub struct RenderedTexture {
10 pub(crate) size: RenderSize,
11 pub(crate) format: wgpu::TextureFormat,
12 pub(crate) texture: wgpu::Texture,
13 view: wgpu::TextureView,
14 _recycle: Option<Shared<RecycleGuard>>,
15}
16
17#[derive(Debug)]
18struct RecycleGuard {
19 texture: wgpu::Texture,
20 view: wgpu::TextureView,
21 token: Option<crate::pool::RecycleToken>,
22}
23
24impl Drop for RecycleGuard {
25 fn drop(&mut self) {
26 if let Some(token) = self.token.take() {
27 token.recycle(self.texture.clone(), self.view.clone());
28 }
29 }
30}
31
32impl RenderedTexture {
33 #[cfg(test)]
34 pub(crate) fn owned(
35 size: RenderSize,
36 format: wgpu::TextureFormat,
37 texture: wgpu::Texture,
38 ) -> Self {
39 let view = crate::pool::default_view(&texture);
40 Self {
41 size,
42 format,
43 texture,
44 view,
45 _recycle: None,
46 }
47 }
48
49 #[must_use]
51 pub const fn size(&self) -> RenderSize {
52 self.size
53 }
54
55 #[cfg_attr(not(feature = "wgpu-interop"), doc(hidden))]
57 #[must_use]
58 pub const fn format(&self) -> wgpu::TextureFormat {
59 self.format
60 }
61
62 #[cfg_attr(not(feature = "wgpu-interop"), doc(hidden))]
64 #[must_use]
65 pub const fn texture(&self) -> &wgpu::Texture {
66 &self.texture
67 }
68
69 #[cfg_attr(not(feature = "wgpu-interop"), doc(hidden))]
72 #[must_use]
73 pub const fn view(&self) -> &wgpu::TextureView {
74 &self.view
75 }
76
77 pub(crate) fn pooled(
78 size: RenderSize,
79 format: wgpu::TextureFormat,
80 lease: crate::pool::TextureLease,
81 ) -> Self {
82 let (texture, view, recycle) = lease.into_parts();
83 Self {
84 size,
85 format,
86 texture: texture.clone(),
87 view: view.clone(),
88 _recycle: Some(Shared::new(RecycleGuard {
89 texture,
90 view,
91 token: Some(recycle),
92 })),
93 }
94 }
95}
96
97#[derive(Clone, Copy, Debug)]
109pub struct SourceView<'a> {
110 kind: SourceKind<'a>,
111}
112
113#[derive(Clone, Copy, Debug)]
115pub(crate) enum SourceKind<'a> {
116 Gpu(&'a wgpu::TextureView),
117 Cpu(&'a crate::CpuSource),
118}
119
120impl<'a> SourceView<'a> {
121 #[cfg_attr(not(feature = "wgpu-interop"), doc(hidden))]
124 #[must_use]
125 pub const fn from_wgpu(view: &'a wgpu::TextureView) -> Self {
126 Self {
127 kind: SourceKind::Gpu(view),
128 }
129 }
130
131 #[must_use]
133 pub const fn cpu(source: &'a crate::CpuSource) -> Self {
134 Self {
135 kind: SourceKind::Cpu(source),
136 }
137 }
138
139 #[cfg_attr(not(feature = "wgpu-interop"), doc(hidden))]
141 #[must_use]
142 pub const fn wgpu_view(self) -> Option<&'a wgpu::TextureView> {
143 match self.kind {
144 SourceKind::Gpu(view) => Some(view),
145 SourceKind::Cpu(_) => None,
146 }
147 }
148
149 #[must_use]
151 pub const fn cpu_source(self) -> Option<&'a crate::CpuSource> {
152 match self.kind {
153 SourceKind::Cpu(source) => Some(source),
154 SourceKind::Gpu(_) => None,
155 }
156 }
157}
158
159impl<'a> From<&'a RenderedTexture> for SourceView<'a> {
160 fn from(texture: &'a RenderedTexture) -> Self {
161 Self::from_wgpu(&texture.view)
162 }
163}
164
165impl<'a> From<&'a crate::UploadTexture> for SourceView<'a> {
166 fn from(texture: &'a crate::UploadTexture) -> Self {
167 Self::from_wgpu(texture.view())
168 }
169}
170
171impl<'a> From<&'a crate::CpuSource> for SourceView<'a> {
172 fn from(source: &'a crate::CpuSource) -> Self {
173 Self::cpu(source)
174 }
175}
176
177#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
179pub struct RenderSize {
180 pub width: u32,
182 pub height: u32,
184}
185
186impl RenderSize {
187 pub const MAX_DIMENSION: u32 = alpha2_media::MAX_FRAME_DIMENSION;
189 pub const MAX_PIXELS: u64 = alpha2_media::MAX_FRAME_PIXELS;
191
192 pub const fn new(width: u32, height: u32) -> Result<Self, RenderError> {
198 if width == 0 || height == 0 {
199 Err(RenderError::ZeroDimension)
200 } else if width > Self::MAX_DIMENSION
201 || height > Self::MAX_DIMENSION
202 || (width as u64) * (height as u64) > Self::MAX_PIXELS
203 {
204 Err(RenderError::DimensionTooLarge)
205 } else {
206 Ok(Self { width, height })
207 }
208 }
209}