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)]
106pub struct SourceView<'a> {
107 view: &'a wgpu::TextureView,
108}
109
110impl<'a> SourceView<'a> {
111 #[cfg_attr(not(feature = "wgpu-interop"), doc(hidden))]
114 #[must_use]
115 pub const fn from_wgpu(view: &'a wgpu::TextureView) -> Self {
116 Self { view }
117 }
118
119 #[cfg_attr(not(feature = "wgpu-interop"), doc(hidden))]
121 #[must_use]
122 pub const fn wgpu_view(self) -> &'a wgpu::TextureView {
123 self.view
124 }
125}
126
127impl<'a> From<&'a RenderedTexture> for SourceView<'a> {
128 fn from(texture: &'a RenderedTexture) -> Self {
129 Self {
130 view: &texture.view,
131 }
132 }
133}
134
135impl<'a> From<&'a crate::UploadTexture> for SourceView<'a> {
136 fn from(texture: &'a crate::UploadTexture) -> Self {
137 Self {
138 view: texture.view(),
139 }
140 }
141}
142
143#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
145pub struct RenderSize {
146 pub width: u32,
148 pub height: u32,
150}
151
152impl RenderSize {
153 pub const MAX_DIMENSION: u32 = alpha2_media::MAX_FRAME_DIMENSION;
155 pub const MAX_PIXELS: u64 = alpha2_media::MAX_FRAME_PIXELS;
157
158 pub const fn new(width: u32, height: u32) -> Result<Self, RenderError> {
164 if width == 0 || height == 0 {
165 Err(RenderError::ZeroDimension)
166 } else if width > Self::MAX_DIMENSION
167 || height > Self::MAX_DIMENSION
168 || (width as u64) * (height as u64) > Self::MAX_PIXELS
169 {
170 Err(RenderError::DimensionTooLarge)
171 } else {
172 Ok(Self { width, height })
173 }
174 }
175}