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