1 /* $Id: s_context.c,v 1.47 2003/03/15 17:33:27 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
27 * Keith Whitwell <keith@tungstengraphics.com>
38 #include "s_context.h"
42 #include "s_triangle.h"
43 #include "s_texture.h"
47 * Recompute the value of swrast->_RasterMask, etc. according to
48 * the current context.
51 _swrast_update_rasterflags( GLcontext
*ctx
)
53 GLuint RasterMask
= 0;
55 if (ctx
->Color
.AlphaEnabled
) RasterMask
|= ALPHATEST_BIT
;
56 if (ctx
->Color
.BlendEnabled
) RasterMask
|= BLEND_BIT
;
57 if (ctx
->Depth
.Test
) RasterMask
|= DEPTH_BIT
;
58 if (ctx
->Fog
.Enabled
) RasterMask
|= FOG_BIT
;
59 if (ctx
->Scissor
.Enabled
) RasterMask
|= CLIP_BIT
;
60 if (ctx
->Stencil
.Enabled
) RasterMask
|= STENCIL_BIT
;
61 if (ctx
->Visual
.rgbMode
) {
62 const GLuint colorMask
= *((GLuint
*) &ctx
->Color
.ColorMask
);
63 if (colorMask
!= 0xffffffff) RasterMask
|= MASKING_BIT
;
64 if (ctx
->Color
.ColorLogicOpEnabled
) RasterMask
|= LOGIC_OP_BIT
;
65 if (ctx
->Texture
._EnabledUnits
) RasterMask
|= TEXTURE_BIT
;
68 if (ctx
->Color
.IndexMask
!= 0xffffffff) RasterMask
|= MASKING_BIT
;
69 if (ctx
->Color
.IndexLogicOpEnabled
) RasterMask
|= LOGIC_OP_BIT
;
72 if (ctx
->DrawBuffer
->UseSoftwareAlphaBuffers
73 && ctx
->Color
.ColorMask
[ACOMP
]
74 && ctx
->Color
.DrawBuffer
!= GL_NONE
)
75 RasterMask
|= ALPHABUF_BIT
;
77 if ( ctx
->Viewport
.X
< 0
78 || ctx
->Viewport
.X
+ ctx
->Viewport
.Width
> (GLint
) ctx
->DrawBuffer
->Width
79 || ctx
->Viewport
.Y
< 0
80 || ctx
->Viewport
.Y
+ ctx
->Viewport
.Height
> (GLint
) ctx
->DrawBuffer
->Height
) {
81 RasterMask
|= CLIP_BIT
;
84 if (ctx
->Depth
.OcclusionTest
)
85 RasterMask
|= OCCLUSION_BIT
;
88 /* If we're not drawing to exactly one color buffer set the
89 * MULTI_DRAW_BIT flag. Also set it if we're drawing to no
90 * buffers or the RGBA or CI mask disables all writes.
92 if (ctx
->Color
._DrawDestMask
!= FRONT_LEFT_BIT
&&
93 ctx
->Color
._DrawDestMask
!= BACK_LEFT_BIT
&&
94 ctx
->Color
._DrawDestMask
!= FRONT_RIGHT_BIT
&&
95 ctx
->Color
._DrawDestMask
!= BACK_RIGHT_BIT
) {
96 /* more than one color buffer designated for writing (or zero buffers) */
97 RasterMask
|= MULTI_DRAW_BIT
;
99 else if (ctx
->Visual
.rgbMode
&& *((GLuint
*) ctx
->Color
.ColorMask
) == 0) {
100 RasterMask
|= MULTI_DRAW_BIT
; /* all RGBA channels disabled */
102 else if (!ctx
->Visual
.rgbMode
&& ctx
->Color
.IndexMask
==0) {
103 RasterMask
|= MULTI_DRAW_BIT
; /* all color index bits disabled */
106 SWRAST_CONTEXT(ctx
)->_RasterMask
= RasterMask
;
111 _swrast_update_polygon( GLcontext
*ctx
)
113 GLfloat backface_sign
= 1;
115 if (ctx
->Polygon
.CullFlag
) {
117 switch(ctx
->Polygon
.CullFaceMode
) {
119 if(ctx
->Polygon
.FrontFace
==GL_CCW
)
123 if(ctx
->Polygon
.FrontFace
!=GL_CCW
)
127 case GL_FRONT_AND_BACK
:
136 SWRAST_CONTEXT(ctx
)->_backface_sign
= backface_sign
;
141 _swrast_update_hint( GLcontext
*ctx
)
143 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
144 swrast
->_PreferPixelFog
= (!swrast
->AllowVertexFog
||
145 (ctx
->Hint
.Fog
== GL_NICEST
&&
146 swrast
->AllowPixelFog
));
151 * Update the swrast->_AnyTextureCombine flag.
154 _swrast_update_texture_env( GLcontext
*ctx
)
156 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
158 swrast
->_AnyTextureCombine
= GL_FALSE
;
159 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
160 if (ctx
->Texture
.Unit
[i
].EnvMode
== GL_COMBINE_EXT
||
161 ctx
->Texture
.Unit
[i
].EnvMode
== GL_COMBINE4_NV
) {
162 swrast
->_AnyTextureCombine
= GL_TRUE
;
169 #define _SWRAST_NEW_DERIVED (_SWRAST_NEW_RASTERMASK | \
174 /* State referenced by _swrast_choose_triangle, _swrast_choose_line.
176 #define _SWRAST_NEW_TRIANGLE (_SWRAST_NEW_DERIVED | \
183 _SWRAST_NEW_RASTERMASK| \
186 _DD_NEW_SEPARATE_SPECULAR)
188 #define _SWRAST_NEW_LINE (_SWRAST_NEW_DERIVED | \
195 _DD_NEW_SEPARATE_SPECULAR)
197 #define _SWRAST_NEW_POINT (_SWRAST_NEW_DERIVED | \
203 _DD_NEW_SEPARATE_SPECULAR)
205 #define _SWRAST_NEW_TEXTURE_SAMPLE_FUNC _NEW_TEXTURE
207 #define _SWRAST_NEW_TEXTURE_ENV_MODE _NEW_TEXTURE
209 #define _SWRAST_NEW_BLEND_FUNC _NEW_COLOR
213 /* Stub for swrast->Triangle to select a true triangle function
214 * after a state change.
217 _swrast_validate_triangle( GLcontext
*ctx
,
222 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
224 _swrast_validate_derived( ctx
);
225 swrast
->choose_triangle( ctx
);
227 if ((ctx
->_TriangleCaps
& DD_SEPARATE_SPECULAR
) &&
228 ctx
->Texture
._EnabledUnits
== 0) {
229 swrast
->SpecTriangle
= swrast
->Triangle
;
230 swrast
->Triangle
= _swrast_add_spec_terms_triangle
;
233 swrast
->Triangle( ctx
, v0
, v1
, v2
);
237 _swrast_validate_line( GLcontext
*ctx
, const SWvertex
*v0
, const SWvertex
*v1
)
239 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
241 _swrast_validate_derived( ctx
);
242 swrast
->choose_line( ctx
);
244 if ((ctx
->_TriangleCaps
& DD_SEPARATE_SPECULAR
) &&
245 ctx
->Texture
._EnabledUnits
== 0) {
246 swrast
->SpecLine
= swrast
->Line
;
247 swrast
->Line
= _swrast_add_spec_terms_line
;
251 swrast
->Line( ctx
, v0
, v1
);
255 _swrast_validate_point( GLcontext
*ctx
, const SWvertex
*v0
)
257 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
259 _swrast_validate_derived( ctx
);
260 swrast
->choose_point( ctx
);
262 if ((ctx
->_TriangleCaps
& DD_SEPARATE_SPECULAR
) &&
263 ctx
->Texture
._EnabledUnits
== 0) {
264 swrast
->SpecPoint
= swrast
->Point
;
265 swrast
->Point
= _swrast_add_spec_terms_point
;
268 swrast
->Point( ctx
, v0
);
273 _swrast_validate_blend_func( GLcontext
*ctx
, GLuint n
,
274 const GLubyte mask
[],
276 CONST GLchan dst
[][4] )
278 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
280 _swrast_validate_derived( ctx
);
281 _swrast_choose_blend_func( ctx
);
283 swrast
->BlendFunc( ctx
, n
, mask
, src
, dst
);
288 _swrast_validate_texture_sample( GLcontext
*ctx
, GLuint texUnit
,
289 const struct gl_texture_object
*tObj
,
290 GLuint n
, const GLfloat texcoords
[][4],
291 const GLfloat lambda
[], GLchan rgba
[][4] )
293 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
295 _swrast_validate_derived( ctx
);
297 /* Compute min/mag filter threshold */
298 if (tObj
->MinFilter
!= tObj
->MagFilter
) {
299 if (tObj
->MagFilter
== GL_LINEAR
300 && (tObj
->MinFilter
== GL_NEAREST_MIPMAP_NEAREST
||
301 tObj
->MinFilter
== GL_NEAREST_MIPMAP_LINEAR
)) {
302 swrast
->_MinMagThresh
[texUnit
] = 0.5F
;
305 swrast
->_MinMagThresh
[texUnit
] = 0.0F
;
309 swrast
->TextureSample
[texUnit
] =
310 _swrast_choose_texture_sample_func( ctx
, tObj
);
312 swrast
->TextureSample
[texUnit
]( ctx
, texUnit
, tObj
, n
, texcoords
,
315 /* GL_SGI_texture_color_table */
316 if (ctx
->Texture
.Unit
[texUnit
].ColorTableEnabled
) {
317 _swrast_texture_table_lookup(&ctx
->Texture
.Unit
[texUnit
].ColorTable
, n
, rgba
);
323 _swrast_sleep( GLcontext
*ctx
, GLuint new_state
)
329 _swrast_invalidate_state( GLcontext
*ctx
, GLuint new_state
)
331 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
334 swrast
->NewState
|= new_state
;
336 /* After 10 statechanges without any swrast functions being called,
337 * put the module to sleep.
339 if (++swrast
->StateChanges
> 10) {
340 swrast
->InvalidateState
= _swrast_sleep
;
341 swrast
->NewState
= ~0;
345 if (new_state
& swrast
->invalidate_triangle
)
346 swrast
->Triangle
= _swrast_validate_triangle
;
348 if (new_state
& swrast
->invalidate_line
)
349 swrast
->Line
= _swrast_validate_line
;
351 if (new_state
& swrast
->invalidate_point
)
352 swrast
->Point
= _swrast_validate_point
;
354 if (new_state
& _SWRAST_NEW_BLEND_FUNC
)
355 swrast
->BlendFunc
= _swrast_validate_blend_func
;
357 if (new_state
& _SWRAST_NEW_TEXTURE_SAMPLE_FUNC
)
358 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++)
359 swrast
->TextureSample
[i
] = _swrast_validate_texture_sample
;
361 if (ctx
->Visual
.rgbMode
) {
362 ASSERT(swrast
->Driver
.WriteRGBASpan
);
363 ASSERT(swrast
->Driver
.WriteRGBSpan
);
364 ASSERT(swrast
->Driver
.WriteMonoRGBASpan
);
365 ASSERT(swrast
->Driver
.WriteRGBAPixels
);
366 ASSERT(swrast
->Driver
.WriteMonoRGBAPixels
);
367 ASSERT(swrast
->Driver
.ReadRGBASpan
);
368 ASSERT(swrast
->Driver
.ReadRGBAPixels
);
371 ASSERT(swrast
->Driver
.WriteCI32Span
);
372 ASSERT(swrast
->Driver
.WriteCI8Span
);
373 ASSERT(swrast
->Driver
.WriteMonoCISpan
);
374 ASSERT(swrast
->Driver
.WriteCI32Pixels
);
375 ASSERT(swrast
->Driver
.WriteMonoCIPixels
);
376 ASSERT(swrast
->Driver
.ReadCI32Span
);
377 ASSERT(swrast
->Driver
.ReadCI32Pixels
);
383 _swrast_validate_derived( GLcontext
*ctx
)
385 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
387 if (swrast
->NewState
) {
388 if (swrast
->NewState
& _SWRAST_NEW_RASTERMASK
)
389 _swrast_update_rasterflags( ctx
);
391 if (swrast
->NewState
& _NEW_POLYGON
)
392 _swrast_update_polygon( ctx
);
394 if (swrast
->NewState
& _NEW_HINT
)
395 _swrast_update_hint( ctx
);
397 if (swrast
->NewState
& _SWRAST_NEW_TEXTURE_ENV_MODE
)
398 _swrast_update_texture_env( ctx
);
400 swrast
->NewState
= 0;
401 swrast
->StateChanges
= 0;
402 swrast
->InvalidateState
= _swrast_invalidate_state
;
406 #define SWRAST_DEBUG 0
408 /* Public entrypoints: See also s_accum.c, s_bitmap.c, etc.
411 _swrast_Quad( GLcontext
*ctx
,
412 const SWvertex
*v0
, const SWvertex
*v1
,
413 const SWvertex
*v2
, const SWvertex
*v3
)
416 _mesa_debug(ctx
, "_swrast_Quad\n");
417 _swrast_print_vertex( ctx
, v0
);
418 _swrast_print_vertex( ctx
, v1
);
419 _swrast_print_vertex( ctx
, v2
);
420 _swrast_print_vertex( ctx
, v3
);
422 SWRAST_CONTEXT(ctx
)->Triangle( ctx
, v0
, v1
, v3
);
423 SWRAST_CONTEXT(ctx
)->Triangle( ctx
, v1
, v2
, v3
);
427 _swrast_Triangle( GLcontext
*ctx
, const SWvertex
*v0
,
428 const SWvertex
*v1
, const SWvertex
*v2
)
431 _mesa_debug(ctx
, "_swrast_Triangle\n");
432 _swrast_print_vertex( ctx
, v0
);
433 _swrast_print_vertex( ctx
, v1
);
434 _swrast_print_vertex( ctx
, v2
);
436 SWRAST_CONTEXT(ctx
)->Triangle( ctx
, v0
, v1
, v2
);
440 _swrast_Line( GLcontext
*ctx
, const SWvertex
*v0
, const SWvertex
*v1
)
443 _mesa_debug(ctx
, "_swrast_Line\n");
444 _swrast_print_vertex( ctx
, v0
);
445 _swrast_print_vertex( ctx
, v1
);
447 SWRAST_CONTEXT(ctx
)->Line( ctx
, v0
, v1
);
451 _swrast_Point( GLcontext
*ctx
, const SWvertex
*v0
)
454 _mesa_debug(ctx
, "_swrast_Point\n");
455 _swrast_print_vertex( ctx
, v0
);
457 SWRAST_CONTEXT(ctx
)->Point( ctx
, v0
);
461 _swrast_InvalidateState( GLcontext
*ctx
, GLuint new_state
)
464 _mesa_debug(ctx
, "_swrast_InvalidateState\n");
466 SWRAST_CONTEXT(ctx
)->InvalidateState( ctx
, new_state
);
470 _swrast_ResetLineStipple( GLcontext
*ctx
)
473 _mesa_debug(ctx
, "_swrast_ResetLineStipple\n");
475 SWRAST_CONTEXT(ctx
)->StippleCounter
= 0;
479 _swrast_allow_vertex_fog( GLcontext
*ctx
, GLboolean value
)
482 _mesa_debug(ctx
, "_swrast_allow_vertex_fog %d\n", value
);
484 SWRAST_CONTEXT(ctx
)->InvalidateState( ctx
, _NEW_HINT
);
485 SWRAST_CONTEXT(ctx
)->AllowVertexFog
= value
;
489 _swrast_allow_pixel_fog( GLcontext
*ctx
, GLboolean value
)
492 _mesa_debug(ctx
, "_swrast_allow_pixel_fog %d\n", value
);
494 SWRAST_CONTEXT(ctx
)->InvalidateState( ctx
, _NEW_HINT
);
495 SWRAST_CONTEXT(ctx
)->AllowPixelFog
= value
;
500 _swrast_CreateContext( GLcontext
*ctx
)
503 SWcontext
*swrast
= (SWcontext
*)CALLOC(sizeof(SWcontext
));
506 _mesa_debug(ctx
, "_swrast_CreateContext\n");
512 swrast
->NewState
= ~0;
514 swrast
->choose_point
= _swrast_choose_point
;
515 swrast
->choose_line
= _swrast_choose_line
;
516 swrast
->choose_triangle
= _swrast_choose_triangle
;
518 swrast
->invalidate_point
= _SWRAST_NEW_POINT
;
519 swrast
->invalidate_line
= _SWRAST_NEW_LINE
;
520 swrast
->invalidate_triangle
= _SWRAST_NEW_TRIANGLE
;
522 swrast
->Point
= _swrast_validate_point
;
523 swrast
->Line
= _swrast_validate_line
;
524 swrast
->Triangle
= _swrast_validate_triangle
;
525 swrast
->InvalidateState
= _swrast_sleep
;
526 swrast
->BlendFunc
= _swrast_validate_blend_func
;
528 swrast
->AllowVertexFog
= GL_TRUE
;
529 swrast
->AllowPixelFog
= GL_TRUE
;
531 if (ctx
->Visual
.doubleBufferMode
)
532 swrast
->CurrentBuffer
= BACK_LEFT_BIT
;
534 swrast
->CurrentBuffer
= FRONT_LEFT_BIT
;
536 /* Optimized Accum buffer */
537 swrast
->_IntegerAccumMode
= GL_TRUE
;
538 swrast
->_IntegerAccumScaler
= 0.0;
540 for (i
= 0; i
< MAX_TEXTURE_IMAGE_UNITS
; i
++)
541 swrast
->TextureSample
[i
] = _swrast_validate_texture_sample
;
543 swrast
->SpanArrays
= MALLOC_STRUCT(span_arrays
);
544 if (!swrast
->SpanArrays
) {
549 /* init point span buffer */
550 swrast
->PointSpan
.primitive
= GL_POINT
;
551 swrast
->PointSpan
.start
= 0;
552 swrast
->PointSpan
.end
= 0;
553 swrast
->PointSpan
.facing
= 0;
554 swrast
->PointSpan
.array
= swrast
->SpanArrays
;
556 assert(ctx
->Const
.MaxTextureUnits
> 0);
557 assert(ctx
->Const
.MaxTextureUnits
<= MAX_TEXTURE_UNITS
);
559 swrast
->TexelBuffer
= (GLchan
*) MALLOC(ctx
->Const
.MaxTextureUnits
*
560 MAX_WIDTH
* 4 * sizeof(GLchan
));
561 if (!swrast
->TexelBuffer
) {
562 FREE(swrast
->SpanArrays
);
567 ctx
->swrast_context
= swrast
;
573 _swrast_DestroyContext( GLcontext
*ctx
)
575 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
578 _mesa_debug(ctx
, "_swrast_DestroyContext\n");
581 FREE( swrast
->SpanArrays
);
582 FREE( swrast
->TexelBuffer
);
585 ctx
->swrast_context
= 0;
589 struct swrast_device_driver
*
590 _swrast_GetDeviceDriverReference( GLcontext
*ctx
)
592 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
593 return &swrast
->Driver
;
597 _swrast_flush( GLcontext
*ctx
)
599 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
600 /* flush any pending fragments from rendering points */
601 if (swrast
->PointSpan
.end
> 0) {
602 if (ctx
->Visual
.rgbMode
) {
603 if (ctx
->Texture
._EnabledUnits
)
604 _mesa_write_texture_span(ctx
, &(swrast
->PointSpan
));
606 _mesa_write_rgba_span(ctx
, &(swrast
->PointSpan
));
609 _mesa_write_index_span(ctx
, &(swrast
->PointSpan
));
611 swrast
->PointSpan
.end
= 0;
616 _swrast_render_primitive( GLcontext
*ctx
, GLenum prim
)
618 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
619 if (swrast
->Primitive
== GL_POINTS
&& prim
!= GL_POINTS
) {
622 swrast
->Primitive
= prim
;
627 _swrast_render_start( GLcontext
*ctx
)
629 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
630 if (swrast
->Driver
.SpanRenderStart
)
631 swrast
->Driver
.SpanRenderStart( ctx
);
632 swrast
->PointSpan
.end
= 0;
636 _swrast_render_finish( GLcontext
*ctx
)
638 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
639 if (swrast
->Driver
.SpanRenderFinish
)
640 swrast
->Driver
.SpanRenderFinish( ctx
);
646 #define SWRAST_DEBUG_VERTICES 0
649 _swrast_print_vertex( GLcontext
*ctx
, const SWvertex
*v
)
653 if (SWRAST_DEBUG_VERTICES
) {
654 _mesa_debug(ctx
, "win %f %f %f %f\n",
655 v
->win
[0], v
->win
[1], v
->win
[2], v
->win
[3]);
657 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++)
658 if (ctx
->Texture
.Unit
[i
]._ReallyEnabled
)
659 _mesa_debug(ctx
, "texcoord[%d] %f %f %f %f\n", i
,
660 v
->texcoord
[i
][0], v
->texcoord
[i
][1],
661 v
->texcoord
[i
][2], v
->texcoord
[i
][3]);
663 #if CHAN_TYPE == GL_FLOAT
664 _mesa_debug(ctx
, "color %f %f %f %f\n",
665 v
->color
[0], v
->color
[1], v
->color
[2], v
->color
[3]);
666 _mesa_debug(ctx
, "spec %f %f %f %f\n",
667 v
->specular
[0], v
->specular
[1],
668 v
->specular
[2], v
->specular
[3]);
670 _mesa_debug(ctx
, "color %d %d %d %d\n",
671 v
->color
[0], v
->color
[1], v
->color
[2], v
->color
[3]);
672 _mesa_debug(ctx
, "spec %d %d %d %d\n",
673 v
->specular
[0], v
->specular
[1],
674 v
->specular
[2], v
->specular
[3]);
676 _mesa_debug(ctx
, "fog %f\n", v
->fog
);
677 _mesa_debug(ctx
, "index %d\n", v
->index
);
678 _mesa_debug(ctx
, "pointsize %f\n", v
->pointSize
);
679 _mesa_debug(ctx
, "\n");