osmesa.c revision bc69de5f21ebb4d6e1c65bf5652d17a9fc87dda7
1/* $Id: osmesa.c,v 1.54 2001/05/10 12:22:32 keithw Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  3.5
6 *
7 * Copyright (C) 1999-2001  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
27
28/*
29 * Off-Screen Mesa rendering / Rendering into client memory space
30 *
31 * Note on thread safety:  this driver is thread safe.  All
32 * functions are reentrant.  The notion of current context is
33 * managed by the core _mesa_make_current() and _mesa_get_current_context()
34 * functions.  Those functions are thread-safe.
35 */
36
37
38#include "glheader.h"
39#include "GL/osmesa.h"
40#include "context.h"
41#include "colormac.h"
42#include "depth.h"
43#include "extensions.h"
44#include "macros.h"
45#include "matrix.h"
46#include "mem.h"
47#include "mmath.h"
48#include "mtypes.h"
49#include "texformat.h"
50#include "texstore.h"
51#include "array_cache/acache.h"
52#include "swrast/swrast.h"
53#include "swrast_setup/swrast_setup.h"
54#include "swrast/s_context.h"
55#include "swrast/s_depth.h"
56#include "swrast/s_lines.h"
57#include "swrast/s_triangle.h"
58#include "tnl/tnl.h"
59#include "tnl/t_context.h"
60#include "tnl/t_pipeline.h"
61
62
63
64/*
65 * This is the OS/Mesa context struct.
66 * Notice how it includes a GLcontext.  By doing this we're mimicking
67 * C++ inheritance/derivation.
68 * Later, we can cast a GLcontext pointer into an OSMesaContext pointer
69 * or vice versa.
70 */
71struct osmesa_context {
72   GLcontext gl_ctx;		/* The core GL/Mesa context */
73   GLvisual *gl_visual;		/* Describes the buffers */
74   GLframebuffer *gl_buffer;	/* Depth, stencil, accum, etc buffers */
75   GLenum format;		/* either GL_RGBA or GL_COLOR_INDEX */
76   void *buffer;		/* the image buffer */
77   GLint width, height;		/* size of image buffer */
78   GLint rowlength;		/* number of pixels per row */
79   GLint userRowLength;		/* user-specified number of pixels per row */
80   GLint rshift, gshift;	/* bit shifts for RGBA formats */
81   GLint bshift, ashift;
82   GLint rInd, gInd, bInd, aInd;/* index offsets for RGBA formats */
83   GLchan *rowaddr[MAX_HEIGHT];	/* address of first pixel in each image row */
84   GLboolean yup;		/* TRUE  -> Y increases upward */
85				/* FALSE -> Y increases downward */
86};
87
88
89
90/* A forward declaration: */
91static void osmesa_update_state( GLcontext *ctx, GLuint newstate );
92static void osmesa_register_swrast_functions( GLcontext *ctx );
93
94
95
96#define OSMESA_CONTEXT(ctx)  ((OSMesaContext) (ctx->DriverCtx))
97
98
99
100/**********************************************************************/
101/*****                    Public Functions                        *****/
102/**********************************************************************/
103
104
105/*
106 * Create an Off-Screen Mesa rendering context.  The only attribute needed is
107 * an RGBA vs Color-Index mode flag.
108 *
109 * Input:  format - either GL_RGBA or GL_COLOR_INDEX
110 *         sharelist - specifies another OSMesaContext with which to share
111 *                     display lists.  NULL indicates no sharing.
112 * Return:  an OSMesaContext or 0 if error
113 */
114OSMesaContext GLAPIENTRY
115OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
116{
117   return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS,
118                                 8, 16, sharelist);
119}
120
121
122
123/*
124 * New in Mesa 3.5
125 *
126 * Create context and specify size of ancillary buffers.
127 */
128OSMesaContext GLAPIENTRY
129OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
130                        GLint accumBits, OSMesaContext sharelist )
131{
132   OSMesaContext osmesa;
133   GLint rshift, gshift, bshift, ashift;
134   GLint rind, gind, bind, aind;
135   GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
136   GLboolean rgbmode;
137   GLboolean swalpha;
138   const GLuint i4 = 1;
139   const GLubyte *i1 = (GLubyte *) &i4;
140   const GLint little_endian = *i1;
141
142   swalpha = GL_FALSE;
143   rind = gind = bind = aind = 0;
144   if (format==OSMESA_COLOR_INDEX) {
145      indexBits = 8;
146      rshift = gshift = bshift = ashift = 0;
147      rgbmode = GL_FALSE;
148   }
149   else if (format==OSMESA_RGBA) {
150      indexBits = 0;
151      redBits = CHAN_BITS;
152      greenBits = CHAN_BITS;
153      blueBits = CHAN_BITS;
154      alphaBits = CHAN_BITS;
155      rind = 0;
156      gind = 1;
157      bind = 2;
158      aind = 3;
159      if (little_endian) {
160         rshift = 0;
161         gshift = 8;
162         bshift = 16;
163         ashift = 24;
164      }
165      else {
166         rshift = 24;
167         gshift = 16;
168         bshift = 8;
169         ashift = 0;
170      }
171      rgbmode = GL_TRUE;
172   }
173   else if (format==OSMESA_BGRA) {
174      indexBits = 0;
175      redBits = CHAN_BITS;
176      greenBits = CHAN_BITS;
177      blueBits = CHAN_BITS;
178      alphaBits = CHAN_BITS;
179      rind = 2;
180      gind = 1;
181      bind = 0;
182      aind = 3;
183      if (little_endian) {
184         ashift = 0;
185         rshift = 8;
186         gshift = 16;
187         bshift = 24;
188      }
189      else {
190         bshift = 24;
191         gshift = 16;
192         rshift = 8;
193         ashift = 0;
194      }
195      rgbmode = GL_TRUE;
196   }
197   else if (format==OSMESA_ARGB) {
198      indexBits = 0;
199      redBits = CHAN_BITS;
200      greenBits = CHAN_BITS;
201      blueBits = CHAN_BITS;
202      alphaBits = CHAN_BITS;
203      rind = 1;
204      gind = 2;
205      bind = 3;
206      aind = 0;
207      if (little_endian) {
208         bshift = 0;
209         gshift = 8;
210         rshift = 16;
211         ashift = 24;
212      }
213      else {
214         ashift = 24;
215         rshift = 16;
216         gshift = 8;
217         bshift = 0;
218      }
219      rgbmode = GL_TRUE;
220   }
221   else if (format==OSMESA_RGB) {
222      indexBits = 0;
223      redBits = CHAN_BITS;
224      greenBits = CHAN_BITS;
225      blueBits = CHAN_BITS;
226      alphaBits = 0;
227      bshift = 0;
228      gshift = 8;
229      rshift = 16;
230      ashift = 24;
231      rind = 0;
232      gind = 1;
233      bind = 2;
234      rgbmode = GL_TRUE;
235      swalpha = GL_TRUE;
236   }
237   else if (format==OSMESA_BGR) {
238      indexBits = 0;
239      redBits = CHAN_BITS;
240      greenBits = CHAN_BITS;
241      blueBits = CHAN_BITS;
242      alphaBits = 0;
243      bshift = 0;
244      gshift = 8;
245      rshift = 16;
246      ashift = 24;
247      rind = 2;
248      gind = 1;
249      bind = 0;
250      rgbmode = GL_TRUE;
251      swalpha = GL_TRUE;
252   }
253   else {
254      return NULL;
255   }
256
257
258   osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
259   if (osmesa) {
260      osmesa->gl_visual = _mesa_create_visual( rgbmode,
261                                               GL_FALSE,    /* double buffer */
262                                               GL_FALSE,    /* stereo */
263                                               redBits,
264                                               greenBits,
265                                               blueBits,
266                                               alphaBits,
267                                               indexBits,
268                                               depthBits,
269                                               stencilBits,
270                                               accumBits,
271                                               accumBits,
272                                               accumBits,
273                                               alphaBits ? accumBits : 0,
274                                               1            /* num samples */
275                                               );
276      if (!osmesa->gl_visual) {
277         FREE(osmesa);
278         return NULL;
279      }
280
281      if (!_mesa_initialize_context(&osmesa->gl_ctx,
282                                    osmesa->gl_visual,
283                                    sharelist ? &sharelist->gl_ctx
284                                              : (GLcontext *) NULL,
285                                    (void *) osmesa, GL_TRUE )) {
286         _mesa_destroy_visual( osmesa->gl_visual );
287         FREE(osmesa);
288         return NULL;
289      }
290
291      _mesa_enable_sw_extensions(&(osmesa->gl_ctx));
292
293      osmesa->gl_buffer = _mesa_create_framebuffer( osmesa->gl_visual,
294                                          osmesa->gl_visual->depthBits > 0,
295                                          osmesa->gl_visual->stencilBits > 0,
296                                          osmesa->gl_visual->accumRedBits > 0,
297                                          osmesa->gl_visual->alphaBits > 0 );
298
299      if (!osmesa->gl_buffer) {
300         _mesa_destroy_visual( osmesa->gl_visual );
301         _mesa_free_context_data( &osmesa->gl_ctx );
302         FREE(osmesa);
303         return NULL;
304      }
305      osmesa->format = format;
306      osmesa->buffer = NULL;
307      osmesa->width = 0;
308      osmesa->height = 0;
309      osmesa->userRowLength = 0;
310      osmesa->rowlength = 0;
311      osmesa->yup = GL_TRUE;
312      osmesa->rshift = rshift;
313      osmesa->gshift = gshift;
314      osmesa->bshift = bshift;
315      osmesa->ashift = ashift;
316      osmesa->rInd = rind;
317      osmesa->gInd = gind;
318      osmesa->bInd = bind;
319      osmesa->aInd = aind;
320
321
322      /* Initialize the software rasterizer and helper modules.
323       */
324      {
325	 GLcontext *ctx = &osmesa->gl_ctx;
326
327	 _swrast_CreateContext( ctx );
328	 _ac_CreateContext( ctx );
329	 _tnl_CreateContext( ctx );
330	 _swsetup_CreateContext( ctx );
331
332	 osmesa_register_swrast_functions( ctx );
333      }
334   }
335   return osmesa;
336}
337
338
339
340
341/*
342 * Destroy an Off-Screen Mesa rendering context.
343 *
344 * Input:  ctx - the context to destroy
345 */
346void GLAPIENTRY OSMesaDestroyContext( OSMesaContext ctx )
347{
348   if (ctx) {
349      _swsetup_DestroyContext( &ctx->gl_ctx );
350      _tnl_DestroyContext( &ctx->gl_ctx );
351      _ac_DestroyContext( &ctx->gl_ctx );
352      _swrast_DestroyContext( &ctx->gl_ctx );
353
354      _mesa_destroy_visual( ctx->gl_visual );
355      _mesa_destroy_framebuffer( ctx->gl_buffer );
356      _mesa_free_context_data( &ctx->gl_ctx );
357      FREE( ctx );
358   }
359}
360
361
362
363/*
364 * Recompute the values of the context's rowaddr array.
365 */
366static void compute_row_addresses( OSMesaContext ctx )
367{
368   GLint bytesPerPixel, bytesPerRow, i;
369   GLubyte *origin = (GLubyte *) ctx->buffer;
370
371   if (ctx->format == OSMESA_COLOR_INDEX) {
372      /* CI mode */
373      bytesPerPixel = 1 * sizeof(GLchan);
374   }
375   else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) {
376      /* RGB mode */
377      bytesPerPixel = 3 * sizeof(GLchan);
378   }
379   else {
380      /* RGBA mode */
381      bytesPerPixel = 4 * sizeof(GLchan);
382   }
383
384   bytesPerRow = ctx->rowlength * bytesPerPixel;
385
386   if (ctx->yup) {
387      /* Y=0 is bottom line of window */
388      for (i = 0; i < MAX_HEIGHT; i++) {
389         ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow);
390      }
391   }
392   else {
393      /* Y=0 is top line of window */
394      for (i = 0; i < MAX_HEIGHT; i++) {
395         GLint j = ctx->height - i - 1;
396         ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow);
397      }
398   }
399}
400
401
402/*
403 * Bind an OSMesaContext to an image buffer.  The image buffer is just a
404 * block of memory which the client provides.  Its size must be at least
405 * as large as width*height*sizeof(type).  Its address should be a multiple
406 * of 4 if using RGBA mode.
407 *
408 * Image data is stored in the order of glDrawPixels:  row-major order
409 * with the lower-left image pixel stored in the first array position
410 * (ie. bottom-to-top).
411 *
412 * Since the only type initially supported is GL_UNSIGNED_BYTE, if the
413 * context is in RGBA mode, each pixel will be stored as a 4-byte RGBA
414 * value.  If the context is in color indexed mode, each pixel will be
415 * stored as a 1-byte value.
416 *
417 * If the context's viewport hasn't been initialized yet, it will now be
418 * initialized to (0,0,width,height).
419 *
420 * Input:  ctx - the rendering context
421 *         buffer - the image buffer memory
422 *         type - data type for pixel components, only GL_UNSIGNED_BYTE
423 *                supported now
424 *         width, height - size of image buffer in pixels, at least 1
425 * Return:  GL_TRUE if success, GL_FALSE if error because of invalid ctx,
426 *          invalid buffer address, type!=GL_UNSIGNED_BYTE, width<1, height<1,
427 *          width>internal limit or height>internal limit.
428 */
429GLboolean GLAPIENTRY
430OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type,
431                   GLsizei width, GLsizei height )
432{
433   if (!ctx || !buffer || type != CHAN_TYPE ||
434       width < 1 || height < 1 ||
435       width > MAX_WIDTH || height > MAX_HEIGHT) {
436      return GL_FALSE;
437   }
438
439   osmesa_update_state( &ctx->gl_ctx, 0 );
440   _mesa_make_current( &ctx->gl_ctx, ctx->gl_buffer );
441
442   ctx->buffer = buffer;
443   ctx->width = width;
444   ctx->height = height;
445   if (ctx->userRowLength)
446      ctx->rowlength = ctx->userRowLength;
447   else
448      ctx->rowlength = width;
449
450   compute_row_addresses( ctx );
451
452   /* init viewport */
453   if (ctx->gl_ctx.Viewport.Width==0) {
454      /* initialize viewport and scissor box to buffer size */
455      _mesa_Viewport( 0, 0, width, height );
456      ctx->gl_ctx.Scissor.Width = width;
457      ctx->gl_ctx.Scissor.Height = height;
458   }
459
460   return GL_TRUE;
461}
462
463
464
465OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void )
466{
467   GLcontext *ctx = _mesa_get_current_context();
468   if (ctx)
469      return (OSMesaContext) ctx;
470   else
471      return NULL;
472}
473
474
475
476void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value )
477{
478   OSMesaContext ctx = OSMesaGetCurrentContext();
479
480   switch (pname) {
481      case OSMESA_ROW_LENGTH:
482         if (value<0) {
483            _mesa_error( &ctx->gl_ctx, GL_INVALID_VALUE,
484                      "OSMesaPixelStore(value)" );
485            return;
486         }
487         ctx->userRowLength = value;
488         ctx->rowlength = value;
489         break;
490      case OSMESA_Y_UP:
491         ctx->yup = value ? GL_TRUE : GL_FALSE;
492         break;
493      default:
494         _mesa_error( &ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
495         return;
496   }
497
498   compute_row_addresses( ctx );
499}
500
501
502void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value )
503{
504   OSMesaContext ctx = OSMesaGetCurrentContext();
505
506   switch (pname) {
507      case OSMESA_WIDTH:
508         *value = ctx->width;
509         return;
510      case OSMESA_HEIGHT:
511         *value = ctx->height;
512         return;
513      case OSMESA_FORMAT:
514         *value = ctx->format;
515         return;
516      case OSMESA_TYPE:
517         *value = CHAN_TYPE;
518         return;
519      case OSMESA_ROW_LENGTH:
520         *value = ctx->rowlength;
521         return;
522      case OSMESA_Y_UP:
523         *value = ctx->yup;
524         return;
525      default:
526         _mesa_error(&ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
527         return;
528   }
529}
530
531/*
532 * Return the depth buffer associated with an OSMesa context.
533 * Input:  c - the OSMesa context
534 * Output:  width, height - size of buffer in pixels
535 *          bytesPerValue - bytes per depth value (2 or 4)
536 *          buffer - pointer to depth buffer values
537 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
538 */
539GLboolean GLAPIENTRY
540OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
541                      GLint *bytesPerValue, void **buffer )
542{
543   if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) {
544      *width = 0;
545      *height = 0;
546      *bytesPerValue = 0;
547      *buffer = 0;
548      return GL_FALSE;
549   }
550   else {
551      *width = c->gl_buffer->Width;
552      *height = c->gl_buffer->Height;
553      if (c->gl_visual->depthBits <= 16)
554         *bytesPerValue = sizeof(GLushort);
555      else
556         *bytesPerValue = sizeof(GLuint);
557      *buffer = c->gl_buffer->DepthBuffer;
558      return GL_TRUE;
559   }
560}
561
562/*
563 * Return the color buffer associated with an OSMesa context.
564 * Input:  c - the OSMesa context
565 * Output:  width, height - size of buffer in pixels
566 *          format - the pixel format (OSMESA_FORMAT)
567 *          buffer - pointer to color buffer values
568 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
569 */
570GLboolean GLAPIENTRY
571OSMesaGetColorBuffer( OSMesaContext c, GLint *width,
572                      GLint *height, GLint *format, void **buffer )
573{
574   if (!c->buffer) {
575      *width = 0;
576      *height = 0;
577      *format = 0;
578      *buffer = 0;
579      return GL_FALSE;
580   }
581   else {
582      *width = c->width;
583      *height = c->height;
584      *format = c->format;
585      *buffer = c->buffer;
586      return GL_TRUE;
587   }
588}
589
590/**********************************************************************/
591/*** Device Driver Functions                                        ***/
592/**********************************************************************/
593
594
595/*
596 * Useful macros:
597 */
598
599#define PACK_RGBA(DST, R, G, B, A)	\
600do {					\
601   (DST)[osmesa->rInd] = R;		\
602   (DST)[osmesa->gInd] = G;		\
603   (DST)[osmesa->bInd] = B;		\
604   (DST)[osmesa->aInd] = A;		\
605} while (0)
606
607#define PACK_RGB(DST, R, G, B)  \
608do {				\
609   (DST)[0] = R;		\
610   (DST)[1] = G;		\
611   (DST)[2] = B;		\
612} while (0)
613
614#define PACK_BGR(DST, R, G, B)  \
615do {				\
616   (DST)[0] = B;		\
617   (DST)[1] = G;		\
618   (DST)[2] = R;		\
619} while (0)
620
621
622#define UNPACK_RED(P)      ( (P)[osmesa->rInd] )
623#define UNPACK_GREEN(P)    ( (P)[osmesa->gInd] )
624#define UNPACK_BLUE(P)     ( (P)[osmesa->bInd] )
625#define UNPACK_ALPHA(P)    ( (P)[osmesa->aInd] )
626
627
628#define PIXELADDR1(X,Y)  (osmesa->rowaddr[Y] + (X))
629#define PIXELADDR3(X,Y)  (osmesa->rowaddr[Y] + 3 * (X))
630#define PIXELADDR4(X,Y)  (osmesa->rowaddr[Y] + 4 * (X))
631
632
633
634static GLboolean set_draw_buffer( GLcontext *ctx, GLenum mode )
635{
636   (void) ctx;
637   if (mode==GL_FRONT_LEFT) {
638      return GL_TRUE;
639   }
640   else {
641      return GL_FALSE;
642   }
643}
644
645
646static void set_read_buffer( GLcontext *ctx, GLframebuffer *buffer, GLenum mode )
647{
648   /* separate read buffer not supported */
649   ASSERT(buffer == ctx->DrawBuffer);
650   ASSERT(mode == GL_FRONT_LEFT);
651}
652
653
654static void clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
655		   GLint x, GLint y, GLint width, GLint height )
656{
657   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
658   const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
659
660   /* sanity check - we only have a front-left buffer */
661   ASSERT((mask & (DD_FRONT_RIGHT_BIT | DD_BACK_LEFT_BIT | DD_BACK_RIGHT_BIT)) == 0);
662   if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) {
663      if (mask & DD_FRONT_LEFT_BIT) {
664	 if (osmesa->format == OSMESA_COLOR_INDEX) {
665	    if (all) {
666	       /* Clear whole CI buffer */
667#if CHAN_TYPE == GL_UNSIGNED_BYTE
668	       MEMSET(osmesa->buffer, ctx->Color.ClearIndex,
669		      osmesa->rowlength * osmesa->height);
670#else
671	       const GLint n = osmesa->rowlength * osmesa->height;
672	       GLchan *buffer = (GLchan *) osmesa->buffer;
673	       GLint i;
674	       for (i = 0; i < n; i ++) {
675		  buffer[i] = ctx->Color.ClearIndex;
676	       }
677#endif
678	    }
679	    else {
680	       /* Clear part of CI buffer */
681	       const GLchan clearIndex = (GLchan) ctx->Color.ClearIndex;
682	       GLint i, j;
683	       for (i = 0; i < height; i++) {
684		  GLchan *ptr1 = PIXELADDR1(x, (y + i));
685		  for (j = 0; j < width; j++) {
686		     *ptr1++ = clearIndex;
687		  }
688	       }
689	    }
690	 }
691	 else if (osmesa->format == OSMESA_RGB) {
692	    const GLchan r = ctx->Color.ClearColor[0];
693	    const GLchan g = ctx->Color.ClearColor[1];
694	    const GLchan b = ctx->Color.ClearColor[2];
695	    if (all) {
696	       /* Clear whole RGB buffer */
697	       GLuint n = osmesa->rowlength * osmesa->height;
698	       GLchan *ptr3 = (GLchan *) osmesa->buffer;
699	       GLuint i;
700	       for (i = 0; i < n; i++) {
701		  PACK_RGB(ptr3, r, g, b);
702		  ptr3 += 3;
703	       }
704	    }
705	    else {
706	       /* Clear part of RGB buffer */
707	       GLint i, j;
708	       for (i = 0; i < height; i++) {
709		  GLchan *ptr3 = PIXELADDR3(x, (y + i));
710		  for (j = 0; j < width; j++) {
711		     PACK_RGB(ptr3, r, g, b);
712		     ptr3 += 3;
713		  }
714	       }
715	    }
716	 }
717	 else if (osmesa->format == OSMESA_BGR) {
718	    const GLchan r = ctx->Color.ClearColor[0];
719	    const GLchan g = ctx->Color.ClearColor[1];
720	    const GLchan b = ctx->Color.ClearColor[2];
721	    if (all) {
722	       /* Clear whole RGB buffer */
723	       const GLint n = osmesa->rowlength * osmesa->height;
724	       GLchan *ptr3 = (GLchan *) osmesa->buffer;
725	       GLint i;
726	       for (i = 0; i < n; i++) {
727		  PACK_BGR(ptr3, r, g, b);
728		  ptr3 += 3;
729	       }
730	    }
731	    else {
732	       /* Clear part of RGB buffer */
733	       GLint i, j;
734	       for (i = 0; i < height; i++) {
735		  GLchan *ptr3 = PIXELADDR3(x, (y + i));
736		  for (j = 0; j < width; j++) {
737		     PACK_BGR(ptr3, r, g, b);
738		     ptr3 += 3;
739		  }
740	       }
741	    }
742	 }
743	 else {
744#if CHAN_TYPE == GL_UNSIGNED_BYTE
745	    /* 4-byte pixel value */
746	    GLuint clearPixel;
747	    GLchan *clr = (GLchan *) &clearPixel;
748	    clr[osmesa->rInd] = ctx->Color.ClearColor[0];
749	    clr[osmesa->gInd] = ctx->Color.ClearColor[1];
750	    clr[osmesa->bInd] = ctx->Color.ClearColor[2];
751	    clr[osmesa->aInd] = ctx->Color.ClearColor[3];
752	    if (all) {
753	       /* Clear whole RGBA buffer */
754	       const GLuint n = osmesa->rowlength * osmesa->height;
755	       GLuint *ptr4 = (GLuint *) osmesa->buffer;
756	       GLuint i;
757	       if (clearPixel) {
758		  for (i = 0; i < n; i++) {
759		     *ptr4++ = clearPixel;
760		  }
761	       }
762	       else {
763		  BZERO(ptr4, n * sizeof(GLuint));
764	       }
765	    }
766	    else {
767	       /* Clear part of RGBA buffer */
768	       GLint i, j;
769	       for (i = 0; i < height; i++) {
770		  GLuint *ptr4 = (GLuint *) PIXELADDR4(x, (y + i));
771		  for (j = 0; j < width; j++) {
772		     *ptr4++ = clearPixel;
773		  }
774	       }
775	    }
776#else
777	    const GLchan r = ctx->Color.ClearColor[0];
778	    const GLchan g = ctx->Color.ClearColor[1];
779	    const GLchan b = ctx->Color.ClearColor[2];
780	    const GLchan a = ctx->Color.ClearColor[3];
781	    if (all) {
782	       /* Clear whole RGBA buffer */
783	       const GLuint n = osmesa->rowlength * osmesa->height;
784	       GLchan *p = (GLchan *) osmesa->buffer;
785	       GLuint i;
786	       for (i = 0; i < n; i++) {
787		  PACK_RGBA(p, r, g, b, a);
788		  p += 4;
789	       }
790	    }
791	    else {
792	       /* Clear part of RGBA buffer */
793	       GLint i, j;
794	       for (i = 0; i < height; i++) {
795		  GLchan *p = PIXELADDR4(x, (y + i));
796		  for (j = 0; j < width; j++) {
797		     PACK_RGBA(p, r, g, b, a);
798		     p += 4;
799		  }
800	       }
801	    }
802
803#endif
804	 }
805	 mask &= ~DD_FRONT_LEFT_BIT;
806      }
807   }
808
809   if (mask)
810      _swrast_Clear( ctx, mask, all, x, y, width, height );
811}
812
813
814
815static void buffer_size( GLcontext *ctx, GLuint *width, GLuint *height )
816{
817   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
818   *width = osmesa->width;
819   *height = osmesa->height;
820}
821
822
823/**********************************************************************/
824/*****        Read/write spans/arrays of RGBA pixels              *****/
825/**********************************************************************/
826
827/* Write RGBA pixels to an RGBA (or permuted) buffer. */
828static void
829write_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
830                 CONST GLchan rgba[][4], const GLubyte mask[] )
831{
832   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
833   GLchan *p = PIXELADDR4(x, y);
834   GLuint i;
835   if (mask) {
836      for (i = 0; i < n; i++, p += 4) {
837         if (mask[i]) {
838            PACK_RGBA(p, rgba[i][RCOMP], rgba[i][GCOMP],
839                         rgba[i][BCOMP], rgba[i][ACOMP]);
840         }
841      }
842   }
843   else {
844      for (i = 0; i < n; i++, p += 4) {
845         PACK_RGBA(p, rgba[i][RCOMP], rgba[i][GCOMP],
846                      rgba[i][BCOMP], rgba[i][ACOMP]);
847      }
848   }
849}
850
851
852/* Write RGBA pixels to an RGBA buffer.  This is the fastest span-writer. */
853static void
854write_rgba_span_rgba( const GLcontext *ctx, GLuint n, GLint x, GLint y,
855                      CONST GLchan rgba[][4], const GLubyte mask[] )
856{
857   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
858   GLuint *ptr4 = (GLuint *) PIXELADDR4(x, y);
859   const GLuint *rgba4 = (const GLuint *) rgba;
860   GLuint i;
861   ASSERT(CHAN_TYPE == GL_UNSIGNED_BYTE);
862   if (mask) {
863      for (i = 0; i < n; i++) {
864         if (mask[i]) {
865            ptr4[i] = rgba4[i];
866         }
867      }
868   }
869   else {
870      MEMCPY( ptr4, rgba4, n * 4 );
871   }
872}
873
874
875/* Write RGB pixels to an RGBA (or permuted) buffer. */
876static void
877write_rgb_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
878                CONST GLchan rgb[][3], const GLubyte mask[] )
879{
880   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
881   GLchan *p = PIXELADDR4(x, y);
882   GLuint i;
883   if (mask) {
884      for (i = 0; i < n; i++, p+=4) {
885         if (mask[i]) {
886            PACK_RGBA(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255);
887         }
888      }
889   }
890   else {
891      for (i = 0; i < n; i++, p+=4) {
892         PACK_RGBA(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255);
893      }
894   }
895}
896
897
898
899static void
900write_monocolor_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
901                      const GLchan color[4], const GLubyte mask[] )
902{
903   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
904   GLchan *p = PIXELADDR4(x, y);
905   GLuint i;
906   for (i = 0; i < n; i++, p += 4) {
907      if (mask[i]) {
908         PACK_RGBA(p, color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP]);
909      }
910   }
911}
912
913
914
915static void
916write_rgba_pixels( const GLcontext *ctx, GLuint n,
917                   const GLint x[], const GLint y[],
918                   CONST GLchan rgba[][4], const GLubyte mask[] )
919{
920   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
921   GLuint i;
922   for (i = 0; i < n; i++) {
923      if (mask[i]) {
924         GLchan *p = PIXELADDR4(x[i], y[i]);
925         PACK_RGBA(p, rgba[i][RCOMP], rgba[i][GCOMP],
926                      rgba[i][BCOMP], rgba[i][ACOMP]);
927      }
928   }
929}
930
931
932
933static void
934write_monocolor_pixels( const GLcontext *ctx, GLuint n,
935                        const GLint x[], const GLint y[],
936                        const GLchan color[4], const GLubyte mask[] )
937{
938   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
939   GLuint i;
940   for (i = 0; i < n; i++) {
941      if (mask[i]) {
942         GLchan *p = PIXELADDR4(x[i], y[i]);
943         PACK_RGBA(p, color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP]);
944      }
945   }
946}
947
948
949static void
950read_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
951                GLchan rgba[][4] )
952{
953   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
954   GLuint i;
955   GLchan *p = PIXELADDR4(x, y);
956   for (i = 0; i < n; i++, p += 4) {
957      rgba[i][RCOMP] = UNPACK_RED(p);
958      rgba[i][GCOMP] = UNPACK_GREEN(p);
959      rgba[i][BCOMP] = UNPACK_BLUE(p);
960      rgba[i][ACOMP] = UNPACK_ALPHA(p);
961   }
962}
963
964
965/* Read RGBA pixels from an RGBA buffer */
966static void
967read_rgba_span_rgba( const GLcontext *ctx, GLuint n, GLint x, GLint y,
968                     GLchan rgba[][4] )
969{
970   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
971   GLuint *ptr4 = (GLuint *) PIXELADDR4(x, y);
972   MEMCPY( rgba, ptr4, n * 4 * sizeof(GLchan) );
973}
974
975
976static void
977read_rgba_pixels( const GLcontext *ctx,
978                  GLuint n, const GLint x[], const GLint y[],
979                  GLchan rgba[][4], const GLubyte mask[] )
980{
981   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
982   GLuint i;
983   for (i = 0; i < n; i++) {
984      if (mask[i]) {
985         const GLchan *p = PIXELADDR4(x[i], y[i]);
986         rgba[i][RCOMP] = UNPACK_RED(p);
987         rgba[i][GCOMP] = UNPACK_GREEN(p);
988         rgba[i][BCOMP] = UNPACK_BLUE(p);
989         rgba[i][ACOMP] = UNPACK_ALPHA(p);
990      }
991   }
992}
993
994/**********************************************************************/
995/*****                3 byte RGB pixel support funcs              *****/
996/**********************************************************************/
997
998/* Write RGBA pixels to an RGB buffer. */
999static void
1000write_rgba_span_RGB( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1001                     CONST GLchan rgba[][4], const GLubyte mask[] )
1002{
1003   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1004   GLchan *p = PIXELADDR3(x, y);
1005   GLuint i;
1006   if (mask) {
1007      for (i = 0; i < n; i++, p += 3) {
1008         if (mask[i]) {
1009            PACK_RGB(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1010         }
1011      }
1012   }
1013   else {
1014      for (i = 0; i < n; i++, p += 3) {
1015         PACK_RGB(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1016      }
1017   }
1018}
1019
1020/* Write RGBA pixels to an BGR buffer. */
1021static void
1022write_rgba_span_BGR( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1023                     CONST GLchan rgba[][4], const GLubyte mask[] )
1024{
1025   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1026   GLchan *p = PIXELADDR3(x, y);
1027   GLuint i;
1028   if (mask) {
1029      for (i = 0; i < n; i++, p += 3) {
1030         if (mask[i]) {
1031            PACK_BGR(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1032         }
1033      }
1034   }
1035   else {
1036      for (i = 0; i < n; i++, p += 3) {
1037         PACK_BGR(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1038      }
1039   }
1040}
1041
1042/* Write RGB pixels to an RGB buffer. */
1043static void
1044write_rgb_span_RGB( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1045                    CONST GLchan rgb[][3], const GLubyte mask[] )
1046{
1047   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1048   GLchan *p = PIXELADDR3(x, y);
1049   GLuint i;
1050   if (mask) {
1051      for (i = 0; i < n; i++, p += 3) {
1052         if (mask[i]) {
1053            PACK_RGB(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1054         }
1055      }
1056   }
1057   else {
1058      for (i = 0; i < n; i++, p += 3) {
1059         PACK_RGB(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1060      }
1061   }
1062}
1063
1064/* Write RGB pixels to an BGR buffer. */
1065static void
1066write_rgb_span_BGR( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1067                    CONST GLchan rgb[][3], const GLubyte mask[] )
1068{
1069   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1070   GLchan *p = PIXELADDR3(x, y);
1071   GLuint i;
1072   if (mask) {
1073      for (i = 0; i < n; i++, p += 3) {
1074         if (mask[i]) {
1075            PACK_BGR(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1076         }
1077      }
1078   }
1079   else {
1080      for (i = 0; i < n; i++, p += 3) {
1081         PACK_BGR(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1082      }
1083   }
1084}
1085
1086
1087static void
1088write_monocolor_span_RGB( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1089                          const GLchan color[4], const GLubyte mask[] )
1090{
1091   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1092   GLchan *p = PIXELADDR3(x, y);
1093   GLuint i;
1094   for (i = 0; i < n; i++, p += 3) {
1095      if (mask[i]) {
1096         PACK_RGB(p, color[RCOMP], color[GCOMP], color[BCOMP]);
1097      }
1098   }
1099}
1100
1101static void
1102write_monocolor_span_BGR( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1103                          const GLchan color[4], const GLubyte mask[] )
1104{
1105   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1106   GLchan *p = PIXELADDR3(x, y);
1107   GLuint i;
1108   for (i = 0; i < n; i++, p += 3) {
1109      if (mask[i]) {
1110         PACK_BGR(p, color[RCOMP], color[GCOMP], color[BCOMP]);
1111      }
1112   }
1113}
1114
1115static void
1116write_rgba_pixels_RGB( const GLcontext *ctx, GLuint n,
1117                       const GLint x[], const GLint y[],
1118                       CONST GLchan rgba[][4], const GLubyte mask[] )
1119{
1120   const OSMesaContext osmesa = (const OSMesaContext) ctx;
1121   GLuint i;
1122   for (i = 0; i < n; i++) {
1123      if (mask[i]) {
1124         GLchan *p = PIXELADDR3(x[i], y[i]);
1125         PACK_RGB(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1126      }
1127   }
1128}
1129
1130static void
1131write_rgba_pixels_BGR( const GLcontext *ctx, GLuint n,
1132                       const GLint x[], const GLint y[],
1133                       CONST GLchan rgba[][4], const GLubyte mask[] )
1134{
1135   const OSMesaContext osmesa = (const OSMesaContext) ctx;
1136   GLuint i;
1137   for (i = 0; i < n; i++) {
1138      if (mask[i]) {
1139         GLchan *p = PIXELADDR3(x[i], y[i]);
1140         PACK_BGR(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1141      }
1142   }
1143}
1144
1145static void
1146write_monocolor_pixels_RGB( const GLcontext *ctx,
1147                            GLuint n, const GLint x[], const GLint y[],
1148                            const GLchan color[4], const GLubyte mask[] )
1149{
1150   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1151   GLuint i;
1152   for (i = 0; i < n; i++) {
1153      if (mask[i]) {
1154         GLchan *p = PIXELADDR3(x[i], y[i]);
1155         PACK_RGB(p, color[RCOMP], color[GCOMP], color[BCOMP]);
1156      }
1157   }
1158}
1159
1160static void
1161write_monocolor_pixels_BGR( const GLcontext *ctx,
1162                            GLuint n, const GLint x[], const GLint y[],
1163                            const GLchan color[4], const GLubyte mask[] )
1164{
1165   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1166   GLuint i;
1167   for (i = 0; i < n; i++) {
1168      if (mask[i]) {
1169         GLchan *p = PIXELADDR3(x[i], y[i]);
1170         PACK_BGR(p, color[RCOMP], color[GCOMP], color[BCOMP]);
1171      }
1172   }
1173}
1174
1175static void
1176read_rgba_span3( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1177                 GLchan rgba[][4] )
1178{
1179   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1180   GLuint i;
1181   const GLchan *p = PIXELADDR3(x, y);
1182   for (i = 0; i < n; i++, p += 3) {
1183      rgba[i][RCOMP] = UNPACK_RED(p);
1184      rgba[i][GCOMP] = UNPACK_GREEN(p);
1185      rgba[i][BCOMP] = UNPACK_BLUE(p);
1186      rgba[i][ACOMP] = 255;
1187   }
1188}
1189
1190static void
1191read_rgba_pixels3( const GLcontext *ctx,
1192                   GLuint n, const GLint x[], const GLint y[],
1193                   GLchan rgba[][4], const GLubyte mask[] )
1194{
1195   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1196   GLuint i;
1197   for (i = 0; i < n; i++) {
1198      if (mask[i]) {
1199         const GLchan *p = PIXELADDR3(x[i], y[i]);
1200         rgba[i][RCOMP] = UNPACK_RED(p);
1201         rgba[i][GCOMP] = UNPACK_GREEN(p);
1202         rgba[i][BCOMP] = UNPACK_BLUE(p);
1203         rgba[i][ACOMP] = 255;
1204      }
1205   }
1206}
1207
1208
1209/**********************************************************************/
1210/*****        Read/write spans/arrays of CI pixels                *****/
1211/**********************************************************************/
1212
1213/* Write 32-bit color index to buffer */
1214static void
1215write_index32_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1216                    const GLuint index[], const GLubyte mask[] )
1217{
1218   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1219   GLchan *ptr1 = PIXELADDR1(x, y);
1220   GLuint i;
1221   if (mask) {
1222      for (i=0;i<n;i++,ptr1++) {
1223         if (mask[i]) {
1224            *ptr1 = (GLchan) index[i];
1225         }
1226      }
1227   }
1228   else {
1229      for (i=0;i<n;i++,ptr1++) {
1230         *ptr1 = (GLchan) index[i];
1231      }
1232   }
1233}
1234
1235
1236/* Write 8-bit color index to buffer */
1237static void
1238write_index8_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1239                   const GLubyte index[], const GLubyte mask[] )
1240{
1241   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1242   GLchan *ptr1 = PIXELADDR1(x, y);
1243   GLuint i;
1244   if (mask) {
1245      for (i=0;i<n;i++,ptr1++) {
1246         if (mask[i]) {
1247            *ptr1 = (GLchan) index[i];
1248         }
1249      }
1250   }
1251   else {
1252      MEMCPY(ptr1, index, n * sizeof(GLchan));
1253   }
1254}
1255
1256
1257static void
1258write_monoindex_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1259                      GLuint colorIndex, const GLubyte mask[] )
1260{
1261   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1262   GLchan *ptr1 = PIXELADDR1(x, y);
1263   GLuint i;
1264   for (i=0;i<n;i++,ptr1++) {
1265      if (mask[i]) {
1266         *ptr1 = (GLchan) colorIndex;
1267      }
1268   }
1269}
1270
1271
1272static void
1273write_index_pixels( const GLcontext *ctx,
1274                    GLuint n, const GLint x[], const GLint y[],
1275                    const GLuint index[], const GLubyte mask[] )
1276{
1277   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1278   GLuint i;
1279   for (i=0;i<n;i++) {
1280      if (mask[i]) {
1281         GLchan *ptr1 = PIXELADDR1(x[i], y[i]);
1282         *ptr1 = (GLchan) index[i];
1283      }
1284   }
1285}
1286
1287
1288static void
1289write_monoindex_pixels( const GLcontext *ctx,
1290                        GLuint n, const GLint x[], const GLint y[],
1291                        GLuint colorIndex, const GLubyte mask[] )
1292{
1293   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1294   GLuint i;
1295   for (i=0;i<n;i++) {
1296      if (mask[i]) {
1297         GLchan *ptr1 = PIXELADDR1(x[i], y[i]);
1298         *ptr1 = (GLchan) colorIndex;
1299      }
1300   }
1301}
1302
1303
1304static void
1305read_index_span( const GLcontext *ctx,
1306                 GLuint n, GLint x, GLint y, GLuint index[] )
1307{
1308   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1309   GLuint i;
1310   const GLchan *ptr1 = (const GLchan *) PIXELADDR1(x, y);
1311   for (i=0;i<n;i++,ptr1++) {
1312      index[i] = (GLuint) *ptr1;
1313   }
1314}
1315
1316
1317static void
1318read_index_pixels( const GLcontext *ctx,
1319                   GLuint n, const GLint x[], const GLint y[],
1320                   GLuint index[], const GLubyte mask[] )
1321{
1322   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1323   GLuint i;
1324   for (i=0;i<n;i++) {
1325      if (mask[i] ) {
1326         const GLchan *ptr1 = PIXELADDR1(x[i], y[i]);
1327         index[i] = (GLuint) *ptr1;
1328      }
1329   }
1330}
1331
1332
1333
1334/**********************************************************************/
1335/*****                   Optimized line rendering                 *****/
1336/**********************************************************************/
1337
1338
1339/*
1340 * Draw a flat-shaded, RGB line into an osmesa buffer.
1341 */
1342static void
1343flat_rgba_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 )
1344{
1345   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1346   const GLchan *color = vert0->color;
1347
1348#define INTERP_XY 1
1349#define CLIP_HACK 1
1350#define PLOT(X, Y)						\
1351do {								\
1352   GLchan *p = PIXELADDR4(X, Y);				\
1353   PACK_RGBA(p, color[0], color[1], color[2], color[3]);	\
1354} while (0)
1355
1356#ifdef WIN32
1357#include "..\swrast\s_linetemp.h"
1358#else
1359#include "swrast/s_linetemp.h"
1360#endif
1361}
1362
1363
1364/*
1365 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
1366 */
1367static void
1368flat_rgba_z_line(GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1)
1369{
1370   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1371   const GLchan *color = vert0->color;
1372
1373#define INTERP_XY 1
1374#define INTERP_Z 1
1375#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1376#define CLIP_HACK 1
1377#define PLOT(X, Y)					\
1378do {							\
1379   if (Z < *zPtr) {					\
1380      GLchan *p = PIXELADDR4(X, Y);			\
1381      PACK_RGBA(p, color[RCOMP], color[GCOMP],		\
1382                   color[BCOMP], color[ACOMP]);		\
1383      *zPtr = Z;					\
1384   }							\
1385} while (0)
1386
1387
1388#ifdef WIN32
1389#include "..\swrast\s_linetemp.h"
1390#else
1391#include "swrast/s_linetemp.h"
1392#endif
1393}
1394
1395
1396/*
1397 * Draw a flat-shaded, alpha-blended, RGB line into an osmesa buffer.
1398 * XXX update for GLchan
1399 */
1400static void
1401flat_blend_rgba_line( GLcontext *ctx,
1402                      const SWvertex *vert0, const SWvertex *vert1 )
1403{
1404   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1405   const GLint rshift = osmesa->rshift;
1406   const GLint gshift = osmesa->gshift;
1407   const GLint bshift = osmesa->bshift;
1408   const GLint avalue = vert0->color[3];
1409   const GLint msavalue = 255 - avalue;
1410   const GLint rvalue = vert0->color[0]*avalue;
1411   const GLint gvalue = vert0->color[1]*avalue;
1412   const GLint bvalue = vert0->color[2]*avalue;
1413
1414#define INTERP_XY 1
1415#define CLIP_HACK 1
1416#define PLOT(X,Y)					\
1417   { GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y);		\
1418     GLuint  pixel = 0;					\
1419     pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);\
1420     pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);\
1421     pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);\
1422     *ptr4 = pixel;					\
1423   }
1424
1425#ifdef WIN32
1426#include "..\swrast\s_linetemp.h"
1427#else
1428#include "swrast/s_linetemp.h"
1429#endif
1430}
1431
1432
1433/*
1434 * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer.
1435 * XXX update for GLchan
1436 */
1437static void
1438flat_blend_rgba_z_line( GLcontext *ctx,
1439                        const SWvertex *vert0, const SWvertex *vert1 )
1440{
1441   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1442   const GLint rshift = osmesa->rshift;
1443   const GLint gshift = osmesa->gshift;
1444   const GLint bshift = osmesa->bshift;
1445   const GLint avalue = vert0->color[3];
1446   const GLint msavalue = 256 - avalue;
1447   const GLint rvalue = vert0->color[0]*avalue;
1448   const GLint gvalue = vert0->color[1]*avalue;
1449   const GLint bvalue = vert0->color[2]*avalue;
1450
1451#define INTERP_XY 1
1452#define INTERP_Z 1
1453#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1454#define CLIP_HACK 1
1455#define PLOT(X,Y)							\
1456	if (Z < *zPtr) {						\
1457	   GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y);			\
1458	   GLuint  pixel = 0;						\
1459	   pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);	\
1460	   pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);	\
1461	   pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);	\
1462	   *ptr4 = pixel; 						\
1463	}
1464
1465#ifdef WIN32
1466#include "..\swrast\s_linetemp.h"
1467#else
1468#include "swrast/s_linetemp.h"
1469#endif
1470}
1471
1472
1473/*
1474 * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer.
1475 * XXX update for GLchan
1476 */
1477static void
1478flat_blend_rgba_z_line_write( GLcontext *ctx,
1479                              const SWvertex *vert0, const SWvertex *vert1 )
1480{
1481   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1482   const GLint rshift = osmesa->rshift;
1483   const GLint gshift = osmesa->gshift;
1484   const GLint bshift = osmesa->bshift;
1485   const GLint avalue = vert0->color[3];
1486   const GLint msavalue = 256 - avalue;
1487   const GLint rvalue = vert0->color[0]*avalue;
1488   const GLint gvalue = vert0->color[1]*avalue;
1489   const GLint bvalue = vert0->color[2]*avalue;
1490
1491#define INTERP_XY 1
1492#define INTERP_Z 1
1493#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1494#define CLIP_HACK 1
1495#define PLOT(X,Y)							\
1496	if (Z < *zPtr) {						\
1497	   GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y);			\
1498	   GLuint  pixel = 0;						\
1499	   pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);	\
1500	   pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);	\
1501	   pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);	\
1502	   *ptr4 = pixel;						\
1503	   *zPtr = Z;							\
1504	}
1505
1506#ifdef WIN32
1507#include "..\swrast\s_linetemp.h"
1508#else
1509#include "swrast/s_linetemp.h"
1510#endif
1511}
1512
1513
1514/*
1515 * Analyze context state to see if we can provide a fast line drawing
1516 * function, like those in lines.c.  Otherwise, return NULL.
1517 */
1518static swrast_line_func
1519osmesa_choose_line_function( GLcontext *ctx )
1520{
1521   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1522   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1523
1524   if (CHAN_BITS != 8)                    return NULL;
1525   if (ctx->RenderMode != GL_RENDER)      return NULL;
1526   if (ctx->Line.SmoothFlag)              return NULL;
1527   if (ctx->Texture._ReallyEnabled)       return NULL;
1528   if (ctx->Light.ShadeModel != GL_FLAT)  return NULL;
1529   if (ctx->Line.Width != 1.0F)           return NULL;
1530   if (ctx->Line.StippleFlag)             return NULL;
1531   if (ctx->Line.SmoothFlag)              return NULL;
1532   if (osmesa->format != OSMESA_RGBA &&
1533       osmesa->format != OSMESA_BGRA &&
1534       osmesa->format != OSMESA_ARGB)     return NULL;
1535
1536   if (swrast->_RasterMask==DEPTH_BIT
1537       && ctx->Depth.Func==GL_LESS
1538       && ctx->Depth.Mask==GL_TRUE
1539       && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
1540      return flat_rgba_z_line;
1541   }
1542
1543   if (swrast->_RasterMask == 0) {
1544      return flat_rgba_line;
1545   }
1546
1547   if (swrast->_RasterMask==(DEPTH_BIT|BLEND_BIT)
1548       && ctx->Depth.Func==GL_LESS
1549       && ctx->Depth.Mask==GL_TRUE
1550       && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
1551       && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
1552       && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
1553       && ctx->Color.BlendSrcA==GL_SRC_ALPHA
1554       && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
1555       && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
1556      return flat_blend_rgba_z_line_write;
1557   }
1558
1559   if (swrast->_RasterMask==(DEPTH_BIT|BLEND_BIT)
1560       && ctx->Depth.Func==GL_LESS
1561       && ctx->Depth.Mask==GL_FALSE
1562       && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
1563       && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
1564       && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
1565       && ctx->Color.BlendSrcA==GL_SRC_ALPHA
1566       && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
1567       && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
1568      return flat_blend_rgba_z_line;
1569   }
1570
1571   if (swrast->_RasterMask==BLEND_BIT
1572       && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
1573       && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
1574       && ctx->Color.BlendSrcA==GL_SRC_ALPHA
1575       && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
1576       && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
1577      return flat_blend_rgba_line;
1578   }
1579
1580   return NULL;
1581}
1582
1583
1584/**********************************************************************/
1585/*****                 Optimized triangle rendering               *****/
1586/**********************************************************************/
1587
1588
1589/*
1590 * Smooth-shaded, z-less triangle, RGBA color.
1591 */
1592static void smooth_rgba_z_triangle( GLcontext *ctx,
1593				    const SWvertex *v0,
1594                                    const SWvertex *v1,
1595                                    const SWvertex *v2 )
1596{
1597   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1598
1599#define INTERP_Z 1
1600#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1601#define INTERP_RGB 1
1602#define INTERP_ALPHA 1
1603#define INNER_LOOP( LEFT, RIGHT, Y )				\
1604{								\
1605   GLint i, len = RIGHT-LEFT;					\
1606   GLchan *img = PIXELADDR4(LEFT, Y); 				\
1607   for (i = 0; i < len; i++, img += 4) {			\
1608      GLdepth z = FixedToDepth(ffz);				\
1609      if (z < zRow[i]) {					\
1610         PACK_RGBA(img, FixedToInt(ffr), FixedToInt(ffg),	\
1611		        FixedToInt(ffb), FixedToInt(ffa));	\
1612         zRow[i] = z;						\
1613      }								\
1614      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;  ffa += fdadx;\
1615      ffz += fdzdx;						\
1616   }								\
1617}
1618#ifdef WIN32
1619#include "..\swrast\s_tritemp.h"
1620#else
1621#include "swrast/s_tritemp.h"
1622#endif
1623}
1624
1625
1626
1627
1628/*
1629 * Flat-shaded, z-less triangle, RGBA color.
1630 */
1631static void flat_rgba_z_triangle( GLcontext *ctx,
1632				  const SWvertex *v0,
1633                                  const SWvertex *v1,
1634                                  const SWvertex *v2 )
1635{
1636   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1637#define INTERP_Z 1
1638#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1639#define SETUP_CODE						\
1640   GLuint pixel;						\
1641   PACK_RGBA((GLchan *) &pixel, v0->color[0], v0->color[1],	\
1642                                v0->color[2], v0->color[3]);
1643
1644#define INNER_LOOP( LEFT, RIGHT, Y )			\
1645{							\
1646   GLint i, len = RIGHT-LEFT;				\
1647   GLuint *img = (GLuint *) PIXELADDR4(LEFT, Y);   	\
1648   for (i=0;i<len;i++) {				\
1649      GLdepth z = FixedToDepth(ffz);			\
1650      if (z < zRow[i]) {				\
1651         img[i] = pixel;				\
1652         zRow[i] = z;					\
1653      }							\
1654      ffz += fdzdx;					\
1655   }							\
1656}
1657#ifdef WIN32
1658#include "..\swrast\s_tritemp.h"
1659#else
1660#include "swrast/s_tritemp.h"
1661#endif
1662}
1663
1664
1665
1666/*
1667 * Return pointer to an accelerated triangle function if possible.
1668 */
1669static swrast_tri_func
1670osmesa_choose_triangle_function( GLcontext *ctx )
1671{
1672   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1673   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1674
1675   if (CHAN_BITS != 8)                  return (swrast_tri_func) NULL;
1676   if (ctx->RenderMode != GL_RENDER)    return (swrast_tri_func) NULL;
1677   if (ctx->Polygon.SmoothFlag)         return (swrast_tri_func) NULL;
1678   if (ctx->Polygon.StippleFlag)        return (swrast_tri_func) NULL;
1679   if (ctx->Texture._ReallyEnabled)     return (swrast_tri_func) NULL;
1680   if (osmesa->format != OSMESA_RGBA &&
1681       osmesa->format != OSMESA_BGRA &&
1682       osmesa->format != OSMESA_ARGB)   return (swrast_tri_func) NULL;
1683
1684   if (swrast->_RasterMask == DEPTH_BIT &&
1685       ctx->Depth.Func == GL_LESS &&
1686       ctx->Depth.Mask == GL_TRUE &&
1687       ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
1688      if (ctx->Light.ShadeModel == GL_SMOOTH) {
1689         return smooth_rgba_z_triangle;
1690      }
1691      else {
1692         return flat_rgba_z_triangle;
1693      }
1694   }
1695   return (swrast_tri_func) NULL;
1696}
1697
1698
1699
1700/* Override for the swrast triangle-selection function.  Try to use one
1701 * of our internal triangle functions, otherwise fall back to the
1702 * standard swrast functions.
1703 */
1704static void osmesa_choose_triangle( GLcontext *ctx )
1705{
1706   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1707
1708   swrast->Triangle = osmesa_choose_triangle_function( ctx );
1709   if (!swrast->Triangle)
1710      _swrast_choose_triangle( ctx );
1711}
1712
1713static void osmesa_choose_line( GLcontext *ctx )
1714{
1715   SWcontext *swrast = SWRAST_CONTEXT(ctx);
1716
1717   swrast->Line = osmesa_choose_line_function( ctx );
1718   if (!swrast->Line)
1719      _swrast_choose_line( ctx );
1720}
1721
1722
1723#define OSMESA_NEW_LINE   (_NEW_LINE | \
1724                           _NEW_TEXTURE | \
1725                           _NEW_LIGHT | \
1726                           _NEW_DEPTH | \
1727                           _NEW_RENDERMODE | \
1728                           _SWRAST_NEW_RASTERMASK)
1729
1730#define OSMESA_NEW_TRIANGLE (_NEW_POLYGON | \
1731                             _NEW_TEXTURE | \
1732                             _NEW_LIGHT | \
1733                             _NEW_DEPTH | \
1734                             _NEW_RENDERMODE | \
1735                             _SWRAST_NEW_RASTERMASK)
1736
1737
1738/* Extend the software rasterizer with our line and triangle
1739 * functions.
1740 */
1741static void osmesa_register_swrast_functions( GLcontext *ctx )
1742{
1743   SWcontext *swrast = SWRAST_CONTEXT( ctx );
1744
1745   swrast->choose_line = osmesa_choose_line;
1746   swrast->choose_triangle = osmesa_choose_triangle;
1747
1748   swrast->invalidate_line |= OSMESA_NEW_LINE;
1749   swrast->invalidate_triangle |= OSMESA_NEW_TRIANGLE;
1750}
1751
1752
1753static const GLubyte *get_string( GLcontext *ctx, GLenum name )
1754{
1755   (void) ctx;
1756   switch (name) {
1757      case GL_RENDERER:
1758         return (const GLubyte *) "Mesa OffScreen";
1759      default:
1760         return NULL;
1761   }
1762}
1763
1764
1765static void osmesa_update_state( GLcontext *ctx, GLuint new_state )
1766{
1767   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1768   struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx );
1769   TNLcontext *tnl = TNL_CONTEXT(ctx);
1770
1771   ASSERT((void *) osmesa == (void *) ctx->DriverCtx);
1772
1773   /*
1774    * XXX these function pointers could be initialized just once during
1775    * context creation since they don't depend on any state changes.
1776    */
1777
1778   ctx->Driver.GetString = get_string;
1779   ctx->Driver.UpdateState = osmesa_update_state;
1780   ctx->Driver.SetDrawBuffer = set_draw_buffer;
1781   ctx->Driver.ResizeBuffersMESA = _swrast_alloc_buffers;
1782   ctx->Driver.GetBufferSize = buffer_size;
1783
1784   ctx->Driver.Accum = _swrast_Accum;
1785   ctx->Driver.Bitmap = _swrast_Bitmap;
1786   ctx->Driver.Clear = clear;
1787   ctx->Driver.CopyPixels = _swrast_CopyPixels;
1788   ctx->Driver.DrawPixels = _swrast_DrawPixels;
1789   ctx->Driver.ReadPixels = _swrast_ReadPixels;
1790
1791   ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
1792   ctx->Driver.TexImage1D = _mesa_store_teximage1d;
1793   ctx->Driver.TexImage2D = _mesa_store_teximage2d;
1794   ctx->Driver.TexImage3D = _mesa_store_teximage3d;
1795   ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
1796   ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
1797   ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
1798   ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
1799
1800   ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
1801   ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
1802   ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
1803   ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
1804   ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
1805   ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
1806   ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
1807   ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
1808   ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
1809
1810
1811   /* RGB(A) span/pixel functions */
1812   if (osmesa->format == OSMESA_RGB) {
1813      swdd->WriteRGBASpan = write_rgba_span_RGB;
1814      swdd->WriteRGBSpan = write_rgb_span_RGB;
1815      swdd->WriteMonoRGBASpan = write_monocolor_span_RGB;
1816      swdd->WriteRGBAPixels = write_rgba_pixels_RGB;
1817      swdd->WriteMonoRGBAPixels = write_monocolor_pixels_RGB;
1818      swdd->ReadRGBASpan = read_rgba_span3;
1819      swdd->ReadRGBAPixels = read_rgba_pixels3;
1820   }
1821   else if (osmesa->format == OSMESA_BGR) {
1822      swdd->WriteRGBASpan = write_rgba_span_BGR;
1823      swdd->WriteRGBSpan = write_rgb_span_BGR;
1824      swdd->WriteMonoRGBASpan = write_monocolor_span_BGR;
1825      swdd->WriteRGBAPixels = write_rgba_pixels_BGR;
1826      swdd->WriteMonoRGBAPixels = write_monocolor_pixels_BGR;
1827      swdd->ReadRGBASpan = read_rgba_span3;
1828      swdd->ReadRGBAPixels = read_rgba_pixels3;
1829   }
1830   else {
1831      /* 4 bytes / pixel in frame buffer */
1832      swdd->WriteRGBSpan = write_rgb_span;
1833      swdd->WriteRGBAPixels = write_rgba_pixels;
1834      swdd->WriteMonoRGBASpan = write_monocolor_span;
1835      swdd->WriteMonoRGBAPixels = write_monocolor_pixels;
1836      if (osmesa->format == OSMESA_RGBA &&
1837          CHAN_TYPE == GL_UNSIGNED_BYTE &&
1838          RCOMP==0 && GCOMP==1 && BCOMP==2 && ACOMP==3) {
1839         /* special, fast case */
1840         swdd->WriteRGBASpan = write_rgba_span_rgba;
1841         swdd->ReadRGBASpan = read_rgba_span_rgba;
1842      }
1843      else {
1844         swdd->WriteRGBASpan = write_rgba_span;
1845         swdd->ReadRGBASpan = read_rgba_span;
1846      }
1847      swdd->ReadRGBAPixels = read_rgba_pixels;
1848   }
1849
1850   /* CI span/pixel functions */
1851   swdd->WriteCI32Span = write_index32_span;
1852   swdd->WriteCI8Span = write_index8_span;
1853   swdd->WriteMonoCISpan = write_monoindex_span;
1854   swdd->WriteCI32Pixels = write_index_pixels;
1855   swdd->WriteMonoCIPixels = write_monoindex_pixels;
1856   swdd->ReadCI32Span = read_index_span;
1857   swdd->ReadCI32Pixels = read_index_pixels;
1858
1859   swdd->SetReadBuffer = set_read_buffer;
1860
1861   tnl->Driver.RunPipeline = _tnl_run_pipeline;
1862   tnl->Driver.RenderStart = _swsetup_RenderStart;
1863   tnl->Driver.RenderFinish = _swsetup_RenderFinish;
1864   tnl->Driver.BuildProjectedVertices = _swsetup_BuildProjectedVertices;
1865   tnl->Driver.RenderPrimitive = _swsetup_RenderPrimitive;
1866   tnl->Driver.PointsFunc = _swsetup_Points;
1867   tnl->Driver.LineFunc = _swsetup_Line;
1868   tnl->Driver.TriangleFunc = _swsetup_Triangle;
1869   tnl->Driver.QuadFunc = _swsetup_Quad;
1870   tnl->Driver.ResetLineStipple = _swrast_ResetLineStipple;
1871   tnl->Driver.RenderInterp = _swsetup_RenderInterp;
1872   tnl->Driver.RenderCopyPV = _swsetup_RenderCopyPV;
1873   tnl->Driver.RenderClippedLine = _swsetup_RenderClippedLine;
1874   tnl->Driver.RenderClippedPolygon = _swsetup_RenderClippedPolygon;
1875
1876
1877   _swrast_InvalidateState( ctx, new_state );
1878   _swsetup_InvalidateState( ctx, new_state );
1879   _ac_InvalidateState( ctx, new_state );
1880   _tnl_InvalidateState( ctx, new_state );
1881}
1882