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