s_context.c revision a6c423d95663cfd8601cf84e10e8e1b12fa6ef15
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.1 4 * 5 * Copyright (C) 1999-2004 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 "imports.h" 30#include "bufferobj.h" 31#include "context.h" 32#include "colormac.h" 33#include "mtypes.h" 34#include "program.h" 35#include "texobj.h" 36#include "nvfragprog.h" 37 38#include "swrast.h" 39#include "s_blend.h" 40#include "s_context.h" 41#include "s_lines.h" 42#include "s_points.h" 43#include "s_span.h" 44#include "s_triangle.h" 45#include "s_texture.h" 46 47 48/** 49 * Recompute the value of swrast->_RasterMask, etc. according to 50 * the current context. The _RasterMask field can be easily tested by 51 * drivers to determine certain basic GL state (does the primitive need 52 * stenciling, logic-op, fog, etc?). 53 */ 54static void 55_swrast_update_rasterflags( GLcontext *ctx ) 56{ 57 GLuint rasterMask = 0; 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 (ctx->Fog.Enabled) rasterMask |= FOG_BIT; 63 if (ctx->Scissor.Enabled) rasterMask |= CLIP_BIT; 64 if (ctx->Stencil.Enabled) rasterMask |= STENCIL_BIT; 65 if (ctx->Visual.rgbMode) { 66 const GLuint colorMask = *((GLuint *) &ctx->Color.ColorMask); 67 if (colorMask != 0xffffffff) rasterMask |= MASKING_BIT; 68 if (ctx->Color._LogicOpEnabled) rasterMask |= LOGIC_OP_BIT; 69 if (ctx->Texture._EnabledUnits) rasterMask |= TEXTURE_BIT; 70 } 71 else { 72 if (ctx->Color.IndexMask != 0xffffffff) rasterMask |= MASKING_BIT; 73 if (ctx->Color.IndexLogicOpEnabled) rasterMask |= LOGIC_OP_BIT; 74 } 75 76 if (ctx->DrawBuffer->UseSoftwareAlphaBuffers 77 && ctx->Color.ColorMask[ACOMP] 78 && ctx->Color.DrawBuffer != GL_NONE) 79 rasterMask |= ALPHABUF_BIT; 80 81 if ( ctx->Viewport.X < 0 82 || ctx->Viewport.X + ctx->Viewport.Width > (GLint) ctx->DrawBuffer->Width 83 || ctx->Viewport.Y < 0 84 || ctx->Viewport.Y + ctx->Viewport.Height > (GLint) ctx->DrawBuffer->Height) { 85 rasterMask |= CLIP_BIT; 86 } 87 88 if (ctx->Depth.OcclusionTest || ctx->Occlusion.Active) 89 rasterMask |= OCCLUSION_BIT; 90 91 92 /* If we're not drawing to exactly one color buffer set the 93 * MULTI_DRAW_BIT flag. Also set it if we're drawing to no 94 * buffers or the RGBA or CI mask disables all writes. 95 */ 96 if (_mesa_bitcount(ctx->Color._DrawDestMask) != 1) { 97 /* more than one color buffer designated for writing (or zero buffers) */ 98 rasterMask |= MULTI_DRAW_BIT; 99 } 100 else if (ctx->Visual.rgbMode && *((GLuint *) ctx->Color.ColorMask) == 0) { 101 rasterMask |= MULTI_DRAW_BIT; /* all RGBA channels disabled */ 102 } 103 else if (!ctx->Visual.rgbMode && ctx->Color.IndexMask==0) { 104 rasterMask |= MULTI_DRAW_BIT; /* all color index bits disabled */ 105 } 106 107 if (ctx->FragmentProgram._Enabled) { 108 rasterMask |= FRAGPROG_BIT; 109 } 110 111 SWRAST_CONTEXT(ctx)->_RasterMask = rasterMask; 112} 113 114 115/** 116 * Examine polycon culls tate to compute the _BackfaceSign field. 117 * _BackfaceSign will be 0 if no culling, -1 if culling back-faces, 118 * and 1 if culling front-faces. The Polygon FrontFace state also 119 * factors in. 120 */ 121static void 122_swrast_update_polygon( GLcontext *ctx ) 123{ 124 GLfloat backface_sign = 1; 125 126 if (ctx->Polygon.CullFlag) { 127 backface_sign = 1; 128 switch(ctx->Polygon.CullFaceMode) { 129 case GL_BACK: 130 if(ctx->Polygon.FrontFace==GL_CCW) 131 backface_sign = -1; 132 break; 133 case GL_FRONT: 134 if(ctx->Polygon.FrontFace!=GL_CCW) 135 backface_sign = -1; 136 break; 137 default: 138 case GL_FRONT_AND_BACK: 139 backface_sign = 0; 140 break; 141 } 142 } 143 else { 144 backface_sign = 0; 145 } 146 147 SWRAST_CONTEXT(ctx)->_BackfaceSign = backface_sign; 148} 149 150 151/** 152 * Update the _PreferPixelFog field to indicate if we need to compute 153 * fog factors per-fragment. 154 */ 155static void 156_swrast_update_fog_hint( GLcontext *ctx ) 157{ 158 SWcontext *swrast = SWRAST_CONTEXT(ctx); 159 swrast->_PreferPixelFog = (!swrast->AllowVertexFog || 160 ctx->FragmentProgram._Enabled || 161 (ctx->Hint.Fog == GL_NICEST && 162 swrast->AllowPixelFog)); 163} 164 165 166 167/** 168 * Update the swrast->_AnyTextureCombine flag. 169 */ 170static void 171_swrast_update_texture_env( GLcontext *ctx ) 172{ 173 SWcontext *swrast = SWRAST_CONTEXT(ctx); 174 GLuint i; 175 swrast->_AnyTextureCombine = GL_FALSE; 176 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { 177 if (ctx->Texture.Unit[i].EnvMode == GL_COMBINE_EXT || 178 ctx->Texture.Unit[i].EnvMode == GL_COMBINE4_NV) { 179 swrast->_AnyTextureCombine = GL_TRUE; 180 return; 181 } 182 } 183} 184 185 186/** 187 * Update swrast->_FogColor and swrast->_FogEnable values. 188 */ 189static void 190_swrast_update_fog_state( GLcontext *ctx ) 191{ 192 SWcontext *swrast = SWRAST_CONTEXT(ctx); 193 194 /* convert fog color to GLchan values */ 195 CLAMPED_FLOAT_TO_CHAN(swrast->_FogColor[RCOMP], ctx->Fog.Color[RCOMP]); 196 CLAMPED_FLOAT_TO_CHAN(swrast->_FogColor[GCOMP], ctx->Fog.Color[GCOMP]); 197 CLAMPED_FLOAT_TO_CHAN(swrast->_FogColor[BCOMP], ctx->Fog.Color[BCOMP]); 198 199 /* determine if fog is needed */ 200 swrast->_FogEnabled = GL_FALSE; 201 if (ctx->Fog.Enabled) { 202 swrast->_FogEnabled = GL_TRUE; 203 } 204 else if (ctx->FragmentProgram._Enabled && 205 ctx->FragmentProgram.Current->Base.Target == GL_FRAGMENT_PROGRAM_ARB) { 206 const struct fragment_program *p; 207 p = (struct fragment_program *) ctx->FragmentProgram.Current; 208 if (p->FogOption != GL_NONE) { 209 swrast->_FogEnabled = GL_TRUE; 210 } 211 } 212} 213 214 215/** 216 * Update state for running fragment programs. Basically, load the 217 * program parameters with current state values. 218 */ 219static void 220_swrast_update_fragment_program( GLcontext *ctx ) 221{ 222 if (ctx->FragmentProgram._Enabled) { 223 struct fragment_program *program = ctx->FragmentProgram.Current; 224 _mesa_load_state_parameters(ctx, program->Parameters); 225 } 226} 227 228 229 230#define _SWRAST_NEW_DERIVED (_SWRAST_NEW_RASTERMASK | \ 231 _NEW_TEXTURE | \ 232 _NEW_HINT | \ 233 _NEW_POLYGON ) 234 235/* State referenced by _swrast_choose_triangle, _swrast_choose_line. 236 */ 237#define _SWRAST_NEW_TRIANGLE (_SWRAST_NEW_DERIVED | \ 238 _NEW_RENDERMODE| \ 239 _NEW_POLYGON| \ 240 _NEW_DEPTH| \ 241 _NEW_STENCIL| \ 242 _NEW_COLOR| \ 243 _NEW_TEXTURE| \ 244 _SWRAST_NEW_RASTERMASK| \ 245 _NEW_LIGHT| \ 246 _NEW_FOG | \ 247 _DD_NEW_SEPARATE_SPECULAR) 248 249#define _SWRAST_NEW_LINE (_SWRAST_NEW_DERIVED | \ 250 _NEW_RENDERMODE| \ 251 _NEW_LINE| \ 252 _NEW_TEXTURE| \ 253 _NEW_LIGHT| \ 254 _NEW_FOG| \ 255 _NEW_DEPTH | \ 256 _DD_NEW_SEPARATE_SPECULAR) 257 258#define _SWRAST_NEW_POINT (_SWRAST_NEW_DERIVED | \ 259 _NEW_RENDERMODE | \ 260 _NEW_POINT | \ 261 _NEW_TEXTURE | \ 262 _NEW_LIGHT | \ 263 _NEW_FOG | \ 264 _DD_NEW_SEPARATE_SPECULAR) 265 266#define _SWRAST_NEW_TEXTURE_SAMPLE_FUNC _NEW_TEXTURE 267 268#define _SWRAST_NEW_TEXTURE_ENV_MODE _NEW_TEXTURE 269 270#define _SWRAST_NEW_BLEND_FUNC _NEW_COLOR 271 272 273 274/** 275 * Stub for swrast->Triangle to select a true triangle function 276 * after a state change. 277 */ 278static void 279_swrast_validate_triangle( GLcontext *ctx, 280 const SWvertex *v0, 281 const SWvertex *v1, 282 const SWvertex *v2 ) 283{ 284 SWcontext *swrast = SWRAST_CONTEXT(ctx); 285 286 _swrast_validate_derived( ctx ); 287 swrast->choose_triangle( ctx ); 288 289 if (ctx->Texture._EnabledUnits == 0 290 && NEED_SECONDARY_COLOR(ctx) 291 && !ctx->FragmentProgram._Enabled) { 292 /* separate specular color, but no texture */ 293 swrast->SpecTriangle = swrast->Triangle; 294 swrast->Triangle = _swrast_add_spec_terms_triangle; 295 } 296 297 swrast->Triangle( ctx, v0, v1, v2 ); 298} 299 300/** 301 * Called via swrast->Line. Examine current GL state and choose a software 302 * line routine. Then call it. 303 */ 304static void 305_swrast_validate_line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 ) 306{ 307 SWcontext *swrast = SWRAST_CONTEXT(ctx); 308 309 _swrast_validate_derived( ctx ); 310 swrast->choose_line( ctx ); 311 312 if (ctx->Texture._EnabledUnits == 0 313 && NEED_SECONDARY_COLOR(ctx) 314 && !ctx->FragmentProgram._Enabled) { 315 swrast->SpecLine = swrast->Line; 316 swrast->Line = _swrast_add_spec_terms_line; 317 } 318 319 320 swrast->Line( ctx, v0, v1 ); 321} 322 323/** 324 * Called via swrast->Point. Examine current GL state and choose a software 325 * point routine. Then call it. 326 */ 327static void 328_swrast_validate_point( GLcontext *ctx, const SWvertex *v0 ) 329{ 330 SWcontext *swrast = SWRAST_CONTEXT(ctx); 331 332 _swrast_validate_derived( ctx ); 333 swrast->choose_point( ctx ); 334 335 if (ctx->Texture._EnabledUnits == 0 336 && NEED_SECONDARY_COLOR(ctx) 337 && !ctx->FragmentProgram._Enabled) { 338 swrast->SpecPoint = swrast->Point; 339 swrast->Point = _swrast_add_spec_terms_point; 340 } 341 342 swrast->Point( ctx, v0 ); 343} 344 345 346/** 347 * Called via swrast->BlendFunc. Examine GL state to choose a blending 348 * function, then call it. 349 */ 350static void _ASMAPI 351_swrast_validate_blend_func( GLcontext *ctx, GLuint n, 352 const GLubyte mask[], 353 GLchan src[][4], 354 CONST GLchan dst[][4] ) 355{ 356 SWcontext *swrast = SWRAST_CONTEXT(ctx); 357 358 _swrast_validate_derived( ctx ); 359 _swrast_choose_blend_func( ctx ); 360 361 swrast->BlendFunc( ctx, n, mask, src, dst ); 362} 363 364 365/** 366 * Called via the swrast->TextureSample[i] function pointer. 367 * Basically, given a texture object, an array of texture coords 368 * and an array of level-of-detail values, return an array of colors. 369 * In this case, determine the correct texture sampling routine 370 * (depending on filter mode, texture dimensions, etc) then call the 371 * sampler routine. 372 */ 373static void 374_swrast_validate_texture_sample( GLcontext *ctx, GLuint texUnit, 375 const struct gl_texture_object *tObj, 376 GLuint n, const GLfloat texcoords[][4], 377 const GLfloat lambda[], GLchan rgba[][4] ) 378{ 379 SWcontext *swrast = SWRAST_CONTEXT(ctx); 380 381 _swrast_validate_derived( ctx ); 382 383 /* Compute min/mag filter threshold */ 384 if (tObj && tObj->MinFilter != tObj->MagFilter) { 385 if (tObj->MagFilter == GL_LINEAR 386 && (tObj->MinFilter == GL_NEAREST_MIPMAP_NEAREST || 387 tObj->MinFilter == GL_NEAREST_MIPMAP_LINEAR)) { 388 swrast->_MinMagThresh[texUnit] = 0.5F; 389 } 390 else { 391 swrast->_MinMagThresh[texUnit] = 0.0F; 392 } 393 } 394 395 swrast->TextureSample[texUnit] = 396 _swrast_choose_texture_sample_func( ctx, tObj ); 397 398 swrast->TextureSample[texUnit]( ctx, texUnit, tObj, n, texcoords, 399 lambda, rgba ); 400} 401 402 403static void 404_swrast_sleep( GLcontext *ctx, GLuint new_state ) 405{ 406 (void) ctx; (void) new_state; 407} 408 409 410static void 411_swrast_invalidate_state( GLcontext *ctx, GLuint new_state ) 412{ 413 SWcontext *swrast = SWRAST_CONTEXT(ctx); 414 GLuint i; 415 416 swrast->NewState |= new_state; 417 418 /* After 10 statechanges without any swrast functions being called, 419 * put the module to sleep. 420 */ 421 if (++swrast->StateChanges > 10) { 422 swrast->InvalidateState = _swrast_sleep; 423 swrast->NewState = ~0; 424 new_state = ~0; 425 } 426 427 if (new_state & swrast->invalidate_triangle) 428 swrast->Triangle = _swrast_validate_triangle; 429 430 if (new_state & swrast->invalidate_line) 431 swrast->Line = _swrast_validate_line; 432 433 if (new_state & swrast->invalidate_point) 434 swrast->Point = _swrast_validate_point; 435 436 if (new_state & _SWRAST_NEW_BLEND_FUNC) 437 swrast->BlendFunc = _swrast_validate_blend_func; 438 439 if (new_state & _SWRAST_NEW_TEXTURE_SAMPLE_FUNC) 440 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) 441 swrast->TextureSample[i] = _swrast_validate_texture_sample; 442 443 /* Debug checks */ 444 if (ctx->Visual.rgbMode) { 445 ASSERT(swrast->Driver.WriteRGBASpan); 446 ASSERT(swrast->Driver.WriteRGBSpan); 447 ASSERT(swrast->Driver.WriteMonoRGBASpan); 448 ASSERT(swrast->Driver.WriteRGBAPixels); 449 ASSERT(swrast->Driver.WriteMonoRGBAPixels); 450 ASSERT(swrast->Driver.ReadRGBASpan); 451 ASSERT(swrast->Driver.ReadRGBAPixels); 452 } 453 else { 454 ASSERT(swrast->Driver.WriteCI32Span); 455 ASSERT(swrast->Driver.WriteCI8Span); 456 ASSERT(swrast->Driver.WriteMonoCISpan); 457 ASSERT(swrast->Driver.WriteCI32Pixels); 458 ASSERT(swrast->Driver.WriteMonoCIPixels); 459 ASSERT(swrast->Driver.ReadCI32Span); 460 ASSERT(swrast->Driver.ReadCI32Pixels); 461 } 462} 463 464 465void 466_swrast_validate_derived( GLcontext *ctx ) 467{ 468 SWcontext *swrast = SWRAST_CONTEXT(ctx); 469 470 if (swrast->NewState) { 471 if (swrast->NewState & _SWRAST_NEW_RASTERMASK) 472 _swrast_update_rasterflags( ctx ); 473 474 if (swrast->NewState & _NEW_POLYGON) 475 _swrast_update_polygon( ctx ); 476 477 if (swrast->NewState & (_NEW_HINT | _NEW_PROGRAM)) 478 _swrast_update_fog_hint( ctx ); 479 480 if (swrast->NewState & _SWRAST_NEW_TEXTURE_ENV_MODE) 481 _swrast_update_texture_env( ctx ); 482 483 if (swrast->NewState & _NEW_FOG) 484 _swrast_update_fog_state( ctx ); 485 486 if (swrast->NewState & _NEW_PROGRAM) 487 _swrast_update_fragment_program( ctx ); 488 489 swrast->NewState = 0; 490 swrast->StateChanges = 0; 491 swrast->InvalidateState = _swrast_invalidate_state; 492 } 493} 494 495#define SWRAST_DEBUG 0 496 497/* Public entrypoints: See also s_accum.c, s_bitmap.c, etc. 498 */ 499void 500_swrast_Quad( GLcontext *ctx, 501 const SWvertex *v0, const SWvertex *v1, 502 const SWvertex *v2, const SWvertex *v3 ) 503{ 504 if (SWRAST_DEBUG) { 505 _mesa_debug(ctx, "_swrast_Quad\n"); 506 _swrast_print_vertex( ctx, v0 ); 507 _swrast_print_vertex( ctx, v1 ); 508 _swrast_print_vertex( ctx, v2 ); 509 _swrast_print_vertex( ctx, v3 ); 510 } 511 SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v3 ); 512 SWRAST_CONTEXT(ctx)->Triangle( ctx, v1, v2, v3 ); 513} 514 515void 516_swrast_Triangle( GLcontext *ctx, const SWvertex *v0, 517 const SWvertex *v1, const SWvertex *v2 ) 518{ 519 if (SWRAST_DEBUG) { 520 _mesa_debug(ctx, "_swrast_Triangle\n"); 521 _swrast_print_vertex( ctx, v0 ); 522 _swrast_print_vertex( ctx, v1 ); 523 _swrast_print_vertex( ctx, v2 ); 524 } 525 SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v2 ); 526} 527 528void 529_swrast_Line( GLcontext *ctx, const SWvertex *v0, const SWvertex *v1 ) 530{ 531 if (SWRAST_DEBUG) { 532 _mesa_debug(ctx, "_swrast_Line\n"); 533 _swrast_print_vertex( ctx, v0 ); 534 _swrast_print_vertex( ctx, v1 ); 535 } 536 SWRAST_CONTEXT(ctx)->Line( ctx, v0, v1 ); 537} 538 539void 540_swrast_Point( GLcontext *ctx, const SWvertex *v0 ) 541{ 542 if (SWRAST_DEBUG) { 543 _mesa_debug(ctx, "_swrast_Point\n"); 544 _swrast_print_vertex( ctx, v0 ); 545 } 546 SWRAST_CONTEXT(ctx)->Point( ctx, v0 ); 547} 548 549void 550_swrast_InvalidateState( GLcontext *ctx, GLuint new_state ) 551{ 552 if (SWRAST_DEBUG) { 553 _mesa_debug(ctx, "_swrast_InvalidateState\n"); 554 } 555 SWRAST_CONTEXT(ctx)->InvalidateState( ctx, new_state ); 556} 557 558void 559_swrast_ResetLineStipple( GLcontext *ctx ) 560{ 561 if (SWRAST_DEBUG) { 562 _mesa_debug(ctx, "_swrast_ResetLineStipple\n"); 563 } 564 SWRAST_CONTEXT(ctx)->StippleCounter = 0; 565} 566 567void 568_swrast_allow_vertex_fog( GLcontext *ctx, GLboolean value ) 569{ 570 if (SWRAST_DEBUG) { 571 _mesa_debug(ctx, "_swrast_allow_vertex_fog %d\n", value); 572 } 573 SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT ); 574 SWRAST_CONTEXT(ctx)->AllowVertexFog = value; 575} 576 577void 578_swrast_allow_pixel_fog( GLcontext *ctx, GLboolean value ) 579{ 580 if (SWRAST_DEBUG) { 581 _mesa_debug(ctx, "_swrast_allow_pixel_fog %d\n", value); 582 } 583 SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT ); 584 SWRAST_CONTEXT(ctx)->AllowPixelFog = value; 585} 586 587 588GLboolean 589_swrast_CreateContext( GLcontext *ctx ) 590{ 591 GLuint i; 592 SWcontext *swrast = (SWcontext *)CALLOC(sizeof(SWcontext)); 593 594 if (SWRAST_DEBUG) { 595 _mesa_debug(ctx, "_swrast_CreateContext\n"); 596 } 597 598 if (!swrast) 599 return GL_FALSE; 600 601 swrast->NewState = ~0; 602 603 swrast->choose_point = _swrast_choose_point; 604 swrast->choose_line = _swrast_choose_line; 605 swrast->choose_triangle = _swrast_choose_triangle; 606 607 swrast->invalidate_point = _SWRAST_NEW_POINT; 608 swrast->invalidate_line = _SWRAST_NEW_LINE; 609 swrast->invalidate_triangle = _SWRAST_NEW_TRIANGLE; 610 611 swrast->Point = _swrast_validate_point; 612 swrast->Line = _swrast_validate_line; 613 swrast->Triangle = _swrast_validate_triangle; 614 swrast->InvalidateState = _swrast_sleep; 615 swrast->BlendFunc = _swrast_validate_blend_func; 616 617 swrast->AllowVertexFog = GL_TRUE; 618 swrast->AllowPixelFog = GL_TRUE; 619 620 if (ctx->Visual.doubleBufferMode) 621 swrast->CurrentBufferBit = DD_BACK_LEFT_BIT; 622 else 623 swrast->CurrentBufferBit = DD_FRONT_LEFT_BIT; 624 625 /* Optimized Accum buffer */ 626 swrast->_IntegerAccumMode = GL_TRUE; 627 swrast->_IntegerAccumScaler = 0.0; 628 629 for (i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++) 630 swrast->TextureSample[i] = _swrast_validate_texture_sample; 631 632 swrast->SpanArrays = MALLOC_STRUCT(span_arrays); 633 if (!swrast->SpanArrays) { 634 FREE(swrast); 635 return GL_FALSE; 636 } 637 638 /* init point span buffer */ 639 swrast->PointSpan.primitive = GL_POINT; 640 swrast->PointSpan.start = 0; 641 swrast->PointSpan.end = 0; 642 swrast->PointSpan.facing = 0; 643 swrast->PointSpan.array = swrast->SpanArrays; 644 645 assert(ctx->Const.MaxTextureUnits > 0); 646 assert(ctx->Const.MaxTextureUnits <= MAX_TEXTURE_UNITS); 647 648 swrast->TexelBuffer = (GLchan *) MALLOC(ctx->Const.MaxTextureUnits * 649 MAX_WIDTH * 4 * sizeof(GLchan)); 650 if (!swrast->TexelBuffer) { 651 FREE(swrast->SpanArrays); 652 FREE(swrast); 653 return GL_FALSE; 654 } 655 656 ctx->swrast_context = swrast; 657 658 return GL_TRUE; 659} 660 661void 662_swrast_DestroyContext( GLcontext *ctx ) 663{ 664 SWcontext *swrast = SWRAST_CONTEXT(ctx); 665 666 if (SWRAST_DEBUG) { 667 _mesa_debug(ctx, "_swrast_DestroyContext\n"); 668 } 669 670 FREE( swrast->SpanArrays ); 671 FREE( swrast->TexelBuffer ); 672 FREE( swrast ); 673 674 ctx->swrast_context = 0; 675} 676 677 678struct swrast_device_driver * 679_swrast_GetDeviceDriverReference( GLcontext *ctx ) 680{ 681 SWcontext *swrast = SWRAST_CONTEXT(ctx); 682 return &swrast->Driver; 683} 684 685void 686_swrast_flush( GLcontext *ctx ) 687{ 688 SWcontext *swrast = SWRAST_CONTEXT(ctx); 689 /* flush any pending fragments from rendering points */ 690 if (swrast->PointSpan.end > 0) { 691 if (ctx->Visual.rgbMode) { 692 if (ctx->Texture._EnabledCoordUnits) 693 _swrast_write_texture_span(ctx, &(swrast->PointSpan)); 694 else 695 _swrast_write_rgba_span(ctx, &(swrast->PointSpan)); 696 } 697 else { 698 _swrast_write_index_span(ctx, &(swrast->PointSpan)); 699 } 700 swrast->PointSpan.end = 0; 701 } 702} 703 704void 705_swrast_render_primitive( GLcontext *ctx, GLenum prim ) 706{ 707 SWcontext *swrast = SWRAST_CONTEXT(ctx); 708 if (swrast->Primitive == GL_POINTS && prim != GL_POINTS) { 709 _swrast_flush(ctx); 710 } 711 swrast->Primitive = prim; 712} 713 714 715void 716_swrast_render_start( GLcontext *ctx ) 717{ 718 SWcontext *swrast = SWRAST_CONTEXT(ctx); 719 if (swrast->Driver.SpanRenderStart) 720 swrast->Driver.SpanRenderStart( ctx ); 721 swrast->PointSpan.end = 0; 722} 723 724void 725_swrast_render_finish( GLcontext *ctx ) 726{ 727 SWcontext *swrast = SWRAST_CONTEXT(ctx); 728 if (swrast->Driver.SpanRenderFinish) 729 swrast->Driver.SpanRenderFinish( ctx ); 730 731 _swrast_flush(ctx); 732} 733 734 735#define SWRAST_DEBUG_VERTICES 0 736 737void 738_swrast_print_vertex( GLcontext *ctx, const SWvertex *v ) 739{ 740 GLuint i; 741 742 if (SWRAST_DEBUG_VERTICES) { 743 _mesa_debug(ctx, "win %f %f %f %f\n", 744 v->win[0], v->win[1], v->win[2], v->win[3]); 745 746 for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) 747 if (ctx->Texture.Unit[i]._ReallyEnabled) 748 _mesa_debug(ctx, "texcoord[%d] %f %f %f %f\n", i, 749 v->texcoord[i][0], v->texcoord[i][1], 750 v->texcoord[i][2], v->texcoord[i][3]); 751 752#if CHAN_TYPE == GL_FLOAT 753 _mesa_debug(ctx, "color %f %f %f %f\n", 754 v->color[0], v->color[1], v->color[2], v->color[3]); 755 _mesa_debug(ctx, "spec %f %f %f %f\n", 756 v->specular[0], v->specular[1], 757 v->specular[2], v->specular[3]); 758#else 759 _mesa_debug(ctx, "color %d %d %d %d\n", 760 v->color[0], v->color[1], v->color[2], v->color[3]); 761 _mesa_debug(ctx, "spec %d %d %d %d\n", 762 v->specular[0], v->specular[1], 763 v->specular[2], v->specular[3]); 764#endif 765 _mesa_debug(ctx, "fog %f\n", v->fog); 766 _mesa_debug(ctx, "index %d\n", v->index); 767 _mesa_debug(ctx, "pointsize %f\n", v->pointSize); 768 _mesa_debug(ctx, "\n"); 769 } 770} 771 772 773/** 774 * Validate access to a PBO to be sure we're not going to read/write 775 * out of buffer bounds. 776 */ 777GLvoid * 778_swrast_validate_pbo_access(const struct gl_pixelstore_attrib *pack, 779 GLsizei width, GLsizei height, GLsizei depth, 780 GLenum format, GLenum type, GLvoid *ptr) 781{ 782 if (pack->BufferObj->Name == 0) { 783 /* no PBO */ 784 return ptr; 785 } 786 else if (_mesa_validate_pbo_access(pack, width, height, depth, format, 787 type, ptr)) { 788 return ADD_POINTERS(pack->BufferObj->Data, ptr); 789 } 790 /* bad access! */ 791 return NULL; 792} 793