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"
39 #include "tgsi/tgsi_scan.h"
41 #define NUM_CHANNELS 4
53 * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
56 constant_coef(struct lp_setup_context
*setup
,
57 struct lp_rast_triangle
*point
,
62 point
->inputs
.a0
[slot
][i
] = value
;
63 point
->inputs
.dadx
[slot
][i
] = 0.0f
;
64 point
->inputs
.dady
[slot
][i
] = 0.0f
;
69 perspective_coef(struct lp_setup_context
*setup
,
70 struct lp_rast_triangle
*point
,
71 const struct point_info
*info
,
75 unsigned sprite_coord_origin
)
78 float dadx
= FIXED_ONE
/ (float)info
->dx12
;
80 point
->inputs
.dadx
[slot
][i
] = dadx
;
81 point
->inputs
.dady
[slot
][i
] = dady
;
82 point
->inputs
.a0
[slot
][i
] = (0.5 -
83 (dadx
* ((float)info
->v0
[0][0] - setup
->pixel_offset
) +
84 dady
* ((float)info
->v0
[0][1] - setup
->pixel_offset
)));
88 float dady
= FIXED_ONE
/ (float)info
->dx12
;
90 if (sprite_coord_origin
== PIPE_SPRITE_COORD_LOWER_LEFT
) {
94 point
->inputs
.dadx
[slot
][i
] = dadx
;
95 point
->inputs
.dady
[slot
][i
] = dady
;
96 point
->inputs
.a0
[slot
][i
] = (0.5 -
97 (dadx
* ((float)info
->v0
[0][0] - setup
->pixel_offset
) +
98 dady
* ((float)info
->v0
[0][1] - setup
->pixel_offset
)));
101 point
->inputs
.a0
[slot
][i
] = 0.0f
;
102 point
->inputs
.dadx
[slot
][i
] = 0.0f
;
103 point
->inputs
.dady
[slot
][i
] = 0.0f
;
106 point
->inputs
.a0
[slot
][i
] = 1.0f
;
107 point
->inputs
.dadx
[slot
][i
] = 0.0f
;
108 point
->inputs
.dady
[slot
][i
] = 0.0f
;
114 * Special coefficient setup for gl_FragCoord.
115 * X and Y are trivial
116 * Z and W are copied from position_coef which should have already been computed.
117 * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
120 setup_point_fragcoord_coef(struct lp_setup_context
*setup
,
121 struct lp_rast_triangle
*point
,
122 const struct point_info
*info
,
127 if (usage_mask
& TGSI_WRITEMASK_X
) {
128 point
->inputs
.a0
[slot
][0] = 0.0;
129 point
->inputs
.dadx
[slot
][0] = 1.0;
130 point
->inputs
.dady
[slot
][0] = 0.0;
134 if (usage_mask
& TGSI_WRITEMASK_Y
) {
135 point
->inputs
.a0
[slot
][1] = 0.0;
136 point
->inputs
.dadx
[slot
][1] = 0.0;
137 point
->inputs
.dady
[slot
][1] = 1.0;
141 if (usage_mask
& TGSI_WRITEMASK_Z
) {
142 constant_coef(setup
, point
, slot
, info
->v0
[0][2], 2);
146 if (usage_mask
& TGSI_WRITEMASK_W
) {
147 constant_coef(setup
, point
, slot
, info
->v0
[0][3], 3);
153 * Compute the point->coef[] array dadx, dady, a0 values.
156 setup_point_coefficients( struct lp_setup_context
*setup
,
157 struct lp_rast_triangle
*point
,
158 const struct point_info
*info
)
160 const struct lp_fragment_shader
*shader
= setup
->fs
.current
.variant
->shader
;
161 unsigned fragcoord_usage_mask
= TGSI_WRITEMASK_XYZ
;
164 /* setup interpolation for all the remaining attributes:
166 for (slot
= 0; slot
< setup
->fs
.nr_inputs
; slot
++) {
167 unsigned vert_attr
= setup
->fs
.input
[slot
].src_index
;
168 unsigned usage_mask
= setup
->fs
.input
[slot
].usage_mask
;
171 switch (setup
->fs
.input
[slot
].interp
) {
172 case LP_INTERP_POSITION
:
174 * The generated pixel interpolators will pick up the coeffs from
175 * slot 0, so all need to ensure that the usage mask is covers all
178 fragcoord_usage_mask
|= usage_mask
;
181 case LP_INTERP_LINEAR
:
182 /* Sprite tex coords may use linear interpolation someday */
185 case LP_INTERP_PERSPECTIVE
:
186 /* check if the sprite coord flag is set for this attribute.
187 * If so, set it up so it up so x any y vary from 0 to 1.
189 if (shader
->info
.input_semantic_name
[slot
] == TGSI_SEMANTIC_GENERIC
) {
190 const int index
= shader
->info
.input_semantic_index
[slot
];
192 if (setup
->sprite_coord_enable
& (1 << index
)) {
193 for (i
= 0; i
< NUM_CHANNELS
; i
++)
194 if (usage_mask
& (1 << i
))
195 perspective_coef(setup
, point
, info
, slot
+1, vert_attr
, i
,
196 setup
->sprite_coord_origin
);
197 fragcoord_usage_mask
|= TGSI_WRITEMASK_W
;
202 /* Otherwise fallthrough */
204 for (i
= 0; i
< NUM_CHANNELS
; i
++) {
205 if (usage_mask
& (1 << i
))
206 constant_coef(setup
, point
, slot
+1, info
->v0
[vert_attr
][i
], i
);
211 /* The internal position input is in slot zero:
213 setup_point_fragcoord_coef(setup
, point
, info
, 0,
214 fragcoord_usage_mask
);
219 subpixel_snap(float a
)
221 return util_iround(FIXED_ONE
* a
);
226 try_setup_point( struct lp_setup_context
*setup
,
227 const float (*v0
)[4] )
229 /* x/y positions in fixed point */
230 const int sizeAttr
= setup
->psize
;
232 = (setup
->point_size_per_vertex
&& sizeAttr
> 0) ? v0
[sizeAttr
][0]
235 /* Point size as fixed point integer, remove rounding errors
236 * and gives minimum width for very small points
238 int fixed_width
= MAX2(FIXED_ONE
,
239 (subpixel_snap(size
) + FIXED_ONE
/2 - 1) & ~(FIXED_ONE
-1));
241 const int x0
= subpixel_snap(v0
[0][0] - setup
->pixel_offset
) - fixed_width
/2;
242 const int y0
= subpixel_snap(v0
[0][1] - setup
->pixel_offset
) - fixed_width
/2;
244 struct lp_scene
*scene
= setup
->scene
;
245 struct lp_rast_triangle
*point
;
248 unsigned nr_planes
= 4;
249 struct point_info info
;
252 /* Bounding rectangle (in pixels) */
254 /* Yes this is necessary to accurately calculate bounding boxes
255 * with the two fill-conventions we support. GL (normally) ends
256 * up needing a bottom-left fill convention, which requires
257 * slightly different rounding.
259 int adj
= (setup
->pixel_offset
!= 0) ? 1 : 0;
261 bbox
.x0
= (x0
+ (FIXED_ONE
-1) + adj
) >> FIXED_ORDER
;
262 bbox
.x1
= (x0
+ fixed_width
+ (FIXED_ONE
-1) + adj
) >> FIXED_ORDER
;
263 bbox
.y0
= (y0
+ (FIXED_ONE
-1)) >> FIXED_ORDER
;
264 bbox
.y1
= (y0
+ fixed_width
+ (FIXED_ONE
-1)) >> FIXED_ORDER
;
266 /* Inclusive coordinates:
272 if (!u_rect_test_intersection(&setup
->draw_region
, &bbox
)) {
273 if (0) debug_printf("offscreen\n");
274 LP_COUNT(nr_culled_tris
);
278 u_rect_find_intersection(&setup
->draw_region
, &bbox
);
280 point
= lp_setup_alloc_triangle(scene
,
288 point
->v
[0][0] = v0
[0][0];
289 point
->v
[0][1] = v0
[0][1];
294 info
.dx12
= fixed_width
;
295 info
.dy01
= fixed_width
;
298 /* Setup parameter interpolants:
300 setup_point_coefficients(setup
, point
, &info
);
302 point
->inputs
.facing
= 1.0F
;
303 point
->inputs
.state
= setup
->fs
.stored
;
304 point
->inputs
.disable
= FALSE
;
305 point
->inputs
.opaque
= FALSE
;
308 point
->plane
[0].dcdx
= -1;
309 point
->plane
[0].dcdy
= 0;
310 point
->plane
[0].c
= 1-bbox
.x0
;
311 point
->plane
[0].ei
= 0;
312 point
->plane
[0].eo
= 1;
314 point
->plane
[1].dcdx
= 1;
315 point
->plane
[1].dcdy
= 0;
316 point
->plane
[1].c
= bbox
.x1
+1;
317 point
->plane
[1].ei
= -1;
318 point
->plane
[1].eo
= 0;
320 point
->plane
[2].dcdx
= 0;
321 point
->plane
[2].dcdy
= 1;
322 point
->plane
[2].c
= 1-bbox
.y0
;
323 point
->plane
[2].ei
= 0;
324 point
->plane
[2].eo
= 1;
326 point
->plane
[3].dcdx
= 0;
327 point
->plane
[3].dcdy
= -1;
328 point
->plane
[3].c
= bbox
.y1
+1;
329 point
->plane
[3].ei
= -1;
330 point
->plane
[3].eo
= 0;
333 return lp_setup_bin_triangle(setup
, point
, &bbox
, nr_planes
);
338 lp_setup_point(struct lp_setup_context
*setup
,
339 const float (*v0
)[4])
341 if (!try_setup_point( setup
, v0
))
343 lp_setup_flush_and_restart(setup
);
345 if (!try_setup_point( setup
, v0
))
352 lp_setup_choose_point( struct lp_setup_context
*setup
)
354 setup
->point
= lp_setup_point
;