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