1 /**************************************************************************
2 *
3 * Copyright 2010, VMware Inc.
4 * All Rights Reserved.
5 *
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:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
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.
25 *
26 **************************************************************************/
27
28 /*
29 * Binning code for points
30 */
31
32 #include "util/u_math.h"
33 #include "util/u_memory.h"
34 #include "lp_setup_context.h"
35 #include "lp_perf.h"
36 #include "lp_rast.h"
37 #include "lp_state_fs.h"
38 #include "lp_state_setup.h"
39 #include "lp_context.h"
40 #include "draw/draw_context.h"
41
42 #define NUM_CHANNELS 4
43
44 struct point_info {
45 /* x,y deltas */
46 int dy01, dy12;
47 int dx01, dx12;
48
49 const float (*v0)[4];
50
51 float (*a0)[4];
52 float (*dadx)[4];
53 float (*dady)[4];
54
55 bool frontfacing;
56 };
57
58
59 /**
60 * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
61 */
62 static void
constant_coef(struct lp_setup_context * setup,struct point_info * info,unsigned slot,const float value,unsigned i)63 constant_coef(struct lp_setup_context *setup,
64 struct point_info *info,
65 unsigned slot,
66 const float value,
67 unsigned i)
68 {
69 info->a0[slot][i] = value;
70 info->dadx[slot][i] = 0.0f;
71 info->dady[slot][i] = 0.0f;
72 }
73
74
75 static void
point_persp_coeff(struct lp_setup_context * setup,const struct point_info * info,unsigned slot,unsigned i)76 point_persp_coeff(struct lp_setup_context *setup,
77 const struct point_info *info,
78 unsigned slot,
79 unsigned i)
80 {
81 /*
82 * Fragment shader expects pre-multiplied w for LP_INTERP_PERSPECTIVE. A
83 * better strategy would be to take the primitive in consideration when
84 * generating the fragment shader key, and therefore avoid the per-fragment
85 * perspective divide.
86 */
87
88 float w0 = info->v0[0][3];
89
90 assert(i < 4);
91
92 info->a0[slot][i] = info->v0[slot][i]*w0;
93 info->dadx[slot][i] = 0.0f;
94 info->dady[slot][i] = 0.0f;
95 }
96
97
98 /**
99 * Setup automatic texcoord coefficients (for sprite rendering).
100 * \param slot the vertex attribute slot to setup
101 * \param i the attribute channel in [0,3]
102 * \param sprite_coord_origin one of PIPE_SPRITE_COORD_x
103 * \param perspective does the shader expects pre-multiplied w, i.e.,
104 * LP_INTERP_PERSPECTIVE is specified in the shader key
105 */
106 static void
texcoord_coef(struct lp_setup_context * setup,const struct point_info * info,unsigned slot,unsigned i,unsigned sprite_coord_origin,bool perspective)107 texcoord_coef(struct lp_setup_context *setup,
108 const struct point_info *info,
109 unsigned slot,
110 unsigned i,
111 unsigned sprite_coord_origin,
112 bool perspective)
113 {
114 float w0 = info->v0[0][3];
115
116 assert(i < 4);
117
118 if (i == 0) {
119 float dadx = FIXED_ONE / (float)info->dx12;
120 float dady = 0.0f;
121 float x0 = info->v0[0][0] - setup->pixel_offset;
122 float y0 = info->v0[0][1] - setup->pixel_offset;
123
124 info->dadx[slot][0] = dadx;
125 info->dady[slot][0] = dady;
126 info->a0[slot][0] = 0.5 - (dadx * x0 + dady * y0);
127
128 if (perspective) {
129 info->dadx[slot][0] *= w0;
130 info->dady[slot][0] *= w0;
131 info->a0[slot][0] *= w0;
132 }
133 } else if (i == 1) {
134 float dadx = 0.0f;
135 float dady = FIXED_ONE / (float)info->dx12;
136 float x0 = info->v0[0][0] - setup->pixel_offset;
137 float y0 = info->v0[0][1] - setup->pixel_offset;
138
139 if (sprite_coord_origin == PIPE_SPRITE_COORD_LOWER_LEFT) {
140 dady = -dady;
141 }
142
143 info->dadx[slot][1] = dadx;
144 info->dady[slot][1] = dady;
145 info->a0[slot][1] = 0.5 - (dadx * x0 + dady * y0);
146
147 if (perspective) {
148 info->dadx[slot][1] *= w0;
149 info->dady[slot][1] *= w0;
150 info->a0[slot][1] *= w0;
151 }
152 } else if (i == 2) {
153 info->a0[slot][2] = 0.0f;
154 info->dadx[slot][2] = 0.0f;
155 info->dady[slot][2] = 0.0f;
156 } else {
157 info->a0[slot][3] = perspective ? w0 : 1.0f;
158 info->dadx[slot][3] = 0.0f;
159 info->dady[slot][3] = 0.0f;
160 }
161 }
162
163
164 /**
165 * Special coefficient setup for gl_FragCoord. X and Y are trivial. Z and W
166 * are copied from position_coef which should have already been computed. We
167 * could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
168 */
169 static void
setup_point_fragcoord_coef(struct lp_setup_context * setup,struct point_info * info,unsigned slot,unsigned usage_mask)170 setup_point_fragcoord_coef(struct lp_setup_context *setup,
171 struct point_info *info,
172 unsigned slot,
173 unsigned usage_mask)
174 {
175 /*X*/
176 if (usage_mask & TGSI_WRITEMASK_X) {
177 info->a0[slot][0] = 0.0;
178 info->dadx[slot][0] = 1.0;
179 info->dady[slot][0] = 0.0;
180 }
181
182 /*Y*/
183 if (usage_mask & TGSI_WRITEMASK_Y) {
184 info->a0[slot][1] = 0.0;
185 info->dadx[slot][1] = 0.0;
186 info->dady[slot][1] = 1.0;
187 }
188
189 /*Z*/
190 if (usage_mask & TGSI_WRITEMASK_Z) {
191 constant_coef(setup, info, slot, info->v0[0][2], 2);
192 }
193
194 /*W*/
195 if (usage_mask & TGSI_WRITEMASK_W) {
196 constant_coef(setup, info, slot, info->v0[0][3], 3);
197 }
198 }
199
200
201 /**
202 * Compute the point->coef[] array dadx, dady, a0 values.
203 */
204 static void
setup_point_coefficients(struct lp_setup_context * setup,struct point_info * info)205 setup_point_coefficients(struct lp_setup_context *setup,
206 struct point_info *info)
207 {
208 const struct lp_setup_variant_key *key = &setup->setup.variant->key;
209 const struct lp_fragment_shader *shader = setup->fs.current.variant->shader;
210 unsigned fragcoord_usage_mask = TGSI_WRITEMASK_XYZ;
211
212 /* setup interpolation for all the remaining attributes:
213 */
214 for (unsigned slot = 0; slot < key->num_inputs; slot++) {
215 unsigned vert_attr = key->inputs[slot].src_index;
216 unsigned usage_mask = key->inputs[slot].usage_mask;
217 enum lp_interp interp = key->inputs[slot].interp;
218 bool perspective = !!(interp == LP_INTERP_PERSPECTIVE);
219 unsigned i;
220
221 if (perspective && usage_mask) {
222 fragcoord_usage_mask |= TGSI_WRITEMASK_W;
223 }
224
225 switch (interp) {
226 case LP_INTERP_POSITION:
227 /*
228 * The generated pixel interpolators will pick up the coeffs from
229 * slot 0, so all need to ensure that the usage mask is covers all
230 * usages.
231 */
232 fragcoord_usage_mask |= usage_mask;
233 break;
234 case LP_INTERP_LINEAR:
235 /* Sprite tex coords may use linear interpolation someday */
236 FALLTHROUGH;
237 case LP_INTERP_PERSPECTIVE: {
238 /* check if the sprite coord flag is set for this attribute.
239 * If so, set it up so it up so x and y vary from 0 to 1.
240 */
241 bool do_texcoord_coef = false;
242 if (shader->info.base.input_semantic_name[slot] ==
243 TGSI_SEMANTIC_PCOORD) {
244 do_texcoord_coef = true;
245 } else if (shader->info.base.input_semantic_name[slot] ==
246 TGSI_SEMANTIC_TEXCOORD) {
247 unsigned semantic_index =
248 shader->info.base.input_semantic_index[slot];
249 /* Note that sprite_coord enable is a bitfield of
250 * PIPE_MAX_SHADER_OUTPUTS bits.
251 */
252 if (semantic_index < PIPE_MAX_SHADER_OUTPUTS &&
253 (setup->sprite_coord_enable & (1u << semantic_index))) {
254 do_texcoord_coef = true;
255 }
256 }
257 if (do_texcoord_coef) {
258 for (i = 0; i < NUM_CHANNELS; i++) {
259 if (usage_mask & (1 << i)) {
260 texcoord_coef(setup, info, slot + 1, i,
261 setup->sprite_coord_origin,
262 perspective);
263 }
264 }
265 break;
266 }
267 }
268 FALLTHROUGH;
269 case LP_INTERP_CONSTANT:
270 for (i = 0; i < NUM_CHANNELS; i++) {
271 if (usage_mask & (1 << i)) {
272 if (perspective) {
273 point_persp_coeff(setup, info, slot+1, i);
274 } else {
275 constant_coef(setup, info, slot+1, info->v0[vert_attr][i], i);
276 }
277 }
278 }
279 break;
280 case LP_INTERP_FACING:
281 for (i = 0; i < NUM_CHANNELS; i++)
282 if (usage_mask & (1 << i))
283 constant_coef(setup, info, slot+1,
284 info->frontfacing ? 1.0f : -1.0f, i);
285 break;
286 default:
287 assert(0);
288 break;
289 }
290 }
291
292 /* The internal position input is in slot zero:
293 */
294 setup_point_fragcoord_coef(setup, info, 0,
295 fragcoord_usage_mask);
296 }
297
298
299 static inline int
subpixel_snap(float a)300 subpixel_snap(float a)
301 {
302 return util_iround(FIXED_ONE * a);
303 }
304
305
306 /**
307 * Print point vertex attribs (for debug).
308 */
309 static void
print_point(struct lp_setup_context * setup,const float (* v0)[4],const float size)310 print_point(struct lp_setup_context *setup,
311 const float (*v0)[4],
312 const float size)
313 {
314 const struct lp_setup_variant_key *key = &setup->setup.variant->key;
315
316 debug_printf("llvmpipe point, width %f\n", size);
317 for (unsigned i = 0; i < 1 + key->num_inputs; i++) {
318 debug_printf(" v0[%d]: %f %f %f %f\n", i,
319 v0[i][0], v0[i][1], v0[i][2], v0[i][3]);
320 }
321 }
322
323
324 static bool
try_setup_point(struct lp_setup_context * setup,const float (* v0)[4])325 try_setup_point(struct lp_setup_context *setup,
326 const float (*v0)[4])
327 {
328 struct llvmpipe_context *lp_context = (struct llvmpipe_context *)setup->pipe;
329 /* x/y positions in fixed point */
330 const struct lp_setup_variant_key *key = &setup->setup.variant->key;
331 const int sizeAttr = setup->psize_slot;
332 float size
333 = (setup->point_size_per_vertex && sizeAttr > 0) ? v0[sizeAttr][0]
334 : setup->point_size;
335
336 if (size > LP_MAX_POINT_WIDTH)
337 size = LP_MAX_POINT_WIDTH;
338
339 /* Yes this is necessary to accurately calculate bounding boxes
340 * with the two fill-conventions we support. GL (normally) ends
341 * up needing a bottom-left fill convention, which requires
342 * slightly different rounding.
343 */
344 const int adj = (setup->bottom_edge_rule != 0) ? 1 : 0;
345 const float pixel_offset = setup->multisample ? 0.0 : setup->pixel_offset;
346 struct lp_scene *scene = setup->scene;
347 int x[2], y[2];
348
349 unsigned viewport_index = 0;
350 if (setup->viewport_index_slot > 0) {
351 unsigned *udata = (unsigned*)v0[setup->viewport_index_slot];
352 viewport_index = lp_clamp_viewport_idx(*udata);
353 }
354
355 unsigned layer = 0;
356 if (setup->layer_slot > 0) {
357 layer = *(unsigned*)v0[setup->layer_slot];
358 layer = MIN2(layer, scene->fb_max_layer);
359 }
360
361 int fixed_width;
362
363 if (0)
364 print_point(setup, v0, size);
365
366 /* Bounding rectangle (in pixels) */
367 struct u_rect bbox;
368 if (!setup->legacy_points) {
369 /*
370 * Rasterize points as quads.
371 */
372 int x0, y0;
373 /* Point size as fixed point integer, remove rounding errors
374 * and gives minimum width for very small points.
375 */
376 fixed_width = MAX2(FIXED_ONE, subpixel_snap(size));
377
378 x0 = subpixel_snap(v0[0][0] - pixel_offset) - fixed_width/2;
379 y0 = subpixel_snap(v0[0][1] - pixel_offset) - fixed_width/2;
380
381 x[0] = x0;
382 x[1] = x0 + fixed_width;
383 y[0] = y0;
384 y[1] = y0 + fixed_width;
385 bbox.x0 = x[0] >> FIXED_ORDER;
386 bbox.x1 = (x[1] + (FIXED_ONE-1)) >> FIXED_ORDER;
387 bbox.y0 = (y[0] + adj) >> FIXED_ORDER;
388 bbox.y1 = (y[1] + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
389
390 /* Inclusive coordinates:
391 */
392 bbox.x1--;
393 bbox.y1--;
394 } else {
395 /*
396 * OpenGL legacy rasterization rules for non-sprite points.
397 *
398 * Per OpenGL 2.1 spec, section 3.3.1, "Basic Point Rasterization".
399 *
400 * This type of point rasterization is only available in pre 3.0 contexts
401 * (or compatibility contexts which we don't support) anyway.
402 */
403
404 const int x0 = subpixel_snap(v0[0][0]);
405 const int y0 = subpixel_snap(v0[0][1]) - adj;
406
407 /* Point size as fixed point integer. For GL legacy points
408 * the point size is always a whole integer.
409 */
410 fixed_width = MAX2(FIXED_ONE,
411 (subpixel_snap(size) + FIXED_ONE/2 - 1) & ~(FIXED_ONE-1));
412 int int_width = fixed_width >> FIXED_ORDER;
413
414 assert(setup->pixel_offset != 0);
415
416 if (int_width == 1) {
417 bbox.x0 = x0 >> FIXED_ORDER;
418 bbox.y0 = y0 >> FIXED_ORDER;
419 bbox.x1 = bbox.x0;
420 bbox.y1 = bbox.y0;
421 } else {
422 if (int_width & 1) {
423 /* Odd width */
424 bbox.x0 = (x0 >> FIXED_ORDER) - (int_width - 1)/2;
425 bbox.y0 = (y0 >> FIXED_ORDER) - (int_width - 1)/2;
426 } else {
427 /* Even width */
428 bbox.x0 = ((x0 + FIXED_ONE/2) >> FIXED_ORDER) - int_width/2;
429 bbox.y0 = ((y0 + FIXED_ONE/2) >> FIXED_ORDER) - int_width/2;
430 }
431
432 bbox.x1 = bbox.x0 + int_width - 1;
433 bbox.y1 = bbox.y0 + int_width - 1;
434 }
435
436 x[0] = (bbox.x0 - 1) << 8;
437 x[1] = (bbox.x1 + 1) << 8;
438 y[0] = (bbox.y0 - 1) << 8;
439 y[1] = (bbox.y1 + 1) << 8;
440 }
441
442 if (0) {
443 debug_printf(" bbox: (%i, %i) - (%i, %i)\n",
444 bbox.x0, bbox.y0,
445 bbox.x1, bbox.y1);
446 }
447
448 if (lp_context->active_statistics_queries) {
449 lp_context->pipeline_statistics.c_primitives++;
450 }
451
452 if (lp_setup_zero_sample_mask(setup)) {
453 if (0) debug_printf("zero sample mask\n");
454 LP_COUNT(nr_culled_tris);
455 return true;
456 }
457
458 if (!u_rect_test_intersection(&setup->draw_regions[viewport_index], &bbox)) {
459 if (0) debug_printf("no intersection\n");
460 LP_COUNT(nr_culled_tris);
461 return true;
462 }
463
464 u_rect_find_intersection(&setup->draw_regions[viewport_index], &bbox);
465
466 /* We can't use rectangle reasterizer for non-legacy points for now. */
467 if (!setup->legacy_points || setup->multisample) {
468 struct lp_rast_triangle *point;
469 struct lp_rast_plane *plane;
470 unsigned nr_planes = 4;
471
472 point = lp_setup_alloc_triangle(scene,
473 key->num_inputs,
474 nr_planes);
475 if (!point)
476 return false;
477
478 #if MESA_DEBUG
479 point->v[0][0] = v0[0][0];
480 point->v[0][1] = v0[0][1];
481 #endif
482
483 LP_COUNT(nr_tris);
484
485 if (draw_will_inject_frontface(lp_context->draw) &&
486 setup->face_slot > 0) {
487 point->inputs.frontfacing = v0[setup->face_slot][0];
488 } else {
489 point->inputs.frontfacing = true;
490 }
491
492 struct point_info info;
493 info.v0 = v0;
494 info.dx01 = 0;
495 info.dx12 = fixed_width;
496 info.dy01 = fixed_width;
497 info.dy12 = 0;
498 info.a0 = GET_A0(&point->inputs);
499 info.dadx = GET_DADX(&point->inputs);
500 info.dady = GET_DADY(&point->inputs);
501 info.frontfacing = point->inputs.frontfacing;
502
503 /* Setup parameter interpolants:
504 */
505 setup_point_coefficients(setup, &info);
506
507 point->inputs.disable = false;
508 point->inputs.is_blit = false;
509 point->inputs.layer = layer;
510 point->inputs.viewport_index = viewport_index;
511 point->inputs.view_index = setup->view_index;
512
513 plane = GET_PLANES(point);
514
515 plane[0].dcdx = ~0U << 8;
516 plane[0].dcdy = 0;
517 plane[0].c = -MAX2(x[0], bbox.x0 << 8);
518 plane[0].eo = 1 << 8;
519
520 plane[1].dcdx = 1 << 8;
521 plane[1].dcdy = 0;
522 plane[1].c = MIN2(x[1], (bbox.x1 + 1) << 8);
523 plane[1].eo = 0;
524
525 plane[2].dcdx = 0;
526 plane[2].dcdy = 1 << 8;
527 plane[2].c = -MAX2(y[0], (bbox.y0 << 8) - adj);
528 plane[2].eo = 1 << 8;
529
530 plane[3].dcdx = 0;
531 plane[3].dcdy = ~0U << 8;
532 plane[3].c = MIN2(y[1], (bbox.y1 + 1) << 8);
533 plane[3].eo = 0;
534
535 if (!setup->legacy_points) {
536 /* adjust for fill-rule*/
537 plane[0].c++; /* left */
538 if (setup->bottom_edge_rule == 0)
539 plane[2].c++; /* top-left */
540 else
541 plane[3].c++; /* bottom-left */
542 }
543
544 int max_szorig = ((bbox.x1 - (bbox.x0 & ~3)) |
545 (bbox.y1 - (bbox.y0 & ~3)));
546 bool use_32bits = max_szorig <= MAX_FIXED_LENGTH32;
547
548 return lp_setup_bin_triangle(setup, point, use_32bits,
549 setup->fs.current.variant->opaque,
550 &bbox, nr_planes, viewport_index);
551
552 } else {
553 struct lp_rast_rectangle *point =
554 lp_setup_alloc_rectangle(scene, key->num_inputs);
555 if (!point)
556 return false;
557 #if MESA_DEBUG
558 point->v[0][0] = v0[0][0];
559 point->v[0][1] = v0[0][1];
560 #endif
561
562 point->box.x0 = bbox.x0;
563 point->box.x1 = bbox.x1;
564 point->box.y0 = bbox.y0;
565 point->box.y1 = bbox.y1;
566
567 LP_COUNT(nr_tris);
568
569 if (draw_will_inject_frontface(lp_context->draw) &&
570 setup->face_slot > 0) {
571 point->inputs.frontfacing = v0[setup->face_slot][0];
572 } else {
573 point->inputs.frontfacing = true;
574 }
575
576 struct point_info info;
577 info.v0 = v0;
578 info.dx01 = 0;
579 info.dx12 = fixed_width;
580 info.dy01 = fixed_width;
581 info.dy12 = 0;
582 info.a0 = GET_A0(&point->inputs);
583 info.dadx = GET_DADX(&point->inputs);
584 info.dady = GET_DADY(&point->inputs);
585 info.frontfacing = point->inputs.frontfacing;
586
587 /* Setup parameter interpolants:
588 */
589 setup_point_coefficients(setup, &info);
590
591 point->inputs.disable = false;
592 point->inputs.is_blit = false;
593 point->inputs.layer = layer;
594 point->inputs.viewport_index = viewport_index;
595 point->inputs.view_index = setup->view_index;
596
597 return lp_setup_bin_rectangle(setup, point,
598 setup->fs.current.variant->opaque);
599 }
600 }
601
602
603 static void
lp_setup_point_discard(struct lp_setup_context * setup,const float (* v0)[4])604 lp_setup_point_discard(struct lp_setup_context *setup,
605 const float (*v0)[4])
606 {
607 }
608
609
610 static void
lp_setup_point(struct lp_setup_context * setup,const float (* v0)[4])611 lp_setup_point(struct lp_setup_context *setup,
612 const float (*v0)[4])
613 {
614 if (!try_setup_point(setup, v0)) {
615 if (!lp_setup_flush_and_restart(setup))
616 return;
617
618 if (!try_setup_point(setup, v0))
619 return;
620 }
621 }
622
623
624 void
lp_setup_choose_point(struct lp_setup_context * setup)625 lp_setup_choose_point(struct lp_setup_context *setup)
626 {
627 if (setup->rasterizer_discard) {
628 setup->point = lp_setup_point_discard;
629 } else {
630 setup->point = lp_setup_point;
631 }
632 }
633
634
635