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