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::VisibilityResultType;
10use crate::types::SamplePosition;
11
12use super::{
13 RenderPassColorAttachmentDescriptorArray, RenderPassDepthAttachmentDescriptor,
14 RenderPassStencilAttachmentDescriptor,
15};
16
17#[repr(transparent)]
21pub struct RenderPassDescriptor(NonNull<c_void>);
22
23impl RenderPassDescriptor {
24 #[inline]
30 pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
31 NonNull::new(ptr).map(Self)
32 }
33
34 #[inline]
36 pub fn as_raw(&self) -> *mut c_void {
37 self.0.as_ptr()
38 }
39
40 pub fn new() -> Option<Self> {
44 unsafe {
45 let class = mtl_sys::class!(MTLRenderPassDescriptor);
46 let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(renderPassDescriptor));
47 if ptr.is_null() {
48 return None;
49 }
50 let _: *mut c_void = msg_send_0(ptr, sel!(retain));
51 Self::from_raw(ptr)
52 }
53 }
54
55 pub fn color_attachments(&self) -> Option<RenderPassColorAttachmentDescriptorArray> {
63 unsafe {
64 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(colorAttachments));
65 RenderPassColorAttachmentDescriptorArray::from_raw(ptr)
66 }
67 }
68
69 pub fn depth_attachment(&self) -> Option<RenderPassDepthAttachmentDescriptor> {
77 unsafe {
78 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(depthAttachment));
79 RenderPassDepthAttachmentDescriptor::from_raw(ptr)
80 }
81 }
82
83 pub fn set_depth_attachment(&self, attachment: Option<&RenderPassDepthAttachmentDescriptor>) {
87 unsafe {
88 let ptr = attachment.map_or(std::ptr::null(), |a| a.as_ptr());
89 msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setDepthAttachment:), ptr);
90 }
91 }
92
93 pub fn stencil_attachment(&self) -> Option<RenderPassStencilAttachmentDescriptor> {
101 unsafe {
102 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(stencilAttachment));
103 RenderPassStencilAttachmentDescriptor::from_raw(ptr)
104 }
105 }
106
107 pub fn set_stencil_attachment(
111 &self,
112 attachment: Option<&RenderPassStencilAttachmentDescriptor>,
113 ) {
114 unsafe {
115 let ptr = attachment.map_or(std::ptr::null(), |a| a.as_ptr());
116 msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setStencilAttachment:), ptr);
117 }
118 }
119
120 pub fn visibility_result_buffer(&self) -> Option<crate::Buffer> {
128 unsafe {
129 let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(visibilityResultBuffer));
130 if ptr.is_null() {
131 return None;
132 }
133 let _: *mut c_void = msg_send_0(ptr, sel!(retain));
134 crate::Buffer::from_raw(ptr)
135 }
136 }
137
138 pub fn set_visibility_result_buffer(&self, buffer: Option<&crate::Buffer>) {
142 unsafe {
143 let ptr = buffer.map_or(std::ptr::null(), |b| b.as_ptr());
144 msg_send_1::<(), *const c_void>(self.as_ptr(), sel!(setVisibilityResultBuffer:), ptr);
145 }
146 }
147
148 #[inline]
152 pub fn visibility_result_type(&self) -> VisibilityResultType {
153 unsafe { msg_send_0(self.as_ptr(), sel!(visibilityResultType)) }
154 }
155
156 #[inline]
160 pub fn set_visibility_result_type(&self, result_type: VisibilityResultType) {
161 unsafe {
162 msg_send_1::<(), VisibilityResultType>(
163 self.as_ptr(),
164 sel!(setVisibilityResultType:),
165 result_type,
166 );
167 }
168 }
169
170 #[inline]
178 pub fn render_target_width(&self) -> UInteger {
179 unsafe { msg_send_0(self.as_ptr(), sel!(renderTargetWidth)) }
180 }
181
182 #[inline]
186 pub fn set_render_target_width(&self, width: UInteger) {
187 unsafe {
188 msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setRenderTargetWidth:), width);
189 }
190 }
191
192 #[inline]
196 pub fn render_target_height(&self) -> UInteger {
197 unsafe { msg_send_0(self.as_ptr(), sel!(renderTargetHeight)) }
198 }
199
200 #[inline]
204 pub fn set_render_target_height(&self, height: UInteger) {
205 unsafe {
206 msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setRenderTargetHeight:), height);
207 }
208 }
209
210 #[inline]
214 pub fn render_target_array_length(&self) -> UInteger {
215 unsafe { msg_send_0(self.as_ptr(), sel!(renderTargetArrayLength)) }
216 }
217
218 #[inline]
222 pub fn set_render_target_array_length(&self, length: UInteger) {
223 unsafe {
224 msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setRenderTargetArrayLength:), length);
225 }
226 }
227
228 #[inline]
236 pub fn default_raster_sample_count(&self) -> UInteger {
237 unsafe { msg_send_0(self.as_ptr(), sel!(defaultRasterSampleCount)) }
238 }
239
240 #[inline]
244 pub fn set_default_raster_sample_count(&self, count: UInteger) {
245 unsafe {
246 msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setDefaultRasterSampleCount:), count);
247 }
248 }
249
250 pub fn set_sample_positions(&self, positions: &[SamplePosition]) {
254 unsafe {
255 mtl_sys::msg_send_2::<(), *const SamplePosition, UInteger>(
256 self.as_ptr(),
257 sel!(setSamplePositions: count:),
258 positions.as_ptr(),
259 positions.len() as UInteger,
260 );
261 }
262 }
263
264 pub fn get_sample_positions(&self, positions: &mut [SamplePosition]) -> UInteger {
268 unsafe {
269 mtl_sys::msg_send_2(
270 self.as_ptr(),
271 sel!(getSamplePositions: count:),
272 positions.as_mut_ptr(),
273 positions.len() as UInteger,
274 )
275 }
276 }
277
278 #[inline]
286 pub fn tile_width(&self) -> UInteger {
287 unsafe { msg_send_0(self.as_ptr(), sel!(tileWidth)) }
288 }
289
290 #[inline]
294 pub fn set_tile_width(&self, width: UInteger) {
295 unsafe {
296 msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setTileWidth:), width);
297 }
298 }
299
300 #[inline]
304 pub fn tile_height(&self) -> UInteger {
305 unsafe { msg_send_0(self.as_ptr(), sel!(tileHeight)) }
306 }
307
308 #[inline]
312 pub fn set_tile_height(&self, height: UInteger) {
313 unsafe {
314 msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setTileHeight:), height);
315 }
316 }
317
318 #[inline]
322 pub fn threadgroup_memory_length(&self) -> UInteger {
323 unsafe { msg_send_0(self.as_ptr(), sel!(threadgroupMemoryLength)) }
324 }
325
326 #[inline]
330 pub fn set_threadgroup_memory_length(&self, length: UInteger) {
331 unsafe {
332 msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setThreadgroupMemoryLength:), length);
333 }
334 }
335
336 #[inline]
340 pub fn imageblock_sample_length(&self) -> UInteger {
341 unsafe { msg_send_0(self.as_ptr(), sel!(imageblockSampleLength)) }
342 }
343
344 #[inline]
348 pub fn set_imageblock_sample_length(&self, length: UInteger) {
349 unsafe {
350 msg_send_1::<(), UInteger>(self.as_ptr(), sel!(setImageblockSampleLength:), length);
351 }
352 }
353
354 pub fn rasterization_rate_map(&self) -> *mut c_void {
364 unsafe { msg_send_0(self.as_ptr(), sel!(rasterizationRateMap)) }
365 }
366
367 pub unsafe fn set_rasterization_rate_map(&self, rate_map: *const c_void) {
375 unsafe {
376 msg_send_1::<(), *const c_void>(
377 self.as_ptr(),
378 sel!(setRasterizationRateMap:),
379 rate_map,
380 );
381 }
382 }
383
384 #[inline]
392 pub fn support_color_attachment_mapping(&self) -> bool {
393 unsafe { msg_send_0(self.as_ptr(), sel!(supportColorAttachmentMapping)) }
394 }
395
396 #[inline]
400 pub fn set_support_color_attachment_mapping(&self, support: bool) {
401 unsafe {
402 msg_send_1::<(), bool>(
403 self.as_ptr(),
404 sel!(setSupportColorAttachmentMapping:),
405 support,
406 );
407 }
408 }
409}
410
411impl Default for RenderPassDescriptor {
412 fn default() -> Self {
413 Self::new().expect("failed to create RenderPassDescriptor")
414 }
415}
416
417impl Clone for RenderPassDescriptor {
418 fn clone(&self) -> Self {
419 unsafe {
420 msg_send_0::<*mut c_void>(self.as_ptr(), sel!(retain));
421 }
422 Self(self.0)
423 }
424}
425
426impl Drop for RenderPassDescriptor {
427 fn drop(&mut self) {
428 unsafe {
429 msg_send_0::<()>(self.as_ptr(), sel!(release));
430 }
431 }
432}
433
434impl Referencing for RenderPassDescriptor {
435 #[inline]
436 fn as_ptr(&self) -> *const c_void {
437 self.0.as_ptr()
438 }
439}
440
441unsafe impl Send for RenderPassDescriptor {}
442unsafe impl Sync for RenderPassDescriptor {}
443
444impl std::fmt::Debug for RenderPassDescriptor {
445 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
446 f.debug_struct("RenderPassDescriptor")
447 .field("render_target_width", &self.render_target_width())
448 .field("render_target_height", &self.render_target_height())
449 .field(
450 "default_raster_sample_count",
451 &self.default_raster_sample_count(),
452 )
453 .finish()
454 }
455}