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