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