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