radeon_state.c revision ecadb51bbcb972a79f3ed79e65a7986b9396e757
1/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.c,v 1.8 2002/12/16 16:18:58 dawes Exp $ */ 2/************************************************************************** 3 4Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California. 5 6All Rights Reserved. 7 8Permission is hereby granted, free of charge, to any person obtaining 9a copy of this software and associated documentation files (the 10"Software"), to deal in the Software without restriction, including 11without limitation the rights to use, copy, modify, merge, publish, 12distribute, sublicense, and/or sell copies of the Software, and to 13permit persons to whom the Software is furnished to do so, subject to 14the following conditions: 15 16The above copyright notice and this permission notice (including the 17next paragraph) shall be included in all copies or substantial 18portions of the Software. 19 20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE 24LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 25OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 26WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 28**************************************************************************/ 29 30/* 31 * Authors: 32 * Gareth Hughes <gareth@valinux.com> 33 * Keith Whitwell <keith@tungstengraphics.com> 34 */ 35 36#include "main/glheader.h" 37#include "main/imports.h" 38#include "main/api_arrayelt.h" 39#include "main/enums.h" 40#include "main/light.h" 41#include "main/state.h" 42#include "main/context.h" 43#include "main/framebuffer.h" 44 45#include "vbo/vbo.h" 46#include "tnl/tnl.h" 47#include "tnl/t_pipeline.h" 48#include "swrast_setup/swrast_setup.h" 49 50#include "radeon_context.h" 51#include "radeon_ioctl.h" 52#include "radeon_state.h" 53#include "radeon_tcl.h" 54#include "radeon_tex.h" 55#include "radeon_swtcl.h" 56#include "drirenderbuffer.h" 57 58static void radeonUpdateSpecular( GLcontext *ctx ); 59 60/* ============================================================= 61 * Alpha blending 62 */ 63 64static void radeonAlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref ) 65{ 66 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 67 int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC]; 68 GLubyte refByte; 69 70 CLAMPED_FLOAT_TO_UBYTE(refByte, ref); 71 72 RADEON_STATECHANGE( rmesa, ctx ); 73 74 pp_misc &= ~(RADEON_ALPHA_TEST_OP_MASK | RADEON_REF_ALPHA_MASK); 75 pp_misc |= (refByte & RADEON_REF_ALPHA_MASK); 76 77 switch ( func ) { 78 case GL_NEVER: 79 pp_misc |= RADEON_ALPHA_TEST_FAIL; 80 break; 81 case GL_LESS: 82 pp_misc |= RADEON_ALPHA_TEST_LESS; 83 break; 84 case GL_EQUAL: 85 pp_misc |= RADEON_ALPHA_TEST_EQUAL; 86 break; 87 case GL_LEQUAL: 88 pp_misc |= RADEON_ALPHA_TEST_LEQUAL; 89 break; 90 case GL_GREATER: 91 pp_misc |= RADEON_ALPHA_TEST_GREATER; 92 break; 93 case GL_NOTEQUAL: 94 pp_misc |= RADEON_ALPHA_TEST_NEQUAL; 95 break; 96 case GL_GEQUAL: 97 pp_misc |= RADEON_ALPHA_TEST_GEQUAL; 98 break; 99 case GL_ALWAYS: 100 pp_misc |= RADEON_ALPHA_TEST_PASS; 101 break; 102 } 103 104 rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc; 105} 106 107static void radeonBlendEquationSeparate( GLcontext *ctx, 108 GLenum modeRGB, GLenum modeA ) 109{ 110 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 111 GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~RADEON_COMB_FCN_MASK; 112 GLboolean fallback = GL_FALSE; 113 114 assert( modeRGB == modeA ); 115 116 switch ( modeRGB ) { 117 case GL_FUNC_ADD: 118 case GL_LOGIC_OP: 119 b |= RADEON_COMB_FCN_ADD_CLAMP; 120 break; 121 122 case GL_FUNC_SUBTRACT: 123 b |= RADEON_COMB_FCN_SUB_CLAMP; 124 break; 125 126 default: 127 if (ctx->Color.BlendEnabled) 128 fallback = GL_TRUE; 129 else 130 b |= RADEON_COMB_FCN_ADD_CLAMP; 131 break; 132 } 133 134 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, fallback ); 135 if ( !fallback ) { 136 RADEON_STATECHANGE( rmesa, ctx ); 137 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b; 138 if ( (ctx->Color.ColorLogicOpEnabled || (ctx->Color.BlendEnabled 139 && ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) ) { 140 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE; 141 } else { 142 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE; 143 } 144 } 145} 146 147static void radeonBlendFuncSeparate( GLcontext *ctx, 148 GLenum sfactorRGB, GLenum dfactorRGB, 149 GLenum sfactorA, GLenum dfactorA ) 150{ 151 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 152 GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & 153 ~(RADEON_SRC_BLEND_MASK | RADEON_DST_BLEND_MASK); 154 GLboolean fallback = GL_FALSE; 155 156 switch ( ctx->Color.BlendSrcRGB ) { 157 case GL_ZERO: 158 b |= RADEON_SRC_BLEND_GL_ZERO; 159 break; 160 case GL_ONE: 161 b |= RADEON_SRC_BLEND_GL_ONE; 162 break; 163 case GL_DST_COLOR: 164 b |= RADEON_SRC_BLEND_GL_DST_COLOR; 165 break; 166 case GL_ONE_MINUS_DST_COLOR: 167 b |= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR; 168 break; 169 case GL_SRC_COLOR: 170 b |= RADEON_SRC_BLEND_GL_SRC_COLOR; 171 break; 172 case GL_ONE_MINUS_SRC_COLOR: 173 b |= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR; 174 break; 175 case GL_SRC_ALPHA: 176 b |= RADEON_SRC_BLEND_GL_SRC_ALPHA; 177 break; 178 case GL_ONE_MINUS_SRC_ALPHA: 179 b |= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA; 180 break; 181 case GL_DST_ALPHA: 182 b |= RADEON_SRC_BLEND_GL_DST_ALPHA; 183 break; 184 case GL_ONE_MINUS_DST_ALPHA: 185 b |= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA; 186 break; 187 case GL_SRC_ALPHA_SATURATE: 188 b |= RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE; 189 break; 190 case GL_CONSTANT_COLOR: 191 case GL_ONE_MINUS_CONSTANT_COLOR: 192 case GL_CONSTANT_ALPHA: 193 case GL_ONE_MINUS_CONSTANT_ALPHA: 194 if (ctx->Color.BlendEnabled) 195 fallback = GL_TRUE; 196 else 197 b |= RADEON_SRC_BLEND_GL_ONE; 198 break; 199 default: 200 break; 201 } 202 203 switch ( ctx->Color.BlendDstRGB ) { 204 case GL_ZERO: 205 b |= RADEON_DST_BLEND_GL_ZERO; 206 break; 207 case GL_ONE: 208 b |= RADEON_DST_BLEND_GL_ONE; 209 break; 210 case GL_SRC_COLOR: 211 b |= RADEON_DST_BLEND_GL_SRC_COLOR; 212 break; 213 case GL_ONE_MINUS_SRC_COLOR: 214 b |= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_COLOR; 215 break; 216 case GL_SRC_ALPHA: 217 b |= RADEON_DST_BLEND_GL_SRC_ALPHA; 218 break; 219 case GL_ONE_MINUS_SRC_ALPHA: 220 b |= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA; 221 break; 222 case GL_DST_COLOR: 223 b |= RADEON_DST_BLEND_GL_DST_COLOR; 224 break; 225 case GL_ONE_MINUS_DST_COLOR: 226 b |= RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR; 227 break; 228 case GL_DST_ALPHA: 229 b |= RADEON_DST_BLEND_GL_DST_ALPHA; 230 break; 231 case GL_ONE_MINUS_DST_ALPHA: 232 b |= RADEON_DST_BLEND_GL_ONE_MINUS_DST_ALPHA; 233 break; 234 case GL_CONSTANT_COLOR: 235 case GL_ONE_MINUS_CONSTANT_COLOR: 236 case GL_CONSTANT_ALPHA: 237 case GL_ONE_MINUS_CONSTANT_ALPHA: 238 if (ctx->Color.BlendEnabled) 239 fallback = GL_TRUE; 240 else 241 b |= RADEON_DST_BLEND_GL_ZERO; 242 break; 243 default: 244 break; 245 } 246 247 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, fallback ); 248 if ( !fallback ) { 249 RADEON_STATECHANGE( rmesa, ctx ); 250 rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b; 251 } 252} 253 254 255/* ============================================================= 256 * Depth testing 257 */ 258 259static void radeonDepthFunc( GLcontext *ctx, GLenum func ) 260{ 261 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 262 263 RADEON_STATECHANGE( rmesa, ctx ); 264 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_TEST_MASK; 265 266 switch ( ctx->Depth.Func ) { 267 case GL_NEVER: 268 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEVER; 269 break; 270 case GL_LESS: 271 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LESS; 272 break; 273 case GL_EQUAL: 274 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_EQUAL; 275 break; 276 case GL_LEQUAL: 277 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LEQUAL; 278 break; 279 case GL_GREATER: 280 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GREATER; 281 break; 282 case GL_NOTEQUAL: 283 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEQUAL; 284 break; 285 case GL_GEQUAL: 286 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GEQUAL; 287 break; 288 case GL_ALWAYS: 289 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_ALWAYS; 290 break; 291 } 292} 293 294 295static void radeonDepthMask( GLcontext *ctx, GLboolean flag ) 296{ 297 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 298 RADEON_STATECHANGE( rmesa, ctx ); 299 300 if ( ctx->Depth.Mask ) { 301 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_WRITE_ENABLE; 302 } else { 303 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_WRITE_ENABLE; 304 } 305} 306 307static void radeonClearDepth( GLcontext *ctx, GLclampd d ) 308{ 309 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 310 GLuint format = (rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] & 311 RADEON_DEPTH_FORMAT_MASK); 312 313 switch ( format ) { 314 case RADEON_DEPTH_FORMAT_16BIT_INT_Z: 315 rmesa->state.depth.clear = d * 0x0000ffff; 316 break; 317 case RADEON_DEPTH_FORMAT_24BIT_INT_Z: 318 rmesa->state.depth.clear = d * 0x00ffffff; 319 break; 320 } 321} 322 323 324/* ============================================================= 325 * Fog 326 */ 327 328 329static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param ) 330{ 331 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 332 union { int i; float f; } c, d; 333 GLchan col[4]; 334 335 switch (pname) { 336 case GL_FOG_MODE: 337 if (!ctx->Fog.Enabled) 338 return; 339 RADEON_STATECHANGE(rmesa, tcl); 340 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK; 341 switch (ctx->Fog.Mode) { 342 case GL_LINEAR: 343 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_LINEAR; 344 break; 345 case GL_EXP: 346 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP; 347 break; 348 case GL_EXP2: 349 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP2; 350 break; 351 default: 352 return; 353 } 354 /* fallthrough */ 355 case GL_FOG_DENSITY: 356 case GL_FOG_START: 357 case GL_FOG_END: 358 if (!ctx->Fog.Enabled) 359 return; 360 c.i = rmesa->hw.fog.cmd[FOG_C]; 361 d.i = rmesa->hw.fog.cmd[FOG_D]; 362 switch (ctx->Fog.Mode) { 363 case GL_EXP: 364 c.f = 0.0; 365 /* While this is the opposite sign from the DDK, it makes the fog test 366 * pass, and matches r200. 367 */ 368 d.f = -ctx->Fog.Density; 369 break; 370 case GL_EXP2: 371 c.f = 0.0; 372 d.f = -(ctx->Fog.Density * ctx->Fog.Density); 373 break; 374 case GL_LINEAR: 375 if (ctx->Fog.Start == ctx->Fog.End) { 376 c.f = 1.0F; 377 d.f = 1.0F; 378 } else { 379 c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start); 380 /* While this is the opposite sign from the DDK, it makes the fog 381 * test pass, and matches r200. 382 */ 383 d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start); 384 } 385 break; 386 default: 387 break; 388 } 389 if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) { 390 RADEON_STATECHANGE( rmesa, fog ); 391 rmesa->hw.fog.cmd[FOG_C] = c.i; 392 rmesa->hw.fog.cmd[FOG_D] = d.i; 393 } 394 break; 395 case GL_FOG_COLOR: 396 RADEON_STATECHANGE( rmesa, ctx ); 397 UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color ); 398 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~RADEON_FOG_COLOR_MASK; 399 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= 400 radeonPackColor( 4, col[0], col[1], col[2], 0 ); 401 break; 402 case GL_FOG_COORD_SRC: 403 radeonUpdateSpecular( ctx ); 404 break; 405 default: 406 return; 407 } 408} 409 410 411/* ============================================================= 412 * Scissoring 413 */ 414 415 416static GLboolean intersect_rect( drm_clip_rect_t *out, 417 drm_clip_rect_t *a, 418 drm_clip_rect_t *b ) 419{ 420 *out = *a; 421 if ( b->x1 > out->x1 ) out->x1 = b->x1; 422 if ( b->y1 > out->y1 ) out->y1 = b->y1; 423 if ( b->x2 < out->x2 ) out->x2 = b->x2; 424 if ( b->y2 < out->y2 ) out->y2 = b->y2; 425 if ( out->x1 >= out->x2 ) return GL_FALSE; 426 if ( out->y1 >= out->y2 ) return GL_FALSE; 427 return GL_TRUE; 428} 429 430 431void radeonRecalcScissorRects( radeonContextPtr rmesa ) 432{ 433 drm_clip_rect_t *out; 434 int i; 435 436 /* Grow cliprect store? 437 */ 438 if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) { 439 while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) { 440 rmesa->state.scissor.numAllocedClipRects += 1; /* zero case */ 441 rmesa->state.scissor.numAllocedClipRects *= 2; 442 } 443 444 if (rmesa->state.scissor.pClipRects) 445 FREE(rmesa->state.scissor.pClipRects); 446 447 rmesa->state.scissor.pClipRects = 448 MALLOC( rmesa->state.scissor.numAllocedClipRects * 449 sizeof(drm_clip_rect_t) ); 450 451 if ( rmesa->state.scissor.pClipRects == NULL ) { 452 rmesa->state.scissor.numAllocedClipRects = 0; 453 return; 454 } 455 } 456 457 out = rmesa->state.scissor.pClipRects; 458 rmesa->state.scissor.numClipRects = 0; 459 460 for ( i = 0 ; i < rmesa->numClipRects ; i++ ) { 461 if ( intersect_rect( out, 462 &rmesa->pClipRects[i], 463 &rmesa->state.scissor.rect ) ) { 464 rmesa->state.scissor.numClipRects++; 465 out++; 466 } 467 } 468} 469 470 471static void radeonUpdateScissor( GLcontext *ctx ) 472{ 473 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 474 475 if ( rmesa->dri.drawable ) { 476 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; 477 478 int x = ctx->Scissor.X; 479 int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height; 480 int w = ctx->Scissor.X + ctx->Scissor.Width - 1; 481 int h = dPriv->h - ctx->Scissor.Y - 1; 482 483 rmesa->state.scissor.rect.x1 = x + dPriv->x; 484 rmesa->state.scissor.rect.y1 = y + dPriv->y; 485 rmesa->state.scissor.rect.x2 = w + dPriv->x + 1; 486 rmesa->state.scissor.rect.y2 = h + dPriv->y + 1; 487 488 radeonRecalcScissorRects( rmesa ); 489 } 490} 491 492 493static void radeonScissor( GLcontext *ctx, 494 GLint x, GLint y, GLsizei w, GLsizei h ) 495{ 496 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 497 498 if ( ctx->Scissor.Enabled ) { 499 RADEON_FIREVERTICES( rmesa ); /* don't pipeline cliprect changes */ 500 radeonUpdateScissor( ctx ); 501 } 502 503} 504 505 506/* ============================================================= 507 * Culling 508 */ 509 510static void radeonCullFace( GLcontext *ctx, GLenum unused ) 511{ 512 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 513 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL]; 514 GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL]; 515 516 s |= RADEON_FFACE_SOLID | RADEON_BFACE_SOLID; 517 t &= ~(RADEON_CULL_FRONT | RADEON_CULL_BACK); 518 519 if ( ctx->Polygon.CullFlag ) { 520 switch ( ctx->Polygon.CullFaceMode ) { 521 case GL_FRONT: 522 s &= ~RADEON_FFACE_SOLID; 523 t |= RADEON_CULL_FRONT; 524 break; 525 case GL_BACK: 526 s &= ~RADEON_BFACE_SOLID; 527 t |= RADEON_CULL_BACK; 528 break; 529 case GL_FRONT_AND_BACK: 530 s &= ~(RADEON_FFACE_SOLID | RADEON_BFACE_SOLID); 531 t |= (RADEON_CULL_FRONT | RADEON_CULL_BACK); 532 break; 533 } 534 } 535 536 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) { 537 RADEON_STATECHANGE(rmesa, set ); 538 rmesa->hw.set.cmd[SET_SE_CNTL] = s; 539 } 540 541 if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) { 542 RADEON_STATECHANGE(rmesa, tcl ); 543 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t; 544 } 545} 546 547static void radeonFrontFace( GLcontext *ctx, GLenum mode ) 548{ 549 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 550 551 RADEON_STATECHANGE( rmesa, set ); 552 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_FFACE_CULL_DIR_MASK; 553 554 RADEON_STATECHANGE( rmesa, tcl ); 555 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_CULL_FRONT_IS_CCW; 556 557 switch ( mode ) { 558 case GL_CW: 559 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CW; 560 break; 561 case GL_CCW: 562 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CCW; 563 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_CULL_FRONT_IS_CCW; 564 break; 565 } 566} 567 568 569/* ============================================================= 570 * Line state 571 */ 572static void radeonLineWidth( GLcontext *ctx, GLfloat widthf ) 573{ 574 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 575 576 RADEON_STATECHANGE( rmesa, lin ); 577 RADEON_STATECHANGE( rmesa, set ); 578 579 /* Line width is stored in U6.4 format. 580 */ 581 rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (GLuint)(widthf * 16.0); 582 if ( widthf > 1.0 ) { 583 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_WIDELINE_ENABLE; 584 } else { 585 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_WIDELINE_ENABLE; 586 } 587} 588 589static void radeonLineStipple( GLcontext *ctx, GLint factor, GLushort pattern ) 590{ 591 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 592 593 RADEON_STATECHANGE( rmesa, lin ); 594 rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] = 595 ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern)); 596} 597 598 599/* ============================================================= 600 * Masks 601 */ 602static void radeonColorMask( GLcontext *ctx, 603 GLboolean r, GLboolean g, 604 GLboolean b, GLboolean a ) 605{ 606 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 607 GLuint mask = radeonPackColor( rmesa->radeonScreen->cpp, 608 ctx->Color.ColorMask[RCOMP], 609 ctx->Color.ColorMask[GCOMP], 610 ctx->Color.ColorMask[BCOMP], 611 ctx->Color.ColorMask[ACOMP] ); 612 613 if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) { 614 RADEON_STATECHANGE( rmesa, msk ); 615 rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask; 616 } 617} 618 619 620/* ============================================================= 621 * Polygon state 622 */ 623 624static void radeonPolygonOffset( GLcontext *ctx, 625 GLfloat factor, GLfloat units ) 626{ 627 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 628 float_ui32_type constant = { units * rmesa->state.depth.scale }; 629 float_ui32_type factoru = { factor }; 630 631 RADEON_STATECHANGE( rmesa, zbs ); 632 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = factoru.ui32; 633 rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32; 634} 635 636static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask ) 637{ 638 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 639 GLuint i; 640 drm_radeon_stipple_t stipple; 641 642 /* Must flip pattern upside down. 643 */ 644 for ( i = 0 ; i < 32 ; i++ ) { 645 rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i]; 646 } 647 648 /* TODO: push this into cmd mechanism 649 */ 650 RADEON_FIREVERTICES( rmesa ); 651 LOCK_HARDWARE( rmesa ); 652 653 /* FIXME: Use window x,y offsets into stipple RAM. 654 */ 655 stipple.mask = rmesa->state.stipple.mask; 656 drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE, 657 &stipple, sizeof(drm_radeon_stipple_t) ); 658 UNLOCK_HARDWARE( rmesa ); 659} 660 661static void radeonPolygonMode( GLcontext *ctx, GLenum face, GLenum mode ) 662{ 663 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 664 GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0; 665 666 /* Can't generally do unfilled via tcl, but some good special 667 * cases work. 668 */ 669 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_UNFILLED, flag); 670 if (rmesa->TclFallback) { 671 radeonChooseRenderState( ctx ); 672 radeonChooseVertexState( ctx ); 673 } 674} 675 676 677/* ============================================================= 678 * Rendering attributes 679 * 680 * We really don't want to recalculate all this every time we bind a 681 * texture. These things shouldn't change all that often, so it makes 682 * sense to break them out of the core texture state update routines. 683 */ 684 685/* Examine lighting and texture state to determine if separate specular 686 * should be enabled. 687 */ 688static void radeonUpdateSpecular( GLcontext *ctx ) 689{ 690 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 691 u_int32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL]; 692 GLuint flag = 0; 693 694 RADEON_STATECHANGE( rmesa, tcl ); 695 696 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR; 697 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE; 698 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_SPEC; 699 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_DIFFUSE; 700 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE; 701 702 p &= ~RADEON_SPECULAR_ENABLE; 703 704 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_DIFFUSE_SPECULAR_COMBINE; 705 706 707 if (ctx->Light.Enabled && 708 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) { 709 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR; 710 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE; 711 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC; 712 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; 713 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE; 714 p |= RADEON_SPECULAR_ENABLE; 715 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= 716 ~RADEON_DIFFUSE_SPECULAR_COMBINE; 717 } 718 else if (ctx->Light.Enabled) { 719 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE; 720 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; 721 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE; 722 } else if (ctx->Fog.ColorSumEnabled ) { 723 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC; 724 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; 725 p |= RADEON_SPECULAR_ENABLE; 726 } else { 727 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE; 728 } 729 730 if (ctx->Fog.Enabled) { 731 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC; 732 if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH) { 733 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR; 734 /* Bizzare: have to leave lighting enabled to get fog. */ 735 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE; 736 } 737 else { 738 /* cannot do tcl fog factor calculation with fog coord source 739 * (send precomputed factors). Cannot use precomputed fog 740 * factors together with tcl spec light (need tcl fallback) */ 741 flag = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] & 742 RADEON_TCL_COMPUTE_SPECULAR) != 0; 743 } 744 } 745 746 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_FOGCOORDSPEC, flag); 747 748 if (NEED_SECONDARY_COLOR(ctx)) { 749 assert( (p & RADEON_SPECULAR_ENABLE) != 0 ); 750 } else { 751 assert( (p & RADEON_SPECULAR_ENABLE) == 0 ); 752 } 753 754 if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) { 755 RADEON_STATECHANGE( rmesa, ctx ); 756 rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p; 757 } 758 759 /* Update vertex/render formats 760 */ 761 if (rmesa->TclFallback) { 762 radeonChooseRenderState( ctx ); 763 radeonChooseVertexState( ctx ); 764 } 765} 766 767 768/* ============================================================= 769 * Materials 770 */ 771 772 773/* Update on colormaterial, material emmissive/ambient, 774 * lightmodel.globalambient 775 */ 776static void update_global_ambient( GLcontext *ctx ) 777{ 778 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 779 float *fcmd = (float *)RADEON_DB_STATE( glt ); 780 781 /* Need to do more if both emmissive & ambient are PREMULT: 782 * Hope this is not needed for MULT 783 */ 784 if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] & 785 ((3 << RADEON_EMISSIVE_SOURCE_SHIFT) | 786 (3 << RADEON_AMBIENT_SOURCE_SHIFT))) == 0) 787 { 788 COPY_3V( &fcmd[GLT_RED], 789 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]); 790 ACC_SCALE_3V( &fcmd[GLT_RED], 791 ctx->Light.Model.Ambient, 792 ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]); 793 } 794 else 795 { 796 COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient ); 797 } 798 799 RADEON_DB_STATECHANGE(rmesa, &rmesa->hw.glt); 800} 801 802/* Update on change to 803 * - light[p].colors 804 * - light[p].enabled 805 */ 806static void update_light_colors( GLcontext *ctx, GLuint p ) 807{ 808 struct gl_light *l = &ctx->Light.Light[p]; 809 810/* fprintf(stderr, "%s\n", __FUNCTION__); */ 811 812 if (l->Enabled) { 813 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 814 float *fcmd = (float *)RADEON_DB_STATE( lit[p] ); 815 816 COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient ); 817 COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse ); 818 COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular ); 819 820 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] ); 821 } 822} 823 824/* Also fallback for asym colormaterial mode in twoside lighting... 825 */ 826static void check_twoside_fallback( GLcontext *ctx ) 827{ 828 GLboolean fallback = GL_FALSE; 829 GLint i; 830 831 if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) { 832 if (ctx->Light.ColorMaterialEnabled && 833 (ctx->Light.ColorMaterialBitmask & BACK_MATERIAL_BITS) != 834 ((ctx->Light.ColorMaterialBitmask & FRONT_MATERIAL_BITS)<<1)) 835 fallback = GL_TRUE; 836 else { 837 for (i = MAT_ATTRIB_FRONT_AMBIENT; i < MAT_ATTRIB_FRONT_INDEXES; i+=2) 838 if (memcmp( ctx->Light.Material.Attrib[i], 839 ctx->Light.Material.Attrib[i+1], 840 sizeof(GLfloat)*4) != 0) { 841 fallback = GL_TRUE; 842 break; 843 } 844 } 845 } 846 847 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_LIGHT_TWOSIDE, fallback ); 848} 849 850 851static void radeonColorMaterial( GLcontext *ctx, GLenum face, GLenum mode ) 852{ 853 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 854 GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]; 855 856 light_model_ctl1 &= ~((3 << RADEON_EMISSIVE_SOURCE_SHIFT) | 857 (3 << RADEON_AMBIENT_SOURCE_SHIFT) | 858 (3 << RADEON_DIFFUSE_SOURCE_SHIFT) | 859 (3 << RADEON_SPECULAR_SOURCE_SHIFT)); 860 861 if (ctx->Light.ColorMaterialEnabled) { 862 GLuint mask = ctx->Light.ColorMaterialBitmask; 863 864 if (mask & MAT_BIT_FRONT_EMISSION) { 865 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << 866 RADEON_EMISSIVE_SOURCE_SHIFT); 867 } 868 else { 869 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT << 870 RADEON_EMISSIVE_SOURCE_SHIFT); 871 } 872 873 if (mask & MAT_BIT_FRONT_AMBIENT) { 874 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << 875 RADEON_AMBIENT_SOURCE_SHIFT); 876 } 877 else { 878 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT << 879 RADEON_AMBIENT_SOURCE_SHIFT); 880 } 881 882 if (mask & MAT_BIT_FRONT_DIFFUSE) { 883 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << 884 RADEON_DIFFUSE_SOURCE_SHIFT); 885 } 886 else { 887 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT << 888 RADEON_DIFFUSE_SOURCE_SHIFT); 889 } 890 891 if (mask & MAT_BIT_FRONT_SPECULAR) { 892 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE << 893 RADEON_SPECULAR_SOURCE_SHIFT); 894 } 895 else { 896 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT << 897 RADEON_SPECULAR_SOURCE_SHIFT); 898 } 899 } 900 else { 901 /* Default to MULT: 902 */ 903 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT << RADEON_EMISSIVE_SOURCE_SHIFT) | 904 (RADEON_LM_SOURCE_STATE_MULT << RADEON_AMBIENT_SOURCE_SHIFT) | 905 (RADEON_LM_SOURCE_STATE_MULT << RADEON_DIFFUSE_SOURCE_SHIFT) | 906 (RADEON_LM_SOURCE_STATE_MULT << RADEON_SPECULAR_SOURCE_SHIFT); 907 } 908 909 if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) { 910 RADEON_STATECHANGE( rmesa, tcl ); 911 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = light_model_ctl1; 912 } 913} 914 915void radeonUpdateMaterial( GLcontext *ctx ) 916{ 917 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 918 GLfloat (*mat)[4] = ctx->Light.Material.Attrib; 919 GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( mtl ); 920 GLuint mask = ~0; 921 922 if (ctx->Light.ColorMaterialEnabled) 923 mask &= ~ctx->Light.ColorMaterialBitmask; 924 925 if (RADEON_DEBUG & DEBUG_STATE) 926 fprintf(stderr, "%s\n", __FUNCTION__); 927 928 929 if (mask & MAT_BIT_FRONT_EMISSION) { 930 fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0]; 931 fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1]; 932 fcmd[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_FRONT_EMISSION][2]; 933 fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3]; 934 } 935 if (mask & MAT_BIT_FRONT_AMBIENT) { 936 fcmd[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_FRONT_AMBIENT][0]; 937 fcmd[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_FRONT_AMBIENT][1]; 938 fcmd[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_FRONT_AMBIENT][2]; 939 fcmd[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_FRONT_AMBIENT][3]; 940 } 941 if (mask & MAT_BIT_FRONT_DIFFUSE) { 942 fcmd[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_FRONT_DIFFUSE][0]; 943 fcmd[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_FRONT_DIFFUSE][1]; 944 fcmd[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_FRONT_DIFFUSE][2]; 945 fcmd[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_FRONT_DIFFUSE][3]; 946 } 947 if (mask & MAT_BIT_FRONT_SPECULAR) { 948 fcmd[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_FRONT_SPECULAR][0]; 949 fcmd[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_FRONT_SPECULAR][1]; 950 fcmd[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_FRONT_SPECULAR][2]; 951 fcmd[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_FRONT_SPECULAR][3]; 952 } 953 if (mask & MAT_BIT_FRONT_SHININESS) { 954 fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0]; 955 } 956 957 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mtl ); 958 959 check_twoside_fallback( ctx ); 960/* update_global_ambient( ctx );*/ 961} 962 963/* _NEW_LIGHT 964 * _NEW_MODELVIEW 965 * _MESA_NEW_NEED_EYE_COORDS 966 * 967 * Uses derived state from mesa: 968 * _VP_inf_norm 969 * _h_inf_norm 970 * _Position 971 * _NormDirection 972 * _ModelViewInvScale 973 * _NeedEyeCoords 974 * _EyeZDir 975 * 976 * which are calculated in light.c and are correct for the current 977 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW 978 * and _MESA_NEW_NEED_EYE_COORDS. 979 */ 980static void update_light( GLcontext *ctx ) 981{ 982 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 983 984 /* Have to check these, or have an automatic shortcircuit mechanism 985 * to remove noop statechanges. (Or just do a better job on the 986 * front end). 987 */ 988 { 989 GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]; 990 991 if (ctx->_NeedEyeCoords) 992 tmp &= ~RADEON_LIGHT_IN_MODELSPACE; 993 else 994 tmp |= RADEON_LIGHT_IN_MODELSPACE; 995 996 997 /* Leave this test disabled: (unexplained q3 lockup) (even with 998 new packets) 999 */ 1000 if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) 1001 { 1002 RADEON_STATECHANGE( rmesa, tcl ); 1003 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = tmp; 1004 } 1005 } 1006 1007 { 1008 GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( eye ); 1009 fcmd[EYE_X] = ctx->_EyeZDir[0]; 1010 fcmd[EYE_Y] = ctx->_EyeZDir[1]; 1011 fcmd[EYE_Z] = - ctx->_EyeZDir[2]; 1012 fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale; 1013 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.eye ); 1014 } 1015 1016 1017 1018 if (ctx->Light.Enabled) { 1019 GLint p; 1020 for (p = 0 ; p < MAX_LIGHTS; p++) { 1021 if (ctx->Light.Light[p].Enabled) { 1022 struct gl_light *l = &ctx->Light.Light[p]; 1023 GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( lit[p] ); 1024 1025 if (l->EyePosition[3] == 0.0) { 1026 COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm ); 1027 COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm ); 1028 fcmd[LIT_POSITION_W] = 0; 1029 fcmd[LIT_DIRECTION_W] = 0; 1030 } else { 1031 COPY_4V( &fcmd[LIT_POSITION_X], l->_Position ); 1032 fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0]; 1033 fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1]; 1034 fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2]; 1035 fcmd[LIT_DIRECTION_W] = 0; 1036 } 1037 1038 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] ); 1039 } 1040 } 1041 } 1042} 1043 1044static void radeonLightfv( GLcontext *ctx, GLenum light, 1045 GLenum pname, const GLfloat *params ) 1046{ 1047 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1048 GLint p = light - GL_LIGHT0; 1049 struct gl_light *l = &ctx->Light.Light[p]; 1050 GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd; 1051 1052 1053 switch (pname) { 1054 case GL_AMBIENT: 1055 case GL_DIFFUSE: 1056 case GL_SPECULAR: 1057 update_light_colors( ctx, p ); 1058 break; 1059 1060 case GL_SPOT_DIRECTION: 1061 /* picked up in update_light */ 1062 break; 1063 1064 case GL_POSITION: { 1065 /* positions picked up in update_light, but can do flag here */ 1066 GLuint flag; 1067 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; 1068 1069 /* FIXME: Set RANGE_ATTEN only when needed */ 1070 if (p&1) 1071 flag = RADEON_LIGHT_1_IS_LOCAL; 1072 else 1073 flag = RADEON_LIGHT_0_IS_LOCAL; 1074 1075 RADEON_STATECHANGE(rmesa, tcl); 1076 if (l->EyePosition[3] != 0.0F) 1077 rmesa->hw.tcl.cmd[idx] |= flag; 1078 else 1079 rmesa->hw.tcl.cmd[idx] &= ~flag; 1080 break; 1081 } 1082 1083 case GL_SPOT_EXPONENT: 1084 RADEON_STATECHANGE(rmesa, lit[p]); 1085 fcmd[LIT_SPOT_EXPONENT] = params[0]; 1086 break; 1087 1088 case GL_SPOT_CUTOFF: { 1089 GLuint flag = (p&1) ? RADEON_LIGHT_1_IS_SPOT : RADEON_LIGHT_0_IS_SPOT; 1090 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; 1091 1092 RADEON_STATECHANGE(rmesa, lit[p]); 1093 fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff; 1094 1095 RADEON_STATECHANGE(rmesa, tcl); 1096 if (l->SpotCutoff != 180.0F) 1097 rmesa->hw.tcl.cmd[idx] |= flag; 1098 else 1099 rmesa->hw.tcl.cmd[idx] &= ~flag; 1100 1101 break; 1102 } 1103 1104 case GL_CONSTANT_ATTENUATION: 1105 RADEON_STATECHANGE(rmesa, lit[p]); 1106 fcmd[LIT_ATTEN_CONST] = params[0]; 1107 if ( params[0] == 0.0 ) 1108 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX; 1109 else 1110 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0]; 1111 break; 1112 case GL_LINEAR_ATTENUATION: 1113 RADEON_STATECHANGE(rmesa, lit[p]); 1114 fcmd[LIT_ATTEN_LINEAR] = params[0]; 1115 break; 1116 case GL_QUADRATIC_ATTENUATION: 1117 RADEON_STATECHANGE(rmesa, lit[p]); 1118 fcmd[LIT_ATTEN_QUADRATIC] = params[0]; 1119 break; 1120 default: 1121 return; 1122 } 1123 1124 /* Set RANGE_ATTEN only when needed */ 1125 switch (pname) { 1126 case GL_POSITION: 1127 case GL_CONSTANT_ATTENUATION: 1128 case GL_LINEAR_ATTENUATION: 1129 case GL_QUADRATIC_ATTENUATION: 1130 { 1131 GLuint *icmd = (GLuint *)RADEON_DB_STATE( tcl ); 1132 GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; 1133 GLuint atten_flag = ( p&1 ) ? RADEON_LIGHT_1_ENABLE_RANGE_ATTEN 1134 : RADEON_LIGHT_0_ENABLE_RANGE_ATTEN; 1135 GLuint atten_const_flag = ( p&1 ) ? RADEON_LIGHT_1_CONSTANT_RANGE_ATTEN 1136 : RADEON_LIGHT_0_CONSTANT_RANGE_ATTEN; 1137 1138 if ( l->EyePosition[3] == 0.0F || 1139 ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) && 1140 fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) { 1141 /* Disable attenuation */ 1142 icmd[idx] &= ~atten_flag; 1143 } else { 1144 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) { 1145 /* Enable only constant portion of attenuation calculation */ 1146 icmd[idx] |= ( atten_flag | atten_const_flag ); 1147 } else { 1148 /* Enable full attenuation calculation */ 1149 icmd[idx] &= ~atten_const_flag; 1150 icmd[idx] |= atten_flag; 1151 } 1152 } 1153 1154 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.tcl ); 1155 break; 1156 } 1157 default: 1158 break; 1159 } 1160} 1161 1162 1163 1164 1165static void radeonLightModelfv( GLcontext *ctx, GLenum pname, 1166 const GLfloat *param ) 1167{ 1168 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1169 1170 switch (pname) { 1171 case GL_LIGHT_MODEL_AMBIENT: 1172 update_global_ambient( ctx ); 1173 break; 1174 1175 case GL_LIGHT_MODEL_LOCAL_VIEWER: 1176 RADEON_STATECHANGE( rmesa, tcl ); 1177 if (ctx->Light.Model.LocalViewer) 1178 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LOCAL_VIEWER; 1179 else 1180 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LOCAL_VIEWER; 1181 break; 1182 1183 case GL_LIGHT_MODEL_TWO_SIDE: 1184 RADEON_STATECHANGE( rmesa, tcl ); 1185 if (ctx->Light.Model.TwoSide) 1186 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_LIGHT_TWOSIDE; 1187 else 1188 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_LIGHT_TWOSIDE; 1189 1190 check_twoside_fallback( ctx ); 1191 1192 if (rmesa->TclFallback) { 1193 radeonChooseRenderState( ctx ); 1194 radeonChooseVertexState( ctx ); 1195 } 1196 break; 1197 1198 case GL_LIGHT_MODEL_COLOR_CONTROL: 1199 radeonUpdateSpecular(ctx); 1200 break; 1201 1202 default: 1203 break; 1204 } 1205} 1206 1207static void radeonShadeModel( GLcontext *ctx, GLenum mode ) 1208{ 1209 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1210 GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL]; 1211 1212 s &= ~(RADEON_DIFFUSE_SHADE_MASK | 1213 RADEON_ALPHA_SHADE_MASK | 1214 RADEON_SPECULAR_SHADE_MASK | 1215 RADEON_FOG_SHADE_MASK); 1216 1217 switch ( mode ) { 1218 case GL_FLAT: 1219 s |= (RADEON_DIFFUSE_SHADE_FLAT | 1220 RADEON_ALPHA_SHADE_FLAT | 1221 RADEON_SPECULAR_SHADE_FLAT | 1222 RADEON_FOG_SHADE_FLAT); 1223 break; 1224 case GL_SMOOTH: 1225 s |= (RADEON_DIFFUSE_SHADE_GOURAUD | 1226 RADEON_ALPHA_SHADE_GOURAUD | 1227 RADEON_SPECULAR_SHADE_GOURAUD | 1228 RADEON_FOG_SHADE_GOURAUD); 1229 break; 1230 default: 1231 return; 1232 } 1233 1234 if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) { 1235 RADEON_STATECHANGE( rmesa, set ); 1236 rmesa->hw.set.cmd[SET_SE_CNTL] = s; 1237 } 1238} 1239 1240 1241/* ============================================================= 1242 * User clip planes 1243 */ 1244 1245static void radeonClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq ) 1246{ 1247 GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0; 1248 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1249 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p]; 1250 1251 RADEON_STATECHANGE( rmesa, ucp[p] ); 1252 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0]; 1253 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1]; 1254 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2]; 1255 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3]; 1256} 1257 1258static void radeonUpdateClipPlanes( GLcontext *ctx ) 1259{ 1260 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1261 GLuint p; 1262 1263 for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { 1264 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { 1265 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p]; 1266 1267 RADEON_STATECHANGE( rmesa, ucp[p] ); 1268 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0]; 1269 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1]; 1270 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2]; 1271 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3]; 1272 } 1273 } 1274} 1275 1276 1277/* ============================================================= 1278 * Stencil 1279 */ 1280 1281static void 1282radeonStencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func, 1283 GLint ref, GLuint mask ) 1284{ 1285 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1286 GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << RADEON_STENCIL_REF_SHIFT) | 1287 ((ctx->Stencil.ValueMask[0] & 0xff) << RADEON_STENCIL_MASK_SHIFT)); 1288 1289 RADEON_STATECHANGE( rmesa, ctx ); 1290 RADEON_STATECHANGE( rmesa, msk ); 1291 1292 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_STENCIL_TEST_MASK; 1293 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(RADEON_STENCIL_REF_MASK| 1294 RADEON_STENCIL_VALUE_MASK); 1295 1296 switch ( ctx->Stencil.Function[0] ) { 1297 case GL_NEVER: 1298 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEVER; 1299 break; 1300 case GL_LESS: 1301 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LESS; 1302 break; 1303 case GL_EQUAL: 1304 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_EQUAL; 1305 break; 1306 case GL_LEQUAL: 1307 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LEQUAL; 1308 break; 1309 case GL_GREATER: 1310 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GREATER; 1311 break; 1312 case GL_NOTEQUAL: 1313 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEQUAL; 1314 break; 1315 case GL_GEQUAL: 1316 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GEQUAL; 1317 break; 1318 case GL_ALWAYS: 1319 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_ALWAYS; 1320 break; 1321 } 1322 1323 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask; 1324} 1325 1326static void 1327radeonStencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask ) 1328{ 1329 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1330 1331 RADEON_STATECHANGE( rmesa, msk ); 1332 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~RADEON_STENCIL_WRITE_MASK; 1333 rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= 1334 ((ctx->Stencil.WriteMask[0] & 0xff) << RADEON_STENCIL_WRITEMASK_SHIFT); 1335} 1336 1337static void radeonStencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail, 1338 GLenum zfail, GLenum zpass ) 1339{ 1340 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1341 1342 /* radeon 7200 have stencil bug, DEC and INC_WRAP will actually both do DEC_WRAP, 1343 and DEC_WRAP (and INVERT) will do INVERT. No way to get correct INC_WRAP and DEC, 1344 but DEC_WRAP can be fixed by using DEC and INC_WRAP at least use INC. */ 1345 1346 GLuint tempRADEON_STENCIL_FAIL_DEC_WRAP; 1347 GLuint tempRADEON_STENCIL_FAIL_INC_WRAP; 1348 GLuint tempRADEON_STENCIL_ZFAIL_DEC_WRAP; 1349 GLuint tempRADEON_STENCIL_ZFAIL_INC_WRAP; 1350 GLuint tempRADEON_STENCIL_ZPASS_DEC_WRAP; 1351 GLuint tempRADEON_STENCIL_ZPASS_INC_WRAP; 1352 1353 if (rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_BROKEN_STENCIL) { 1354 tempRADEON_STENCIL_FAIL_DEC_WRAP = RADEON_STENCIL_FAIL_DEC; 1355 tempRADEON_STENCIL_FAIL_INC_WRAP = RADEON_STENCIL_FAIL_INC; 1356 tempRADEON_STENCIL_ZFAIL_DEC_WRAP = RADEON_STENCIL_ZFAIL_DEC; 1357 tempRADEON_STENCIL_ZFAIL_INC_WRAP = RADEON_STENCIL_ZFAIL_INC; 1358 tempRADEON_STENCIL_ZPASS_DEC_WRAP = RADEON_STENCIL_ZPASS_DEC; 1359 tempRADEON_STENCIL_ZPASS_INC_WRAP = RADEON_STENCIL_ZPASS_INC; 1360 } 1361 else { 1362 tempRADEON_STENCIL_FAIL_DEC_WRAP = RADEON_STENCIL_FAIL_DEC_WRAP; 1363 tempRADEON_STENCIL_FAIL_INC_WRAP = RADEON_STENCIL_FAIL_INC_WRAP; 1364 tempRADEON_STENCIL_ZFAIL_DEC_WRAP = RADEON_STENCIL_ZFAIL_DEC_WRAP; 1365 tempRADEON_STENCIL_ZFAIL_INC_WRAP = RADEON_STENCIL_ZFAIL_INC_WRAP; 1366 tempRADEON_STENCIL_ZPASS_DEC_WRAP = RADEON_STENCIL_ZPASS_DEC_WRAP; 1367 tempRADEON_STENCIL_ZPASS_INC_WRAP = RADEON_STENCIL_ZPASS_INC_WRAP; 1368 } 1369 1370 RADEON_STATECHANGE( rmesa, ctx ); 1371 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(RADEON_STENCIL_FAIL_MASK | 1372 RADEON_STENCIL_ZFAIL_MASK | 1373 RADEON_STENCIL_ZPASS_MASK); 1374 1375 switch ( ctx->Stencil.FailFunc[0] ) { 1376 case GL_KEEP: 1377 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_KEEP; 1378 break; 1379 case GL_ZERO: 1380 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_ZERO; 1381 break; 1382 case GL_REPLACE: 1383 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_REPLACE; 1384 break; 1385 case GL_INCR: 1386 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INC; 1387 break; 1388 case GL_DECR: 1389 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_DEC; 1390 break; 1391 case GL_INCR_WRAP: 1392 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_FAIL_INC_WRAP; 1393 break; 1394 case GL_DECR_WRAP: 1395 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_FAIL_DEC_WRAP; 1396 break; 1397 case GL_INVERT: 1398 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INVERT; 1399 break; 1400 } 1401 1402 switch ( ctx->Stencil.ZFailFunc[0] ) { 1403 case GL_KEEP: 1404 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_KEEP; 1405 break; 1406 case GL_ZERO: 1407 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_ZERO; 1408 break; 1409 case GL_REPLACE: 1410 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_REPLACE; 1411 break; 1412 case GL_INCR: 1413 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INC; 1414 break; 1415 case GL_DECR: 1416 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_DEC; 1417 break; 1418 case GL_INCR_WRAP: 1419 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZFAIL_INC_WRAP; 1420 break; 1421 case GL_DECR_WRAP: 1422 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZFAIL_DEC_WRAP; 1423 break; 1424 case GL_INVERT: 1425 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INVERT; 1426 break; 1427 } 1428 1429 switch ( ctx->Stencil.ZPassFunc[0] ) { 1430 case GL_KEEP: 1431 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_KEEP; 1432 break; 1433 case GL_ZERO: 1434 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_ZERO; 1435 break; 1436 case GL_REPLACE: 1437 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_REPLACE; 1438 break; 1439 case GL_INCR: 1440 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INC; 1441 break; 1442 case GL_DECR: 1443 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_DEC; 1444 break; 1445 case GL_INCR_WRAP: 1446 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZPASS_INC_WRAP; 1447 break; 1448 case GL_DECR_WRAP: 1449 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZPASS_DEC_WRAP; 1450 break; 1451 case GL_INVERT: 1452 rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INVERT; 1453 break; 1454 } 1455} 1456 1457static void radeonClearStencil( GLcontext *ctx, GLint s ) 1458{ 1459 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1460 1461 rmesa->state.stencil.clear = 1462 ((GLuint) (ctx->Stencil.Clear & 0xff) | 1463 (0xff << RADEON_STENCIL_MASK_SHIFT) | 1464 ((ctx->Stencil.WriteMask[0] & 0xff) << RADEON_STENCIL_WRITEMASK_SHIFT)); 1465} 1466 1467 1468/* ============================================================= 1469 * Window position and viewport transformation 1470 */ 1471 1472/* 1473 * To correctly position primitives: 1474 */ 1475#define SUBPIXEL_X 0.125 1476#define SUBPIXEL_Y 0.125 1477 1478 1479/** 1480 * Called when window size or position changes or viewport or depth range 1481 * state is changed. We update the hardware viewport state here. 1482 */ 1483void radeonUpdateWindow( GLcontext *ctx ) 1484{ 1485 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1486 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; 1487 GLfloat xoffset = (GLfloat)dPriv->x; 1488 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h; 1489 const GLfloat *v = ctx->Viewport._WindowMap.m; 1490 1491 float_ui32_type sx = { v[MAT_SX] }; 1492 float_ui32_type tx = { v[MAT_TX] + xoffset + SUBPIXEL_X }; 1493 float_ui32_type sy = { - v[MAT_SY] }; 1494 float_ui32_type ty = { (- v[MAT_TY]) + yoffset + SUBPIXEL_Y }; 1495 float_ui32_type sz = { v[MAT_SZ] * rmesa->state.depth.scale }; 1496 float_ui32_type tz = { v[MAT_TZ] * rmesa->state.depth.scale }; 1497 1498 RADEON_FIREVERTICES( rmesa ); 1499 RADEON_STATECHANGE( rmesa, vpt ); 1500 1501 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = sx.ui32; 1502 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32; 1503 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = sy.ui32; 1504 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32; 1505 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = sz.ui32; 1506 rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32; 1507} 1508 1509 1510static void radeonViewport( GLcontext *ctx, GLint x, GLint y, 1511 GLsizei width, GLsizei height ) 1512{ 1513 /* Don't pipeline viewport changes, conflict with window offset 1514 * setting below. Could apply deltas to rescue pipelined viewport 1515 * values, or keep the originals hanging around. 1516 */ 1517 radeonUpdateWindow( ctx ); 1518} 1519 1520static void radeonDepthRange( GLcontext *ctx, GLclampd nearval, 1521 GLclampd farval ) 1522{ 1523 radeonUpdateWindow( ctx ); 1524} 1525 1526void radeonUpdateViewportOffset( GLcontext *ctx ) 1527{ 1528 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1529 __DRIdrawablePrivate *dPriv = rmesa->dri.drawable; 1530 GLfloat xoffset = (GLfloat)dPriv->x; 1531 GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h; 1532 const GLfloat *v = ctx->Viewport._WindowMap.m; 1533 1534 float_ui32_type tx; 1535 float_ui32_type ty; 1536 1537 tx.f = v[MAT_TX] + xoffset + SUBPIXEL_X; 1538 ty.f = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y; 1539 1540 if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != tx.ui32 || 1541 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != ty.ui32 ) 1542 { 1543 /* Note: this should also modify whatever data the context reset 1544 * code uses... 1545 */ 1546 RADEON_STATECHANGE( rmesa, vpt ); 1547 rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32; 1548 rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32; 1549 1550 /* update polygon stipple x/y screen offset */ 1551 { 1552 GLuint stx, sty; 1553 GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC]; 1554 1555 m &= ~(RADEON_STIPPLE_X_OFFSET_MASK | 1556 RADEON_STIPPLE_Y_OFFSET_MASK); 1557 1558 /* add magic offsets, then invert */ 1559 stx = 31 - ((rmesa->dri.drawable->x - 1) & RADEON_STIPPLE_COORD_MASK); 1560 sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1) 1561 & RADEON_STIPPLE_COORD_MASK); 1562 1563 m |= ((stx << RADEON_STIPPLE_X_OFFSET_SHIFT) | 1564 (sty << RADEON_STIPPLE_Y_OFFSET_SHIFT)); 1565 1566 if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) { 1567 RADEON_STATECHANGE( rmesa, msc ); 1568 rmesa->hw.msc.cmd[MSC_RE_MISC] = m; 1569 } 1570 } 1571 } 1572 1573 radeonUpdateScissor( ctx ); 1574} 1575 1576 1577 1578/* ============================================================= 1579 * Miscellaneous 1580 */ 1581 1582static void radeonClearColor( GLcontext *ctx, const GLfloat color[4] ) 1583{ 1584 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1585 GLubyte c[4]; 1586 CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]); 1587 CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]); 1588 CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]); 1589 CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]); 1590 rmesa->state.color.clear = radeonPackColor( rmesa->radeonScreen->cpp, 1591 c[0], c[1], c[2], c[3] ); 1592} 1593 1594 1595static void radeonRenderMode( GLcontext *ctx, GLenum mode ) 1596{ 1597 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1598 FALLBACK( rmesa, RADEON_FALLBACK_RENDER_MODE, (mode != GL_RENDER) ); 1599} 1600 1601 1602static GLuint radeon_rop_tab[] = { 1603 RADEON_ROP_CLEAR, 1604 RADEON_ROP_AND, 1605 RADEON_ROP_AND_REVERSE, 1606 RADEON_ROP_COPY, 1607 RADEON_ROP_AND_INVERTED, 1608 RADEON_ROP_NOOP, 1609 RADEON_ROP_XOR, 1610 RADEON_ROP_OR, 1611 RADEON_ROP_NOR, 1612 RADEON_ROP_EQUIV, 1613 RADEON_ROP_INVERT, 1614 RADEON_ROP_OR_REVERSE, 1615 RADEON_ROP_COPY_INVERTED, 1616 RADEON_ROP_OR_INVERTED, 1617 RADEON_ROP_NAND, 1618 RADEON_ROP_SET, 1619}; 1620 1621static void radeonLogicOpCode( GLcontext *ctx, GLenum opcode ) 1622{ 1623 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1624 GLuint rop = (GLuint)opcode - GL_CLEAR; 1625 1626 ASSERT( rop < 16 ); 1627 1628 RADEON_STATECHANGE( rmesa, msk ); 1629 rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = radeon_rop_tab[rop]; 1630} 1631 1632 1633/** 1634 * Set up the cliprects for either front or back-buffer drawing. 1635 */ 1636void radeonSetCliprects( radeonContextPtr rmesa ) 1637{ 1638 __DRIdrawablePrivate *const drawable = rmesa->dri.drawable; 1639 __DRIdrawablePrivate *const readable = rmesa->dri.readable; 1640 GLframebuffer *const draw_fb = (GLframebuffer*) drawable->driverPrivate; 1641 GLframebuffer *const read_fb = (GLframebuffer*) readable->driverPrivate; 1642 1643 if (draw_fb->_ColorDrawBufferIndexes[0] == BUFFER_BACK_LEFT) { 1644 /* Can't ignore 2d windows if we are page flipping. 1645 */ 1646 if ( drawable->numBackClipRects == 0 || rmesa->doPageFlip ) { 1647 rmesa->numClipRects = drawable->numClipRects; 1648 rmesa->pClipRects = drawable->pClipRects; 1649 } 1650 else { 1651 rmesa->numClipRects = drawable->numBackClipRects; 1652 rmesa->pClipRects = drawable->pBackClipRects; 1653 } 1654 } 1655 else { 1656 /* front buffer (or none, or multiple buffers */ 1657 rmesa->numClipRects = drawable->numClipRects; 1658 rmesa->pClipRects = drawable->pClipRects; 1659 } 1660 1661 if ((draw_fb->Width != drawable->w) || (draw_fb->Height != drawable->h)) { 1662 _mesa_resize_framebuffer(rmesa->glCtx, draw_fb, 1663 drawable->w, drawable->h); 1664 draw_fb->Initialized = GL_TRUE; 1665 } 1666 1667 if (drawable != readable) { 1668 if ((read_fb->Width != readable->w) || (read_fb->Height != readable->h)) { 1669 _mesa_resize_framebuffer(rmesa->glCtx, read_fb, 1670 readable->w, readable->h); 1671 read_fb->Initialized = GL_TRUE; 1672 } 1673 } 1674 1675 if (rmesa->state.scissor.enabled) 1676 radeonRecalcScissorRects( rmesa ); 1677 1678 rmesa->lastStamp = drawable->lastStamp; 1679} 1680 1681 1682/** 1683 * Called via glDrawBuffer. 1684 */ 1685static void radeonDrawBuffer( GLcontext *ctx, GLenum mode ) 1686{ 1687 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1688 1689 if (RADEON_DEBUG & DEBUG_DRI) 1690 fprintf(stderr, "%s %s\n", __FUNCTION__, 1691 _mesa_lookup_enum_by_nr( mode )); 1692 1693 RADEON_FIREVERTICES(rmesa); /* don't pipeline cliprect changes */ 1694 1695 if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) { 1696 /* 0 (GL_NONE) buffers or multiple color drawing buffers */ 1697 FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE ); 1698 return; 1699 } 1700 1701 switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0] ) { 1702 case BUFFER_FRONT_LEFT: 1703 case BUFFER_BACK_LEFT: 1704 FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE ); 1705 break; 1706 default: 1707 FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE ); 1708 return; 1709 } 1710 1711 radeonSetCliprects( rmesa ); 1712 1713 /* We'll set the drawing engine's offset/pitch parameters later 1714 * when we update other state. 1715 */ 1716} 1717 1718static void radeonReadBuffer( GLcontext *ctx, GLenum mode ) 1719{ 1720 /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */ 1721} 1722 1723 1724/* ============================================================= 1725 * State enable/disable 1726 */ 1727 1728static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state ) 1729{ 1730 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 1731 GLuint p, flag; 1732 1733 if ( RADEON_DEBUG & DEBUG_STATE ) 1734 fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__, 1735 _mesa_lookup_enum_by_nr( cap ), 1736 state ? "GL_TRUE" : "GL_FALSE" ); 1737 1738 switch ( cap ) { 1739 /* Fast track this one... 1740 */ 1741 case GL_TEXTURE_1D: 1742 case GL_TEXTURE_2D: 1743 case GL_TEXTURE_3D: 1744 break; 1745 1746 case GL_ALPHA_TEST: 1747 RADEON_STATECHANGE( rmesa, ctx ); 1748 if (state) { 1749 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ALPHA_TEST_ENABLE; 1750 } else { 1751 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ALPHA_TEST_ENABLE; 1752 } 1753 break; 1754 1755 case GL_BLEND: 1756 RADEON_STATECHANGE( rmesa, ctx ); 1757 if (state) { 1758 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ALPHA_BLEND_ENABLE; 1759 } else { 1760 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ALPHA_BLEND_ENABLE; 1761 } 1762 if ( (ctx->Color.ColorLogicOpEnabled || (ctx->Color.BlendEnabled 1763 && ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) ) { 1764 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE; 1765 } else { 1766 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE; 1767 } 1768 1769 /* Catch a possible fallback: 1770 */ 1771 if (state) { 1772 ctx->Driver.BlendEquationSeparate( ctx, 1773 ctx->Color.BlendEquationRGB, 1774 ctx->Color.BlendEquationA ); 1775 ctx->Driver.BlendFuncSeparate( ctx, ctx->Color.BlendSrcRGB, 1776 ctx->Color.BlendDstRGB, 1777 ctx->Color.BlendSrcA, 1778 ctx->Color.BlendDstA ); 1779 } 1780 else { 1781 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, GL_FALSE ); 1782 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, GL_FALSE ); 1783 } 1784 break; 1785 1786 case GL_CLIP_PLANE0: 1787 case GL_CLIP_PLANE1: 1788 case GL_CLIP_PLANE2: 1789 case GL_CLIP_PLANE3: 1790 case GL_CLIP_PLANE4: 1791 case GL_CLIP_PLANE5: 1792 p = cap-GL_CLIP_PLANE0; 1793 RADEON_STATECHANGE( rmesa, tcl ); 1794 if (state) { 1795 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (RADEON_UCP_ENABLE_0<<p); 1796 radeonClipPlane( ctx, cap, NULL ); 1797 } 1798 else { 1799 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(RADEON_UCP_ENABLE_0<<p); 1800 } 1801 break; 1802 1803 case GL_COLOR_MATERIAL: 1804 radeonColorMaterial( ctx, 0, 0 ); 1805 radeonUpdateMaterial( ctx ); 1806 break; 1807 1808 case GL_CULL_FACE: 1809 radeonCullFace( ctx, 0 ); 1810 break; 1811 1812 case GL_DEPTH_TEST: 1813 RADEON_STATECHANGE(rmesa, ctx ); 1814 if ( state ) { 1815 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_Z_ENABLE; 1816 } else { 1817 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_Z_ENABLE; 1818 } 1819 break; 1820 1821 case GL_DITHER: 1822 RADEON_STATECHANGE(rmesa, ctx ); 1823 if ( state ) { 1824 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_DITHER_ENABLE; 1825 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->state.color.roundEnable; 1826 } else { 1827 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_DITHER_ENABLE; 1828 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->state.color.roundEnable; 1829 } 1830 break; 1831 1832 case GL_FOG: 1833 RADEON_STATECHANGE(rmesa, ctx ); 1834 if ( state ) { 1835 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_FOG_ENABLE; 1836 radeonFogfv( ctx, GL_FOG_MODE, NULL ); 1837 } else { 1838 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_FOG_ENABLE; 1839 RADEON_STATECHANGE(rmesa, tcl); 1840 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK; 1841 } 1842 radeonUpdateSpecular( ctx ); /* for PK_SPEC */ 1843 _mesa_allow_light_in_model( ctx, !state ); 1844 break; 1845 1846 case GL_LIGHT0: 1847 case GL_LIGHT1: 1848 case GL_LIGHT2: 1849 case GL_LIGHT3: 1850 case GL_LIGHT4: 1851 case GL_LIGHT5: 1852 case GL_LIGHT6: 1853 case GL_LIGHT7: 1854 RADEON_STATECHANGE(rmesa, tcl); 1855 p = cap - GL_LIGHT0; 1856 if (p&1) 1857 flag = (RADEON_LIGHT_1_ENABLE | 1858 RADEON_LIGHT_1_ENABLE_AMBIENT | 1859 RADEON_LIGHT_1_ENABLE_SPECULAR); 1860 else 1861 flag = (RADEON_LIGHT_0_ENABLE | 1862 RADEON_LIGHT_0_ENABLE_AMBIENT | 1863 RADEON_LIGHT_0_ENABLE_SPECULAR); 1864 1865 if (state) 1866 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag; 1867 else 1868 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag; 1869 1870 /* 1871 */ 1872 update_light_colors( ctx, p ); 1873 break; 1874 1875 case GL_LIGHTING: 1876 RADEON_STATECHANGE(rmesa, tcl); 1877 radeonUpdateSpecular(ctx); 1878 check_twoside_fallback( ctx ); 1879 break; 1880 1881 case GL_LINE_SMOOTH: 1882 RADEON_STATECHANGE( rmesa, ctx ); 1883 if ( state ) { 1884 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_LINE; 1885 } else { 1886 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_LINE; 1887 } 1888 break; 1889 1890 case GL_LINE_STIPPLE: 1891 RADEON_STATECHANGE( rmesa, ctx ); 1892 if ( state ) { 1893 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_PATTERN_ENABLE; 1894 } else { 1895 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_PATTERN_ENABLE; 1896 } 1897 break; 1898 1899 case GL_COLOR_LOGIC_OP: 1900 RADEON_STATECHANGE( rmesa, ctx ); 1901 if ( (ctx->Color.ColorLogicOpEnabled || (ctx->Color.BlendEnabled 1902 && ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) ) { 1903 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_ROP_ENABLE; 1904 } else { 1905 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE; 1906 } 1907 break; 1908 1909 case GL_NORMALIZE: 1910 RADEON_STATECHANGE( rmesa, tcl ); 1911 if ( state ) { 1912 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_NORMALIZE_NORMALS; 1913 } else { 1914 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_NORMALIZE_NORMALS; 1915 } 1916 break; 1917 1918 case GL_POLYGON_OFFSET_POINT: 1919 RADEON_STATECHANGE( rmesa, set ); 1920 if ( state ) { 1921 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_POINT; 1922 } else { 1923 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_POINT; 1924 } 1925 break; 1926 1927 case GL_POLYGON_OFFSET_LINE: 1928 RADEON_STATECHANGE( rmesa, set ); 1929 if ( state ) { 1930 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_LINE; 1931 } else { 1932 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_LINE; 1933 } 1934 break; 1935 1936 case GL_POLYGON_OFFSET_FILL: 1937 RADEON_STATECHANGE( rmesa, set ); 1938 if ( state ) { 1939 rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_ZBIAS_ENABLE_TRI; 1940 } else { 1941 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_TRI; 1942 } 1943 break; 1944 1945 case GL_POLYGON_SMOOTH: 1946 RADEON_STATECHANGE( rmesa, ctx ); 1947 if ( state ) { 1948 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ANTI_ALIAS_POLY; 1949 } else { 1950 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_POLY; 1951 } 1952 break; 1953 1954 case GL_POLYGON_STIPPLE: 1955 RADEON_STATECHANGE(rmesa, ctx ); 1956 if ( state ) { 1957 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_STIPPLE_ENABLE; 1958 } else { 1959 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_STIPPLE_ENABLE; 1960 } 1961 break; 1962 1963 case GL_RESCALE_NORMAL_EXT: { 1964 GLboolean tmp = ctx->_NeedEyeCoords ? state : !state; 1965 RADEON_STATECHANGE( rmesa, tcl ); 1966 if ( tmp ) { 1967 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS; 1968 } else { 1969 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS; 1970 } 1971 break; 1972 } 1973 1974 case GL_SCISSOR_TEST: 1975 RADEON_FIREVERTICES( rmesa ); 1976 rmesa->state.scissor.enabled = state; 1977 radeonUpdateScissor( ctx ); 1978 break; 1979 1980 case GL_STENCIL_TEST: 1981 if ( rmesa->state.stencil.hwBuffer ) { 1982 RADEON_STATECHANGE( rmesa, ctx ); 1983 if ( state ) { 1984 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= RADEON_STENCIL_ENABLE; 1985 } else { 1986 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_STENCIL_ENABLE; 1987 } 1988 } else { 1989 FALLBACK( rmesa, RADEON_FALLBACK_STENCIL, state ); 1990 } 1991 break; 1992 1993 case GL_TEXTURE_GEN_Q: 1994 case GL_TEXTURE_GEN_R: 1995 case GL_TEXTURE_GEN_S: 1996 case GL_TEXTURE_GEN_T: 1997 /* Picked up in radeonUpdateTextureState. 1998 */ 1999 rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE; 2000 break; 2001 2002 case GL_COLOR_SUM_EXT: 2003 radeonUpdateSpecular ( ctx ); 2004 break; 2005 2006 default: 2007 return; 2008 } 2009} 2010 2011 2012static void radeonLightingSpaceChange( GLcontext *ctx ) 2013{ 2014 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 2015 GLboolean tmp; 2016 RADEON_STATECHANGE( rmesa, tcl ); 2017 2018 if (RADEON_DEBUG & DEBUG_STATE) 2019 fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords, 2020 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]); 2021 2022 if (ctx->_NeedEyeCoords) 2023 tmp = ctx->Transform.RescaleNormals; 2024 else 2025 tmp = !ctx->Transform.RescaleNormals; 2026 2027 if ( tmp ) { 2028 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_RESCALE_NORMALS; 2029 } else { 2030 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS; 2031 } 2032 2033 if (RADEON_DEBUG & DEBUG_STATE) 2034 fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords, 2035 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]); 2036} 2037 2038/* ============================================================= 2039 * Deferred state management - matrices, textures, other? 2040 */ 2041 2042 2043void radeonUploadTexMatrix( radeonContextPtr rmesa, 2044 int unit, GLboolean swapcols ) 2045{ 2046/* Here's how this works: on r100, only 3 tex coords can be submitted, so the 2047 vector looks like this probably: (s t r|q 0) (not sure if the last coord 2048 is hardwired to 0, could be 1 too). Interestingly, it actually looks like 2049 texgen generates all 4 coords, at least tests with projtex indicated that. 2050 So: if we need the q coord in the end (solely determined by the texture 2051 target, i.e. 2d / 1d / texrect targets) we swap the third and 4th row. 2052 Additionally, if we don't have texgen but 4 tex coords submitted, we swap 2053 column 3 and 4 (for the 2d / 1d / texrect targets) since the the q coord 2054 will get submitted in the "wrong", i.e. 3rd, slot. 2055 If an app submits 3 coords for 2d targets, we assume it is saving on vertex 2056 size and using the texture matrix to swap the r and q coords around (ut2k3 2057 does exactly that), so we don't need the 3rd / 4th column swap - still need 2058 the 3rd / 4th row swap of course. This will potentially break for apps which 2059 use TexCoord3x just for fun. Additionally, it will never work if an app uses 2060 an "advanced" texture matrix and relies on all 4 texcoord inputs to generate 2061 the maximum needed 3. This seems impossible to do with hw tcl on r100, and 2062 incredibly hard to detect so we can't just fallback in such a case. Assume 2063 it never happens... - rs 2064*/ 2065 2066 int idx = TEXMAT_0 + unit; 2067 float *dest = ((float *)RADEON_DB_STATE( mat[idx] )) + MAT_ELT_0; 2068 int i; 2069 struct gl_texture_unit tUnit = rmesa->glCtx->Texture.Unit[unit]; 2070 GLfloat *src = rmesa->tmpmat[unit].m; 2071 2072 rmesa->TexMatColSwap &= ~(1 << unit); 2073 if ((tUnit._ReallyEnabled & (TEXTURE_3D_BIT | TEXTURE_CUBE_BIT)) == 0) { 2074 if (swapcols) { 2075 rmesa->TexMatColSwap |= 1 << unit; 2076 /* attention some elems are swapped 2 times! */ 2077 *dest++ = src[0]; 2078 *dest++ = src[4]; 2079 *dest++ = src[12]; 2080 *dest++ = src[8]; 2081 *dest++ = src[1]; 2082 *dest++ = src[5]; 2083 *dest++ = src[13]; 2084 *dest++ = src[9]; 2085 *dest++ = src[2]; 2086 *dest++ = src[6]; 2087 *dest++ = src[15]; 2088 *dest++ = src[11]; 2089 /* those last 4 are probably never used */ 2090 *dest++ = src[3]; 2091 *dest++ = src[7]; 2092 *dest++ = src[14]; 2093 *dest++ = src[10]; 2094 } 2095 else { 2096 for (i = 0; i < 2; i++) { 2097 *dest++ = src[i]; 2098 *dest++ = src[i+4]; 2099 *dest++ = src[i+8]; 2100 *dest++ = src[i+12]; 2101 } 2102 for (i = 3; i >= 2; i--) { 2103 *dest++ = src[i]; 2104 *dest++ = src[i+4]; 2105 *dest++ = src[i+8]; 2106 *dest++ = src[i+12]; 2107 } 2108 } 2109 } 2110 else { 2111 for (i = 0 ; i < 4 ; i++) { 2112 *dest++ = src[i]; 2113 *dest++ = src[i+4]; 2114 *dest++ = src[i+8]; 2115 *dest++ = src[i+12]; 2116 } 2117 } 2118 2119 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); 2120} 2121 2122 2123static void upload_matrix( radeonContextPtr rmesa, GLfloat *src, int idx ) 2124{ 2125 float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0; 2126 int i; 2127 2128 2129 for (i = 0 ; i < 4 ; i++) { 2130 *dest++ = src[i]; 2131 *dest++ = src[i+4]; 2132 *dest++ = src[i+8]; 2133 *dest++ = src[i+12]; 2134 } 2135 2136 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); 2137} 2138 2139static void upload_matrix_t( radeonContextPtr rmesa, GLfloat *src, int idx ) 2140{ 2141 float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0; 2142 memcpy(dest, src, 16*sizeof(float)); 2143 RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); 2144} 2145 2146 2147static void update_texturematrix( GLcontext *ctx ) 2148{ 2149 radeonContextPtr rmesa = RADEON_CONTEXT( ctx ); 2150 GLuint tpc = rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL]; 2151 GLuint vs = rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL]; 2152 int unit; 2153 GLuint texMatEnabled = 0; 2154 rmesa->NeedTexMatrix = 0; 2155 rmesa->TexMatColSwap = 0; 2156 2157 for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) { 2158 if (ctx->Texture.Unit[unit]._ReallyEnabled) { 2159 GLboolean needMatrix = GL_FALSE; 2160 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) { 2161 needMatrix = GL_TRUE; 2162 texMatEnabled |= (RADEON_TEXGEN_TEXMAT_0_ENABLE | 2163 RADEON_TEXMAT_0_ENABLE) << unit; 2164 2165 if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) { 2166 /* Need to preconcatenate any active texgen 2167 * obj/eyeplane matrices: 2168 */ 2169 _math_matrix_mul_matrix( &rmesa->tmpmat[unit], 2170 ctx->TextureMatrixStack[unit].Top, 2171 &rmesa->TexGenMatrix[unit] ); 2172 } 2173 else { 2174 _math_matrix_copy( &rmesa->tmpmat[unit], 2175 ctx->TextureMatrixStack[unit].Top ); 2176 } 2177 } 2178 else if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) { 2179 _math_matrix_copy( &rmesa->tmpmat[unit], &rmesa->TexGenMatrix[unit] ); 2180 needMatrix = GL_TRUE; 2181 } 2182 if (needMatrix) { 2183 rmesa->NeedTexMatrix |= 1 << unit; 2184 radeonUploadTexMatrix( rmesa, unit, 2185 !ctx->Texture.Unit[unit].TexGenEnabled ); 2186 } 2187 } 2188 } 2189 2190 tpc = (texMatEnabled | rmesa->TexGenEnabled); 2191 2192 /* TCL_TEX_COMPUTED_x is TCL_TEX_INPUT_x | 0x8 */ 2193 vs &= ~((RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT) | 2194 (RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_1_OUTPUT_SHIFT) | 2195 (RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_2_OUTPUT_SHIFT)); 2196 2197 vs |= (((tpc & RADEON_TEXGEN_TEXMAT_0_ENABLE) << 2198 (RADEON_TCL_TEX_0_OUTPUT_SHIFT + 3)) | 2199 ((tpc & RADEON_TEXGEN_TEXMAT_1_ENABLE) << 2200 (RADEON_TCL_TEX_1_OUTPUT_SHIFT + 2)) | 2201 ((tpc & RADEON_TEXGEN_TEXMAT_2_ENABLE) << 2202 (RADEON_TCL_TEX_2_OUTPUT_SHIFT + 1))); 2203 2204 if (tpc != rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] || 2205 vs != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL]) { 2206 2207 RADEON_STATECHANGE(rmesa, tcl); 2208 rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = tpc; 2209 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] = vs; 2210 } 2211} 2212 2213 2214/** 2215 * Tell the card where to render (offset, pitch). 2216 * Effected by glDrawBuffer, etc 2217 */ 2218void 2219radeonUpdateDrawBuffer(GLcontext *ctx) 2220{ 2221 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 2222 struct gl_framebuffer *fb = ctx->DrawBuffer; 2223 driRenderbuffer *drb; 2224 2225 if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) { 2226 /* draw to front */ 2227 drb = (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer; 2228 } 2229 else if (fb->_ColorDrawBufferIndexes[0] == BUFFER_BACK_LEFT) { 2230 /* draw to back */ 2231 drb = (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer; 2232 } 2233 else { 2234 /* drawing to multiple buffers, or none */ 2235 return; 2236 } 2237 2238 assert(drb); 2239 assert(drb->flippedPitch); 2240 2241 RADEON_STATECHANGE( rmesa, ctx ); 2242 2243 /* Note: we used the (possibly) page-flipped values */ 2244 rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET] 2245 = ((drb->flippedOffset + rmesa->radeonScreen->fbLocation) 2246 & RADEON_COLOROFFSET_MASK); 2247 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch; 2248 if (rmesa->sarea->tiling_enabled) { 2249 rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= RADEON_COLOR_TILE_ENABLE; 2250 } 2251} 2252 2253 2254void radeonValidateState( GLcontext *ctx ) 2255{ 2256 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 2257 GLuint new_state = rmesa->NewGLState; 2258 2259 if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) { 2260 radeonUpdateDrawBuffer(ctx); 2261 } 2262 2263 if (new_state & _NEW_TEXTURE) { 2264 radeonUpdateTextureState( ctx ); 2265 new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */ 2266 } 2267 2268 /* Need an event driven matrix update? 2269 */ 2270 if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) 2271 upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, MODEL_PROJ ); 2272 2273 /* Need these for lighting (shouldn't upload otherwise) 2274 */ 2275 if (new_state & (_NEW_MODELVIEW)) { 2276 upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, MODEL ); 2277 upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, MODEL_IT ); 2278 } 2279 2280 /* Does this need to be triggered on eg. modelview for 2281 * texgen-derived objplane/eyeplane matrices? 2282 */ 2283 if (new_state & _NEW_TEXTURE_MATRIX) { 2284 update_texturematrix( ctx ); 2285 } 2286 2287 if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) { 2288 update_light( ctx ); 2289 } 2290 2291 /* emit all active clip planes if projection matrix changes. 2292 */ 2293 if (new_state & (_NEW_PROJECTION)) { 2294 if (ctx->Transform.ClipPlanesEnabled) 2295 radeonUpdateClipPlanes( ctx ); 2296 } 2297 2298 2299 rmesa->NewGLState = 0; 2300} 2301 2302 2303static void radeonInvalidateState( GLcontext *ctx, GLuint new_state ) 2304{ 2305 _swrast_InvalidateState( ctx, new_state ); 2306 _swsetup_InvalidateState( ctx, new_state ); 2307 _vbo_InvalidateState( ctx, new_state ); 2308 _tnl_InvalidateState( ctx, new_state ); 2309 _ae_invalidate_state( ctx, new_state ); 2310 RADEON_CONTEXT(ctx)->NewGLState |= new_state; 2311} 2312 2313 2314/* A hack. Need a faster way to find this out. 2315 */ 2316static GLboolean check_material( GLcontext *ctx ) 2317{ 2318 TNLcontext *tnl = TNL_CONTEXT(ctx); 2319 GLint i; 2320 2321 for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT; 2322 i < _TNL_ATTRIB_MAT_BACK_INDEXES; 2323 i++) 2324 if (tnl->vb.AttribPtr[i] && 2325 tnl->vb.AttribPtr[i]->stride) 2326 return GL_TRUE; 2327 2328 return GL_FALSE; 2329} 2330 2331 2332static void radeonWrapRunPipeline( GLcontext *ctx ) 2333{ 2334 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); 2335 GLboolean has_material; 2336 2337 if (0) 2338 fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState); 2339 2340 /* Validate state: 2341 */ 2342 if (rmesa->NewGLState) 2343 radeonValidateState( ctx ); 2344 2345 has_material = (ctx->Light.Enabled && check_material( ctx )); 2346 2347 if (has_material) { 2348 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_TRUE ); 2349 } 2350 2351 /* Run the pipeline. 2352 */ 2353 _tnl_run_pipeline( ctx ); 2354 2355 if (has_material) { 2356 TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_FALSE ); 2357 } 2358} 2359 2360 2361/* Initialize the driver's state functions. 2362 * Many of the ctx->Driver functions might have been initialized to 2363 * software defaults in the earlier _mesa_init_driver_functions() call. 2364 */ 2365void radeonInitStateFuncs( GLcontext *ctx ) 2366{ 2367 ctx->Driver.UpdateState = radeonInvalidateState; 2368 ctx->Driver.LightingSpaceChange = radeonLightingSpaceChange; 2369 2370 ctx->Driver.DrawBuffer = radeonDrawBuffer; 2371 ctx->Driver.ReadBuffer = radeonReadBuffer; 2372 2373 ctx->Driver.AlphaFunc = radeonAlphaFunc; 2374 ctx->Driver.BlendEquationSeparate = radeonBlendEquationSeparate; 2375 ctx->Driver.BlendFuncSeparate = radeonBlendFuncSeparate; 2376 ctx->Driver.ClearColor = radeonClearColor; 2377 ctx->Driver.ClearDepth = radeonClearDepth; 2378 ctx->Driver.ClearIndex = NULL; 2379 ctx->Driver.ClearStencil = radeonClearStencil; 2380 ctx->Driver.ClipPlane = radeonClipPlane; 2381 ctx->Driver.ColorMask = radeonColorMask; 2382 ctx->Driver.CullFace = radeonCullFace; 2383 ctx->Driver.DepthFunc = radeonDepthFunc; 2384 ctx->Driver.DepthMask = radeonDepthMask; 2385 ctx->Driver.DepthRange = radeonDepthRange; 2386 ctx->Driver.Enable = radeonEnable; 2387 ctx->Driver.Fogfv = radeonFogfv; 2388 ctx->Driver.FrontFace = radeonFrontFace; 2389 ctx->Driver.Hint = NULL; 2390 ctx->Driver.IndexMask = NULL; 2391 ctx->Driver.LightModelfv = radeonLightModelfv; 2392 ctx->Driver.Lightfv = radeonLightfv; 2393 ctx->Driver.LineStipple = radeonLineStipple; 2394 ctx->Driver.LineWidth = radeonLineWidth; 2395 ctx->Driver.LogicOpcode = radeonLogicOpCode; 2396 ctx->Driver.PolygonMode = radeonPolygonMode; 2397 ctx->Driver.PolygonOffset = radeonPolygonOffset; 2398 ctx->Driver.PolygonStipple = radeonPolygonStipple; 2399 ctx->Driver.RenderMode = radeonRenderMode; 2400 ctx->Driver.Scissor = radeonScissor; 2401 ctx->Driver.ShadeModel = radeonShadeModel; 2402 ctx->Driver.StencilFuncSeparate = radeonStencilFuncSeparate; 2403 ctx->Driver.StencilMaskSeparate = radeonStencilMaskSeparate; 2404 ctx->Driver.StencilOpSeparate = radeonStencilOpSeparate; 2405 ctx->Driver.Viewport = radeonViewport; 2406 2407 TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = radeonUpdateMaterial; 2408 TNL_CONTEXT(ctx)->Driver.RunPipeline = radeonWrapRunPipeline; 2409} 2410