1/**************************************************************************
2 *
3 * Copyright 2010-2021 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 THE AUTHORS 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 * Setup/binning code for screen-aligned quads.
30 */
31
32#include "util/u_math.h"
33#include "util/u_memory.h"
34#include "lp_perf.h"
35#include "lp_setup_context.h"
36#include "lp_rast.h"
37#include "lp_state_fs.h"
38#include "lp_state_setup.h"
39
40
41#define NUM_CHANNELS 4
42
43#define UNDETERMINED_BLIT  -1
44
45
46static inline int
47subpixel_snap(float a)
48{
49   return util_iround(FIXED_ONE * a);
50}
51
52
53static inline float
54fixed_to_float(int a)
55{
56   return a * (1.0f / FIXED_ONE);
57}
58
59
60/**
61 * Alloc space for a new rectangle plus the input.a0/dadx/dady arrays
62 * immediately after it.
63 * The memory is allocated from the per-scene pool, not per-tile.
64 * \param size  returns number of bytes allocated
65 * \param nr_inputs  number of fragment shader inputs
66 * \return pointer to rectangle space
67 */
68struct lp_rast_rectangle *
69lp_setup_alloc_rectangle(struct lp_scene *scene, unsigned nr_inputs)
70{
71   unsigned input_array_sz = NUM_CHANNELS * (nr_inputs + 1) * sizeof(float);
72   struct lp_rast_rectangle *rect;
73   unsigned bytes;
74
75   bytes = sizeof(*rect) + (3 * input_array_sz);
76
77   rect = lp_scene_alloc_aligned( scene, bytes, 16 );
78   if (rect == NULL)
79      return NULL;
80
81   rect->inputs.stride = input_array_sz;
82
83   return rect;
84}
85
86
87/**
88 * The rectangle covers the whole tile- shade whole tile.
89 * XXX no rectangle/triangle dependencies in this file - share it with
90 * the same code in lp_setup_tri.c
91 * \param tx, ty  the tile position in tiles, not pixels
92 */
93boolean
94lp_setup_whole_tile(struct lp_setup_context *setup,
95                    const struct lp_rast_shader_inputs *inputs,
96                    int tx, int ty)
97{
98   struct lp_scene *scene = setup->scene;
99
100   LP_COUNT(nr_fully_covered_64);
101
102   /* if variant is opaque and scissor doesn't effect the tile */
103   if (inputs->opaque) {
104      /* Several things prevent this optimization from working:
105       * - For layered rendering we can't determine if this covers the same layer
106       * as previous rendering (or in case of clears those actually always cover
107       * all layers so optimization is impossible). Need to use fb_max_layer and
108       * not setup->layer_slot to determine this since even if there's currently
109       * no slot assigned previous rendering could have used one.
110       * - If there were any Begin/End query commands in the scene then those
111       * would get removed which would be very wrong. Furthermore, if queries
112       * were just active we also can't do the optimization since to get
113       * accurate query results we unfortunately need to execute the rendering
114       * commands.
115       */
116      if (!scene->fb.zsbuf && scene->fb_max_layer == 0 && !scene->had_queries) {
117         /*
118          * All previous rendering will be overwritten so reset the bin.
119          */
120         lp_scene_bin_reset( scene, tx, ty );
121      }
122
123      if (inputs->is_blit) {
124         LP_COUNT(nr_blit_64);
125         return lp_scene_bin_cmd_with_state( scene, tx, ty,
126                                             setup->fs.stored,
127                                             LP_RAST_OP_BLIT,
128                                             lp_rast_arg_inputs(inputs) );
129      }
130      else {
131         LP_COUNT(nr_shade_opaque_64);
132         return lp_scene_bin_cmd_with_state( scene, tx, ty,
133                                             setup->fs.stored,
134                                             LP_RAST_OP_SHADE_TILE_OPAQUE,
135                                             lp_rast_arg_inputs(inputs) );
136      }
137   }
138   else {
139      LP_COUNT(nr_shade_64);
140      return lp_scene_bin_cmd_with_state( scene, tx, ty,
141                                          setup->fs.stored,
142                                          LP_RAST_OP_SHADE_TILE,
143                                          lp_rast_arg_inputs(inputs) );
144   }
145}
146
147
148boolean
149lp_setup_is_blit(const struct lp_setup_context *setup,
150                 const struct lp_rast_shader_inputs *inputs)
151{
152   const struct lp_fragment_shader_variant *variant =
153      setup->fs.current.variant;
154
155   if (variant->blit) {
156      /*
157       * Detect blits.
158       */
159      const struct lp_jit_texture *texture =
160         &setup->fs.current.jit_context.textures[0];
161      float dsdx, dsdy, dtdx, dtdy;
162
163      /* XXX: dadx vs dady confusion below?
164       */
165      dsdx = GET_DADX(inputs)[1][0]*texture->width;
166      dsdy = GET_DADX(inputs)[1][1]*texture->width;
167      dtdx = GET_DADY(inputs)[1][0]*texture->height;
168      dtdy = GET_DADY(inputs)[1][1]*texture->height;
169
170      /*
171       * We don't need to check s0/t0 tolerances
172       * as we establish as pre-condition that there is no
173       * texture filtering.
174       */
175
176      ASSERTED struct lp_sampler_static_state *samp0 = lp_fs_variant_key_sampler_idx(&variant->key, 0);
177      assert(samp0);
178      assert(samp0->sampler_state.min_img_filter == PIPE_TEX_FILTER_NEAREST);
179      assert(samp0->sampler_state.mag_img_filter == PIPE_TEX_FILTER_NEAREST);
180
181      /*
182       * Check for 1:1 match of texels to dest pixels
183       */
184
185      if (util_is_approx(dsdx, 1.0f, 1.0f/LP_MAX_WIDTH) &&
186          util_is_approx(dsdy, 0.0f, 1.0f/LP_MAX_HEIGHT) &&
187          util_is_approx(dtdx, 0.0f, 1.0f/LP_MAX_WIDTH) &&
188          util_is_approx(dtdy, 1.0f, 1.0f/LP_MAX_HEIGHT)) {
189         return true;
190      }
191      else {
192#if 0
193         debug_printf("dsdx = %f\n", dsdx);
194         debug_printf("dsdy = %f\n", dsdy);
195         debug_printf("dtdx = %f\n", dtdx);
196         debug_printf("dtdy = %f\n", dtdy);
197         debug_printf("\n");
198#endif
199         return FALSE;
200      }
201   }
202
203   return FALSE;
204}
205
206
207static inline void
208partial(struct lp_setup_context *setup,
209        const struct lp_rast_rectangle *rect,
210        unsigned ix, unsigned iy,
211        unsigned mask)
212{
213   if (mask == 0) {
214      assert(rect->box.x0 <= ix * TILE_SIZE);
215      assert(rect->box.y0 <= iy * TILE_SIZE);
216      assert(rect->box.x1 >= (ix+1) * TILE_SIZE - 1);
217      assert(rect->box.y1 >= (iy+1) * TILE_SIZE - 1);
218
219      lp_setup_whole_tile(setup, &rect->inputs, ix, iy);
220   }
221   else {
222      LP_COUNT(nr_partially_covered_64);
223      lp_scene_bin_cmd_with_state( setup->scene,
224                                   ix, iy,
225                                   setup->fs.stored,
226                                   LP_RAST_OP_RECTANGLE,
227                                   lp_rast_arg_rectangle(rect) );
228   }
229}
230
231
232/**
233 * Setup/bin a screen-aligned rect.
234 * We need three corner vertices in order to correctly setup
235 * interpolated parameters.  We *could* get away with just the
236 * diagonal vertices but it'd cause ugliness elsewhere.
237 *
238 *   + -------v0
239 *   |        |
240 *  v2 ------ v1
241 *
242 * By an unfortunate mixup between GL and D3D coordinate spaces, half
243 * of this file talks about clockwise rectangles (which were CCW in GL
244 * coordinate space), while the other half prefers to work with D3D
245 * CCW rectangles.
246 */
247static boolean
248try_rect_cw(struct lp_setup_context *setup,
249            const float (*v0)[4],
250            const float (*v1)[4],
251            const float (*v2)[4],
252            boolean frontfacing)
253{
254   const struct lp_fragment_shader_variant *variant =
255      setup->fs.current.variant;
256   const struct lp_setup_variant_key *key = &setup->setup.variant->key;
257   struct lp_scene *scene = setup->scene;
258   struct lp_rast_rectangle *rect;
259   boolean cw;
260   struct u_rect bbox;
261   unsigned viewport_index = 0;
262   unsigned layer = 0;
263   const float (*pv)[4];
264
265   /* x/y positions in fixed point */
266   int x0 = subpixel_snap(v0[0][0] - setup->pixel_offset);
267   int x1 = subpixel_snap(v1[0][0] - setup->pixel_offset);
268   int x2 = subpixel_snap(v2[0][0] - setup->pixel_offset);
269   int y0 = subpixel_snap(v0[0][1] - setup->pixel_offset);
270   int y1 = subpixel_snap(v1[0][1] - setup->pixel_offset);
271   int y2 = subpixel_snap(v2[0][1] - setup->pixel_offset);
272
273   LP_COUNT(nr_rects);
274
275   /* Cull clockwise rects without overflowing.
276    */
277   cw = (x2 < x1) ^ (y0 < y2);
278   if (cw) {
279      LP_COUNT(nr_culled_rects);
280      return TRUE;
281   }
282
283   if (setup->flatshade_first) {
284      pv = v0;
285   }
286   else {
287      pv = v2;
288   }
289   if (setup->viewport_index_slot > 0) {
290      unsigned *udata = (unsigned*)pv[setup->viewport_index_slot];
291      viewport_index = lp_clamp_viewport_idx(*udata);
292   }
293   if (setup->layer_slot > 0) {
294      layer = *(unsigned*)pv[setup->layer_slot];
295      layer = MIN2(layer, scene->fb_max_layer);
296   }
297
298   /* Bounding rectangle (in pixels) */
299   {
300      /* Yes this is necessary to accurately calculate bounding boxes
301       * with the two fill-conventions we support.  GL (normally) ends
302       * up needing a bottom-left fill convention, which requires
303       * slightly different rounding.
304       */
305      int adj = (setup->bottom_edge_rule != 0) ? 1 : 0;
306
307      bbox.x0 = (MIN3(x0, x1, x2) + (FIXED_ONE-1)) >> FIXED_ORDER;
308      bbox.x1 = (MAX3(x0, x1, x2) + (FIXED_ONE-1)) >> FIXED_ORDER;
309      bbox.y0 = (MIN3(y0, y1, y2) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
310      bbox.y1 = (MAX3(y0, y1, y2) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
311
312      /* Inclusive coordinates:
313       */
314      bbox.x1--;
315      bbox.y1--;
316   }
317
318   if (!u_rect_test_intersection(&setup->draw_regions[viewport_index], &bbox)) {
319      if (0) debug_printf("no intersection\n");
320      LP_COUNT(nr_culled_rects);
321      return TRUE;
322   }
323
324   u_rect_find_intersection(&setup->draw_regions[viewport_index], &bbox);
325
326   rect = lp_setup_alloc_rectangle(scene, key->num_inputs);
327   if (!rect)
328      return FALSE;
329
330#ifdef DEBUG
331   rect->v[0][0] = v0[0][0];
332   rect->v[0][1] = v0[0][1];
333   rect->v[1][0] = v1[0][0];
334   rect->v[1][1] = v1[0][1];
335#endif
336
337   rect->box.x0 = bbox.x0;
338   rect->box.x1 = bbox.x1;
339   rect->box.y0 = bbox.y0;
340   rect->box.y1 = bbox.y1;
341
342   /* Setup parameter interpolants:
343    */
344   setup->setup.variant->jit_function( v0,
345				       v1,
346				       v2,
347				       frontfacing,
348				       GET_A0(&rect->inputs),
349				       GET_DADX(&rect->inputs),
350				       GET_DADY(&rect->inputs),
351                                       &setup->setup.variant->key );
352
353   rect->inputs.frontfacing = frontfacing;
354   rect->inputs.disable = FALSE;
355   rect->inputs.is_blit = lp_setup_is_blit(setup, &rect->inputs);
356   rect->inputs.opaque = variant->opaque;
357   rect->inputs.layer = layer;
358   rect->inputs.viewport_index = viewport_index;
359   rect->inputs.view_index = setup->view_index;
360
361   return lp_setup_bin_rectangle(setup, rect);
362}
363
364
365boolean
366lp_setup_bin_rectangle(struct lp_setup_context *setup,
367                       struct lp_rast_rectangle *rect)
368{
369   struct lp_scene *scene = setup->scene;
370   unsigned ix0, iy0, ix1, iy1;
371   unsigned i, j;
372   unsigned left_mask = 0;
373   unsigned right_mask = 0;
374   unsigned top_mask = 0;
375   unsigned bottom_mask = 0;
376
377   /*
378    * All fields of 'rect' are now set.  The remaining code here is
379    * concerned with binning.
380    */
381
382   /* Convert to inclusive tile coordinates:
383    */
384   ix0 = rect->box.x0 / TILE_SIZE;
385   iy0 = rect->box.y0 / TILE_SIZE;
386   ix1 = rect->box.x1 / TILE_SIZE;
387   iy1 = rect->box.y1 / TILE_SIZE;
388
389   /*
390    * Clamp to framebuffer size
391    */
392   assert(ix0 == MAX2(ix0, 0));
393   assert(iy0 == MAX2(iy0, 0));
394   assert(ix1 == MIN2(ix1, scene->tiles_x - 1));
395   assert(iy1 == MIN2(iy1, scene->tiles_y - 1));
396
397   if (ix0 * TILE_SIZE != rect->box.x0)
398      left_mask = RECT_PLANE_LEFT;
399
400   if (ix1 * TILE_SIZE + TILE_SIZE - 1 != rect->box.x1)
401      right_mask  = RECT_PLANE_RIGHT;
402
403   if (iy0 * TILE_SIZE != rect->box.y0)
404      top_mask    = RECT_PLANE_TOP;
405
406   if (iy1 * TILE_SIZE + TILE_SIZE - 1 != rect->box.y1)
407      bottom_mask = RECT_PLANE_BOTTOM;
408
409   /* Determine which tile(s) intersect the rectangle's bounding box
410    */
411   if (iy0 == iy1 && ix0 == ix1) {
412      partial(setup, rect, ix0, iy0,
413              (left_mask | right_mask | top_mask | bottom_mask));
414   }
415   else if (ix0 == ix1) {
416      unsigned mask = left_mask | right_mask;
417      partial(setup, rect, ix0, iy0, mask | top_mask);
418      for (i = iy0 + 1; i < iy1; i++)
419         partial(setup, rect, ix0, i, mask);
420      partial(setup, rect, ix0, iy1, mask | bottom_mask);
421   }
422   else if (iy0 == iy1) {
423      unsigned mask = top_mask | bottom_mask;
424      partial(setup, rect, ix0, iy0, mask | left_mask);
425      for (i = ix0 + 1; i < ix1; i++)
426         partial(setup, rect, i, iy0, mask);
427      partial(setup, rect, ix1, iy0, mask | right_mask);
428   }
429   else {
430      partial(setup, rect, ix0, iy0, left_mask  | top_mask);
431      partial(setup, rect, ix0, iy1, left_mask  | bottom_mask);
432      partial(setup, rect, ix1, iy0, right_mask | top_mask);
433      partial(setup, rect, ix1, iy1, right_mask | bottom_mask);
434
435      /* Top/Bottom fringes
436       */
437      for (i = ix0 + 1; i < ix1; i++) {
438         partial(setup, rect, i, iy0, top_mask);
439         partial(setup, rect, i, iy1, bottom_mask);
440      }
441
442      /* Left/Right fringes
443       */
444      for (i = iy0 + 1; i < iy1; i++) {
445         partial(setup, rect, ix0, i, left_mask);
446         partial(setup, rect, ix1, i, right_mask);
447      }
448
449      /* Full interior tiles
450       */
451      for (j = iy0 + 1; j < iy1; j++) {
452         for (i = ix0 + 1; i < ix1; i++) {
453            lp_setup_whole_tile(setup, &rect->inputs, i, j);
454         }
455      }
456   }
457
458   /* Catch any out-of-memory which occurred during binning.  Do this
459    * once here rather than checking all the return values throughout.
460    */
461   if (lp_scene_is_oom(scene)) {
462      /* Disable rasterization of this partially-binned rectangle.
463       * We'll flush this scene and re-bin the entire rectangle:
464       */
465      rect->inputs.disable = TRUE;
466      return FALSE;
467   }
468
469   return TRUE;
470}
471
472
473void
474lp_rect_cw(struct lp_setup_context *setup,
475         const float (*v0)[4],
476         const float (*v1)[4],
477         const float (*v2)[4],
478         boolean frontfacing)
479{
480   if (!try_rect_cw(setup, v0, v1, v2, frontfacing)) {
481      if (!lp_setup_flush_and_restart(setup))
482         return;
483
484      if (!try_rect_cw(setup, v0, v1, v2, frontfacing))
485         return;
486   }
487}
488
489
490/**
491 * Take the six vertices for two triangles and try to determine if they
492 * form a screen-aligned quad/rectangle.  If so, draw the rect directly,
493 * else, draw as two regular triangles.
494 */
495static boolean
496do_rect_ccw(struct lp_setup_context *setup,
497            const float (*v0)[4],
498            const float (*v1)[4],
499            const float (*v2)[4],
500            const float (*v3)[4],
501            const float (*v4)[4],
502            const float (*v5)[4],
503            boolean front)
504{
505   const float (*rv0)[4], (*rv1)[4], (*rv2)[4], (*rv3)[4];  /* rect verts */
506
507#define SAME_POS(A, B)   (A[0][0] == B[0][0] && \
508                          A[0][1] == B[0][1] && \
509                          A[0][2] == B[0][2] && \
510                          A[0][3] == B[0][3])
511
512   /* Only need to consider CCW orientations.  There are nine ways
513    * that two counter-clockwise triangles can join up:
514    */
515   if (SAME_POS(v0, v3)) {
516      if (SAME_POS(v2, v4)) {
517         /*
518          *    v5   v4/v2
519          *     +-----+
520          *     |   / |
521          *     |  /  |
522          *     | /   |
523          *     +-----+
524          *   v3/v0   v1
525          */
526         rv0 = v5;
527         rv1 = v0;
528         rv2 = v1;
529         rv3 = v2;
530      }
531      else if (SAME_POS(v1, v5)) {
532         /*
533          *    v4   v3/v0
534          *     +-----+
535          *     |   / |
536          *     |  /  |
537          *     | /   |
538          *     +-----+
539          *   v5/v1   v2
540          */
541         rv0 = v4;
542         rv1 = v1;
543         rv2 = v2;
544         rv3 = v0;
545      }
546      else {
547         goto emit_triangles;
548      }
549   }
550   else if (SAME_POS(v0, v5)) {
551      if (SAME_POS(v2, v3)) {
552         /*
553          *    v4   v3/v2
554          *     +-----+
555          *     |   / |
556          *     |  /  |
557          *     | /   |
558          *     +-----+
559          *   v5/v0   v1
560          */
561         rv0 = v4;
562         rv1 = v0;
563         rv2 = v1;
564         rv3 = v2;
565      }
566      else if (SAME_POS(v1, v4)) {
567         /*
568          *    v3   v5/v0
569          *     +-----+
570          *     |   / |
571          *     |  /  |
572          *     | /   |
573          *     +-----+
574          *   v4/v1   v2
575          */
576         rv0 = v3;
577         rv1 = v1;
578         rv2 = v2;
579         rv3 = v0;
580      }
581      else {
582         goto emit_triangles;
583      }
584   }
585   else if (SAME_POS(v0, v4)) {
586      if (SAME_POS(v2, v5)) {
587         /*
588          *    v3   v5/v2
589          *     +-----+
590          *     |   / |
591          *     |  /  |
592          *     | /   |
593          *     +-----+
594          *   v4/v0   v1
595          */
596         rv0 = v3;
597         rv1 = v0;
598         rv2 = v1;
599         rv3 = v2;
600      }
601      else if (SAME_POS(v1, v3)) {
602         /*
603          *    v5   v4/v0
604          *     +-----+
605          *     |   / |
606          *     |  /  |
607          *     | /   |
608          *     +-----+
609          *   v3/v1   v2
610          */
611         rv0 = v5;
612         rv1 = v1;
613         rv2 = v2;
614         rv3 = v0;
615      }
616      else {
617         goto emit_triangles;
618      }
619   }
620   else if (SAME_POS(v2, v3)) {
621      if (SAME_POS(v1, v4)) {
622         /*
623          *    v5   v4/v1
624          *     +-----+
625          *     |   / |
626          *     |  /  |
627          *     | /   |
628          *     +-----+
629          *   v3/v2   v0
630          */
631         rv0 = v5;
632         rv1 = v2;
633         rv2 = v0;
634         rv3 = v1;
635      }
636      else {
637         goto emit_triangles;
638      }
639   }
640   else if (SAME_POS(v2, v5)) {
641      if (SAME_POS(v1, v3)) {
642         /*
643          *    v4   v3/v1
644          *     +-----+
645          *     |   / |
646          *     |  /  |
647          *     | /   |
648          *     +-----+
649          *   v5/v2   v0
650          */
651         rv0 = v4;
652         rv1 = v2;
653         rv2 = v0;
654         rv3 = v1;
655      }
656      else {
657         goto emit_triangles;
658      }
659   }
660   else if (SAME_POS(v2, v4)) {
661      if (SAME_POS(v1, v5)) {
662         /*
663          *    v3   v5/v1
664          *     +-----+
665          *     |   / |
666          *     |  /  |
667          *     | /   |
668          *     +-----+
669          *   v4/v2   v0
670          */
671         rv0 = v3;
672         rv1 = v2;
673         rv2 = v0;
674         rv3 = v1;
675      }
676      else {
677         goto emit_triangles;
678      }
679   }
680   else {
681      goto emit_triangles;
682   }
683
684
685#define SAME_X(A, B)   (A[0][0] == B[0][0])
686#define SAME_Y(A, B)   (A[0][1] == B[0][1])
687
688   /* The vertices are now counter clockwise, as such:
689    *
690    *  rv0 -------rv3
691    *    |        |
692    *  rv1 ------ rv2
693    *
694    * To render as a rectangle,
695    *   * The X values should be the same at v0, v1 and v2, v3.
696    *   * The Y values should be the same at v0, v3 and v1, v2.
697    */
698   if (SAME_Y(rv0, rv1)) {
699      const float (*tmp)[4];
700      tmp = rv0;
701      rv0 = rv1;
702      rv1 = rv2;
703      rv2 = rv3;
704      rv3 = tmp;
705   }
706
707   if (SAME_X(rv0, rv1) && SAME_X(rv2, rv3) &&
708       SAME_Y(rv0, rv3) && SAME_Y(rv1, rv2)) {
709
710      const struct lp_setup_variant_key *key = &setup->setup.variant->key;
711      const unsigned n = key->num_inputs;
712      unsigned i, j;
713
714      /* We have a rectangle.  Check that the other attributes are
715       * coplanar.
716       */
717      for (i = 0; i < n; i++) {
718         for (j = 0; j < 4; j++) {
719            if (key->inputs[i].usage_mask & (1<<j)) {
720               unsigned k = key->inputs[i].src_index;
721               float dxdx1, dxdx2, dxdy1, dxdy2;
722               dxdx1 = rv0[k][j] - rv3[k][j];
723               dxdx2 = rv1[k][j] - rv2[k][j];
724               dxdy1 = rv0[k][j] - rv1[k][j];
725               dxdy2 = rv3[k][j] - rv2[k][j];
726               if (dxdx1 != dxdx2 ||
727                   dxdy1 != dxdy2) {
728                  goto emit_triangles;
729               }
730            }
731         }
732      }
733
734      /* Note we're changing to clockwise here.  Fix this by reworking
735       * lp_rect_cw to expect/operate on ccw rects.  Note that
736       * function was previously misnamed.
737       */
738      lp_rect_cw(setup, rv0, rv2, rv1, front);
739      return TRUE;
740   }
741   else {
742      /* setup->quad(setup, rv0, rv1, rv2, rv3); */
743   }
744
745emit_triangles:
746   return FALSE;
747}
748
749
750enum winding {
751   WINDING_NONE = 0,
752   WINDING_CCW,
753   WINDING_CW
754};
755
756
757static inline enum winding
758winding(const float (*v0)[4],
759        const float (*v1)[4],
760        const float (*v2)[4])
761{
762   /* edge vectors e = v0 - v2, f = v1 - v2 */
763   const float ex = v0[0][0] - v2[0][0];
764   const float ey = v0[0][1] - v2[0][1];
765   const float fx = v1[0][0] - v2[0][0];
766   const float fy = v1[0][1] - v2[0][1];
767
768   /* det = cross(e,f).z */
769   const float det = ex * fy - ey * fx;
770
771   if (det < 0.0f)
772      return WINDING_CCW;
773   else if (det > 0.0f)
774      return WINDING_CW;
775   else
776      return WINDING_NONE;
777}
778
779
780static boolean
781setup_rect_cw(struct lp_setup_context *setup,
782              const float (*v0)[4],
783              const float (*v1)[4],
784              const float (*v2)[4],
785              const float (*v3)[4],
786              const float (*v4)[4],
787              const float (*v5)[4])
788{
789   enum winding winding0 = winding(v0, v1, v2);
790   enum winding winding1 = winding(v3, v4, v5);
791
792   if (winding0 == WINDING_CW &&
793       winding1 == WINDING_CW) {
794      return do_rect_ccw(setup, v0, v2, v1, v3, v5, v4, !setup->ccw_is_frontface);
795   } else if (winding0 == WINDING_CW) {
796      setup->triangle(setup, v0, v1, v2);
797      return TRUE;
798   } else if (winding1 == WINDING_CW) {
799      setup->triangle(setup, v3, v4, v5);
800      return TRUE;
801   } else {
802      return TRUE;
803   }
804}
805
806
807static boolean
808setup_rect_ccw(struct lp_setup_context *setup,
809               const float (*v0)[4],
810               const float (*v1)[4],
811               const float (*v2)[4],
812               const float (*v3)[4],
813               const float (*v4)[4],
814               const float (*v5)[4])
815{
816   enum winding winding0 = winding(v0, v1, v2);
817   enum winding winding1 = winding(v3, v4, v5);
818
819   if (winding0 == WINDING_CCW &&
820       winding1 == WINDING_CCW) {
821      return do_rect_ccw(setup, v0, v1, v2, v3, v4, v5, setup->ccw_is_frontface);
822   } else if (winding0 == WINDING_CCW) {
823      setup->triangle(setup, v0, v1, v2);
824      return TRUE;
825   } else if (winding1 == WINDING_CCW) {
826      return FALSE;
827      setup->triangle(setup, v3, v4, v5);
828      return TRUE;
829   } else {
830      return TRUE;
831   }
832}
833
834
835static boolean
836setup_rect_noop(struct lp_setup_context *setup,
837                const float (*v0)[4],
838                const float (*v1)[4],
839                const float (*v2)[4],
840                const float (*v3)[4],
841                const float (*v4)[4],
842                const float (*v5)[4])
843{
844   return TRUE;
845}
846
847
848static boolean
849setup_rect_both(struct lp_setup_context *setup,
850                const float (*v0)[4],
851                const float (*v1)[4],
852                const float (*v2)[4],
853                const float (*v3)[4],
854                const float (*v4)[4],
855                const float (*v5)[4])
856{
857   enum winding winding0 = winding(v0, v1, v2);
858   enum winding winding1 = winding(v3, v4, v5);
859
860   if (winding0 != winding1) {
861      /* If we knew that the "front" parameter wasn't going to be
862       * referenced, could rearrange one of the two triangles such
863       * that they were both CCW.  Aero actually does send mixed
864       * CW/CCW rectangles under some circumstances, but we catch them
865       * explicitly.
866       */
867      return FALSE;
868   }
869   else if (winding0 == WINDING_CCW) {
870      return do_rect_ccw(setup, v0, v1, v2, v3, v4, v5, setup->ccw_is_frontface);
871   }
872   else if (winding0 == WINDING_CW) {
873      return do_rect_ccw(setup, v0, v2, v1, v3, v5, v4, !setup->ccw_is_frontface);
874   } else {
875      return TRUE;
876   }
877}
878
879
880void
881lp_setup_choose_rect( struct lp_setup_context *setup )
882{
883   if (setup->rasterizer_discard) {
884      setup->rect = setup_rect_noop;
885      return;
886   }
887
888   switch (setup->cullmode) {
889   case PIPE_FACE_NONE:
890      setup->rect = setup_rect_both;
891      break;
892   case PIPE_FACE_BACK:
893      setup->rect = setup->ccw_is_frontface ? setup_rect_ccw : setup_rect_cw;
894      break;
895   case PIPE_FACE_FRONT:
896      setup->rect = setup->ccw_is_frontface ? setup_rect_cw : setup_rect_ccw;
897      break;
898   default:
899      setup->rect = setup_rect_noop;
900      break;
901   }
902}
903