r200_state.c revision cb08dcbbf29dfa82128c8302f7aa69e90478a5ea
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#include "r200_vertprog.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 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 out_0 |= R200_VTX_DISCRETE_FOG; 496 } 497 else { 498 fog |= R200_FOG_USE_SPEC_ALPHA; 499 out_0 &= ~R200_VTX_DISCRETE_FOG; 500 } 501 502 if ( fog != rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] ) { 503 R200_STATECHANGE( rmesa, ctx ); 504 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = fog; 505 } 506 507 if (out_0 != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0]) { 508 R200_STATECHANGE( rmesa, vtx ); 509 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] = out_0; 510 } 511 512 break; 513 } 514 default: 515 return; 516 } 517 518 if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) { 519 R200_STATECHANGE( rmesa, fog ); 520 rmesa->hw.fog.cmd[FOG_C] = c.i; 521 rmesa->hw.fog.cmd[FOG_D] = d.i; 522 } 523} 524 525 526/* ============================================================= 527 * Scissoring 528 */ 529 530 531static GLboolean intersect_rect( drm_clip_rect_t *out, 532 drm_clip_rect_t *a, 533 drm_clip_rect_t *b ) 534{ 535 *out = *a; 536 if ( b->x1 > out->x1 ) out->x1 = b->x1; 537 if ( b->y1 > out->y1 ) out->y1 = b->y1; 538 if ( b->x2 < out->x2 ) out->x2 = b->x2; 539 if ( b->y2 < out->y2 ) out->y2 = b->y2; 540 if ( out->x1 >= out->x2 ) return GL_FALSE; 541 if ( out->y1 >= out->y2 ) return GL_FALSE; 542 return GL_TRUE; 543} 544 545 546void r200RecalcScissorRects( r200ContextPtr rmesa ) 547{ 548 drm_clip_rect_t *out; 549 int i; 550 551 /* Grow cliprect store? 552 */ 553 if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) { 554 while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) { 555 rmesa->state.scissor.numAllocedClipRects += 1; /* zero case */ 556 rmesa->state.scissor.numAllocedClipRects *= 2; 557 } 558 559 if (rmesa->state.scissor.pClipRects) 560 FREE(rmesa->state.scissor.pClipRects); 561 562 rmesa->state.scissor.pClipRects = 563 MALLOC( rmesa->state.scissor.numAllocedClipRects * 564 sizeof(drm_clip_rect_t) ); 565 566 if ( rmesa->state.scissor.pClipRects == NULL ) { 567 rmesa->state.scissor.numAllocedClipRects = 0; 568 return; 569 } 570 } 571 572 out = rmesa->state.scissor.pClipRects; 573 rmesa->state.scissor.numClipRects = 0; 574 575 for ( i = 0 ; i < rmesa->numClipRects ; i++ ) { 576 if ( intersect_rect( out, 577 &rmesa->pClipRects[i], 578 &rmesa->state.scissor.rect ) ) { 579 rmesa->state.scissor.numClipRects++; 580 out++; 581 } 582 } 583} 584 585 586static void r200UpdateScissor( GLcontext *ctx ) 587{ 588 r200ContextPtr rmesa = R200_CONTEXT(ctx); 589 590 if ( rmesa->dri.drawable ) { 591 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; 592 593 int x = ctx->Scissor.X; 594 int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height; 595 int w = ctx->Scissor.X + ctx->Scissor.Width - 1; 596 int h = dPriv->h - ctx->Scissor.Y - 1; 597 598 rmesa->state.scissor.rect.x1 = x + dPriv->x; 599 rmesa->state.scissor.rect.y1 = y + dPriv->y; 600 rmesa->state.scissor.rect.x2 = w + dPriv->x + 1; 601 rmesa->state.scissor.rect.y2 = h + dPriv->y + 1; 602 603 r200RecalcScissorRects( rmesa ); 604 } 605} 606 607 608static void r200Scissor( GLcontext *ctx, 609 GLint x, GLint y, GLsizei w, GLsizei h ) 610{ 611 r200ContextPtr rmesa = R200_CONTEXT(ctx); 612 613 if ( ctx->Scissor.Enabled ) { 614 R200_FIREVERTICES( rmesa ); /* don't pipeline cliprect changes */ 615 r200UpdateScissor( ctx ); 616 } 617 618} 619 620 621/* ============================================================= 622 * Culling 623 */ 624 625static void r200CullFace( GLcontext *ctx, GLenum unused ) 626{ 627 r200ContextPtr rmesa = R200_CONTEXT(ctx); 628 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL]; 629 GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL]; 630 631 s |= R200_FFACE_SOLID | R200_BFACE_SOLID; 632 t &= ~(R200_CULL_FRONT | R200_CULL_BACK); 633 634 if ( ctx->Polygon.CullFlag ) { 635 switch ( ctx->Polygon.CullFaceMode ) { 636 case GL_FRONT: 637 s &= ~R200_FFACE_SOLID; 638 t |= R200_CULL_FRONT; 639 break; 640 case GL_BACK: 641 s &= ~R200_BFACE_SOLID; 642 t |= R200_CULL_BACK; 643 break; 644 case GL_FRONT_AND_BACK: 645 s &= ~(R200_FFACE_SOLID | R200_BFACE_SOLID); 646 t |= (R200_CULL_FRONT | R200_CULL_BACK); 647 break; 648 } 649 } 650 651 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) { 652 R200_STATECHANGE(rmesa, set ); 653 rmesa->hw.set.cmd[SET_SE_CNTL] = s; 654 } 655 656 if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) { 657 R200_STATECHANGE(rmesa, tcl ); 658 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t; 659 } 660} 661 662static void r200FrontFace( GLcontext *ctx, GLenum mode ) 663{ 664 r200ContextPtr rmesa = R200_CONTEXT(ctx); 665 666 R200_STATECHANGE( rmesa, set ); 667 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_FFACE_CULL_DIR_MASK; 668 669 R200_STATECHANGE( rmesa, tcl ); 670 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_CULL_FRONT_IS_CCW; 671 672 switch ( mode ) { 673 case GL_CW: 674 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CW; 675 break; 676 case GL_CCW: 677 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_FFACE_CULL_CCW; 678 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_CULL_FRONT_IS_CCW; 679 break; 680 } 681} 682 683/* ============================================================= 684 * Point state 685 */ 686static void r200PointSize( GLcontext *ctx, GLfloat size ) 687{ 688 r200ContextPtr rmesa = R200_CONTEXT(ctx); 689 690 R200_STATECHANGE( rmesa, cst ); 691 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= ~0xffff; 692 rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= ((GLuint)(ctx->Point.Size * 16.0)); 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 float_ui32_type constant = { units * rmesa->state.depth.scale }; 767 float_ui32_type factoru = { factor }; 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] = factoru.ui32; 776 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32; 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 1322static void r200UpdateLocalViewer ( GLcontext *ctx ) 1323{ 1324/* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and 1325 GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that 1326 for these and only these modes). This means specular highlights may turn out 1327 wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER 1328 is not set, though it seems to happen rarely and the effect seems quite 1329 subtle. May need TCL fallback to fix it completely, though I'm not sure 1330 how you'd identify the cases where the specular highlights indeed will 1331 be wrong. Don't know if fglrx does something special in that case. 1332*/ 1333 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1334 R200_STATECHANGE( rmesa, tcl ); 1335 if (ctx->Light.Model.LocalViewer || 1336 ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS) 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} 1341 1342static void r200LightModelfv( GLcontext *ctx, GLenum pname, 1343 const GLfloat *param ) 1344{ 1345 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1346 1347 switch (pname) { 1348 case GL_LIGHT_MODEL_AMBIENT: 1349 update_global_ambient( ctx ); 1350 break; 1351 1352 case GL_LIGHT_MODEL_LOCAL_VIEWER: 1353 r200UpdateLocalViewer( ctx ); 1354 break; 1355 1356 case GL_LIGHT_MODEL_TWO_SIDE: 1357 R200_STATECHANGE( rmesa, tcl ); 1358 if (ctx->Light.Model.TwoSide) 1359 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE; 1360 else 1361 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~(R200_LIGHT_TWOSIDE); 1362 if (rmesa->TclFallback) { 1363 r200ChooseRenderState( ctx ); 1364 r200ChooseVertexState( ctx ); 1365 } 1366 break; 1367 1368 case GL_LIGHT_MODEL_COLOR_CONTROL: 1369 r200UpdateSpecular(ctx); 1370 break; 1371 1372 default: 1373 break; 1374 } 1375} 1376 1377static void r200ShadeModel( GLcontext *ctx, GLenum mode ) 1378{ 1379 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1380 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL]; 1381 1382 s &= ~(R200_DIFFUSE_SHADE_MASK | 1383 R200_ALPHA_SHADE_MASK | 1384 R200_SPECULAR_SHADE_MASK | 1385 R200_FOG_SHADE_MASK); 1386 1387 switch ( mode ) { 1388 case GL_FLAT: 1389 s |= (R200_DIFFUSE_SHADE_FLAT | 1390 R200_ALPHA_SHADE_FLAT | 1391 R200_SPECULAR_SHADE_FLAT | 1392 R200_FOG_SHADE_FLAT); 1393 break; 1394 case GL_SMOOTH: 1395 s |= (R200_DIFFUSE_SHADE_GOURAUD | 1396 R200_ALPHA_SHADE_GOURAUD | 1397 R200_SPECULAR_SHADE_GOURAUD | 1398 R200_FOG_SHADE_GOURAUD); 1399 break; 1400 default: 1401 return; 1402 } 1403 1404 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) { 1405 R200_STATECHANGE( rmesa, set ); 1406 rmesa->hw.set.cmd[SET_SE_CNTL] = s; 1407 } 1408} 1409 1410 1411/* ============================================================= 1412 * User clip planes 1413 */ 1414 1415static void r200ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq ) 1416{ 1417 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0; 1418 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1419 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p]; 1420 1421 R200_STATECHANGE( rmesa, ucp[p] ); 1422 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0]; 1423 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1]; 1424 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2]; 1425 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3]; 1426} 1427 1428static void r200UpdateClipPlanes( GLcontext *ctx ) 1429{ 1430 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1431 GLuint p; 1432 1433 for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { 1434 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { 1435 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p]; 1436 1437 R200_STATECHANGE( rmesa, ucp[p] ); 1438 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0]; 1439 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1]; 1440 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2]; 1441 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3]; 1442 } 1443 } 1444} 1445 1446 1447/* ============================================================= 1448 * Stencil 1449 */ 1450 1451static void 1452r200StencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func, 1453 GLint ref, GLuint mask ) 1454{ 1455 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1456 GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << R200_STENCIL_REF_SHIFT) | 1457 ((ctx->Stencil.ValueMask[0] & 0xff) << R200_STENCIL_MASK_SHIFT)); 1458 1459 R200_STATECHANGE( rmesa, ctx ); 1460 R200_STATECHANGE( rmesa, msk ); 1461 1462 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK; 1463 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK| 1464 R200_STENCIL_VALUE_MASK); 1465 1466 switch ( ctx->Stencil.Function[0] ) { 1467 case GL_NEVER: 1468 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER; 1469 break; 1470 case GL_LESS: 1471 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS; 1472 break; 1473 case GL_EQUAL: 1474 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL; 1475 break; 1476 case GL_LEQUAL: 1477 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL; 1478 break; 1479 case GL_GREATER: 1480 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER; 1481 break; 1482 case GL_NOTEQUAL: 1483 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL; 1484 break; 1485 case GL_GEQUAL: 1486 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL; 1487 break; 1488 case GL_ALWAYS: 1489 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS; 1490 break; 1491 } 1492 1493 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask; 1494} 1495 1496static void 1497r200StencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask ) 1498{ 1499 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1500 1501 R200_STATECHANGE( rmesa, msk ); 1502 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK; 1503 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= 1504 ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT); 1505} 1506 1507static void 1508r200StencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail, 1509 GLenum zfail, GLenum zpass ) 1510{ 1511 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1512 1513 R200_STATECHANGE( rmesa, ctx ); 1514 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK | 1515 R200_STENCIL_ZFAIL_MASK | 1516 R200_STENCIL_ZPASS_MASK); 1517 1518 switch ( ctx->Stencil.FailFunc[0] ) { 1519 case GL_KEEP: 1520 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP; 1521 break; 1522 case GL_ZERO: 1523 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO; 1524 break; 1525 case GL_REPLACE: 1526 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE; 1527 break; 1528 case GL_INCR: 1529 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC; 1530 break; 1531 case GL_DECR: 1532 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC; 1533 break; 1534 case GL_INCR_WRAP_EXT: 1535 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP; 1536 break; 1537 case GL_DECR_WRAP_EXT: 1538 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP; 1539 break; 1540 case GL_INVERT: 1541 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT; 1542 break; 1543 } 1544 1545 switch ( ctx->Stencil.ZFailFunc[0] ) { 1546 case GL_KEEP: 1547 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP; 1548 break; 1549 case GL_ZERO: 1550 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO; 1551 break; 1552 case GL_REPLACE: 1553 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE; 1554 break; 1555 case GL_INCR: 1556 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC; 1557 break; 1558 case GL_DECR: 1559 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC; 1560 break; 1561 case GL_INCR_WRAP_EXT: 1562 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP; 1563 break; 1564 case GL_DECR_WRAP_EXT: 1565 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP; 1566 break; 1567 case GL_INVERT: 1568 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT; 1569 break; 1570 } 1571 1572 switch ( ctx->Stencil.ZPassFunc[0] ) { 1573 case GL_KEEP: 1574 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP; 1575 break; 1576 case GL_ZERO: 1577 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO; 1578 break; 1579 case GL_REPLACE: 1580 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE; 1581 break; 1582 case GL_INCR: 1583 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC; 1584 break; 1585 case GL_DECR: 1586 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC; 1587 break; 1588 case GL_INCR_WRAP_EXT: 1589 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP; 1590 break; 1591 case GL_DECR_WRAP_EXT: 1592 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP; 1593 break; 1594 case GL_INVERT: 1595 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT; 1596 break; 1597 } 1598} 1599 1600static void r200ClearStencil( GLcontext *ctx, GLint s ) 1601{ 1602 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1603 1604 rmesa->state.stencil.clear = 1605 ((GLuint) (ctx->Stencil.Clear & 0xff) | 1606 (0xff << R200_STENCIL_MASK_SHIFT) | 1607 ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT)); 1608} 1609 1610 1611/* ============================================================= 1612 * Window position and viewport transformation 1613 */ 1614 1615/* 1616 * To correctly position primitives: 1617 */ 1618#define SUBPIXEL_X 0.125 1619#define SUBPIXEL_Y 0.125 1620 1621void r200UpdateWindow( GLcontext *ctx ) 1622{ 1623 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1624 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; 1625 GLfloat xoffset = (GLfloat)dPriv->x; 1626 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h; 1627 const GLfloat *v = ctx->Viewport._WindowMap.m; 1628 1629 float_ui32_type sx = { v[MAT_SX] }; 1630 float_ui32_type tx = { v[MAT_TX] + xoffset + SUBPIXEL_X }; 1631 float_ui32_type sy = { - v[MAT_SY] }; 1632 float_ui32_type ty = { (- v[MAT_TY]) + yoffset + SUBPIXEL_Y }; 1633 float_ui32_type sz = { v[MAT_SZ] * rmesa->state.depth.scale }; 1634 float_ui32_type tz = { v[MAT_TZ] * rmesa->state.depth.scale }; 1635 1636 R200_FIREVERTICES( rmesa ); 1637 R200_STATECHANGE( rmesa, vpt ); 1638 1639 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = sx.ui32; 1640 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32; 1641 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = sy.ui32; 1642 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32; 1643 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = sz.ui32; 1644 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32; 1645} 1646 1647 1648 1649static void r200Viewport( GLcontext *ctx, GLint x, GLint y, 1650 GLsizei width, GLsizei height ) 1651{ 1652 /* Don't pipeline viewport changes, conflict with window offset 1653 * setting below. Could apply deltas to rescue pipelined viewport 1654 * values, or keep the originals hanging around. 1655 */ 1656 r200UpdateWindow( ctx ); 1657} 1658 1659static void r200DepthRange( GLcontext *ctx, GLclampd nearval, 1660 GLclampd farval ) 1661{ 1662 r200UpdateWindow( ctx ); 1663} 1664 1665void r200UpdateViewportOffset( GLcontext *ctx ) 1666{ 1667 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1668 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; 1669 GLfloat xoffset = (GLfloat)dPriv->x; 1670 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h; 1671 const GLfloat *v = ctx->Viewport._WindowMap.m; 1672 1673 float_ui32_type tx; 1674 float_ui32_type ty; 1675 1676 tx.f = v[MAT_TX] + xoffset + SUBPIXEL_X; 1677 ty.f = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y; 1678 1679 if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != tx.ui32 || 1680 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != ty.ui32 ) 1681 { 1682 /* Note: this should also modify whatever data the context reset 1683 * code uses... 1684 */ 1685 R200_STATECHANGE( rmesa, vpt ); 1686 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32; 1687 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32; 1688 1689 /* update polygon stipple x/y screen offset */ 1690 { 1691 GLuint stx, sty; 1692 GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC]; 1693 1694 m &= ~(R200_STIPPLE_X_OFFSET_MASK | 1695 R200_STIPPLE_Y_OFFSET_MASK); 1696 1697 /* add magic offsets, then invert */ 1698 stx = 31 - ((rmesa->dri.drawable->x - 1) & R200_STIPPLE_COORD_MASK); 1699 sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1) 1700 & R200_STIPPLE_COORD_MASK); 1701 1702 m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) | 1703 (sty << R200_STIPPLE_Y_OFFSET_SHIFT)); 1704 1705 if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) { 1706 R200_STATECHANGE( rmesa, msc ); 1707 rmesa->hw.msc.cmd[MSC_RE_MISC] = m; 1708 } 1709 } 1710 } 1711 1712 r200UpdateScissor( ctx ); 1713} 1714 1715 1716 1717/* ============================================================= 1718 * Miscellaneous 1719 */ 1720 1721static void r200ClearColor( GLcontext *ctx, const GLfloat c[4] ) 1722{ 1723 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1724 GLubyte color[4]; 1725 CLAMPED_FLOAT_TO_UBYTE(color[0], c[0]); 1726 CLAMPED_FLOAT_TO_UBYTE(color[1], c[1]); 1727 CLAMPED_FLOAT_TO_UBYTE(color[2], c[2]); 1728 CLAMPED_FLOAT_TO_UBYTE(color[3], c[3]); 1729 rmesa->state.color.clear = r200PackColor( rmesa->r200Screen->cpp, 1730 color[0], color[1], 1731 color[2], color[3] ); 1732} 1733 1734 1735static void r200RenderMode( GLcontext *ctx, GLenum mode ) 1736{ 1737 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1738 FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) ); 1739} 1740 1741 1742static GLuint r200_rop_tab[] = { 1743 R200_ROP_CLEAR, 1744 R200_ROP_AND, 1745 R200_ROP_AND_REVERSE, 1746 R200_ROP_COPY, 1747 R200_ROP_AND_INVERTED, 1748 R200_ROP_NOOP, 1749 R200_ROP_XOR, 1750 R200_ROP_OR, 1751 R200_ROP_NOR, 1752 R200_ROP_EQUIV, 1753 R200_ROP_INVERT, 1754 R200_ROP_OR_REVERSE, 1755 R200_ROP_COPY_INVERTED, 1756 R200_ROP_OR_INVERTED, 1757 R200_ROP_NAND, 1758 R200_ROP_SET, 1759}; 1760 1761static void r200LogicOpCode( GLcontext *ctx, GLenum opcode ) 1762{ 1763 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1764 GLuint rop = (GLuint)opcode - GL_CLEAR; 1765 1766 ASSERT( rop < 16 ); 1767 1768 R200_STATECHANGE( rmesa, msk ); 1769 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop]; 1770} 1771 1772 1773void r200SetCliprects( r200ContextPtr rmesa, GLenum mode ) 1774{ 1775 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; 1776 1777 switch ( mode ) { 1778 case GL_FRONT_LEFT: 1779 rmesa->numClipRects = dPriv->numClipRects; 1780 rmesa->pClipRects = dPriv->pClipRects; 1781 break; 1782 case GL_BACK_LEFT: 1783 /* Can't ignore 2d windows if we are page flipping. 1784 */ 1785 if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) { 1786 rmesa->numClipRects = dPriv->numClipRects; 1787 rmesa->pClipRects = dPriv->pClipRects; 1788 } 1789 else { 1790 rmesa->numClipRects = dPriv->numBackClipRects; 1791 rmesa->pClipRects = dPriv->pBackClipRects; 1792 } 1793 break; 1794 default: 1795 fprintf(stderr, "bad mode in r200SetCliprects\n"); 1796 return; 1797 } 1798 1799 if (rmesa->state.scissor.enabled) 1800 r200RecalcScissorRects( rmesa ); 1801} 1802 1803 1804static void r200DrawBuffer( GLcontext *ctx, GLenum mode ) 1805{ 1806 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1807 1808 if (R200_DEBUG & DEBUG_DRI) 1809 fprintf(stderr, "%s %s\n", __FUNCTION__, 1810 _mesa_lookup_enum_by_nr( mode )); 1811 1812 R200_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */ 1813 1814 /* 1815 * _ColorDrawBufferMask is easier to cope with than <mode>. 1816 * Check for software fallback, update cliprects. 1817 */ 1818 switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) { 1819 case BUFFER_BIT_FRONT_LEFT: 1820 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE ); 1821 r200SetCliprects( rmesa, GL_FRONT_LEFT ); 1822 break; 1823 case BUFFER_BIT_BACK_LEFT: 1824 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE ); 1825 r200SetCliprects( rmesa, GL_BACK_LEFT ); 1826 break; 1827 default: 1828 /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */ 1829 FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE ); 1830 return; 1831 } 1832 1833 /* We'll set the drawing engine's offset/pitch parameters later 1834 * when we update other state. 1835 */ 1836} 1837 1838 1839static void r200ReadBuffer( GLcontext *ctx, GLenum mode ) 1840{ 1841 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */ 1842} 1843 1844/* ============================================================= 1845 * State enable/disable 1846 */ 1847 1848static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state ) 1849{ 1850 r200ContextPtr rmesa = R200_CONTEXT(ctx); 1851 GLuint p, flag; 1852 1853 if ( R200_DEBUG & DEBUG_STATE ) 1854 fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__, 1855 _mesa_lookup_enum_by_nr( cap ), 1856 state ? "GL_TRUE" : "GL_FALSE" ); 1857 1858 switch ( cap ) { 1859 /* Fast track this one... 1860 */ 1861 case GL_TEXTURE_1D: 1862 case GL_TEXTURE_2D: 1863 case GL_TEXTURE_3D: 1864 break; 1865 1866 case GL_ALPHA_TEST: 1867 R200_STATECHANGE( rmesa, ctx ); 1868 if (state) { 1869 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE; 1870 } else { 1871 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE; 1872 } 1873 break; 1874 1875 case GL_BLEND: 1876 case GL_COLOR_LOGIC_OP: 1877 r200_set_blend_state( ctx ); 1878 break; 1879 1880 case GL_CLIP_PLANE0: 1881 case GL_CLIP_PLANE1: 1882 case GL_CLIP_PLANE2: 1883 case GL_CLIP_PLANE3: 1884 case GL_CLIP_PLANE4: 1885 case GL_CLIP_PLANE5: 1886 p = cap-GL_CLIP_PLANE0; 1887 R200_STATECHANGE( rmesa, tcl ); 1888 if (state) { 1889 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p); 1890 r200ClipPlane( ctx, cap, NULL ); 1891 } 1892 else { 1893 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p); 1894 } 1895 break; 1896 1897 case GL_COLOR_MATERIAL: 1898 r200ColorMaterial( ctx, 0, 0 ); 1899 r200UpdateMaterial( ctx ); 1900 break; 1901 1902 case GL_CULL_FACE: 1903 r200CullFace( ctx, 0 ); 1904 break; 1905 1906 case GL_DEPTH_TEST: 1907 R200_STATECHANGE(rmesa, ctx ); 1908 if ( state ) { 1909 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE; 1910 } else { 1911 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE; 1912 } 1913 break; 1914 1915 case GL_DITHER: 1916 R200_STATECHANGE(rmesa, ctx ); 1917 if ( state ) { 1918 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE; 1919 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->state.color.roundEnable; 1920 } else { 1921 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE; 1922 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable; 1923 } 1924 break; 1925 1926 case GL_FOG: 1927 R200_STATECHANGE(rmesa, ctx ); 1928 if ( state ) { 1929 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE; 1930 r200Fogfv( ctx, GL_FOG_MODE, NULL ); 1931 } else { 1932 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE; 1933 R200_STATECHANGE(rmesa, tcl); 1934 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK; 1935 } 1936 r200UpdateSpecular( ctx ); /* for PK_SPEC */ 1937 if (rmesa->TclFallback) 1938 r200ChooseVertexState( ctx ); 1939 _mesa_allow_light_in_model( ctx, !state ); 1940 break; 1941 1942 case GL_LIGHT0: 1943 case GL_LIGHT1: 1944 case GL_LIGHT2: 1945 case GL_LIGHT3: 1946 case GL_LIGHT4: 1947 case GL_LIGHT5: 1948 case GL_LIGHT6: 1949 case GL_LIGHT7: 1950 R200_STATECHANGE(rmesa, tcl); 1951 p = cap - GL_LIGHT0; 1952 if (p&1) 1953 flag = (R200_LIGHT_1_ENABLE | 1954 R200_LIGHT_1_ENABLE_AMBIENT | 1955 R200_LIGHT_1_ENABLE_SPECULAR); 1956 else 1957 flag = (R200_LIGHT_0_ENABLE | 1958 R200_LIGHT_0_ENABLE_AMBIENT | 1959 R200_LIGHT_0_ENABLE_SPECULAR); 1960 1961 if (state) 1962 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag; 1963 else 1964 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag; 1965 1966 /* 1967 */ 1968 update_light_colors( ctx, p ); 1969 break; 1970 1971 case GL_LIGHTING: 1972 r200UpdateSpecular(ctx); 1973 /* for reflection map fixup - might set recheck_texgen for all units too */ 1974 rmesa->NewGLState |= _NEW_TEXTURE; 1975 break; 1976 1977 case GL_LINE_SMOOTH: 1978 R200_STATECHANGE( rmesa, ctx ); 1979 if ( state ) { 1980 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE; 1981 } else { 1982 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE; 1983 } 1984 break; 1985 1986 case GL_LINE_STIPPLE: 1987 R200_STATECHANGE( rmesa, set ); 1988 if ( state ) { 1989 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE; 1990 } else { 1991 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE; 1992 } 1993 break; 1994 1995 case GL_NORMALIZE: 1996 R200_STATECHANGE( rmesa, tcl ); 1997 if ( state ) { 1998 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS; 1999 } else { 2000 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS; 2001 } 2002 break; 2003 2004 /* Pointsize registers on r200 only work for point sprites, and point smooth 2005 * doesn't work for point sprites (and isn't needed for 1.0 sized aa points). 2006 * In any case, setting pointmin == pointsizemax == 1.0 for aa points 2007 * is enough to satisfy conform. 2008 */ 2009 case GL_POINT_SMOOTH: 2010 break; 2011 2012 /* These don't really do anything, as we don't use the 3vtx 2013 * primitives yet. 2014 */ 2015#if 0 2016 case GL_POLYGON_OFFSET_POINT: 2017 R200_STATECHANGE( rmesa, set ); 2018 if ( state ) { 2019 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT; 2020 } else { 2021 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT; 2022 } 2023 break; 2024 2025 case GL_POLYGON_OFFSET_LINE: 2026 R200_STATECHANGE( rmesa, set ); 2027 if ( state ) { 2028 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE; 2029 } else { 2030 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE; 2031 } 2032 break; 2033#endif 2034 2035 case GL_POLYGON_OFFSET_FILL: 2036 R200_STATECHANGE( rmesa, set ); 2037 if ( state ) { 2038 rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI; 2039 } else { 2040 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI; 2041 } 2042 break; 2043 2044 case GL_POLYGON_SMOOTH: 2045 R200_STATECHANGE( rmesa, ctx ); 2046 if ( state ) { 2047 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY; 2048 } else { 2049 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY; 2050 } 2051 break; 2052 2053 case GL_POLYGON_STIPPLE: 2054 R200_STATECHANGE(rmesa, set ); 2055 if ( state ) { 2056 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE; 2057 } else { 2058 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE; 2059 } 2060 break; 2061 2062 case GL_RESCALE_NORMAL_EXT: { 2063 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state; 2064 R200_STATECHANGE( rmesa, tcl ); 2065 if ( tmp ) { 2066 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS; 2067 } else { 2068 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS; 2069 } 2070 break; 2071 } 2072 2073 case GL_SCISSOR_TEST: 2074 R200_FIREVERTICES( rmesa ); 2075 rmesa->state.scissor.enabled = state; 2076 r200UpdateScissor( ctx ); 2077 break; 2078 2079 case GL_STENCIL_TEST: 2080 if ( rmesa->state.stencil.hwBuffer ) { 2081 R200_STATECHANGE( rmesa, ctx ); 2082 if ( state ) { 2083 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE; 2084 } else { 2085 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE; 2086 } 2087 } else { 2088 FALLBACK( rmesa, R200_FALLBACK_STENCIL, state ); 2089 } 2090 break; 2091 2092 case GL_TEXTURE_GEN_Q: 2093 case GL_TEXTURE_GEN_R: 2094 case GL_TEXTURE_GEN_S: 2095 case GL_TEXTURE_GEN_T: 2096 /* Picked up in r200UpdateTextureState. 2097 */ 2098 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE; 2099 break; 2100 2101 case GL_COLOR_SUM_EXT: 2102 r200UpdateSpecular ( ctx ); 2103 break; 2104 2105 case GL_VERTEX_PROGRAM_ARB: 2106 if (!state) { 2107 GLuint i; 2108 rmesa->curr_vp_hw = NULL; 2109 R200_STATECHANGE( rmesa, vap ); 2110 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE; 2111 /* mark all tcl atoms (tcl vector state got overwritten) dirty 2112 not sure about tcl scalar state - we need at least grd 2113 with vert progs too. 2114 ucp looks like it doesn't get overwritten (may even work 2115 with vp for pos-invariant progs if we're lucky) */ 2116 R200_STATECHANGE( rmesa, mtl[0] ); 2117 R200_STATECHANGE( rmesa, mtl[1] ); 2118 R200_STATECHANGE( rmesa, fog ); 2119 R200_STATECHANGE( rmesa, glt ); 2120 R200_STATECHANGE( rmesa, eye ); 2121 for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++) { 2122 R200_STATECHANGE( rmesa, mat[i] ); 2123 } 2124 for (i = 0 ; i < 8; i++) { 2125 R200_STATECHANGE( rmesa, lit[i] ); 2126 } 2127 R200_STATECHANGE( rmesa, tcl ); 2128 for (i = 0; i <= ctx->Const.MaxClipPlanes; i++) { 2129 if (ctx->Transform.ClipPlanesEnabled & (1 << i)) { 2130 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0 << i); 2131 } 2132/* else { 2133 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i); 2134 }*/ 2135 } 2136 /* FIXME: ugly as hell. need to call everything which might change tcl_output_vtxfmt0/1 and compsel */ 2137 r200UpdateSpecular( ctx ); 2138 r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL ); 2139#if 1 2140 /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM), 2141 but without it doom3 locks up at always the same places. Why? */ 2142 /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before 2143 accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */ 2144 r200UpdateTextureState( ctx ); 2145 /* if we call r200UpdateTextureState we need the code below because we are calling it with 2146 non-current derived enabled values which may revert the state atoms for frag progs even when 2147 they already got disabled... ugh 2148 Should really figure out why we need to call r200UpdateTextureState in the first place */ 2149 GLuint unit; 2150 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) { 2151 R200_STATECHANGE( rmesa, pix[unit] ); 2152 R200_STATECHANGE( rmesa, tex[unit] ); 2153 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &= 2154 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE); 2155 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT; 2156 /* need to guard this with drmSupportsFragmentShader? Should never get here if 2157 we don't announce ATI_fs, right? */ 2158 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0; 2159 } 2160 R200_STATECHANGE( rmesa, cst ); 2161 R200_STATECHANGE( rmesa, tf ); 2162 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0; 2163#endif 2164 } 2165 else { 2166 /* picked up later */ 2167 } 2168 break; 2169 2170 case GL_FRAGMENT_SHADER_ATI: 2171 if ( !state ) { 2172 /* restore normal tex env colors and make sure tex env combine will get updated 2173 mark env atoms dirty (as their data was overwritten by afs even 2174 if they didn't change) and restore tex coord routing */ 2175 GLuint unit; 2176 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) { 2177 R200_STATECHANGE( rmesa, pix[unit] ); 2178 R200_STATECHANGE( rmesa, tex[unit] ); 2179 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &= 2180 ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE); 2181 rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT; 2182 /* need to guard this with drmSupportsFragmentShader? Should never get here if 2183 we don't announce ATI_fs, right? */ 2184 rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0; 2185 } 2186 R200_STATECHANGE( rmesa, cst ); 2187 R200_STATECHANGE( rmesa, tf ); 2188 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0; 2189 } 2190 else { 2191 /* need to mark this dirty as pix/tf atoms have overwritten the data 2192 even if the data in the atoms didn't change */ 2193 R200_STATECHANGE( rmesa, atf ); 2194 R200_STATECHANGE( rmesa, afs[1] ); 2195 /* everything else picked up in r200UpdateTextureState hopefully */ 2196 } 2197 break; 2198 default: 2199 return; 2200 } 2201} 2202 2203 2204void r200LightingSpaceChange( GLcontext *ctx ) 2205{ 2206 r200ContextPtr rmesa = R200_CONTEXT(ctx); 2207 GLboolean tmp; 2208 2209 if (R200_DEBUG & DEBUG_STATE) 2210 fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords, 2211 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]); 2212 2213 if (ctx->_NeedEyeCoords) 2214 tmp = ctx->Transform.RescaleNormals; 2215 else 2216 tmp = !ctx->Transform.RescaleNormals; 2217 2218 R200_STATECHANGE( rmesa, tcl ); 2219 if ( tmp ) { 2220 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS; 2221 } else { 2222 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS; 2223 } 2224 2225 if (R200_DEBUG & DEBUG_STATE) 2226 fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords, 2227 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]); 2228} 2229 2230/* ============================================================= 2231 * Deferred state management - matrices, textures, other? 2232 */ 2233 2234 2235 2236 2237static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx ) 2238{ 2239 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0; 2240 int i; 2241 2242 2243 for (i = 0 ; i < 4 ; i++) { 2244 *dest++ = src[i]; 2245 *dest++ = src[i+4]; 2246 *dest++ = src[i+8]; 2247 *dest++ = src[i+12]; 2248 } 2249 2250 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); 2251} 2252 2253static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx ) 2254{ 2255 float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0; 2256 memcpy(dest, src, 16*sizeof(float)); 2257 R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); 2258} 2259 2260 2261static void update_texturematrix( GLcontext *ctx ) 2262{ 2263 r200ContextPtr rmesa = R200_CONTEXT( ctx ); 2264 GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]; 2265 GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]; 2266 int unit; 2267 2268 if (R200_DEBUG & DEBUG_STATE) 2269 fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__, 2270 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]); 2271 2272 rmesa->TexMatEnabled = 0; 2273 rmesa->TexMatCompSel = 0; 2274 2275 for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) { 2276 if (!ctx->Texture.Unit[unit]._ReallyEnabled) 2277 continue; 2278 2279 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) { 2280 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE| 2281 R200_TEXMAT_0_ENABLE) << unit; 2282 2283 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit; 2284 2285 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) { 2286 /* Need to preconcatenate any active texgen 2287 * obj/eyeplane matrices: 2288 */ 2289 _math_matrix_mul_matrix( &rmesa->tmpmat, 2290 ctx->TextureMatrixStack[unit].Top, 2291 &rmesa->TexGenMatrix[unit] ); 2292 upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit ); 2293 } 2294 else { 2295 upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m, 2296 R200_MTX_TEX0+unit ); 2297 } 2298 } 2299 else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) { 2300 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m, 2301 R200_MTX_TEX0+unit ); 2302 } 2303 } 2304 2305 tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled); 2306 if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]) { 2307 R200_STATECHANGE(rmesa, tcg); 2308 rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc; 2309 } 2310 2311 compsel &= ~R200_OUTPUT_TEX_MASK; 2312 compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel; 2313 if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) { 2314 R200_STATECHANGE(rmesa, vtx); 2315 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel; 2316 } 2317} 2318 2319 2320 2321/** 2322 * Tell the card where to render (offset, pitch). 2323 * Effected by glDrawBuffer, etc 2324 */ 2325void 2326r200UpdateDrawBuffer(GLcontext *ctx) 2327{ 2328 r200ContextPtr rmesa = R200_CONTEXT(ctx); 2329 struct gl_framebuffer *fb = ctx->DrawBuffer; 2330 driRenderbuffer *drb; 2331 2332 if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) { 2333 /* draw to front */ 2334 drb = (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer; 2335 } 2336 else if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT) { 2337 /* draw to back */ 2338 drb = (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer; 2339 } 2340 else { 2341 /* drawing to multiple buffers, or none */ 2342 return; 2343 } 2344 2345 assert(drb); 2346 assert(drb->flippedPitch); 2347 2348 R200_STATECHANGE( rmesa, ctx ); 2349 2350 /* Note: we used the (possibly) page-flipped values */ 2351 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] 2352 = ((drb->flippedOffset + rmesa->r200Screen->fbLocation) 2353 & R200_COLOROFFSET_MASK); 2354 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch; 2355 if (rmesa->sarea->tiling_enabled) { 2356 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE; 2357 } 2358} 2359 2360 2361 2362void r200ValidateState( GLcontext *ctx ) 2363{ 2364 r200ContextPtr rmesa = R200_CONTEXT(ctx); 2365 GLuint new_state = rmesa->NewGLState; 2366 2367 if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { 2368 r200UpdateDrawBuffer(ctx); 2369 } 2370 2371 if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM)) { 2372 r200UpdateTextureState( ctx ); 2373 new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */ 2374 r200UpdateLocalViewer( ctx ); 2375 } 2376 2377/* FIXME: don't really need most of these when vertex progs are enabled */ 2378 2379 /* Need an event driven matrix update? 2380 */ 2381 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) 2382 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP ); 2383 2384 /* Need these for lighting (shouldn't upload otherwise) 2385 */ 2386 if (new_state & (_NEW_MODELVIEW)) { 2387 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV ); 2388 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV ); 2389 } 2390 2391 /* Does this need to be triggered on eg. modelview for 2392 * texgen-derived objplane/eyeplane matrices? 2393 */ 2394 if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) { 2395 update_texturematrix( ctx ); 2396 } 2397 2398 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) { 2399 update_light( ctx ); 2400 } 2401 2402 /* emit all active clip planes if projection matrix changes. 2403 */ 2404 if (new_state & (_NEW_PROJECTION)) { 2405 if (ctx->Transform.ClipPlanesEnabled) 2406 r200UpdateClipPlanes( ctx ); 2407 } 2408 2409 if (new_state & (_NEW_PROGRAM| 2410 /* need to test for pretty much anything due to possible parameter bindings */ 2411 _NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM| 2412 _NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX| 2413 _NEW_FOG|_NEW_POINT|_NEW_TRACK_MATRIX)) { 2414 if (ctx->VertexProgram._Enabled) { 2415 r200SetupVertexProg( ctx ); 2416 } 2417 else TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, 0); 2418 } 2419 2420 rmesa->NewGLState = 0; 2421} 2422 2423 2424static void r200InvalidateState( GLcontext *ctx, GLuint new_state ) 2425{ 2426 _swrast_InvalidateState( ctx, new_state ); 2427 _swsetup_InvalidateState( ctx, new_state ); 2428 _ac_InvalidateState( ctx, new_state ); 2429 _tnl_InvalidateState( ctx, new_state ); 2430 _ae_invalidate_state( ctx, new_state ); 2431 R200_CONTEXT(ctx)->NewGLState |= new_state; 2432 r200VtxfmtInvalidate( ctx ); 2433} 2434 2435/* A hack. The r200 can actually cope just fine with materials 2436 * between begin/ends, so fix this. But how ? 2437 */ 2438static GLboolean check_material( GLcontext *ctx ) 2439{ 2440 TNLcontext *tnl = TNL_CONTEXT(ctx); 2441 GLint i; 2442 2443 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT; 2444 i < _TNL_ATTRIB_MAT_BACK_INDEXES; 2445 i++) 2446 if (tnl->vb.AttribPtr[i] && 2447 tnl->vb.AttribPtr[i]->stride) 2448 return GL_TRUE; 2449 2450 return GL_FALSE; 2451} 2452 2453static void r200WrapRunPipeline( GLcontext *ctx ) 2454{ 2455 r200ContextPtr rmesa = R200_CONTEXT(ctx); 2456 GLboolean has_material; 2457 2458 if (0) 2459 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState); 2460 2461 /* Validate state: 2462 */ 2463 if (rmesa->NewGLState) 2464 r200ValidateState( ctx ); 2465 2466 has_material = (ctx->Light.Enabled && check_material( ctx )); 2467 2468 if (has_material) { 2469 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE ); 2470 } 2471 2472 /* Run the pipeline. 2473 */ 2474 _tnl_run_pipeline( ctx ); 2475 2476 if (has_material) { 2477 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE ); 2478 } 2479} 2480 2481 2482/* Initialize the driver's state functions. 2483 */ 2484void r200InitStateFuncs( struct dd_function_table *functions ) 2485{ 2486 functions->UpdateState = r200InvalidateState; 2487 functions->LightingSpaceChange = r200LightingSpaceChange; 2488 2489 functions->DrawBuffer = r200DrawBuffer; 2490 functions->ReadBuffer = r200ReadBuffer; 2491 2492 functions->AlphaFunc = r200AlphaFunc; 2493 functions->BlendColor = r200BlendColor; 2494 functions->BlendEquationSeparate = r200BlendEquationSeparate; 2495 functions->BlendFuncSeparate = r200BlendFuncSeparate; 2496 functions->ClearColor = r200ClearColor; 2497 functions->ClearDepth = r200ClearDepth; 2498 functions->ClearIndex = NULL; 2499 functions->ClearStencil = r200ClearStencil; 2500 functions->ClipPlane = r200ClipPlane; 2501 functions->ColorMask = r200ColorMask; 2502 functions->CullFace = r200CullFace; 2503 functions->DepthFunc = r200DepthFunc; 2504 functions->DepthMask = r200DepthMask; 2505 functions->DepthRange = r200DepthRange; 2506 functions->Enable = r200Enable; 2507 functions->Fogfv = r200Fogfv; 2508 functions->FrontFace = r200FrontFace; 2509 functions->Hint = NULL; 2510 functions->IndexMask = NULL; 2511 functions->LightModelfv = r200LightModelfv; 2512 functions->Lightfv = r200Lightfv; 2513 functions->LineStipple = r200LineStipple; 2514 functions->LineWidth = r200LineWidth; 2515 functions->LogicOpcode = r200LogicOpCode; 2516 functions->PolygonMode = r200PolygonMode; 2517 functions->PolygonOffset = r200PolygonOffset; 2518 functions->PolygonStipple = r200PolygonStipple; 2519 functions->PointSize = r200PointSize; 2520 functions->RenderMode = r200RenderMode; 2521 functions->Scissor = r200Scissor; 2522 functions->ShadeModel = r200ShadeModel; 2523 functions->StencilFuncSeparate = r200StencilFuncSeparate; 2524 functions->StencilMaskSeparate = r200StencilMaskSeparate; 2525 functions->StencilOpSeparate = r200StencilOpSeparate; 2526 functions->Viewport = r200Viewport; 2527 2528 /* Swrast hooks for imaging extensions: 2529 */ 2530 functions->CopyColorTable = _swrast_CopyColorTable; 2531 functions->CopyColorSubTable = _swrast_CopyColorSubTable; 2532 functions->CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; 2533 functions->CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; 2534} 2535 2536 2537void r200InitTnlFuncs( GLcontext *ctx ) 2538{ 2539 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial; 2540 TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline; 2541} 2542