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