2 * Mesa 3-D graphics library
4 * Copyright (C) 2012-2015 LunarG, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
25 * Chia-I Wu <olv@lunarg.com>
28 #include "ilo_debug.h"
29 #include "ilo_state_viewport.h"
32 viewport_matrix_get_gen6_guardband(const struct ilo_dev
*dev
,
33 const struct ilo_state_viewport_matrix_info
*mat
,
34 float *min_gbx
, float *max_gbx
,
35 float *min_gby
, float *max_gby
)
38 * From the Sandy Bridge PRM, volume 2 part 1, page 234:
40 * "Per-Device Guardband Extents
42 * - Supported X,Y ScreenSpace "Guardband" Extent: [-16K,16K-1]
43 * - Maximum Post-Clamp Delta (X or Y): 16K"
45 * "In addition, in order to be correctly rendered, objects must have a
46 * screenspace bounding box not exceeding 8K in the X or Y direction.
47 * This additional restriction must also be comprehended by software,
48 * i.e., enforced by use of clipping."
50 * From the Ivy Bridge PRM, volume 2 part 1, page 248:
52 * "Per-Device Guardband Extents
54 * - Supported X,Y ScreenSpace "Guardband" Extent: [-32K,32K-1]
55 * - Maximum Post-Clamp Delta (X or Y): N/A"
57 * "In addition, in order to be correctly rendered, objects must have a
58 * screenspace bounding box not exceeding 8K in the X or Y direction.
59 * This additional restriction must also be comprehended by software,
60 * i.e., enforced by use of clipping."
62 * Combined, the bounding box of any object can not exceed 8K in both
65 * Below we set the guardband as a squre of length 8K, centered at where
66 * the viewport is. This makes sure all objects passing the GB test are
67 * valid to the renderer, and those failing the XY clipping have a
68 * better chance of passing the GB test.
70 const int max_extent
= (ilo_dev_gen(dev
) >= ILO_GEN(7)) ? 32768 : 16384;
71 const int half_len
= 8192 / 2;
72 int center_x
= (int) mat
->translate
[0];
73 int center_y
= (int) mat
->translate
[1];
74 float scale_x
, scale_y
;
76 ILO_DEV_ASSERT(dev
, 6, 8);
78 /* make sure the guardband is within the valid range */
79 if (center_x
- half_len
< -max_extent
)
80 center_x
= -max_extent
+ half_len
;
81 else if (center_x
+ half_len
> max_extent
- 1)
82 center_x
= max_extent
- half_len
;
84 if (center_y
- half_len
< -max_extent
)
85 center_y
= -max_extent
+ half_len
;
86 else if (center_y
+ half_len
> max_extent
- 1)
87 center_y
= max_extent
- half_len
;
89 scale_x
= fabsf(mat
->scale
[0]);
90 scale_y
= fabsf(mat
->scale
[1]);
92 * From the Haswell PRM, volume 2d, page 292-293:
94 * "Note: Minimum allowed value for this field (X/Y Min Clip Guardband)
97 * "Note: Maximum allowed value for this field (X/Y Max Clip Guardband)
100 * Avoid small scales.
108 *min_gbx
= ((float) (center_x
- half_len
) - mat
->translate
[0]) / scale_x
;
109 *max_gbx
= ((float) (center_x
+ half_len
) - mat
->translate
[0]) / scale_x
;
110 *min_gby
= ((float) (center_y
- half_len
) - mat
->translate
[1]) / scale_y
;
111 *max_gby
= ((float) (center_y
+ half_len
) - mat
->translate
[1]) / scale_y
;
115 viewport_matrix_get_extent(const struct ilo_state_viewport_matrix_info
*mat
,
116 int axis
, float *min
, float *max
)
118 const float scale_abs
= fabsf(mat
->scale
[axis
]);
120 *min
= -1.0f
* scale_abs
+ mat
->translate
[axis
];
121 *max
= 1.0f
* scale_abs
+ mat
->translate
[axis
];
125 viewport_matrix_set_gen7_SF_CLIP_VIEWPORT(struct ilo_state_viewport
*vp
,
126 const struct ilo_dev
*dev
,
127 const struct ilo_state_viewport_matrix_info
*matrices
,
132 ILO_DEV_ASSERT(dev
, 6, 8);
134 for (i
= 0; i
< count
; i
++) {
135 const struct ilo_state_viewport_matrix_info
*mat
= &matrices
[i
];
136 float min_gbx
, max_gbx
, min_gby
, max_gby
;
139 viewport_matrix_get_gen6_guardband(dev
, mat
,
140 &min_gbx
, &max_gbx
, &min_gby
, &max_gby
);
142 dw
[0] = fui(mat
->scale
[0]);
143 dw
[1] = fui(mat
->scale
[1]);
144 dw
[2] = fui(mat
->scale
[2]);
145 dw
[3] = fui(mat
->translate
[0]);
146 dw
[4] = fui(mat
->translate
[1]);
147 dw
[5] = fui(mat
->translate
[2]);
151 dw
[8] = fui(min_gbx
);
152 dw
[9] = fui(max_gbx
);
153 dw
[10] = fui(min_gby
);
154 dw
[11] = fui(max_gby
);
156 if (ilo_dev_gen(dev
) >= ILO_GEN(8)) {
157 float min_x
, max_x
, min_y
, max_y
;
159 viewport_matrix_get_extent(mat
, 0, &min_x
, &max_x
);
160 viewport_matrix_get_extent(mat
, 1, &min_y
, &max_y
);
163 dw
[13] = fui(max_x
- 1.0f
);
165 dw
[15] = fui(max_y
- 1.0f
);
173 STATIC_ASSERT(ARRAY_SIZE(vp
->sf_clip
[i
]) >= 16);
174 memcpy(vp
->sf_clip
[i
], dw
, sizeof(dw
));
181 viewport_matrix_set_gen6_CC_VIEWPORT(struct ilo_state_viewport
*vp
,
182 const struct ilo_dev
*dev
,
183 const struct ilo_state_viewport_matrix_info
*matrices
,
188 ILO_DEV_ASSERT(dev
, 6, 8);
190 for (i
= 0; i
< count
; i
++) {
191 const struct ilo_state_viewport_matrix_info
*mat
= &matrices
[i
];
194 viewport_matrix_get_extent(mat
, 2, &min_z
, &max_z
);
196 STATIC_ASSERT(ARRAY_SIZE(vp
->cc
[i
]) >= 2);
197 vp
->cc
[i
][0] = fui(min_z
);
198 vp
->cc
[i
][1] = fui(max_z
);
205 viewport_scissor_set_gen6_SCISSOR_RECT(struct ilo_state_viewport
*vp
,
206 const struct ilo_dev
*dev
,
207 const struct ilo_state_viewport_scissor_info
*scissors
,
210 const uint16_t max_size
= (ilo_dev_gen(dev
) >= ILO_GEN(7)) ? 16384 : 8192;
213 ILO_DEV_ASSERT(dev
, 6, 8);
215 for (i
= 0; i
< count
; i
++) {
216 const struct ilo_state_viewport_scissor_info
*scissor
= &scissors
[i
];
217 uint16_t min_x
, min_y
, max_x
, max_y
;
220 min_x
= (scissor
->min_x
< max_size
) ? scissor
->min_x
: max_size
- 1;
221 min_y
= (scissor
->min_y
< max_size
) ? scissor
->min_y
: max_size
- 1;
222 max_x
= (scissor
->max_x
< max_size
) ? scissor
->max_x
: max_size
- 1;
223 max_y
= (scissor
->max_y
< max_size
) ? scissor
->max_y
: max_size
- 1;
225 dw0
= min_y
<< GEN6_SCISSOR_DW0_MIN_Y__SHIFT
|
226 min_x
<< GEN6_SCISSOR_DW0_MIN_X__SHIFT
;
227 dw1
= max_y
<< GEN6_SCISSOR_DW1_MAX_Y__SHIFT
|
228 max_x
<< GEN6_SCISSOR_DW1_MAX_X__SHIFT
;
230 STATIC_ASSERT(ARRAY_SIZE(vp
->scissor
[i
]) >= 2);
231 vp
->scissor
[i
][0] = dw0
;
232 vp
->scissor
[i
][1] = dw1
;
239 ilo_state_viewport_init(struct ilo_state_viewport
*vp
,
240 const struct ilo_dev
*dev
,
241 const struct ilo_state_viewport_info
*info
)
243 const size_t elem_size
= ilo_state_viewport_data_size(dev
, 1);
245 assert(ilo_is_zeroed(vp
, sizeof(*vp
)));
246 assert(ilo_is_zeroed(info
->data
, info
->data_size
));
248 vp
->data
= info
->data
;
250 if (info
->data_size
/ elem_size
< ILO_STATE_VIEWPORT_MAX_COUNT
)
251 vp
->array_size
= info
->data_size
/ elem_size
;
253 vp
->array_size
= ILO_STATE_VIEWPORT_MAX_COUNT
;
255 return ilo_state_viewport_set_params(vp
, dev
, &info
->params
, false);
259 ilo_state_viewport_init_data_only(struct ilo_state_viewport
*vp
,
260 const struct ilo_dev
*dev
,
261 void *data
, size_t data_size
)
263 struct ilo_state_viewport_info info
;
265 memset(&info
, 0, sizeof(info
));
267 info
.data_size
= data_size
;
269 return ilo_state_viewport_init(vp
, dev
, &info
);
273 ilo_state_viewport_init_for_rectlist(struct ilo_state_viewport
*vp
,
274 const struct ilo_dev
*dev
,
275 void *data
, size_t data_size
)
277 struct ilo_state_viewport_info info
;
278 struct ilo_state_viewport_matrix_info mat
;
279 struct ilo_state_viewport_scissor_info sci
;
281 memset(&info
, 0, sizeof(info
));
282 memset(&mat
, 0, sizeof(mat
));
283 memset(&sci
, 0, sizeof(sci
));
286 info
.data_size
= data_size
;
287 info
.params
.matrices
= &mat
;
288 info
.params
.scissors
= &sci
;
289 info
.params
.count
= 1;
295 return ilo_state_viewport_init(vp
, dev
, &info
);
299 viewport_set_count(struct ilo_state_viewport
*vp
,
300 const struct ilo_dev
*dev
,
303 assert(count
<= vp
->array_size
);
306 vp
->sf_clip
= (uint32_t (*)[16]) vp
->data
;
307 vp
->cc
= (uint32_t (*)[ 2]) (vp
->sf_clip
+ count
);
308 vp
->scissor
= (uint32_t (*)[ 2]) (vp
->cc
+ count
);
312 ilo_state_viewport_set_params(struct ilo_state_viewport
*vp
,
313 const struct ilo_dev
*dev
,
314 const struct ilo_state_viewport_params_info
*params
,
320 assert(vp
->count
== params
->count
);
322 ret
&= viewport_scissor_set_gen6_SCISSOR_RECT(vp
, dev
,
323 params
->scissors
, params
->count
);
325 viewport_set_count(vp
, dev
, params
->count
);
327 ret
&= viewport_matrix_set_gen7_SF_CLIP_VIEWPORT(vp
, dev
,
328 params
->matrices
, params
->count
);
329 ret
&= viewport_matrix_set_gen6_CC_VIEWPORT(vp
, dev
,
330 params
->matrices
, params
->count
);
331 ret
&= viewport_scissor_set_gen6_SCISSOR_RECT(vp
, dev
,
332 params
->scissors
, params
->count
);
341 ilo_state_viewport_full_delta(const struct ilo_state_viewport
*vp
,
342 const struct ilo_dev
*dev
,
343 struct ilo_state_viewport_delta
*delta
)
345 delta
->dirty
= ILO_STATE_VIEWPORT_SF_CLIP_VIEWPORT
|
346 ILO_STATE_VIEWPORT_CC_VIEWPORT
|
347 ILO_STATE_VIEWPORT_SCISSOR_RECT
;
351 ilo_state_viewport_get_delta(const struct ilo_state_viewport
*vp
,
352 const struct ilo_dev
*dev
,
353 const struct ilo_state_viewport
*old
,
354 struct ilo_state_viewport_delta
*delta
)
356 const size_t sf_clip_size
= sizeof(vp
->sf_clip
[0]) * vp
->count
;
357 const size_t cc_size
= sizeof(vp
->cc
[0]) * vp
->count
;
358 const size_t scissor_size
= sizeof(vp
->scissor
[0]) * vp
->count
;
360 /* no shallow copying */
361 assert(vp
->data
!= old
->data
);
363 if (vp
->count
!= old
->count
) {
364 ilo_state_viewport_full_delta(vp
, dev
, delta
);
370 if (memcmp(vp
->sf_clip
, old
->sf_clip
, sf_clip_size
))
371 delta
->dirty
|= ILO_STATE_VIEWPORT_SF_CLIP_VIEWPORT
;
373 if (memcmp(vp
->cc
, old
->cc
, cc_size
))
374 delta
->dirty
|= ILO_STATE_VIEWPORT_CC_VIEWPORT
;
376 if (memcmp(vp
->scissor
, old
->scissor
, scissor_size
))
377 delta
->dirty
|= ILO_STATE_VIEWPORT_SCISSOR_RECT
;