xref: /aosp_15_r20/external/mesa3d/src/nouveau/nil/extent.rs (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 // Copyright © 2024 Collabora, Ltd.
2 // SPDX-License-Identifier: MIT
3 
4 use crate::format::Format;
5 use crate::image::SampleLayout;
6 use crate::tiling::{gob_height, Tiling, GOB_DEPTH, GOB_WIDTH_B};
7 use crate::Minify;
8 
9 pub mod units {
10     #[derive(Clone, Debug, Copy, PartialEq)]
11     pub struct Elements {}
12 
13     #[derive(Clone, Debug, Copy, PartialEq)]
14     pub struct Pixels {}
15 
16     #[derive(Clone, Debug, Copy, PartialEq)]
17     pub struct Samples {}
18 
19     #[derive(Clone, Debug, Copy, PartialEq)]
20     pub struct Bytes {}
21 
22     #[derive(Clone, Debug, Copy, PartialEq)]
23     pub struct Tiles {}
24 
25     #[derive(Clone, Debug, Copy, PartialEq)]
26     pub struct GOBs {}
27 }
28 
29 #[derive(Clone, Debug, Copy, PartialEq, Default)]
30 #[repr(C)]
31 pub struct Extent4D<U> {
32     pub width: u32,
33     pub height: u32,
34     pub depth: u32,
35     pub array_len: u32,
36     phantom: std::marker::PhantomData<U>,
37 }
38 
39 impl<U> Extent4D<U> {
new( width: u32, height: u32, depth: u32, array_len: u32, ) -> Extent4D<U>40     pub fn new(
41         width: u32,
42         height: u32,
43         depth: u32,
44         array_len: u32,
45     ) -> Extent4D<U> {
46         Extent4D {
47             width,
48             height,
49             depth,
50             array_len,
51             phantom: std::marker::PhantomData,
52         }
53     }
54 
align(self, alignment: &Self) -> Self55     pub fn align(self, alignment: &Self) -> Self {
56         Self {
57             width: self.width.next_multiple_of(alignment.width),
58             height: self.height.next_multiple_of(alignment.height),
59             depth: self.depth.next_multiple_of(alignment.depth),
60             array_len: self.array_len.next_multiple_of(alignment.array_len),
61             phantom: std::marker::PhantomData,
62         }
63     }
64 
mul<V>(self, other: Extent4D<V>) -> Extent4D<V>65     fn mul<V>(self, other: Extent4D<V>) -> Extent4D<V> {
66         Extent4D {
67             width: self.width * other.width,
68             height: self.height * other.height,
69             depth: self.depth * other.depth,
70             array_len: self.array_len * other.array_len,
71             phantom: std::marker::PhantomData,
72         }
73     }
74 
div_ceil<V>(self, other: Self) -> Extent4D<V>75     fn div_ceil<V>(self, other: Self) -> Extent4D<V> {
76         Extent4D {
77             width: self.width.div_ceil(other.width),
78             height: self.height.div_ceil(other.height),
79             depth: self.depth.div_ceil(other.depth),
80             array_len: self.array_len.div_ceil(other.array_len),
81             phantom: std::marker::PhantomData,
82         }
83     }
84 
cast_units<V>(self) -> Extent4D<V>85     pub fn cast_units<V>(self) -> Extent4D<V> {
86         Extent4D {
87             width: self.width,
88             height: self.height,
89             depth: self.depth,
90             array_len: self.array_len,
91             phantom: std::marker::PhantomData,
92         }
93     }
94 }
95 
96 impl Extent4D<units::Pixels> {
to_sa( self, sample_layout: SampleLayout, ) -> Extent4D<units::Samples>97     pub fn to_sa(
98         self,
99         sample_layout: SampleLayout,
100     ) -> Extent4D<units::Samples> {
101         self.mul(sample_layout.px_extent_sa())
102     }
103 
to_el( self, format: Format, sample_layout: SampleLayout, ) -> Extent4D<units::Elements>104     pub fn to_el(
105         self,
106         format: Format,
107         sample_layout: SampleLayout,
108     ) -> Extent4D<units::Elements> {
109         self.to_sa(sample_layout).div_ceil(format.el_extent_sa())
110     }
111 
to_B( self, format: Format, sample_layout: SampleLayout, ) -> Extent4D<units::Bytes>112     pub fn to_B(
113         self,
114         format: Format,
115         sample_layout: SampleLayout,
116     ) -> Extent4D<units::Bytes> {
117         self.to_el(format, sample_layout).to_B(format)
118     }
119 
to_tl( self, tiling: &Tiling, format: Format, sample_layout: SampleLayout, ) -> Extent4D<units::Tiles>120     pub fn to_tl(
121         self,
122         tiling: &Tiling,
123         format: Format,
124         sample_layout: SampleLayout,
125     ) -> Extent4D<units::Tiles> {
126         let tl_extent_B = tiling.extent_B();
127         self.to_B(format, sample_layout).div_ceil(tl_extent_B)
128     }
129 }
130 
131 #[no_mangle]
nil_extent4d_px_to_el( extent_px: Extent4D<units::Pixels>, format: Format, sample_layout: SampleLayout, ) -> Extent4D<units::Elements>132 pub extern "C" fn nil_extent4d_px_to_el(
133     extent_px: Extent4D<units::Pixels>,
134     format: Format,
135     sample_layout: SampleLayout,
136 ) -> Extent4D<units::Elements> {
137     extent_px.to_el(format, sample_layout)
138 }
139 
140 #[no_mangle]
nil_extent4d_px_to_tl( extent_px: Extent4D<units::Pixels>, tiling: &Tiling, format: Format, sample_layout: SampleLayout, ) -> Extent4D<units::Tiles>141 pub extern "C" fn nil_extent4d_px_to_tl(
142     extent_px: Extent4D<units::Pixels>,
143     tiling: &Tiling,
144     format: Format,
145     sample_layout: SampleLayout,
146 ) -> Extent4D<units::Tiles> {
147     extent_px.to_tl(tiling, format, sample_layout)
148 }
149 
150 impl Extent4D<units::Samples> {
to_px(self, sample_layout: SampleLayout) -> Extent4D<units::Pixels>151     pub fn to_px(self, sample_layout: SampleLayout) -> Extent4D<units::Pixels> {
152         self.div_ceil(sample_layout.px_extent_sa())
153     }
154 }
155 
156 impl Extent4D<units::Elements> {
to_B(self, format: Format) -> Extent4D<units::Bytes>157     pub fn to_B(self, format: Format) -> Extent4D<units::Bytes> {
158         Extent4D {
159             width: self.width * format.el_size_B(),
160             ..self.cast_units()
161         }
162     }
163 
to_sa(self, format: Format) -> Extent4D<units::Samples>164     pub fn to_sa(self, format: Format) -> Extent4D<units::Samples> {
165         self.mul(format.el_extent_sa())
166     }
167 }
168 
169 impl Extent4D<units::Bytes> {
size_B(&self) -> u64170     pub fn size_B(&self) -> u64 {
171         // size_B of something with layers doesn't make sense because we can't
172         // know the array stride based only on the other dimensions.
173         assert!(self.array_len == 1);
174         u64::from(self.width) * u64::from(self.height) * u64::from(self.depth)
175     }
176 
to_GOB(self, gob_height_is_8: bool) -> Extent4D<units::GOBs>177     pub fn to_GOB(self, gob_height_is_8: bool) -> Extent4D<units::GOBs> {
178         let gob_extent_B = Extent4D {
179             width: GOB_WIDTH_B,
180             height: gob_height(gob_height_is_8),
181             depth: GOB_DEPTH,
182             array_len: 1,
183             phantom: std::marker::PhantomData,
184         };
185 
186         self.div_ceil(gob_extent_B)
187     }
188 }
189 
190 #[derive(Clone, Debug, Copy, PartialEq)]
191 #[repr(C)]
192 pub struct Offset4D<U> {
193     pub x: u32,
194     pub y: u32,
195     pub z: u32,
196     pub a: u32,
197     phantom: std::marker::PhantomData<U>,
198 }
199 
200 impl<U> Offset4D<U> {
div_floor<V>(self, other: Extent4D<U>) -> Offset4D<V>201     fn div_floor<V>(self, other: Extent4D<U>) -> Offset4D<V> {
202         Offset4D {
203             x: self.x / other.width,
204             y: self.y / other.height,
205             z: self.z / other.depth,
206             a: self.a / other.array_len,
207             phantom: std::marker::PhantomData,
208         }
209     }
210 
mul<V>(self, other: Extent4D<V>) -> Offset4D<V>211     fn mul<V>(self, other: Extent4D<V>) -> Offset4D<V> {
212         Offset4D {
213             x: self.x * other.width,
214             y: self.y * other.height,
215             z: self.z * other.depth,
216             a: self.a * other.array_len,
217             phantom: std::marker::PhantomData,
218         }
219     }
220 
cast_units<V>(self) -> Offset4D<V>221     fn cast_units<V>(self) -> Offset4D<V> {
222         Offset4D {
223             x: self.x,
224             y: self.y,
225             z: self.z,
226             a: self.a,
227             phantom: std::marker::PhantomData,
228         }
229     }
230 }
231 
232 impl Offset4D<units::Pixels> {
to_el( self, format: Format, sample_layout: SampleLayout, ) -> Offset4D<units::Elements>233     pub fn to_el(
234         self,
235         format: Format,
236         sample_layout: SampleLayout,
237     ) -> Offset4D<units::Elements> {
238         self.mul(sample_layout.px_extent_sa())
239             .div_floor(format.el_extent_sa())
240     }
241 
to_B( self, format: Format, sample_layout: SampleLayout, ) -> Offset4D<units::Bytes>242     pub fn to_B(
243         self,
244         format: Format,
245         sample_layout: SampleLayout,
246     ) -> Offset4D<units::Bytes> {
247         self.to_el(format, sample_layout).to_B(format)
248     }
249 
to_tl( self, tiling: &Tiling, format: Format, sample_layout: SampleLayout, ) -> Offset4D<units::Tiles>250     pub fn to_tl(
251         self,
252         tiling: &Tiling,
253         format: Format,
254         sample_layout: SampleLayout,
255     ) -> Offset4D<units::Tiles> {
256         self.to_B(format, sample_layout)
257             .div_floor(tiling.extent_B())
258     }
259 }
260 
261 #[no_mangle]
nil_offset4d_px_to_el( offset: Offset4D<units::Pixels>, format: Format, sample_layout: SampleLayout, ) -> Offset4D<units::Elements>262 pub extern "C" fn nil_offset4d_px_to_el(
263     offset: Offset4D<units::Pixels>,
264     format: Format,
265     sample_layout: SampleLayout,
266 ) -> Offset4D<units::Elements> {
267     offset.to_el(format, sample_layout)
268 }
269 
270 #[no_mangle]
nil_offset4d_px_to_tl( offset: Offset4D<units::Pixels>, tiling: &Tiling, format: Format, sample_layout: SampleLayout, ) -> Offset4D<units::Tiles>271 pub extern "C" fn nil_offset4d_px_to_tl(
272     offset: Offset4D<units::Pixels>,
273     tiling: &Tiling,
274     format: Format,
275     sample_layout: SampleLayout,
276 ) -> Offset4D<units::Tiles> {
277     offset.to_tl(tiling, format, sample_layout)
278 }
279 
280 impl Offset4D<units::Elements> {
to_B(self, format: Format) -> Offset4D<units::Bytes>281     pub fn to_B(self, format: Format) -> Offset4D<units::Bytes> {
282         Offset4D {
283             x: self.x * format.el_size_B(),
284             ..self.cast_units()
285         }
286     }
287 }
288 
289 impl Minify<u32> for Extent4D<units::Pixels> {
minify(self, level: u32) -> Self290     fn minify(self, level: u32) -> Self {
291         Self {
292             width: self.width.minify(level),
293             height: self.height.minify(level),
294             depth: self.depth.minify(level),
295             ..self
296         }
297     }
298 }
299