r200_state.c revision 6c48c93a5358ab04d6779afb14203bd1680a37a0
1/************************************************************************** 2 3Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. 4 5The Weather Channel (TM) funded Tungsten Graphics to develop the 6initial release of the Radeon 8500 driver under the XFree86 license. 7This notice must be preserved. 8 9Permission is hereby granted, free of charge, to any person obtaining 10a copy of this software and associated documentation files (the 11"Software"), to deal in the Software without restriction, including 12without limitation the rights to use, copy, modify, merge, publish, 13distribute, sublicense, and/or sell copies of the Software, and to 14permit persons to whom the Software is furnished to do so, subject to 15the following conditions: 16 17The above copyright notice and this permission notice (including the 18next paragraph) shall be included in all copies or substantial 19portions of the Software. 20 21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 22EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 25LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 26OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 27WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 29**************************************************************************/ 30 31/* 32 * Authors: 33 * Keith Whitwell <keith@tungstengraphics.com> 34 */ 35 36#include "main/glheader.h" 37#include "main/imports.h" 38#include "main/api_arrayelt.h" 39#include "main/enums.h" 40#include "main/colormac.h" 41#include "main/light.h" 42#include "main/framebuffer.h" 43 44#include "swrast/swrast.h" 45#include "vbo/vbo.h" 46#include "tnl/tnl.h" 47#include "tnl/t_pipeline.h" 48#include "swrast_setup/swrast_setup.h" 49 50#include "radeon_common.h" 51#include "radeon_mipmap_tree.h" 52#include "r200_context.h" 53#include "r200_ioctl.h" 54#include "r200_state.h" 55#include "r200_tcl.h" 56#include "r200_tex.h" 57#include "r200_swtcl.h" 58#include "r200_vertprog.h" 59 60#include "drirenderbuffer.h" 61 62 63/* ============================================================= 64 * Alpha blending 65 */ 66 67static void r200AlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref ) 68{ 69 r200ContextPtr rmesa = R200_CONTEXT(ctx); 70 int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC]; 71 GLubyte refByte; 72 73 CLAMPED_FLOAT_TO_UBYTE(refByte, ref); 74 75 R200_STATECHANGE( rmesa, ctx ); 76 77 pp_misc &= ~(R200_ALPHA_TEST_OP_MASK | R200_REF_ALPHA_MASK); 78 pp_misc |= (refByte & R200_REF_ALPHA_MASK); 79 80 switch ( func ) { 81 case GL_NEVER: 82 pp_misc |= R200_ALPHA_TEST_FAIL; 83 break; 84 case GL_LESS: 85 pp_misc |= R200_ALPHA_TEST_LESS; 86 break; 87 case GL_EQUAL: 88 pp_misc |= R200_ALPHA_TEST_EQUAL; 89 break; 90 case GL_LEQUAL: 91 pp_misc |= R200_ALPHA_TEST_LEQUAL; 92 break; 93 case GL_GREATER: 94 pp_misc |= R200_ALPHA_TEST_GREATER; 95 break; 96 case GL_NOTEQUAL: 97 pp_misc |= R200_ALPHA_TEST_NEQUAL; 98 break; 99 case GL_GEQUAL: 100 pp_misc |= R200_ALPHA_TEST_GEQUAL; 101 break; 102 case GL_ALWAYS: 103 pp_misc |= R200_ALPHA_TEST_PASS; 104 break; 105 } 106 107 rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc; 108} 109 110static void r200BlendColor( GLcontext *ctx, const GLfloat cf[4] ) 111{ 112 GLubyte color[4]; 113 r200ContextPtr rmesa = R200_CONTEXT(ctx); 114 R200_STATECHANGE( rmesa, ctx ); 115 CLAMPED_FLOAT_TO_UBYTE(color[0], cf[0]); 116 CLAMPED_FLOAT_TO_UBYTE(color[1], cf[1]); 117 CLAMPED_FLOAT_TO_UBYTE(color[2], cf[2]); 118 CLAMPED_FLOAT_TO_UBYTE(color[3], cf[3]); 119 if (rmesa->radeon.radeonScreen->drmSupportsBlendColor) 120 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCOLOR] = radeonPackColor( 4, color[0], color[1], color[2], color[3] ); 121} 122 123/** 124 * Calculate the hardware blend factor setting. This same function is used 125 * for source and destination of both alpha and RGB. 126 * 127 * \returns 128 * The hardware register value for the specified blend factor. This value 129 * will need to be shifted into the correct position for either source or 130 * destination factor. 131 * 132 * \todo 133 * Since the two cases where source and destination are handled differently 134 * are essentially error cases, they should never happen. Determine if these 135 * cases can be removed. 136 */ 137static int blend_factor( GLenum factor, GLboolean is_src ) 138{ 139 int func; 140 141 switch ( factor ) { 142 case GL_ZERO: 143 func = R200_BLEND_GL_ZERO; 144 break; 145 case GL_ONE: 146 func = R200_BLEND_GL_ONE; 147 break; 148 case GL_DST_COLOR: 149 func = R200_BLEND_GL_DST_COLOR; 150 break; 151 case GL_ONE_MINUS_DST_COLOR: 152 func = R200_BLEND_GL_ONE_MINUS_DST_COLOR; 153 break; 154 case GL_SRC_COLOR: 155 func = R200_BLEND_GL_SRC_COLOR; 156 break; 157 case GL_ONE_MINUS_SRC_COLOR: 158 func = R200_BLEND_GL_ONE_MINUS_SRC_COLOR; 159 break; 160 case GL_SRC_ALPHA: 161 func = R200_BLEND_GL_SRC_ALPHA; 162 break; 163 case GL_ONE_MINUS_SRC_ALPHA: 164 func = R200_BLEND_GL_ONE_MINUS_SRC_ALPHA; 165 break; 166 case GL_DST_ALPHA: 167 func = R200_BLEND_GL_DST_ALPHA; 168 break; 169 case GL_ONE_MINUS_DST_ALPHA: 170 func = R200_BLEND_GL_ONE_MINUS_DST_ALPHA; 171 break; 172 case GL_SRC_ALPHA_SATURATE: 173 func = (is_src) ? R200_BLEND_GL_SRC_ALPHA_SATURATE : R200_BLEND_GL_ZERO; 174 break; 175 case GL_CONSTANT_COLOR: 176 func = R200_BLEND_GL_CONST_COLOR; 177 break; 178 case GL_ONE_MINUS_CONSTANT_COLOR: 179 func = R200_BLEND_GL_ONE_MINUS_CONST_COLOR; 180 break; 181 case GL_CONSTANT_ALPHA: 182 func = R200_BLEND_GL_CONST_ALPHA; 183 break; 184 case GL_ONE_MINUS_CONSTANT_ALPHA: 185 func = R200_BLEND_GL_ONE_MINUS_CONST_ALPHA; 186 break; 187 default: 188 func = (is_src) ? R200_BLEND_GL_ONE : R200_BLEND_GL_ZERO; 189 } 190 return func; 191} 192 193/** 194 * Sets both the blend equation and the blend function. 195 * This is done in a single 196 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX) 197 * change the interpretation of the blend function. 198 * Also, make sure that blend function and blend equation are set to their default 199 * value if color blending is not enabled, since at least blend equations GL_MIN 200 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for 201 * unknown reasons. 202 */ 203static void r200_set_blend_state( GLcontext * ctx ) 204{ 205 r200ContextPtr rmesa = R200_CONTEXT(ctx); 206 GLuint cntl = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & 207 ~(R200_ROP_ENABLE | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE); 208 209 int func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | 210 (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT); 211 int eqn = R200_COMB_FCN_ADD_CLAMP; 212 int funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | 213 (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT); 214 int eqnA = R200_COMB_FCN_ADD_CLAMP; 215 216 R200_STATECHANGE( rmesa, ctx ); 217 218 if (rmesa->radeon.radeonScreen->drmSupportsBlendColor) { 219 if (ctx->Color.ColorLogicOpEnabled) { 220 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE; 221 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func; 222 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func; 223 return; 224 } else if (ctx->Color.BlendEnabled) { 225 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE; 226 } 227 else { 228 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl; 229 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func; 230 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func; 231 return; 232 } 233 } 234 else { 235 if (ctx->Color.ColorLogicOpEnabled) { 236 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE; 237 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func; 238 return; 239 } else if (ctx->Color.BlendEnabled) { 240 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ALPHA_BLEND_ENABLE; 241 } 242 else { 243 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl; 244 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func; 245 return; 246 } 247 } 248 249 func = (blend_factor( ctx->Color.BlendSrcRGB, GL_TRUE ) << R200_SRC_BLEND_SHIFT) | 250 (blend_factor( ctx->Color.BlendDstRGB, GL_FALSE ) << R200_DST_BLEND_SHIFT); 251 252 switch(ctx->Color.BlendEquationRGB) { 253 case GL_FUNC_ADD: 254 eqn = R200_COMB_FCN_ADD_CLAMP; 255 break; 256 257 case GL_FUNC_SUBTRACT: 258 eqn = R200_COMB_FCN_SUB_CLAMP; 259 break; 260 261 case GL_FUNC_REVERSE_SUBTRACT: 262 eqn = R200_COMB_FCN_RSUB_CLAMP; 263 break; 264 265 case GL_MIN: 266 eqn = R200_COMB_FCN_MIN; 267 func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | 268 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); 269 break; 270 271 case GL_MAX: 272 eqn = R200_COMB_FCN_MAX; 273 func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | 274 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); 275 break; 276 277 default: 278 fprintf( stderr, "[%s:%u] Invalid RGB blend equation (0x%04x).\n", 279 __FUNCTION__, __LINE__, ctx->Color.BlendEquationRGB ); 280 return; 281 } 282 283 if (!rmesa->radeon.radeonScreen->drmSupportsBlendColor) { 284 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = eqn | func; 285 return; 286 } 287 288 funcA = (blend_factor( ctx->Color.BlendSrcA, GL_TRUE ) << R200_SRC_BLEND_SHIFT) | 289 (blend_factor( ctx->Color.BlendDstA, GL_FALSE ) << R200_DST_BLEND_SHIFT); 290 291 switch(ctx->Color.BlendEquationA) { 292 case GL_FUNC_ADD: 293 eqnA = R200_COMB_FCN_ADD_CLAMP; 294 break; 295 296 case GL_FUNC_SUBTRACT: 297 eqnA = R200_COMB_FCN_SUB_CLAMP; 298 break; 299 300 case GL_FUNC_REVERSE_SUBTRACT: 301 eqnA = R200_COMB_FCN_RSUB_CLAMP; 302 break; 303 304 case GL_MIN: 305 eqnA = R200_COMB_FCN_MIN; 306 funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | 307 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); 308 break; 309 310 case GL_MAX: 311 eqnA = R200_COMB_FCN_MAX; 312 funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | 313 (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); 314 break; 315 316 default: 317 fprintf( stderr, "[%s:%u] Invalid A blend equation (0x%04x).\n", 318 __FUNCTION__, __LINE__, ctx->Color.BlendEquationA ); 319 return; 320 } 321 322 rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqnA | funcA; 323 rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func; 324 325} 326 327static void r200BlendEquationSeparate( GLcontext *ctx, 328 GLenum modeRGB, GLenum modeA ) 329{ 330 r200_set_blend_state( ctx ); 331} 332 333static void r200BlendFuncSeparate( GLcontext *ctx, 334 GLenum sfactorRGB, GLenum dfactorRGB, 335 GLenum sfactorA, GLenum dfactorA ) 336{ 337 r200_set_blend_state( ctx ); 338} 339 340 341/* ============================================================= 342 * Depth testing 343 */ 344 345static void r200DepthFunc( GLcontext *ctx, GLenum func ) 346{ 347 r200ContextPtr rmesa = R200_CONTEXT(ctx); 348 349 R200_STATECHANGE( rmesa, ctx ); 350 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_TEST_MASK; 351 352 switch ( ctx->Depth.Func ) { 353 case GL_NEVER: 354 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEVER; 355 break; 356 case GL_LESS: 357 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LESS; 358 break; 359 case GL_EQUAL: 360 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_EQUAL; 361 break; 362 case GL_LEQUAL: 363 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LEQUAL; 364 break; 365 case GL_GREATER: 366 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GREATER; 367 break; 368 case GL_NOTEQUAL: 369 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEQUAL; 370 break; 371 case GL_GEQUAL: 372 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GEQUAL; 373 break; 374 case GL_ALWAYS: 375 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_ALWAYS; 376 break; 377 } 378} 379 380static void r200ClearDepth( GLcontext *ctx, GLclampd d ) 381{ 382 r200ContextPtr rmesa = R200_CONTEXT(ctx); 383 GLuint format = (rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] & 384 R200_DEPTH_FORMAT_MASK); 385 386 switch ( format ) { 387 case R200_DEPTH_FORMAT_16BIT_INT_Z: 388 rmesa->radeon.state.depth.clear = d * 0x0000ffff; 389 break; 390 case R200_DEPTH_FORMAT_24BIT_INT_Z: 391 rmesa->radeon.state.depth.clear = d * 0x00ffffff; 392 break; 393 } 394} 395 396static void r200DepthMask( GLcontext *ctx, GLboolean flag ) 397{ 398 r200ContextPtr rmesa = R200_CONTEXT(ctx); 399 R200_STATECHANGE( rmesa, ctx ); 400 401 if ( ctx->Depth.Mask ) { 402 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_WRITE_ENABLE; 403 } else { 404 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_WRITE_ENABLE; 405 } 406} 407 408 409/* ============================================================= 410 * Fog 411 */ 412 413 414static void r200Fogfv( GLcontext *ctx, GLenum pname, const GLfloat *param ) 415{ 416 r200ContextPtr rmesa = R200_CONTEXT(ctx); 417 union { int i; float f; } c, d; 418 GLchan col[4]; 419 GLuint i; 420 421 c.i = rmesa->hw.fog.cmd[FOG_C]; 422 d.i = rmesa->hw.fog.cmd[FOG_D]; 423 424 switch (pname) { 425 case GL_FOG_MODE: 426 if (!ctx->Fog.Enabled) 427 return; 428 R200_STATECHANGE(rmesa, tcl); 429 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK; 430 switch (ctx->Fog.Mode) { 431 case GL_LINEAR: 432 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_LINEAR; 433 if (ctx->Fog.Start == ctx->Fog.End) { 434 c.f = 1.0F; 435 d.f = 1.0F; 436 } 437 else { 438 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start); 439 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start); 440 } 441 break; 442 case GL_EXP: 443 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP; 444 c.f = 0.0; 445 d.f = -ctx->Fog.Density; 446 break; 447 case GL_EXP2: 448 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP2; 449 c.f = 0.0; 450 d.f = -(ctx->Fog.Density * ctx->Fog.Density); 451 break; 452 default: 453 return; 454 } 455 break; 456 case GL_FOG_DENSITY: 457 switch (ctx->Fog.Mode) { 458 case GL_EXP: 459 c.f = 0.0; 460 d.f = -ctx->Fog.Density; 461 break; 462 case GL_EXP2: 463 c.f = 0.0; 464 d.f = -(ctx->Fog.Density * ctx->Fog.Density); 465 break; 466 default: 467 break; 468 } 469 break; 470 case GL_FOG_START: 471 case GL_FOG_END: 472 if (ctx->Fog.Mode == GL_LINEAR) { 473 if (ctx->Fog.Start == ctx->Fog.End) { 474 c.f = 1.0F; 475 d.f = 1.0F; 476 } else { 477 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start); 478 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start); 479 } 480 } 481 break; 482 case GL_FOG_COLOR: 483 R200_STATECHANGE( rmesa, ctx ); 484 UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color ); 485 i = radeonPackColor( 4, col[0], col[1], col[2], 0 ); 486 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_COLOR_MASK; 487 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= i; 488 break; 489 case GL_FOG_COORD_SRC: { 490 GLuint out_0 = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0]; 491 GLuint fog = rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR]; 492 493 fog &= ~R200_FOG_USE_MASK; 494 if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD || ctx->VertexProgram.Enabled) { 495 fog |= R200_FOG_USE_VTX_FOG; 496 out_0 |= R200_VTX_DISCRETE_FOG; 497 } 498 else { 499 fog |= R200_FOG_USE_SPEC_ALPHA; 500 out_0 &= ~R200_VTX_DISCRETE_FOG; 501 } 502 503 if ( fog != rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] ) { 504 R200_STATECHANGE( rmesa, ctx ); 505 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = fog; 506 } 507 508 if (out_0 != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0]) { 509 R200_STATECHANGE( rmesa, vtx ); 510 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] = out_0; 511 } 512 513 break; 514 } 515 default: 516 return; 517 } 518 519 if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) { 520 R200_STATECHANGE( rmesa, fog ); 521 rmesa->hw.fog.cmd[FOG_C] = c.i; 522 rmesa->hw.fog.cmd[FOG_D] = d.i; 523 } 524} 525 526/* ============================================================= 527 * Culling 528 */ 529 530static void r200CullFace( GLcontext *ctx, GLenum unused ) 531{ 532 r200ContextPtr rmesa = R200_CONTEXT(ctx); 533 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL]; 534 GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL]; 535 536 s |= R200_FFACE_SOLID | R200_BFACE_SOLID; 537 t &= ~(R200_CULL_FRONT | R200_CULL_BACK); 538 539 if ( ctx->Polygon.CullFlag ) { 540 switch ( ctx->Polygon.CullFaceMode ) { 541 case GL_FRONT: 542 s &= ~R200_FFACE_SOLID; 543 t |= R200_CULL_FRONT; 544 break; 545 case GL_BACK: 546 s &= ~R200_BFACE_SOLID; 547 t |= R200_CULL_BACK; 548 break; 549 case GL_FRONT_AND_BACK: 550 s &= ~(R200_FFACE_SOLID | R200_BFACE_SOLID); 551 t |= (R200_CULL_FRONT | R200_CULL_BACK); 552 break; 553 } 554 } 555 556 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) { 557 R200_STATECHANGE(rmesa, set ); 558 rmesa->hw.set.cmd[SET_SE_CNTL] = s; 559 } 560 561 if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) { 562 R200_STATECHANGE(rmesa, tcl ); 563 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t; 564 } 565} 566 567static void r200FrontFace( GLcontext *ctx, GLenum mode ) 568{ 569 r200ContextPtr rmesa = R200_CONTEXT(ctx); 570 571 R200_STATECHANGE( rmesa, set ); 572 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_FFACE_CULL_DIR_MASK; 573 574 R200_STATECHANGE( rmesa, tcl ); 575 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_CULL_FRONT_IS_CCW; 576 577 switch ( mode ) { 578 case GL_CW: 579 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CW; 580 break; 581 case GL_CCW: 582 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CCW; 583 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_CULL_FRONT_IS_CCW; 584 break; 585 } 586} 587 588/* ============================================================= 589 * Point state 590 */ 591static void r200PointSize( GLcontext *ctx, GLfloat size ) 592{ 593 r200ContextPtr rmesa = R200_CONTEXT(ctx); 594 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd; 595 596 R200_STATECHANGE( rmesa, cst ); 597 R200_STATECHANGE( rmesa, ptp ); 598 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= ~0xffff; 599 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= ((GLuint)(ctx->Point.Size * 16.0)); 600/* this is the size param of the point size calculation (point size reg value 601 is not used when calculation is active). */ 602 fcmd[PTP_VPORT_SCALE_PTSIZE] = ctx->Point.Size; 603} 604 605static void r200PointParameter( GLcontext *ctx, GLenum pname, const GLfloat *params) 606{ 607 r200ContextPtr rmesa = R200_CONTEXT(ctx); 608 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd; 609 610 switch (pname) { 611 case GL_POINT_SIZE_MIN: 612 /* Can clamp both in tcl and setup - just set both (as does fglrx) */ 613 R200_STATECHANGE( rmesa, lin ); 614 R200_STATECHANGE( rmesa, ptp ); 615 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= 0xffff; 616 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)(ctx->Point.MinSize * 16.0) << 16; 617 fcmd[PTP_CLAMP_MIN] = ctx->Point.MinSize; 618 break; 619 case GL_POINT_SIZE_MAX: 620 R200_STATECHANGE( rmesa, cst ); 621 R200_STATECHANGE( rmesa, ptp ); 622 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= 0xffff; 623 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= (GLuint)(ctx->Point.MaxSize * 16.0) << 16; 624 fcmd[PTP_CLAMP_MAX] = ctx->Point.MaxSize; 625 break; 626 case GL_POINT_DISTANCE_ATTENUATION: 627 R200_STATECHANGE( rmesa, vtx ); 628 R200_STATECHANGE( rmesa, spr ); 629 R200_STATECHANGE( rmesa, ptp ); 630 GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd; 631 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= 632 ~(R200_PS_MULT_MASK | R200_PS_LIN_ATT_ZERO | R200_PS_SE_SEL_STATE); 633 /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in 634 r200ValidateState looks like overkill */ 635 if (ctx->Point.Params[0] != 1.0 || 636 ctx->Point.Params[1] != 0.0 || 637 ctx->Point.Params[2] != 0.0 || 638 (ctx->VertexProgram.Enabled && ctx->VertexProgram.PointSizeEnabled)) { 639 /* all we care for vp would be the ps_se_sel_state setting */ 640 fcmd[PTP_ATT_CONST_QUAD] = ctx->Point.Params[2]; 641 fcmd[PTP_ATT_CONST_LIN] = ctx->Point.Params[1]; 642 fcmd[PTP_ATT_CONST_CON] = ctx->Point.Params[0]; 643 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_MULT_ATTENCONST; 644 if (ctx->Point.Params[1] == 0.0) 645 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_LIN_ATT_ZERO; 646/* FIXME: setting this here doesn't look quite ok - we only want to do 647 that if we're actually drawing points probably */ 648 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_PT_SIZE; 649 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= R200_VTX_POINT_SIZE; 650 } 651 else { 652 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= 653 R200_PS_SE_SEL_STATE | R200_PS_MULT_CONST; 654 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_PT_SIZE; 655 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~R200_VTX_POINT_SIZE; 656 } 657 break; 658 case GL_POINT_FADE_THRESHOLD_SIZE: 659 /* don't support multisampling, so doesn't matter. */ 660 break; 661 /* can't do these but don't need them. 662 case GL_POINT_SPRITE_R_MODE_NV: 663 case GL_POINT_SPRITE_COORD_ORIGIN: */ 664 default: 665 fprintf(stderr, "bad pname parameter in r200PointParameter\n"); 666 return; 667 } 668} 669 670/* ============================================================= 671 * Line state 672 */ 673static void r200LineWidth( GLcontext *ctx, GLfloat widthf ) 674{ 675 r200ContextPtr rmesa = R200_CONTEXT(ctx); 676 677 R200_STATECHANGE( rmesa, lin ); 678 R200_STATECHANGE( rmesa, set ); 679 680 /* Line width is stored in U6.4 format. 681 * Same min/max limits for AA, non-AA lines. 682 */ 683 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= ~0xffff; 684 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint) 685 (CLAMP(widthf, ctx->Const.MinLineWidth, ctx->Const.MaxLineWidth) * 16.0); 686 687 if ( widthf > 1.0 ) { 688 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_WIDELINE_ENABLE; 689 } else { 690 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_WIDELINE_ENABLE; 691 } 692} 693 694static void r200LineStipple( GLcontext *ctx, GLint factor, GLushort pattern ) 695{ 696 r200ContextPtr rmesa = R200_CONTEXT(ctx); 697 698 R200_STATECHANGE( rmesa, lin ); 699 rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] = 700 ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern)); 701} 702 703 704/* ============================================================= 705 * Masks 706 */ 707static void r200ColorMask( GLcontext *ctx, 708 GLboolean r, GLboolean g, 709 GLboolean b, GLboolean a ) 710{ 711 r200ContextPtr rmesa = R200_CONTEXT(ctx); 712 GLuint mask = radeonPackColor( rmesa->radeon.radeonScreen->cpp, 713 ctx->Color.ColorMask[RCOMP], 714 ctx->Color.ColorMask[GCOMP], 715 ctx->Color.ColorMask[BCOMP], 716 ctx->Color.ColorMask[ACOMP] ); 717 718 GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE; 719 720 if (!(r && g && b && a)) 721 flag |= R200_PLANE_MASK_ENABLE; 722 723 if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) { 724 R200_STATECHANGE( rmesa, ctx ); 725 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag; 726 } 727 728 if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) { 729 R200_STATECHANGE( rmesa, msk ); 730 rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask; 731 } 732} 733 734 735/* ============================================================= 736 * Polygon state 737 */ 738 739static void r200PolygonOffset( GLcontext *ctx, 740 GLfloat factor, GLfloat units ) 741{ 742 r200ContextPtr rmesa = R200_CONTEXT(ctx); 743 float_ui32_type constant = { units * rmesa->radeon.state.depth.scale }; 744 float_ui32_type factoru = { factor }; 745 746/* factor *= 2; */ 747/* constant *= 2; */ 748 749/* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */ 750 751 R200_STATECHANGE( rmesa, zbs ); 752 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = factoru.ui32; 753 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32; 754} 755 756static void r200PolygonStipple( GLcontext *ctx, const GLubyte *mask ) 757{ 758 r200ContextPtr rmesa = R200_CONTEXT(ctx); 759 GLuint i; 760 drm_radeon_stipple_t stipple; 761 762 /* Must flip pattern upside down. 763 */ 764 for ( i = 0 ; i < 32 ; i++ ) { 765 rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i]; 766 } 767 768 /* TODO: push this into cmd mechanism 769 */ 770 radeon_firevertices(&rmesa->radeon); 771 LOCK_HARDWARE( &rmesa->radeon ); 772 773 /* FIXME: Use window x,y offsets into stipple RAM. 774 */ 775 stipple.mask = rmesa->state.stipple.mask; 776 drmCommandWrite( rmesa->radeon.dri.fd, DRM_RADEON_STIPPLE, 777 &stipple, sizeof(stipple) ); 778 UNLOCK_HARDWARE( &rmesa->radeon ); 779} 780 781static void r200PolygonMode( GLcontext *ctx, GLenum face, GLenum mode ) 782{ 783 r200ContextPtr rmesa = R200_CONTEXT(ctx); 784 GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0; 785 786 /* Can't generally do unfilled via tcl, but some good special 787 * cases work. 788 */ 789 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_UNFILLED, flag); 790 if (rmesa->radeon.TclFallback) { 791 r200ChooseRenderState( ctx ); 792 r200ChooseVertexState( ctx ); 793 } 794} 795 796 797/* ============================================================= 798 * Rendering attributes 799 * 800 * We really don't want to recalculate all this every time we bind a 801 * texture. These things shouldn't change all that often, so it makes 802 * sense to break them out of the core texture state update routines. 803 */ 804 805/* Examine lighting and texture state to determine if separate specular 806 * should be enabled. 807 */ 808static void r200UpdateSpecular( GLcontext *ctx ) 809{ 810 r200ContextPtr rmesa = R200_CONTEXT(ctx); 811 uint32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL]; 812 813 R200_STATECHANGE( rmesa, tcl ); 814 R200_STATECHANGE( rmesa, vtx ); 815 816 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_0_SHIFT); 817 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_1_SHIFT); 818 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_0; 819 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_1; 820 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHTING_ENABLE; 821 822 p &= ~R200_SPECULAR_ENABLE; 823 824 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_DIFFUSE_SPECULAR_COMBINE; 825 826 827 if (ctx->Light.Enabled && 828 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) { 829 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= 830 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) | 831 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT)); 832 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0; 833 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1; 834 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE; 835 p |= R200_SPECULAR_ENABLE; 836 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= 837 ~R200_DIFFUSE_SPECULAR_COMBINE; 838 } 839 else if (ctx->Light.Enabled) { 840 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= 841 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT)); 842 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0; 843 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE; 844 } else if (ctx->Fog.ColorSumEnabled ) { 845 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= 846 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) | 847 (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT)); 848 p |= R200_SPECULAR_ENABLE; 849 } else { 850 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= 851 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT)); 852 } 853 854 if (ctx->Fog.Enabled) { 855 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= 856 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT)); 857 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1; 858 } 859 860 if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) { 861 R200_STATECHANGE( rmesa, ctx ); 862 rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p; 863 } 864 865 /* Update vertex/render formats 866 */ 867 if (rmesa->radeon.TclFallback) { 868 r200ChooseRenderState( ctx ); 869 r200ChooseVertexState( ctx ); 870 } 871} 872 873 874/* ============================================================= 875 * Materials 876 */ 877 878 879/* Update on colormaterial, material emmissive/ambient, 880 * lightmodel.globalambient 881 */ 882static void update_global_ambient( GLcontext *ctx ) 883{ 884 r200ContextPtr rmesa = R200_CONTEXT(ctx); 885 float *fcmd = (float *)R200_DB_STATE( glt ); 886 887 /* Need to do more if both emmissive & ambient are PREMULT: 888 * I believe this is not nessary when using source_material. This condition thus 889 * will never happen currently, and the function has no dependencies on materials now 890 */ 891 if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] & 892 ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) | 893 (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT))) == 0) 894 { 895 COPY_3V( &fcmd[GLT_RED], 896 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]); 897 ACC_SCALE_3V( &fcmd[GLT_RED], 898 ctx->Light.Model.Ambient, 899 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]); 900 } 901 else 902 { 903 COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient ); 904 } 905 906 R200_DB_STATECHANGE(rmesa, &rmesa->hw.glt); 907} 908 909/* Update on change to 910 * - light[p].colors 911 * - light[p].enabled 912 */ 913static void update_light_colors( GLcontext *ctx, GLuint p ) 914{ 915 struct gl_light *l = &ctx->Light.Light[p]; 916 917/* fprintf(stderr, "%s\n", __FUNCTION__); */ 918 919 if (l->Enabled) { 920 r200ContextPtr rmesa = R200_CONTEXT(ctx); 921 float *fcmd = (float *)R200_DB_STATE( lit[p] ); 922 923 COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient ); 924 COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse ); 925 COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular ); 926 927 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] ); 928 } 929} 930 931static void r200ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode ) 932{ 933 r200ContextPtr rmesa = R200_CONTEXT(ctx); 934 GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]; 935 light_model_ctl1 &= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT) | 936 (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT) | 937 (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT) | 938 (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT) | 939 (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT) | 940 (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT) | 941 (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT) | 942 (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT)); 943 944 if (ctx->Light.ColorMaterialEnabled) { 945 GLuint mask = ctx->Light.ColorMaterialBitmask; 946 947 if (mask & MAT_BIT_FRONT_EMISSION) { 948 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << 949 R200_FRONT_EMISSIVE_SOURCE_SHIFT); 950 } 951 else 952 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 << 953 R200_FRONT_EMISSIVE_SOURCE_SHIFT); 954 955 if (mask & MAT_BIT_FRONT_AMBIENT) { 956 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << 957 R200_FRONT_AMBIENT_SOURCE_SHIFT); 958 } 959 else 960 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 << 961 R200_FRONT_AMBIENT_SOURCE_SHIFT); 962 963 if (mask & MAT_BIT_FRONT_DIFFUSE) { 964 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << 965 R200_FRONT_DIFFUSE_SOURCE_SHIFT); 966 } 967 else 968 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 << 969 R200_FRONT_DIFFUSE_SOURCE_SHIFT); 970 971 if (mask & MAT_BIT_FRONT_SPECULAR) { 972 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << 973 R200_FRONT_SPECULAR_SOURCE_SHIFT); 974 } 975 else { 976 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 << 977 R200_FRONT_SPECULAR_SOURCE_SHIFT); 978 } 979 980 if (mask & MAT_BIT_BACK_EMISSION) { 981 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << 982 R200_BACK_EMISSIVE_SOURCE_SHIFT); 983 } 984 985 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 << 986 R200_BACK_EMISSIVE_SOURCE_SHIFT); 987 988 if (mask & MAT_BIT_BACK_AMBIENT) { 989 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << 990 R200_BACK_AMBIENT_SOURCE_SHIFT); 991 } 992 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 << 993 R200_BACK_AMBIENT_SOURCE_SHIFT); 994 995 if (mask & MAT_BIT_BACK_DIFFUSE) { 996 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << 997 R200_BACK_DIFFUSE_SOURCE_SHIFT); 998 } 999 else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 << 1000 R200_BACK_DIFFUSE_SOURCE_SHIFT); 1001 1002 if (mask & MAT_BIT_BACK_SPECULAR) { 1003 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << 1004 R200_BACK_SPECULAR_SOURCE_SHIFT); 1005 } 1006 else { 1007 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 << 1008 R200_BACK_SPECULAR_SOURCE_SHIFT); 1009 } 1010 } 1011 else { 1012 /* Default to SOURCE_MATERIAL: 1013 */ 1014 light_model_ctl1 |= 1015 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) | 1016 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_AMBIENT_SOURCE_SHIFT) | 1017 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_DIFFUSE_SOURCE_SHIFT) | 1018 (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_SPECULAR_SOURCE_SHIFT) | 1019 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_EMISSIVE_SOURCE_SHIFT) | 1020 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_AMBIENT_SOURCE_SHIFT) | 1021 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_DIFFUSE_SOURCE_SHIFT) | 1022 (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_SPECULAR_SOURCE_SHIFT); 1023 } 1024 1025 if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]) { 1026 R200_STATECHANGE( rmesa, tcl ); 1027 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = light_model_ctl1; 1028 } 1029 1030 1031} 1032 1033void r200UpdateMaterial( GLcontext *ctx ) 1034{ 1035 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1036 GLfloat (*mat)[4] = ctx->Light.Material.Attrib; 1037 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( mtl[0] ); 1038 GLfloat *fcmd2 = (GLfloat *)R200_DB_STATE( mtl[1] ); 1039 GLuint mask = ~0; 1040 1041 /* Might be possible and faster to update everything unconditionally? */ 1042 if (ctx->Light.ColorMaterialEnabled) 1043 mask &= ~ctx->Light.ColorMaterialBitmask; 1044 1045 if (R200_DEBUG & DEBUG_STATE) 1046 fprintf(stderr, "%s\n", __FUNCTION__); 1047 1048 if (mask & MAT_BIT_FRONT_EMISSION) { 1049 fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0]; 1050 fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1]; 1051 fcmd[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_FRONT_EMISSION][2]; 1052 fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3]; 1053 } 1054 if (mask & MAT_BIT_FRONT_AMBIENT) { 1055 fcmd[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_FRONT_AMBIENT][0]; 1056 fcmd[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_FRONT_AMBIENT][1]; 1057 fcmd[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_FRONT_AMBIENT][2]; 1058 fcmd[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_FRONT_AMBIENT][3]; 1059 } 1060 if (mask & MAT_BIT_FRONT_DIFFUSE) { 1061 fcmd[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_FRONT_DIFFUSE][0]; 1062 fcmd[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_FRONT_DIFFUSE][1]; 1063 fcmd[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_FRONT_DIFFUSE][2]; 1064 fcmd[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_FRONT_DIFFUSE][3]; 1065 } 1066 if (mask & MAT_BIT_FRONT_SPECULAR) { 1067 fcmd[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_FRONT_SPECULAR][0]; 1068 fcmd[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_FRONT_SPECULAR][1]; 1069 fcmd[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_FRONT_SPECULAR][2]; 1070 fcmd[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_FRONT_SPECULAR][3]; 1071 } 1072 if (mask & MAT_BIT_FRONT_SHININESS) { 1073 fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0]; 1074 } 1075 1076 if (mask & MAT_BIT_BACK_EMISSION) { 1077 fcmd2[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_BACK_EMISSION][0]; 1078 fcmd2[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_BACK_EMISSION][1]; 1079 fcmd2[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_BACK_EMISSION][2]; 1080 fcmd2[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_BACK_EMISSION][3]; 1081 } 1082 if (mask & MAT_BIT_BACK_AMBIENT) { 1083 fcmd2[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_BACK_AMBIENT][0]; 1084 fcmd2[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_BACK_AMBIENT][1]; 1085 fcmd2[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_BACK_AMBIENT][2]; 1086 fcmd2[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_BACK_AMBIENT][3]; 1087 } 1088 if (mask & MAT_BIT_BACK_DIFFUSE) { 1089 fcmd2[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_BACK_DIFFUSE][0]; 1090 fcmd2[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_BACK_DIFFUSE][1]; 1091 fcmd2[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_BACK_DIFFUSE][2]; 1092 fcmd2[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_BACK_DIFFUSE][3]; 1093 } 1094 if (mask & MAT_BIT_BACK_SPECULAR) { 1095 fcmd2[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_BACK_SPECULAR][0]; 1096 fcmd2[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_BACK_SPECULAR][1]; 1097 fcmd2[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_BACK_SPECULAR][2]; 1098 fcmd2[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_BACK_SPECULAR][3]; 1099 } 1100 if (mask & MAT_BIT_BACK_SHININESS) { 1101 fcmd2[MTL_SHININESS] = mat[MAT_ATTRIB_BACK_SHININESS][0]; 1102 } 1103 1104 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[0] ); 1105 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[1] ); 1106 1107 /* currently material changes cannot trigger a global ambient change, I believe this is correct 1108 update_global_ambient( ctx ); */ 1109} 1110 1111/* _NEW_LIGHT 1112 * _NEW_MODELVIEW 1113 * _MESA_NEW_NEED_EYE_COORDS 1114 * 1115 * Uses derived state from mesa: 1116 * _VP_inf_norm 1117 * _h_inf_norm 1118 * _Position 1119 * _NormDirection 1120 * _ModelViewInvScale 1121 * _NeedEyeCoords 1122 * _EyeZDir 1123 * 1124 * which are calculated in light.c and are correct for the current 1125 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW 1126 * and _MESA_NEW_NEED_EYE_COORDS. 1127 */ 1128static void update_light( GLcontext *ctx ) 1129{ 1130 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1131 1132 /* Have to check these, or have an automatic shortcircuit mechanism 1133 * to remove noop statechanges. (Or just do a better job on the 1134 * front end). 1135 */ 1136 { 1137 GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]; 1138 1139 if (ctx->_NeedEyeCoords) 1140 tmp &= ~R200_LIGHT_IN_MODELSPACE; 1141 else 1142 tmp |= R200_LIGHT_IN_MODELSPACE; 1143 1144 if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]) 1145 { 1146 R200_STATECHANGE( rmesa, tcl ); 1147 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = tmp; 1148 } 1149 } 1150 1151 { 1152 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( eye ); 1153 fcmd[EYE_X] = ctx->_EyeZDir[0]; 1154 fcmd[EYE_Y] = ctx->_EyeZDir[1]; 1155 fcmd[EYE_Z] = - ctx->_EyeZDir[2]; 1156 fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale; 1157 R200_DB_STATECHANGE( rmesa, &rmesa->hw.eye ); 1158 } 1159 1160 1161 1162 if (ctx->Light.Enabled) { 1163 GLint p; 1164 for (p = 0 ; p < MAX_LIGHTS; p++) { 1165 if (ctx->Light.Light[p].Enabled) { 1166 struct gl_light *l = &ctx->Light.Light[p]; 1167 GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] ); 1168 1169 if (l->EyePosition[3] == 0.0) { 1170 COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm ); 1171 COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm ); 1172 fcmd[LIT_POSITION_W] = 0; 1173 fcmd[LIT_DIRECTION_W] = 0; 1174 } else { 1175 COPY_4V( &fcmd[LIT_POSITION_X], l->_Position ); 1176 fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0]; 1177 fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1]; 1178 fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2]; 1179 fcmd[LIT_DIRECTION_W] = 0; 1180 } 1181 1182 R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] ); 1183 } 1184 } 1185 } 1186} 1187 1188static void r200Lightfv( GLcontext *ctx, GLenum light, 1189 GLenum pname, const GLfloat *params ) 1190{ 1191 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1192 GLint p = light - GL_LIGHT0; 1193 struct gl_light *l = &ctx->Light.Light[p]; 1194 GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd; 1195 1196 1197 switch (pname) { 1198 case GL_AMBIENT: 1199 case GL_DIFFUSE: 1200 case GL_SPECULAR: 1201 update_light_colors( ctx, p ); 1202 break; 1203 1204 case GL_SPOT_DIRECTION: 1205 /* picked up in update_light */ 1206 break; 1207 1208 case GL_POSITION: { 1209 /* positions picked up in update_light, but can do flag here */ 1210 GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL; 1211 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; 1212 1213 R200_STATECHANGE(rmesa, tcl); 1214 if (l->EyePosition[3] != 0.0F) 1215 rmesa->hw.tcl.cmd[idx] |= flag; 1216 else 1217 rmesa->hw.tcl.cmd[idx] &= ~flag; 1218 break; 1219 } 1220 1221 case GL_SPOT_EXPONENT: 1222 R200_STATECHANGE(rmesa, lit[p]); 1223 fcmd[LIT_SPOT_EXPONENT] = params[0]; 1224 break; 1225 1226 case GL_SPOT_CUTOFF: { 1227 GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT; 1228 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; 1229 1230 R200_STATECHANGE(rmesa, lit[p]); 1231 fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff; 1232 1233 R200_STATECHANGE(rmesa, tcl); 1234 if (l->SpotCutoff != 180.0F) 1235 rmesa->hw.tcl.cmd[idx] |= flag; 1236 else 1237 rmesa->hw.tcl.cmd[idx] &= ~flag; 1238 1239 break; 1240 } 1241 1242 case GL_CONSTANT_ATTENUATION: 1243 R200_STATECHANGE(rmesa, lit[p]); 1244 fcmd[LIT_ATTEN_CONST] = params[0]; 1245 if ( params[0] == 0.0 ) 1246 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX; 1247 else 1248 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0]; 1249 break; 1250 case GL_LINEAR_ATTENUATION: 1251 R200_STATECHANGE(rmesa, lit[p]); 1252 fcmd[LIT_ATTEN_LINEAR] = params[0]; 1253 break; 1254 case GL_QUADRATIC_ATTENUATION: 1255 R200_STATECHANGE(rmesa, lit[p]); 1256 fcmd[LIT_ATTEN_QUADRATIC] = params[0]; 1257 break; 1258 default: 1259 return; 1260 } 1261 1262 /* Set RANGE_ATTEN only when needed */ 1263 switch (pname) { 1264 case GL_POSITION: 1265 case GL_CONSTANT_ATTENUATION: 1266 case GL_LINEAR_ATTENUATION: 1267 case GL_QUADRATIC_ATTENUATION: { 1268 GLuint *icmd = (GLuint *)R200_DB_STATE( tcl ); 1269 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; 1270 GLuint atten_flag = ( p&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN 1271 : R200_LIGHT_0_ENABLE_RANGE_ATTEN; 1272 GLuint atten_const_flag = ( p&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN 1273 : R200_LIGHT_0_CONSTANT_RANGE_ATTEN; 1274 1275 if ( l->EyePosition[3] == 0.0F || 1276 ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) && 1277 fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) { 1278 /* Disable attenuation */ 1279 icmd[idx] &= ~atten_flag; 1280 } else { 1281 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) { 1282 /* Enable only constant portion of attenuation calculation */ 1283 icmd[idx] |= ( atten_flag | atten_const_flag ); 1284 } else { 1285 /* Enable full attenuation calculation */ 1286 icmd[idx] &= ~atten_const_flag; 1287 icmd[idx] |= atten_flag; 1288 } 1289 } 1290 1291 R200_DB_STATECHANGE( rmesa, &rmesa->hw.tcl ); 1292 break; 1293 } 1294 default: 1295 break; 1296 } 1297} 1298 1299static void r200UpdateLocalViewer ( GLcontext *ctx ) 1300{ 1301/* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and 1302 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that 1303 for these and only these modes). This means specular highlights may turn out 1304 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER 1305 is not set, though it seems to happen rarely and the effect seems quite 1306 subtle. May need TCL fallback to fix it completely, though I'm not sure 1307 how you'd identify the cases where the specular highlights indeed will 1308 be wrong. Don't know if fglrx does something special in that case. 1309*/ 1310 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1311 R200_STATECHANGE( rmesa, tcl ); 1312 if (ctx->Light.Model.LocalViewer || 1313 ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS) 1314 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER; 1315 else 1316 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER; 1317} 1318 1319static void r200LightModelfv( GLcontext *ctx, GLenum pname, 1320 const GLfloat *param ) 1321{ 1322 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1323 1324 switch (pname) { 1325 case GL_LIGHT_MODEL_AMBIENT: 1326 update_global_ambient( ctx ); 1327 break; 1328 1329 case GL_LIGHT_MODEL_LOCAL_VIEWER: 1330 r200UpdateLocalViewer( ctx ); 1331 break; 1332 1333 case GL_LIGHT_MODEL_TWO_SIDE: 1334 R200_STATECHANGE( rmesa, tcl ); 1335 if (ctx->Light.Model.TwoSide) 1336 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE; 1337 else 1338 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~(R200_LIGHT_TWOSIDE); 1339 if (rmesa->radeon.TclFallback) { 1340 r200ChooseRenderState( ctx ); 1341 r200ChooseVertexState( ctx ); 1342 } 1343 break; 1344 1345 case GL_LIGHT_MODEL_COLOR_CONTROL: 1346 r200UpdateSpecular(ctx); 1347 break; 1348 1349 default: 1350 break; 1351 } 1352} 1353 1354static void r200ShadeModel( GLcontext *ctx, GLenum mode ) 1355{ 1356 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1357 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL]; 1358 1359 s &= ~(R200_DIFFUSE_SHADE_MASK | 1360 R200_ALPHA_SHADE_MASK | 1361 R200_SPECULAR_SHADE_MASK | 1362 R200_FOG_SHADE_MASK | 1363 R200_DISC_FOG_SHADE_MASK); 1364 1365 switch ( mode ) { 1366 case GL_FLAT: 1367 s |= (R200_DIFFUSE_SHADE_FLAT | 1368 R200_ALPHA_SHADE_FLAT | 1369 R200_SPECULAR_SHADE_FLAT | 1370 R200_FOG_SHADE_FLAT | 1371 R200_DISC_FOG_SHADE_FLAT); 1372 break; 1373 case GL_SMOOTH: 1374 s |= (R200_DIFFUSE_SHADE_GOURAUD | 1375 R200_ALPHA_SHADE_GOURAUD | 1376 R200_SPECULAR_SHADE_GOURAUD | 1377 R200_FOG_SHADE_GOURAUD | 1378 R200_DISC_FOG_SHADE_GOURAUD); 1379 break; 1380 default: 1381 return; 1382 } 1383 1384 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) { 1385 R200_STATECHANGE( rmesa, set ); 1386 rmesa->hw.set.cmd[SET_SE_CNTL] = s; 1387 } 1388} 1389 1390 1391/* ============================================================= 1392 * User clip planes 1393 */ 1394 1395static void r200ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq ) 1396{ 1397 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0; 1398 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1399 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p]; 1400 1401 R200_STATECHANGE( rmesa, ucp[p] ); 1402 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0]; 1403 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1]; 1404 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2]; 1405 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3]; 1406} 1407 1408static void r200UpdateClipPlanes( GLcontext *ctx ) 1409{ 1410 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1411 GLuint p; 1412 1413 for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { 1414 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { 1415 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p]; 1416 1417 R200_STATECHANGE( rmesa, ucp[p] ); 1418 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0]; 1419 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1]; 1420 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2]; 1421 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3]; 1422 } 1423 } 1424} 1425 1426 1427/* ============================================================= 1428 * Stencil 1429 */ 1430 1431static void 1432r200StencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func, 1433 GLint ref, GLuint mask ) 1434{ 1435 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1436 GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << R200_STENCIL_REF_SHIFT) | 1437 ((ctx->Stencil.ValueMask[0] & 0xff) << R200_STENCIL_MASK_SHIFT)); 1438 1439 R200_STATECHANGE( rmesa, ctx ); 1440 R200_STATECHANGE( rmesa, msk ); 1441 1442 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK; 1443 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK| 1444 R200_STENCIL_VALUE_MASK); 1445 1446 switch ( ctx->Stencil.Function[0] ) { 1447 case GL_NEVER: 1448 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER; 1449 break; 1450 case GL_LESS: 1451 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS; 1452 break; 1453 case GL_EQUAL: 1454 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL; 1455 break; 1456 case GL_LEQUAL: 1457 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL; 1458 break; 1459 case GL_GREATER: 1460 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER; 1461 break; 1462 case GL_NOTEQUAL: 1463 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL; 1464 break; 1465 case GL_GEQUAL: 1466 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL; 1467 break; 1468 case GL_ALWAYS: 1469 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS; 1470 break; 1471 } 1472 1473 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask; 1474} 1475 1476static void 1477r200StencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask ) 1478{ 1479 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1480 1481 R200_STATECHANGE( rmesa, msk ); 1482 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK; 1483 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= 1484 ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT); 1485} 1486 1487static void 1488r200StencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail, 1489 GLenum zfail, GLenum zpass ) 1490{ 1491 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1492 1493 R200_STATECHANGE( rmesa, ctx ); 1494 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK | 1495 R200_STENCIL_ZFAIL_MASK | 1496 R200_STENCIL_ZPASS_MASK); 1497 1498 switch ( ctx->Stencil.FailFunc[0] ) { 1499 case GL_KEEP: 1500 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP; 1501 break; 1502 case GL_ZERO: 1503 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO; 1504 break; 1505 case GL_REPLACE: 1506 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE; 1507 break; 1508 case GL_INCR: 1509 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC; 1510 break; 1511 case GL_DECR: 1512 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC; 1513 break; 1514 case GL_INCR_WRAP_EXT: 1515 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP; 1516 break; 1517 case GL_DECR_WRAP_EXT: 1518 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP; 1519 break; 1520 case GL_INVERT: 1521 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT; 1522 break; 1523 } 1524 1525 switch ( ctx->Stencil.ZFailFunc[0] ) { 1526 case GL_KEEP: 1527 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP; 1528 break; 1529 case GL_ZERO: 1530 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO; 1531 break; 1532 case GL_REPLACE: 1533 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE; 1534 break; 1535 case GL_INCR: 1536 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC; 1537 break; 1538 case GL_DECR: 1539 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC; 1540 break; 1541 case GL_INCR_WRAP_EXT: 1542 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP; 1543 break; 1544 case GL_DECR_WRAP_EXT: 1545 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP; 1546 break; 1547 case GL_INVERT: 1548 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT; 1549 break; 1550 } 1551 1552 switch ( ctx->Stencil.ZPassFunc[0] ) { 1553 case GL_KEEP: 1554 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP; 1555 break; 1556 case GL_ZERO: 1557 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO; 1558 break; 1559 case GL_REPLACE: 1560 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE; 1561 break; 1562 case GL_INCR: 1563 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC; 1564 break; 1565 case GL_DECR: 1566 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC; 1567 break; 1568 case GL_INCR_WRAP_EXT: 1569 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP; 1570 break; 1571 case GL_DECR_WRAP_EXT: 1572 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP; 1573 break; 1574 case GL_INVERT: 1575 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT; 1576 break; 1577 } 1578} 1579 1580static void r200ClearStencil( GLcontext *ctx, GLint s ) 1581{ 1582 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1583 1584 rmesa->radeon.state.stencil.clear = 1585 ((GLuint) (ctx->Stencil.Clear & 0xff) | 1586 (0xff << R200_STENCIL_MASK_SHIFT) | 1587 ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT)); 1588} 1589 1590 1591/* ============================================================= 1592 * Window position and viewport transformation 1593 */ 1594 1595/* 1596 * To correctly position primitives: 1597 */ 1598#define SUBPIXEL_X 0.125 1599#define SUBPIXEL_Y 0.125 1600 1601 1602/** 1603 * Called when window size or position changes or viewport or depth range 1604 * state is changed. We update the hardware viewport state here. 1605 */ 1606void r200UpdateWindow( GLcontext *ctx ) 1607{ 1608 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1609 __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable; 1610 GLfloat xoffset = dPriv ? (GLfloat) dPriv->x : 0; 1611 GLfloat yoffset = dPriv ? (GLfloat) dPriv->y + dPriv->h : 0; 1612 const GLfloat *v = ctx->Viewport._WindowMap.m; 1613 const GLboolean render_to_fbo = (ctx->DrawBuffer ? (ctx->DrawBuffer->Name != 0) : 0); 1614 GLfloat y_scale, y_bias; 1615 1616 if (render_to_fbo) { 1617 y_scale = 1.0; 1618 y_bias = 0; 1619 } else { 1620 y_scale = -1.0; 1621 y_bias = yoffset; 1622 } 1623 1624 float_ui32_type sx = { v[MAT_SX] }; 1625 float_ui32_type tx = { v[MAT_TX] + xoffset + SUBPIXEL_X }; 1626 float_ui32_type sy = { v[MAT_SY] * y_scale }; 1627 float_ui32_type ty = { (v[MAT_TY] * y_scale) + y_bias + SUBPIXEL_Y }; 1628 float_ui32_type sz = { v[MAT_SZ] * rmesa->radeon.state.depth.scale }; 1629 float_ui32_type tz = { v[MAT_TZ] * rmesa->radeon.state.depth.scale }; 1630 1631 R200_STATECHANGE( rmesa, vpt ); 1632 1633 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = sx.ui32; 1634 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32; 1635 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = sy.ui32; 1636 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32; 1637 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = sz.ui32; 1638 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32; 1639} 1640 1641 1642 1643static void r200Viewport( GLcontext *ctx, GLint x, GLint y, 1644 GLsizei width, GLsizei height ) 1645{ 1646 /* Don't pipeline viewport changes, conflict with window offset 1647 * setting below. Could apply deltas to rescue pipelined viewport 1648 * values, or keep the originals hanging around. 1649 */ 1650 r200UpdateWindow( ctx ); 1651 1652 radeon_viewport(ctx, x, y, width, height); 1653} 1654 1655static void r200DepthRange( GLcontext *ctx, GLclampd nearval, 1656 GLclampd farval ) 1657{ 1658 r200UpdateWindow( ctx ); 1659} 1660 1661void r200UpdateViewportOffset( GLcontext *ctx ) 1662{ 1663 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1664 __DRIdrawablePrivate *dPriv = rmesa->radeon.dri.drawable; 1665 GLfloat xoffset = (GLfloat)dPriv->x; 1666 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h; 1667 const GLfloat *v = ctx->Viewport._WindowMap.m; 1668 1669 float_ui32_type tx; 1670 float_ui32_type ty; 1671 1672 tx.f = v[MAT_TX] + xoffset + SUBPIXEL_X; 1673 ty.f = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y; 1674 1675 if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != tx.ui32 || 1676 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != ty.ui32 ) 1677 { 1678 /* Note: this should also modify whatever data the context reset 1679 * code uses... 1680 */ 1681 R200_STATECHANGE( rmesa, vpt ); 1682 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32; 1683 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32; 1684 1685 /* update polygon stipple x/y screen offset */ 1686 { 1687 GLuint stx, sty; 1688 GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC]; 1689 1690 m &= ~(R200_STIPPLE_X_OFFSET_MASK | 1691 R200_STIPPLE_Y_OFFSET_MASK); 1692 1693 /* add magic offsets, then invert */ 1694 stx = 31 - ((rmesa->radeon.dri.drawable->x - 1) & R200_STIPPLE_COORD_MASK); 1695 sty = 31 - ((rmesa->radeon.dri.drawable->y + rmesa->radeon.dri.drawable->h - 1) 1696 & R200_STIPPLE_COORD_MASK); 1697 1698 m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) | 1699 (sty << R200_STIPPLE_Y_OFFSET_SHIFT)); 1700 1701 if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) { 1702 R200_STATECHANGE( rmesa, msc ); 1703 rmesa->hw.msc.cmd[MSC_RE_MISC] = m; 1704 } 1705 } 1706 } 1707 1708 radeonUpdateScissor( ctx ); 1709} 1710 1711 1712 1713/* ============================================================= 1714 * Miscellaneous 1715 */ 1716 1717static void r200ClearColor( GLcontext *ctx, const GLfloat c[4] ) 1718{ 1719 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1720 GLubyte color[4]; 1721 CLAMPED_FLOAT_TO_UBYTE(color[0], c[0]); 1722 CLAMPED_FLOAT_TO_UBYTE(color[1], c[1]); 1723 CLAMPED_FLOAT_TO_UBYTE(color[2], c[2]); 1724 CLAMPED_FLOAT_TO_UBYTE(color[3], c[3]); 1725 rmesa->radeon.state.color.clear = radeonPackColor( rmesa->radeon.radeonScreen->cpp, 1726 color[0], color[1], 1727 color[2], color[3] ); 1728} 1729 1730 1731static void r200RenderMode( GLcontext *ctx, GLenum mode ) 1732{ 1733 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1734 FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) ); 1735} 1736 1737 1738static GLuint r200_rop_tab[] = { 1739 R200_ROP_CLEAR, 1740 R200_ROP_AND, 1741 R200_ROP_AND_REVERSE, 1742 R200_ROP_COPY, 1743 R200_ROP_AND_INVERTED, 1744 R200_ROP_NOOP, 1745 R200_ROP_XOR, 1746 R200_ROP_OR, 1747 R200_ROP_NOR, 1748 R200_ROP_EQUIV, 1749 R200_ROP_INVERT, 1750 R200_ROP_OR_REVERSE, 1751 R200_ROP_COPY_INVERTED, 1752 R200_ROP_OR_INVERTED, 1753 R200_ROP_NAND, 1754 R200_ROP_SET, 1755}; 1756 1757static void r200LogicOpCode( GLcontext *ctx, GLenum opcode ) 1758{ 1759 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1760 GLuint rop = (GLuint)opcode - GL_CLEAR; 1761 1762 ASSERT( rop < 16 ); 1763 1764 R200_STATECHANGE( rmesa, msk ); 1765 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop]; 1766} 1767 1768/* ============================================================= 1769 * State enable/disable 1770 */ 1771 1772static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state ) 1773{ 1774 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1775 GLuint p, flag; 1776 1777 if ( R200_DEBUG & DEBUG_STATE ) 1778 fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__, 1779 _mesa_lookup_enum_by_nr( cap ), 1780 state ? "GL_TRUE" : "GL_FALSE" ); 1781 1782 switch ( cap ) { 1783 /* Fast track this one... 1784 */ 1785 case GL_TEXTURE_1D: 1786 case GL_TEXTURE_2D: 1787 case GL_TEXTURE_3D: 1788 break; 1789 1790 case GL_ALPHA_TEST: 1791 R200_STATECHANGE( rmesa, ctx ); 1792 if (state) { 1793 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE; 1794 } else { 1795 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE; 1796 } 1797 break; 1798 1799 case GL_BLEND: 1800 case GL_COLOR_LOGIC_OP: 1801 r200_set_blend_state( ctx ); 1802 break; 1803 1804 case GL_CLIP_PLANE0: 1805 case GL_CLIP_PLANE1: 1806 case GL_CLIP_PLANE2: 1807 case GL_CLIP_PLANE3: 1808 case GL_CLIP_PLANE4: 1809 case GL_CLIP_PLANE5: 1810 p = cap-GL_CLIP_PLANE0; 1811 R200_STATECHANGE( rmesa, tcl ); 1812 if (state) { 1813 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p); 1814 r200ClipPlane( ctx, cap, NULL ); 1815 } 1816 else { 1817 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p); 1818 } 1819 break; 1820 1821 case GL_COLOR_MATERIAL: 1822 r200ColorMaterial( ctx, 0, 0 ); 1823 r200UpdateMaterial( ctx ); 1824 break; 1825 1826 case GL_CULL_FACE: 1827 r200CullFace( ctx, 0 ); 1828 break; 1829 1830 case GL_DEPTH_TEST: 1831 R200_STATECHANGE(rmesa, ctx ); 1832 if ( state ) { 1833 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE; 1834 } else { 1835 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE; 1836 } 1837 break; 1838 1839 case GL_DITHER: 1840 R200_STATECHANGE(rmesa, ctx ); 1841 if ( state ) { 1842 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE; 1843 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->radeon.state.color.roundEnable; 1844 } else { 1845 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE; 1846 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->radeon.state.color.roundEnable; 1847 } 1848 break; 1849 1850 case GL_FOG: 1851 R200_STATECHANGE(rmesa, ctx ); 1852 if ( state ) { 1853 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE; 1854 r200Fogfv( ctx, GL_FOG_MODE, NULL ); 1855 } else { 1856 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE; 1857 R200_STATECHANGE(rmesa, tcl); 1858 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK; 1859 } 1860 r200UpdateSpecular( ctx ); /* for PK_SPEC */ 1861 if (rmesa->radeon.TclFallback) 1862 r200ChooseVertexState( ctx ); 1863 _mesa_allow_light_in_model( ctx, !state ); 1864 break; 1865 1866 case GL_LIGHT0: 1867 case GL_LIGHT1: 1868 case GL_LIGHT2: 1869 case GL_LIGHT3: 1870 case GL_LIGHT4: 1871 case GL_LIGHT5: 1872 case GL_LIGHT6: 1873 case GL_LIGHT7: 1874 R200_STATECHANGE(rmesa, tcl); 1875 p = cap - GL_LIGHT0; 1876 if (p&1) 1877 flag = (R200_LIGHT_1_ENABLE | 1878 R200_LIGHT_1_ENABLE_AMBIENT | 1879 R200_LIGHT_1_ENABLE_SPECULAR); 1880 else 1881 flag = (R200_LIGHT_0_ENABLE | 1882 R200_LIGHT_0_ENABLE_AMBIENT | 1883 R200_LIGHT_0_ENABLE_SPECULAR); 1884 1885 if (state) 1886 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag; 1887 else 1888 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag; 1889 1890 /* 1891 */ 1892 update_light_colors( ctx, p ); 1893 break; 1894 1895 case GL_LIGHTING: 1896 r200UpdateSpecular(ctx); 1897 /* for reflection map fixup - might set recheck_texgen for all units too */ 1898 rmesa->radeon.NewGLState |= _NEW_TEXTURE; 1899 break; 1900 1901 case GL_LINE_SMOOTH: 1902 R200_STATECHANGE( rmesa, ctx ); 1903 if ( state ) { 1904 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE; 1905 } else { 1906 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE; 1907 } 1908 break; 1909 1910 case GL_LINE_STIPPLE: 1911 R200_STATECHANGE( rmesa, set ); 1912 if ( state ) { 1913 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE; 1914 } else { 1915 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE; 1916 } 1917 break; 1918 1919 case GL_NORMALIZE: 1920 R200_STATECHANGE( rmesa, tcl ); 1921 if ( state ) { 1922 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS; 1923 } else { 1924 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS; 1925 } 1926 break; 1927 1928 /* Pointsize registers on r200 only work for point sprites, and point smooth 1929 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points). 1930 * In any case, setting pointmin == pointsizemax == 1.0 for aa points 1931 * is enough to satisfy conform. 1932 */ 1933 case GL_POINT_SMOOTH: 1934 break; 1935 1936 /* These don't really do anything, as we don't use the 3vtx 1937 * primitives yet. 1938 */ 1939#if 0 1940 case GL_POLYGON_OFFSET_POINT: 1941 R200_STATECHANGE( rmesa, set ); 1942 if ( state ) { 1943 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT; 1944 } else { 1945 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT; 1946 } 1947 break; 1948 1949 case GL_POLYGON_OFFSET_LINE: 1950 R200_STATECHANGE( rmesa, set ); 1951 if ( state ) { 1952 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE; 1953 } else { 1954 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE; 1955 } 1956 break; 1957#endif 1958 1959 case GL_POINT_SPRITE_ARB: 1960 R200_STATECHANGE( rmesa, spr ); 1961 if ( state ) { 1962 int i; 1963 for (i = 0; i < 6; i++) { 1964 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= 1965 ctx->Point.CoordReplace[i] << (R200_PS_GEN_TEX_0_SHIFT + i); 1966 } 1967 } else { 1968 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~R200_PS_GEN_TEX_MASK; 1969 } 1970 break; 1971 1972 case GL_POLYGON_OFFSET_FILL: 1973 R200_STATECHANGE( rmesa, set ); 1974 if ( state ) { 1975 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI; 1976 } else { 1977 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI; 1978 } 1979 break; 1980 1981 case GL_POLYGON_SMOOTH: 1982 R200_STATECHANGE( rmesa, ctx ); 1983 if ( state ) { 1984 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY; 1985 } else { 1986 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY; 1987 } 1988 break; 1989 1990 case GL_POLYGON_STIPPLE: 1991 R200_STATECHANGE(rmesa, set ); 1992 if ( state ) { 1993 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE; 1994 } else { 1995 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE; 1996 } 1997 break; 1998 1999 case GL_RESCALE_NORMAL_EXT: { 2000 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state; 2001 R200_STATECHANGE( rmesa, tcl ); 2002 if ( tmp ) { 2003 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS; 2004 } else { 2005 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS; 2006 } 2007 break; 2008 } 2009 2010 case GL_SCISSOR_TEST: 2011 radeon_firevertices(&rmesa->radeon); 2012 rmesa->radeon.state.scissor.enabled = state; 2013 radeonUpdateScissor( ctx ); 2014 break; 2015 2016 case GL_STENCIL_TEST: 2017 if ( rmesa->radeon.state.stencil.hwBuffer ) { 2018 R200_STATECHANGE( rmesa, ctx ); 2019 if ( state ) { 2020 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE; 2021 } else { 2022 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE; 2023 } 2024 } else { 2025 FALLBACK( rmesa, R200_FALLBACK_STENCIL, state ); 2026 } 2027 break; 2028 2029 case GL_TEXTURE_GEN_Q: 2030 case GL_TEXTURE_GEN_R: 2031 case GL_TEXTURE_GEN_S: 2032 case GL_TEXTURE_GEN_T: 2033 /* Picked up in r200UpdateTextureState. 2034 */ 2035 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE; 2036 break; 2037 2038 case GL_COLOR_SUM_EXT: 2039 r200UpdateSpecular ( ctx ); 2040 break; 2041 2042 case GL_VERTEX_PROGRAM_ARB: 2043 if (!state) { 2044 GLuint i; 2045 rmesa->curr_vp_hw = NULL; 2046 R200_STATECHANGE( rmesa, vap ); 2047 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE; 2048 /* mark all tcl atoms (tcl vector state got overwritten) dirty 2049 not sure about tcl scalar state - we need at least grd 2050 with vert progs too. 2051 ucp looks like it doesn't get overwritten (may even work 2052 with vp for pos-invariant progs if we're lucky) */ 2053 R200_STATECHANGE( rmesa, mtl[0] ); 2054 R200_STATECHANGE( rmesa, mtl[1] ); 2055 R200_STATECHANGE( rmesa, fog ); 2056 R200_STATECHANGE( rmesa, glt ); 2057 R200_STATECHANGE( rmesa, eye ); 2058 for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++) { 2059 R200_STATECHANGE( rmesa, mat[i] ); 2060 } 2061 for (i = 0 ; i < 8; i++) { 2062 R200_STATECHANGE( rmesa, lit[i] ); 2063 } 2064 R200_STATECHANGE( rmesa, tcl ); 2065 for (i = 0; i <= ctx->Const.MaxClipPlanes; i++) { 2066 if (ctx->Transform.ClipPlanesEnabled & (1 << i)) { 2067 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0 << i); 2068 } 2069/* else { 2070 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i); 2071 }*/ 2072 } 2073 /* ugly. Need to call everything which might change compsel. */ 2074 r200UpdateSpecular( ctx ); 2075#if 0 2076 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM), 2077 but without it doom3 locks up at always the same places. Why? */ 2078 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before 2079 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */ 2080 r200UpdateTextureState( ctx ); 2081 /* if we call r200UpdateTextureState we need the code below because we are calling it with 2082 non-current derived enabled values which may revert the state atoms for frag progs even when 2083 they already got disabled... ugh 2084 Should really figure out why we need to call r200UpdateTextureState in the first place */ 2085 GLuint unit; 2086 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) { 2087 R200_STATECHANGE( rmesa, pix[unit] ); 2088 R200_STATECHANGE( rmesa, tex[unit] ); 2089 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &= 2090 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE); 2091 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT; 2092 /* need to guard this with drmSupportsFragmentShader? Should never get here if 2093 we don't announce ATI_fs, right? */ 2094 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0; 2095 } 2096 R200_STATECHANGE( rmesa, cst ); 2097 R200_STATECHANGE( rmesa, tf ); 2098 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0; 2099#endif 2100 } 2101 else { 2102 /* picked up later */ 2103 } 2104 /* call functions which change hw state based on ARB_vp enabled or not. */ 2105 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL ); 2106 r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL ); 2107 break; 2108 2109 case GL_VERTEX_PROGRAM_POINT_SIZE_ARB: 2110 r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL ); 2111 break; 2112 2113 case GL_FRAGMENT_SHADER_ATI: 2114 if ( !state ) { 2115 /* restore normal tex env colors and make sure tex env combine will get updated 2116 mark env atoms dirty (as their data was overwritten by afs even 2117 if they didn't change) and restore tex coord routing */ 2118 GLuint unit; 2119 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) { 2120 R200_STATECHANGE( rmesa, pix[unit] ); 2121 R200_STATECHANGE( rmesa, tex[unit] ); 2122 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &= 2123 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE); 2124 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT; 2125 /* need to guard this with drmSupportsFragmentShader? Should never get here if 2126 we don't announce ATI_fs, right? */ 2127 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0; 2128 } 2129 R200_STATECHANGE( rmesa, cst ); 2130 R200_STATECHANGE( rmesa, tf ); 2131 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0; 2132 } 2133 else { 2134 /* need to mark this dirty as pix/tf atoms have overwritten the data 2135 even if the data in the atoms didn't change */ 2136 R200_STATECHANGE( rmesa, atf ); 2137 R200_STATECHANGE( rmesa, afs[1] ); 2138 /* everything else picked up in r200UpdateTextureState hopefully */ 2139 } 2140 break; 2141 default: 2142 return; 2143 } 2144} 2145 2146 2147void r200LightingSpaceChange( GLcontext *ctx ) 2148{ 2149 r200ContextPtr rmesa = R200_CONTEXT(ctx); 2150 GLboolean tmp; 2151 2152 if (R200_DEBUG & DEBUG_STATE) 2153 fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords, 2154 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]); 2155 2156 if (ctx->_NeedEyeCoords) 2157 tmp = ctx->Transform.RescaleNormals; 2158 else 2159 tmp = !ctx->Transform.RescaleNormals; 2160 2161 R200_STATECHANGE( rmesa, tcl ); 2162 if ( tmp ) { 2163 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS; 2164 } else { 2165 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS; 2166 } 2167 2168 if (R200_DEBUG & DEBUG_STATE) 2169 fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords, 2170 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]); 2171} 2172 2173/* ============================================================= 2174 * Deferred state management - matrices, textures, other? 2175 */ 2176 2177 2178 2179 2180static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx ) 2181{ 2182 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0; 2183 int i; 2184 2185 2186 for (i = 0 ; i < 4 ; i++) { 2187 *dest++ = src[i]; 2188 *dest++ = src[i+4]; 2189 *dest++ = src[i+8]; 2190 *dest++ = src[i+12]; 2191 } 2192 2193 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); 2194} 2195 2196static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx ) 2197{ 2198 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0; 2199 memcpy(dest, src, 16*sizeof(float)); 2200 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); 2201} 2202 2203 2204static void update_texturematrix( GLcontext *ctx ) 2205{ 2206 r200ContextPtr rmesa = R200_CONTEXT( ctx ); 2207 GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]; 2208 GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]; 2209 int unit; 2210 2211 if (R200_DEBUG & DEBUG_STATE) 2212 fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__, 2213 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]); 2214 2215 rmesa->TexMatEnabled = 0; 2216 rmesa->TexMatCompSel = 0; 2217 2218 for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) { 2219 if (!ctx->Texture.Unit[unit]._ReallyEnabled) 2220 continue; 2221 2222 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) { 2223 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE| 2224 R200_TEXMAT_0_ENABLE) << unit; 2225 2226 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit; 2227 2228 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) { 2229 /* Need to preconcatenate any active texgen 2230 * obj/eyeplane matrices: 2231 */ 2232 _math_matrix_mul_matrix( &rmesa->tmpmat, 2233 ctx->TextureMatrixStack[unit].Top, 2234 &rmesa->TexGenMatrix[unit] ); 2235 upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit ); 2236 } 2237 else { 2238 upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m, 2239 R200_MTX_TEX0+unit ); 2240 } 2241 } 2242 else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) { 2243 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m, 2244 R200_MTX_TEX0+unit ); 2245 } 2246 } 2247 2248 tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled); 2249 if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]) { 2250 R200_STATECHANGE(rmesa, tcg); 2251 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc; 2252 } 2253 2254 compsel &= ~R200_OUTPUT_TEX_MASK; 2255 compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel; 2256 if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) { 2257 R200_STATECHANGE(rmesa, vtx); 2258 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel; 2259 } 2260} 2261 2262static GLboolean r200ValidateBuffers(GLcontext *ctx) 2263{ 2264 r200ContextPtr rmesa = R200_CONTEXT(ctx); 2265 struct radeon_cs_space_check bos[8]; 2266 struct radeon_renderbuffer *rrb; 2267 int num_bo = 0; 2268 int i; 2269 int flushed = 0, ret; 2270again: 2271 num_bo = 0; 2272 2273 rrb = radeon_get_colorbuffer(&rmesa->radeon); 2274 /* color buffer */ 2275 if (rrb && rrb->bo) { 2276 bos[num_bo].bo = rrb->bo; 2277 bos[num_bo].read_domains = 0; 2278 bos[num_bo].write_domain = RADEON_GEM_DOMAIN_VRAM; 2279 bos[num_bo].new_accounted = 0; 2280 num_bo++; 2281 } 2282 2283 /* depth buffer */ 2284 rrb = radeon_get_depthbuffer(&rmesa->radeon); 2285 /* color buffer */ 2286 if (rrb && rrb->bo) { 2287 bos[num_bo].bo = rrb->bo; 2288 bos[num_bo].read_domains = 0; 2289 bos[num_bo].write_domain = RADEON_GEM_DOMAIN_VRAM; 2290 bos[num_bo].new_accounted = 0; 2291 num_bo++; 2292 } 2293 2294 for (i = 0; i < ctx->Const.MaxTextureImageUnits; ++i) { 2295 radeonTexObj *t; 2296 2297 if (!ctx->Texture.Unit[i]._ReallyEnabled) 2298 continue; 2299 2300 t = radeon_tex_obj(ctx->Texture.Unit[i]._Current); 2301 bos[num_bo].bo = t->mt->bo; 2302 bos[num_bo].read_domains = RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM; 2303 bos[num_bo].write_domain = 0; 2304 bos[num_bo].new_accounted = 0; 2305 num_bo++; 2306 } 2307 2308 ret = radeon_cs_space_check(rmesa->radeon.cmdbuf.cs, bos, num_bo); 2309 if (ret == RADEON_CS_SPACE_OP_TO_BIG) 2310 return GL_FALSE; 2311 if (ret == RADEON_CS_SPACE_FLUSH) { 2312 radeonFlush(ctx); 2313 if (flushed) 2314 return GL_FALSE; 2315 flushed = 1; 2316 goto again; 2317 } 2318 return GL_TRUE; 2319} 2320 2321GLboolean r200ValidateState( GLcontext *ctx ) 2322{ 2323 r200ContextPtr rmesa = R200_CONTEXT(ctx); 2324 GLuint new_state = rmesa->radeon.NewGLState; 2325 2326 if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { 2327 _mesa_update_framebuffer(ctx); 2328 /* this updates the DrawBuffer's Width/Height if it's a FBO */ 2329 _mesa_update_draw_buffer_bounds(ctx); 2330 2331 R200_STATECHANGE(rmesa, ctx); 2332 } 2333 2334 if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM)) { 2335 r200UpdateTextureState( ctx ); 2336 new_state |= rmesa->radeon.NewGLState; /* may add TEXTURE_MATRIX */ 2337 r200UpdateLocalViewer( ctx ); 2338 } 2339 2340 /* we need to do a space check here */ 2341 if (!r200ValidateBuffers(ctx)) 2342 return GL_FALSE; 2343 2344/* FIXME: don't really need most of these when vertex progs are enabled */ 2345 2346 /* Need an event driven matrix update? 2347 */ 2348 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) 2349 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP ); 2350 2351 /* Need these for lighting (shouldn't upload otherwise) 2352 */ 2353 if (new_state & (_NEW_MODELVIEW)) { 2354 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV ); 2355 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV ); 2356 } 2357 2358 /* Does this need to be triggered on eg. modelview for 2359 * texgen-derived objplane/eyeplane matrices? 2360 */ 2361 if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) { 2362 update_texturematrix( ctx ); 2363 } 2364 2365 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) { 2366 update_light( ctx ); 2367 } 2368 2369 /* emit all active clip planes if projection matrix changes. 2370 */ 2371 if (new_state & (_NEW_PROJECTION)) { 2372 if (ctx->Transform.ClipPlanesEnabled) 2373 r200UpdateClipPlanes( ctx ); 2374 } 2375 2376 if (new_state & (_NEW_PROGRAM| 2377 /* need to test for pretty much anything due to possible parameter bindings */ 2378 _NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM| 2379 _NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX| 2380 _NEW_FOG|_NEW_POINT|_NEW_TRACK_MATRIX)) { 2381 if (ctx->VertexProgram._Enabled) { 2382 r200SetupVertexProg( ctx ); 2383 } 2384 else TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, 0); 2385 } 2386 2387 rmesa->radeon.NewGLState = 0; 2388 return GL_TRUE; 2389} 2390 2391 2392static void r200InvalidateState( GLcontext *ctx, GLuint new_state ) 2393{ 2394 _swrast_InvalidateState( ctx, new_state ); 2395 _swsetup_InvalidateState( ctx, new_state ); 2396 _vbo_InvalidateState( ctx, new_state ); 2397 _tnl_InvalidateState( ctx, new_state ); 2398 _ae_invalidate_state( ctx, new_state ); 2399 R200_CONTEXT(ctx)->radeon.NewGLState |= new_state; 2400} 2401 2402/* A hack. The r200 can actually cope just fine with materials 2403 * between begin/ends, so fix this. 2404 * Should map to inputs just like the generic vertex arrays for vertex progs. 2405 * In theory there could still be too many and we'd still need a fallback. 2406 */ 2407static GLboolean check_material( GLcontext *ctx ) 2408{ 2409 TNLcontext *tnl = TNL_CONTEXT(ctx); 2410 GLint i; 2411 2412 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT; 2413 i < _TNL_ATTRIB_MAT_BACK_INDEXES; 2414 i++) 2415 if (tnl->vb.AttribPtr[i] && 2416 tnl->vb.AttribPtr[i]->stride) 2417 return GL_TRUE; 2418 2419 return GL_FALSE; 2420} 2421 2422static void r200WrapRunPipeline( GLcontext *ctx ) 2423{ 2424 r200ContextPtr rmesa = R200_CONTEXT(ctx); 2425 GLboolean has_material; 2426 2427 if (0) 2428 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->radeon.NewGLState); 2429 2430 /* Validate state: 2431 */ 2432 if (rmesa->radeon.NewGLState) 2433 if (!r200ValidateState( ctx )) 2434 FALLBACK(rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE); 2435 2436 has_material = !ctx->VertexProgram._Enabled && ctx->Light.Enabled && check_material( ctx ); 2437 2438 if (has_material) { 2439 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE ); 2440 } 2441 2442 /* Run the pipeline. 2443 */ 2444 _tnl_run_pipeline( ctx ); 2445 2446 if (has_material) { 2447 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE ); 2448 } 2449} 2450 2451 2452/* Initialize the driver's state functions. 2453 */ 2454void r200InitStateFuncs( struct dd_function_table *functions ) 2455{ 2456 functions->UpdateState = r200InvalidateState; 2457 functions->LightingSpaceChange = r200LightingSpaceChange; 2458 2459 functions->DrawBuffer = radeonDrawBuffer; 2460 functions->ReadBuffer = radeonReadBuffer; 2461 2462 functions->AlphaFunc = r200AlphaFunc; 2463 functions->BlendColor = r200BlendColor; 2464 functions->BlendEquationSeparate = r200BlendEquationSeparate; 2465 functions->BlendFuncSeparate = r200BlendFuncSeparate; 2466 functions->ClearColor = r200ClearColor; 2467 functions->ClearDepth = r200ClearDepth; 2468 functions->ClearIndex = NULL; 2469 functions->ClearStencil = r200ClearStencil; 2470 functions->ClipPlane = r200ClipPlane; 2471 functions->ColorMask = r200ColorMask; 2472 functions->CullFace = r200CullFace; 2473 functions->DepthFunc = r200DepthFunc; 2474 functions->DepthMask = r200DepthMask; 2475 functions->DepthRange = r200DepthRange; 2476 functions->Enable = r200Enable; 2477 functions->Fogfv = r200Fogfv; 2478 functions->FrontFace = r200FrontFace; 2479 functions->Hint = NULL; 2480 functions->IndexMask = NULL; 2481 functions->LightModelfv = r200LightModelfv; 2482 functions->Lightfv = r200Lightfv; 2483 functions->LineStipple = r200LineStipple; 2484 functions->LineWidth = r200LineWidth; 2485 functions->LogicOpcode = r200LogicOpCode; 2486 functions->PolygonMode = r200PolygonMode; 2487 functions->PolygonOffset = r200PolygonOffset; 2488 functions->PolygonStipple = r200PolygonStipple; 2489 functions->PointParameterfv = r200PointParameter; 2490 functions->PointSize = r200PointSize; 2491 functions->RenderMode = r200RenderMode; 2492 functions->Scissor = radeonScissor; 2493 functions->ShadeModel = r200ShadeModel; 2494 functions->StencilFuncSeparate = r200StencilFuncSeparate; 2495 functions->StencilMaskSeparate = r200StencilMaskSeparate; 2496 functions->StencilOpSeparate = r200StencilOpSeparate; 2497 functions->Viewport = r200Viewport; 2498} 2499 2500 2501void r200InitTnlFuncs( GLcontext *ctx ) 2502{ 2503 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial; 2504 TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline; 2505} 2506