//! This file has been automatically generated by `objc2`'s `header-translator`.
//! DO NOT EDIT
use core::ffi::*;
use core::ptr::NonNull;
use objc2::__framework_prelude::*;
use objc2_foundation::*;

use crate::*;

extern_class!(
    /// A helper object for convient access to samples stored in an array.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtlrasterizationratesamplearray?language=objc)
    #[unsafe(super(NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct MTLRasterizationRateSampleArray;
);

extern_conformance!(
    unsafe impl NSObjectProtocol for MTLRasterizationRateSampleArray {}
);

impl MTLRasterizationRateSampleArray {
    extern_methods!(
        /// Retrieves the sample value at the specified index.
        ///
        /// Returns: NSNumber instance describing the value of the sample at the specified index, or 0 if the index is out of range.
        ///
        /// # Safety
        ///
        /// `index` might not be bounds-checked.
        #[unsafe(method(objectAtIndexedSubscript:))]
        #[unsafe(method_family = none)]
        pub unsafe fn objectAtIndexedSubscript(&self, index: NSUInteger) -> Retained<NSNumber>;

        /// Stores a sample value at the specified index.
        ///
        /// The value will be converted to a single precision floating point value.
        ///
        /// # Safety
        ///
        /// `index` might not be bounds-checked.
        #[unsafe(method(setObject:atIndexedSubscript:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setObject_atIndexedSubscript(&self, value: &NSNumber, index: NSUInteger);
    );
}

/// Methods declared on superclass `NSObject`.
impl MTLRasterizationRateSampleArray {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub fn new() -> Retained<Self>;
    );
}

impl DefaultRetained for MTLRasterizationRateSampleArray {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

extern_class!(
    /// Describes the minimum rasterization rate screen space using two piecewise linear functions.
    ///
    /// The two piecewise linear function (PLF) describe the desired rasterization quality on the horizontal and vertical axis separately.
    /// Each quality sample in the PLF is stored in an array as single precision floating point value between 0 (lowest quality) and 1 (highest quality).
    /// The first sample in the array describes the quality at the top (vertical) or left (horizontal) edge of screen space.
    /// The last sample in the array describes the quality at the bottom (vertical) or right (horizontal) edge of screen space.
    /// All other samples are spaced equidistant in screen space.
    /// MTLRasterizationRateLayerDescriptor instances will be stored inside a MTLRasterizationRateMapDescriptor which in turn is compiled by MTLDevice into a MTLRasterizationRateMap.
    /// Because MTLDevice may not support the requested granularity, the provided samples may be rounded up (towards higher quality) during compilation.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtlrasterizationratelayerdescriptor?language=objc)
    #[unsafe(super(NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct MTLRasterizationRateLayerDescriptor;
);

extern_conformance!(
    unsafe impl NSCopying for MTLRasterizationRateLayerDescriptor {}
);

unsafe impl CopyingHelper for MTLRasterizationRateLayerDescriptor {
    type Result = Self;
}

extern_conformance!(
    unsafe impl NSObjectProtocol for MTLRasterizationRateLayerDescriptor {}
);

impl MTLRasterizationRateLayerDescriptor {
    extern_methods!(
        /// Do not use, instead use initWithNumSamples:
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub fn init(this: Allocated<Self>) -> Retained<Self>;

        #[cfg(feature = "MTLTypes")]
        /// Initialize a descriptor for a layer with the given number of quality samples on the horizontal and vertical axis.
        ///
        /// Parameter `sampleCount`: The width and height components are the number of samples on the horizontal and vertical axis respectively. The depth component is ignored.
        ///
        /// All values are initialized to zero.
        ///
        /// # Safety
        ///
        /// `sampleCount` might not be bounds-checked.
        #[unsafe(method(initWithSampleCount:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithSampleCount(
            this: Allocated<Self>,
            sample_count: MTLSize,
        ) -> Retained<Self>;

