Go to the source code of this file.
Data Structures | |
struct | clipper |
Defines | |
#define | IS_NEGATIVE(X) ((X) < 0.0) |
Clipping stage. | |
#define | DIFFERENT_SIGNS(x, y) ((x) * (y) <= 0.0F && (x) - (y) != 0.0F) |
#define | MAX_CLIPPED_VERTICES ((2 * (6 + PIPE_MAX_CLIP_PLANES))+1) |
#define | LINTERP(T, OUT, IN) ((OUT) + (T) * ((IN) - (OUT))) |
Functions | |
static struct clipper * | clipper_stage (struct draw_stage *stage) |
static void | interp_attr (float *fdst, float t, const float *fin, const float *fout) |
static void | copy_colors (struct draw_stage *stage, struct vertex_header *dst, const struct vertex_header *src) |
static void | interp (const struct clipper *clip, struct vertex_header *dst, float t, const struct vertex_header *out, const struct vertex_header *in) |
static void | emit_poly (struct draw_stage *stage, struct vertex_header **inlist, unsigned n, const struct prim_header *origPrim) |
static float | dot4 (const float *a, const float *b) |
static void | do_clip_tri (struct draw_stage *stage, struct prim_header *header, unsigned clipmask) |
static void | do_clip_line (struct draw_stage *stage, struct prim_header *header, unsigned clipmask) |
static void | clip_point (struct draw_stage *stage, struct prim_header *header) |
static void | clip_line (struct draw_stage *stage, struct prim_header *header) |
static void | clip_tri (struct draw_stage *stage, struct prim_header *header) |
static void | clip_init_state (struct draw_stage *stage) |
static void | clip_first_tri (struct draw_stage *stage, struct prim_header *header) |
static void | clip_first_line (struct draw_stage *stage, struct prim_header *header) |
static void | clip_flush (struct draw_stage *stage, unsigned flags) |
static void | clip_reset_stipple_counter (struct draw_stage *stage) |
static void | clip_destroy (struct draw_stage *stage) |
struct draw_stage * | draw_clip_stage (struct draw_context *draw) |
Allocate a new clipper stage. |
#define DIFFERENT_SIGNS | ( | x, | |||
y | ) | ((x) * (y) <= 0.0F && (x) - (y) != 0.0F) |
Definition at line 49 of file draw_pipe_clip.c.
#define IS_NEGATIVE | ( | X | ) | ((X) < 0.0) |
#define LINTERP | ( | T, | |||
OUT, | |||||
IN | ) | ((OUT) + (T) * ((IN) - (OUT))) |
Definition at line 79 of file draw_pipe_clip.c.
#define MAX_CLIPPED_VERTICES ((2 * (6 + PIPE_MAX_CLIP_PLANES))+1) |
Definition at line 53 of file draw_pipe_clip.c.
static void clip_destroy | ( | struct draw_stage * | stage | ) | [static] |
Definition at line 478 of file draw_pipe_clip.c.
References draw_free_temp_verts(), and FREE.
00479 { 00480 draw_free_temp_verts( stage ); 00481 FREE( stage ); 00482 }
static void clip_first_line | ( | struct draw_stage * | stage, | |
struct prim_header * | header | |||
) | [static] |
Definition at line 455 of file draw_pipe_clip.c.
References clip_init_state(), and draw_stage::line.
00457 { 00458 clip_init_state( stage ); 00459 stage->line( stage, header ); 00460 }
static void clip_first_tri | ( | struct draw_stage * | stage, | |
struct prim_header * | header | |||
) | [static] |
Definition at line 448 of file draw_pipe_clip.c.
References clip_init_state(), and draw_stage::tri.
00450 { 00451 clip_init_state( stage ); 00452 stage->tri( stage, header ); 00453 }
static void clip_flush | ( | struct draw_stage * | stage, | |
unsigned | flags | |||
) | [static] |
Definition at line 463 of file draw_pipe_clip.c.
References clip_first_line(), clip_first_tri(), draw_stage::flush, draw_stage::line, draw_stage::next, and draw_stage::tri.
00465 { 00466 stage->tri = clip_first_tri; 00467 stage->line = clip_first_line; 00468 stage->next->flush( stage->next, flags ); 00469 }
static void clip_init_state | ( | struct draw_stage * | stage | ) | [static] |
Definition at line 423 of file draw_pipe_clip.c.
References clip_line(), clip_tri(), clipper_stage(), clipper::color_attribs, draw_stage::draw, FALSE, clipper::flat, pipe_rasterizer_state::flatshade, draw_vertex_shader::info, draw_stage::line, clipper::num_color_attribs, tgsi_shader_info::num_outputs, tgsi_shader_info::output_semantic_name, draw_context::rasterizer, TGSI_SEMANTIC_BCOLOR, TGSI_SEMANTIC_COLOR, draw_stage::tri, TRUE, draw_context::vertex_shader, and draw_context::vs.
00424 { 00425 struct clipper *clipper = clipper_stage( stage ); 00426 00427 clipper->flat = stage->draw->rasterizer->flatshade ? TRUE : FALSE; 00428 00429 if (clipper->flat) { 00430 const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader; 00431 uint i; 00432 00433 clipper->num_color_attribs = 0; 00434 for (i = 0; i < vs->info.num_outputs; i++) { 00435 if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_COLOR || 00436 vs->info.output_semantic_name[i] == TGSI_SEMANTIC_BCOLOR) { 00437 clipper->color_attribs[clipper->num_color_attribs++] = i; 00438 } 00439 } 00440 } 00441 00442 stage->tri = clip_tri; 00443 stage->line = clip_line; 00444 }
static void clip_line | ( | struct draw_stage * | stage, | |
struct prim_header * | header | |||
) | [static] |
Definition at line 382 of file draw_pipe_clip.c.
References vertex_header::clipmask, do_clip_line(), draw_stage::line, draw_stage::next, and prim_header::v.
00384 { 00385 unsigned clipmask = (header->v[0]->clipmask | 00386 header->v[1]->clipmask); 00387 00388 if (clipmask == 0) { 00389 /* no clipping needed */ 00390 stage->next->line( stage->next, header ); 00391 } 00392 else if ((header->v[0]->clipmask & 00393 header->v[1]->clipmask) == 0) { 00394 do_clip_line(stage, header, clipmask); 00395 } 00396 /* else, totally clipped */ 00397 }
static void clip_point | ( | struct draw_stage * | stage, | |
struct prim_header * | header | |||
) | [static] |
Definition at line 373 of file draw_pipe_clip.c.
References vertex_header::clipmask, draw_stage::next, draw_stage::point, and prim_header::v.
00375 { 00376 if (header->v[0]->clipmask == 0) 00377 stage->next->point( stage->next, header ); 00378 }
static void clip_reset_stipple_counter | ( | struct draw_stage * | stage | ) | [static] |
Definition at line 472 of file draw_pipe_clip.c.
References draw_stage::next, and draw_stage::reset_stipple_counter.
00473 { 00474 stage->next->reset_stipple_counter( stage->next ); 00475 }
static void clip_tri | ( | struct draw_stage * | stage, | |
struct prim_header * | header | |||
) | [static] |
Definition at line 401 of file draw_pipe_clip.c.
References vertex_header::clipmask, do_clip_tri(), draw_stage::next, draw_stage::tri, and prim_header::v.
00403 { 00404 unsigned clipmask = (header->v[0]->clipmask | 00405 header->v[1]->clipmask | 00406 header->v[2]->clipmask); 00407 00408 if (clipmask == 0) { 00409 /* no clipping needed */ 00410 stage->next->tri( stage->next, header ); 00411 } 00412 else if ((header->v[0]->clipmask & 00413 header->v[1]->clipmask & 00414 header->v[2]->clipmask) == 0) { 00415 do_clip_tri(stage, header, clipmask); 00416 } 00417 }
static struct clipper* clipper_stage | ( | struct draw_stage * | stage | ) | [static, read] |
Definition at line 73 of file draw_pipe_clip.c.
00074 { 00075 return (struct clipper *)stage; 00076 }
static void copy_colors | ( | struct draw_stage * | stage, | |
struct vertex_header * | dst, | |||
const struct vertex_header * | src | |||
) | [static] |
Definition at line 95 of file draw_pipe_clip.c.
References clipper_stage(), clipper::color_attribs, COPY_4FV, vertex_header::data, and clipper::num_color_attribs.
00098 { 00099 const struct clipper *clipper = clipper_stage(stage); 00100 uint i; 00101 for (i = 0; i < clipper->num_color_attribs; i++) { 00102 const uint attr = clipper->color_attribs[i]; 00103 COPY_4FV(dst->data[attr], src->data[attr]); 00104 } 00105 }
static void do_clip_line | ( | struct draw_stage * | stage, | |
struct prim_header * | header, | |||
unsigned | clipmask | |||
) | [static] |
Definition at line 313 of file draw_pipe_clip.c.
References vertex_header::clip, vertex_header::clipmask, clipper_stage(), copy_colors(), dot4(), clipper::flat, interp(), draw_stage::line, MAX2, draw_stage::next, clipper::plane, draw_stage::tmp, and prim_header::v.
00316 { 00317 const struct clipper *clipper = clipper_stage( stage ); 00318 struct vertex_header *v0 = header->v[0]; 00319 struct vertex_header *v1 = header->v[1]; 00320 const float *pos0 = v0->clip; 00321 const float *pos1 = v1->clip; 00322 float t0 = 0.0F; 00323 float t1 = 0.0F; 00324 struct prim_header newprim; 00325 00326 while (clipmask) { 00327 const unsigned plane_idx = ffs(clipmask)-1; 00328 const float *plane = clipper->plane[plane_idx]; 00329 const float dp0 = dot4( pos0, plane ); 00330 const float dp1 = dot4( pos1, plane ); 00331 00332 if (dp1 < 0.0F) { 00333 float t = dp1 / (dp1 - dp0); 00334 t1 = MAX2(t1, t); 00335 } 00336 00337 if (dp0 < 0.0F) { 00338 float t = dp0 / (dp0 - dp1); 00339 t0 = MAX2(t0, t); 00340 } 00341 00342 if (t0 + t1 >= 1.0F) 00343 return; /* discard */ 00344 00345 clipmask &= ~(1 << plane_idx); /* turn off this plane's bit */ 00346 } 00347 00348 if (v0->clipmask) { 00349 interp( clipper, stage->tmp[0], t0, v0, v1 ); 00350 00351 if (clipper->flat) 00352 copy_colors(stage, stage->tmp[0], v0); 00353 00354 newprim.v[0] = stage->tmp[0]; 00355 } 00356 else { 00357 newprim.v[0] = v0; 00358 } 00359 00360 if (v1->clipmask) { 00361 interp( clipper, stage->tmp[1], t1, v1, v0 ); 00362 newprim.v[1] = stage->tmp[1]; 00363 } 00364 else { 00365 newprim.v[1] = v1; 00366 } 00367 00368 stage->next->line( stage->next, &newprim ); 00369 }
static void do_clip_tri | ( | struct draw_stage * | stage, | |
struct prim_header * | header, | |||
unsigned | clipmask | |||
) | [static] |
Definition at line 216 of file draw_pipe_clip.c.
References vertex_header::clip, clipper_stage(), copy_colors(), DIFFERENT_SIGNS, dot4(), dup_vert(), vertex_header::edgeflag, emit_poly(), clipper::flat, interp(), IS_NEGATIVE, MAX_CLIPPED_VERTICES, clipper::plane, clipper::stage, draw_stage::tmp, and prim_header::v.
00219 { 00220 struct clipper *clipper = clipper_stage( stage ); 00221 struct vertex_header *a[MAX_CLIPPED_VERTICES]; 00222 struct vertex_header *b[MAX_CLIPPED_VERTICES]; 00223 struct vertex_header **inlist = a; 00224 struct vertex_header **outlist = b; 00225 unsigned tmpnr = 0; 00226 unsigned n = 3; 00227 unsigned i; 00228 00229 inlist[0] = header->v[0]; 00230 inlist[1] = header->v[1]; 00231 inlist[2] = header->v[2]; 00232 00233 while (clipmask && n >= 3) { 00234 const unsigned plane_idx = ffs(clipmask)-1; 00235 const float *plane = clipper->plane[plane_idx]; 00236 struct vertex_header *vert_prev = inlist[0]; 00237 float dp_prev = dot4( vert_prev->clip, plane ); 00238 unsigned outcount = 0; 00239 00240 clipmask &= ~(1<<plane_idx); 00241 00242 inlist[n] = inlist[0]; /* prevent rotation of vertices */ 00243 00244 for (i = 1; i <= n; i++) { 00245 struct vertex_header *vert = inlist[i]; 00246 00247 float dp = dot4( vert->clip, plane ); 00248 00249 if (!IS_NEGATIVE(dp_prev)) { 00250 outlist[outcount++] = vert_prev; 00251 } 00252 00253 if (DIFFERENT_SIGNS(dp, dp_prev)) { 00254 struct vertex_header *new_vert = clipper->stage.tmp[tmpnr++]; 00255 outlist[outcount++] = new_vert; 00256 00257 if (IS_NEGATIVE(dp)) { 00258 /* Going out of bounds. Avoid division by zero as we 00259 * know dp != dp_prev from DIFFERENT_SIGNS, above. 00260 */ 00261 float t = dp / (dp - dp_prev); 00262 interp( clipper, new_vert, t, vert, vert_prev ); 00263 00264 /* Force edgeflag true in this case: 00265 */ 00266 new_vert->edgeflag = 1; 00267 } else { 00268 /* Coming back in. 00269 */ 00270 float t = dp_prev / (dp_prev - dp); 00271 interp( clipper, new_vert, t, vert_prev, vert ); 00272 00273 /* Copy starting vert's edgeflag: 00274 */ 00275 new_vert->edgeflag = vert_prev->edgeflag; 00276 } 00277 } 00278 00279 vert_prev = vert; 00280 dp_prev = dp; 00281 } 00282 00283 { 00284 struct vertex_header **tmp = inlist; 00285 inlist = outlist; 00286 outlist = tmp; 00287 n = outcount; 00288 } 00289 } 00290 00291 /* If flat-shading, copy color to new provoking vertex. 00292 */ 00293 if (clipper->flat && inlist[0] != header->v[2]) { 00294 if (1) { 00295 inlist[0] = dup_vert(stage, inlist[0], tmpnr++); 00296 } 00297 00298 copy_colors(stage, inlist[0], header->v[2]); 00299 } 00300 00301 00302 00303 /* Emit the polygon as triangles to the setup stage: 00304 */ 00305 if (n >= 3) 00306 emit_poly( stage, inlist, n, header ); 00307 }
static float dot4 | ( | const float * | a, | |
const float * | b | |||
) | [static] |
struct draw_stage* draw_clip_stage | ( | struct draw_context * | draw | ) | [read] |
Allocate a new clipper stage.
Definition at line 489 of file draw_pipe_clip.c.
References CALLOC_STRUCT, clip_destroy(), clip_first_line(), clip_first_tri(), clip_flush(), clip_point(), clip_reset_stipple_counter(), draw_stage::destroy, draw_stage::draw, draw_alloc_temp_verts(), draw_stage::flush, draw_stage::line, MAX_CLIPPED_VERTICES, draw_context::plane, clipper::plane, draw_stage::point, draw_stage::reset_stipple_counter, clipper::stage, and draw_stage::tri.
00490 { 00491 struct clipper *clipper = CALLOC_STRUCT(clipper); 00492 if (clipper == NULL) 00493 goto fail; 00494 00495 if (!draw_alloc_temp_verts( &clipper->stage, MAX_CLIPPED_VERTICES+1 )) 00496 goto fail; 00497 00498 clipper->stage.draw = draw; 00499 clipper->stage.point = clip_point; 00500 clipper->stage.line = clip_first_line; 00501 clipper->stage.tri = clip_first_tri; 00502 clipper->stage.flush = clip_flush; 00503 clipper->stage.reset_stipple_counter = clip_reset_stipple_counter; 00504 clipper->stage.destroy = clip_destroy; 00505 00506 clipper->plane = draw->plane; 00507 00508 return &clipper->stage; 00509 00510 fail: 00511 if (clipper) 00512 clipper->stage.destroy( &clipper->stage ); 00513 00514 return NULL; 00515 }
static void emit_poly | ( | struct draw_stage * | stage, | |
struct vertex_header ** | inlist, | |||
unsigned | n, | |||
const struct prim_header * | origPrim | |||
) | [static] |
Definition at line 159 of file draw_pipe_clip.c.
References vertex_header::data, debug_printf(), prim_header::det, draw_stage::draw, DRAW_PIPE_EDGE_FLAG_0, DRAW_PIPE_EDGE_FLAG_1, DRAW_PIPE_EDGE_FLAG_2, DRAW_PIPE_RESET_STIPPLE, prim_header::flags, draw_vertex_shader::info, draw_stage::next, tgsi_shader_info::num_outputs, prim_header::pad, draw_stage::tri, prim_header::v, draw_context::vertex_shader, and draw_context::vs.
00163 { 00164 struct prim_header header; 00165 unsigned i; 00166 00167 const ushort edge_first = DRAW_PIPE_EDGE_FLAG_2; 00168 const ushort edge_middle = DRAW_PIPE_EDGE_FLAG_0; 00169 const ushort edge_last = DRAW_PIPE_EDGE_FLAG_1; 00170 00171 /* later stages may need the determinant, but only the sign matters */ 00172 header.det = origPrim->det; 00173 header.flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle; 00174 header.pad = 0; 00175 00176 for (i = 2; i < n; i++, header.flags = edge_middle) { 00177 header.v[0] = inlist[i-1]; 00178 header.v[1] = inlist[i]; 00179 header.v[2] = inlist[0]; /* keep in v[2] for flatshading */ 00180 00181 if (i == n-1) 00182 header.flags |= edge_last; 00183 00184 if (0) { 00185 const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader; 00186 uint j, k; 00187 debug_printf("Clipped tri:\n"); 00188 for (j = 0; j < 3; j++) { 00189 for (k = 0; k < vs->info.num_outputs; k++) { 00190 debug_printf(" Vert %d: Attr %d: %f %f %f %f\n", j, k, 00191 header.v[j]->data[k][0], 00192 header.v[j]->data[k][1], 00193 header.v[j]->data[k][2], 00194 header.v[j]->data[k][3]); 00195 } 00196 } 00197 } 00198 00199 stage->next->tri( stage->next, &header ); 00200 } 00201 }
static void interp | ( | const struct clipper * | clip, | |
struct vertex_header * | dst, | |||
float | t, | |||
const struct vertex_header * | out, | |||
const struct vertex_header * | in | |||
) | [static] |
Definition at line 111 of file draw_pipe_clip.c.
References vertex_header::clip, vertex_header::clipmask, vertex_header::data, draw_stage::draw, vertex_header::edgeflag, interp_attr(), draw_context::num_vs_outputs, vertex_header::pad, draw_context::position_output, pipe_viewport_state::scale, clipper::stage, pipe_viewport_state::translate, UNDEFINED_VERTEX_ID, vertex_header::vertex_id, draw_context::viewport, and draw_context::vs.
00116 { 00117 const unsigned nr_attrs = clip->stage.draw->vs.num_vs_outputs; 00118 const unsigned pos_attr = clip->stage.draw->vs.position_output; 00119 unsigned j; 00120 00121 /* Vertex header. 00122 */ 00123 { 00124 dst->clipmask = 0; 00125 dst->edgeflag = 0; /* will get overwritten later */ 00126 dst->pad = 0; 00127 dst->vertex_id = UNDEFINED_VERTEX_ID; 00128 } 00129 00130 /* Clip coordinates: interpolate normally 00131 */ 00132 { 00133 interp_attr(dst->clip, t, in->clip, out->clip); 00134 } 00135 00136 /* Do the projective divide and insert window coordinates: 00137 */ 00138 { 00139 const float *pos = dst->clip; 00140 const float *scale = clip->stage.draw->viewport.scale; 00141 const float *trans = clip->stage.draw->viewport.translate; 00142 const float oow = 1.0f / pos[3]; 00143 00144 dst->data[pos_attr][0] = pos[0] * oow * scale[0] + trans[0]; 00145 dst->data[pos_attr][1] = pos[1] * oow * scale[1] + trans[1]; 00146 dst->data[pos_attr][2] = pos[2] * oow * scale[2] + trans[2]; 00147 dst->data[pos_attr][3] = oow; 00148 } 00149 00150 /* Other attributes 00151 */ 00152 for (j = 0; j < nr_attrs; j++) { 00153 if (j != pos_attr) 00154 interp_attr(dst->data[j], t, in->data[j], out->data[j]); 00155 } 00156 }
static void interp_attr | ( | float * | fdst, | |
float | t, | |||
const float * | fin, | |||
const float * | fout | |||
) | [static] |