1 /**************************************************************************
3 * Copyright 2010, VMware Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
29 * Binning code for points
32 #include "lp_setup_context.h"
33 #include "util/u_math.h"
34 #include "util/u_memory.h"
36 #include "lp_setup_context.h"
38 #include "lp_state_fs.h"
40 #define NUM_CHANNELS 4
52 * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
54 static void constant_coef( struct lp_setup_context
*setup
,
55 struct lp_rast_triangle
*point
,
60 point
->inputs
.a0
[slot
][i
] = value
;
61 point
->inputs
.dadx
[slot
][i
] = 0.0f
;
62 point
->inputs
.dady
[slot
][i
] = 0.0f
;
66 * Special coefficient setup for gl_FragCoord.
68 * Z and W are copied from position_coef which should have already been computed.
69 * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
72 setup_point_fragcoord_coef(struct lp_setup_context
*setup
,
73 struct lp_rast_triangle
*point
,
74 const struct point_info
*info
,
79 if (usage_mask
& TGSI_WRITEMASK_X
) {
80 point
->inputs
.a0
[slot
][0] = 0.0;
81 point
->inputs
.dadx
[slot
][0] = 1.0;
82 point
->inputs
.dady
[slot
][0] = 0.0;
86 if (usage_mask
& TGSI_WRITEMASK_Y
) {
87 point
->inputs
.a0
[slot
][1] = 0.0;
88 point
->inputs
.dadx
[slot
][1] = 0.0;
89 point
->inputs
.dady
[slot
][1] = 1.0;
93 if (usage_mask
& TGSI_WRITEMASK_Z
) {
94 constant_coef(setup
, point
, slot
, info
->v0
[0][2], 2);
98 if (usage_mask
& TGSI_WRITEMASK_W
) {
99 constant_coef(setup
, point
, slot
, info
->v0
[0][3], 3);
104 * Compute the point->coef[] array dadx, dady, a0 values.
107 setup_point_coefficients( struct lp_setup_context
*setup
,
108 struct lp_rast_triangle
*point
,
109 const struct point_info
*info
)
111 unsigned fragcoord_usage_mask
= TGSI_WRITEMASK_XYZ
;
114 /* setup interpolation for all the remaining attributes:
116 for (slot
= 0; slot
< setup
->fs
.nr_inputs
; slot
++) {
117 unsigned vert_attr
= setup
->fs
.input
[slot
].src_index
;
118 unsigned usage_mask
= setup
->fs
.input
[slot
].usage_mask
;
121 switch (setup
->fs
.input
[slot
].interp
) {
122 case LP_INTERP_POSITION
:
124 * The generated pixel interpolators will pick up the coeffs from
125 * slot 0, so all need to ensure that the usage mask is covers all
128 fragcoord_usage_mask
|= usage_mask
;
132 for (i
= 0; i
< NUM_CHANNELS
; i
++) {
133 if (usage_mask
& (1 << i
))
134 constant_coef(setup
, point
, slot
+1, info
->v0
[vert_attr
][i
], i
);
139 /* The internal position input is in slot zero:
141 setup_point_fragcoord_coef(setup
, point
, info
, 0,
142 fragcoord_usage_mask
);
146 subpixel_snap(float a
)
148 return util_iround(FIXED_ONE
* a
);
152 static void lp_setup_point( struct lp_setup_context
*setup
,
153 const float (*v0
)[4] )
155 /* x/y positions in fixed point */
156 const int sizeAttr
= setup
->psize
;
158 = sizeAttr
> 0 ? v0
[sizeAttr
][0]
160 const float half_width
= 0.5F
* size
;
162 const int x0
= subpixel_snap(v0
[0][0] - half_width
- setup
->pixel_offset
);
163 const int x1
= subpixel_snap(v0
[0][0] - half_width
- setup
->pixel_offset
);
164 const int x2
= subpixel_snap(v0
[0][0] + half_width
- setup
->pixel_offset
);
165 const int y0
= subpixel_snap(v0
[0][1] - half_width
- setup
->pixel_offset
);
166 const int y1
= subpixel_snap(v0
[0][1] + half_width
- setup
->pixel_offset
);
167 const int y2
= subpixel_snap(v0
[0][1] + half_width
- setup
->pixel_offset
);
168 struct lp_scene
*scene
= lp_setup_get_current_scene(setup
);
169 struct lp_rast_triangle
*point
;
172 unsigned nr_planes
= 4;
173 struct point_info info
;
176 /* Bounding rectangle (in pixels) */
178 /* Yes this is necessary to accurately calculate bounding boxes
179 * with the two fill-conventions we support. GL (normally) ends
180 * up needing a bottom-left fill convention, which requires
181 * slightly different rounding.
183 int adj
= (setup
->pixel_offset
!= 0) ? 1 : 0;
185 bbox
.x0
= (MIN3(x0
, x1
, x2
) + (FIXED_ONE
-1)) >> FIXED_ORDER
;
186 bbox
.x1
= (MAX3(x0
, x1
, x2
) + (FIXED_ONE
-1)) >> FIXED_ORDER
;
187 bbox
.y0
= (MIN3(y0
, y1
, y2
) + (FIXED_ONE
-1) + adj
) >> FIXED_ORDER
;
188 bbox
.y1
= (MAX3(y0
, y1
, y2
) + (FIXED_ONE
-1) + adj
) >> FIXED_ORDER
;
190 /* Inclusive coordinates:
196 if (!u_rect_test_intersection(&setup
->draw_region
, &bbox
)) {
197 if (0) debug_printf("offscreen\n");
198 LP_COUNT(nr_culled_tris
);
202 u_rect_find_intersection(&setup
->draw_region
, &bbox
);
204 point
= lp_setup_alloc_triangle(scene
,
212 point
->v
[0][0] = v0
[0][0];
213 point
->v
[0][1] = v0
[0][1];
222 /* Setup parameter interpolants:
224 setup_point_coefficients(setup
, point
, &info
);
226 point
->inputs
.facing
= 1.0F
;
227 point
->inputs
.state
= setup
->fs
.stored
;
230 point
->plane
[0].dcdx
= -1;
231 point
->plane
[0].dcdy
= 0;
232 point
->plane
[0].c
= 1-bbox
.x0
;
233 point
->plane
[0].ei
= 0;
234 point
->plane
[0].eo
= 1;
236 point
->plane
[1].dcdx
= 1;
237 point
->plane
[1].dcdy
= 0;
238 point
->plane
[1].c
= bbox
.x1
+1;
239 point
->plane
[1].ei
= -1;
240 point
->plane
[1].eo
= 0;
242 point
->plane
[2].dcdx
= 0;
243 point
->plane
[2].dcdy
= 1;
244 point
->plane
[2].c
= 1-bbox
.y0
;
245 point
->plane
[2].ei
= 0;
246 point
->plane
[2].eo
= 1;
248 point
->plane
[3].dcdx
= 0;
249 point
->plane
[3].dcdy
= -1;
250 point
->plane
[3].c
= bbox
.y1
+1;
251 point
->plane
[3].ei
= -1;
252 point
->plane
[3].eo
= 0;
255 lp_setup_bin_triangle(setup
, point
, &bbox
, nr_planes
);
260 lp_setup_choose_point( struct lp_setup_context
*setup
)
262 setup
->point
= lp_setup_point
;