        #[cfg(feature = "MTLTypes")]
        /// Initialize a descriptor for a layer with the given number of quality samples on the horizontal and vertical axis.
        ///
        /// Parameter `sampleCount`: The width and height components are the number of samples on the horizontal and vertical axis respectively. The depth component is ignored.
        ///
        /// Parameter `horizontal`: The initial sample values on the horizontal axis. Must point to an array of sampleCount.width elements, of which the values will be copied into the MTLRasterizationRateLayerDescriptor.
        ///
        /// Parameter `vertical`: The initial sample values on the vertical axis. Must point to an array of sampleCount.height elements, of which the values will be copied into the MTLRasterizationRateLayerDescriptor.
        ///
        /// Use initWithSampleCount: to initialize with zeroes instead.
        ///
        /// # Safety
        ///
        /// - `sampleCount` might not be bounds-checked.
        /// - `horizontal` must be a valid pointer.
        /// - `vertical` must be a valid pointer.
        #[unsafe(method(initWithSampleCount:horizontal:vertical:))]
        #[unsafe(method_family = init)]
        pub unsafe fn initWithSampleCount_horizontal_vertical(
            this: Allocated<Self>,
            sample_count: MTLSize,
            horizontal: NonNull<c_float>,
            vertical: NonNull<c_float>,
        ) -> Retained<Self>;

        #[cfg(feature = "MTLTypes")]
        /// Returns: The maximum number of quality samples that this descriptor can use to describe its function, for the horizontal and vertical axis, this is the sampleCount that the descriptor was initialized with. The depth component of the returned MTLSize is always 0.
        #[unsafe(method(maxSampleCount))]
        #[unsafe(method_family = none)]
        pub fn maxSampleCount(&self) -> MTLSize;

        /// Provide direct access to the quality samples stored in the descriptor.
        ///
        /// Returns: Pointer to the (mutable) storage array for samples on the horizontal axis.
        ///
        /// The returned pointer points to the first element of an array of sampleCount.width elements.
        #[unsafe(method(horizontalSampleStorage))]
        #[unsafe(method_family = none)]
        pub fn horizontalSampleStorage(&self) -> NonNull<c_float>;

        /// Provide direct access to the quality samples stored in the descriptor.
        ///
        /// Returns: Pointer to the (mutable) storage array for samples on the vertical axis.
        ///
        /// The returned pointer points to the first element of an array of sampleCount.height elements.
        #[unsafe(method(verticalSampleStorage))]
        #[unsafe(method_family = none)]
        pub fn verticalSampleStorage(&self) -> NonNull<c_float>;

        /// Provide convenient bounds-checked access to the quality samples stored in the descriptor.
        ///
        /// Returns: Returns a syntactic sugar helper to get or set sample values on the horizontal axis.
        #[unsafe(method(horizontal))]
        #[unsafe(method_family = none)]
        pub fn horizontal(&self) -> Retained<MTLRasterizationRateSampleArray>;

        /// Provide convenient bounds-checked access to the quality samples stored in the descriptor.
        ///
        /// Returns: Returns a syntactic sugar helper to get or set sample values on the vertical axis.
        #[unsafe(method(vertical))]
        #[unsafe(method_family = none)]
        pub fn vertical(&self) -> Retained<MTLRasterizationRateSampleArray>;
    );
}

/// Methods declared on superclass `NSObject`.
impl MTLRasterizationRateLayerDescriptor {
    extern_methods!(
        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub fn new() -> Retained<Self>;
    );
}

impl DefaultRetained for MTLRasterizationRateLayerDescriptor {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

impl MTLRasterizationRateLayerDescriptor {
    extern_methods!(
        #[cfg(feature = "MTLTypes")]
        /// Setter for [`sampleCount`][Self::sampleCount].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setSampleCount:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setSampleCount(&self, sample_count: MTLSize);
    );
}

extern_class!(
    /// Mutable array of MTLRasterizationRateLayerDescriptor
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtlrasterizationratelayerarray?language=objc)
    #[unsafe(super(NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct MTLRasterizationRateLayerArray;
);

extern_conformance!(
    unsafe impl NSObjectProtocol for MTLRasterizationRateLayerArray {}
);

impl MTLRasterizationRateLayerArray {
    extern_methods!(
        /// Returns: The MTLRasterizationRateLayerDescriptor instance for the given layerIndex, or nil if no instance hasn't been set for this index.
        ///
        /// Use setObject:atIndexedSubscript: to set the layer
        ///
        /// # Safety
        ///
        /// `layerIndex` might not be bounds-checked.
        #[unsafe(method(objectAtIndexedSubscript:))]
        #[unsafe(method_family = none)]
        pub unsafe fn objectAtIndexedSubscript(
            &self,
            layer_index: NSUInteger,
        ) -> Option<Retained<MTLRasterizationRateLayerDescriptor>>;

        /// Sets the MTLRasterizationRateLayerDescriptor instance for the given layerIndex.
        ///
        /// The previous instance at this index will be overwritten.
        ///
        /// # Safety
        ///
        /// `layerIndex` might not be bounds-checked.
        #[unsafe(method(setObject:atIndexedSubscript:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setObject_atIndexedSubscript(
            &self,
            layer: Option<&MTLRasterizationRateLayerDescriptor>,
            layer_index: NSUInteger,
        );
    );
}

