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