/** * Compute the setup->coef[] array dadx, dady, a0 values. * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized. */ static void setup_tri_coefficients( struct setup_context *setup ) { struct softpipe_context *softpipe = setup->softpipe; const struct sp_fragment_shader *spfs = softpipe->fs; const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe); uint fragSlot; /* z and w are done by linear interpolation: */ tri_linear_coeff(setup, &setup->posCoef, 0, 2); tri_linear_coeff(setup, &setup->posCoef, 0, 3); /* setup interpolation for all the remaining attributes: */ for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) { const uint vertSlot = vinfo->attrib[fragSlot].src_index; uint j; switch (vinfo->attrib[fragSlot].interp_mode) { case INTERP_CONSTANT: for (j = 0; j < NUM_CHANNELS; j++) const_coeff(setup, &setup->coef[fragSlot], vertSlot, j); break; case INTERP_LINEAR: for (j = 0; j < NUM_CHANNELS; j++) tri_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j); break; case INTERP_PERSPECTIVE: for (j = 0; j < NUM_CHANNELS; j++) tri_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j); break; case INTERP_POS: setup_fragcoord_coeff(setup, fragSlot); break; default: assert(0); } if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FOG) { /* FOG.y = front/back facing XXX fix this */ setup->coef[fragSlot].a0[1] = 1.0f - setup->quad.input.facing; setup->coef[fragSlot].dadx[1] = 0.0; setup->coef[fragSlot].dady[1] = 0.0; } } }
/** * Compute the setup->coef[] array dadx, dady, a0 values. * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized. */ static void setup_tri_coefficients( struct setup_context *setup ) { struct llvmpipe_context *llvmpipe = setup->llvmpipe; const struct lp_fragment_shader *lpfs = llvmpipe->fs; const struct vertex_info *vinfo = llvmpipe_get_vertex_info(llvmpipe); uint fragSlot; /* z and w are done by linear interpolation: */ tri_pos_coeff(setup, 0, 2); tri_pos_coeff(setup, 0, 3); /* setup interpolation for all the remaining attributes: */ for (fragSlot = 0; fragSlot < lpfs->info.num_inputs; fragSlot++) { const uint vertSlot = vinfo->attrib[fragSlot].src_index; switch (vinfo->attrib[fragSlot].interp_mode) { case INTERP_CONSTANT: const_coeff(setup, fragSlot, vertSlot); break; case INTERP_LINEAR: tri_linear_coeff(setup, fragSlot, vertSlot); break; case INTERP_PERSPECTIVE: tri_persp_coeff(setup, fragSlot, vertSlot); break; case INTERP_POS: setup_fragcoord_coeff(setup, fragSlot); break; default: assert(0); } if (lpfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) { setup->coef.a0[1 + fragSlot][0] = 1.0f - setup->facing; setup->coef.dadx[1 + fragSlot][0] = 0.0; setup->coef.dady[1 + fragSlot][0] = 0.0; } } }
/** * Compute the setup->coef[] array dadx, dady, a0 values. * Must be called after setup->vmin,vmax are initialized. */ static boolean setup_line_coefficients(struct setup_context *setup, const float (*v0)[4], const float (*v1)[4]) { struct softpipe_context *softpipe = setup->softpipe; const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info; const struct sp_setup_info *sinfo = &softpipe->setup_info; uint fragSlot; float area; float v[2]; assert(sinfo->valid); /* use setup->vmin, vmax to point to vertices */ if (softpipe->rasterizer->flatshade_first) setup->vprovoke = v0; else setup->vprovoke = v1; setup->vmin = v0; setup->vmax = v1; setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0]; setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1]; /* NOTE: this is not really area but something proportional to it */ area = setup->emaj.dx * setup->emaj.dx + setup->emaj.dy * setup->emaj.dy; if (area == 0.0f || util_is_inf_or_nan(area)) return FALSE; setup->oneoverarea = 1.0f / area; /* z and w are done by linear interpolation: */ v[0] = setup->vmin[0][2]; v[1] = setup->vmax[0][2]; line_linear_coeff(setup, &setup->posCoef, 2, v); v[0] = setup->vmin[0][3]; v[1] = setup->vmax[0][3]; line_linear_coeff(setup, &setup->posCoef, 3, v); /* setup interpolation for all the remaining attributes: */ for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) { const uint vertSlot = sinfo->attrib[fragSlot].src_index; uint j; switch (sinfo->attrib[fragSlot].interp) { case SP_INTERP_CONSTANT: for (j = 0; j < TGSI_NUM_CHANNELS; j++) const_coeff(setup, &setup->coef[fragSlot], vertSlot, j); break; case SP_INTERP_LINEAR: for (j = 0; j < TGSI_NUM_CHANNELS; j++) { line_apply_cylindrical_wrap(setup->vmin[vertSlot][j], setup->vmax[vertSlot][j], fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j), v); line_linear_coeff(setup, &setup->coef[fragSlot], j, v); } break; case SP_INTERP_PERSPECTIVE: for (j = 0; j < TGSI_NUM_CHANNELS; j++) { line_apply_cylindrical_wrap(setup->vmin[vertSlot][j], setup->vmax[vertSlot][j], fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j), v); line_persp_coeff(setup, &setup->coef[fragSlot], j, v); } break; case SP_INTERP_POS: setup_fragcoord_coeff(setup, fragSlot); break; default: assert(0); } if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) { /* convert 0 to 1.0 and 1 to -1.0 */ setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f; setup->coef[fragSlot].dadx[0] = 0.0; setup->coef[fragSlot].dady[0] = 0.0; } } return TRUE; }
/** * Compute the setup->coef[] array dadx, dady, a0 values. * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized. */ static void setup_tri_coefficients(struct setup_context *setup) { struct softpipe_context *softpipe = setup->softpipe; const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info; const struct sp_setup_info *sinfo = &softpipe->setup_info; uint fragSlot; float v[3]; assert(sinfo->valid); /* z and w are done by linear interpolation: */ v[0] = setup->vmin[0][2]; v[1] = setup->vmid[0][2]; v[2] = setup->vmax[0][2]; tri_linear_coeff(setup, &setup->posCoef, 2, v); v[0] = setup->vmin[0][3]; v[1] = setup->vmid[0][3]; v[2] = setup->vmax[0][3]; tri_linear_coeff(setup, &setup->posCoef, 3, v); /* setup interpolation for all the remaining attributes: */ for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) { const uint vertSlot = sinfo->attrib[fragSlot].src_index; uint j; switch (sinfo->attrib[fragSlot].interp) { case SP_INTERP_CONSTANT: for (j = 0; j < TGSI_NUM_CHANNELS; j++) { const_coeff(setup, &setup->coef[fragSlot], vertSlot, j); } break; case SP_INTERP_LINEAR: for (j = 0; j < TGSI_NUM_CHANNELS; j++) { tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j], setup->vmid[vertSlot][j], setup->vmax[vertSlot][j], fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j), v); tri_linear_coeff(setup, &setup->coef[fragSlot], j, v); } break; case SP_INTERP_PERSPECTIVE: for (j = 0; j < TGSI_NUM_CHANNELS; j++) { tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j], setup->vmid[vertSlot][j], setup->vmax[vertSlot][j], fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j), v); tri_persp_coeff(setup, &setup->coef[fragSlot], j, v); } break; case SP_INTERP_POS: setup_fragcoord_coeff(setup, fragSlot); break; default: assert(0); } if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) { /* convert 0 to 1.0 and 1 to -1.0 */ setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f; setup->coef[fragSlot].dadx[0] = 0.0; setup->coef[fragSlot].dady[0] = 0.0; } if (0) { for (j = 0; j < TGSI_NUM_CHANNELS; j++) { debug_printf("attr[%d].%c: a0:%f dx:%f dy:%f\n", fragSlot, "xyzw"[j], setup->coef[fragSlot].a0[j], setup->coef[fragSlot].dadx[j], setup->coef[fragSlot].dady[j]); } } } }
/** * Do setup for point rasterization, then render the point. * Round or square points... * XXX could optimize a lot for 1-pixel points. */ void sp_setup_point(struct setup_context *setup, const float (*v0)[4]) { struct softpipe_context *softpipe = setup->softpipe; const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info; const int sizeAttr = setup->softpipe->psize_slot; const float size = sizeAttr > 0 ? v0[sizeAttr][0] : setup->softpipe->rasterizer->point_size; const float halfSize = 0.5F * size; const boolean round = (boolean) setup->softpipe->rasterizer->point_smooth; const float x = v0[0][0]; /* Note: data[0] is always position */ const float y = v0[0][1]; const struct sp_setup_info *sinfo = &softpipe->setup_info; uint fragSlot; uint layer = 0; unsigned viewport_index = 0; #if DEBUG_VERTS debug_printf("Setup point:\n"); print_vertex(setup, v0); #endif assert(sinfo->valid); if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard) return; assert(setup->softpipe->reduced_prim == PIPE_PRIM_POINTS); if (setup->softpipe->layer_slot > 0) { layer = *(unsigned *)v0[setup->softpipe->layer_slot]; layer = MIN2(layer, setup->max_layer); } setup->quad[0].input.layer = layer; if (setup->softpipe->viewport_index_slot > 0) { unsigned *udata = (unsigned*)v0[setup->softpipe->viewport_index_slot]; viewport_index = sp_clamp_viewport_idx(*udata); } setup->quad[0].input.viewport_index = viewport_index; /* For points, all interpolants are constant-valued. * However, for point sprites, we'll need to setup texcoords appropriately. * XXX: which coefficients are the texcoords??? * We may do point sprites as textured quads... * * KW: We don't know which coefficients are texcoords - ultimately * the choice of what interpolation mode to use for each attribute * should be determined by the fragment program, using * per-attribute declaration statements that include interpolation * mode as a parameter. So either the fragment program will have * to be adjusted for pointsprite vs normal point behaviour, or * otherwise a special interpolation mode will have to be defined * which matches the required behaviour for point sprites. But - * the latter is not a feature of normal hardware, and as such * probably should be ruled out on that basis. */ setup->vprovoke = v0; /* setup Z, W */ const_coeff(setup, &setup->posCoef, 0, 2); const_coeff(setup, &setup->posCoef, 0, 3); for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) { const uint vertSlot = sinfo->attrib[fragSlot].src_index; uint j; switch (sinfo->attrib[fragSlot].interp) { case SP_INTERP_CONSTANT: /* fall-through */ case SP_INTERP_LINEAR: for (j = 0; j < TGSI_NUM_CHANNELS; j++) const_coeff(setup, &setup->coef[fragSlot], vertSlot, j); break; case SP_INTERP_PERSPECTIVE: for (j = 0; j < TGSI_NUM_CHANNELS; j++) point_persp_coeff(setup, setup->vprovoke, &setup->coef[fragSlot], vertSlot, j); break; case SP_INTERP_POS: setup_fragcoord_coeff(setup, fragSlot); break; default: assert(0); } if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) { /* convert 0 to 1.0 and 1 to -1.0 */ setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f; setup->coef[fragSlot].dadx[0] = 0.0; setup->coef[fragSlot].dady[0] = 0.0; } } if (halfSize <= 0.5 && !round) { /* special case for 1-pixel points */ const int ix = ((int) x) & 1; const int iy = ((int) y) & 1; setup->quad[0].input.x0 = (int) x - ix; setup->quad[0].input.y0 = (int) y - iy; setup->quad[0].inout.mask = (1 << ix) << (2 * iy); clip_emit_quad(setup, &setup->quad[0]); } else { if (round) { /* rounded points */ const int ixmin = block((int) (x - halfSize)); const int ixmax = block((int) (x + halfSize)); const int iymin = block((int) (y - halfSize)); const int iymax = block((int) (y + halfSize)); const float rmin = halfSize - 0.7071F; /* 0.7071 = sqrt(2)/2 */ const float rmax = halfSize + 0.7071F; const float rmin2 = MAX2(0.0F, rmin * rmin); const float rmax2 = rmax * rmax; const float cscale = 1.0F / (rmax2 - rmin2); int ix, iy; for (iy = iymin; iy <= iymax; iy += 2) { for (ix = ixmin; ix <= ixmax; ix += 2) { float dx, dy, dist2, cover; setup->quad[0].inout.mask = 0x0; dx = (ix + 0.5f) - x; dy = (iy + 0.5f) - y; dist2 = dx * dx + dy * dy; if (dist2 <= rmax2) { cover = 1.0F - (dist2 - rmin2) * cscale; setup->quad[0].input.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0f); setup->quad[0].inout.mask |= MASK_TOP_LEFT; } dx = (ix + 1.5f) - x; dy = (iy + 0.5f) - y; dist2 = dx * dx + dy * dy; if (dist2 <= rmax2) { cover = 1.0F - (dist2 - rmin2) * cscale; setup->quad[0].input.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0f); setup->quad[0].inout.mask |= MASK_TOP_RIGHT; } dx = (ix + 0.5f) - x; dy = (iy + 1.5f) - y; dist2 = dx * dx + dy * dy; if (dist2 <= rmax2) { cover = 1.0F - (dist2 - rmin2) * cscale; setup->quad[0].input.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0f); setup->quad[0].inout.mask |= MASK_BOTTOM_LEFT; } dx = (ix + 1.5f) - x; dy = (iy + 1.5f) - y; dist2 = dx * dx + dy * dy; if (dist2 <= rmax2) { cover = 1.0F - (dist2 - rmin2) * cscale; setup->quad[0].input.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0f); setup->quad[0].inout.mask |= MASK_BOTTOM_RIGHT; } if (setup->quad[0].inout.mask) { setup->quad[0].input.x0 = ix; setup->quad[0].input.y0 = iy; clip_emit_quad(setup, &setup->quad[0]); } } } } else { /* square points */ const int xmin = (int) (x + 0.75 - halfSize); const int ymin = (int) (y + 0.25 - halfSize); const int xmax = xmin + (int) size; const int ymax = ymin + (int) size; /* XXX could apply scissor to xmin,ymin,xmax,ymax now */ const int ixmin = block(xmin); const int ixmax = block(xmax - 1); const int iymin = block(ymin); const int iymax = block(ymax - 1); int ix, iy; /* debug_printf("(%f, %f) -> X:%d..%d Y:%d..%d\n", x, y, xmin, xmax,ymin,ymax); */ for (iy = iymin; iy <= iymax; iy += 2) { uint rowMask = 0xf; if (iy < ymin) { /* above the top edge */ rowMask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT); } if (iy + 1 >= ymax) { /* below the bottom edge */ rowMask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT); } for (ix = ixmin; ix <= ixmax; ix += 2) { uint mask = rowMask; if (ix < xmin) { /* fragment is past left edge of point, turn off left bits */ mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT); } if (ix + 1 >= xmax) { /* past the right edge */ mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT); } setup->quad[0].inout.mask = mask; setup->quad[0].input.x0 = ix; setup->quad[0].input.y0 = iy; clip_emit_quad(setup, &setup->quad[0]); } } } } }
/** * Compute the setup->coef[] array dadx, dady, a0 values. * Must be called after setup->vmin,vmax are initialized. */ static INLINE boolean setup_line_coefficients(struct setup_context *setup, const float (*v0)[4], const float (*v1)[4]) { struct softpipe_context *softpipe = setup->softpipe; const struct sp_fragment_shader *spfs = softpipe->fs; const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe); uint fragSlot; float area; /* use setup->vmin, vmax to point to vertices */ if (softpipe->rasterizer->flatshade_first) setup->vprovoke = v0; else setup->vprovoke = v1; setup->vmin = v0; setup->vmax = v1; setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0]; setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1]; /* NOTE: this is not really area but something proportional to it */ area = setup->emaj.dx * setup->emaj.dx + setup->emaj.dy * setup->emaj.dy; if (area == 0.0f || util_is_inf_or_nan(area)) return FALSE; setup->oneoverarea = 1.0f / area; /* z and w are done by linear interpolation: */ line_linear_coeff(setup, &setup->posCoef, 0, 2); line_linear_coeff(setup, &setup->posCoef, 0, 3); /* setup interpolation for all the remaining attributes: */ for (fragSlot = 0; fragSlot < spfs->info.num_inputs; fragSlot++) { const uint vertSlot = vinfo->attrib[fragSlot].src_index; uint j; switch (vinfo->attrib[fragSlot].interp_mode) { case INTERP_CONSTANT: for (j = 0; j < NUM_CHANNELS; j++) const_coeff(setup, &setup->coef[fragSlot], vertSlot, j); break; case INTERP_LINEAR: for (j = 0; j < NUM_CHANNELS; j++) line_linear_coeff(setup, &setup->coef[fragSlot], vertSlot, j); break; case INTERP_PERSPECTIVE: for (j = 0; j < NUM_CHANNELS; j++) line_persp_coeff(setup, &setup->coef[fragSlot], vertSlot, j); break; case INTERP_POS: setup_fragcoord_coeff(setup, fragSlot); break; default: assert(0); } if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) { setup->coef[fragSlot].a0[0] = 1.0f - setup->facing; setup->coef[fragSlot].dadx[0] = 0.0; setup->coef[fragSlot].dady[0] = 0.0; } } return TRUE; }