s_context.c revision 3b4fbbc129c711a5aec8d653d5c6eb2e195f947c
1/* $Id: s_context.c,v 1.36 2002/07/09 01:22:52 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 4.1 6 * 7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 * Authors: 27 * Keith Whitwell <keithw@valinux.com> 28 */ 29 30#include "glheader.h" 31#include "context.h" 32#include "mtypes.h" 33#include "mem.h" 34 35#include "swrast.h" 36#include "s_points.h" 37#include "s_lines.h" 38#include "s_triangle.h" 39#include "s_blend.h" 40#include "s_context.h" 41#include "s_texture.h" 42 43 44/* 45 * Recompute the value of swrast->_RasterMask, etc. according to 46 * the current context. 47 */ 48static void 49_swrast_update_rasterflags( GLcontext *ctx ) 50{ 51 GLuint RasterMask = 0; 52 53 if (ctx->Color.AlphaEnabled) RasterMask |= ALPHATEST_BIT; 54 if (ctx->Color.BlendEnabled) RasterMask |= BLEND_BIT; 55 if (ctx->Depth.Test) RasterMask |= DEPTH_BIT; 56 if (ctx->Fog.Enabled) RasterMask |= FOG_BIT; 57 if (ctx->Scissor.Enabled) RasterMask |= CLIP_BIT; 58 if (ctx->Stencil.Enabled) RasterMask |= STENCIL_BIT; 59 if (ctx->Visual.rgbMode) { 60 const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask); 61 if (colorMask != 0xffffffff) RasterMask |= MASKING_BIT; 62 if (ctx->Color.ColorLogicOpEnabled) RasterMask |= LOGIC_OP_BIT; 63 if (ctx->Texture._EnabledUnits) RasterMask |= TEXTURE_BIT; 64 } 65 else { 66 if (ctx->Color.IndexMask != 0xffffffff) RasterMask |= MASKING_BIT; 67 if (ctx->Color.IndexLogicOpEnabled) RasterMask |= LOGIC_OP_BIT; 68 } 69 70 if (ctx->DrawBuffer->UseSoftwareAlphaBuffers 71 && ctx->Color.ColorMask[ACOMP] 72 && ctx->Color.DrawBuffer != GL_NONE) 73 RasterMask |= ALPHABUF_BIT; 74 75 if ( ctx->Viewport.X < 0 76 || ctx->Viewport.X + ctx->Viewport.Width > (GLint) ctx->DrawBuffer->Width 77 || ctx->Viewport.Y < 0 78 || ctx->Viewport.Y + ctx->Viewport.Height > (GLint) ctx->DrawBuffer->Height) { 79 RasterMask |= CLIP_BIT; 80 } 81 82 if (ctx->Depth.OcclusionTest) 83 RasterMask |= OCCLUSION_BIT; 84 85 86 /* If we're not drawing to exactly one color buffer set the 87 * MULTI_DRAW_BIT flag. Also set it if we're drawing to no 88 * buffers or the RGBA or CI mask disables all writes. 89 */ 90 if (ctx->Color._DrawDestMask != FRONT_LEFT_BIT && 91 ctx->Color._DrawDestMask != BACK_LEFT_BIT && 92 ctx->Color._DrawDestMask != FRONT_RIGHT_BIT && 93 ctx->Color._DrawDestMask != BACK_RIGHT_BIT) { 94 /* more than one color buffer designated for writing (or zero buffers) */ 95 RasterMask |= MULTI_DRAW_BIT; 96 } 97 else if (ctx->Visual.rgbMode && *((GLuint *) ctx->Color.ColorMask) == 0) { 98 RasterMask |= MULTI_DRAW_BIT; /* all RGBA channels disabled */ 99 } 100 else if (!ctx->Visual.rgbMode && ctx->Color.IndexMask==0) { 101 RasterMask |= MULTI_DRAW_BIT; /* all color index bits disabled */ 102 } 103 104 SWRAST_CONTEXT(ctx)->_RasterMask = RasterMask; 105} 106 107 108static void 109_swrast_update_polygon( GLcontext *ctx ) 110{ 111 GLfloat backface_sign = 1; 112 113 if (ctx->Polygon.CullFlag) { 114 backface_sign = 1; 115 switch(ctx->Polygon.CullFaceMode) { 116 case GL_BACK: 117 if(ctx->Polygon.FrontFace==GL_CCW) 118 backface_sign = -1; 119 break; 120 case GL_FRONT: 121 if(ctx->Polygon.FrontFace!=GL_CCW) 122 backface_sign = -1; 123 break; 124 default: 125 case GL_FRONT_AND_BACK: 126 backface_sign = 0; 127 break; 128 } 129 } 130 else { 131 backface_sign = 0; 132 } 133 134 SWRAST_CONTEXT(ctx)->_backface_sign = backface_sign; 135} 136 137 138static void 139_swrast_update_hint( GLcontext *ctx ) 140{ 141 SWcontext *swrast = SWRAST_CONTEXT(ctx); 142 swrast->_PreferPixelFog = (!swrast->AllowVertexFog || 143 (ctx->Hint.Fog == GL_NICEST && 144 swrast->AllowPixelFog)); 145} 146 147 148/* 149 * Update the swrast->_AnyTextureCombine flag. 150 */ 151static void 152_swrast_update_texture_env( GLcontext *ctx ) 153{ 154 SWcontext *swrast = SWRAST_CONTEXT(ctx); 155 GLuint i; 156 swrast->_AnyTextureCombine = GL_FALSE; 157 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { 158 if (ctx->Texture.Unit[i].EnvMode == GL_COMBINE_EXT || 159 ctx->Texture.Unit[i].EnvMode == GL_COMBINE4_NV) { 160 swrast->_AnyTextureCombine = GL_TRUE; 161 return; 162 } 163 } 164} 165 166 167#define _SWRAST_NEW_DERIVED (_SWRAST_NEW_RASTERMASK | \ 168 _NEW_TEXTURE | \ 169 _NEW_HINT | \ 170 _NEW_POLYGON ) 171 172/* State referenced by _swrast_choose_triangle, _swrast_choose_line. 173 */ 174#define _SWRAST_NEW_TRIANGLE (_SWRAST_NEW_DERIVED | \ 175 _NEW_RENDERMODE| \ 176 _NEW_POLYGON| \ 177 _NEW_DEPTH| \ 178 _NEW_STENCIL| \ 179 _NEW_COLOR| \ 180 _NEW_TEXTURE| \ 181 _SWRAST_NEW_RASTERMASK| \ 182 _NEW_LIGHT| \ 183 _NEW_FOG | \ 184 _DD_NEW_SEPARATE_SPECULAR) 185 186#define _SWRAST_NEW_LINE (_SWRAST_NEW_DERIVED | \ 187 _NEW_RENDERMODE| \ 188 _NEW_LINE| \ 189 _NEW_TEXTURE| \ 190 _NEW_LIGHT| \ 191 _NEW_FOG| \ 192 _NEW_DEPTH | \ 193 _DD_NEW_SEPARATE_SPECULAR) 194 195#define _SWRAST_NEW_POINT (_SWRAST_NEW_DERIVED | \ 196 _NEW_RENDERMODE | \ 197 _NEW_POINT | \ 198 _NEW_TEXTURE | \ 199 _NEW_LIGHT | \ 200 _NEW_FOG | \ 201 _DD_NEW_SEPARATE_SPECULAR) 202 203#define _SWRAST_NEW_TEXTURE_SAMPLE_FUNC _NEW_TEXTURE 204 205#define _SWRAST_NEW_TEXTURE_ENV_MODE _NEW_TEXTURE 206 207#define _SWRAST_NEW_BLEND_FUNC _NEW_COLOR 208 209 210 211/* Stub for swrast->Triangle to select a true triangle function 212 * after a state change. 213 */ 214static void 215_swrast_validate_triangle( GLcontext *ctx, 216 const SWvertex *v0, 217 const SWvertex *v1, 218 const SWvertex *v2 ) 219{ 220 SWcontext *swrast = SWRAST_CONTEXT(ctx); 221 222 _swrast_validate_derived( ctx ); 223 swrast->choose_triangle( ctx ); 224 225 if ((ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) && 226 ctx->Texture._EnabledUnits == 0) { 227 swrast->SpecTriangle = swrast->Triangle; 228 swrast->Triangle = _swrast_add_spec_terms_triangle; 229 } 230 231 swrast->Triangle( ctx, v0, v1, v2 ); 232} 233 234static void 235_swrast_validate_line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 ) 236{ 237 SWcontext *swrast = SWRAST_CONTEXT(ctx); 238 239 _swrast_validate_derived( ctx ); 240 swrast->choose_line( ctx ); 241 242 if ((ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) && 243 ctx->Texture._EnabledUnits == 0) { 244 swrast->SpecLine = swrast->Line; 245 swrast->Line = _swrast_add_spec_terms_line; 246 } 247 248 249 swrast->Line( ctx, v0, v1 ); 250} 251 252static void 253_swrast_validate_point( GLcontext *ctx, const SWvertex *v0 ) 254{ 255 SWcontext *swrast = SWRAST_CONTEXT(ctx); 256 257 _swrast_validate_derived( ctx ); 258 swrast->choose_point( ctx ); 259 260 if ((ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) && 261 ctx->Texture._EnabledUnits == 0) { 262 swrast->SpecPoint = swrast->Point; 263 swrast->Point = _swrast_add_spec_terms_point; 264 } 265 266 swrast->Point( ctx, v0 ); 267} 268 269static void 270_swrast_validate_blend_func( GLcontext *ctx, GLuint n, 271 const GLubyte mask[], 272 GLchan src[][4], 273 CONST GLchan dst[][4] ) 274{ 275 SWcontext *swrast = SWRAST_CONTEXT(ctx); 276 277 _swrast_validate_derived( ctx ); 278 _swrast_choose_blend_func( ctx ); 279 280 swrast->BlendFunc( ctx, n, mask, src, dst ); 281} 282 283 284static void 285_swrast_validate_texture_sample( GLcontext *ctx, GLuint texUnit, 286 const struct gl_texture_object *tObj, 287 GLuint n, GLfloat texcoords[][4], 288 const GLfloat lambda[], GLchan rgba[][4] ) 289{ 290 SWcontext *swrast = SWRAST_CONTEXT(ctx); 291 292 _swrast_validate_derived( ctx ); 293 _swrast_choose_texture_sample_func( ctx, texUnit, tObj ); 294 295 swrast->TextureSample[texUnit]( ctx, texUnit, tObj, n, texcoords, 296 lambda, rgba ); 297} 298 299 300static void 301_swrast_sleep( GLcontext *ctx, GLuint new_state ) 302{ 303} 304 305 306static void 307_swrast_invalidate_state( GLcontext *ctx, GLuint new_state ) 308{ 309 SWcontext *swrast = SWRAST_CONTEXT(ctx); 310 GLuint i; 311 312 swrast->NewState |= new_state; 313 314 /* After 10 statechanges without any swrast functions being called, 315 * put the module to sleep. 316 */ 317 if (++swrast->StateChanges > 10) { 318 swrast->InvalidateState = _swrast_sleep; 319 swrast->NewState = ~0; 320 new_state = ~0; 321 } 322 323 if (new_state & swrast->invalidate_triangle) 324 swrast->Triangle = _swrast_validate_triangle; 325 326 if (new_state & swrast->invalidate_line) 327 swrast->Line = _swrast_validate_line; 328 329 if (new_state & swrast->invalidate_point) 330 swrast->Point = _swrast_validate_point; 331 332 if (new_state & _SWRAST_NEW_BLEND_FUNC) 333 swrast->BlendFunc = _swrast_validate_blend_func; 334 335 if (new_state & _SWRAST_NEW_TEXTURE_SAMPLE_FUNC) 336 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) 337 swrast->TextureSample[i] = _swrast_validate_texture_sample; 338 339 if (ctx->Visual.rgbMode) { 340 ASSERT(swrast->Driver.WriteRGBASpan); 341 ASSERT(swrast->Driver.WriteRGBSpan); 342 ASSERT(swrast->Driver.WriteMonoRGBASpan); 343 ASSERT(swrast->Driver.WriteRGBAPixels); 344 ASSERT(swrast->Driver.WriteMonoRGBAPixels); 345 ASSERT(swrast->Driver.ReadRGBASpan); 346 ASSERT(swrast->Driver.ReadRGBAPixels); 347 } 348 else { 349 ASSERT(swrast->Driver.WriteCI32Span); 350 ASSERT(swrast->Driver.WriteCI8Span); 351 ASSERT(swrast->Driver.WriteMonoCISpan); 352 ASSERT(swrast->Driver.WriteCI32Pixels); 353 ASSERT(swrast->Driver.WriteMonoCIPixels); 354 ASSERT(swrast->Driver.ReadCI32Span); 355 ASSERT(swrast->Driver.ReadCI32Pixels); 356 } 357} 358 359 360void 361_swrast_validate_derived( GLcontext *ctx ) 362{ 363 SWcontext *swrast = SWRAST_CONTEXT(ctx); 364 365 if (swrast->NewState) { 366 if (swrast->NewState & _SWRAST_NEW_RASTERMASK) 367 _swrast_update_rasterflags( ctx ); 368 369 if (swrast->NewState & _NEW_POLYGON) 370 _swrast_update_polygon( ctx ); 371 372 if (swrast->NewState & _NEW_HINT) 373 _swrast_update_hint( ctx ); 374 375 if (swrast->NewState & _SWRAST_NEW_TEXTURE_ENV_MODE) 376 _swrast_update_texture_env( ctx ); 377 378 swrast->NewState = 0; 379 swrast->StateChanges = 0; 380 swrast->InvalidateState = _swrast_invalidate_state; 381 } 382} 383 384#define SWRAST_DEBUG 0 385 386/* Public entrypoints: See also s_accum.c, s_bitmap.c, etc. 387 */ 388void 389_swrast_Quad( GLcontext *ctx, 390 const SWvertex *v0, const SWvertex *v1, 391 const SWvertex *v2, const SWvertex *v3 ) 392{ 393 if (SWRAST_DEBUG) { 394 _mesa_debug(ctx, "_swrast_Quad\n"); 395 _swrast_print_vertex( ctx, v0 ); 396 _swrast_print_vertex( ctx, v1 ); 397 _swrast_print_vertex( ctx, v2 ); 398 _swrast_print_vertex( ctx, v3 ); 399 } 400 SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v3 ); 401 SWRAST_CONTEXT(ctx)->Triangle( ctx, v1, v2, v3 ); 402} 403 404void 405_swrast_Triangle( GLcontext *ctx, const SWvertex *v0, 406 const SWvertex *v1, const SWvertex *v2 ) 407{ 408 if (SWRAST_DEBUG) { 409 _mesa_debug(ctx, "_swrast_Triangle\n"); 410 _swrast_print_vertex( ctx, v0 ); 411 _swrast_print_vertex( ctx, v1 ); 412 _swrast_print_vertex( ctx, v2 ); 413 } 414 SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v2 ); 415} 416 417void 418_swrast_Line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 ) 419{ 420 if (SWRAST_DEBUG) { 421 _mesa_debug(ctx, "_swrast_Line\n"); 422 _swrast_print_vertex( ctx, v0 ); 423 _swrast_print_vertex( ctx, v1 ); 424 } 425 SWRAST_CONTEXT(ctx)->Line( ctx, v0, v1 ); 426} 427 428void 429_swrast_Point( GLcontext *ctx, const SWvertex *v0 ) 430{ 431 if (SWRAST_DEBUG) { 432 _mesa_debug(ctx, "_swrast_Point\n"); 433 _swrast_print_vertex( ctx, v0 ); 434 } 435 SWRAST_CONTEXT(ctx)->Point( ctx, v0 ); 436} 437 438void 439_swrast_InvalidateState( GLcontext *ctx, GLuint new_state ) 440{ 441 if (SWRAST_DEBUG) { 442 _mesa_debug(ctx, "_swrast_InvalidateState\n"); 443 } 444 SWRAST_CONTEXT(ctx)->InvalidateState( ctx, new_state ); 445} 446 447void 448_swrast_ResetLineStipple( GLcontext *ctx ) 449{ 450 if (SWRAST_DEBUG) { 451 _mesa_debug(ctx, "_swrast_ResetLineStipple\n"); 452 } 453 SWRAST_CONTEXT(ctx)->StippleCounter = 0; 454} 455 456void 457_swrast_allow_vertex_fog( GLcontext *ctx, GLboolean value ) 458{ 459 if (SWRAST_DEBUG) { 460 _mesa_debug(ctx, "_swrast_allow_vertex_fog %d\n", value); 461 } 462 SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT ); 463 SWRAST_CONTEXT(ctx)->AllowVertexFog = value; 464} 465 466void 467_swrast_allow_pixel_fog( GLcontext *ctx, GLboolean value ) 468{ 469 if (SWRAST_DEBUG) { 470 _mesa_debug(ctx, "_swrast_allow_pixel_fog %d\n", value); 471 } 472 SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT ); 473 SWRAST_CONTEXT(ctx)->AllowPixelFog = value; 474} 475 476 477GLboolean 478_swrast_CreateContext( GLcontext *ctx ) 479{ 480 GLuint i; 481 SWcontext *swrast = (SWcontext *)CALLOC(sizeof(SWcontext)); 482 483 if (SWRAST_DEBUG) { 484 _mesa_debug(ctx, "_swrast_CreateContext\n"); 485 } 486 487 if (!swrast) 488 return GL_FALSE; 489 490 swrast->NewState = ~0; 491 492 swrast->choose_point = _swrast_choose_point; 493 swrast->choose_line = _swrast_choose_line; 494 swrast->choose_triangle = _swrast_choose_triangle; 495 496 swrast->invalidate_point = _SWRAST_NEW_POINT; 497 swrast->invalidate_line = _SWRAST_NEW_LINE; 498 swrast->invalidate_triangle = _SWRAST_NEW_TRIANGLE; 499 500 swrast->Point = _swrast_validate_point; 501 swrast->Line = _swrast_validate_line; 502 swrast->Triangle = _swrast_validate_triangle; 503 swrast->InvalidateState = _swrast_sleep; 504 swrast->BlendFunc = _swrast_validate_blend_func; 505 506 swrast->AllowVertexFog = GL_TRUE; 507 swrast->AllowPixelFog = GL_TRUE; 508 509 /* Optimized Accum buffer */ 510 swrast->_IntegerAccumMode = GL_TRUE; 511 swrast->_IntegerAccumScaler = 0.0; 512 513 for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) 514 swrast->TextureSample[i] = _swrast_validate_texture_sample; 515 516 swrast->span = (struct sw_span *) MALLOC(sizeof(struct sw_span)); 517 if (!swrast->span) { 518 FREE(swrast); 519 return GL_FALSE; 520 } 521 522 assert(ctx->Const.MaxTextureUnits > 0); 523 assert(ctx->Const.MaxTextureUnits <= MAX_TEXTURE_UNITS); 524 525 swrast->TexelBuffer = (GLchan *) MALLOC(ctx->Const.MaxTextureUnits * 526 MAX_WIDTH * 4 * sizeof(GLchan)); 527 if (!swrast->TexelBuffer) { 528 FREE(swrast->span); 529 FREE(swrast); 530 return GL_FALSE; 531 } 532 533 ctx->swrast_context = swrast; 534 535 return GL_TRUE; 536} 537 538void 539_swrast_DestroyContext( GLcontext *ctx ) 540{ 541 SWcontext *swrast = SWRAST_CONTEXT(ctx); 542 543 if (SWRAST_DEBUG) { 544 _mesa_debug(ctx, "_swrast_DestroyContext\n"); 545 } 546 547 FREE( swrast->span ); 548 FREE( swrast->TexelBuffer ); 549 FREE( swrast ); 550 551 ctx->swrast_context = 0; 552} 553 554 555struct swrast_device_driver * 556_swrast_GetDeviceDriverReference( GLcontext *ctx ) 557{ 558 SWcontext *swrast = SWRAST_CONTEXT(ctx); 559 return &swrast->Driver; 560} 561 562#define SWRAST_DEBUG_VERTICES 0 563 564void 565_swrast_print_vertex( GLcontext *ctx, const SWvertex *v ) 566{ 567 GLuint i; 568 569 if (SWRAST_DEBUG_VERTICES) { 570 _mesa_debug(ctx, "win %f %f %f %f\n", 571 v->win[0], v->win[1], v->win[2], v->win[3]); 572 573 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) 574 if (ctx->Texture.Unit[i]._ReallyEnabled) 575 _mesa_debug(ctx, "texcoord[%d] %f %f %f %f\n", i, 576 v->texcoord[i][0], v->texcoord[i][1], 577 v->texcoord[i][2], v->texcoord[i][3]); 578 579#if CHAN_TYPE == GL_FLOAT 580 _mesa_debug(ctx, "color %f %f %f %f\n", 581 v->color[0], v->color[1], v->color[2], v->color[3]); 582 _mesa_debug(ctx, "spec %f %f %f %f\n", 583 v->specular[0], v->specular[1], 584 v->specular[2], v->specular[3]); 585#else 586 _mesa_debug(ctx, "color %d %d %d %d\n", 587 v->color[0], v->color[1], v->color[2], v->color[3]); 588 _mesa_debug(ctx, "spec %d %d %d %d\n", 589 v->specular[0], v->specular[1], 590 v->specular[2], v->specular[3]); 591#endif 592 _mesa_debug(ctx, "fog %f\n", v->fog); 593 _mesa_debug(ctx, "index %d\n", v->index); 594 _mesa_debug(ctx, "pointsize %f\n", v->pointSize); 595 _mesa_debug(ctx, "\n"); 596 } 597} 598 599 600void 601_swrast_flush( GLcontext *ctx ) 602{ 603 /* no-op */ 604} 605