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