• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 2012-2015 LunarG, Inc.
5  *
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:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
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.
23  *
24  * Authors:
25  *    Chia-I Wu <olv@lunarg.com>
26  */
27 
28 #include "ilo_debug.h"
29 #include "ilo_state_viewport.h"
30 
31 static void
viewport_matrix_get_gen6_guardband(const struct ilo_dev * dev,const struct ilo_state_viewport_matrix_info * mat,float * min_gbx,float * max_gbx,float * min_gby,float * max_gby)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)
36 {
37    /*
38     * From the Sandy Bridge PRM, volume 2 part 1, page 234:
39     *
40     *     "Per-Device Guardband Extents
41     *
42     *       - Supported X,Y ScreenSpace "Guardband" Extent: [-16K,16K-1]
43     *       - Maximum Post-Clamp Delta (X or Y): 16K"
44     *
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."
49     *
50     * From the Ivy Bridge PRM, volume 2 part 1, page 248:
51     *
52     *     "Per-Device Guardband Extents
53     *
54     *       - Supported X,Y ScreenSpace "Guardband" Extent: [-32K,32K-1]
55     *       - Maximum Post-Clamp Delta (X or Y): N/A"
56     *
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."
61     *
62     * Combined, the bounding box of any object can not exceed 8K in both
63     * width and height.
64     *
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.
69     */
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;
75 
76    ILO_DEV_ASSERT(dev, 6, 8);
77 
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;
83 
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;
88 
89    scale_x = fabsf(mat->scale[0]);
90    scale_y = fabsf(mat->scale[1]);
91    /*
92     * From the Haswell PRM, volume 2d, page 292-293:
93     *
94     *     "Note: Minimum allowed value for this field (X/Y Min Clip Guardband)
95     *      is -16384."
96     *
97     *     "Note: Maximum allowed value for this field (X/Y Max Clip Guardband)
98     *      is 16383."
99     *
100     * Avoid small scales.
101     */
102    if (scale_x < 1.0f)
103       scale_x = 1.0f;
104    if (scale_y < 1.0f)
105       scale_y = 1.0f;
106 
107    /* in NDC space */
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;
112 }
113 
114 static void
viewport_matrix_get_extent(const struct ilo_state_viewport_matrix_info * mat,int axis,float * min,float * max)115 viewport_matrix_get_extent(const struct ilo_state_viewport_matrix_info *mat,
116                            int axis, float *min, float *max)
117 {
118    const float scale_abs = fabsf(mat->scale[axis]);
119 
120    *min = -1.0f * scale_abs + mat->translate[axis];
121    *max =  1.0f * scale_abs + mat->translate[axis];
122 }
123 
124 static bool
viewport_matrix_set_gen7_SF_CLIP_VIEWPORT(struct ilo_state_viewport * vp,const struct ilo_dev * dev,const struct ilo_state_viewport_matrix_info * matrices,uint8_t count)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,
128                                           uint8_t count)
129 {
130    uint8_t i;
131 
132    ILO_DEV_ASSERT(dev, 6, 8);
133 
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;
137       uint32_t dw[16];
138 
139       viewport_matrix_get_gen6_guardband(dev, mat,
140             &min_gbx, &max_gbx, &min_gby, &max_gby);
141 
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]);
148       dw[6] = 0;
149       dw[7] = 0;
150 
151       dw[8] = fui(min_gbx);
152       dw[9] = fui(max_gbx);
153       dw[10] = fui(min_gby);
154       dw[11] = fui(max_gby);
155 
156       if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
157          float min_x, max_x, min_y, max_y;
158 
159          viewport_matrix_get_extent(mat, 0, &min_x, &max_x);
160          viewport_matrix_get_extent(mat, 1, &min_y, &max_y);
161 
162          dw[12] = fui(min_x);
163          dw[13] = fui(max_x - 1.0f);
164          dw[14] = fui(min_y);
165          dw[15] = fui(max_y - 1.0f);
166       } else {
167          dw[12] = 0;
168          dw[13] = 0;
169          dw[14] = 0;
170          dw[15] = 0;
171       }
172 
173       STATIC_ASSERT(ARRAY_SIZE(vp->sf_clip[i]) >= 16);
174       memcpy(vp->sf_clip[i], dw, sizeof(dw));
175    }
176 
177    return true;
178 }
179 
180 static bool
viewport_matrix_set_gen6_CC_VIEWPORT(struct ilo_state_viewport * vp,const struct ilo_dev * dev,const struct ilo_state_viewport_matrix_info * matrices,uint8_t count)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,
184                                      uint8_t count)
185 {
186    uint8_t i;
187 
188    ILO_DEV_ASSERT(dev, 6, 8);
189 
190    for (i = 0; i < count; i++) {
191       const struct ilo_state_viewport_matrix_info *mat = &matrices[i];
192       float min_z, max_z;
193 
194       viewport_matrix_get_extent(mat, 2, &min_z, &max_z);
195 
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);
199    }
200 
201    return true;
202 }
203 
204 static bool
viewport_scissor_set_gen6_SCISSOR_RECT(struct ilo_state_viewport * vp,const struct ilo_dev * dev,const struct ilo_state_viewport_scissor_info * scissors,uint8_t count)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,
208                                        uint8_t count)
209 {
210    const uint16_t max_size = (ilo_dev_gen(dev) >= ILO_GEN(7)) ? 16384 : 8192;
211    uint8_t i;
212 
213    ILO_DEV_ASSERT(dev, 6, 8);
214 
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;
218       uint32_t dw0, dw1;
219 
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;
224 
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;
229 
230       STATIC_ASSERT(ARRAY_SIZE(vp->scissor[i]) >= 2);
231       vp->scissor[i][0] = dw0;
232       vp->scissor[i][1] = dw1;
233    }
234 
235    return true;
236 }
237 
238 bool
ilo_state_viewport_init(struct ilo_state_viewport * vp,const struct ilo_dev * dev,const struct ilo_state_viewport_info * info)239 ilo_state_viewport_init(struct ilo_state_viewport *vp,
240                         const struct ilo_dev *dev,
241                         const struct ilo_state_viewport_info *info)
242 {
243    const size_t elem_size = ilo_state_viewport_data_size(dev, 1);
244 
245    assert(ilo_is_zeroed(vp, sizeof(*vp)));
246    assert(ilo_is_zeroed(info->data, info->data_size));
247 
248    vp->data = info->data;
249 
250    if (info->data_size / elem_size < ILO_STATE_VIEWPORT_MAX_COUNT)
251       vp->array_size = info->data_size / elem_size;
252    else
253       vp->array_size = ILO_STATE_VIEWPORT_MAX_COUNT;
254 
255    return ilo_state_viewport_set_params(vp, dev, &info->params, false);
256 }
257 
258 bool
ilo_state_viewport_init_data_only(struct ilo_state_viewport * vp,const struct ilo_dev * dev,void * data,size_t data_size)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)
262 {
263    struct ilo_state_viewport_info info;
264 
265    memset(&info, 0, sizeof(info));
266    info.data = data;
267    info.data_size = data_size;
268 
269    return ilo_state_viewport_init(vp, dev, &info);
270 }
271 
272 bool
ilo_state_viewport_init_for_rectlist(struct ilo_state_viewport * vp,const struct ilo_dev * dev,void * data,size_t data_size)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)
276 {
277    struct ilo_state_viewport_info info;
278    struct ilo_state_viewport_matrix_info mat;
279    struct ilo_state_viewport_scissor_info sci;
280 
281    memset(&info, 0, sizeof(info));
282    memset(&mat, 0, sizeof(mat));
283    memset(&sci, 0, sizeof(sci));
284 
285    info.data = data;
286    info.data_size = data_size;
287    info.params.matrices = &mat;
288    info.params.scissors = &sci;
289    info.params.count = 1;
290 
291    mat.scale[0] = 1.0f;
292    mat.scale[1] = 1.0f;
293    mat.scale[2] = 1.0f;
294 
295    return ilo_state_viewport_init(vp, dev, &info);
296 }
297 
298 static void
viewport_set_count(struct ilo_state_viewport * vp,const struct ilo_dev * dev,uint8_t count)299 viewport_set_count(struct ilo_state_viewport *vp,
300                    const struct ilo_dev *dev,
301                    uint8_t count)
302 {
303    assert(count <= vp->array_size);
304 
305    vp->count = count;
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);
309 }
310 
311 bool
ilo_state_viewport_set_params(struct ilo_state_viewport * vp,const struct ilo_dev * dev,const struct ilo_state_viewport_params_info * params,bool scissors_only)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,
315                               bool scissors_only)
316 {
317    bool ret = true;
318 
319    if (scissors_only) {
320       assert(vp->count == params->count);
321 
322       ret &= viewport_scissor_set_gen6_SCISSOR_RECT(vp, dev,
323             params->scissors, params->count);
324    } else {
325       viewport_set_count(vp, dev, params->count);
326 
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);
333    }
334 
335    assert(ret);
336 
337    return ret;
338 }
339 
340 void
ilo_state_viewport_full_delta(const struct ilo_state_viewport * vp,const struct ilo_dev * dev,struct ilo_state_viewport_delta * delta)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)
344 {
345    delta->dirty = ILO_STATE_VIEWPORT_SF_CLIP_VIEWPORT |
346                   ILO_STATE_VIEWPORT_CC_VIEWPORT |
347                   ILO_STATE_VIEWPORT_SCISSOR_RECT;
348 }
349 
350 void
ilo_state_viewport_get_delta(const struct ilo_state_viewport * vp,const struct ilo_dev * dev,const struct ilo_state_viewport * old,struct ilo_state_viewport_delta * delta)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)
355 {
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;
359 
360    /* no shallow copying */
361    assert(vp->data != old->data);
362 
363    if (vp->count != old->count) {
364       ilo_state_viewport_full_delta(vp, dev, delta);
365       return;
366    }
367 
368    delta->dirty = 0;
369 
370    if (memcmp(vp->sf_clip, old->sf_clip, sf_clip_size))
371       delta->dirty |= ILO_STATE_VIEWPORT_SF_CLIP_VIEWPORT;
372 
373    if (memcmp(vp->cc, old->cc, cc_size))
374       delta->dirty |= ILO_STATE_VIEWPORT_CC_VIEWPORT;
375 
376    if (memcmp(vp->scissor, old->scissor, scissor_size))
377       delta->dirty |= ILO_STATE_VIEWPORT_SCISSOR_RECT;
378 }
379