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