00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00035 #include "util/u_memory.h"
00036 #include "util/u_math.h"
00037
00038 #include "pipe/p_shader_tokens.h"
00039
00040 #include "draw_vs.h"
00041 #include "draw_pipe.h"
00042
00043
00044 #ifndef IS_NEGATIVE
00045 #define IS_NEGATIVE(X) ((X) < 0.0)
00046 #endif
00047
00048 #ifndef DIFFERENT_SIGNS
00049 #define DIFFERENT_SIGNS(x, y) ((x) * (y) <= 0.0F && (x) - (y) != 0.0F)
00050 #endif
00051
00052 #ifndef MAX_CLIPPED_VERTICES
00053 #define MAX_CLIPPED_VERTICES ((2 * (6 + PIPE_MAX_CLIP_PLANES))+1)
00054 #endif
00055
00056
00057
00058 struct clipper {
00059 struct draw_stage stage;
00061
00062
00063 boolean flat;
00064 uint num_color_attribs;
00065 uint color_attribs[4];
00066
00067 float (*plane)[4];
00068 };
00069
00070
00071
00072
00073 static INLINE struct clipper *clipper_stage( struct draw_stage *stage )
00074 {
00075 return (struct clipper *)stage;
00076 }
00077
00078
00079 #define LINTERP(T, OUT, IN) ((OUT) + (T) * ((IN) - (OUT)))
00080
00081
00082
00083
00084 static void interp_attr( float *fdst,
00085 float t,
00086 const float *fin,
00087 const float *fout )
00088 {
00089 fdst[0] = LINTERP( t, fout[0], fin[0] );
00090 fdst[1] = LINTERP( t, fout[1], fin[1] );
00091 fdst[2] = LINTERP( t, fout[2], fin[2] );
00092 fdst[3] = LINTERP( t, fout[3], fin[3] );
00093 }
00094
00095 static void copy_colors( struct draw_stage *stage,
00096 struct vertex_header *dst,
00097 const struct vertex_header *src )
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 }
00106
00107
00108
00109
00110
00111 static void interp( const struct clipper *clip,
00112 struct vertex_header *dst,
00113 float t,
00114 const struct vertex_header *out,
00115 const struct vertex_header *in )
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
00122
00123 {
00124 dst->clipmask = 0;
00125 dst->edgeflag = 0;
00126 dst->pad = 0;
00127 dst->vertex_id = UNDEFINED_VERTEX_ID;
00128 }
00129
00130
00131
00132 {
00133 interp_attr(dst->clip, t, in->clip, out->clip);
00134 }
00135
00136
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
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 }
00157
00158
00159 static void emit_poly( struct draw_stage *stage,
00160 struct vertex_header **inlist,
00161 unsigned n,
00162 const struct prim_header *origPrim)
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
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];
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 }
00202
00203 static INLINE float
00204 dot4(const float *a, const float *b)
00205 {
00206 return (a[0]*b[0] +
00207 a[1]*b[1] +
00208 a[2]*b[2] +
00209 a[3]*b[3]);
00210 }
00211
00212
00213
00214
00215 static void
00216 do_clip_tri( struct draw_stage *stage,
00217 struct prim_header *header,
00218 unsigned clipmask )
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];
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
00259
00260
00261 float t = dp / (dp - dp_prev);
00262 interp( clipper, new_vert, t, vert, vert_prev );
00263
00264
00265
00266 new_vert->edgeflag = 1;
00267 } else {
00268
00269
00270 float t = dp_prev / (dp_prev - dp);
00271 interp( clipper, new_vert, t, vert_prev, vert );
00272
00273
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
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
00304
00305 if (n >= 3)
00306 emit_poly( stage, inlist, n, header );
00307 }
00308
00309
00310
00311
00312 static void
00313 do_clip_line( struct draw_stage *stage,
00314 struct prim_header *header,
00315 unsigned clipmask )
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;
00344
00345 clipmask &= ~(1 << plane_idx);
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 }
00370
00371
00372 static void
00373 clip_point( struct draw_stage *stage,
00374 struct prim_header *header )
00375 {
00376 if (header->v[0]->clipmask == 0)
00377 stage->next->point( stage->next, header );
00378 }
00379
00380
00381 static void
00382 clip_line( struct draw_stage *stage,
00383 struct prim_header *header )
00384 {
00385 unsigned clipmask = (header->v[0]->clipmask |
00386 header->v[1]->clipmask);
00387
00388 if (clipmask == 0) {
00389
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
00397 }
00398
00399
00400 static void
00401 clip_tri( struct draw_stage *stage,
00402 struct prim_header *header )
00403 {
00404 unsigned clipmask = (header->v[0]->clipmask |
00405 header->v[1]->clipmask |
00406 header->v[2]->clipmask);
00407
00408 if (clipmask == 0) {
00409
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 }
00418
00419
00420
00421
00422 static void
00423 clip_init_state( struct draw_stage *stage )
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 }
00445
00446
00447
00448 static void clip_first_tri( struct draw_stage *stage,
00449 struct prim_header *header )
00450 {
00451 clip_init_state( stage );
00452 stage->tri( stage, header );
00453 }
00454
00455 static void clip_first_line( struct draw_stage *stage,
00456 struct prim_header *header )
00457 {
00458 clip_init_state( stage );
00459 stage->line( stage, header );
00460 }
00461
00462
00463 static void clip_flush( struct draw_stage *stage,
00464 unsigned flags )
00465 {
00466 stage->tri = clip_first_tri;
00467 stage->line = clip_first_line;
00468 stage->next->flush( stage->next, flags );
00469 }
00470
00471
00472 static void clip_reset_stipple_counter( struct draw_stage *stage )
00473 {
00474 stage->next->reset_stipple_counter( stage->next );
00475 }
00476
00477
00478 static void clip_destroy( struct draw_stage *stage )
00479 {
00480 draw_free_temp_verts( stage );
00481 FREE( stage );
00482 }
00483
00484
00489 struct draw_stage *draw_clip_stage( struct draw_context *draw )
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 }