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