1 /************************************************************************** 2 * 3 * Copyright 2010, VMware Inc. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 /* 29 * Binning code for points 30 */ 31 32 #include "util/u_math.h" 33 #include "util/u_memory.h" 34 #include "lp_setup_context.h" 35 #include "lp_perf.h" 36 #include "lp_rast.h" 37 #include "lp_state_fs.h" 38 #include "lp_state_setup.h" 39 #include "lp_context.h" 40 #include "tgsi/tgsi_scan.h" 41 #include "draw/draw_context.h" 42 43 #define NUM_CHANNELS 4 44 45 struct point_info { 46 /* x,y deltas */ 47 int dy01, dy12; 48 int dx01, dx12; 49 50 const float (*v0)[4]; 51 52 float (*a0)[4]; 53 float (*dadx)[4]; 54 float (*dady)[4]; 55 56 boolean frontfacing; 57 }; 58 59 60 /** 61 * Compute a0 for a constant-valued coefficient (GL_FLAT shading). 62 */ 63 static void 64 constant_coef(struct lp_setup_context *setup, 65 struct point_info *info, 66 unsigned slot, 67 const float value, 68 unsigned i) 69 { 70 info->a0[slot][i] = value; 71 info->dadx[slot][i] = 0.0f; 72 info->dady[slot][i] = 0.0f; 73 } 74 75 76 static void 77 point_persp_coeff(struct lp_setup_context *setup, 78 const struct point_info *info, 79 unsigned slot, 80 unsigned i) 81 { 82 /* 83 * Fragment shader expects pre-multiplied w for LP_INTERP_PERSPECTIVE. A 84 * better stratergy would be to take the primitive in consideration when 85 * generating the fragment shader key, and therefore avoid the per-fragment 86 * perspective divide. 87 */ 88 89 float w0 = info->v0[0][3]; 90 91 assert(i < 4); 92 93 info->a0[slot][i] = info->v0[slot][i]*w0; 94 info->dadx[slot][i] = 0.0f; 95 info->dady[slot][i] = 0.0f; 96 } 97 98 99 /** 100 * Setup automatic texcoord coefficients (for sprite rendering). 101 * \param slot the vertex attribute slot to setup 102 * \param i the attribute channel in [0,3] 103 * \param sprite_coord_origin one of PIPE_SPRITE_COORD_x 104 * \param perspective does the shader expects pre-multiplied w, i.e., 105 * LP_INTERP_PERSPECTIVE is specified in the shader key 106 */ 107 static void 108 texcoord_coef(struct lp_setup_context *setup, 109 const struct point_info *info, 110 unsigned slot, 111 unsigned i, 112 unsigned sprite_coord_origin, 113 boolean perspective) 114 { 115 float w0 = info->v0[0][3]; 116 117 assert(i < 4); 118 119 if (i == 0) { 120 float dadx = FIXED_ONE / (float)info->dx12; 121 float dady = 0.0f; 122 float x0 = info->v0[0][0] - setup->pixel_offset; 123 float y0 = info->v0[0][1] - setup->pixel_offset; 124 125 info->dadx[slot][0] = dadx; 126 info->dady[slot][0] = dady; 127 info->a0[slot][0] = 0.5 - (dadx * x0 + dady * y0); 128 129 if (perspective) { 130 info->dadx[slot][0] *= w0; 131 info->dady[slot][0] *= w0; 132 info->a0[slot][0] *= w0; 133 } 134 } 135 else if (i == 1) { 136 float dadx = 0.0f; 137 float dady = FIXED_ONE / (float)info->dx12; 138 float x0 = info->v0[0][0] - setup->pixel_offset; 139 float y0 = info->v0[0][1] - setup->pixel_offset; 140 141 if (sprite_coord_origin == PIPE_SPRITE_COORD_LOWER_LEFT) { 142 dady = -dady; 143 } 144 145 info->dadx[slot][1] = dadx; 146 info->dady[slot][1] = dady; 147 info->a0[slot][1] = 0.5 - (dadx * x0 + dady * y0); 148 149 if (perspective) { 150 info->dadx[slot][1] *= w0; 151 info->dady[slot][1] *= w0; 152 info->a0[slot][1] *= w0; 153 } 154 } 155 else if (i == 2) { 156 info->a0[slot][2] = 0.0f; 157 info->dadx[slot][2] = 0.0f; 158 info->dady[slot][2] = 0.0f; 159 } 160 else { 161 info->a0[slot][3] = perspective ? w0 : 1.0f; 162 info->dadx[slot][3] = 0.0f; 163 info->dady[slot][3] = 0.0f; 164 } 165 } 166 167 168 /** 169 * Special coefficient setup for gl_FragCoord. 170 * X and Y are trivial 171 * Z and W are copied from position_coef which should have already been computed. 172 * We could do a bit less work if we'd examine gl_FragCoord's swizzle mask. 173 */ 174 static void 175 setup_point_fragcoord_coef(struct lp_setup_context *setup, 176 struct point_info *info, 177 unsigned slot, 178 unsigned usage_mask) 179 { 180 /*X*/ 181 if (usage_mask & TGSI_WRITEMASK_X) { 182 info->a0[slot][0] = 0.0; 183 info->dadx[slot][0] = 1.0; 184 info->dady[slot][0] = 0.0; 185 } 186 187 /*Y*/ 188 if (usage_mask & TGSI_WRITEMASK_Y) { 189 info->a0[slot][1] = 0.0; 190 info->dadx[slot][1] = 0.0; 191 info->dady[slot][1] = 1.0; 192 } 193 194 /*Z*/ 195 if (usage_mask & TGSI_WRITEMASK_Z) { 196 constant_coef(setup, info, slot, info->v0[0][2], 2); 197 } 198 199 /*W*/ 200 if (usage_mask & TGSI_WRITEMASK_W) { 201 constant_coef(setup, info, slot, info->v0[0][3], 3); 202 } 203 } 204 205 206 /** 207 * Compute the point->coef[] array dadx, dady, a0 values. 208 */ 209 static void 210 setup_point_coefficients( struct lp_setup_context *setup, 211 struct point_info *info) 212 { 213 const struct lp_setup_variant_key *key = &setup->setup.variant->key; 214 const struct lp_fragment_shader *shader = setup->fs.current.variant->shader; 215 unsigned fragcoord_usage_mask = TGSI_WRITEMASK_XYZ; 216 unsigned slot; 217 218 /* setup interpolation for all the remaining attributes: 219 */ 220 for (slot = 0; slot < key->num_inputs; slot++) { 221 unsigned vert_attr = key->inputs[slot].src_index; 222 unsigned usage_mask = key->inputs[slot].usage_mask; 223 enum lp_interp interp = key->inputs[slot].interp; 224 boolean perspective = !!(interp == LP_INTERP_PERSPECTIVE); 225 unsigned i; 226 227 if (perspective & usage_mask) { 228 fragcoord_usage_mask |= TGSI_WRITEMASK_W; 229 } 230 231 switch (interp) { 232 case LP_INTERP_POSITION: 233 /* 234 * The generated pixel interpolators will pick up the coeffs from 235 * slot 0, so all need to ensure that the usage mask is covers all 236 * usages. 237 */ 238 fragcoord_usage_mask |= usage_mask; 239 break; 240 241 case LP_INTERP_LINEAR: 242 /* Sprite tex coords may use linear interpolation someday */ 243 /* fall-through */ 244 case LP_INTERP_PERSPECTIVE: 245 /* check if the sprite coord flag is set for this attribute. 246 * If so, set it up so it up so x and y vary from 0 to 1. 247 */ 248 if (shader->info.base.input_semantic_name[slot] == TGSI_SEMANTIC_GENERIC) { 249 unsigned semantic_index = shader->info.base.input_semantic_index[slot]; 250 /* Note that sprite_coord enable is a bitfield of 251 * PIPE_MAX_SHADER_OUTPUTS bits. 252 */ 253 if (semantic_index < PIPE_MAX_SHADER_OUTPUTS && 254 (setup->sprite_coord_enable & (1 << semantic_index))) { 255 for (i = 0; i < NUM_CHANNELS; i++) { 256 if (usage_mask & (1 << i)) { 257 texcoord_coef(setup, info, slot + 1, i, 258 setup->sprite_coord_origin, 259 perspective); 260 } 261 } 262 break; 263 } 264 } 265 /* fall-through */ 266 case LP_INTERP_CONSTANT: 267 for (i = 0; i < NUM_CHANNELS; i++) { 268 if (usage_mask & (1 << i)) { 269 if (perspective) { 270 point_persp_coeff(setup, info, slot+1, i); 271 } 272 else { 273 constant_coef(setup, info, slot+1, info->v0[vert_attr][i], i); 274 } 275 } 276 } 277 break; 278 279 case LP_INTERP_FACING: 280 for (i = 0; i < NUM_CHANNELS; i++) 281 if (usage_mask & (1 << i)) 282 constant_coef(setup, info, slot+1, 283 info->frontfacing ? 1.0f : -1.0f, i); 284 break; 285 286 default: 287 assert(0); 288 break; 289 } 290 } 291 292 /* The internal position input is in slot zero: 293 */ 294 setup_point_fragcoord_coef(setup, info, 0, 295 fragcoord_usage_mask); 296 } 297 298 299 static inline int 300 subpixel_snap(float a) 301 { 302 return util_iround(FIXED_ONE * a); 303 } 304 305 /** 306 * Print point vertex attribs (for debug). 307 */ 308 static void 309 print_point(struct lp_setup_context *setup, 310 const float (*v0)[4], 311 const float size) 312 { 313 const struct lp_setup_variant_key *key = &setup->setup.variant->key; 314 uint i; 315 316 debug_printf("llvmpipe point, width %f\n", size); 317 for (i = 0; i < 1 + key->num_inputs; i++) { 318 debug_printf(" v0[%d]: %f %f %f %f\n", i, 319 v0[i][0], v0[i][1], v0[i][2], v0[i][3]); 320 } 321 } 322 323 324 static boolean 325 try_setup_point( struct lp_setup_context *setup, 326 const float (*v0)[4] ) 327 { 328 struct llvmpipe_context *lp_context = (struct llvmpipe_context *)setup->pipe; 329 /* x/y positions in fixed point */ 330 const struct lp_setup_variant_key *key = &setup->setup.variant->key; 331 const int sizeAttr = setup->psize_slot; 332 const float size 333 = (setup->point_size_per_vertex && sizeAttr > 0) ? v0[sizeAttr][0] 334 : setup->point_size; 335 336 /* Yes this is necessary to accurately calculate bounding boxes 337 * with the two fill-conventions we support. GL (normally) ends 338 * up needing a bottom-left fill convention, which requires 339 * slightly different rounding. 340 */ 341 int adj = (setup->bottom_edge_rule != 0) ? 1 : 0; 342 343 struct lp_scene *scene = setup->scene; 344 struct lp_rast_triangle *point; 345 unsigned bytes; 346 struct u_rect bbox; 347 unsigned nr_planes = 4; 348 struct point_info info; 349 unsigned viewport_index = 0; 350 unsigned layer = 0; 351 int fixed_width; 352 353 if (setup->viewport_index_slot > 0) { 354 unsigned *udata = (unsigned*)v0[setup->viewport_index_slot]; 355 viewport_index = lp_clamp_viewport_idx(*udata); 356 } 357 if (setup->layer_slot > 0) { 358 layer = *(unsigned*)v0[setup->layer_slot]; 359 layer = MIN2(layer, scene->fb_max_layer); 360 } 361 362 if (0) 363 print_point(setup, v0, size); 364 365 /* Bounding rectangle (in pixels) */ 366 if (!lp_context->rasterizer || 367 lp_context->rasterizer->point_quad_rasterization) { 368 /* 369 * Rasterize points as quads. 370 */ 371 int x0, y0; 372 /* Point size as fixed point integer, remove rounding errors 373 * and gives minimum width for very small points. 374 */ 375 fixed_width = MAX2(FIXED_ONE, subpixel_snap(size)); 376 377 x0 = subpixel_snap(v0[0][0] - setup->pixel_offset) - fixed_width/2; 378 y0 = subpixel_snap(v0[0][1] - setup->pixel_offset) - fixed_width/2; 379 380 bbox.x0 = (x0 + (FIXED_ONE-1)) >> FIXED_ORDER; 381 bbox.x1 = (x0 + fixed_width + (FIXED_ONE-1)) >> FIXED_ORDER; 382 bbox.y0 = (y0 + (FIXED_ONE-1) + adj) >> FIXED_ORDER; 383 bbox.y1 = (y0 + fixed_width + (FIXED_ONE-1) + adj) >> FIXED_ORDER; 384 385 /* Inclusive coordinates: 386 */ 387 bbox.x1--; 388 bbox.y1--; 389 } else { 390 /* 391 * OpenGL legacy rasterization rules for non-sprite points. 392 * 393 * Per OpenGL 2.1 spec, section 3.3.1, "Basic Point Rasterization". 394 * 395 * This type of point rasterization is only available in pre 3.0 contexts 396 * (or compatibilility contexts which we don't support) anyway. 397 */ 398 399 const int x0 = subpixel_snap(v0[0][0]); 400 const int y0 = subpixel_snap(v0[0][1]) - adj; 401 402 int int_width; 403 /* Point size as fixed point integer. For GL legacy points 404 * the point size is always a whole integer. 405 */ 406 fixed_width = MAX2(FIXED_ONE, 407 (subpixel_snap(size) + FIXED_ONE/2 - 1) & ~(FIXED_ONE-1)); 408 int_width = fixed_width >> FIXED_ORDER; 409 410 assert(setup->pixel_offset != 0); 411 412 if (int_width == 1) { 413 bbox.x0 = x0 >> FIXED_ORDER; 414 bbox.y0 = y0 >> FIXED_ORDER; 415 bbox.x1 = bbox.x0; 416 bbox.y1 = bbox.y0; 417 } else { 418 if (int_width & 1) { 419 /* Odd width */ 420 bbox.x0 = (x0 >> FIXED_ORDER) - (int_width - 1)/2; 421 bbox.y0 = (y0 >> FIXED_ORDER) - (int_width - 1)/2; 422 } else { 423 /* Even width */ 424 bbox.x0 = ((x0 + FIXED_ONE/2) >> FIXED_ORDER) - int_width/2; 425 bbox.y0 = ((y0 + FIXED_ONE/2) >> FIXED_ORDER) - int_width/2; 426 } 427 428 bbox.x1 = bbox.x0 + int_width - 1; 429 bbox.y1 = bbox.y0 + int_width - 1; 430 } 431 } 432 433 if (0) { 434 debug_printf(" bbox: (%i, %i) - (%i, %i)\n", 435 bbox.x0, bbox.y0, 436 bbox.x1, bbox.y1); 437 } 438 439 if (!u_rect_test_intersection(&setup->draw_regions[viewport_index], &bbox)) { 440 if (0) debug_printf("offscreen\n"); 441 LP_COUNT(nr_culled_tris); 442 return TRUE; 443 } 444 445 u_rect_find_intersection(&setup->draw_regions[viewport_index], &bbox); 446 447 point = lp_setup_alloc_triangle(scene, 448 key->num_inputs, 449 nr_planes, 450 &bytes); 451 if (!point) 452 return FALSE; 453 454 #ifdef DEBUG 455 point->v[0][0] = v0[0][0]; 456 point->v[0][1] = v0[0][1]; 457 #endif 458 459 LP_COUNT(nr_tris); 460 461 if (lp_context->active_statistics_queries && 462 !llvmpipe_rasterization_disabled(lp_context)) { 463 lp_context->pipeline_statistics.c_primitives++; 464 } 465 466 if (draw_will_inject_frontface(lp_context->draw) && 467 setup->face_slot > 0) { 468 point->inputs.frontfacing = v0[setup->face_slot][0]; 469 } else { 470 point->inputs.frontfacing = TRUE; 471 } 472 473 info.v0 = v0; 474 info.dx01 = 0; 475 info.dx12 = fixed_width; 476 info.dy01 = fixed_width; 477 info.dy12 = 0; 478 info.a0 = GET_A0(&point->inputs); 479 info.dadx = GET_DADX(&point->inputs); 480 info.dady = GET_DADY(&point->inputs); 481 info.frontfacing = point->inputs.frontfacing; 482 483 /* Setup parameter interpolants: 484 */ 485 setup_point_coefficients(setup, &info); 486 487 point->inputs.disable = FALSE; 488 point->inputs.opaque = FALSE; 489 point->inputs.layer = layer; 490 point->inputs.viewport_index = viewport_index; 491 492 { 493 struct lp_rast_plane *plane = GET_PLANES(point); 494 495 plane[0].dcdx = -1 << 8; 496 plane[0].dcdy = 0; 497 plane[0].c = (1-bbox.x0) << 8; 498 plane[0].eo = 1 << 8; 499 500 plane[1].dcdx = 1 << 8; 501 plane[1].dcdy = 0; 502 plane[1].c = (bbox.x1+1) << 8; 503 plane[1].eo = 0; 504 505 plane[2].dcdx = 0; 506 plane[2].dcdy = 1 << 8; 507 plane[2].c = (1-bbox.y0) << 8; 508 plane[2].eo = 1 << 8; 509 510 plane[3].dcdx = 0; 511 plane[3].dcdy = -1 << 8; 512 plane[3].c = (bbox.y1+1) << 8; 513 plane[3].eo = 0; 514 } 515 516 return lp_setup_bin_triangle(setup, point, &bbox, nr_planes, viewport_index); 517 } 518 519 520 static void 521 lp_setup_point(struct lp_setup_context *setup, 522 const float (*v0)[4]) 523 { 524 if (!try_setup_point( setup, v0 )) 525 { 526 if (!lp_setup_flush_and_restart(setup)) 527 return; 528 529 if (!try_setup_point( setup, v0 )) 530 return; 531 } 532 } 533 534 535 void 536 lp_setup_choose_point( struct lp_setup_context *setup ) 537 { 538 setup->point = lp_setup_point; 539 } 540 541 542