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