xref: /aosp_15_r20/external/mesa3d/src/nouveau/nil/format.rs (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 // Copyright © 2024 Collabora, Ltd.
2 // SPDX-License-Identifier: MIT
3 
4 use nil_rs_bindings::*;
5 use nvidia_headers::classes::{cla297, clb097, clb197};
6 
7 use crate::extent::{units, Extent4D};
8 
9 #[repr(C)]
10 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
11 pub struct Format {
12     p_format: pipe_format,
13 }
14 
15 impl TryFrom<pipe_format> for Format {
16     type Error = &'static str;
17 
try_from(p_format: pipe_format) -> Result<Self, Self::Error>18     fn try_from(p_format: pipe_format) -> Result<Self, Self::Error> {
19         unsafe {
20             if p_format >= PIPE_FORMAT_COUNT {
21                 Err("pipe_format is out-of-bounds")
22             } else if nil_format_table[p_format as usize].support() == 0 {
23                 Err("Unsupported pipe_format")
24             } else {
25                 Ok(Format { p_format })
26             }
27         }
28     }
29 }
30 
31 impl From<Format> for pipe_format {
from(format: Format) -> pipe_format32     fn from(format: Format) -> pipe_format {
33         format.p_format
34     }
35 }
36 
37 impl Format {
description(&self) -> &'static util_format_description38     fn description(&self) -> &'static util_format_description {
39         unsafe { &*util_format_description((*self).into()) }
40     }
41 
el_size_B(&self) -> u3242     pub(crate) fn el_size_B(&self) -> u32 {
43         let bits = self.description().block.bits;
44         debug_assert!(bits % 8 == 0);
45         bits / 8
46     }
47 
el_extent_sa(&self) -> Extent4D<units::Samples>48     pub(crate) fn el_extent_sa(&self) -> Extent4D<units::Samples> {
49         let desc = self.description();
50         Extent4D::new(desc.block.width, desc.block.height, desc.block.depth, 1)
51     }
52 
info(&self) -> &nil_format_info53     pub(crate) fn info(&self) -> &nil_format_info {
54         unsafe { &nil_format_table[self.p_format as usize] }
55     }
56 
is_integer(&self) -> bool57     pub(crate) fn is_integer(&self) -> bool {
58         unsafe { util_format_is_pure_integer((*self).into()) }
59     }
60 
has_depth(&self) -> bool61     pub(crate) fn has_depth(&self) -> bool {
62         self.description().colorspace == UTIL_FORMAT_COLORSPACE_ZS
63             && u32::from(self.description().swizzle[0]) != PIPE_SWIZZLE_NONE
64     }
65 
has_stencil(&self) -> bool66     pub(crate) fn has_stencil(&self) -> bool {
67         self.description().colorspace == UTIL_FORMAT_COLORSPACE_ZS
68             && u32::from(self.description().swizzle[1]) != PIPE_SWIZZLE_NONE
69     }
70 
is_depth_or_stencil(&self) -> bool71     pub(crate) fn is_depth_or_stencil(&self) -> bool {
72         self.has_depth() || self.has_stencil()
73     }
74 
is_srgb(&self) -> bool75     pub(crate) fn is_srgb(&self) -> bool {
76         self.description().colorspace == UTIL_FORMAT_COLORSPACE_SRGB
77     }
78 
supports_texturing(&self, dev: &nv_device_info) -> bool79     pub fn supports_texturing(&self, dev: &nv_device_info) -> bool {
80         if self.info().support() & NIL_FORMAT_SUPPORTS_TEXTURE_BIT == 0 {
81             return false;
82         }
83 
84         let desc = self.description();
85         if desc.layout == UTIL_FORMAT_LAYOUT_ETC
86             || desc.layout == UTIL_FORMAT_LAYOUT_ASTC
87         {
88             return dev.type_ == NV_DEVICE_TYPE_SOC
89                 && dev.cls_eng3d >= cla297::KEPLER_C;
90         }
91 
92         true
93     }
94 
supports_filtering(&self, dev: &nv_device_info) -> bool95     pub fn supports_filtering(&self, dev: &nv_device_info) -> bool {
96         self.supports_texturing(dev) && !self.is_integer()
97     }
98 
supports_buffer(&self) -> bool99     pub fn supports_buffer(&self) -> bool {
100         self.info().support() & NIL_FORMAT_SUPPORTS_BUFFER_BIT != 0
101     }
102 
supports_storage(&self, dev: &nv_device_info) -> bool103     pub fn supports_storage(&self, dev: &nv_device_info) -> bool {
104         if (self.p_format == PIPE_FORMAT_R64_UINT
105             || self.p_format == PIPE_FORMAT_R64_SINT)
106             && dev.cls_eng3d < clb097::MAXWELL_A
107         {
108             return false;
109         }
110         self.info().support() & NIL_FORMAT_SUPPORTS_STORAGE_BIT != 0
111     }
112 
supports_color_targets(&self, _dev: &nv_device_info) -> bool113     pub fn supports_color_targets(&self, _dev: &nv_device_info) -> bool {
114         self.info().support() & NIL_FORMAT_SUPPORTS_RENDER_BIT != 0
115     }
116 
supports_blending(&self, _dev: &nv_device_info) -> bool117     pub fn supports_blending(&self, _dev: &nv_device_info) -> bool {
118         self.info().support() & NIL_FORMAT_SUPPORTS_ALPHA_BLEND_BIT != 0
119     }
120 
supports_depth_stencil(&self, dev: &nv_device_info) -> bool121     pub fn supports_depth_stencil(&self, dev: &nv_device_info) -> bool {
122         if self.p_format == PIPE_FORMAT_S8_UINT {
123             return dev.cls_eng3d >= clb197::MAXWELL_B;
124         }
125         self.info().support() & NIL_FORMAT_SUPPORTS_DEPTH_STENCIL_BIT != 0
126     }
127 }
128 
129 #[no_mangle]
nil_format_supports_texturing( dev: &nv_device_info, p_format: pipe_format, ) -> bool130 pub extern "C" fn nil_format_supports_texturing(
131     dev: &nv_device_info,
132     p_format: pipe_format,
133 ) -> bool {
134     Format::try_from(p_format).is_ok_and(|f| f.supports_texturing(dev))
135 }
136 
137 #[no_mangle]
nil_format_supports_filtering( dev: &nv_device_info, p_format: pipe_format, ) -> bool138 pub extern "C" fn nil_format_supports_filtering(
139     dev: &nv_device_info,
140     p_format: pipe_format,
141 ) -> bool {
142     Format::try_from(p_format).is_ok_and(|f| f.supports_filtering(dev))
143 }
144 
145 #[no_mangle]
nil_format_supports_buffer( _dev: &nv_device_info, p_format: pipe_format, ) -> bool146 pub extern "C" fn nil_format_supports_buffer(
147     _dev: &nv_device_info,
148     p_format: pipe_format,
149 ) -> bool {
150     Format::try_from(p_format).is_ok_and(|f| f.supports_buffer())
151 }
152 
153 #[no_mangle]
nil_format_supports_storage( dev: &nv_device_info, p_format: pipe_format, ) -> bool154 pub extern "C" fn nil_format_supports_storage(
155     dev: &nv_device_info,
156     p_format: pipe_format,
157 ) -> bool {
158     Format::try_from(p_format).is_ok_and(|f| f.supports_storage(dev))
159 }
160 
161 #[no_mangle]
nil_format_supports_color_targets( dev: &nv_device_info, p_format: pipe_format, ) -> bool162 pub extern "C" fn nil_format_supports_color_targets(
163     dev: &nv_device_info,
164     p_format: pipe_format,
165 ) -> bool {
166     Format::try_from(p_format).is_ok_and(|f| f.supports_color_targets(dev))
167 }
168 
169 #[no_mangle]
nil_format_supports_blending( dev: &nv_device_info, p_format: pipe_format, ) -> bool170 pub extern "C" fn nil_format_supports_blending(
171     dev: &nv_device_info,
172     p_format: pipe_format,
173 ) -> bool {
174     Format::try_from(p_format).is_ok_and(|f| f.supports_blending(dev))
175 }
176 
177 #[no_mangle]
nil_format_supports_depth_stencil( dev: &nv_device_info, p_format: pipe_format, ) -> bool178 pub extern "C" fn nil_format_supports_depth_stencil(
179     dev: &nv_device_info,
180     p_format: pipe_format,
181 ) -> bool {
182     Format::try_from(p_format).is_ok_and(|f| f.supports_depth_stencil(dev))
183 }
184 
185 #[no_mangle]
nil_format_to_color_target(p_format: pipe_format) -> u32186 pub extern "C" fn nil_format_to_color_target(p_format: pipe_format) -> u32 {
187     Format::try_from(p_format).unwrap().info().czt()
188 }
189 
190 #[no_mangle]
nil_format_to_depth_stencil(p_format: pipe_format) -> u32191 pub extern "C" fn nil_format_to_depth_stencil(p_format: pipe_format) -> u32 {
192     Format::try_from(p_format).unwrap().info().czt()
193 }
194 
195 #[no_mangle]
nil_format(p_format: pipe_format) -> Format196 pub extern "C" fn nil_format(p_format: pipe_format) -> Format {
197     p_format.try_into().unwrap()
198 }
199