Skip to main content

mtl_gpu/pipeline/
color_attachment.rs

1//! Color attachment descriptors for render pipelines.
2//!
3//! Corresponds to `MTL::RenderPipelineColorAttachmentDescriptor`.
4
5use std::ffi::c_void;
6use std::ptr::NonNull;
7
8use mtl_foundation::{Referencing, UInteger};
9use mtl_sys::{msg_send_0, msg_send_1, sel};
10
11use crate::enums::{BlendFactor, BlendOperation, ColorWriteMask, PixelFormat};
12
13/// Describes the color attachment for a render pipeline.
14///
15/// C++ equivalent: `MTL::RenderPipelineColorAttachmentDescriptor`
16#[repr(transparent)]
17pub struct RenderPipelineColorAttachmentDescriptor(pub(crate) NonNull<c_void>);
18
19impl RenderPipelineColorAttachmentDescriptor {
20    /// Allocate a new color attachment descriptor.
21    ///
22    /// C++ equivalent: `static RenderPipelineColorAttachmentDescriptor* alloc()`
23    pub fn alloc() -> Option<Self> {
24        unsafe {
25            let class = mtl_sys::class!(MTLRenderPipelineColorAttachmentDescriptor);
26            let ptr: *mut c_void = msg_send_0(class.as_ptr(), sel!(alloc));
27            Self::from_raw(ptr)
28        }
29    }
30
31    /// Initialize the descriptor.
32    ///
33    /// C++ equivalent: `RenderPipelineColorAttachmentDescriptor* init()`
34    pub fn init(self) -> Option<Self> {
35        unsafe {
36            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(init));
37            std::mem::forget(self);
38            Self::from_raw(ptr)
39        }
40    }
41
42    /// Create a new color attachment descriptor.
43    pub fn new() -> Option<Self> {
44        Self::alloc().and_then(|d| d.init())
45    }
46
47    /// Create from a raw pointer.
48    ///
49    /// # Safety
50    ///
51    /// The pointer must be a valid color attachment descriptor object.
52    #[inline]
53    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
54        NonNull::new(ptr).map(Self)
55    }
56
57    /// Get the raw pointer.
58    #[inline]
59    pub fn as_raw(&self) -> *mut c_void {
60        self.0.as_ptr()
61    }
62
63    // =========================================================================
64    // Properties
65    // =========================================================================
66
67    /// Get the pixel format.
68    ///
69    /// C++ equivalent: `PixelFormat pixelFormat() const`
70    #[inline]
71    pub fn pixel_format(&self) -> PixelFormat {
72        unsafe { msg_send_0(self.as_ptr(), sel!(pixelFormat)) }
73    }
74
75    /// Set the pixel format.
76    ///
77    /// C++ equivalent: `void setPixelFormat(MTL::PixelFormat pixelFormat)`
78    #[inline]
79    pub fn set_pixel_format(&self, format: PixelFormat) {
80        unsafe {
81            msg_send_1::<(), PixelFormat>(self.as_ptr(), sel!(setPixelFormat:), format);
82        }
83    }
84
85    /// Check if blending is enabled.
86    ///
87    /// C++ equivalent: `bool isBlendingEnabled() const`
88    #[inline]
89    pub fn is_blending_enabled(&self) -> bool {
90        unsafe { msg_send_0(self.as_ptr(), sel!(isBlendingEnabled)) }
91    }
92
93    /// Set blending enabled.
94    ///
95    /// C++ equivalent: `void setBlendingEnabled(bool blendingEnabled)`
96    #[inline]
97    pub fn set_blending_enabled(&self, enabled: bool) {
98        unsafe {
99            msg_send_1::<(), bool>(self.as_ptr(), sel!(setBlendingEnabled:), enabled);
100        }
101    }
102
103    /// Get the source RGB blend factor.
104    ///
105    /// C++ equivalent: `BlendFactor sourceRGBBlendFactor() const`
106    #[inline]
107    pub fn source_rgb_blend_factor(&self) -> BlendFactor {
108        unsafe { msg_send_0(self.as_ptr(), sel!(sourceRGBBlendFactor)) }
109    }
110
111    /// Set the source RGB blend factor.
112    ///
113    /// C++ equivalent: `void setSourceRGBBlendFactor(MTL::BlendFactor sourceRGBBlendFactor)`
114    #[inline]
115    pub fn set_source_rgb_blend_factor(&self, factor: BlendFactor) {
116        unsafe {
117            msg_send_1::<(), BlendFactor>(self.as_ptr(), sel!(setSourceRGBBlendFactor:), factor);
118        }
119    }
120
121    /// Get the destination RGB blend factor.
122    ///
123    /// C++ equivalent: `BlendFactor destinationRGBBlendFactor() const`
124    #[inline]
125    pub fn destination_rgb_blend_factor(&self) -> BlendFactor {
126        unsafe { msg_send_0(self.as_ptr(), sel!(destinationRGBBlendFactor)) }
127    }
128
129    /// Set the destination RGB blend factor.
130    ///
131    /// C++ equivalent: `void setDestinationRGBBlendFactor(MTL::BlendFactor destinationRGBBlendFactor)`
132    #[inline]
133    pub fn set_destination_rgb_blend_factor(&self, factor: BlendFactor) {
134        unsafe {
135            msg_send_1::<(), BlendFactor>(
136                self.as_ptr(),
137                sel!(setDestinationRGBBlendFactor:),
138                factor,
139            );
140        }
141    }
142
143    /// Get the RGB blend operation.
144    ///
145    /// C++ equivalent: `BlendOperation rgbBlendOperation() const`
146    #[inline]
147    pub fn rgb_blend_operation(&self) -> BlendOperation {
148        unsafe { msg_send_0(self.as_ptr(), sel!(rgbBlendOperation)) }
149    }
150
151    /// Set the RGB blend operation.
152    ///
153    /// C++ equivalent: `void setRgbBlendOperation(MTL::BlendOperation rgbBlendOperation)`
154    #[inline]
155    pub fn set_rgb_blend_operation(&self, operation: BlendOperation) {
156        unsafe {
157            msg_send_1::<(), BlendOperation>(self.as_ptr(), sel!(setRgbBlendOperation:), operation);
158        }
159    }
160
161    /// Get the source alpha blend factor.
162    ///
163    /// C++ equivalent: `BlendFactor sourceAlphaBlendFactor() const`
164    #[inline]
165    pub fn source_alpha_blend_factor(&self) -> BlendFactor {
166        unsafe { msg_send_0(self.as_ptr(), sel!(sourceAlphaBlendFactor)) }
167    }
168
169    /// Set the source alpha blend factor.
170    ///
171    /// C++ equivalent: `void setSourceAlphaBlendFactor(MTL::BlendFactor sourceAlphaBlendFactor)`
172    #[inline]
173    pub fn set_source_alpha_blend_factor(&self, factor: BlendFactor) {
174        unsafe {
175            msg_send_1::<(), BlendFactor>(self.as_ptr(), sel!(setSourceAlphaBlendFactor:), factor);
176        }
177    }
178
179    /// Get the destination alpha blend factor.
180    ///
181    /// C++ equivalent: `BlendFactor destinationAlphaBlendFactor() const`
182    #[inline]
183    pub fn destination_alpha_blend_factor(&self) -> BlendFactor {
184        unsafe { msg_send_0(self.as_ptr(), sel!(destinationAlphaBlendFactor)) }
185    }
186
187    /// Set the destination alpha blend factor.
188    ///
189    /// C++ equivalent: `void setDestinationAlphaBlendFactor(MTL::BlendFactor destinationAlphaBlendFactor)`
190    #[inline]
191    pub fn set_destination_alpha_blend_factor(&self, factor: BlendFactor) {
192        unsafe {
193            msg_send_1::<(), BlendFactor>(
194                self.as_ptr(),
195                sel!(setDestinationAlphaBlendFactor:),
196                factor,
197            );
198        }
199    }
200
201    /// Get the alpha blend operation.
202    ///
203    /// C++ equivalent: `BlendOperation alphaBlendOperation() const`
204    #[inline]
205    pub fn alpha_blend_operation(&self) -> BlendOperation {
206        unsafe { msg_send_0(self.as_ptr(), sel!(alphaBlendOperation)) }
207    }
208
209    /// Set the alpha blend operation.
210    ///
211    /// C++ equivalent: `void setAlphaBlendOperation(MTL::BlendOperation alphaBlendOperation)`
212    #[inline]
213    pub fn set_alpha_blend_operation(&self, operation: BlendOperation) {
214        unsafe {
215            msg_send_1::<(), BlendOperation>(
216                self.as_ptr(),
217                sel!(setAlphaBlendOperation:),
218                operation,
219            );
220        }
221    }
222
223    /// Get the color write mask.
224    ///
225    /// C++ equivalent: `ColorWriteMask writeMask() const`
226    #[inline]
227    pub fn write_mask(&self) -> ColorWriteMask {
228        unsafe { msg_send_0(self.as_ptr(), sel!(writeMask)) }
229    }
230
231    /// Set the color write mask.
232    ///
233    /// C++ equivalent: `void setWriteMask(MTL::ColorWriteMask writeMask)`
234    #[inline]
235    pub fn set_write_mask(&self, mask: ColorWriteMask) {
236        unsafe {
237            msg_send_1::<(), ColorWriteMask>(self.as_ptr(), sel!(setWriteMask:), mask);
238        }
239    }
240}
241
242impl Clone for RenderPipelineColorAttachmentDescriptor {
243    fn clone(&self) -> Self {
244        unsafe {
245            let ptr: *mut c_void = msg_send_0(self.as_ptr(), sel!(copy));
246            Self::from_raw(ptr).expect("copy returned null")
247        }
248    }
249}
250
251impl Drop for RenderPipelineColorAttachmentDescriptor {
252    fn drop(&mut self) {
253        unsafe {
254            msg_send_0::<()>(self.as_ptr(), sel!(release));
255        }
256    }
257}
258
259impl Default for RenderPipelineColorAttachmentDescriptor {
260    fn default() -> Self {
261        Self::new().expect("failed to create color attachment descriptor")
262    }
263}
264
265impl Referencing for RenderPipelineColorAttachmentDescriptor {
266    #[inline]
267    fn as_ptr(&self) -> *const c_void {
268        self.0.as_ptr()
269    }
270}
271
272unsafe impl Send for RenderPipelineColorAttachmentDescriptor {}
273unsafe impl Sync for RenderPipelineColorAttachmentDescriptor {}
274
275impl std::fmt::Debug for RenderPipelineColorAttachmentDescriptor {
276    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
277        f.debug_struct("RenderPipelineColorAttachmentDescriptor")
278            .field("pixel_format", &self.pixel_format())
279            .field("is_blending_enabled", &self.is_blending_enabled())
280            .finish()
281    }
282}
283
284// ============================================================================
285// Render Pipeline Color Attachment Descriptor Array
286// ============================================================================
287
288/// Array of color attachment descriptors.
289///
290/// C++ equivalent: `MTL::RenderPipelineColorAttachmentDescriptorArray`
291#[repr(transparent)]
292pub struct RenderPipelineColorAttachmentDescriptorArray(pub(crate) NonNull<c_void>);
293
294impl RenderPipelineColorAttachmentDescriptorArray {
295    /// Create from a raw pointer.
296    ///
297    /// # Safety
298    ///
299    /// The pointer must be a valid color attachment descriptor array object.
300    #[inline]
301    pub unsafe fn from_raw(ptr: *mut c_void) -> Option<Self> {
302        NonNull::new(ptr).map(Self)
303    }
304
305    /// Get the raw pointer.
306    #[inline]
307    pub fn as_raw(&self) -> *mut c_void {
308        self.0.as_ptr()
309    }
310
311    /// Get the color attachment descriptor at the given index.
312    ///
313    /// C++ equivalent: `RenderPipelineColorAttachmentDescriptor* object(NS::UInteger attachmentIndex)`
314    pub fn object(&self, index: UInteger) -> Option<RenderPipelineColorAttachmentDescriptor> {
315        unsafe {
316            let ptr: *mut c_void =
317                msg_send_1(self.as_ptr(), sel!(objectAtIndexedSubscript:), index);
318            if ptr.is_null() {
319                return None;
320            }
321            // Retain because it's an internal reference
322            let _: *mut c_void = msg_send_0(ptr, sel!(retain));
323            RenderPipelineColorAttachmentDescriptor::from_raw(ptr)
324        }
325    }
326
327    /// Set the color attachment descriptor at the given index.
328    ///
329    /// C++ equivalent: `void setObject(const MTL::RenderPipelineColorAttachmentDescriptor* attachment, NS::UInteger attachmentIndex)`
330    pub fn set_object(
331        &self,
332        attachment: &RenderPipelineColorAttachmentDescriptor,
333        index: UInteger,
334    ) {
335        unsafe {
336            mtl_sys::msg_send_2::<(), *const c_void, UInteger>(
337                self.as_ptr(),
338                sel!(setObject: atIndexedSubscript:),
339                attachment.as_ptr(),
340                index,
341            );
342        }
343    }
344}
345
346impl Referencing for RenderPipelineColorAttachmentDescriptorArray {
347    #[inline]
348    fn as_ptr(&self) -> *const c_void {
349        self.0.as_ptr()
350    }
351}
352
353unsafe impl Send for RenderPipelineColorAttachmentDescriptorArray {}
354unsafe impl Sync for RenderPipelineColorAttachmentDescriptorArray {}