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