1#[cfg(feature = "opengl")]
5pub mod gl;
6
7#[cfg(feature = "vulkan")]
9pub mod vk;
10
11#[cfg(feature = "wgpu")]
13pub mod wgpu;
14
15#[cfg(all(target_os = "windows", feature = "dxgi"))]
17pub mod dxgi;
18
19#[cfg(all(target_os = "windows", feature = "d3d9"))]
21pub mod d3d9;
22
23#[cfg(all(target_os = "windows", feature = "d3d11"))]
25pub mod d3d11;
26
27#[cfg(all(target_os = "windows", feature = "d3d12"))]
29pub mod d3d12;
30
31#[cfg(all(target_vendor = "apple", feature = "metal"))]
32pub mod metal;
33
34mod viewport;
35
36#[doc(hidden)]
37pub mod map;
38pub mod shader_features;
39pub mod string;
40
41pub use viewport::Viewport;
42
43use num_traits::{AsPrimitive, Num};
44use std::convert::Infallible;
45use std::ops::{Add, Sub};
46use std::str::FromStr;
47
48#[repr(u32)]
49#[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Hash)]
50#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
51pub enum ImageFormat {
53 #[default]
54 Unknown = 0,
55
56 R8Unorm,
58 R8Uint,
59 R8Sint,
60 R8G8Unorm,
61 R8G8Uint,
62 R8G8Sint,
63 R8G8B8A8Unorm,
64 R8G8B8A8Uint,
65 R8G8B8A8Sint,
66 R8G8B8A8Srgb,
67
68 A2B10G10R10UnormPack32,
70 A2B10G10R10UintPack32,
71
72 R16Uint,
74 R16Sint,
75 R16Sfloat,
76 R16G16Uint,
77 R16G16Sint,
78 R16G16Sfloat,
79 R16G16B16A16Uint,
80 R16G16B16A16Sint,
81 R16G16B16A16Sfloat,
82
83 R32Uint,
85 R32Sint,
86 R32Sfloat,
87 R32G32Uint,
88 R32G32Sint,
89 R32G32Sfloat,
90 R32G32B32A32Uint,
91 R32G32B32A32Sint,
92 R32G32B32A32Sfloat,
93}
94
95#[repr(i32)]
96#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Hash)]
97#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
98pub enum FilterMode {
100 Linear = 0,
102
103 #[default]
104 Nearest,
106}
107
108impl FromStr for WrapMode {
109 type Err = Infallible;
110
111 fn from_str(s: &str) -> Result<Self, Self::Err> {
112 Ok(match s {
113 "clamp_to_border" => WrapMode::ClampToBorder,
114 "clamp_to_edge" => WrapMode::ClampToEdge,
115 "repeat" => WrapMode::Repeat,
116 "mirrored_repeat" => WrapMode::MirroredRepeat,
117 _ => WrapMode::ClampToBorder,
118 })
119 }
120}
121
122impl FromStr for FilterMode {
123 type Err = Infallible;
124
125 fn from_str(s: &str) -> Result<Self, Self::Err> {
126 Ok(match s {
127 "linear" => FilterMode::Linear,
128 "nearest" => FilterMode::Nearest,
129 _ => FilterMode::Nearest,
130 })
131 }
132}
133
134#[repr(u32)]
136#[derive(Default, Copy, Clone, Debug, Eq, PartialEq, Hash)]
137#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
138pub enum ColorSpace {
139 #[default]
141 Sdr = 0,
142 Hdr10 = 1,
145 ScRgb = 2,
148 PqScRgb = 3,
150}
151
152impl ColorSpace {
153 pub fn is_hdr(&self) -> bool {
155 !matches!(*self, ColorSpace::Sdr)
156 }
157}
158
159#[repr(i32)]
160#[derive(Copy, Clone, Default, Debug, Eq, PartialEq, Hash)]
161#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
162pub enum WrapMode {
164 #[default]
165 ClampToBorder = 0,
167 ClampToEdge,
169 Repeat,
171 MirroredRepeat,
173}
174
175impl FromStr for ImageFormat {
176 type Err = Infallible;
177
178 fn from_str(s: &str) -> Result<Self, Self::Err> {
179 Ok(match s {
180 "UNKNOWN" => Self::Unknown,
181
182 "R8_UNORM" => Self::R8Unorm,
183 "R8_UINT" => Self::R8Uint,
184 "R8_SINT" => Self::R8Sint,
185 "R8G8_UNORM" => Self::R8G8Unorm,
186 "R8G8_UINT" => Self::R8Uint,
187 "R8G8_SINT" => Self::R8G8Sint,
188 "R8G8B8A8_UNORM" => Self::R8G8B8A8Unorm,
189 "R8G8B8A8_UINT" => Self::R8G8B8A8Uint,
190 "R8G8B8A8_SINT" => Self::R8G8B8A8Sint,
191 "R8G8B8A8_SRGB" => Self::R8G8B8A8Srgb,
192
193 "A2B10G10R10_UNORM_PACK32" => Self::A2B10G10R10UnormPack32,
194 "A2B10G10R10_UINT_PACK32" => Self::A2B10G10R10UintPack32,
195
196 "R16_UINT" => Self::R16Uint,
197 "R16_SINT" => Self::R16Sint,
198 "R16_SFLOAT" => Self::R16Sfloat,
199 "R16G16_UINT" => Self::R16G16Uint,
200 "R16G16_SINT" => Self::R16G16Sint,
201 "R16G16_SFLOAT" => Self::R16G16Sfloat,
202 "R16G16B16A16_UINT" => Self::R16G16B16A16Uint,
203 "R16G16B16A16_SINT" => Self::R16G16B16A16Sint,
204 "R16G16B16A16_SFLOAT" => Self::R16G16B16A16Sfloat,
205
206 "R32_UINT" => Self::R32Uint,
207 "R32_SINT" => Self::R32Sint,
208 "R32_SFLOAT" => Self::R32Sfloat,
209 "R32G32_UINT" => Self::R32G32Uint,
210 "R32G32_SINT" => Self::R32G32Sint,
211 "R32G32_SFLOAT" => Self::R32G32Sfloat,
212 "R32G32B32A32_UINT" => Self::R32G32B32A32Uint,
213 "R32G32B32A32_SINT" => Self::R32G32B32A32Sint,
214 "R32G32B32A32_SFLOAT" => Self::R32G32B32A32Sfloat,
215 _ => Self::Unknown,
216 })
217 }
218}
219
220#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
222#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
223pub struct Size<T> {
224 pub width: T,
225 pub height: T,
226}
227
228impl<T> Size<T> {
229 pub fn new(width: T, height: T) -> Self {
231 Size { width, height }
232 }
233}
234
235impl AsPrimitive<u64> for Size<u32> {
236 fn as_(self) -> u64 {
237 ((self.width as u64) << 32) | (self.height as u64)
238 }
239}
240
241impl<T: AsPrimitive<f32>> Size<T> {
242 #[inline(always)]
244 pub fn aspect_ratio(&self) -> f32 {
245 self.width.as_() / self.height.as_()
246 }
247}
248
249impl<T: Sub<Output = T>> Sub for Size<T> {
250 type Output = Size<T>;
251
252 fn sub(self, rhs: Self) -> Self::Output {
253 Self {
254 width: self.width - rhs.width,
255 height: self.height - rhs.height,
256 }
257 }
258}
259
260impl<T: Sub<T, Output = T> + Copy> Sub<T> for Size<T> {
261 type Output = Size<T>;
262
263 fn sub(self, rhs: T) -> Self::Output {
264 Self {
265 width: self.width - rhs,
266 height: self.height - rhs,
267 }
268 }
269}
270
271impl<T: Add<Output = T>> Add for Size<T> {
272 type Output = Size<T>;
273
274 fn add(self, rhs: Self) -> Self::Output {
275 Self {
276 width: self.width + rhs.width,
277 height: self.height + rhs.height,
278 }
279 }
280}
281
282impl<T: Add<T, Output = T> + Copy> Add<T> for Size<T> {
283 type Output = Size<T>;
284
285 fn add(self, rhs: T) -> Self::Output {
286 Self {
287 width: self.width + rhs,
288 height: self.height + rhs,
289 }
290 }
291}
292
293impl<T> From<Size<T>> for [f32; 4]
294where
295 T: Copy + AsPrimitive<f32>,
296{
297 fn from(value: Size<T>) -> Self {
299 [
300 value.width.as_(),
301 value.height.as_(),
302 1.0 / value.width.as_(),
303 1.0 / value.height.as_(),
304 ]
305 }
306}
307
308pub trait GetSize<C: Num> {
310 type Error;
311 fn size(&self) -> Result<Size<C>, Self::Error>;
313}
314
315impl<T: GetSize<u32>> GetSize<f32> for T {
316 type Error = T::Error;
317
318 fn size(&self) -> Result<Size<f32>, Self::Error> {
319 let size = <T as GetSize<u32>>::size(self)?;
320 Ok(Size {
321 width: size.width as f32,
322 height: size.height as f32,
323 })
324 }
325}