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
00028
00029
00030
00031
00032 #include "brw_defines.h"
00033 #include "brw_context.h"
00034 #include "brw_eu.h"
00035 #include "brw_util.h"
00036 #include "brw_clip.h"
00037
00038
00039
00040
00041
00042
00043
00044 static void compute_tri_direction( struct brw_clip_compile *c )
00045 {
00046 struct brw_compile *p = &c->func;
00047 struct brw_reg e = c->reg.tmp0;
00048 struct brw_reg f = c->reg.tmp1;
00049 struct brw_reg v0 = byte_offset(c->reg.vertex[0], c->offset[VERT_RESULT_HPOS]);
00050 struct brw_reg v1 = byte_offset(c->reg.vertex[1], c->offset[VERT_RESULT_HPOS]);
00051 struct brw_reg v2 = byte_offset(c->reg.vertex[2], c->offset[VERT_RESULT_HPOS]);
00052
00053
00054
00055
00056 brw_ADD(p, e, v0, negate(v2));
00057 brw_ADD(p, f, v1, negate(v2));
00058
00059
00060
00061 brw_set_access_mode(p, BRW_ALIGN_16);
00062 brw_MUL(p, vec4(brw_null_reg()), brw_swizzle(e, 1,2,0,3), brw_swizzle(f,2,0,1,3));
00063 brw_MAC(p, vec4(e), negate(brw_swizzle(e, 2,0,1,3)), brw_swizzle(f,1,2,0,3));
00064 brw_set_access_mode(p, BRW_ALIGN_1);
00065
00066 brw_MUL(p, c->reg.dir, c->reg.dir, vec4(e));
00067 }
00068
00069
00070 static void cull_direction( struct brw_clip_compile *c )
00071 {
00072 struct brw_compile *p = &c->func;
00073 struct brw_instruction *ccw;
00074 unsigned conditional;
00075
00076 assert (!(c->key.fill_ccw == CLIP_CULL &&
00077 c->key.fill_cw == CLIP_CULL));
00078
00079 if (c->key.fill_ccw == CLIP_CULL)
00080 conditional = BRW_CONDITIONAL_GE;
00081 else
00082 conditional = BRW_CONDITIONAL_L;
00083
00084 brw_CMP(p,
00085 vec1(brw_null_reg()),
00086 conditional,
00087 get_element(c->reg.dir, 2),
00088 brw_imm_f(0));
00089
00090 ccw = brw_IF(p, BRW_EXECUTE_1);
00091 {
00092 brw_clip_kill_thread(c);
00093 }
00094 brw_ENDIF(p, ccw);
00095 }
00096
00097
00098
00099 static void copy_bfc( struct brw_clip_compile *c )
00100 {
00101 struct brw_compile *p = &c->func;
00102 struct brw_instruction *ccw;
00103 unsigned conditional;
00104
00105
00106
00107 if (!(c->offset[VERT_RESULT_COL0] && c->offset[VERT_RESULT_BFC0]) &&
00108 !(c->offset[VERT_RESULT_COL1] && c->offset[VERT_RESULT_BFC1]))
00109 return;
00110
00111
00112
00113
00114
00115 if (c->key.copy_bfc_ccw)
00116 conditional = BRW_CONDITIONAL_GE;
00117 else
00118 conditional = BRW_CONDITIONAL_L;
00119
00120 brw_CMP(p,
00121 vec1(brw_null_reg()),
00122 conditional,
00123 get_element(c->reg.dir, 2),
00124 brw_imm_f(0));
00125
00126 ccw = brw_IF(p, BRW_EXECUTE_1);
00127 {
00128 unsigned i;
00129
00130 for (i = 0; i < 3; i++) {
00131 if (c->offset[VERT_RESULT_COL0] && c->offset[VERT_RESULT_BFC0])
00132 brw_MOV(p,
00133 byte_offset(c->reg.vertex[i], c->offset[VERT_RESULT_COL0]),
00134 byte_offset(c->reg.vertex[i], c->offset[VERT_RESULT_BFC0]));
00135
00136 if (c->offset[VERT_RESULT_COL1] && c->offset[VERT_RESULT_BFC1])
00137 brw_MOV(p,
00138 byte_offset(c->reg.vertex[i], c->offset[VERT_RESULT_COL1]),
00139 byte_offset(c->reg.vertex[i], c->offset[VERT_RESULT_BFC1]));
00140 }
00141 }
00142 brw_ENDIF(p, ccw);
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156 static void compute_offset( struct brw_clip_compile *c )
00157 {
00158 struct brw_compile *p = &c->func;
00159 struct brw_reg off = c->reg.offset;
00160 struct brw_reg dir = c->reg.dir;
00161
00162 brw_math_invert(p, get_element(off, 2), get_element(dir, 2));
00163 brw_MUL(p, vec2(off), dir, get_element(off, 2));
00164
00165 brw_CMP(p,
00166 vec1(brw_null_reg()),
00167 BRW_CONDITIONAL_GE,
00168 brw_abs(get_element(off, 0)),
00169 brw_abs(get_element(off, 1)));
00170
00171 brw_SEL(p, vec1(off), brw_abs(get_element(off, 0)), brw_abs(get_element(off, 1)));
00172 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
00173
00174 brw_MUL(p, vec1(off), off, brw_imm_f(c->key.offset_factor));
00175 brw_ADD(p, vec1(off), off, brw_imm_f(c->key.offset_units));
00176 }
00177
00178
00179 static void merge_edgeflags( struct brw_clip_compile *c )
00180 {
00181 struct brw_compile *p = &c->func;
00182 struct brw_instruction *is_poly;
00183 struct brw_reg tmp0 = get_element_ud(c->reg.tmp0, 0);
00184
00185 brw_AND(p, tmp0, get_element_ud(c->reg.R0, 2), brw_imm_ud(PRIM_MASK));
00186 brw_CMP(p,
00187 vec1(brw_null_reg()),
00188 BRW_CONDITIONAL_EQ,
00189 tmp0,
00190 brw_imm_ud(_3DPRIM_POLYGON));
00191
00192
00193
00194
00195 is_poly = brw_IF(p, BRW_EXECUTE_1);
00196 {
00197 brw_set_conditionalmod(p, BRW_CONDITIONAL_EQ);
00198 brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<8));
00199 brw_MOV(p, byte_offset(c->reg.vertex[0], c->offset[VERT_RESULT_EDGE]), brw_imm_f(0));
00200 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
00201
00202 brw_set_conditionalmod(p, BRW_CONDITIONAL_EQ);
00203 brw_AND(p, vec1(brw_null_reg()), get_element_ud(c->reg.R0, 2), brw_imm_ud(1<<9));
00204 brw_MOV(p, byte_offset(c->reg.vertex[2], c->offset[VERT_RESULT_EDGE]), brw_imm_f(0));
00205 brw_set_predicate_control(p, BRW_PREDICATE_NONE);
00206 }
00207 brw_ENDIF(p, is_poly);
00208 }
00209
00210
00211
00212 static void apply_one_offset( struct brw_clip_compile *c,
00213 struct brw_indirect vert )
00214 {
00215 struct brw_compile *p = &c->func;
00216 struct brw_reg pos = deref_4f(vert, c->offset[VERT_RESULT_HPOS]);
00217 struct brw_reg z = get_element(pos, 2);
00218
00219 brw_ADD(p, z, z, vec1(c->reg.offset));
00220 }
00221
00222
00223
00224
00225
00226
00227 static void emit_lines(struct brw_clip_compile *c,
00228 boolean do_offset)
00229 {
00230 struct brw_compile *p = &c->func;
00231 struct brw_instruction *loop;
00232 struct brw_instruction *draw_edge;
00233 struct brw_indirect v0 = brw_indirect(0, 0);
00234 struct brw_indirect v1 = brw_indirect(1, 0);
00235 struct brw_indirect v0ptr = brw_indirect(2, 0);
00236 struct brw_indirect v1ptr = brw_indirect(3, 0);
00237
00238
00239
00240 if (do_offset) {
00241 brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
00242 brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
00243
00244 loop = brw_DO(p, BRW_EXECUTE_1);
00245 {
00246 brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
00247 brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
00248
00249 apply_one_offset(c, v0);
00250
00251 brw_set_conditionalmod(p, BRW_CONDITIONAL_G);
00252 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
00253 }
00254 brw_WHILE(p, loop);
00255 }
00256
00257
00258
00259
00260 brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
00261 brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
00262 brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v0ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
00263 brw_ADD(p, get_addr_reg(v1ptr), get_addr_reg(v1ptr), retype(c->reg.nr_verts, BRW_REGISTER_TYPE_UW));
00264 brw_MOV(p, deref_1uw(v1ptr, 0), deref_1uw(v0ptr, 0));
00265
00266 loop = brw_DO(p, BRW_EXECUTE_1);
00267 {
00268 brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
00269 brw_MOV(p, get_addr_reg(v1), deref_1uw(v0ptr, 2));
00270 brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
00271
00272
00273 brw_CMP(p,
00274 vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,
00275 deref_1f(v0, c->offset[VERT_RESULT_EDGE]),
00276 brw_imm_f(0));
00277 draw_edge = brw_IF(p, BRW_EXECUTE_1);
00278 {
00279 brw_clip_emit_vue(c, v0, 1, 0, (_3DPRIM_LINESTRIP << 2) | R02_PRIM_START);
00280 brw_clip_emit_vue(c, v1, 1, 0, (_3DPRIM_LINESTRIP << 2) | R02_PRIM_END);
00281 }
00282 brw_ENDIF(p, draw_edge);
00283
00284 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
00285 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
00286 }
00287 brw_WHILE(p, loop);
00288 }
00289
00290
00291
00292 static void emit_points(struct brw_clip_compile *c,
00293 boolean do_offset )
00294 {
00295 struct brw_compile *p = &c->func;
00296 struct brw_instruction *loop;
00297 struct brw_instruction *draw_point;
00298
00299 struct brw_indirect v0 = brw_indirect(0, 0);
00300 struct brw_indirect v0ptr = brw_indirect(2, 0);
00301
00302 brw_MOV(p, c->reg.loopcount, c->reg.nr_verts);
00303 brw_MOV(p, get_addr_reg(v0ptr), brw_address(c->reg.inlist));
00304
00305 loop = brw_DO(p, BRW_EXECUTE_1);
00306 {
00307 brw_MOV(p, get_addr_reg(v0), deref_1uw(v0ptr, 0));
00308 brw_ADD(p, get_addr_reg(v0ptr), get_addr_reg(v0ptr), brw_imm_uw(2));
00309
00310
00311
00312 brw_CMP(p,
00313 vec1(brw_null_reg()), BRW_CONDITIONAL_NZ,
00314 deref_1f(v0, c->offset[VERT_RESULT_EDGE]),
00315 brw_imm_f(0));
00316 draw_point = brw_IF(p, BRW_EXECUTE_1);
00317 {
00318 if (do_offset)
00319 apply_one_offset(c, v0);
00320
00321 brw_clip_emit_vue(c, v0, 1, 0, (_3DPRIM_POINTLIST << 2) | R02_PRIM_START | R02_PRIM_END);
00322 }
00323 brw_ENDIF(p, draw_point);
00324
00325 brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
00326 brw_ADD(p, c->reg.loopcount, c->reg.loopcount, brw_imm_d(-1));
00327 }
00328 brw_WHILE(p, loop);
00329 }
00330
00331
00332
00333
00334
00335
00336
00337 static void emit_primitives( struct brw_clip_compile *c,
00338 unsigned mode,
00339 boolean do_offset )
00340 {
00341 switch (mode) {
00342 case CLIP_FILL:
00343 brw_clip_tri_emit_polygon(c);
00344 break;
00345
00346 case CLIP_LINE:
00347 emit_lines(c, do_offset);
00348 break;
00349
00350 case CLIP_POINT:
00351 emit_points(c, do_offset);
00352 break;
00353
00354 case CLIP_CULL:
00355 assert(0);
00356 break;
00357 }
00358 }
00359
00360
00361
00362 static void emit_unfilled_primitives( struct brw_clip_compile *c )
00363 {
00364 struct brw_compile *p = &c->func;
00365 struct brw_instruction *ccw;
00366
00367
00368
00369 if (c->key.fill_ccw != c->key.fill_cw &&
00370 c->key.fill_ccw != CLIP_CULL &&
00371 c->key.fill_cw != CLIP_CULL)
00372 {
00373 brw_CMP(p,
00374 vec1(brw_null_reg()),
00375 BRW_CONDITIONAL_GE,
00376 get_element(c->reg.dir, 2),
00377 brw_imm_f(0));
00378
00379 ccw = brw_IF(p, BRW_EXECUTE_1);
00380 {
00381 emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);
00382 }
00383 ccw = brw_ELSE(p, ccw);
00384 {
00385 emit_primitives(c, c->key.fill_cw, c->key.offset_cw);
00386 }
00387 brw_ENDIF(p, ccw);
00388 }
00389 else if (c->key.fill_cw != CLIP_CULL) {
00390 emit_primitives(c, c->key.fill_cw, c->key.offset_cw);
00391 }
00392 else if (c->key.fill_ccw != CLIP_CULL) {
00393 emit_primitives(c, c->key.fill_ccw, c->key.offset_ccw);
00394 }
00395 }
00396
00397
00398
00399
00400 static void check_nr_verts( struct brw_clip_compile *c )
00401 {
00402 struct brw_compile *p = &c->func;
00403 struct brw_instruction *if_insn;
00404
00405 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_L, c->reg.nr_verts, brw_imm_d(3));
00406 if_insn = brw_IF(p, BRW_EXECUTE_1);
00407 {
00408 brw_clip_kill_thread(c);
00409 }
00410 brw_ENDIF(p, if_insn);
00411 }
00412
00413
00414 void brw_emit_unfilled_clip( struct brw_clip_compile *c )
00415 {
00416 struct brw_compile *p = &c->func;
00417 struct brw_instruction *do_clip;
00418
00419
00420 c->need_direction = ((c->key.offset_ccw || c->key.offset_cw) ||
00421 (c->key.fill_ccw != c->key.fill_cw) ||
00422 c->key.fill_ccw == CLIP_CULL ||
00423 c->key.fill_cw == CLIP_CULL ||
00424 c->key.copy_bfc_cw ||
00425 c->key.copy_bfc_ccw);
00426
00427 brw_clip_tri_alloc_regs(c, 3 + c->key.nr_userclip + 6);
00428 brw_clip_tri_init_vertices(c);
00429
00430 assert(c->offset[VERT_RESULT_EDGE]);
00431
00432 if (c->key.fill_ccw == CLIP_CULL &&
00433 c->key.fill_cw == CLIP_CULL) {
00434 brw_clip_kill_thread(c);
00435 return;
00436 }
00437
00438 merge_edgeflags(c);
00439
00440
00441
00442 if (c->need_direction)
00443 compute_tri_direction(c);
00444
00445 if (c->key.fill_ccw == CLIP_CULL ||
00446 c->key.fill_cw == CLIP_CULL)
00447 cull_direction(c);
00448
00449 if (c->key.offset_ccw ||
00450 c->key.offset_cw)
00451 compute_offset(c);
00452
00453 if (c->key.copy_bfc_ccw ||
00454 c->key.copy_bfc_cw)
00455 copy_bfc(c);
00456
00457
00458
00459 if (c->key.do_flat_shading)
00460 brw_clip_tri_flat_shade(c);
00461
00462 brw_clip_init_clipmask(c);
00463 brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_NZ, c->reg.planemask, brw_imm_ud(0));
00464 do_clip = brw_IF(p, BRW_EXECUTE_1);
00465 {
00466 brw_clip_init_planes(c);
00467 brw_clip_tri(c);
00468 check_nr_verts(c);
00469 }
00470 brw_ENDIF(p, do_clip);
00471
00472 emit_unfilled_primitives(c);
00473 brw_clip_kill_thread(c);
00474 }
00475
00476
00477