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