1use crate::{
2 ffi, texture_usage, util::take_optional_string, MetalDevice, MetalFunction, TextureDescriptor,
3};
4use core::ffi::c_void;
5
6pub mod primitive_type {
8 pub const POINT: usize = 0;
10 pub const LINE: usize = 1;
12 pub const LINE_STRIP: usize = 2;
14 pub const TRIANGLE: usize = 3;
16 pub const TRIANGLE_STRIP: usize = 4;
18}
19
20pub mod load_action {
22 pub const DONT_CARE: usize = 0;
24 pub const LOAD: usize = 1;
26 pub const CLEAR: usize = 2;
28}
29
30pub mod store_action {
32 pub const DONT_CARE: usize = 0;
34 pub const STORE: usize = 1;
36 pub const MULTISAMPLE_RESOLVE: usize = 2;
38 pub const STORE_AND_MULTISAMPLE_RESOLVE: usize = 3;
40}
41
42pub struct RenderPipelineState {
44 ptr: *mut c_void,
45}
46
47unsafe impl Send for RenderPipelineState {}
50unsafe impl Sync for RenderPipelineState {}
51
52impl Drop for RenderPipelineState {
53 fn drop(&mut self) {
54 if !self.ptr.is_null() {
55 unsafe { ffi::am_object_release(self.ptr) };
56 self.ptr = core::ptr::null_mut();
57 }
58 }
59}
60
61impl RenderPipelineState {
62 #[must_use]
64 pub const fn as_ptr(&self) -> *mut c_void {
65 self.ptr
66 }
67
68 fn wrap(ptr: *mut c_void) -> Option<Self> {
69 if ptr.is_null() {
70 None
71 } else {
72 Some(Self { ptr })
73 }
74 }
75
76 pub(crate) const unsafe fn from_retained_ptr(ptr: *mut c_void) -> Self {
77 Self { ptr }
78 }
79
80 #[must_use]
82 pub fn label(&self) -> Option<String> {
83 unsafe { take_optional_string(ffi::am_object_copy_label(self.ptr)) }
84 }
85}
86
87impl MetalDevice {
88 pub fn new_render_pipeline_state(
94 &self,
95 vertex: &MetalFunction,
96 fragment: &MetalFunction,
97 color_pixel_format: usize,
98 sample_count: usize,
99 ) -> Result<RenderPipelineState, String> {
100 let mut err: *mut core::ffi::c_char = core::ptr::null_mut();
101 let ptr = unsafe {
102 ffi::am_device_new_render_pipeline_state(
103 self.as_ptr(),
104 vertex.as_ptr(),
105 fragment.as_ptr(),
106 color_pixel_format,
107 sample_count,
108 &mut err,
109 )
110 };
111 RenderPipelineState::wrap(ptr).ok_or_else(|| unsafe {
112 take_optional_string(err)
113 .unwrap_or_else(|| "MTLDevice.makeRenderPipelineState returned nil".to_string())
114 })
115 }
116}
117
118impl TextureDescriptor {
119 #[must_use]
121 pub const fn render_target_2d(width: usize, height: usize, pixel_format: usize) -> Self {
122 Self {
123 pixel_format,
124 width,
125 height,
126 mipmapped: false,
127 usage: texture_usage::RENDER_TARGET | texture_usage::SHADER_READ,
128 storage_mode: crate::storage_mode::PRIVATE,
129 }
130 }
131}