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