1 /* 2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. 3 4 The Weather Channel (TM) funded Tungsten Graphics to develop the 5 initial release of the Radeon 8500 driver under the XFree86 license. 6 This notice must be preserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining 9 a copy of this software and associated documentation files (the 10 "Software"), to deal in the Software without restriction, including 11 without limitation the rights to use, copy, modify, merge, publish, 12 distribute, sublicense, and/or sell copies of the Software, and to 13 permit persons to whom the Software is furnished to do so, subject to 14 the following conditions: 15 16 The above copyright notice and this permission notice (including the 17 next paragraph) shall be included in all copies or substantial 18 portions of the Software. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 28 **************************************************************************/ 29 30 /* 31 * Authors: 32 * Keith Whitwell <keithw (at) vmware.com> 33 */ 34 35 #include "main/glheader.h" 36 #include "main/mtypes.h" 37 #include "main/enums.h" 38 #include "main/image.h" 39 #include "main/imports.h" 40 #include "main/macros.h" 41 42 #include "swrast/s_context.h" 43 #include "swrast/s_fog.h" 44 #include "swrast_setup/swrast_setup.h" 45 #include "tnl/tnl.h" 46 #include "tnl/t_context.h" 47 #include "tnl/t_pipeline.h" 48 49 #include "r200_context.h" 50 #include "r200_ioctl.h" 51 #include "r200_state.h" 52 #include "r200_swtcl.h" 53 #include "r200_tcl.h" 54 55 56 /*********************************************************************** 57 * Initialization 58 ***********************************************************************/ 59 60 #define EMIT_ATTR( ATTR, STYLE, F0 ) \ 61 do { \ 62 rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = (ATTR); \ 63 rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = (STYLE); \ 64 rmesa->radeon.swtcl.vertex_attr_count++; \ 65 fmt_0 |= F0; \ 66 } while (0) 67 68 #define EMIT_PAD( N ) \ 69 do { \ 70 rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = 0; \ 71 rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = EMIT_PAD; \ 72 rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].offset = (N); \ 73 rmesa->radeon.swtcl.vertex_attr_count++; \ 74 } while (0) 75 76 static void r200SetVertexFormat( struct gl_context *ctx ) 77 { 78 r200ContextPtr rmesa = R200_CONTEXT( ctx ); 79 TNLcontext *tnl = TNL_CONTEXT(ctx); 80 struct vertex_buffer *VB = &tnl->vb; 81 GLbitfield64 index_bitset = tnl->render_inputs_bitset; 82 int fmt_0 = 0; 83 int fmt_1 = 0; 84 int offset = 0; 85 86 /* Important: 87 */ 88 if ( VB->NdcPtr != NULL ) { 89 VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr; 90 } 91 else { 92 VB->AttribPtr[VERT_ATTRIB_POS] = VB->ClipPtr; 93 } 94 95 assert( VB->AttribPtr[VERT_ATTRIB_POS] != NULL ); 96 rmesa->radeon.swtcl.vertex_attr_count = 0; 97 98 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to 99 * build up a hardware vertex. 100 */ 101 if ( !rmesa->swtcl.needproj || 102 (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) ) { 103 /* need w coord for projected textures */ 104 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F, R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0 ); 105 offset = 4; 106 } 107 else { 108 EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F, R200_VTX_XY | R200_VTX_Z0 ); 109 offset = 3; 110 } 111 112 if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_POINTSIZE)) { 113 EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, R200_VTX_POINT_SIZE ); 114 offset += 1; 115 } 116 117 rmesa->swtcl.coloroffset = offset; 118 #if MESA_LITTLE_ENDIAN 119 EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) ); 120 #else 121 EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_ABGR, (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) ); 122 #endif 123 offset += 1; 124 125 rmesa->swtcl.specoffset = 0; 126 if (index_bitset & 127 (BITFIELD64_BIT(_TNL_ATTRIB_COLOR1) | BITFIELD64_BIT(_TNL_ATTRIB_FOG))) { 128 129 #if MESA_LITTLE_ENDIAN 130 if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) { 131 rmesa->swtcl.specoffset = offset; 132 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) ); 133 } 134 else { 135 EMIT_PAD( 3 ); 136 } 137 138 if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) { 139 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) ); 140 } 141 else { 142 EMIT_PAD( 1 ); 143 } 144 #else 145 if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) { 146 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) ); 147 } 148 else { 149 EMIT_PAD( 1 ); 150 } 151 152 if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) { 153 rmesa->swtcl.specoffset = offset; 154 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) ); 155 } 156 else { 157 EMIT_PAD( 3 ); 158 } 159 #endif 160 } 161 162 if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) { 163 int i; 164 165 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { 166 if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_TEX(i))) { 167 GLuint sz = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]->size; 168 169 fmt_1 |= sz << (3 * i); 170 EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_1F + sz - 1, 0 ); 171 } 172 } 173 } 174 175 if ( (rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] & R200_FOG_USE_MASK) 176 != R200_FOG_USE_SPEC_ALPHA ) { 177 R200_STATECHANGE( rmesa, ctx ); 178 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_USE_MASK; 179 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= R200_FOG_USE_SPEC_ALPHA; 180 } 181 182 if (rmesa->radeon.tnl_index_bitset != index_bitset || 183 (rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0) || 184 (rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) { 185 R200_NEWPRIM(rmesa); 186 R200_STATECHANGE( rmesa, vtx ); 187 rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0; 188 rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = fmt_1; 189 190 rmesa->radeon.swtcl.vertex_size = 191 _tnl_install_attrs( ctx, 192 rmesa->radeon.swtcl.vertex_attrs, 193 rmesa->radeon.swtcl.vertex_attr_count, 194 NULL, 0 ); 195 rmesa->radeon.swtcl.vertex_size /= 4; 196 rmesa->radeon.tnl_index_bitset = index_bitset; 197 } 198 } 199 200 static void r200_predict_emit_size( r200ContextPtr rmesa ) 201 { 202 if (RADEON_DEBUG & RADEON_VERTS) 203 fprintf(stderr, "%s\n", __func__); 204 const int vertex_array_size = 7; 205 const int prim_size = 3; 206 if (!rmesa->radeon.swtcl.emit_prediction) { 207 const int state_size = radeonCountStateEmitSize(&rmesa->radeon); 208 if (rcommonEnsureCmdBufSpace(&rmesa->radeon, 209 state_size + 210 vertex_array_size + prim_size, 211 __func__)) 212 rmesa->radeon.swtcl.emit_prediction = radeonCountStateEmitSize(&rmesa->radeon); 213 else 214 rmesa->radeon.swtcl.emit_prediction = state_size; 215 rmesa->radeon.swtcl.emit_prediction += vertex_array_size + prim_size 216 + rmesa->radeon.cmdbuf.cs->cdw; 217 } 218 } 219 220 221 static void r200RenderStart( struct gl_context *ctx ) 222 { 223 r200SetVertexFormat( ctx ); 224 if (RADEON_DEBUG & RADEON_VERTS) 225 fprintf(stderr, "%s\n", __func__); 226 } 227 228 229 /** 230 * Set vertex state for SW TCL. The primary purpose of this function is to 231 * determine in advance whether or not the hardware can / should do the 232 * projection divide or Mesa should do it. 233 */ 234 void r200ChooseVertexState( struct gl_context *ctx ) 235 { 236 r200ContextPtr rmesa = R200_CONTEXT( ctx ); 237 TNLcontext *tnl = TNL_CONTEXT(ctx); 238 GLuint vte; 239 GLuint vap; 240 GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL || 241 ctx->Polygon.BackMode != GL_FILL); 242 GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide; 243 244 /* We must ensure that we don't do _tnl_need_projected_coords while in a 245 * rasterization fallback. As this function will be called again when we 246 * leave a rasterization fallback, we can just skip it for now. 247 */ 248 if (rmesa->radeon.Fallback != 0) 249 return; 250 251 vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]; 252 vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]; 253 254 /* HW perspective divide is a win, but tiny vertex formats are a 255 * bigger one. 256 */ 257 if ((0 == (tnl->render_inputs_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX))) 258 || twosided 259 || unfilled) { 260 rmesa->swtcl.needproj = GL_TRUE; 261 vte |= R200_VTX_XY_FMT | R200_VTX_Z_FMT; 262 vte &= ~R200_VTX_W0_FMT; 263 if (tnl->render_inputs_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) { 264 vap &= ~R200_VAP_FORCE_W_TO_ONE; 265 } 266 else { 267 vap |= R200_VAP_FORCE_W_TO_ONE; 268 } 269 } 270 else { 271 rmesa->swtcl.needproj = GL_FALSE; 272 vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT); 273 vte |= R200_VTX_W0_FMT; 274 vap &= ~R200_VAP_FORCE_W_TO_ONE; 275 } 276 277 _tnl_need_projected_coords( ctx, rmesa->swtcl.needproj ); 278 279 if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) { 280 R200_STATECHANGE( rmesa, vte ); 281 rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte; 282 } 283 284 if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) { 285 R200_STATECHANGE( rmesa, vap ); 286 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap; 287 } 288 } 289 290 void r200_swtcl_flush(struct gl_context *ctx, uint32_t current_offset) 291 { 292 r200ContextPtr rmesa = R200_CONTEXT(ctx); 293 if (RADEON_DEBUG & RADEON_VERTS) 294 fprintf(stderr, "%s\n", __func__); 295 296 297 radeonEmitState(&rmesa->radeon); 298 r200EmitVertexAOS( rmesa, 299 rmesa->radeon.swtcl.vertex_size, 300 rmesa->radeon.swtcl.bo, 301 current_offset); 302 303 304 r200EmitVbufPrim( rmesa, 305 rmesa->radeon.swtcl.hw_primitive, 306 rmesa->radeon.swtcl.numverts); 307 if ( rmesa->radeon.swtcl.emit_prediction < rmesa->radeon.cmdbuf.cs->cdw ) 308 WARN_ONCE("Rendering was %d commands larger than predicted size." 309 " We might overflow command buffer.\n", 310 rmesa->radeon.cmdbuf.cs->cdw - rmesa->radeon.swtcl.emit_prediction ); 311 312 rmesa->radeon.swtcl.emit_prediction = 0; 313 314 } 315 316 /**************************************************************************/ 317 318 319 static inline GLuint reduced_hw_prim( struct gl_context *ctx, GLuint prim) 320 { 321 switch (prim) { 322 case GL_POINTS: 323 return ((!ctx->Point.SmoothFlag) ? 324 R200_VF_PRIM_POINT_SPRITES : R200_VF_PRIM_POINTS); 325 case GL_LINES: 326 /* fallthrough */ 327 case GL_LINE_LOOP: 328 /* fallthrough */ 329 case GL_LINE_STRIP: 330 return R200_VF_PRIM_LINES; 331 default: 332 /* all others reduced to triangles */ 333 return R200_VF_PRIM_TRIANGLES; 334 } 335 } 336 337 338 static void r200RasterPrimitive( struct gl_context *ctx, GLuint hwprim ); 339 static void r200RenderPrimitive( struct gl_context *ctx, GLenum prim ); 340 static void r200ResetLineStipple( struct gl_context *ctx ); 341 342 /*********************************************************************** 343 * Emit primitives as inline vertices * 344 ***********************************************************************/ 345 346 #define HAVE_POINTS 1 347 #define HAVE_LINES 1 348 #define HAVE_LINE_STRIPS 1 349 #define HAVE_TRIANGLES 1 350 #define HAVE_TRI_STRIPS 1 351 #define HAVE_TRI_FANS 1 352 #define HAVE_QUADS 0 353 #define HAVE_QUAD_STRIPS 0 354 #define HAVE_POLYGONS 1 355 #define HAVE_ELTS 0 356 357 static void* r200_alloc_verts( r200ContextPtr rmesa, GLuint n, GLuint size) 358 { 359 void *rv; 360 do { 361 r200_predict_emit_size( rmesa ); 362 rv = rcommonAllocDmaLowVerts( &rmesa->radeon, n, size * 4 ); 363 } while(!rv); 364 return rv; 365 } 366 367 #undef LOCAL_VARS 368 #undef ALLOC_VERTS 369 #define CTX_ARG r200ContextPtr rmesa 370 #define GET_VERTEX_DWORDS() rmesa->radeon.swtcl.vertex_size 371 #define ALLOC_VERTS( n, size ) r200_alloc_verts(rmesa, n, size) 372 #define LOCAL_VARS \ 373 r200ContextPtr rmesa = R200_CONTEXT(ctx); \ 374 const char *r200verts = (char *)rmesa->radeon.swtcl.verts; 375 #define VERT(x) (radeonVertex *)(r200verts + ((x) * vertsize * sizeof(int))) 376 #define VERTEX radeonVertex 377 #define DO_DEBUG_VERTS (1 && (R200_DEBUG & RADEON_VERTS)) 378 379 #undef TAG 380 #define TAG(x) r200_##x 381 #include "tnl_dd/t_dd_triemit.h" 382 383 384 /*********************************************************************** 385 * Macros for t_dd_tritmp.h to draw basic primitives * 386 ***********************************************************************/ 387 388 #define QUAD( a, b, c, d ) r200_quad( rmesa, a, b, c, d ) 389 #define TRI( a, b, c ) r200_triangle( rmesa, a, b, c ) 390 #define LINE( a, b ) r200_line( rmesa, a, b ) 391 #define POINT( a ) r200_point( rmesa, a ) 392 393 /*********************************************************************** 394 * Build render functions from dd templates * 395 ***********************************************************************/ 396 397 #define R200_TWOSIDE_BIT 0x01 398 #define R200_UNFILLED_BIT 0x02 399 #define R200_MAX_TRIFUNC 0x04 400 401 402 static struct { 403 tnl_points_func points; 404 tnl_line_func line; 405 tnl_triangle_func triangle; 406 tnl_quad_func quad; 407 } rast_tab[R200_MAX_TRIFUNC]; 408 409 410 #define DO_FALLBACK 0 411 #define DO_UNFILLED ((IND & R200_UNFILLED_BIT) != 0) 412 #define DO_TWOSIDE ((IND & R200_TWOSIDE_BIT) != 0) 413 #define DO_FLAT 0 414 #define DO_OFFSET 0 415 #define DO_TRI 1 416 #define DO_QUAD 1 417 #define DO_LINE 1 418 #define DO_POINTS 1 419 #define DO_FULL_QUAD 1 420 421 #define HAVE_SPEC 1 422 #define HAVE_BACK_COLORS 0 423 #define HAVE_HW_FLATSHADE 1 424 #define TAB rast_tab 425 426 #define DEPTH_SCALE 1.0 427 #define UNFILLED_TRI unfilled_tri 428 #define UNFILLED_QUAD unfilled_quad 429 #define VERT_X(_v) _v->v.x 430 #define VERT_Y(_v) _v->v.y 431 #define VERT_Z(_v) _v->v.z 432 #define AREA_IS_CCW( a ) (a < 0) 433 #define GET_VERTEX(e) (rmesa->radeon.swtcl.verts + (e*rmesa->radeon.swtcl.vertex_size*sizeof(int))) 434 435 #define VERT_SET_RGBA( v, c ) \ 436 do { \ 437 radeon_color_t *color = (radeon_color_t *)&((v)->ui[coloroffset]); \ 438 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \ 439 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \ 440 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \ 441 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \ 442 } while (0) 443 444 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset] 445 446 #define VERT_SET_SPEC( v, c ) \ 447 do { \ 448 if (specoffset) { \ 449 radeon_color_t *spec = (radeon_color_t *)&((v)->ui[specoffset]); \ 450 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \ 451 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \ 452 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \ 453 } \ 454 } while (0) 455 #define VERT_COPY_SPEC( v0, v1 ) \ 456 do { \ 457 if (specoffset) { \ 458 radeon_color_t *spec0 = (radeon_color_t *)&((v0)->ui[specoffset]); \ 459 radeon_color_t *spec1 = (radeon_color_t *)&((v1)->ui[specoffset]); \ 460 spec0->red = spec1->red; \ 461 spec0->green = spec1->green; \ 462 spec0->blue = spec1->blue; \ 463 } \ 464 } while (0) 465 466 /* These don't need LE32_TO_CPU() as they used to save and restore 467 * colors which are already in the correct format. 468 */ 469 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset] 470 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx] 471 #define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset] 472 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx] 473 474 #undef LOCAL_VARS 475 #undef TAG 476 #undef INIT 477 478 #define LOCAL_VARS(n) \ 479 r200ContextPtr rmesa = R200_CONTEXT(ctx); \ 480 GLuint color[n] = {0}, spec[n] = {0}; \ 481 GLuint coloroffset = rmesa->swtcl.coloroffset; \ 482 GLuint specoffset = rmesa->swtcl.specoffset; \ 483 (void) color; (void) spec; (void) coloroffset; (void) specoffset; 484 485 /*********************************************************************** 486 * Helpers for rendering unfilled primitives * 487 ***********************************************************************/ 488 489 #define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim(ctx, x) ) 490 #define RENDER_PRIMITIVE rmesa->radeon.swtcl.render_primitive 491 #undef TAG 492 #define TAG(x) x 493 #include "tnl_dd/t_dd_unfilled.h" 494 #undef IND 495 496 497 /*********************************************************************** 498 * Generate GL render functions * 499 ***********************************************************************/ 500 501 502 #define IND (0) 503 #define TAG(x) x 504 #include "tnl_dd/t_dd_tritmp.h" 505 506 #define IND (R200_TWOSIDE_BIT) 507 #define TAG(x) x##_twoside 508 #include "tnl_dd/t_dd_tritmp.h" 509 510 #define IND (R200_UNFILLED_BIT) 511 #define TAG(x) x##_unfilled 512 #include "tnl_dd/t_dd_tritmp.h" 513 514 #define IND (R200_TWOSIDE_BIT|R200_UNFILLED_BIT) 515 #define TAG(x) x##_twoside_unfilled 516 #include "tnl_dd/t_dd_tritmp.h" 517 518 519 static void init_rast_tab( void ) 520 { 521 init(); 522 init_twoside(); 523 init_unfilled(); 524 init_twoside_unfilled(); 525 } 526 527 /**********************************************************************/ 528 /* Render unclipped begin/end objects */ 529 /**********************************************************************/ 530 531 #define RENDER_POINTS( start, count ) \ 532 for ( ; start < count ; start++) \ 533 r200_point( rmesa, VERT(start) ) 534 #define RENDER_LINE( v0, v1 ) \ 535 r200_line( rmesa, VERT(v0), VERT(v1) ) 536 #define RENDER_TRI( v0, v1, v2 ) \ 537 r200_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) ) 538 #define RENDER_QUAD( v0, v1, v2, v3 ) \ 539 r200_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) ) 540 #define INIT(x) do { \ 541 r200RenderPrimitive( ctx, x ); \ 542 } while (0) 543 #undef LOCAL_VARS 544 #define LOCAL_VARS \ 545 r200ContextPtr rmesa = R200_CONTEXT(ctx); \ 546 const GLuint vertsize = rmesa->radeon.swtcl.vertex_size; \ 547 const char *r200verts = (char *)rmesa->radeon.swtcl.verts; \ 548 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \ 549 const GLboolean stipple = ctx->Line.StippleFlag; \ 550 (void) elt; (void) stipple; 551 #define RESET_STIPPLE if ( stipple ) r200ResetLineStipple( ctx ); 552 #define RESET_OCCLUSION 553 #define PRESERVE_VB_DEFS 554 #define ELT(x) (x) 555 #define TAG(x) r200_##x##_verts 556 #include "tnl/t_vb_rendertmp.h" 557 #undef ELT 558 #undef TAG 559 #define TAG(x) r200_##x##_elts 560 #define ELT(x) elt[x] 561 #include "tnl/t_vb_rendertmp.h" 562 563 564 565 /**********************************************************************/ 566 /* Choose render functions */ 567 /**********************************************************************/ 568 569 void r200ChooseRenderState( struct gl_context *ctx ) 570 { 571 TNLcontext *tnl = TNL_CONTEXT(ctx); 572 r200ContextPtr rmesa = R200_CONTEXT(ctx); 573 GLuint index = 0; 574 GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL || 575 ctx->Polygon.BackMode != GL_FILL); 576 GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide; 577 578 if (!rmesa->radeon.TclFallback || rmesa->radeon.Fallback) 579 return; 580 581 if (twosided) 582 index |= R200_TWOSIDE_BIT; 583 if (unfilled) 584 index |= R200_UNFILLED_BIT; 585 586 if (index != rmesa->radeon.swtcl.RenderIndex) { 587 tnl->Driver.Render.Points = rast_tab[index].points; 588 tnl->Driver.Render.Line = rast_tab[index].line; 589 tnl->Driver.Render.ClippedLine = rast_tab[index].line; 590 tnl->Driver.Render.Triangle = rast_tab[index].triangle; 591 tnl->Driver.Render.Quad = rast_tab[index].quad; 592 593 if (index == 0) { 594 tnl->Driver.Render.PrimTabVerts = r200_render_tab_verts; 595 tnl->Driver.Render.PrimTabElts = r200_render_tab_elts; 596 tnl->Driver.Render.ClippedPolygon = r200_fast_clipped_poly; 597 } else { 598 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; 599 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; 600 tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon; 601 } 602 603 rmesa->radeon.swtcl.RenderIndex = index; 604 } 605 } 606 607 608 /**********************************************************************/ 609 /* High level hooks for t_vb_render.c */ 610 /**********************************************************************/ 611 612 613 static void r200RasterPrimitive( struct gl_context *ctx, GLuint hwprim ) 614 { 615 r200ContextPtr rmesa = R200_CONTEXT(ctx); 616 617 radeon_prepare_render(&rmesa->radeon); 618 if (rmesa->radeon.NewGLState) 619 r200ValidateState( ctx ); 620 621 622 if (rmesa->radeon.swtcl.hw_primitive != hwprim) { 623 /* need to disable perspective-correct texturing for point sprites */ 624 if ((hwprim & 0xf) == R200_VF_PRIM_POINT_SPRITES && ctx->Point.PointSprite) { 625 if (rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE) { 626 R200_STATECHANGE( rmesa, set ); 627 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PERSPECTIVE_ENABLE; 628 } 629 } 630 else if (!(rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE)) { 631 R200_STATECHANGE( rmesa, set ); 632 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PERSPECTIVE_ENABLE; 633 } 634 R200_NEWPRIM( rmesa ); 635 rmesa->radeon.swtcl.hw_primitive = hwprim; 636 } 637 } 638 639 static void r200RenderPrimitive( struct gl_context *ctx, GLenum prim ) 640 { 641 r200ContextPtr rmesa = R200_CONTEXT(ctx); 642 GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL || 643 ctx->Polygon.BackMode != GL_FILL); 644 645 rmesa->radeon.swtcl.render_primitive = prim; 646 if (prim < GL_TRIANGLES || !unfilled) 647 r200RasterPrimitive( ctx, reduced_hw_prim(ctx, prim) ); 648 } 649 650 static void r200RenderFinish( struct gl_context *ctx ) 651 { 652 } 653 654 static void r200ResetLineStipple( struct gl_context *ctx ) 655 { 656 r200ContextPtr rmesa = R200_CONTEXT(ctx); 657 R200_STATECHANGE( rmesa, lin ); 658 } 659 660 661 /**********************************************************************/ 662 /* Transition to/from hardware rasterization. */ 663 /**********************************************************************/ 664 665 static const char * const fallbackStrings[] = { 666 "Texture mode", 667 "glDrawBuffer(GL_FRONT_AND_BACK)", 668 "glEnable(GL_STENCIL) without hw stencil buffer", 669 "glRenderMode(selection or feedback)", 670 "R200_NO_RAST", 671 "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)" 672 }; 673 674 675 static const char *getFallbackString(GLuint bit) 676 { 677 int i = 0; 678 while (bit > 1) { 679 i++; 680 bit >>= 1; 681 } 682 return fallbackStrings[i]; 683 } 684 685 686 void r200Fallback( struct gl_context *ctx, GLuint bit, GLboolean mode ) 687 { 688 r200ContextPtr rmesa = R200_CONTEXT(ctx); 689 TNLcontext *tnl = TNL_CONTEXT(ctx); 690 GLuint oldfallback = rmesa->radeon.Fallback; 691 692 if (mode) { 693 rmesa->radeon.Fallback |= bit; 694 if (oldfallback == 0) { 695 radeon_firevertices(&rmesa->radeon); 696 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_TRUE ); 697 _swsetup_Wakeup( ctx ); 698 rmesa->radeon.swtcl.RenderIndex = ~0; 699 if (R200_DEBUG & RADEON_FALLBACKS) { 700 fprintf(stderr, "R200 begin rasterization fallback: 0x%x %s\n", 701 bit, getFallbackString(bit)); 702 } 703 } 704 } 705 else { 706 rmesa->radeon.Fallback &= ~bit; 707 if (oldfallback == bit) { 708 709 _swrast_flush( ctx ); 710 tnl->Driver.Render.Start = r200RenderStart; 711 tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive; 712 tnl->Driver.Render.Finish = r200RenderFinish; 713 714 tnl->Driver.Render.BuildVertices = _tnl_build_vertices; 715 tnl->Driver.Render.CopyPV = _tnl_copy_pv; 716 tnl->Driver.Render.Interp = _tnl_interp; 717 718 tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple; 719 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_FALSE ); 720 if (rmesa->radeon.TclFallback) { 721 /* These are already done if rmesa->radeon.TclFallback goes to 722 * zero above. But not if it doesn't (R200_NO_TCL for 723 * example?) 724 */ 725 _tnl_invalidate_vertex_state( ctx, ~0 ); 726 _tnl_invalidate_vertices( ctx, ~0 ); 727 rmesa->radeon.tnl_index_bitset = 0; 728 r200ChooseVertexState( ctx ); 729 r200ChooseRenderState( ctx ); 730 } 731 if (R200_DEBUG & RADEON_FALLBACKS) { 732 fprintf(stderr, "R200 end rasterization fallback: 0x%x %s\n", 733 bit, getFallbackString(bit)); 734 } 735 } 736 } 737 } 738 739 740 741 742 /** 743 * Cope with depth operations by drawing individual pixels as points. 744 * 745 * \todo 746 * The way the vertex state is set in this routine is hokey. It seems to 747 * work, but it's very hackish. This whole routine is pretty hackish. If 748 * the bitmap is small enough, it seems like it would be faster to copy it 749 * to AGP memory and use it as a non-power-of-two texture (i.e., 750 * NV_texture_rectangle). 751 */ 752 void 753 r200PointsBitmap( struct gl_context *ctx, GLint px, GLint py, 754 GLsizei width, GLsizei height, 755 const struct gl_pixelstore_attrib *unpack, 756 const GLubyte *bitmap ) 757 { 758 r200ContextPtr rmesa = R200_CONTEXT(ctx); 759 const GLfloat *rc = ctx->Current.RasterColor; 760 GLint row, col; 761 radeonVertex vert; 762 GLuint orig_vte; 763 GLuint h; 764 765 766 /* Turn off tcl. 767 */ 768 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_BITMAP, 1 ); 769 770 /* Choose tiny vertex format 771 */ 772 { 773 const GLuint fmt_0 = R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0 774 | (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT); 775 const GLuint fmt_1 = 0; 776 GLuint vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]; 777 GLuint vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]; 778 779 vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT); 780 vte |= R200_VTX_W0_FMT; 781 vap &= ~R200_VAP_FORCE_W_TO_ONE; 782 783 rmesa->radeon.swtcl.vertex_size = 5; 784 785 if ( (rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0) 786 || (rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) { 787 R200_NEWPRIM(rmesa); 788 R200_STATECHANGE( rmesa, vtx ); 789 rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0; 790 rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = fmt_1; 791 } 792 793 if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) { 794 R200_STATECHANGE( rmesa, vte ); 795 rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte; 796 } 797 798 if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) { 799 R200_STATECHANGE( rmesa, vap ); 800 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap; 801 } 802 } 803 804 /* Ready for point primitives: 805 */ 806 r200RenderPrimitive( ctx, GL_POINTS ); 807 808 /* Turn off the hw viewport transformation: 809 */ 810 R200_STATECHANGE( rmesa, vte ); 811 orig_vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]; 812 rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VPORT_X_SCALE_ENA | 813 R200_VPORT_Y_SCALE_ENA | 814 R200_VPORT_Z_SCALE_ENA | 815 R200_VPORT_X_OFFSET_ENA | 816 R200_VPORT_Y_OFFSET_ENA | 817 R200_VPORT_Z_OFFSET_ENA); 818 819 /* Turn off other stuff: Stipple?, texture?, blending?, etc. 820 */ 821 822 823 /* Populate the vertex 824 * 825 * Incorporate FOG into RGBA 826 */ 827 if (ctx->Fog.Enabled) { 828 const GLfloat *fc = ctx->Fog.Color; 829 GLfloat color[4]; 830 GLfloat f; 831 832 if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) 833 f = _swrast_z_to_fogfactor(ctx, ctx->Current.Attrib[VERT_ATTRIB_FOG][0]); 834 else 835 f = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance); 836 837 color[0] = f * rc[0] + (1.F - f) * fc[0]; 838 color[1] = f * rc[1] + (1.F - f) * fc[1]; 839 color[2] = f * rc[2] + (1.F - f) * fc[2]; 840 color[3] = rc[3]; 841 842 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.red, color[0]); 843 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.green, color[1]); 844 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.blue, color[2]); 845 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.alpha, color[3]); 846 } 847 else { 848 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.red, rc[0]); 849 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.green, rc[1]); 850 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.blue, rc[2]); 851 UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.alpha, rc[3]); 852 } 853 854 855 vert.tv.z = ctx->Current.RasterPos[2]; 856 857 858 /* Update window height 859 */ 860 h = radeon_get_drawable(&rmesa->radeon)->h; 861 862 /* Clipping handled by existing mechansims in r200_ioctl.c? 863 */ 864 for (row=0; row<height; row++) { 865 const GLubyte *src = (const GLubyte *) 866 _mesa_image_address2d(unpack, bitmap, width, height, 867 GL_COLOR_INDEX, GL_BITMAP, row, 0 ); 868 869 if (unpack->LsbFirst) { 870 /* Lsb first */ 871 GLubyte mask = 1U << (unpack->SkipPixels & 0x7); 872 for (col=0; col<width; col++) { 873 if (*src & mask) { 874 vert.tv.x = px+col; 875 vert.tv.y = h - (py+row) - 1; 876 r200_point( rmesa, &vert ); 877 } 878 src += (mask >> 7); 879 mask = ((mask << 1) & 0xff) | (mask >> 7); 880 } 881 882 /* get ready for next row */ 883 if (mask != 1) 884 src++; 885 } 886 else { 887 /* Msb first */ 888 GLubyte mask = 128U >> (unpack->SkipPixels & 0x7); 889 for (col=0; col<width; col++) { 890 if (*src & mask) { 891 vert.tv.x = px+col; 892 vert.tv.y = h - (py+row) - 1; 893 r200_point( rmesa, &vert ); 894 } 895 src += mask & 1; 896 mask = ((mask << 7) & 0xff) | (mask >> 1); 897 } 898 /* get ready for next row */ 899 if (mask != 128) 900 src++; 901 } 902 } 903 904 /* Fire outstanding vertices, restore state 905 */ 906 R200_STATECHANGE( rmesa, vte ); 907 rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = orig_vte; 908 909 /* Unfallback 910 */ 911 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_BITMAP, 0 ); 912 913 /* Need to restore vertexformat? 914 */ 915 if (rmesa->radeon.TclFallback) 916 r200ChooseVertexState( ctx ); 917 } 918 919 920 921 /**********************************************************************/ 922 /* Initialization. */ 923 /**********************************************************************/ 924 925 void r200InitSwtcl( struct gl_context *ctx ) 926 { 927 TNLcontext *tnl = TNL_CONTEXT(ctx); 928 r200ContextPtr rmesa = R200_CONTEXT(ctx); 929 static int firsttime = 1; 930 931 if (firsttime) { 932 init_rast_tab(); 933 firsttime = 0; 934 } 935 rmesa->radeon.swtcl.emit_prediction = 0; 936 937 tnl->Driver.Render.Start = r200RenderStart; 938 tnl->Driver.Render.Finish = r200RenderFinish; 939 tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive; 940 tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple; 941 tnl->Driver.Render.BuildVertices = _tnl_build_vertices; 942 tnl->Driver.Render.CopyPV = _tnl_copy_pv; 943 tnl->Driver.Render.Interp = _tnl_interp; 944 945 /* FIXME: what are these numbers? */ 946 _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, 947 36 * sizeof(GLfloat) ); 948 949 rmesa->radeon.swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf; 950 rmesa->radeon.swtcl.RenderIndex = ~0; 951 rmesa->radeon.swtcl.render_primitive = GL_TRIANGLES; 952 rmesa->radeon.swtcl.hw_primitive = 0; 953 } 954 955