/// Methods declared on superclass `NSObject`.
impl MTLRasterizationRateLayerArray {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub fn new() -> Retained<Self>;
    );
}

impl DefaultRetained for MTLRasterizationRateLayerArray {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

extern_class!(
    /// Describes a MTLRasterizationRateMap containing an arbitrary number of MTLRasterizationRateLayerDescriptor instances.
    ///
    /// An MTLRasterizationRateMapDescriptor is compiled into an MTLRasterizationRateMap using MTLDevice.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtlrasterizationratemapdescriptor?language=objc)
    #[unsafe(super(NSObject))]
    #[derive(Debug, PartialEq, Eq, Hash)]
    pub struct MTLRasterizationRateMapDescriptor;
);

extern_conformance!(
    unsafe impl NSCopying for MTLRasterizationRateMapDescriptor {}
);

unsafe impl CopyingHelper for MTLRasterizationRateMapDescriptor {
    type Result = Self;
}

extern_conformance!(
    unsafe impl NSObjectProtocol for MTLRasterizationRateMapDescriptor {}
);

impl MTLRasterizationRateMapDescriptor {
    extern_methods!(
        #[cfg(feature = "MTLTypes")]
        /// Convenience descriptor creation function without layers
        ///
        /// Parameter `screenSize`: The dimensions, in screen space pixels, of the region where variable rasterization is applied. The depth component of MTLSize is ignored.
        ///
        /// Returns: A descriptor containing no layers. Add or remove layers using setObject:atIndexedSubscript:.
        ///
        /// # Safety
        ///
        /// `screenSize` might not be bounds-checked.
        #[unsafe(method(rasterizationRateMapDescriptorWithScreenSize:))]
        #[unsafe(method_family = none)]
        pub unsafe fn rasterizationRateMapDescriptorWithScreenSize(
            screen_size: MTLSize,
        ) -> Retained<MTLRasterizationRateMapDescriptor>;

        #[cfg(feature = "MTLTypes")]
        /// Convenience descriptor creation function for a single layer.
        ///
        /// Parameter `screenSize`: The dimensions, in screen space pixels, of the region where variable rasterization is applied. The depth component of MTLSize is ignored.
        ///
        /// Parameter `layer`: The single layer describing how the rasterization rate varies in screen space
        ///
        /// Returns: A descriptor containing a single layer. Add or remove layers using setObject:atIndexedSubscript:.
        ///
        /// # Safety
        ///
        /// `screenSize` might not be bounds-checked.
        #[unsafe(method(rasterizationRateMapDescriptorWithScreenSize:layer:))]
        #[unsafe(method_family = none)]
        pub unsafe fn rasterizationRateMapDescriptorWithScreenSize_layer(
            screen_size: MTLSize,
            layer: &MTLRasterizationRateLayerDescriptor,
        ) -> Retained<MTLRasterizationRateMapDescriptor>;

        /// Returns: The MTLRasterizationRateLayerDescriptor instance for the given layerIndex, or nil if no instance hasn't been set for this index.
        ///
        /// Use setLayer:atIndex: to add or set the layer.
        /// Identical to "layers[layerIndex]".
        ///
        /// # Safety
        ///
        /// `layerIndex` might not be bounds-checked.
        #[unsafe(method(layerAtIndex:))]
        #[unsafe(method_family = none)]
        pub unsafe fn layerAtIndex(
            &self,
            layer_index: NSUInteger,
        ) -> Option<Retained<MTLRasterizationRateLayerDescriptor>>;

        /// Sets the MTLRasterizationRateLayerDescriptor instance for the given layerIndex.
        ///
        /// The previous instance at the index, if any, will be overwritten.
        /// Set nil to an index to remove the layer at that index from the descriptor.
        /// Identical to "layers[layerIndex] = layer".
        ///
        /// # Safety
        ///
        /// `layerIndex` might not be bounds-checked.
        #[unsafe(method(setLayer:atIndex:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setLayer_atIndex(
            &self,
            layer: Option<&MTLRasterizationRateLayerDescriptor>,
            layer_index: NSUInteger,
        );

