1#ifndef UTIL_BOX_INLINES_H
2#define UTIL_BOX_INLINES_H
3
4#include "pipe/p_state.h"
5#include "util/u_math.h"
6#include "util/format/u_format.h"
7
8static inline void
9u_box_1d(unsigned x, unsigned w, struct pipe_box *box)
10{
11   box->x = x;
12   box->y = 0;
13   box->z = 0;
14   box->width = w;
15   box->height = 1;
16   box->depth = 1;
17}
18
19static inline void
20u_box_2d(unsigned x,unsigned y, unsigned w, unsigned h, struct pipe_box *box)
21{
22   box->x = x;
23   box->y = y;
24   box->z = 0;
25   box->width = w;
26   box->height = h;
27   box->depth = 1;
28}
29
30static inline void
31u_box_origin_2d(unsigned w, unsigned h, struct pipe_box *box)
32{
33   box->x = 0;
34   box->y = 0;
35   box->z = 0;
36   box->width = w;
37   box->height = h;
38   box->depth = 1;
39}
40
41static inline void
42u_box_2d_zslice(unsigned x, unsigned y, unsigned z,
43                unsigned w, unsigned h, struct pipe_box *box)
44{
45   box->x = x;
46   box->y = y;
47   box->z = z;
48   box->width = w;
49   box->height = h;
50   box->depth = 1;
51}
52
53static inline void
54u_box_3d(unsigned x, unsigned y, unsigned z,
55         unsigned w, unsigned h, unsigned d,
56         struct pipe_box *box)
57{
58   box->x = x;
59   box->y = y;
60   box->z = z;
61   box->width = w;
62   box->height = h;
63   box->depth = d;
64}
65
66/* Clips @dst to width @w and height @h.
67 * Returns -1 if the resulting box would be empty (then @dst is left unchanged).
68 *          0 if nothing has been reduced.
69 *          1 if width has been reduced.
70 *          2 if height has been reduced.
71 *          3 if both width and height have been reduced.
72 * Aliasing permitted.
73 */
74static inline int
75u_box_clip_2d(struct pipe_box *dst,
76              const struct pipe_box *box, int w, int h)
77{
78   unsigned i;
79   int a[2], b[2], dim[2];
80   int *start, *end;
81   int res = 0;
82
83   if (!box->width || !box->height)
84      return -1;
85   dim[0] = w;
86   dim[1] = h;
87   a[0] = box->x;
88   a[1] = box->y;
89   b[0] = box->x + box->width;
90   b[1] = box->y + box->height;
91
92   for (i = 0; i < 2; ++i) {
93      start = (a[i] <= b[i]) ? &a[i] : &b[i];
94      end = (a[i] <= b[i]) ? &b[i] : &a[i];
95
96      if (*end < 0 || *start >= dim[i])
97         return -1;
98      if (*start < 0) {
99         *start = 0;
100         res |= (1 << i);
101      }
102      if (*end > dim[i]) {
103         *end = dim[i];
104         res |= (1 << i);
105      }
106   }
107
108   if (res) {
109      dst->x = a[0];
110      dst->y = a[1];
111      dst->width = b[0] - a[0];
112      dst->height = b[1] - a[1];
113   }
114   return res;
115}
116
117static inline int64_t
118u_box_volume_3d(const struct pipe_box *box)
119{
120   return (int64_t)box->width * box->height * box->depth;
121}
122
123/* Aliasing of @dst permitted. Supports empty width */
124static inline void
125u_box_union_1d(struct pipe_box *dst,
126               const struct pipe_box *a, const struct pipe_box *b)
127{
128   int x, width;
129
130   if (a->width == 0) {
131       x = b->x;
132       width = b->width;
133   } else if (b->width == 0) {
134       x = a->x;
135       width = a->width;
136   } else {
137       x = MIN2(a->x, b->x);
138       width = MAX2(a->x + a->width, b->x + b->width) - x;
139   }
140
141   dst->x = x;
142   dst->width = width;
143}
144
145/* Aliasing of @dst permitted. */
146static inline void
147u_box_intersect_1d(struct pipe_box *dst,
148               const struct pipe_box *a, const struct pipe_box *b)
149{
150   int x;
151
152   x = MAX2(a->x, b->x);
153
154   dst->width = MIN2(a->x + a->width, b->x + b->width) - x;
155   dst->x = x;
156   if (dst->width <= 0) {
157      dst->x = 0;
158      dst->width = 0;
159   }
160}
161
162/* Aliasing of @dst permitted. */
163static inline void
164u_box_union_2d(struct pipe_box *dst,
165               const struct pipe_box *a, const struct pipe_box *b)
166{
167   int x, y;
168
169   x = MIN2(a->x, b->x);
170   y = MIN2(a->y, b->y);
171
172   dst->width = MAX2(a->x + a->width, b->x + b->width) - x;
173   dst->height = MAX2(a->y + a->height, b->y + b->height) - y;
174   dst->x = x;
175   dst->y = y;
176}
177
178/* Aliasing of @dst permitted. */
179static inline void
180u_box_union_3d(struct pipe_box *dst,
181               const struct pipe_box *a, const struct pipe_box *b)
182{
183   int x, y, z;
184
185   x = MIN2(a->x, b->x);
186   y = MIN2(a->y, b->y);
187   z = MIN2(a->z, b->z);
188
189   dst->width = MAX2(a->x + a->width, b->x + b->width) - x;
190   dst->height = MAX2(a->y + a->height, b->y + b->height) - y;
191   dst->depth = MAX2(a->z + a->depth, b->z + b->depth) - z;
192   dst->x = x;
193   dst->y = y;
194   dst->z = z;
195}
196
197static inline boolean
198u_box_test_intersection_2d(const struct pipe_box *a,
199                           const struct pipe_box *b)
200{
201   unsigned i;
202   int a_l[2], a_r[2], b_l[2], b_r[2];
203
204   a_l[0] = MIN2(a->x, a->x + a->width);
205   a_r[0] = MAX2(a->x, a->x + a->width);
206   a_l[1] = MIN2(a->y, a->y + a->height);
207   a_r[1] = MAX2(a->y, a->y + a->height);
208
209   b_l[0] = MIN2(b->x, b->x + b->width);
210   b_r[0] = MAX2(b->x, b->x + b->width);
211   b_l[1] = MIN2(b->y, b->y + b->height);
212   b_r[1] = MAX2(b->y, b->y + b->height);
213
214   for (i = 0; i < 2; ++i) {
215      if (a_l[i] > b_r[i] || a_r[i] < b_l[i])
216         return FALSE;
217   }
218   return TRUE;
219}
220
221static inline void
222u_box_minify_2d(struct pipe_box *dst,
223                const struct pipe_box *src, unsigned l)
224{
225   dst->x = src->x >> l;
226   dst->y = src->y >> l;
227   dst->width = MAX2(src->width >> l, 1);
228   dst->height = MAX2(src->height >> l, 1);
229}
230
231static inline void
232u_box_minify_3d(struct pipe_box *dst,
233                const struct pipe_box *src, unsigned l)
234{
235   dst->x = src->x >> l;
236   dst->y = src->y >> l;
237   dst->z = src->z >> l;
238   dst->width = MAX2(src->width >> l, 1);
239   dst->height = MAX2(src->height >> l, 1);
240   dst->depth = MAX2(src->depth >> l, 1);
241}
242
243/* Converts a box specified in pixels to an equivalent box specified
244 * in blocks, where the boxes represent a region-of-interest of an image with
245 * the given format. This is trivial (a copy) for uncompressed formats.
246 */
247static inline void
248u_box_pixels_to_blocks(struct pipe_box *blocks,
249                       const struct pipe_box *pixels, enum pipe_format format)
250{
251   u_box_3d(
252         pixels->x / util_format_get_blockwidth(format),
253         pixels->y / util_format_get_blockheight(format),
254         pixels->z,
255         DIV_ROUND_UP(pixels->width, util_format_get_blockwidth(format)),
256         DIV_ROUND_UP(pixels->height, util_format_get_blockheight(format)),
257         pixels->depth,
258         blocks);
259}
260
261#endif
262