mtl-rs 0.2.1

Rust bindings for Apple's Metal API
use objc2::{Message, extern_protocol, msg_send, rc::Retained, runtime::ProtocolObject};
use objc2_foundation::{NSObjectProtocol, NSString};

use crate::{MTLBuffer, MTLCoordinate2D, MTLDevice, device::MTLSizeAndAlign, types::MTLSize};

extern_protocol!(
    /// Compiled read-only object that determines how variable rasterization rate is applied when rendering.
    ///
    /// # Safety
    ///
    /// Implementors must be valid Objective-C objects that conform to the
    /// `MTLRasterizationRateMap` protocol.
    #[expect(
        clippy::missing_safety_doc,
        reason = "extern_protocol does not attach this safety section to its generated unsafe trait"
    )]
    pub unsafe trait MTLRasterizationRateMap: NSObjectProtocol + Send + Sync {
        /// The device on which the rasterization rate map was created
        #[unsafe(method(device))]
        #[unsafe(method_family = none)]
        fn device(&self) -> Retained<ProtocolObject<dyn MTLDevice>>;

        /// The dimensions, in screen space pixels, of the region where variable rasterization is applied.
        #[unsafe(method(screenSize))]
        #[unsafe(method_family = none)]
        fn screen_size(&self) -> MTLSize;

        /// The granularity, in physical pixels, at which variable rasterization rate varies.
        #[unsafe(method(physicalGranularity))]
        #[unsafe(method_family = none)]
        fn physical_granularity(&self) -> MTLSize;

        /// The number of different configured layers in the rasterization map.
        #[unsafe(method(layerCount))]
        #[unsafe(method_family = none)]
        fn layer_count(&self) -> usize;

        /// Returns the size and alignment requirements of the parameter buffer for this rate map.
        #[unsafe(method(parameterBufferSizeAndAlign))]
        #[unsafe(method_family = none)]
        fn parameter_buffer_size_and_align(&self) -> MTLSizeAndAlign;

        /// Copy the parameter data into the provided buffer at the provided offset.
        #[unsafe(method(copyParameterDataToBuffer:offset:))]
        #[unsafe(method_family = none)]
        fn copy_parameter_data_to_buffer_offset(
            &self,
            buffer: &ProtocolObject<dyn MTLBuffer>,
            offset: usize,
        );

        /// Returns the physical render-target dimensions for a layer.
        #[unsafe(method(physicalSizeForLayer:))]
        #[unsafe(method_family = none)]
        fn physical_size_for_layer(
            &self,
            layer_index: usize,
        ) -> MTLSize;

        /// Computes screen to physical coordinates mapping for the given layer.
        #[unsafe(method(mapScreenToPhysicalCoordinates:forLayer:))]
        #[unsafe(method_family = none)]
        fn map_screen_to_physical_coordinates_for_layer(
            &self,
            screen_coordinates: MTLCoordinate2D,
            layer_index: usize,
        ) -> MTLCoordinate2D;

        /// Computes physical to screen coordinates mapping for the given layer.
        #[unsafe(method(mapPhysicalToScreenCoordinates:forLayer:))]
        #[unsafe(method_family = none)]
        fn map_physical_to_screen_coordinates_for_layer(
            &self,
            physical_coordinates: MTLCoordinate2D,
            layer_index: usize,
        ) -> MTLCoordinate2D;
    }
);

/// Rust-native accessors for a rasterization-rate map.
pub trait MTLRasterizationRateMapExt: MTLRasterizationRateMap + Message {
    /// A string that identifies this rasterization-rate map.
    fn label(&self) -> Option<String>
    where
        Self: Sized,
    {
        let label: Option<Retained<NSString>> = unsafe { msg_send![self, label] };
        label.map(|label| label.to_string())
    }
}

impl<T: MTLRasterizationRateMap + Message> MTLRasterizationRateMapExt for T {}