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