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