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