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