xref: /aosp_15_r20/external/mesa3d/src/util/box.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 #ifndef UTIL_BOX_H
2 #define UTIL_BOX_H
3 
4 #include "util/u_math.h"
5 #include "util/format/u_format.h"
6 
7 /**
8  * Subregion of 1D/2D/3D image resource.
9  */
10 struct pipe_box
11 {
12    /* Only "x" and "width" are used to represent buffer ranges.
13     * The maximum representable texture size is ANY x ANY x 16K.
14     */
15    int32_t x;
16    int32_t width;
17    int32_t y;
18    int32_t height;
19    int16_t z;
20    int16_t depth;
21 };
22 
23 static inline void
u_box_1d(unsigned x,unsigned w,struct pipe_box * box)24 u_box_1d(unsigned x, unsigned w, struct pipe_box *box)
25 {
26    box->x = x;
27    box->y = 0;
28    box->z = 0;
29    box->width = w;
30    box->height = 1;
31    box->depth = 1;
32 }
33 
34 static inline void
u_box_2d(unsigned x,unsigned y,unsigned w,unsigned h,struct pipe_box * box)35 u_box_2d(unsigned x,unsigned y, unsigned w, unsigned h, struct pipe_box *box)
36 {
37    box->x = x;
38    box->y = y;
39    box->z = 0;
40    box->width = w;
41    box->height = h;
42    box->depth = 1;
43 }
44 
45 static inline void
u_box_origin_2d(unsigned w,unsigned h,struct pipe_box * box)46 u_box_origin_2d(unsigned w, unsigned h, struct pipe_box *box)
47 {
48    box->x = 0;
49    box->y = 0;
50    box->z = 0;
51    box->width = w;
52    box->height = h;
53    box->depth = 1;
54 }
55 
56 static inline void
u_box_2d_zslice(unsigned x,unsigned y,unsigned z,unsigned w,unsigned h,struct pipe_box * box)57 u_box_2d_zslice(unsigned x, unsigned y, unsigned z,
58                 unsigned w, unsigned h, struct pipe_box *box)
59 {
60    box->x = x;
61    box->y = y;
62    box->z = z;
63    box->width = w;
64    box->height = h;
65    box->depth = 1;
66 }
67 
68 static inline void
u_box_3d(unsigned x,unsigned y,unsigned z,unsigned w,unsigned h,unsigned d,struct pipe_box * box)69 u_box_3d(unsigned x, unsigned y, unsigned z,
70          unsigned w, unsigned h, unsigned d,
71          struct pipe_box *box)
72 {
73    box->x = x;
74    box->y = y;
75    box->z = z;
76    box->width = w;
77    box->height = h;
78    box->depth = d;
79 }
80 
81 /* Clips @dst to width @w and height @h.
82  * Returns -1 if the resulting box would be empty (then @dst is left unchanged).
83  *          0 if nothing has been reduced.
84  *          1 if width has been reduced.
85  *          2 if height has been reduced.
86  *          3 if both width and height have been reduced.
87  * Aliasing permitted.
88  */
89 static inline int
u_box_clip_2d(struct pipe_box * dst,const struct pipe_box * box,int w,int h)90 u_box_clip_2d(struct pipe_box *dst,
91               const struct pipe_box *box, int w, int h)
92 {
93    unsigned i;
94    int a[2], b[2], dim[2];
95    int *start, *end;
96    int res = 0;
97 
98    if (!box->width || !box->height)
99       return -1;
100    dim[0] = w;
101    dim[1] = h;
102    a[0] = box->x;
103    a[1] = box->y;
104    b[0] = box->x + box->width;
105    b[1] = box->y + box->height;
106 
107    for (i = 0; i < 2; ++i) {
108       start = (a[i] <= b[i]) ? &a[i] : &b[i];
109       end = (a[i] <= b[i]) ? &b[i] : &a[i];
110 
111       if (*end < 0 || *start >= dim[i])
112          return -1;
113       if (*start < 0) {
114          *start = 0;
115          res |= (1 << i);
116       }
117       if (*end > dim[i]) {
118          *end = dim[i];
119          res |= (1 << i);
120       }
121    }
122 
123    if (res) {
124       dst->x = a[0];
125       dst->y = a[1];
126       dst->width = b[0] - a[0];
127       dst->height = b[1] - a[1];
128    }
129    return res;
130 }
131 
132 static inline int64_t
u_box_volume_3d(const struct pipe_box * box)133 u_box_volume_3d(const struct pipe_box *box)
134 {
135    return (int64_t)box->width * box->height * box->depth;
136 }
137 
138 /* Aliasing of @dst permitted. Supports empty width */
139 static inline void
u_box_union_1d(struct pipe_box * dst,const struct pipe_box * a,const struct pipe_box * b)140 u_box_union_1d(struct pipe_box *dst,
141                const struct pipe_box *a, const struct pipe_box *b)
142 {
143    int x, width;
144 
145    if (a->width == 0) {
146        x = b->x;
147        width = b->width;
148    } else if (b->width == 0) {
149        x = a->x;
150        width = a->width;
151    } else {
152        x = MIN2(a->x, b->x);
153        width = MAX2(a->x + a->width, b->x + b->width) - x;
154    }
155 
156    dst->x = x;
157    dst->width = width;
158 }
159 
160 /* Aliasing of @dst permitted. */
161 static inline void
u_box_intersect_1d(struct pipe_box * dst,const struct pipe_box * a,const struct pipe_box * b)162 u_box_intersect_1d(struct pipe_box *dst,
163                const struct pipe_box *a, const struct pipe_box *b)
164 {
165    int x;
166 
167    x = MAX2(a->x, b->x);
168 
169    dst->width = MIN2(a->x + a->width, b->x + b->width) - x;
170    dst->x = x;
171    if (dst->width <= 0) {
172       dst->x = 0;
173       dst->width = 0;
174    }
175 }
176 
177 /* Aliasing of @dst permitted. */
178 static inline void
u_box_union_2d(struct pipe_box * dst,const struct pipe_box * a,const struct pipe_box * b)179 u_box_union_2d(struct pipe_box *dst,
180                const struct pipe_box *a, const struct pipe_box *b)
181 {
182    int x, y;
183 
184    x = MIN2(a->x, b->x);
185    y = MIN2(a->y, b->y);
186 
187    dst->width = MAX2(a->x + a->width, b->x + b->width) - x;
188    dst->height = MAX2(a->y + a->height, b->y + b->height) - y;
189    dst->x = x;
190    dst->y = y;
191 }
192 
193 /* Aliasing of @dst permitted. */
194 static inline void
u_box_union_3d(struct pipe_box * dst,const struct pipe_box * a,const struct pipe_box * b)195 u_box_union_3d(struct pipe_box *dst,
196                const struct pipe_box *a, const struct pipe_box *b)
197 {
198    int x, y, z;
199 
200    x = MIN2(a->x, b->x);
201    y = MIN2(a->y, b->y);
202    z = MIN2(a->z, b->z);
203 
204    dst->width = MAX2(a->x + a->width, b->x + b->width) - x;
205    dst->height = MAX2(a->y + a->height, b->y + b->height) - y;
206    dst->depth = MAX2(a->z + a->depth, b->z + b->depth) - z;
207    dst->x = x;
208    dst->y = y;
209    dst->z = z;
210 }
211 
212 static inline bool
u_box_test_intersection_1d(const struct pipe_box * a,const struct pipe_box * b)213 u_box_test_intersection_1d(const struct pipe_box *a,
214                            const struct pipe_box *b)
215 {
216    int ax[2], bx[2];
217 
218    ax[0] = MIN2(a->x, a->x + a->width);
219    ax[1] = MAX2(a->x, a->x + a->width - 1);
220 
221    bx[0] = MIN2(b->x, b->x + b->width);
222    bx[1] = MAX2(b->x, b->x + b->width - 1);
223 
224    return ax[1] >= bx[0] && bx[1] >= ax[0];
225 }
226 
227 static inline bool
u_box_test_intersection_2d(const struct pipe_box * a,const struct pipe_box * b)228 u_box_test_intersection_2d(const struct pipe_box *a,
229                            const struct pipe_box *b)
230 {
231    unsigned i;
232    int a_l[2], a_r[2], b_l[2], b_r[2];
233 
234    a_l[0] = MIN2(a->x, a->x + a->width);
235    a_r[0] = MAX2(a->x, a->x + a->width);
236    a_l[1] = MIN2(a->y, a->y + a->height);
237    a_r[1] = MAX2(a->y, a->y + a->height);
238 
239    b_l[0] = MIN2(b->x, b->x + b->width);
240    b_r[0] = MAX2(b->x, b->x + b->width);
241    b_l[1] = MIN2(b->y, b->y + b->height);
242    b_r[1] = MAX2(b->y, b->y + b->height);
243 
244    for (i = 0; i < 2; ++i) {
245       if (a_l[i] > b_r[i] || a_r[i] < b_l[i])
246          return false;
247    }
248    return true;
249 }
250 
251 static inline bool
u_box_test_intersection_3d(const struct pipe_box * a,const struct pipe_box * b)252 u_box_test_intersection_3d(const struct pipe_box *a,
253                            const struct pipe_box *b)
254 {
255    int ax[2], ay[2], ad[2], bx[2], by[2], bd[2];
256 
257    ax[0] = MIN2(a->x, a->x + a->width);
258    ax[1] = MAX2(a->x, a->x + a->width - 1);
259    ay[0] = MIN2(a->y, a->y + a->height);
260    ay[1] = MAX2(a->y, a->y + a->height - 1);
261    ad[0] = MIN2(a->z, a->z + a->depth);
262    ad[1] = MAX2(a->z, a->z + a->depth - 1);
263 
264    bx[0] = MIN2(b->x, b->x + b->width);
265    bx[1] = MAX2(b->x, b->x + b->width - 1);
266    by[0] = MIN2(b->y, b->y + b->height);
267    by[1] = MAX2(b->y, b->y + b->height - 1);
268    bd[0] = MIN2(b->z, b->z + b->depth);
269    bd[1] = MAX2(b->z, b->z + b->depth - 1);
270 
271    return ax[1] >= bx[0] && bx[1] >= ax[0] &&
272           ay[1] >= by[0] && by[1] >= ay[0] &&
273           ad[1] >= bd[0] && bd[1] >= ad[0];
274 }
275 
276 static inline void
u_box_minify_2d(struct pipe_box * dst,const struct pipe_box * src,unsigned l)277 u_box_minify_2d(struct pipe_box *dst,
278                 const struct pipe_box *src, unsigned l)
279 {
280    dst->x = src->x >> l;
281    dst->y = src->y >> l;
282    dst->width = MAX2(src->width >> l, 1);
283    dst->height = MAX2(src->height >> l, 1);
284 }
285 
286 static inline void
u_box_minify_3d(struct pipe_box * dst,const struct pipe_box * src,unsigned l)287 u_box_minify_3d(struct pipe_box *dst,
288                 const struct pipe_box *src, unsigned l)
289 {
290    dst->x = src->x >> l;
291    dst->y = src->y >> l;
292    dst->z = src->z >> l;
293    dst->width = MAX2(src->width >> l, 1);
294    dst->height = MAX2(src->height >> l, 1);
295    dst->depth = MAX2(src->depth >> l, 1);
296 }
297 
298 /* Converts a box specified in pixels to an equivalent box specified
299  * in blocks, where the boxes represent a region-of-interest of an image with
300  * the given format. This is trivial (a copy) for uncompressed formats.
301  */
302 static inline void
u_box_pixels_to_blocks(struct pipe_box * blocks,const struct pipe_box * pixels,enum pipe_format format)303 u_box_pixels_to_blocks(struct pipe_box *blocks,
304                        const struct pipe_box *pixels, enum pipe_format format)
305 {
306    u_box_3d(
307          pixels->x / util_format_get_blockwidth(format),
308          pixels->y / util_format_get_blockheight(format),
309          pixels->z,
310          DIV_ROUND_UP(pixels->width, util_format_get_blockwidth(format)),
311          DIV_ROUND_UP(pixels->height, util_format_get_blockheight(format)),
312          pixels->depth,
313          blocks);
314 }
315 
316 static inline bool
util_is_box_sint16(const struct pipe_box * box)317 util_is_box_sint16(const struct pipe_box *box)
318 {
319    return util_is_sint16(box->x) && util_is_sint16(box->y) &&
320           util_is_sint16(box->z) && util_is_sint16(box->width) &&
321           util_is_sint16(box->height) && util_is_sint16(box->depth) &&
322           util_is_sint16(box->x + box->width) &&
323           util_is_sint16(box->y + box->height) &&
324           util_is_sint16(box->z + box->depth);
325 }
326 
327 static inline bool
util_is_box_out_of_bounds(const struct pipe_box * src_box,unsigned coord_mask,unsigned width,unsigned height,unsigned mip_level)328 util_is_box_out_of_bounds(const struct pipe_box *src_box, unsigned coord_mask,
329                           unsigned width, unsigned height, unsigned mip_level)
330 {
331    int src_width = u_minify(width, mip_level);
332    int src_height = u_minify(height, mip_level);
333    struct pipe_box box = *src_box;
334 
335    /* Eliminate negative width/height/depth. */
336    if (box.width < 0) {
337       box.x += box.width;
338       box.width *= -1;
339    }
340    if (box.height < 0) {
341       box.y += box.height;
342       box.height *= -1;
343    }
344 
345    bool x_in_bounds = box.x >= 0 && box.x < src_width &&
346                       box.x + box.width > 0 && box.x + box.width <= src_width;
347    bool y_in_bounds = box.y >= 0 && box.y < src_height &&
348                       box.y + box.height > 0 && box.y + box.height <= src_height;
349 
350    /* Return if the box is not in bounds. */
351    if (coord_mask & BITFIELD_BIT(0) && !x_in_bounds)
352       return true;
353    if (coord_mask & BITFIELD_BIT(1) && !y_in_bounds)
354       return true;
355 
356    return false;
357 }
358 
359 #endif
360