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