1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2007 VMware, Inc.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the
8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including
9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish,
10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to
11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to
12bf215546Sopenharmony_ci * the following conditions:
13bf215546Sopenharmony_ci *
14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the
15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions
16bf215546Sopenharmony_ci * of the Software.
17bf215546Sopenharmony_ci *
18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25bf215546Sopenharmony_ci *
26bf215546Sopenharmony_ci **************************************************************************/
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci/*
29bf215546Sopenharmony_ci * Binning code for lines
30bf215546Sopenharmony_ci */
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "util/u_math.h"
33bf215546Sopenharmony_ci#include "util/u_memory.h"
34bf215546Sopenharmony_ci#include "lp_perf.h"
35bf215546Sopenharmony_ci#include "lp_setup_context.h"
36bf215546Sopenharmony_ci#include "lp_rast.h"
37bf215546Sopenharmony_ci#include "lp_state_fs.h"
38bf215546Sopenharmony_ci#include "lp_state_setup.h"
39bf215546Sopenharmony_ci#include "lp_context.h"
40bf215546Sopenharmony_ci#include "draw/draw_context.h"
41bf215546Sopenharmony_ci
42bf215546Sopenharmony_ci#define NUM_CHANNELS 4
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_cistruct lp_line_info {
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_ci   float dx;
47bf215546Sopenharmony_ci   float dy;
48bf215546Sopenharmony_ci   float oneoverarea;
49bf215546Sopenharmony_ci   boolean frontfacing;
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci   const float (*v1)[4];
52bf215546Sopenharmony_ci   const float (*v2)[4];
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ci   float (*a0)[4];
55bf215546Sopenharmony_ci   float (*dadx)[4];
56bf215546Sopenharmony_ci   float (*dady)[4];
57bf215546Sopenharmony_ci};
58bf215546Sopenharmony_ci
59bf215546Sopenharmony_ci
60bf215546Sopenharmony_ci/**
61bf215546Sopenharmony_ci * Compute a0 for a constant-valued coefficient (GL_FLAT shading).
62bf215546Sopenharmony_ci */
63bf215546Sopenharmony_cistatic void constant_coef( struct lp_setup_context *setup,
64bf215546Sopenharmony_ci                           struct lp_line_info *info,
65bf215546Sopenharmony_ci                           unsigned slot,
66bf215546Sopenharmony_ci                           const float value,
67bf215546Sopenharmony_ci                           unsigned i )
68bf215546Sopenharmony_ci{
69bf215546Sopenharmony_ci   info->a0[slot][i] = value;
70bf215546Sopenharmony_ci   info->dadx[slot][i] = 0.0f;
71bf215546Sopenharmony_ci   info->dady[slot][i] = 0.0f;
72bf215546Sopenharmony_ci}
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci/**
76bf215546Sopenharmony_ci * Compute a0, dadx and dady for a linearly interpolated coefficient,
77bf215546Sopenharmony_ci * for a triangle.
78bf215546Sopenharmony_ci */
79bf215546Sopenharmony_cistatic void linear_coef( struct lp_setup_context *setup,
80bf215546Sopenharmony_ci                         struct lp_line_info *info,
81bf215546Sopenharmony_ci                         unsigned slot,
82bf215546Sopenharmony_ci                         unsigned vert_attr,
83bf215546Sopenharmony_ci                         unsigned i)
84bf215546Sopenharmony_ci{
85bf215546Sopenharmony_ci   float a1 = info->v1[vert_attr][i];
86bf215546Sopenharmony_ci   float a2 = info->v2[vert_attr][i];
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci   float da21 = a1 - a2;
89bf215546Sopenharmony_ci   float dadx = da21 * info->dx * info->oneoverarea;
90bf215546Sopenharmony_ci   float dady = da21 * info->dy * info->oneoverarea;
91bf215546Sopenharmony_ci
92bf215546Sopenharmony_ci   info->dadx[slot][i] = dadx;
93bf215546Sopenharmony_ci   info->dady[slot][i] = dady;
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci   info->a0[slot][i] = (a1 -
96bf215546Sopenharmony_ci                              (dadx * (info->v1[0][0] - setup->pixel_offset) +
97bf215546Sopenharmony_ci                               dady * (info->v1[0][1] - setup->pixel_offset)));
98bf215546Sopenharmony_ci}
99bf215546Sopenharmony_ci
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci/**
102bf215546Sopenharmony_ci * Compute a0, dadx and dady for a perspective-corrected interpolant,
103bf215546Sopenharmony_ci * for a triangle.
104bf215546Sopenharmony_ci * We basically multiply the vertex value by 1/w before computing
105bf215546Sopenharmony_ci * the plane coefficients (a0, dadx, dady).
106bf215546Sopenharmony_ci * Later, when we compute the value at a particular fragment position we'll
107bf215546Sopenharmony_ci * divide the interpolated value by the interpolated W at that fragment.
108bf215546Sopenharmony_ci */
109bf215546Sopenharmony_cistatic void perspective_coef( struct lp_setup_context *setup,
110bf215546Sopenharmony_ci                              struct lp_line_info *info,
111bf215546Sopenharmony_ci                              unsigned slot,
112bf215546Sopenharmony_ci                              unsigned vert_attr,
113bf215546Sopenharmony_ci                              unsigned i)
114bf215546Sopenharmony_ci{
115bf215546Sopenharmony_ci   /* premultiply by 1/w  (v[0][3] is always 1/w):
116bf215546Sopenharmony_ci    */
117bf215546Sopenharmony_ci   float a1 = info->v1[vert_attr][i] * info->v1[0][3];
118bf215546Sopenharmony_ci   float a2 = info->v2[vert_attr][i] * info->v2[0][3];
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci   float da21 = a1 - a2;
121bf215546Sopenharmony_ci   float dadx = da21 * info->dx * info->oneoverarea;
122bf215546Sopenharmony_ci   float dady = da21 * info->dy * info->oneoverarea;
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci   info->dadx[slot][i] = dadx;
125bf215546Sopenharmony_ci   info->dady[slot][i] = dady;
126bf215546Sopenharmony_ci
127bf215546Sopenharmony_ci   info->a0[slot][i] = (a1 -
128bf215546Sopenharmony_ci                        (dadx * (info->v1[0][0] - setup->pixel_offset) +
129bf215546Sopenharmony_ci                         dady * (info->v1[0][1] - setup->pixel_offset)));
130bf215546Sopenharmony_ci}
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_cistatic void
133bf215546Sopenharmony_cisetup_fragcoord_coef( struct lp_setup_context *setup,
134bf215546Sopenharmony_ci                      struct lp_line_info *info,
135bf215546Sopenharmony_ci                      unsigned slot,
136bf215546Sopenharmony_ci                      unsigned usage_mask)
137bf215546Sopenharmony_ci{
138bf215546Sopenharmony_ci   /*X*/
139bf215546Sopenharmony_ci   if (usage_mask & TGSI_WRITEMASK_X) {
140bf215546Sopenharmony_ci      info->a0[slot][0] = 0.0;
141bf215546Sopenharmony_ci      info->dadx[slot][0] = 1.0;
142bf215546Sopenharmony_ci      info->dady[slot][0] = 0.0;
143bf215546Sopenharmony_ci   }
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci   /*Y*/
146bf215546Sopenharmony_ci   if (usage_mask & TGSI_WRITEMASK_Y) {
147bf215546Sopenharmony_ci      info->a0[slot][1] = 0.0;
148bf215546Sopenharmony_ci      info->dadx[slot][1] = 0.0;
149bf215546Sopenharmony_ci      info->dady[slot][1] = 1.0;
150bf215546Sopenharmony_ci   }
151bf215546Sopenharmony_ci
152bf215546Sopenharmony_ci   /*Z*/
153bf215546Sopenharmony_ci   if (usage_mask & TGSI_WRITEMASK_Z) {
154bf215546Sopenharmony_ci      linear_coef(setup, info, slot, 0, 2);
155bf215546Sopenharmony_ci   }
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   /*W*/
158bf215546Sopenharmony_ci   if (usage_mask & TGSI_WRITEMASK_W) {
159bf215546Sopenharmony_ci      linear_coef(setup, info, slot, 0, 3);
160bf215546Sopenharmony_ci   }
161bf215546Sopenharmony_ci}
162bf215546Sopenharmony_ci
163bf215546Sopenharmony_ci/**
164bf215546Sopenharmony_ci * Compute the tri->coef[] array dadx, dady, a0 values.
165bf215546Sopenharmony_ci */
166bf215546Sopenharmony_cistatic void setup_line_coefficients( struct lp_setup_context *setup,
167bf215546Sopenharmony_ci                                     struct lp_line_info *info)
168bf215546Sopenharmony_ci{
169bf215546Sopenharmony_ci   const struct lp_setup_variant_key *key = &setup->setup.variant->key;
170bf215546Sopenharmony_ci   unsigned fragcoord_usage_mask = TGSI_WRITEMASK_XYZ;
171bf215546Sopenharmony_ci   unsigned slot;
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci   /* setup interpolation for all the remaining attributes:
174bf215546Sopenharmony_ci    */
175bf215546Sopenharmony_ci   for (slot = 0; slot < key->num_inputs; slot++) {
176bf215546Sopenharmony_ci      unsigned vert_attr = key->inputs[slot].src_index;
177bf215546Sopenharmony_ci      unsigned usage_mask = key->inputs[slot].usage_mask;
178bf215546Sopenharmony_ci      unsigned i;
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci      switch (key->inputs[slot].interp) {
181bf215546Sopenharmony_ci      case LP_INTERP_CONSTANT:
182bf215546Sopenharmony_ci         if (key->flatshade_first) {
183bf215546Sopenharmony_ci            for (i = 0; i < NUM_CHANNELS; i++)
184bf215546Sopenharmony_ci               if (usage_mask & (1 << i))
185bf215546Sopenharmony_ci                  constant_coef(setup, info, slot+1, info->v1[vert_attr][i], i);
186bf215546Sopenharmony_ci         }
187bf215546Sopenharmony_ci         else {
188bf215546Sopenharmony_ci            for (i = 0; i < NUM_CHANNELS; i++)
189bf215546Sopenharmony_ci               if (usage_mask & (1 << i))
190bf215546Sopenharmony_ci                  constant_coef(setup, info, slot+1, info->v2[vert_attr][i], i);
191bf215546Sopenharmony_ci         }
192bf215546Sopenharmony_ci         break;
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci      case LP_INTERP_LINEAR:
195bf215546Sopenharmony_ci         for (i = 0; i < NUM_CHANNELS; i++)
196bf215546Sopenharmony_ci            if (usage_mask & (1 << i))
197bf215546Sopenharmony_ci               linear_coef(setup, info, slot+1, vert_attr, i);
198bf215546Sopenharmony_ci         break;
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci      case LP_INTERP_PERSPECTIVE:
201bf215546Sopenharmony_ci         for (i = 0; i < NUM_CHANNELS; i++)
202bf215546Sopenharmony_ci            if (usage_mask & (1 << i))
203bf215546Sopenharmony_ci               perspective_coef(setup, info, slot+1, vert_attr, i);
204bf215546Sopenharmony_ci         fragcoord_usage_mask |= TGSI_WRITEMASK_W;
205bf215546Sopenharmony_ci         break;
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_ci      case LP_INTERP_POSITION:
208bf215546Sopenharmony_ci         /*
209bf215546Sopenharmony_ci          * The generated pixel interpolators will pick up the coeffs from
210bf215546Sopenharmony_ci          * slot 0, so all need to ensure that the usage mask is covers all
211bf215546Sopenharmony_ci          * usages.
212bf215546Sopenharmony_ci          */
213bf215546Sopenharmony_ci         fragcoord_usage_mask |= usage_mask;
214bf215546Sopenharmony_ci         break;
215bf215546Sopenharmony_ci
216bf215546Sopenharmony_ci      case LP_INTERP_FACING:
217bf215546Sopenharmony_ci         for (i = 0; i < NUM_CHANNELS; i++)
218bf215546Sopenharmony_ci            if (usage_mask & (1 << i))
219bf215546Sopenharmony_ci               constant_coef(setup, info, slot+1,
220bf215546Sopenharmony_ci                             info->frontfacing ? 1.0f : -1.0f, i);
221bf215546Sopenharmony_ci         break;
222bf215546Sopenharmony_ci
223bf215546Sopenharmony_ci      default:
224bf215546Sopenharmony_ci         assert(0);
225bf215546Sopenharmony_ci      }
226bf215546Sopenharmony_ci   }
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci   /* The internal position input is in slot zero:
229bf215546Sopenharmony_ci    */
230bf215546Sopenharmony_ci   setup_fragcoord_coef(setup, info, 0,
231bf215546Sopenharmony_ci                        fragcoord_usage_mask);
232bf215546Sopenharmony_ci}
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_cistatic inline int subpixel_snap( float a )
237bf215546Sopenharmony_ci{
238bf215546Sopenharmony_ci   return util_iround(FIXED_ONE * a);
239bf215546Sopenharmony_ci}
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_ci/**
243bf215546Sopenharmony_ci * Print line vertex attribs (for debug).
244bf215546Sopenharmony_ci */
245bf215546Sopenharmony_cistatic void
246bf215546Sopenharmony_ciprint_line(struct lp_setup_context *setup,
247bf215546Sopenharmony_ci           const float (*v1)[4],
248bf215546Sopenharmony_ci           const float (*v2)[4])
249bf215546Sopenharmony_ci{
250bf215546Sopenharmony_ci   const struct lp_setup_variant_key *key = &setup->setup.variant->key;
251bf215546Sopenharmony_ci   uint i;
252bf215546Sopenharmony_ci
253bf215546Sopenharmony_ci   debug_printf("llvmpipe line\n");
254bf215546Sopenharmony_ci   for (i = 0; i < 1 + key->num_inputs; i++) {
255bf215546Sopenharmony_ci      debug_printf("  v1[%d]:  %f %f %f %f\n", i,
256bf215546Sopenharmony_ci                   v1[i][0], v1[i][1], v1[i][2], v1[i][3]);
257bf215546Sopenharmony_ci   }
258bf215546Sopenharmony_ci   for (i = 0; i < 1 + key->num_inputs; i++) {
259bf215546Sopenharmony_ci      debug_printf("  v2[%d]:  %f %f %f %f\n", i,
260bf215546Sopenharmony_ci                   v2[i][0], v2[i][1], v2[i][2], v2[i][3]);
261bf215546Sopenharmony_ci   }
262bf215546Sopenharmony_ci}
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_ci
265bf215546Sopenharmony_cistatic inline boolean sign(float x){
266bf215546Sopenharmony_ci   return x >= 0;
267bf215546Sopenharmony_ci}
268bf215546Sopenharmony_ci
269bf215546Sopenharmony_ci
270bf215546Sopenharmony_ci/* Used on positive floats only:
271bf215546Sopenharmony_ci */
272bf215546Sopenharmony_cistatic inline float fracf(float f)
273bf215546Sopenharmony_ci{
274bf215546Sopenharmony_ci   return f - floorf(f);
275bf215546Sopenharmony_ci}
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_cistatic boolean
280bf215546Sopenharmony_citry_setup_line( struct lp_setup_context *setup,
281bf215546Sopenharmony_ci               const float (*v1)[4],
282bf215546Sopenharmony_ci               const float (*v2)[4])
283bf215546Sopenharmony_ci{
284bf215546Sopenharmony_ci   struct llvmpipe_context *lp_context = (struct llvmpipe_context *)setup->pipe;
285bf215546Sopenharmony_ci   struct lp_scene *scene = setup->scene;
286bf215546Sopenharmony_ci   const struct lp_setup_variant_key *key = &setup->setup.variant->key;
287bf215546Sopenharmony_ci   struct lp_rast_triangle *line;
288bf215546Sopenharmony_ci   struct lp_rast_plane *plane;
289bf215546Sopenharmony_ci   struct lp_line_info info;
290bf215546Sopenharmony_ci   float width = MAX2(1.0, setup->line_width);
291bf215546Sopenharmony_ci   const struct u_rect *scissor;
292bf215546Sopenharmony_ci   struct u_rect bbox, bboxpos;
293bf215546Sopenharmony_ci   boolean s_planes[4];
294bf215546Sopenharmony_ci   unsigned tri_bytes;
295bf215546Sopenharmony_ci   int x[4];
296bf215546Sopenharmony_ci   int y[4];
297bf215546Sopenharmony_ci   int i;
298bf215546Sopenharmony_ci   int nr_planes = 4;
299bf215546Sopenharmony_ci   unsigned viewport_index = 0;
300bf215546Sopenharmony_ci   unsigned layer = 0;
301bf215546Sopenharmony_ci   float pixel_offset = setup->multisample ? 0.0 : setup->pixel_offset;
302bf215546Sopenharmony_ci
303bf215546Sopenharmony_ci   float dx, dy;
304bf215546Sopenharmony_ci   float area;
305bf215546Sopenharmony_ci   const float (*pv)[4];
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_ci   if (lp_context->active_statistics_queries) {
308bf215546Sopenharmony_ci      lp_context->pipeline_statistics.c_primitives++;
309bf215546Sopenharmony_ci   }
310bf215546Sopenharmony_ci
311bf215546Sopenharmony_ci   if (0)
312bf215546Sopenharmony_ci      print_line(setup, v1, v2);
313bf215546Sopenharmony_ci
314bf215546Sopenharmony_ci   if (setup->flatshade_first) {
315bf215546Sopenharmony_ci      pv = v1;
316bf215546Sopenharmony_ci   }
317bf215546Sopenharmony_ci   else {
318bf215546Sopenharmony_ci      pv = v2;
319bf215546Sopenharmony_ci   }
320bf215546Sopenharmony_ci   if (setup->viewport_index_slot > 0) {
321bf215546Sopenharmony_ci      unsigned *udata = (unsigned*)pv[setup->viewport_index_slot];
322bf215546Sopenharmony_ci      viewport_index = lp_clamp_viewport_idx(*udata);
323bf215546Sopenharmony_ci   }
324bf215546Sopenharmony_ci   if (setup->layer_slot > 0) {
325bf215546Sopenharmony_ci      layer = *(unsigned*)pv[setup->layer_slot];
326bf215546Sopenharmony_ci      layer = MIN2(layer, scene->fb_max_layer);
327bf215546Sopenharmony_ci   }
328bf215546Sopenharmony_ci
329bf215546Sopenharmony_ci   dx = v1[0][0] - v2[0][0];
330bf215546Sopenharmony_ci   dy = v1[0][1] - v2[0][1];
331bf215546Sopenharmony_ci   area = (dx * dx  + dy * dy);
332bf215546Sopenharmony_ci   if (area == 0) {
333bf215546Sopenharmony_ci      LP_COUNT(nr_culled_tris);
334bf215546Sopenharmony_ci      return TRUE;
335bf215546Sopenharmony_ci   }
336bf215546Sopenharmony_ci
337bf215546Sopenharmony_ci   info.oneoverarea = 1.0f / area;
338bf215546Sopenharmony_ci   info.dx = dx;
339bf215546Sopenharmony_ci   info.dy = dy;
340bf215546Sopenharmony_ci   info.v1 = v1;
341bf215546Sopenharmony_ci   info.v2 = v2;
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci
344bf215546Sopenharmony_ci   if (setup->rectangular_lines) {
345bf215546Sopenharmony_ci      float scale = (setup->line_width * 0.5f) / sqrtf(area);
346bf215546Sopenharmony_ci      int tx = subpixel_snap(-dy * scale);
347bf215546Sopenharmony_ci      int ty = subpixel_snap(+dx * scale);
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_ci      x[0] = subpixel_snap(v1[0][0] - pixel_offset) - tx;
350bf215546Sopenharmony_ci      x[1] = subpixel_snap(v2[0][0] - pixel_offset) - tx;
351bf215546Sopenharmony_ci      x[2] = subpixel_snap(v2[0][0] - pixel_offset) + tx;
352bf215546Sopenharmony_ci      x[3] = subpixel_snap(v1[0][0] - pixel_offset) + tx;
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci      y[0] = subpixel_snap(v1[0][1] - pixel_offset) - ty;
355bf215546Sopenharmony_ci      y[1] = subpixel_snap(v2[0][1] - pixel_offset) - ty;
356bf215546Sopenharmony_ci      y[2] = subpixel_snap(v2[0][1] - pixel_offset) + ty;
357bf215546Sopenharmony_ci      y[3] = subpixel_snap(v1[0][1] - pixel_offset) + ty;
358bf215546Sopenharmony_ci   } else {
359bf215546Sopenharmony_ci      float x_offset = 0, y_offset=0;
360bf215546Sopenharmony_ci      float x_offset_end = 0, y_offset_end = 0;
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_ci      float x1diff = v1[0][0] - floorf(v1[0][0]) - 0.5f;
363bf215546Sopenharmony_ci      float y1diff = v1[0][1] - floorf(v1[0][1]) - 0.5f;
364bf215546Sopenharmony_ci      float x2diff = v2[0][0] - floorf(v2[0][0]) - 0.5f;
365bf215546Sopenharmony_ci      float y2diff = v2[0][1] - floorf(v2[0][1]) - 0.5f;
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci      /* linewidth should be interpreted as integer */
368bf215546Sopenharmony_ci      int fixed_width = util_iround(width) * FIXED_ONE;
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ci      bool draw_start;
371bf215546Sopenharmony_ci      bool draw_end;
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_ci      if (fabsf(dx) >= fabsf(dy)) {
374bf215546Sopenharmony_ci         float dydx = dy / dx;
375bf215546Sopenharmony_ci
376bf215546Sopenharmony_ci         /* X-MAJOR LINE */
377bf215546Sopenharmony_ci
378bf215546Sopenharmony_ci         if (y2diff == -0.5 && dy < 0) {
379bf215546Sopenharmony_ci            y2diff = 0.5;
380bf215546Sopenharmony_ci         }
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_ci         /*
383bf215546Sopenharmony_ci         * Diamond exit rule test for starting point
384bf215546Sopenharmony_ci         */
385bf215546Sopenharmony_ci         if (fabsf(x1diff) + fabsf(y1diff) < 0.5) {
386bf215546Sopenharmony_ci            draw_start = true;
387bf215546Sopenharmony_ci         }
388bf215546Sopenharmony_ci         else if (sign(x1diff) == sign(-dx)) {
389bf215546Sopenharmony_ci            draw_start = false;
390bf215546Sopenharmony_ci         }
391bf215546Sopenharmony_ci         else if (sign(-y1diff) != sign(dy)) {
392bf215546Sopenharmony_ci            draw_start = true;
393bf215546Sopenharmony_ci         }
394bf215546Sopenharmony_ci         else {
395bf215546Sopenharmony_ci            /* do intersection test */
396bf215546Sopenharmony_ci            float yintersect = fracf(v1[0][1]) + x1diff * dydx;
397bf215546Sopenharmony_ci            draw_start = (yintersect < 1.0 && yintersect > 0.0);
398bf215546Sopenharmony_ci         }
399bf215546Sopenharmony_ci
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci         /*
402bf215546Sopenharmony_ci         * Diamond exit rule test for ending point
403bf215546Sopenharmony_ci         */
404bf215546Sopenharmony_ci         if (fabsf(x2diff) + fabsf(y2diff) < 0.5) {
405bf215546Sopenharmony_ci            draw_end = false;
406bf215546Sopenharmony_ci         }
407bf215546Sopenharmony_ci         else if (sign(x2diff) != sign(-dx)) {
408bf215546Sopenharmony_ci            draw_end = false;
409bf215546Sopenharmony_ci         }
410bf215546Sopenharmony_ci         else if (sign(-y2diff) == sign(dy)) {
411bf215546Sopenharmony_ci            draw_end = true;
412bf215546Sopenharmony_ci         }
413bf215546Sopenharmony_ci         else {
414bf215546Sopenharmony_ci            /* do intersection test */
415bf215546Sopenharmony_ci            float yintersect = fracf(v2[0][1]) + x2diff * dydx;
416bf215546Sopenharmony_ci            draw_end = (yintersect < 1.0 && yintersect > 0.0);
417bf215546Sopenharmony_ci         }
418bf215546Sopenharmony_ci
419bf215546Sopenharmony_ci         /* Are we already drawing start/end?
420bf215546Sopenharmony_ci         */
421bf215546Sopenharmony_ci         bool will_draw_start = sign(-x1diff) != sign(dx);
422bf215546Sopenharmony_ci         bool will_draw_end = (sign(x2diff) == sign(-dx)) || x2diff==0;
423bf215546Sopenharmony_ci
424bf215546Sopenharmony_ci         /* interpolate using the preferred wide-lines formula */
425bf215546Sopenharmony_ci         info.dx *= 1 + dydx * dydx;
426bf215546Sopenharmony_ci         info.dy = 0;
427bf215546Sopenharmony_ci
428bf215546Sopenharmony_ci         if (dx < 0) {
429bf215546Sopenharmony_ci            /* if v2 is to the right of v1, swap pointers */
430bf215546Sopenharmony_ci            const float (*temp)[4] = v1;
431bf215546Sopenharmony_ci            v1 = v2;
432bf215546Sopenharmony_ci            v2 = temp;
433bf215546Sopenharmony_ci            dx = -dx;
434bf215546Sopenharmony_ci            dy = -dy;
435bf215546Sopenharmony_ci            /* Otherwise shift planes appropriately */
436bf215546Sopenharmony_ci            if (will_draw_start != draw_start) {
437bf215546Sopenharmony_ci               x_offset_end = -x1diff - 0.5;
438bf215546Sopenharmony_ci               y_offset_end = x_offset_end * dydx;
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci            }
441bf215546Sopenharmony_ci            if (will_draw_end != draw_end) {
442bf215546Sopenharmony_ci               x_offset = -x2diff - 0.5;
443bf215546Sopenharmony_ci               y_offset = x_offset * dydx;
444bf215546Sopenharmony_ci            }
445bf215546Sopenharmony_ci
446bf215546Sopenharmony_ci         }
447bf215546Sopenharmony_ci         else {
448bf215546Sopenharmony_ci            /* Otherwise shift planes appropriately */
449bf215546Sopenharmony_ci            if (will_draw_start != draw_start) {
450bf215546Sopenharmony_ci               x_offset = -x1diff + 0.5;
451bf215546Sopenharmony_ci               y_offset = x_offset * dydx;
452bf215546Sopenharmony_ci            }
453bf215546Sopenharmony_ci            if (will_draw_end != draw_end) {
454bf215546Sopenharmony_ci               x_offset_end = -x2diff + 0.5;
455bf215546Sopenharmony_ci               y_offset_end = x_offset_end * dydx;
456bf215546Sopenharmony_ci            }
457bf215546Sopenharmony_ci         }
458bf215546Sopenharmony_ci
459bf215546Sopenharmony_ci         /* x/y positions in fixed point */
460bf215546Sopenharmony_ci         x[0] = subpixel_snap(v1[0][0] + x_offset     - pixel_offset);
461bf215546Sopenharmony_ci         x[1] = subpixel_snap(v2[0][0] + x_offset_end - pixel_offset);
462bf215546Sopenharmony_ci         x[2] = subpixel_snap(v2[0][0] + x_offset_end - pixel_offset);
463bf215546Sopenharmony_ci         x[3] = subpixel_snap(v1[0][0] + x_offset     - pixel_offset);
464bf215546Sopenharmony_ci
465bf215546Sopenharmony_ci         y[0] = subpixel_snap(v1[0][1] + y_offset     - pixel_offset) - fixed_width/2;
466bf215546Sopenharmony_ci         y[1] = subpixel_snap(v2[0][1] + y_offset_end - pixel_offset) - fixed_width/2;
467bf215546Sopenharmony_ci         y[2] = subpixel_snap(v2[0][1] + y_offset_end - pixel_offset) + fixed_width/2;
468bf215546Sopenharmony_ci         y[3] = subpixel_snap(v1[0][1] + y_offset     - pixel_offset) + fixed_width/2;
469bf215546Sopenharmony_ci      }
470bf215546Sopenharmony_ci      else {
471bf215546Sopenharmony_ci         const float dxdy = dx / dy;
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_ci         /* Y-MAJOR LINE */
474bf215546Sopenharmony_ci         x1diff = v1[0][0] - floorf(v1[0][0]) - 0.5f;
475bf215546Sopenharmony_ci         y1diff = v1[0][1] - floorf(v1[0][1]) - 0.5f;
476bf215546Sopenharmony_ci         x2diff = v2[0][0] - floorf(v2[0][0]) - 0.5f;
477bf215546Sopenharmony_ci         y2diff = v2[0][1] - floorf(v2[0][1]) - 0.5f;
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci         if (x2diff == -0.5 && dx < 0) {
480bf215546Sopenharmony_ci            x2diff = 0.5;
481bf215546Sopenharmony_ci         }
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci         /*
484bf215546Sopenharmony_ci         * Diamond exit rule test for starting point
485bf215546Sopenharmony_ci         */
486bf215546Sopenharmony_ci         if (fabsf(x1diff) + fabsf(y1diff) < 0.5) {
487bf215546Sopenharmony_ci            draw_start = true;
488bf215546Sopenharmony_ci         }
489bf215546Sopenharmony_ci         else if (sign(-y1diff) == sign(dy)) {
490bf215546Sopenharmony_ci            draw_start = false;
491bf215546Sopenharmony_ci         }
492bf215546Sopenharmony_ci         else if (sign(x1diff) != sign(-dx)) {
493bf215546Sopenharmony_ci            draw_start = true;
494bf215546Sopenharmony_ci         }
495bf215546Sopenharmony_ci         else {
496bf215546Sopenharmony_ci            /* do intersection test */
497bf215546Sopenharmony_ci            float xintersect = fracf(v1[0][0]) + y1diff * dxdy;
498bf215546Sopenharmony_ci            draw_start = (xintersect < 1.0 && xintersect > 0.0);
499bf215546Sopenharmony_ci         }
500bf215546Sopenharmony_ci
501bf215546Sopenharmony_ci         /*
502bf215546Sopenharmony_ci         * Diamond exit rule test for ending point
503bf215546Sopenharmony_ci         */
504bf215546Sopenharmony_ci         if (fabsf(x2diff) + fabsf(y2diff) < 0.5) {
505bf215546Sopenharmony_ci            draw_end = false;
506bf215546Sopenharmony_ci         }
507bf215546Sopenharmony_ci         else if (sign(-y2diff) != sign(dy) ) {
508bf215546Sopenharmony_ci            draw_end = false;
509bf215546Sopenharmony_ci         }
510bf215546Sopenharmony_ci         else if (sign(x2diff) == sign(-dx) ) {
511bf215546Sopenharmony_ci            draw_end = true;
512bf215546Sopenharmony_ci         }
513bf215546Sopenharmony_ci         else {
514bf215546Sopenharmony_ci            /* do intersection test */
515bf215546Sopenharmony_ci            float xintersect = fracf(v2[0][0]) + y2diff * dxdy;
516bf215546Sopenharmony_ci            draw_end = (xintersect < 1.0 && xintersect >= 0.0);
517bf215546Sopenharmony_ci         }
518bf215546Sopenharmony_ci
519bf215546Sopenharmony_ci         /* Are we already drawing start/end?
520bf215546Sopenharmony_ci         */
521bf215546Sopenharmony_ci         bool will_draw_start = sign(y1diff) == sign(dy);
522bf215546Sopenharmony_ci         bool will_draw_end = (sign(-y2diff) == sign(dy)) || y2diff==0;
523bf215546Sopenharmony_ci
524bf215546Sopenharmony_ci         /* interpolate using the preferred wide-lines formula */
525bf215546Sopenharmony_ci         info.dx = 0;
526bf215546Sopenharmony_ci         info.dy *= 1 + dxdy * dxdy;
527bf215546Sopenharmony_ci
528bf215546Sopenharmony_ci         if (dy > 0) {
529bf215546Sopenharmony_ci            /* if v2 is on top of v1, swap pointers */
530bf215546Sopenharmony_ci            const float (*temp)[4] = v1;
531bf215546Sopenharmony_ci            v1 = v2;
532bf215546Sopenharmony_ci            v2 = temp;
533bf215546Sopenharmony_ci            dx = -dx;
534bf215546Sopenharmony_ci            dy = -dy;
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci            /* Otherwise shift planes appropriately */
537bf215546Sopenharmony_ci            if (will_draw_start != draw_start) {
538bf215546Sopenharmony_ci               y_offset_end = -y1diff + 0.5;
539bf215546Sopenharmony_ci               x_offset_end = y_offset_end * dxdy;
540bf215546Sopenharmony_ci            }
541bf215546Sopenharmony_ci            if (will_draw_end != draw_end) {
542bf215546Sopenharmony_ci               y_offset = -y2diff + 0.5;
543bf215546Sopenharmony_ci               x_offset = y_offset * dxdy;
544bf215546Sopenharmony_ci            }
545bf215546Sopenharmony_ci         }
546bf215546Sopenharmony_ci         else {
547bf215546Sopenharmony_ci            /* Otherwise shift planes appropriately */
548bf215546Sopenharmony_ci            if (will_draw_start != draw_start) {
549bf215546Sopenharmony_ci               y_offset = -y1diff - 0.5;
550bf215546Sopenharmony_ci               x_offset = y_offset * dxdy;
551bf215546Sopenharmony_ci            }
552bf215546Sopenharmony_ci            if (will_draw_end != draw_end) {
553bf215546Sopenharmony_ci               y_offset_end = -y2diff - 0.5;
554bf215546Sopenharmony_ci               x_offset_end = y_offset_end * dxdy;
555bf215546Sopenharmony_ci            }
556bf215546Sopenharmony_ci         }
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci         /* x/y positions in fixed point */
559bf215546Sopenharmony_ci         x[0] = subpixel_snap(v1[0][0] + x_offset     - pixel_offset) - fixed_width/2;
560bf215546Sopenharmony_ci         x[1] = subpixel_snap(v2[0][0] + x_offset_end - pixel_offset) - fixed_width/2;
561bf215546Sopenharmony_ci         x[2] = subpixel_snap(v2[0][0] + x_offset_end - pixel_offset) + fixed_width/2;
562bf215546Sopenharmony_ci         x[3] = subpixel_snap(v1[0][0] + x_offset     - pixel_offset) + fixed_width/2;
563bf215546Sopenharmony_ci
564bf215546Sopenharmony_ci         y[0] = subpixel_snap(v1[0][1] + y_offset     - pixel_offset);
565bf215546Sopenharmony_ci         y[1] = subpixel_snap(v2[0][1] + y_offset_end - pixel_offset);
566bf215546Sopenharmony_ci         y[2] = subpixel_snap(v2[0][1] + y_offset_end - pixel_offset);
567bf215546Sopenharmony_ci         y[3] = subpixel_snap(v1[0][1] + y_offset     - pixel_offset);
568bf215546Sopenharmony_ci      }
569bf215546Sopenharmony_ci   }
570bf215546Sopenharmony_ci
571bf215546Sopenharmony_ci   /* Bounding rectangle (in pixels) */
572bf215546Sopenharmony_ci   {
573bf215546Sopenharmony_ci      /* Yes this is necessary to accurately calculate bounding boxes
574bf215546Sopenharmony_ci       * with the two fill-conventions we support.  GL (normally) ends
575bf215546Sopenharmony_ci       * up needing a bottom-left fill convention, which requires
576bf215546Sopenharmony_ci       * slightly different rounding.
577bf215546Sopenharmony_ci       */
578bf215546Sopenharmony_ci      int adj = (setup->bottom_edge_rule != 0) ? 1 : 0;
579bf215546Sopenharmony_ci
580bf215546Sopenharmony_ci      bbox.x0 = (MIN4(x[0], x[1], x[2], x[3]) + (FIXED_ONE-1)) >> FIXED_ORDER;
581bf215546Sopenharmony_ci      bbox.x1 = (MAX4(x[0], x[1], x[2], x[3]) + (FIXED_ONE-1)) >> FIXED_ORDER;
582bf215546Sopenharmony_ci      bbox.y0 = (MIN4(y[0], y[1], y[2], y[3]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
583bf215546Sopenharmony_ci      bbox.y1 = (MAX4(y[0], y[1], y[2], y[3]) + (FIXED_ONE-1) + adj) >> FIXED_ORDER;
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_ci      /* Inclusive coordinates:
586bf215546Sopenharmony_ci       */
587bf215546Sopenharmony_ci      bbox.x1--;
588bf215546Sopenharmony_ci      bbox.y1--;
589bf215546Sopenharmony_ci   }
590bf215546Sopenharmony_ci
591bf215546Sopenharmony_ci   if (!u_rect_test_intersection(&setup->draw_regions[viewport_index], &bbox)) {
592bf215546Sopenharmony_ci      if (0) debug_printf("no intersection\n");
593bf215546Sopenharmony_ci      LP_COUNT(nr_culled_tris);
594bf215546Sopenharmony_ci      return TRUE;
595bf215546Sopenharmony_ci   }
596bf215546Sopenharmony_ci
597bf215546Sopenharmony_ci   int max_szorig = ((bbox.x1 - (bbox.x0 & ~3)) |
598bf215546Sopenharmony_ci                     (bbox.y1 - (bbox.y0 & ~3)));
599bf215546Sopenharmony_ci   boolean use_32bits = max_szorig <= MAX_FIXED_LENGTH32;
600bf215546Sopenharmony_ci   bboxpos = bbox;
601bf215546Sopenharmony_ci
602bf215546Sopenharmony_ci   /* Can safely discard negative regions:
603bf215546Sopenharmony_ci    */
604bf215546Sopenharmony_ci   bboxpos.x0 = MAX2(bboxpos.x0, 0);
605bf215546Sopenharmony_ci   bboxpos.y0 = MAX2(bboxpos.y0, 0);
606bf215546Sopenharmony_ci
607bf215546Sopenharmony_ci   nr_planes = 4;
608bf215546Sopenharmony_ci   /*
609bf215546Sopenharmony_ci    * Determine how many scissor planes we need, that is drop scissor
610bf215546Sopenharmony_ci    * edges if the bounding box of the tri is fully inside that edge.
611bf215546Sopenharmony_ci    */
612bf215546Sopenharmony_ci   scissor = &setup->draw_regions[viewport_index];
613bf215546Sopenharmony_ci   scissor_planes_needed(s_planes, &bboxpos, scissor);
614bf215546Sopenharmony_ci   nr_planes += s_planes[0] + s_planes[1] + s_planes[2] + s_planes[3];
615bf215546Sopenharmony_ci
616bf215546Sopenharmony_ci   line = lp_setup_alloc_triangle(scene,
617bf215546Sopenharmony_ci                                  key->num_inputs,
618bf215546Sopenharmony_ci                                  nr_planes,
619bf215546Sopenharmony_ci                                  &tri_bytes);
620bf215546Sopenharmony_ci   if (!line)
621bf215546Sopenharmony_ci      return FALSE;
622bf215546Sopenharmony_ci
623bf215546Sopenharmony_ci#ifdef DEBUG
624bf215546Sopenharmony_ci   line->v[0][0] = v1[0][0];
625bf215546Sopenharmony_ci   line->v[1][0] = v2[0][0];
626bf215546Sopenharmony_ci   line->v[0][1] = v1[0][1];
627bf215546Sopenharmony_ci   line->v[1][1] = v2[0][1];
628bf215546Sopenharmony_ci#endif
629bf215546Sopenharmony_ci
630bf215546Sopenharmony_ci   LP_COUNT(nr_tris);
631bf215546Sopenharmony_ci
632bf215546Sopenharmony_ci   /* calculate the deltas */
633bf215546Sopenharmony_ci   plane = GET_PLANES(line);
634bf215546Sopenharmony_ci   plane[0].dcdy = x[0] - x[1];
635bf215546Sopenharmony_ci   plane[1].dcdy = x[1] - x[2];
636bf215546Sopenharmony_ci   plane[2].dcdy = x[2] - x[3];
637bf215546Sopenharmony_ci   plane[3].dcdy = x[3] - x[0];
638bf215546Sopenharmony_ci
639bf215546Sopenharmony_ci   plane[0].dcdx = y[0] - y[1];
640bf215546Sopenharmony_ci   plane[1].dcdx = y[1] - y[2];
641bf215546Sopenharmony_ci   plane[2].dcdx = y[2] - y[3];
642bf215546Sopenharmony_ci   plane[3].dcdx = y[3] - y[0];
643bf215546Sopenharmony_ci
644bf215546Sopenharmony_ci   if (draw_will_inject_frontface(lp_context->draw) &&
645bf215546Sopenharmony_ci       setup->face_slot > 0) {
646bf215546Sopenharmony_ci      line->inputs.frontfacing = v1[setup->face_slot][0];
647bf215546Sopenharmony_ci   } else {
648bf215546Sopenharmony_ci      line->inputs.frontfacing = TRUE;
649bf215546Sopenharmony_ci   }
650bf215546Sopenharmony_ci
651bf215546Sopenharmony_ci   /* Setup parameter interpolants:
652bf215546Sopenharmony_ci    */
653bf215546Sopenharmony_ci   info.a0 = GET_A0(&line->inputs);
654bf215546Sopenharmony_ci   info.dadx = GET_DADX(&line->inputs);
655bf215546Sopenharmony_ci   info.dady = GET_DADY(&line->inputs);
656bf215546Sopenharmony_ci   info.frontfacing = line->inputs.frontfacing;
657bf215546Sopenharmony_ci   setup_line_coefficients(setup, &info);
658bf215546Sopenharmony_ci
659bf215546Sopenharmony_ci   line->inputs.disable = FALSE;
660bf215546Sopenharmony_ci   line->inputs.layer = layer;
661bf215546Sopenharmony_ci   line->inputs.viewport_index = viewport_index;
662bf215546Sopenharmony_ci   line->inputs.view_index = setup->view_index;
663bf215546Sopenharmony_ci
664bf215546Sopenharmony_ci   /*
665bf215546Sopenharmony_ci    * XXX: this code is mostly identical to the one in lp_setup_tri, except it
666bf215546Sopenharmony_ci    * uses 4 planes instead of 3. Could share the code (including the sse
667bf215546Sopenharmony_ci    * assembly, in fact we'd get the 4th plane for free).
668bf215546Sopenharmony_ci    * The only difference apart from storing the 4th plane would be some
669bf215546Sopenharmony_ci    * different shuffle for calculating dcdx/dcdy.
670bf215546Sopenharmony_ci    */
671bf215546Sopenharmony_ci   for (i = 0; i < 4; i++) {
672bf215546Sopenharmony_ci
673bf215546Sopenharmony_ci      /* half-edge constants, will be iterated over the whole render
674bf215546Sopenharmony_ci       * target.
675bf215546Sopenharmony_ci       */
676bf215546Sopenharmony_ci      plane[i].c = IMUL64(plane[i].dcdx, x[i]) - IMUL64(plane[i].dcdy, y[i]);
677bf215546Sopenharmony_ci
678bf215546Sopenharmony_ci      /* correct for top-left vs. bottom-left fill convention.
679bf215546Sopenharmony_ci       */
680bf215546Sopenharmony_ci      if (plane[i].dcdx < 0) {
681bf215546Sopenharmony_ci         /* both fill conventions want this - adjust for left edges */
682bf215546Sopenharmony_ci         plane[i].c++;
683bf215546Sopenharmony_ci      }
684bf215546Sopenharmony_ci      else if (plane[i].dcdx == 0) {
685bf215546Sopenharmony_ci         if (setup->bottom_edge_rule == 0) {
686bf215546Sopenharmony_ci            /* correct for top-left fill convention:
687bf215546Sopenharmony_ci             */
688bf215546Sopenharmony_ci            if (plane[i].dcdy > 0) plane[i].c++;
689bf215546Sopenharmony_ci         }
690bf215546Sopenharmony_ci         else {
691bf215546Sopenharmony_ci            /* correct for bottom-left fill convention:
692bf215546Sopenharmony_ci             */
693bf215546Sopenharmony_ci            if (plane[i].dcdy < 0) plane[i].c++;
694bf215546Sopenharmony_ci         }
695bf215546Sopenharmony_ci      }
696bf215546Sopenharmony_ci
697bf215546Sopenharmony_ci      plane[i].dcdx *= FIXED_ONE;
698bf215546Sopenharmony_ci      plane[i].dcdy *= FIXED_ONE;
699bf215546Sopenharmony_ci
700bf215546Sopenharmony_ci      /* find trivial reject offsets for each edge for a single-pixel
701bf215546Sopenharmony_ci       * sized block.  These will be scaled up at each recursive level to
702bf215546Sopenharmony_ci       * match the active blocksize.  Scaling in this way works best if
703bf215546Sopenharmony_ci       * the blocks are square.
704bf215546Sopenharmony_ci       */
705bf215546Sopenharmony_ci      plane[i].eo = 0;
706bf215546Sopenharmony_ci      if (plane[i].dcdx < 0) plane[i].eo -= plane[i].dcdx;
707bf215546Sopenharmony_ci      if (plane[i].dcdy > 0) plane[i].eo += plane[i].dcdy;
708bf215546Sopenharmony_ci   }
709bf215546Sopenharmony_ci
710bf215546Sopenharmony_ci   if (nr_planes > 4) {
711bf215546Sopenharmony_ci      lp_setup_add_scissor_planes(scissor, &plane[4], s_planes, setup->multisample);
712bf215546Sopenharmony_ci   }
713bf215546Sopenharmony_ci
714bf215546Sopenharmony_ci   return lp_setup_bin_triangle(setup, line, use_32bits, false, &bboxpos, nr_planes, viewport_index);
715bf215546Sopenharmony_ci}
716bf215546Sopenharmony_ci
717bf215546Sopenharmony_ci
718bf215546Sopenharmony_cistatic void lp_setup_line_discard(struct lp_setup_context *setup,
719bf215546Sopenharmony_ci                                  const float (*v0)[4],
720bf215546Sopenharmony_ci                                  const float (*v1)[4])
721bf215546Sopenharmony_ci{
722bf215546Sopenharmony_ci}
723bf215546Sopenharmony_ci
724bf215546Sopenharmony_cistatic void lp_setup_line(struct lp_setup_context *setup,
725bf215546Sopenharmony_ci                          const float (*v0)[4],
726bf215546Sopenharmony_ci                          const float (*v1)[4])
727bf215546Sopenharmony_ci{
728bf215546Sopenharmony_ci   if (!try_setup_line(setup, v0, v1)) {
729bf215546Sopenharmony_ci      if (!lp_setup_flush_and_restart(setup))
730bf215546Sopenharmony_ci         return;
731bf215546Sopenharmony_ci
732bf215546Sopenharmony_ci      if (!try_setup_line(setup, v0, v1))
733bf215546Sopenharmony_ci         return;
734bf215546Sopenharmony_ci   }
735bf215546Sopenharmony_ci}
736bf215546Sopenharmony_ci
737bf215546Sopenharmony_ci
738bf215546Sopenharmony_civoid lp_setup_choose_line(struct lp_setup_context *setup)
739bf215546Sopenharmony_ci{
740bf215546Sopenharmony_ci   if (setup->rasterizer_discard) {
741bf215546Sopenharmony_ci      setup->line = lp_setup_line_discard;
742bf215546Sopenharmony_ci   } else {
743bf215546Sopenharmony_ci      setup->line = lp_setup_line;
744bf215546Sopenharmony_ci   }
745bf215546Sopenharmony_ci}
746bf215546Sopenharmony_ci
747bf215546Sopenharmony_ci
748