1use crate::{arc, cf, define_mtl, define_obj_type, define_opts, mtl, ns, objc};
2
3#[cfg(feature = "io_surface")]
4use crate::io;
5
6#[doc(alias = "MTLTextureType")]
8#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)]
9#[repr(usize)]
10pub enum Type {
11 #[doc(alias = "MTLTextureType1D")]
12 _1d = 0,
13
14 #[doc(alias = "MTLTextureType1DArray")]
15 _1dArray = 1,
16
17 #[doc(alias = "MTLTextureType2D")]
18 _2d = 2,
19
20 #[doc(alias = "MTLTextureType2DArray")]
21 _2dArray = 3,
22
23 #[doc(alias = "MTLTextureType2DMultisample")]
24 _2dMultisample = 4,
25
26 #[doc(alias = "MTLTextureTypeCube")]
27 Cube = 5,
28
29 #[doc(alias = "MTLTextureTypeCubeArray")]
30 CubeArray = 6,
31
32 #[doc(alias = "MTLTextureType3D")]
33 _3d = 7,
34
35 #[doc(alias = "MTLTextureType2DMultisampleArray")]
36 _2dMultisampleArray = 8,
37
38 #[doc(alias = "MTLTextureTypeTextureBuffer")]
39 TextureBuffer = 9,
40}
41
42#[doc(alias = "MTLTextureSwizzle")]
43#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)]
44#[repr(u8)]
45pub enum Swizzle {
46 #[doc(alias = "MTLTextureSwizzleZero")]
47 Zero = 0,
48
49 #[doc(alias = "MTLTextureSwizzleOne")]
50 One = 1,
51
52 #[doc(alias = "MTLTextureSwizzleRed")]
53 Red = 2,
54
55 #[doc(alias = "MTLTextureSwizzleGreen")]
56 Green = 3,
57
58 #[doc(alias = "MTLTextureSwizzleBlue")]
59 Blue = 4,
60
61 #[doc(alias = "MTLTextureSwizzleAlpha")]
62 Alpha = 5,
63}
64
65#[doc(alias = "MTLTextureSwizzleChannels")]
66#[derive(Debug, Clone, Copy, PartialEq, Eq)]
67#[repr(C)]
68pub struct SwizzleChannels {
69 pub red: Swizzle,
70 pub green: Swizzle,
71 pub blue: Swizzle,
72 pub alpha: Swizzle,
73}
74
75impl Default for SwizzleChannels {
76 #[inline]
77 fn default() -> SwizzleChannels {
78 SwizzleChannels {
79 red: Swizzle::Red,
80 green: Swizzle::Green,
81 blue: Swizzle::Blue,
82 alpha: Swizzle::Alpha,
83 }
84 }
85}
86
87define_obj_type!(
88 #[doc(alias = "MTLSharedTextureHandle")]
89 pub SharedTextureHandle(ns::Id)
90);
91
92impl SharedTextureHandle {
93 #[objc::msg_send(device)]
94 pub fn device(&self) -> &mtl::Device;
95
96 #[objc::msg_send(label)]
97 pub fn label(&self) -> Option<&ns::String>;
98}
99
100define_opts!(
101 #[doc(alias = "MTLTextureUsage")]
102 pub Usage(usize)
103);
104
105impl Usage {
106 #[doc(alias = "MTLTextureUsageUnknown")]
107 pub const UNKNOWN: Self = Self(0x0000);
108
109 #[doc(alias = "MTLTextureUsageShaderRead")]
110 pub const SHADER_READ: Self = Self(0x0001);
111
112 #[doc(alias = "MTLTextureUsageShaderWrite")]
113 pub const SHADER_WRITE: Self = Self(0x0002);
114
115 #[doc(alias = "MTLTextureUsageRenderTarget")]
116 pub const RENDER_TARGET: Self = Self(0x0004);
117
118 #[doc(alias = "MTLTextureUsagePixelFormatView")]
119 pub const PIXEL_FORMAT_VIEW: Self = Self(0x0010);
120
121 #[doc(alias = "MTLTextureUsageShaderAtomic")]
122 pub const SHADER_ATOMIC: Self = Self(0x0020);
123
124 pub fn to_cf_number(&self) -> arc::R<cf::Number> {
125 cf::Number::from_i64(self.0 as _)
126 }
127
128 pub fn to_ns_number(&self) -> arc::R<ns::Number> {
129 ns::Number::with_i64(self.0 as _)
130 }
131}
132
133#[doc(alias = "MTLTextureCompressionType")]
134#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)]
135#[repr(usize)]
136pub enum Compression {
137 #[doc(alias = "MTLTextureCompressionTypeLossless")]
138 Lossless = 0,
139
140 #[doc(alias = "MTLTextureCompressionTypeLossy")]
141 Lossy = 1,
142}
143
144define_obj_type!(
145 #[doc(alias = "MTLTextureDescriptor")]
147 pub Desc(ns::Id),
148 MTL_TEXTURE_DESCRIPTOR
149);
150
151impl ns::Copying for Desc {}
152
153impl Desc {
154 #[objc::msg_send(texture2DDescriptorWithPixelFormat:width:height:mipmapped:)]
155 pub fn new_2d(
156 pixel_format: mtl::PixelFormat,
157 width: usize,
158 height: usize,
159 mipmapped: bool,
160 ) -> arc::R<Desc>;
161
162 #[objc::msg_send(textureCubeDescriptorWithPixelFormat:size:mipmapped:)]
171 pub fn new_cube(pixel_format: mtl::PixelFormat, size: usize, mipmapped: bool) -> arc::R<Desc>;
172
173 #[objc::msg_send(textureBufferDescriptorWithPixelFormat:width:resourceOptions:usage:)]
174 pub fn new_buff(
175 pixel_format: mtl::PixelFormat,
176 width: usize,
177 res_opts: mtl::resource::Opts,
178 usage: Usage,
179 ) -> arc::R<Desc>;
180
181 #[objc::msg_send(textureType)]
182 pub fn texture_type(&self) -> Type;
183
184 #[objc::msg_send(setTextureType:)]
185 pub fn set_texture_type(&mut self, val: Type);
186
187 #[inline]
188 pub fn with_texture_type(&mut self, val: Type) -> &mut Self {
189 self.set_texture_type(val);
190 self
191 }
192
193 #[objc::msg_send(pixelFormat)]
194 pub fn pixel_format(&self) -> mtl::PixelFormat;
195
196 #[objc::msg_send(setPixelFormat:)]
197 pub fn set_pixel_format(&mut self, val: mtl::PixelFormat);
198
199 define_mtl!(
206 width,
207 set_width,
208 height,
209 set_height,
210 depth,
211 set_depth,
212 res_opts,
213 set_res_opts,
214 cpu_cache_mode,
215 set_cpu_cache_mode,
216 storage_mode,
217 set_storage_mode,
218 hazard_tracking_mode,
219 set_hazard_tracking_mode
220 );
221
222 #[objc::msg_send(mipmapLevelCount)]
223 pub fn mipmap_level_count(&self) -> usize;
224
225 #[objc::msg_send(setMipmapLevelCount:)]
226 pub fn set_mipmap_level_count(&mut self, val: usize);
227
228 #[objc::msg_send(sampleCount)]
229 pub fn sample_count(&self) -> usize;
230
231 #[objc::msg_send(setSampleCount:)]
232 pub fn set_sample_count(&mut self, val: usize);
233
234 #[objc::msg_send(arrayLength)]
235 pub fn array_len(&self) -> usize;
236
237 #[objc::msg_send(setArrayLength:)]
238 pub fn set_array_len(&mut self, val: usize);
239
240 #[objc::msg_send(usage)]
241 pub fn usage(&self) -> Usage;
242
243 #[objc::msg_send(setUsage:)]
244 pub fn set_usage(&mut self, val: Usage);
245
246 #[objc::msg_send(allowGPUOptimizedContents)]
248 pub fn allow_gpu_optimized_contents(&self) -> bool;
249
250 #[objc::msg_send(setAllowGPUOptimizedContents:)]
251 pub fn set_allow_gpu_optimized_contents(&mut self, val: bool);
252
253 #[objc::msg_send(compressionType)]
254 pub fn compression_type(&self) -> Compression;
255
256 #[objc::msg_send(setCompressionType:)]
257 pub fn set_compression_type(&mut self, val: Compression);
258
259 #[objc::msg_send(swizzle)]
260 pub fn swizzle(&self) -> SwizzleChannels;
261
262 #[objc::msg_send(setSwizzle:)]
263 pub fn set_swizzle(&mut self, val: SwizzleChannels);
264}
265
266define_obj_type!(
267 #[doc(alias = "MTLTexture")]
269 pub Texture(mtl::Res)
270);
271
272impl Texture {
273 define_mtl!(width, height, depth, gpu_res_id);
274
275 #[objc::msg_send(parentTexture)]
278 pub fn parent_texture(&self) -> Option<&Texture>;
279
280 #[objc::msg_send(newTextureViewWithPixelFormat:)]
281 pub fn new_texture_view_with_pixel_format(
282 &self,
283 pixel_format: mtl::PixelFormat,
284 ) -> Option<arc::R<Texture>>;
285
286 #[objc::msg_send(buffer)]
289 pub fn buf(&self) -> Option<&mtl::Buf>;
290
291 #[objc::msg_send(bufferOffset)]
293 pub fn buf_offset(&self) -> usize;
294
295 #[objc::msg_send(bufferBytesPerRow)]
297 pub fn buf_bytes_per_row(&self) -> usize;
298
299 #[cfg(feature = "io_surface")]
300 #[objc::msg_send(iosurface)]
301 pub fn io_surf(&self) -> Option<&io::Surf>;
302
303 #[objc::msg_send(iosurfacePlane)]
304 pub fn io_surf_plane(&self) -> usize;
305
306 #[objc::msg_send(textureType)]
307 pub fn texture_type(&self) -> Type;
308
309 #[objc::msg_send(pixelFormat)]
310 pub fn pixel_format(&self) -> mtl::PixelFormat;
311
312 #[objc::msg_send(mipmapLevelCount)]
313 pub fn mipmap_level_count(&self) -> usize;
314
315 #[objc::msg_send(sampleCount)]
316 pub fn sample_count(&self) -> usize;
317
318 #[objc::msg_send(arrayLength)]
319 pub fn array_len(&self) -> usize;
320}
321
322unsafe extern "C" {
323 static MTL_TEXTURE_DESCRIPTOR: &'static objc::Class<Desc>;
324}
325
326#[cfg(test)]
327mod tests {
328 use crate::mtl;
329
330 #[test]
331 fn basics1() {
332 let mut td = mtl::TextureDesc::new_2d(mtl::PixelFormat::A8UNorm, 100, 200, false);
333
334 assert_eq!(td.texture_type(), mtl::TextureType::_2d);
335 assert_eq!(td.pixel_format(), mtl::PixelFormat::A8UNorm);
336 assert_eq!(td.width(), 100);
337 assert_eq!(td.height(), 200);
338 assert_eq!(td.depth(), 1);
339 assert_eq!(td.mipmap_level_count(), 1);
340 assert_eq!(td.sample_count(), 1);
341 assert_eq!(td.array_len(), 1);
342
343 td.set_width(200);
344 assert_eq!(td.width(), 200);
345
346 td.set_height(300);
347 assert_eq!(td.height(), 300);
348 }
349
350 #[test]
351 fn basics2() {
352 let td = mtl::TextureDesc::new_cube(mtl::PixelFormat::A8UNorm, 100, false);
353
354 assert_eq!(td.texture_type(), mtl::TextureType::Cube);
355 }
356
357 #[test]
358 fn basics3() {
359 let device = mtl::Device::sys_default().unwrap();
360
361 let td = mtl::TextureDesc::new_2d(mtl::PixelFormat::A8UNorm, 100, 200, false);
362
363 let t = device.new_texture(&td).unwrap();
364
365 assert_eq!(t.width(), 100);
366 assert_eq!(t.height(), 200);
367 assert_eq!(t.depth(), 1);
368 }
369
370 #[test]
371 fn basics4() {
372 let device = mtl::Device::sys_default().unwrap();
373
374 let td = mtl::TextureDesc::new_2d(mtl::PixelFormat::A8UNorm, 100, 200, false);
375
376 let t = device.new_texture(&td).unwrap();
377
378 assert!(t.parent_texture().is_none());
379 assert!(t.io_surf().is_none());
380 assert_eq!(t.texture_type(), mtl::texture::Type::_2d);
381 assert_eq!(t.pixel_format(), mtl::PixelFormat::A8UNorm);
382 assert!(t.io_surf().is_none());
383 assert_eq!(t.io_surf_plane(), 0);
384
385 let tv = t
386 .new_texture_view_with_pixel_format(mtl::PixelFormat::A8UNorm)
387 .unwrap();
388
389 assert!(tv.parent_texture().is_some());
390 assert_eq!(tv.width(), 100);
391 assert_eq!(tv.height(), 200);
392 }
393}