        /// Returns: A modifiable array of layers
        ///
        /// Accesses the layers currently stored in the descriptor.
        /// Syntactic sugar around "layerAtIndex:" and "setLayer:atIndex:"
        #[unsafe(method(layers))]
        #[unsafe(method_family = none)]
        pub fn layers(&self) -> Retained<MTLRasterizationRateLayerArray>;

        #[cfg(feature = "MTLTypes")]
        /// Returns: The dimensions, in screen space pixels, of the region where variable rasterization is applied.
        ///
        /// The region always has its origin at [0, 0].
        /// The depth component of MTLSize is ignored.
        #[unsafe(method(screenSize))]
        #[unsafe(method_family = none)]
        pub fn screenSize(&self) -> MTLSize;

        #[cfg(feature = "MTLTypes")]
        /// Setter for [`screenSize`][Self::screenSize].
        ///
        /// # Safety
        ///
        /// This might not be bounds-checked.
        #[unsafe(method(setScreenSize:))]
        #[unsafe(method_family = none)]
        pub unsafe fn setScreenSize(&self, screen_size: MTLSize);

        /// A string to help identify this object.
        ///
        /// The default value is nil.
        #[unsafe(method(label))]
        #[unsafe(method_family = none)]
        pub fn label(&self) -> Option<Retained<NSString>>;

        /// Setter for [`label`][Self::label].
        ///
        /// This is [copied][objc2_foundation::NSCopying::copy] when set.
        #[unsafe(method(setLabel:))]
        #[unsafe(method_family = none)]
        pub fn setLabel(&self, label: Option<&NSString>);

        /// Returns: The number of subsequent non-nil layer instances stored in the descriptor, starting at index 0.
        ///
        /// This property is modified by setting new layer instances using setLayer:atIndex: or assigning to layers[X]
        #[unsafe(method(layerCount))]
        #[unsafe(method_family = none)]
        pub fn layerCount(&self) -> NSUInteger;
    );
}

/// Methods declared on superclass `NSObject`.
impl MTLRasterizationRateMapDescriptor {
    extern_methods!(
        #[unsafe(method(init))]
        #[unsafe(method_family = init)]
        pub fn init(this: Allocated<Self>) -> Retained<Self>;

        #[unsafe(method(new))]
        #[unsafe(method_family = new)]
        pub fn new() -> Retained<Self>;
    );
}

impl DefaultRetained for MTLRasterizationRateMapDescriptor {
    #[inline]
    fn default_retained() -> Retained<Self> {
        Self::new()
    }
}

