1use std::ffi::c_void;
4use std::ptr::NonNull;
5
6use mtl_foundation::{Referencing, UInteger};
7use mtl_sys::{msg_send_0, msg_send_1, sel};
8
9use crate::enums::{
10 CPUCacheMode, HazardTrackingMode, PixelFormat, ResourceOptions, SparsePageSize, StorageMode,
11 TextureCompressionType, TextureSwizzleChannels, TextureType, TextureUsage,
12};
13
14#[repr(transparent)]
18pub struct TextureDescriptor(pub(crate) NonNull<c_void>);
19
20impl TextureDescriptor {
21 pub fn new() -> Option<Self> {
25 unsafe {
26 let class = mtl_sys::Class::get("MTLTextureDescriptor")?;
27 let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
28 if ptr.is_null() {
29 return None;
30 }
31 let ptr: *mut c_void = msg_send_0(ptr, sel!(init));
32 Self::from_raw(ptr)
33 }
34 }
35
36 pub fn texture_2d_descriptor(
40 pixel_format: PixelFormat,
41 width: UInteger,
42 height: UInteger,
43 mipmapped: bool,
44 ) -> Option<Self> {
45 unsafe {
46 let class = mtl_sys::Class::get("MTLTextureDescriptor")?;
47 let ptr: *mut c_void = mtl_sys::msg_send_4(
48 class.as_ptr(),
49 sel!(texture2DDescriptorWithPixelFormat: width: height: mipmapped:),
50 pixel_format,
51 width,
52 height,
53 mipmapped,
54 );
55 if ptr.is_null() {
56 return None;
57 }
58 let _: *mut c_void = msg_send_0(ptr, sel!(retain));
60 Self::from_raw(ptr)
61 }
62 }
63
64 pub fn texture_cube_descriptor(
68 pixel_format: PixelFormat,
69 size: UInteger,
70 mipmapped: bool,
71 ) -> Option<Self> {
72 unsafe {
73 let class = mtl_sys::Class::get("MTLTextureDescriptor")?;
74 let ptr: *mut c_void = mtl_sys::msg_send_3(
75 class.as_ptr(),
76 sel!(textureCubeDescriptorWithPixelFormat: size: mipmapped:),
77 pixel_format,
78 size,
79 mipmapped,
80 );
81 if ptr.is_null() {
82 return None;
83 }
84 let _: *mut c_void = msg_send_0(ptr, sel!(retain));
86 Self::from_raw(ptr)
87 }
88 }
89
90 pub fn texture_buffer_descriptor(
94 pixel_format: PixelFormat,
95 width: UInteger,
96 resource_options: ResourceOptions,
97 usage: TextureUsage,
98 ) -> Option<Self> {
99 unsafe {
100 let class = mtl_sys::Class::get("MTLTextureDescriptor")?;
101 let ptr: *mut c_void = mtl_sys::msg_send_4(
102 class.as_ptr(),
103 sel!(textureBufferDescriptorWithPixelFormat: width: resourceOptions: usage:),
104 pixel_format,
105 width,
106 resource_options,
107 usage,
108 );
109 if ptr.is_null() {
110 return None;
111 }
112 let _: *mut c_void = msg_send_0(ptr, sel!(retain));
114 Self::from_raw(ptr)
115 }
116 }
117
118 #[inline]
124 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
125 NonNull::new(ptr).map(Self)
126 }
127
128 #[inline]
130 pub fn as_raw(&self) -> *mut c_void {
131 self.0.as_ptr()
132 }
133
134 #[inline]
140 pub fn texture_type(&self) -> TextureType {
141 unsafe { msg_send_0(self.as_ptr(), sel!(textureType)) }
142 }
143
144 #[inline]
146 pub fn pixel_format(&self) -> PixelFormat {
147 unsafe { msg_send_0(self.as_ptr(), sel!(pixelFormat)) }
148 }
149
150 #[inline]
152 pub fn width(&self) -> UInteger {
153 unsafe { msg_send_0(self.as_ptr(), sel!(width)) }
154 }
155
156 #[inline]
158 pub fn height(&self) -> UInteger {
159 unsafe { msg_send_0(self.as_ptr(), sel!(height)) }
160 }
161
162 #[inline]
164 pub fn depth(&self) -> UInteger {
165 unsafe { msg_send_0(self.as_ptr(), sel!(depth)) }
166 }
167
168 #[inline]
170 pub fn mipmap_level_count(&self) -> UInteger {
171 unsafe { msg_send_0(self.as_ptr(), sel!(mipmapLevelCount)) }
172 }
173
174 #[inline]
176 pub fn sample_count(&self) -> UInteger {
177 unsafe { msg_send_0(self.as_ptr(), sel!(sampleCount)) }
178 }
179
180 #[inline]
182 pub fn array_length(&self) -> UInteger {
183 unsafe { msg_send_0(self.as_ptr(), sel!(arrayLength)) }
184 }
185
186 #[inline]
188 pub fn storage_mode(&self) -> StorageMode {
189 unsafe { msg_send_0(self.as_ptr(), sel!(storageMode)) }
190 }
191
192 #[inline]
194 pub fn cpu_cache_mode(&self) -> CPUCacheMode {
195 unsafe { msg_send_0(self.as_ptr(), sel!(cpuCacheMode)) }
196 }
197
198 #[inline]
200 pub fn hazard_tracking_mode(&self) -> HazardTrackingMode {
201 unsafe { msg_send_0(self.as_ptr(), sel!(hazardTrackingMode)) }
202 }
203
204 #[inline]
206 pub fn resource_options(&self) -> ResourceOptions {
207 unsafe { msg_send_0(self.as_ptr(), sel!(resourceOptions)) }
208 }
209
210 #[inline]
212 pub fn usage(&self) -> TextureUsage {
213 unsafe { msg_send_0(self.as_ptr(), sel!(usage)) }
214 }
215
216 #[inline]
218 pub fn allow_gpu_optimized_contents(&self) -> bool {
219 unsafe { msg_send_0(self.as_ptr(), sel!(allowGPUOptimizedContents)) }
220 }
221
222 #[inline]
224 pub fn compression_type(&self) -> TextureCompressionType {
225 unsafe { msg_send_0(self.as_ptr(), sel!(compressionType)) }
226 }
227
228 #[inline]
230 pub fn swizzle(&self) -> TextureSwizzleChannels {
231 unsafe { msg_send_0(self.as_ptr(), sel!(swizzle)) }
232 }
233
234 #[inline]
236 pub fn placement_sparse_page_size(&self) -> SparsePageSize {
237 unsafe { msg_send_0(self.as_ptr(), sel!(placementSparsePageSize)) }
238 }
239
240 #[inline]
246 pub fn set_texture_type(&self, texture_type: TextureType) {
247 unsafe {
248 msg_send_1::<(), TextureType>(self.as_ptr(), sel!(setTextureType:), texture_type);
249 }
250 }
251
252 #[inline]
254 pub fn set_pixel_format(&self, pixel_format: PixelFormat) {
255 unsafe {
256 msg_send_1::<(), PixelFormat>(self.as_ptr(), sel!(setPixelFormat:), pixel_format);
257 }
258 }
259
260 #[inline]
262 pub fn set_width(&self, width: UInteger) {
263 unsafe {
264 msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setWidth:), width);
265 }
266 }
267
268 #[inline]
270 pub fn set_height(&self, height: UInteger) {
271 unsafe {
272 msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setHeight:), height);
273 }
274 }
275
276 #[inline]
278 pub fn set_depth(&self, depth: UInteger) {
279 unsafe {
280 msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setDepth:), depth);
281 }
282 }
283
284 #[inline]
286 pub fn set_mipmap_level_count(&self, count: UInteger) {
287 unsafe {
288 msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setMipmapLevelCount:), count);
289 }
290 }
291
292 #[inline]
294 pub fn set_sample_count(&self, count: UInteger) {
295 unsafe {
296 msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setSampleCount:), count);
297 }
298 }
299
300 #[inline]
302 pub fn set_array_length(&self, length: UInteger) {
303 unsafe {
304 msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setArrayLength:), length);
305 }
306 }
307
308 #[inline]
310 pub fn set_storage_mode(&self, mode: StorageMode) {
311 unsafe {
312 msg_send_1::<(), StorageMode>(self.as_ptr(), sel!(setStorageMode:), mode);
313 }
314 }
315
316 #[inline]
318 pub fn set_cpu_cache_mode(&self, mode: CPUCacheMode) {
319 unsafe {
320 msg_send_1::<(), CPUCacheMode>(self.as_ptr(), sel!(setCpuCacheMode:), mode);
321 }
322 }
323
324 #[inline]
326 pub fn set_hazard_tracking_mode(&self, mode: HazardTrackingMode) {
327 unsafe {
328 msg_send_1::<(), HazardTrackingMode>(self.as_ptr(), sel!(setHazardTrackingMode:), mode);
329 }
330 }
331
332 #[inline]
334 pub fn set_resource_options(&self, options: ResourceOptions) {
335 unsafe {
336 msg_send_1::<(), ResourceOptions>(self.as_ptr(), sel!(setResourceOptions:), options);
337 }
338 }
339
340 #[inline]
342 pub fn set_usage(&self, usage: TextureUsage) {
343 unsafe {
344 msg_send_1::<(), TextureUsage>(self.as_ptr(), sel!(setUsage:), usage);
345 }
346 }
347
348 #[inline]
350 pub fn set_allow_gpu_optimized_contents(&self, allow: bool) {
351 unsafe {
352 msg_send_1::<(), bool>(self.as_ptr(), sel!(setAllowGPUOptimizedContents:), allow);
353 }
354 }
355
356 #[inline]
358 pub fn set_compression_type(&self, compression_type: TextureCompressionType) {
359 unsafe {
360 msg_send_1::<(), TextureCompressionType>(
361 self.as_ptr(),
362 sel!(setCompressionType:),
363 compression_type,
364 );
365 }
366 }
367
368 #[inline]
370 pub fn set_swizzle(&self, swizzle: TextureSwizzleChannels) {
371 unsafe {
372 msg_send_1::<(), TextureSwizzleChannels>(self.as_ptr(), sel!(setSwizzle:), swizzle);
373 }
374 }
375
376 #[inline]
378 pub fn set_placement_sparse_page_size(&self, size: SparsePageSize) {
379 unsafe {
380 msg_send_1::<(), SparsePageSize>(
381 self.as_ptr(),
382 sel!(setPlacementSparsePageSize:),
383 size,
384 );
385 }
386 }
387}
388
389impl Default for TextureDescriptor {
390 fn default() -> Self {
391 Self::new().expect("failed to create texture descriptor")
392 }
393}
394
395impl Clone for TextureDescriptor {
396 fn clone(&self) -> Self {
397 unsafe {
398 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
399 Self::from_raw(ptr).expect("failed to copy texture descriptor")
400 }
401 }
402}
403
404impl Drop for TextureDescriptor {
405 fn drop(&mut self) {
406 unsafe {
407 msg_send_0::<()>(self.as_ptr(), sel!(release));
408 }
409 }
410}
411
412impl Referencing for TextureDescriptor {
413 #[inline]
414 fn as_ptr(&self) -> *const c_void {
415 self.0.as_ptr()
416 }
417}
418
419unsafe impl Send for TextureDescriptor {}
420unsafe impl Sync for TextureDescriptor {}
421
422impl std::fmt::Debug for TextureDescriptor {
423 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
424 f.debug_struct("TextureDescriptor")
425 .field("texture_type", &self.texture_type())
426 .field("pixel_format", &self.pixel_format())
427 .field("width", &self.width())
428 .field("height", &self.height())
429 .field("depth", &self.depth())
430 .finish()
431 }
432}