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