s_context.c revision 3464ebd5
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.1 4 * 5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Keith Whitwell <keith@tungstengraphics.com> 26 * Brian Paul 27 */ 28 29#include "main/imports.h" 30#include "main/bufferobj.h" 31#include "main/colormac.h" 32#include "main/mtypes.h" 33#include "main/teximage.h" 34#include "program/prog_parameter.h" 35#include "program/prog_statevars.h" 36#include "swrast.h" 37#include "s_blend.h" 38#include "s_context.h" 39#include "s_lines.h" 40#include "s_points.h" 41#include "s_span.h" 42#include "s_triangle.h" 43#include "s_texfilter.h" 44 45 46/** 47 * Recompute the value of swrast->_RasterMask, etc. according to 48 * the current context. The _RasterMask field can be easily tested by 49 * drivers to determine certain basic GL state (does the primitive need 50 * stenciling, logic-op, fog, etc?). 51 */ 52static void 53_swrast_update_rasterflags( struct gl_context *ctx ) 54{ 55 SWcontext *swrast = SWRAST_CONTEXT(ctx); 56 GLbitfield rasterMask = 0; 57 GLuint i; 58 59 if (ctx->Color.AlphaEnabled) rasterMask |= ALPHATEST_BIT; 60 if (ctx->Color.BlendEnabled) rasterMask |= BLEND_BIT; 61 if (ctx->Depth.Test) rasterMask |= DEPTH_BIT; 62 if (swrast->_FogEnabled) rasterMask |= FOG_BIT; 63 if (ctx->Scissor.Enabled) rasterMask |= CLIP_BIT; 64 if (ctx->Stencil._Enabled) rasterMask |= STENCIL_BIT; 65 for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { 66 if (!ctx->Color.ColorMask[i][0] || 67 !ctx->Color.ColorMask[i][1] || 68 !ctx->Color.ColorMask[i][2] || 69 !ctx->Color.ColorMask[i][3]) { 70 rasterMask |= MASKING_BIT; 71 break; 72 } 73 } 74 if (ctx->Color._LogicOpEnabled) rasterMask |= LOGIC_OP_BIT; 75 if (ctx->Texture._EnabledUnits) rasterMask |= TEXTURE_BIT; 76 if ( ctx->Viewport.X < 0 77 || ctx->Viewport.X + ctx->Viewport.Width > (GLint) ctx->DrawBuffer->Width 78 || ctx->Viewport.Y < 0 79 || ctx->Viewport.Y + ctx->Viewport.Height > (GLint) ctx->DrawBuffer->Height) { 80 rasterMask |= CLIP_BIT; 81 } 82 83 if (ctx->Query.CurrentOcclusionObject) 84 rasterMask |= OCCLUSION_BIT; 85 86 87 /* If we're not drawing to exactly one color buffer set the 88 * MULTI_DRAW_BIT flag. Also set it if we're drawing to no 89 * buffers or the RGBA or CI mask disables all writes. 90 */ 91 if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) { 92 /* more than one color buffer designated for writing (or zero buffers) */ 93 rasterMask |= MULTI_DRAW_BIT; 94 } 95 96 for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { 97 if (ctx->Color.ColorMask[i][0] + 98 ctx->Color.ColorMask[i][1] + 99 ctx->Color.ColorMask[i][2] + 100 ctx->Color.ColorMask[i][3] == 0) { 101 rasterMask |= MULTI_DRAW_BIT; /* all RGBA channels disabled */ 102 break; 103 } 104 } 105 106 107 if (ctx->FragmentProgram._Current) { 108 rasterMask |= FRAGPROG_BIT; 109 } 110 111 if (ctx->ATIFragmentShader._Enabled) { 112 rasterMask |= ATIFRAGSHADER_BIT; 113 } 114 115#if CHAN_TYPE == GL_FLOAT 116 if (ctx->Color.ClampFragmentColor == GL_TRUE) { 117 rasterMask |= CLAMPING_BIT; 118 } 119#endif 120 121 SWRAST_CONTEXT(ctx)->_RasterMask = rasterMask; 122} 123 124 125/** 126 * Examine polygon cull state to compute the _BackfaceCullSign field. 127 * _BackfaceCullSign will be 0 if no culling, -1 if culling back-faces, 128 * and 1 if culling front-faces. The Polygon FrontFace state also 129 * factors in. 130 */ 131static void 132_swrast_update_polygon( struct gl_context *ctx ) 133{ 134 GLfloat backface_sign; 135 136 if (ctx->Polygon.CullFlag) { 137 switch (ctx->Polygon.CullFaceMode) { 138 case GL_BACK: 139 backface_sign = -1.0F; 140 break; 141 case GL_FRONT: 142 backface_sign = 1.0F; 143 break; 144 case GL_FRONT_AND_BACK: 145 /* fallthrough */ 146 default: 147 backface_sign = 0.0F; 148 } 149 } 150 else { 151 backface_sign = 0.0F; 152 } 153 154 SWRAST_CONTEXT(ctx)->_BackfaceCullSign = backface_sign; 155 156 /* This is for front/back-face determination, but not for culling */ 157 SWRAST_CONTEXT(ctx)->_BackfaceSign 158 = (ctx->Polygon.FrontFace == GL_CW) ? -1.0F : 1.0F; 159} 160 161 162 163/** 164 * Update the _PreferPixelFog field to indicate if we need to compute 165 * fog blend factors (from the fog coords) per-fragment. 166 */ 167static void 168_swrast_update_fog_hint( struct gl_context *ctx ) 169{ 170 SWcontext *swrast = SWRAST_CONTEXT(ctx); 171 swrast->_PreferPixelFog = (!swrast->AllowVertexFog || 172 ctx->FragmentProgram._Current || 173 (ctx->Hint.Fog == GL_NICEST && 174 swrast->AllowPixelFog)); 175} 176 177 178 179/** 180 * Update the swrast->_TextureCombinePrimary flag. 181 */ 182static void 183_swrast_update_texture_env( struct gl_context *ctx ) 184{ 185 SWcontext *swrast = SWRAST_CONTEXT(ctx); 186 GLuint i; 187 188 swrast->_TextureCombinePrimary = GL_FALSE; 189 190 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { 191 const struct gl_tex_env_combine_state *combine = 192 ctx->Texture.Unit[i]._CurrentCombine; 193 GLuint term; 194 for (term = 0; term < combine->_NumArgsRGB; term++) { 195 if (combine->SourceRGB[term] == GL_PRIMARY_COLOR) { 196 swrast->_TextureCombinePrimary = GL_TRUE; 197 return; 198 } 199 if (combine->SourceA[term] == GL_PRIMARY_COLOR) { 200 swrast->_TextureCombinePrimary = GL_TRUE; 201 return; 202 } 203 } 204 } 205} 206 207 208/** 209 * Determine if we can defer texturing/shading until after Z/stencil 210 * testing. This potentially allows us to skip texturing/shading for 211 * lots of fragments. 212 */ 213static void 214_swrast_update_deferred_texture(struct gl_context *ctx) 215{ 216 SWcontext *swrast = SWRAST_CONTEXT(ctx); 217 if (ctx->Color.AlphaEnabled) { 218 /* alpha test depends on post-texture/shader colors */ 219 swrast->_DeferredTexture = GL_FALSE; 220 } 221 else { 222 const struct gl_fragment_program *fprog 223 = ctx->FragmentProgram._Current; 224 if (fprog && (fprog->Base.OutputsWritten & (1 << FRAG_RESULT_DEPTH))) { 225 /* Z comes from fragment program/shader */ 226 swrast->_DeferredTexture = GL_FALSE; 227 } 228 else if (fprog && fprog->UsesKill) { 229 swrast->_DeferredTexture = GL_FALSE; 230 } 231 else if (ctx->Query.CurrentOcclusionObject) { 232 /* occlusion query depends on shader discard/kill results */ 233 swrast->_DeferredTexture = GL_FALSE; 234 } 235 else { 236 swrast->_DeferredTexture = GL_TRUE; 237 } 238 } 239} 240 241 242/** 243 * Update swrast->_FogColor and swrast->_FogEnable values. 244 */ 245static void 246_swrast_update_fog_state( struct gl_context *ctx ) 247{ 248 SWcontext *swrast = SWRAST_CONTEXT(ctx); 249 const struct gl_fragment_program *fp = ctx->FragmentProgram._Current; 250 251 assert((fp == NULL) || (fp->Base.Target == GL_FRAGMENT_PROGRAM_ARB)); 252 253 /* determine if fog is needed, and if so, which fog mode */ 254 swrast->_FogEnabled = (fp == NULL && ctx->Fog.Enabled); 255} 256 257 258/** 259 * Update state for running fragment programs. Basically, load the 260 * program parameters with current state values. 261 */ 262static void 263_swrast_update_fragment_program(struct gl_context *ctx, GLbitfield newState) 264{ 265 const struct gl_fragment_program *fp = ctx->FragmentProgram._Current; 266 if (fp) { 267 _mesa_load_state_parameters(ctx, fp->Base.Parameters); 268 } 269} 270 271 272/** 273 * See if we can do early diffuse+specular (primary+secondary) color 274 * add per vertex instead of per-fragment. 275 */ 276static void 277_swrast_update_specular_vertex_add(struct gl_context *ctx) 278{ 279 SWcontext *swrast = SWRAST_CONTEXT(ctx); 280 GLboolean separateSpecular = ctx->Fog.ColorSumEnabled || 281 (ctx->Light.Enabled && 282 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR); 283 284 swrast->SpecularVertexAdd = (separateSpecular 285 && ctx->Texture._EnabledUnits == 0x0 286 && !ctx->FragmentProgram._Current 287 && !ctx->ATIFragmentShader._Enabled); 288} 289 290 291#define _SWRAST_NEW_DERIVED (_SWRAST_NEW_RASTERMASK | \ 292 _NEW_PROGRAM_CONSTANTS | \ 293 _NEW_TEXTURE | \ 294 _NEW_HINT | \ 295 _NEW_POLYGON ) 296 297/* State referenced by _swrast_choose_triangle, _swrast_choose_line. 298 */ 299#define _SWRAST_NEW_TRIANGLE (_SWRAST_NEW_DERIVED | \ 300 _NEW_RENDERMODE| \ 301 _NEW_POLYGON| \ 302 _NEW_DEPTH| \ 303 _NEW_STENCIL| \ 304 _NEW_COLOR| \ 305 _NEW_TEXTURE| \ 306 _SWRAST_NEW_RASTERMASK| \ 307 _NEW_LIGHT| \ 308 _NEW_FOG | \ 309 _DD_NEW_SEPARATE_SPECULAR) 310 311#define _SWRAST_NEW_LINE (_SWRAST_NEW_DERIVED | \ 312 _NEW_RENDERMODE| \ 313 _NEW_LINE| \ 314 _NEW_TEXTURE| \ 315 _NEW_LIGHT| \ 316 _NEW_FOG| \ 317 _NEW_DEPTH | \ 318 _DD_NEW_SEPARATE_SPECULAR) 319 320#define _SWRAST_NEW_POINT (_SWRAST_NEW_DERIVED | \ 321 _NEW_RENDERMODE | \ 322 _NEW_POINT | \ 323 _NEW_TEXTURE | \ 324 _NEW_LIGHT | \ 325 _NEW_FOG | \ 326 _DD_NEW_SEPARATE_SPECULAR) 327 328#define _SWRAST_NEW_TEXTURE_SAMPLE_FUNC _NEW_TEXTURE 329 330#define _SWRAST_NEW_TEXTURE_ENV_MODE _NEW_TEXTURE 331 332#define _SWRAST_NEW_BLEND_FUNC _NEW_COLOR 333 334 335 336/** 337 * Stub for swrast->Triangle to select a true triangle function 338 * after a state change. 339 */ 340static void 341_swrast_validate_triangle( struct gl_context *ctx, 342 const SWvertex *v0, 343 const SWvertex *v1, 344 const SWvertex *v2 ) 345{ 346 SWcontext *swrast = SWRAST_CONTEXT(ctx); 347 348 _swrast_validate_derived( ctx ); 349 swrast->choose_triangle( ctx ); 350 ASSERT(swrast->Triangle); 351 352 if (swrast->SpecularVertexAdd) { 353 /* separate specular color, but no texture */ 354 swrast->SpecTriangle = swrast->Triangle; 355 swrast->Triangle = _swrast_add_spec_terms_triangle; 356 } 357 358 swrast->Triangle( ctx, v0, v1, v2 ); 359} 360 361/** 362 * Called via swrast->Line. Examine current GL state and choose a software 363 * line routine. Then call it. 364 */ 365static void 366_swrast_validate_line( struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1 ) 367{ 368 SWcontext *swrast = SWRAST_CONTEXT(ctx); 369 370 _swrast_validate_derived( ctx ); 371 swrast->choose_line( ctx ); 372 ASSERT(swrast->Line); 373 374 if (swrast->SpecularVertexAdd) { 375 swrast->SpecLine = swrast->Line; 376 swrast->Line = _swrast_add_spec_terms_line; 377 } 378 379 swrast->Line( ctx, v0, v1 ); 380} 381 382/** 383 * Called via swrast->Point. Examine current GL state and choose a software 384 * point routine. Then call it. 385 */ 386static void 387_swrast_validate_point( struct gl_context *ctx, const SWvertex *v0 ) 388{ 389 SWcontext *swrast = SWRAST_CONTEXT(ctx); 390 391 _swrast_validate_derived( ctx ); 392 swrast->choose_point( ctx ); 393 394 if (swrast->SpecularVertexAdd) { 395 swrast->SpecPoint = swrast->Point; 396 swrast->Point = _swrast_add_spec_terms_point; 397 } 398 399 swrast->Point( ctx, v0 ); 400} 401 402 403/** 404 * Called via swrast->BlendFunc. Examine GL state to choose a blending 405 * function, then call it. 406 */ 407static void _ASMAPI 408_swrast_validate_blend_func(struct gl_context *ctx, GLuint n, const GLubyte mask[], 409 GLvoid *src, const GLvoid *dst, 410 GLenum chanType ) 411{ 412 SWcontext *swrast = SWRAST_CONTEXT(ctx); 413 414 _swrast_validate_derived( ctx ); /* why is this needed? */ 415 _swrast_choose_blend_func( ctx, chanType ); 416 417 swrast->BlendFunc( ctx, n, mask, src, dst, chanType ); 418} 419 420 421/** 422 * Make sure we have texture image data for all the textures we may need 423 * for subsequent rendering. 424 */ 425static void 426_swrast_validate_texture_images(struct gl_context *ctx) 427{ 428 SWcontext *swrast = SWRAST_CONTEXT(ctx); 429 GLuint u; 430 431 if (!swrast->ValidateTextureImage || !ctx->Texture._EnabledUnits) { 432 /* no textures enabled, or no way to validate images! */ 433 return; 434 } 435 436 for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) { 437 if (ctx->Texture.Unit[u]._ReallyEnabled) { 438 struct gl_texture_object *texObj = ctx->Texture.Unit[u]._Current; 439 ASSERT(texObj); 440 if (texObj) { 441 GLuint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; 442 GLuint face; 443 for (face = 0; face < numFaces; face++) { 444 GLint lvl; 445 for (lvl = texObj->BaseLevel; lvl <= texObj->_MaxLevel; lvl++) { 446 struct gl_texture_image *texImg = texObj->Image[face][lvl]; 447 if (texImg && !texImg->Data) { 448 swrast->ValidateTextureImage(ctx, texObj, face, lvl); 449 ASSERT(texObj->Image[face][lvl]->Data); 450 } 451 } 452 } 453 } 454 } 455 } 456} 457 458 459/** 460 * Free the texture image data attached to all currently enabled 461 * textures. Meant to be called by device drivers when transitioning 462 * from software to hardware rendering. 463 */ 464void 465_swrast_eject_texture_images(struct gl_context *ctx) 466{ 467 GLuint u; 468 469 if (!ctx->Texture._EnabledUnits) { 470 /* no textures enabled */ 471 return; 472 } 473 474 for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) { 475 if (ctx->Texture.Unit[u]._ReallyEnabled) { 476 struct gl_texture_object *texObj = ctx->Texture.Unit[u]._Current; 477 ASSERT(texObj); 478 if (texObj) { 479 GLuint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; 480 GLuint face; 481 for (face = 0; face < numFaces; face++) { 482 GLint lvl; 483 for (lvl = texObj->BaseLevel; lvl <= texObj->_MaxLevel; lvl++) { 484 struct gl_texture_image *texImg = texObj->Image[face][lvl]; 485 if (texImg && texImg->Data) { 486 _mesa_free_texmemory(texImg->Data); 487 texImg->Data = NULL; 488 } 489 } 490 } 491 } 492 } 493 } 494} 495 496 497 498static void 499_swrast_sleep( struct gl_context *ctx, GLbitfield new_state ) 500{ 501 (void) ctx; (void) new_state; 502} 503 504 505static void 506_swrast_invalidate_state( struct gl_context *ctx, GLbitfield new_state ) 507{ 508 SWcontext *swrast = SWRAST_CONTEXT(ctx); 509 GLuint i; 510 511 swrast->NewState |= new_state; 512 513 /* After 10 statechanges without any swrast functions being called, 514 * put the module to sleep. 515 */ 516 if (++swrast->StateChanges > 10) { 517 swrast->InvalidateState = _swrast_sleep; 518 swrast->NewState = ~0; 519 new_state = ~0; 520 } 521 522 if (new_state & swrast->InvalidateTriangleMask) 523 swrast->Triangle = _swrast_validate_triangle; 524 525 if (new_state & swrast->InvalidateLineMask) 526 swrast->Line = _swrast_validate_line; 527 528 if (new_state & swrast->InvalidatePointMask) 529 swrast->Point = _swrast_validate_point; 530 531 if (new_state & _SWRAST_NEW_BLEND_FUNC) 532 swrast->BlendFunc = _swrast_validate_blend_func; 533 534 if (new_state & _SWRAST_NEW_TEXTURE_SAMPLE_FUNC) 535 for (i = 0 ; i < ctx->Const.MaxTextureImageUnits ; i++) 536 swrast->TextureSample[i] = NULL; 537} 538 539 540void 541_swrast_update_texture_samplers(struct gl_context *ctx) 542{ 543 SWcontext *swrast = SWRAST_CONTEXT(ctx); 544 GLuint u; 545 546 if (!swrast) 547 return; /* pipe hack */ 548 549 for (u = 0; u < ctx->Const.MaxTextureImageUnits; u++) { 550 const struct gl_texture_object *tObj = ctx->Texture.Unit[u]._Current; 551 /* Note: If tObj is NULL, the sample function will be a simple 552 * function that just returns opaque black (0,0,0,1). 553 */ 554 swrast->TextureSample[u] = _swrast_choose_texture_sample_func(ctx, tObj); 555 } 556} 557 558 559/** 560 * Update swrast->_ActiveAttribs, swrast->_NumActiveAttribs, 561 * swrast->_ActiveAtttribMask. 562 */ 563static void 564_swrast_update_active_attribs(struct gl_context *ctx) 565{ 566 SWcontext *swrast = SWRAST_CONTEXT(ctx); 567 GLuint attribsMask; 568 569 /* 570 * Compute _ActiveAttribsMask = which fragment attributes are needed. 571 */ 572 if (ctx->FragmentProgram._Current) { 573 /* fragment program/shader */ 574 attribsMask = ctx->FragmentProgram._Current->Base.InputsRead; 575 attribsMask &= ~FRAG_BIT_WPOS; /* WPOS is always handled specially */ 576 } 577 else if (ctx->ATIFragmentShader._Enabled) { 578 attribsMask = ~0; /* XXX fix me */ 579 } 580 else { 581 /* fixed function */ 582 attribsMask = 0x0; 583 584#if CHAN_TYPE == GL_FLOAT 585 attribsMask |= FRAG_BIT_COL0; 586#endif 587 588 if (ctx->Fog.ColorSumEnabled || 589 (ctx->Light.Enabled && 590 ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) { 591 attribsMask |= FRAG_BIT_COL1; 592 } 593 594 if (swrast->_FogEnabled) 595 attribsMask |= FRAG_BIT_FOGC; 596 597 attribsMask |= (ctx->Texture._EnabledUnits << FRAG_ATTRIB_TEX0); 598 } 599 600 swrast->_ActiveAttribMask = attribsMask; 601 602 /* Update _ActiveAttribs[] list */ 603 { 604 GLuint i, num = 0; 605 for (i = 0; i < FRAG_ATTRIB_MAX; i++) { 606 if (attribsMask & (1 << i)) { 607 swrast->_ActiveAttribs[num++] = i; 608 /* how should this attribute be interpolated? */ 609 if (i == FRAG_ATTRIB_COL0 || i == FRAG_ATTRIB_COL1) 610 swrast->_InterpMode[i] = ctx->Light.ShadeModel; 611 else 612 swrast->_InterpMode[i] = GL_SMOOTH; 613 } 614 } 615 swrast->_NumActiveAttribs = num; 616 } 617} 618 619 620void 621_swrast_validate_derived( struct gl_context *ctx ) 622{ 623 SWcontext *swrast = SWRAST_CONTEXT(ctx); 624 625 if (swrast->NewState) { 626 if (swrast->NewState & _NEW_POLYGON) 627 _swrast_update_polygon( ctx ); 628 629 if (swrast->NewState & (_NEW_HINT | _NEW_PROGRAM)) 630 _swrast_update_fog_hint( ctx ); 631 632 if (swrast->NewState & _SWRAST_NEW_TEXTURE_ENV_MODE) 633 _swrast_update_texture_env( ctx ); 634 635 if (swrast->NewState & (_NEW_FOG | _NEW_PROGRAM)) 636 _swrast_update_fog_state( ctx ); 637 638 if (swrast->NewState & (_NEW_PROGRAM_CONSTANTS | _NEW_PROGRAM)) 639 _swrast_update_fragment_program( ctx, swrast->NewState ); 640 641 if (swrast->NewState & (_NEW_TEXTURE | _NEW_PROGRAM)) { 642 _swrast_update_texture_samplers( ctx ); 643 _swrast_validate_texture_images(ctx); 644 } 645 646 if (swrast->NewState & (_NEW_COLOR | _NEW_PROGRAM)) 647 _swrast_update_deferred_texture(ctx); 648 649 if (swrast->NewState & _SWRAST_NEW_RASTERMASK) 650 _swrast_update_rasterflags( ctx ); 651 652 if (swrast->NewState & (_NEW_DEPTH | 653 _NEW_FOG | 654 _NEW_LIGHT | 655 _NEW_PROGRAM | 656 _NEW_TEXTURE)) 657 _swrast_update_active_attribs(ctx); 658 659 if (swrast->NewState & (_NEW_FOG | 660 _NEW_PROGRAM | 661 _NEW_LIGHT | 662 _NEW_TEXTURE)) 663 _swrast_update_specular_vertex_add(ctx); 664 665 swrast->NewState = 0; 666 swrast->StateChanges = 0; 667 swrast->InvalidateState = _swrast_invalidate_state; 668 } 669} 670 671#define SWRAST_DEBUG 0 672 673/* Public entrypoints: See also s_accum.c, s_bitmap.c, etc. 674 */ 675void 676_swrast_Quad( struct gl_context *ctx, 677 const SWvertex *v0, const SWvertex *v1, 678 const SWvertex *v2, const SWvertex *v3 ) 679{ 680 if (SWRAST_DEBUG) { 681 _mesa_debug(ctx, "_swrast_Quad\n"); 682 _swrast_print_vertex( ctx, v0 ); 683 _swrast_print_vertex( ctx, v1 ); 684 _swrast_print_vertex( ctx, v2 ); 685 _swrast_print_vertex( ctx, v3 ); 686 } 687 SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v3 ); 688 SWRAST_CONTEXT(ctx)->Triangle( ctx, v1, v2, v3 ); 689} 690 691void 692_swrast_Triangle( struct gl_context *ctx, const SWvertex *v0, 693 const SWvertex *v1, const SWvertex *v2 ) 694{ 695 if (SWRAST_DEBUG) { 696 _mesa_debug(ctx, "_swrast_Triangle\n"); 697 _swrast_print_vertex( ctx, v0 ); 698 _swrast_print_vertex( ctx, v1 ); 699 _swrast_print_vertex( ctx, v2 ); 700 } 701 SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v2 ); 702} 703 704void 705_swrast_Line( struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1 ) 706{ 707 if (SWRAST_DEBUG) { 708 _mesa_debug(ctx, "_swrast_Line\n"); 709 _swrast_print_vertex( ctx, v0 ); 710 _swrast_print_vertex( ctx, v1 ); 711 } 712 SWRAST_CONTEXT(ctx)->Line( ctx, v0, v1 ); 713} 714 715void 716_swrast_Point( struct gl_context *ctx, const SWvertex *v0 ) 717{ 718 if (SWRAST_DEBUG) { 719 _mesa_debug(ctx, "_swrast_Point\n"); 720 _swrast_print_vertex( ctx, v0 ); 721 } 722 SWRAST_CONTEXT(ctx)->Point( ctx, v0 ); 723} 724 725void 726_swrast_InvalidateState( struct gl_context *ctx, GLbitfield new_state ) 727{ 728 if (SWRAST_DEBUG) { 729 _mesa_debug(ctx, "_swrast_InvalidateState\n"); 730 } 731 SWRAST_CONTEXT(ctx)->InvalidateState( ctx, new_state ); 732} 733 734void 735_swrast_ResetLineStipple( struct gl_context *ctx ) 736{ 737 if (SWRAST_DEBUG) { 738 _mesa_debug(ctx, "_swrast_ResetLineStipple\n"); 739 } 740 SWRAST_CONTEXT(ctx)->StippleCounter = 0; 741} 742 743void 744_swrast_SetFacing(struct gl_context *ctx, GLuint facing) 745{ 746 SWRAST_CONTEXT(ctx)->PointLineFacing = facing; 747} 748 749void 750_swrast_allow_vertex_fog( struct gl_context *ctx, GLboolean value ) 751{ 752 if (SWRAST_DEBUG) { 753 _mesa_debug(ctx, "_swrast_allow_vertex_fog %d\n", value); 754 } 755 SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT ); 756 SWRAST_CONTEXT(ctx)->AllowVertexFog = value; 757} 758 759void 760_swrast_allow_pixel_fog( struct gl_context *ctx, GLboolean value ) 761{ 762 if (SWRAST_DEBUG) { 763 _mesa_debug(ctx, "_swrast_allow_pixel_fog %d\n", value); 764 } 765 SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT ); 766 SWRAST_CONTEXT(ctx)->AllowPixelFog = value; 767} 768 769 770GLboolean 771_swrast_CreateContext( struct gl_context *ctx ) 772{ 773 GLuint i; 774 SWcontext *swrast = (SWcontext *)CALLOC(sizeof(SWcontext)); 775 776 if (SWRAST_DEBUG) { 777 _mesa_debug(ctx, "_swrast_CreateContext\n"); 778 } 779 780 if (!swrast) 781 return GL_FALSE; 782 783 swrast->NewState = ~0; 784 785 swrast->choose_point = _swrast_choose_point; 786 swrast->choose_line = _swrast_choose_line; 787 swrast->choose_triangle = _swrast_choose_triangle; 788 789 swrast->InvalidatePointMask = _SWRAST_NEW_POINT; 790 swrast->InvalidateLineMask = _SWRAST_NEW_LINE; 791 swrast->InvalidateTriangleMask = _SWRAST_NEW_TRIANGLE; 792 793 swrast->Point = _swrast_validate_point; 794 swrast->Line = _swrast_validate_line; 795 swrast->Triangle = _swrast_validate_triangle; 796 swrast->InvalidateState = _swrast_sleep; 797 swrast->BlendFunc = _swrast_validate_blend_func; 798 799 swrast->AllowVertexFog = GL_TRUE; 800 swrast->AllowPixelFog = GL_TRUE; 801 802 /* Optimized Accum buffer */ 803 swrast->_IntegerAccumMode = GL_FALSE; 804 swrast->_IntegerAccumScaler = 0.0; 805 806 for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++) 807 swrast->TextureSample[i] = NULL; 808 809 swrast->SpanArrays = MALLOC_STRUCT(sw_span_arrays); 810 if (!swrast->SpanArrays) { 811 FREE(swrast); 812 return GL_FALSE; 813 } 814 swrast->SpanArrays->ChanType = CHAN_TYPE; 815#if CHAN_TYPE == GL_UNSIGNED_BYTE 816 swrast->SpanArrays->rgba = swrast->SpanArrays->rgba8; 817#elif CHAN_TYPE == GL_UNSIGNED_SHORT 818 swrast->SpanArrays->rgba = swrast->SpanArrays->rgba16; 819#else 820 swrast->SpanArrays->rgba = swrast->SpanArrays->attribs[FRAG_ATTRIB_COL0]; 821#endif 822 823 /* init point span buffer */ 824 swrast->PointSpan.primitive = GL_POINT; 825 swrast->PointSpan.end = 0; 826 swrast->PointSpan.facing = 0; 827 swrast->PointSpan.array = swrast->SpanArrays; 828 829 swrast->TexelBuffer = (GLfloat *) MALLOC(ctx->Const.MaxTextureImageUnits * 830 MAX_WIDTH * 4 * sizeof(GLfloat)); 831 if (!swrast->TexelBuffer) { 832 FREE(swrast->SpanArrays); 833 FREE(swrast); 834 return GL_FALSE; 835 } 836 837 ctx->swrast_context = swrast; 838 839 return GL_TRUE; 840} 841 842void 843_swrast_DestroyContext( struct gl_context *ctx ) 844{ 845 SWcontext *swrast = SWRAST_CONTEXT(ctx); 846 847 if (SWRAST_DEBUG) { 848 _mesa_debug(ctx, "_swrast_DestroyContext\n"); 849 } 850 851 FREE( swrast->SpanArrays ); 852 if (swrast->ZoomedArrays) 853 FREE( swrast->ZoomedArrays ); 854 FREE( swrast->TexelBuffer ); 855 FREE( swrast ); 856 857 ctx->swrast_context = 0; 858} 859 860 861struct swrast_device_driver * 862_swrast_GetDeviceDriverReference( struct gl_context *ctx ) 863{ 864 SWcontext *swrast = SWRAST_CONTEXT(ctx); 865 return &swrast->Driver; 866} 867 868void 869_swrast_flush( struct gl_context *ctx ) 870{ 871 SWcontext *swrast = SWRAST_CONTEXT(ctx); 872 /* flush any pending fragments from rendering points */ 873 if (swrast->PointSpan.end > 0) { 874 _swrast_write_rgba_span(ctx, &(swrast->PointSpan)); 875 swrast->PointSpan.end = 0; 876 } 877} 878 879void 880_swrast_render_primitive( struct gl_context *ctx, GLenum prim ) 881{ 882 SWcontext *swrast = SWRAST_CONTEXT(ctx); 883 if (swrast->Primitive == GL_POINTS && prim != GL_POINTS) { 884 _swrast_flush(ctx); 885 } 886 swrast->Primitive = prim; 887} 888 889 890void 891_swrast_render_start( struct gl_context *ctx ) 892{ 893 SWcontext *swrast = SWRAST_CONTEXT(ctx); 894 if (swrast->Driver.SpanRenderStart) 895 swrast->Driver.SpanRenderStart( ctx ); 896 swrast->PointSpan.end = 0; 897} 898 899void 900_swrast_render_finish( struct gl_context *ctx ) 901{ 902 SWcontext *swrast = SWRAST_CONTEXT(ctx); 903 if (swrast->Driver.SpanRenderFinish) 904 swrast->Driver.SpanRenderFinish( ctx ); 905 906 _swrast_flush(ctx); 907} 908 909 910#define SWRAST_DEBUG_VERTICES 0 911 912void 913_swrast_print_vertex( struct gl_context *ctx, const SWvertex *v ) 914{ 915 GLuint i; 916 917 if (SWRAST_DEBUG_VERTICES) { 918 _mesa_debug(ctx, "win %f %f %f %f\n", 919 v->attrib[FRAG_ATTRIB_WPOS][0], 920 v->attrib[FRAG_ATTRIB_WPOS][1], 921 v->attrib[FRAG_ATTRIB_WPOS][2], 922 v->attrib[FRAG_ATTRIB_WPOS][3]); 923 924 for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) 925 if (ctx->Texture.Unit[i]._ReallyEnabled) 926 _mesa_debug(ctx, "texcoord[%d] %f %f %f %f\n", i, 927 v->attrib[FRAG_ATTRIB_TEX0 + i][0], 928 v->attrib[FRAG_ATTRIB_TEX0 + i][1], 929 v->attrib[FRAG_ATTRIB_TEX0 + i][2], 930 v->attrib[FRAG_ATTRIB_TEX0 + i][3]); 931 932#if CHAN_TYPE == GL_FLOAT 933 _mesa_debug(ctx, "color %f %f %f %f\n", 934 v->color[0], v->color[1], v->color[2], v->color[3]); 935#else 936 _mesa_debug(ctx, "color %d %d %d %d\n", 937 v->color[0], v->color[1], v->color[2], v->color[3]); 938#endif 939 _mesa_debug(ctx, "spec %g %g %g %g\n", 940 v->attrib[FRAG_ATTRIB_COL1][0], 941 v->attrib[FRAG_ATTRIB_COL1][1], 942 v->attrib[FRAG_ATTRIB_COL1][2], 943 v->attrib[FRAG_ATTRIB_COL1][3]); 944 _mesa_debug(ctx, "fog %f\n", v->attrib[FRAG_ATTRIB_FOGC][0]); 945 _mesa_debug(ctx, "index %f\n", v->attrib[FRAG_ATTRIB_CI][0]); 946 _mesa_debug(ctx, "pointsize %f\n", v->pointSize); 947 _mesa_debug(ctx, "\n"); 948 } 949} 950