static void clip_emit_quad_job( struct setup_context *setup, uint thread, struct quad_job *job ) { struct quad_header quad; quad.input = job->input; quad.inout = job->inout; quad.coef = setup->quad.coef; quad.posCoef = setup->quad.posCoef; quad.nr_attrs = setup->quad.nr_attrs; clip_emit_quad( setup, &quad, thread ); }
/** * Plot a pixel in a line segment. */ static inline void plot(struct setup_context *setup, int x, int y) { const int iy = y & 1; const int ix = x & 1; const int quadX = x - ix; const int quadY = y - iy; const int mask = (1 << ix) << (2 * iy); if (quadX != setup->quad[0].input.x0 || quadY != setup->quad[0].input.y0) { /* flush prev quad, start new quad */ if (setup->quad[0].input.x0 != -1) clip_emit_quad(setup, &setup->quad[0]); setup->quad[0].input.x0 = quadX; setup->quad[0].input.y0 = quadY; setup->quad[0].inout.mask = 0x0; } setup->quad[0].inout.mask |= mask; }
/** * 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]); } } } } }
/** * Do setup for line rasterization, then render the line. * Single-pixel width, no stipple, etc. We rely on the 'draw' module * to handle stippling and wide lines. */ void sp_setup_line(struct setup_context *setup, const float (*v0)[4], const float (*v1)[4]) { int x0 = (int) v0[0][0]; int x1 = (int) v1[0][0]; int y0 = (int) v0[0][1]; int y1 = (int) v1[0][1]; int dx = x1 - x0; int dy = y1 - y0; int xstep, ystep; uint layer = 0; unsigned viewport_index = 0; #if DEBUG_VERTS debug_printf("Setup line:\n"); print_vertex(setup, v0); print_vertex(setup, v1); #endif if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard) return; if (dx == 0 && dy == 0) return; if (!setup_line_coefficients(setup, v0, v1)) return; assert(v0[0][0] < 1.0e9); assert(v0[0][1] < 1.0e9); assert(v1[0][0] < 1.0e9); assert(v1[0][1] < 1.0e9); if (dx < 0) { dx = -dx; /* make positive */ xstep = -1; } else { xstep = 1; } if (dy < 0) { dy = -dy; /* make positive */ ystep = -1; } else { ystep = 1; } assert(dx >= 0); assert(dy >= 0); assert(setup->softpipe->reduced_prim == PIPE_PRIM_LINES); setup->quad[0].input.x0 = setup->quad[0].input.y0 = -1; setup->quad[0].inout.mask = 0x0; if (setup->softpipe->layer_slot > 0) { layer = *(unsigned *)setup->vprovoke[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*)setup->vprovoke[setup->softpipe->viewport_index_slot]; viewport_index = sp_clamp_viewport_idx(*udata); } setup->quad[0].input.viewport_index = viewport_index; /* XXX temporary: set coverage to 1.0 so the line appears * if AA mode happens to be enabled. */ setup->quad[0].input.coverage[0] = setup->quad[0].input.coverage[1] = setup->quad[0].input.coverage[2] = setup->quad[0].input.coverage[3] = 1.0; if (dx > dy) { /*** X-major line ***/ int i; const int errorInc = dy + dy; int error = errorInc - dx; const int errorDec = error - dx; for (i = 0; i < dx; i++) { plot(setup, x0, y0); x0 += xstep; if (error < 0) { error += errorInc; } else { error += errorDec; y0 += ystep; } } } else { /*** Y-major line ***/ int i; const int errorInc = dx + dx; int error = errorInc - dy; const int errorDec = error - dy; for (i = 0; i < dy; i++) { plot(setup, x0, y0); y0 += ystep; if (error < 0) { error += errorInc; } else { error += errorDec; x0 += xstep; } } } /* draw final quad */ if (setup->quad[0].inout.mask) { clip_emit_quad(setup, &setup->quad[0]); } }
/** * Do setup for line rasterization, then render the line. * Single-pixel width, no stipple, etc. We rely on the 'draw' module * to handle stippling and wide lines. */ void llvmpipe_setup_line(struct setup_context *setup, const float (*v0)[4], const float (*v1)[4]) { int x0 = (int) v0[0][0]; int x1 = (int) v1[0][0]; int y0 = (int) v0[0][1]; int y1 = (int) v1[0][1]; int dx = x1 - x0; int dy = y1 - y0; int xstep, ystep; #if DEBUG_VERTS debug_printf("Setup line:\n"); print_vertex(setup, v0); print_vertex(setup, v1); #endif if (setup->llvmpipe->no_rast) return; if (dx == 0 && dy == 0) return; if (!setup_line_coefficients(setup, v0, v1)) return; assert(v0[0][0] < 1.0e9); assert(v0[0][1] < 1.0e9); assert(v1[0][0] < 1.0e9); assert(v1[0][1] < 1.0e9); if (dx < 0) { dx = -dx; /* make positive */ xstep = -1; } else { xstep = 1; } if (dy < 0) { dy = -dy; /* make positive */ ystep = -1; } else { ystep = 1; } assert(dx >= 0); assert(dy >= 0); assert(setup->llvmpipe->reduced_prim == PIPE_PRIM_LINES); setup->quad[0].input.x0 = setup->quad[0].input.y0 = -1; setup->quad[0].inout.mask = 0x0; /* XXX temporary: set coverage to 1.0 so the line appears * if AA mode happens to be enabled. */ setup->quad[0].input.coverage[0] = setup->quad[0].input.coverage[1] = setup->quad[0].input.coverage[2] = setup->quad[0].input.coverage[3] = 1.0; if (dx > dy) { /*** X-major line ***/ int i; const int errorInc = dy + dy; int error = errorInc - dx; const int errorDec = error - dx; for (i = 0; i < dx; i++) { plot(setup, x0, y0); x0 += xstep; if (error < 0) { error += errorInc; } else { error += errorDec; y0 += ystep; } } } else { /*** Y-major line ***/ int i; const int errorInc = dx + dx; int error = errorInc - dy; const int errorDec = error - dy; for (i = 0; i < dy; i++) { plot(setup, x0, y0); y0 += ystep; if (error < 0) { error += errorInc; } else { error += errorDec; x0 += xstep; } } } /* draw final quad */ if (setup->quad[0].inout.mask) { clip_emit_quad( setup, &setup->quad[0] ); } }