extern_protocol!(
    /// Compiled read-only object that determines how variable rasterization rate is applied when rendering.
    ///
    /// A variable rasterization rate map is compiled by MTLDevice from a MTLRasterizationRateMapDescriptor containing one or more MTLRasterizationRateLayerDescriptor.
    /// During compilation, the quality samples provided in the MTLRasterizationRateLayerDescriptor may be rounded up to the nearest supported value or granularity, depending on hardware support.
    /// However, the compilation will never round values down, so the actual rasterization will always happen at a quality level matching or exceeding the provided quality samples.
    /// During rasterization using the MTLRasterizationRateMap the screen space rendering is stored in a smaller area of the framebuffer, such that lower quality regions will not occupy as many texels as higher quality regions.
    /// The quality will never exceed 1:1 in any region of screen space.
    /// Because a smaller area of the framebuffer is populated, less fragment shader invocations are required to render content, and less bandwidth is consumed to store the shaded values.
    /// Use a rasterization rate map to reduce rendering quality in less-important or less-sampled regions of the framebuffer, such as the periphery of a VR/AR display or a far-away cascade of a shadow map.
    ///
    /// See also [Apple's documentation](https://developer.apple.com/documentation/metal/mtlrasterizationratemap?language=objc)
    pub unsafe trait MTLRasterizationRateMap: NSObjectProtocol + Send + Sync {
        #[cfg(feature = "MTLDevice")]
        /// Returns: The device on which the rasterization rate map was created
        #[unsafe(method(device))]
        #[unsafe(method_family = none)]
        fn device(&self) -> Retained<ProtocolObject<dyn MTLDevice>>;

        /// A string to help identify this object.
        #[unsafe(method(label))]
        #[unsafe(method_family = none)]
        fn label(&self) -> Option<Retained<NSString>>;

        #[cfg(feature = "MTLTypes")]
        /// Returns: The dimensions, in screen space pixels, of the region where variable rasterization is applied.
        ///
        /// The region always has its origin at [0, 0].
        /// The depth component of the returned MTLSize is always 0.
        #[unsafe(method(screenSize))]
        #[unsafe(method_family = none)]
        fn screenSize(&self) -> MTLSize;

        #[cfg(feature = "MTLTypes")]
        /// Returns: The granularity, in physical pixels, at which variable rasterization rate varies.
        ///
        /// Rendering algorithms that use binning or tiling in screen space may want to determine the screen space bin size using this value.
        /// The depth component of the returned MTLSize is always 0.
        #[unsafe(method(physicalGranularity))]
        #[unsafe(method_family = none)]
        fn physicalGranularity(&self) -> MTLSize;

        /// Returns: The number of different configured layers in the rasterization map.
        ///
        /// Different render-target layers may target different variable rasterization configurations.
        /// The rasterization rate layer for a primitive is selected on the [[render_target_layer_index]].
        #[unsafe(method(layerCount))]
        #[unsafe(method_family = none)]
        fn layerCount(&self) -> NSUInteger;

        #[cfg(feature = "MTLDevice")]
        /// Returns the size and alignment requirements of the parameter buffer for this rate map.
        ///
        /// The parameter data can be copied into a buffer with this size and alignment using copyParameterDataToBuffer:offset:
        #[unsafe(method(parameterBufferSizeAndAlign))]
        #[unsafe(method_family = none)]
        fn parameterBufferSizeAndAlign(&self) -> MTLSizeAndAlign;

        #[cfg(all(
            feature = "MTLAllocation",
            feature = "MTLBuffer",
            feature = "MTLResource"
        ))]
        /// Copy the parameter data into the provided buffer at the provided offset.
        ///
        /// The buffer must have storageMode MTLStorageModeShared, and a size of at least parameterBufferSizeAndAlign.size + offset.
        /// The specified offset must be a multiple of parameterBufferSize.align.
        /// The buffer can be bound to a shader stage to map screen space to physical fragment space, or vice versa.
        ///
        /// # Safety
        ///
        /// - `buffer` may need to be synchronized.
        /// - `buffer` may be unretained, you must ensure it is kept alive while in use.
        /// - `buffer` contents should be of the correct type.
        /// - `offset` might not be bounds-checked.
        #[unsafe(method(copyParameterDataToBuffer:offset:))]
        #[unsafe(method_family = none)]
        unsafe fn copyParameterDataToBuffer_offset(
            &self,
            buffer: &ProtocolObject<dyn MTLBuffer>,
            offset: NSUInteger,
        );

        #[cfg(feature = "MTLTypes")]
        /// The dimensions, in physical fragments, of the area in the render target where variable rasterization is applied
        ///
        /// Different configured layers may have a different rasterization rate and may have different size after rendering.
        /// The rasterization rate layer for a primitive is selected on the [[render_target_layer_index]].
        ///
        /// # Safety
        ///
        /// `layerIndex` might not be bounds-checked.
        #[unsafe(method(physicalSizeForLayer:))]
        #[unsafe(method_family = none)]
        unsafe fn physicalSizeForLayer(&self, layer_index: NSUInteger) -> MTLSize;

        #[cfg(feature = "MTLTypes")]
        /// Computes where an offset relative to the top-left of screen space, in screen space pixels, would end up in the framebuffer, in physical fragments.
        /// The returned value is less-or-equal the input value because the rasterization quality never exceeds 1:1 in any region.
        ///
        /// # Safety
        ///
        /// `layerIndex` might not be bounds-checked.
        #[unsafe(method(mapScreenToPhysicalCoordinates:forLayer:))]
        #[unsafe(method_family = none)]
        unsafe fn mapScreenToPhysicalCoordinates_forLayer(
            &self,
            screen_coordinates: MTLCoordinate2D,
            layer_index: NSUInteger,
        ) -> MTLCoordinate2D;

        #[cfg(feature = "MTLTypes")]
        /// Computes where an offset relative to the top-left of the framebuffer, in physical pixels, would end up in screen space, in screen space pixels.
        /// The returned value is greater-or-equal the input value because the rasterization quality never exceeds 1:1 in any region.
        ///
        /// # Safety
        ///
        /// `layerIndex` might not be bounds-checked.
        #[unsafe(method(mapPhysicalToScreenCoordinates:forLayer:))]
        #[unsafe(method_family = none)]
        unsafe fn mapPhysicalToScreenCoordinates_forLayer(
            &self,
            physical_coordinates: MTLCoordinate2D,
            layer_index: NSUInteger,
        ) -> MTLCoordinate2D;
    }
);
