osmesa.c revision f42d366bb6fadefb5a0e4fe19c35f88ce1345906
1/* $Id: osmesa.c,v 1.89 2002/10/05 03:02:01 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            GLchan r, g, b;
771            CLAMPED_FLOAT_TO_CHAN(r, ctx->Color.ClearColor[0]);
772            CLAMPED_FLOAT_TO_CHAN(g, ctx->Color.ClearColor[1]);
773            CLAMPED_FLOAT_TO_CHAN(b, ctx->Color.ClearColor[2]);
774	    if (all) {
775	       /* Clear whole RGB buffer */
776	       GLuint n = osmesa->rowlength * osmesa->height;
777	       GLchan *ptr3 = (GLchan *) osmesa->buffer;
778	       GLuint i;
779	       for (i = 0; i < n; i++) {
780		  PACK_RGB(ptr3, r, g, b);
781		  ptr3 += 3;
782	       }
783	    }
784	    else {
785	       /* Clear part of RGB buffer */
786	       GLint i, j;
787	       for (i = 0; i < height; i++) {
788		  GLchan *ptr3 = PIXELADDR3(x, (y + i));
789		  for (j = 0; j < width; j++) {
790		     PACK_RGB(ptr3, r, g, b);
791		     ptr3 += 3;
792		  }
793	       }
794	    }
795	 }
796	 else if (osmesa->format == OSMESA_BGR) {
797            GLchan r, g, b;
798            CLAMPED_FLOAT_TO_CHAN(r, ctx->Color.ClearColor[0]);
799            CLAMPED_FLOAT_TO_CHAN(g, ctx->Color.ClearColor[1]);
800            CLAMPED_FLOAT_TO_CHAN(b, ctx->Color.ClearColor[2]);
801	    if (all) {
802	       /* Clear whole RGB buffer */
803	       const GLint n = osmesa->rowlength * osmesa->height;
804	       GLchan *ptr3 = (GLchan *) osmesa->buffer;
805	       GLint i;
806	       for (i = 0; i < n; i++) {
807		  PACK_BGR(ptr3, r, g, b);
808		  ptr3 += 3;
809	       }
810	    }
811	    else {
812	       /* Clear part of RGB buffer */
813	       GLint i, j;
814	       for (i = 0; i < height; i++) {
815		  GLchan *ptr3 = PIXELADDR3(x, (y + i));
816		  for (j = 0; j < width; j++) {
817		     PACK_BGR(ptr3, r, g, b);
818		     ptr3 += 3;
819		  }
820	       }
821	    }
822	 }
823         else if (osmesa->format == OSMESA_RGB_565) {
824            GLushort clearPixel;
825            GLchan r, g, b;
826            CLAMPED_FLOAT_TO_CHAN(r, ctx->Color.ClearColor[0]);
827            CLAMPED_FLOAT_TO_CHAN(g, ctx->Color.ClearColor[1]);
828            CLAMPED_FLOAT_TO_CHAN(b, ctx->Color.ClearColor[2]);
829            PACK_RGB_565(clearPixel, r, g, b);
830            if (all) {
831               /* Clear whole RGB buffer */
832	       const GLuint n = osmesa->rowlength * osmesa->height;
833               GLushort *ptr2 = (GLushort *) osmesa->buffer;
834               GLuint  i;
835               for (i = 0; i < n; i++) {
836                  *ptr2 = clearPixel;
837                  ptr2++;
838               }
839            }
840            else {
841               /* clear scissored region */
842               GLint i, j;
843               for (i = 0; i < height; i++) {
844                  GLushort *ptr2 = (GLushort *) PIXELADDR2(x, (y + i));
845                  for (j = 0; j < width; j++) {
846                     *ptr2 = clearPixel;
847                     ptr2++;
848                  }
849               }
850            }
851         }
852	 else {
853#if CHAN_TYPE == GL_UNSIGNED_BYTE
854	    /* 4-byte pixel value */
855	    GLuint clearPixel;
856	    GLchan *clr = (GLchan *) &clearPixel;
857            CLAMPED_FLOAT_TO_CHAN(clr[osmesa->rInd], ctx->Color.ClearColor[0]);
858            CLAMPED_FLOAT_TO_CHAN(clr[osmesa->gInd], ctx->Color.ClearColor[1]);
859            CLAMPED_FLOAT_TO_CHAN(clr[osmesa->bInd], ctx->Color.ClearColor[2]);
860            CLAMPED_FLOAT_TO_CHAN(clr[osmesa->aInd], ctx->Color.ClearColor[3]);
861	    if (all) {
862	       /* Clear whole RGBA buffer */
863	       const GLuint n = osmesa->rowlength * osmesa->height;
864	       GLuint *ptr4 = (GLuint *) osmesa->buffer;
865	       GLuint i;
866	       if (clearPixel) {
867		  for (i = 0; i < n; i++) {
868		     *ptr4++ = clearPixel;
869		  }
870	       }
871	       else {
872		  BZERO(ptr4, n * sizeof(GLuint));
873	       }
874	    }
875	    else {
876	       /* Clear part of RGBA buffer */
877	       GLint i, j;
878	       for (i = 0; i < height; i++) {
879		  GLuint *ptr4 = (GLuint *) PIXELADDR4(x, (y + i));
880		  for (j = 0; j < width; j++) {
881		     *ptr4++ = clearPixel;
882		  }
883	       }
884	    }
885#else
886            GLchan r, g, b, a;
887            CLAMPED_FLOAT_TO_CHAN(r, ctx->Color.ClearColor[0]);
888            CLAMPED_FLOAT_TO_CHAN(g, ctx->Color.ClearColor[1]);
889            CLAMPED_FLOAT_TO_CHAN(b, ctx->Color.ClearColor[2]);
890            CLAMPED_FLOAT_TO_CHAN(a, ctx->Color.ClearColor[3]);
891	    if (all) {
892	       /* Clear whole RGBA buffer */
893	       const GLuint n = osmesa->rowlength * osmesa->height;
894	       GLchan *p = (GLchan *) osmesa->buffer;
895	       GLuint i;
896	       for (i = 0; i < n; i++) {
897		  PACK_RGBA(p, r, g, b, a);
898		  p += 4;
899	       }
900	    }
901	    else {
902	       /* Clear part of RGBA buffer */
903	       GLint i, j;
904	       for (i = 0; i < height; i++) {
905		  GLchan *p = PIXELADDR4(x, (y + i));
906		  for (j = 0; j < width; j++) {
907		     PACK_RGBA(p, r, g, b, a);
908		     p += 4;
909		  }
910	       }
911	    }
912
913#endif
914	 }
915	 mask &= ~DD_FRONT_LEFT_BIT;
916      }
917   }
918
919   if (mask)
920      _swrast_Clear( ctx, mask, all, x, y, width, height );
921}
922
923
924
925static void buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
926{
927   /* don't use GET_CURRENT_CONTEXT(ctx) here - it's a problem on Windows */
928   GLcontext *ctx = (GLcontext *) _glapi_get_context();
929   (void) buffer;
930   if (ctx) {
931      OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
932      *width = osmesa->width;
933      *height = osmesa->height;
934   }
935}
936
937
938/**********************************************************************/
939/*****        Read/write spans/arrays of RGBA pixels              *****/
940/**********************************************************************/
941
942/* Write RGBA pixels to an RGBA (or permuted) buffer. */
943static void
944write_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
945                 CONST GLchan rgba[][4], const GLubyte mask[] )
946{
947   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
948   GLchan *p = PIXELADDR4(x, y);
949   GLuint i;
950   if (mask) {
951      for (i = 0; i < n; i++, p += 4) {
952         if (mask[i]) {
953            PACK_RGBA(p, rgba[i][RCOMP], rgba[i][GCOMP],
954                         rgba[i][BCOMP], rgba[i][ACOMP]);
955         }
956      }
957   }
958   else {
959      for (i = 0; i < n; i++, p += 4) {
960         PACK_RGBA(p, rgba[i][RCOMP], rgba[i][GCOMP],
961                      rgba[i][BCOMP], rgba[i][ACOMP]);
962      }
963   }
964}
965
966
967/* Write RGBA pixels to an RGBA buffer.  This is the fastest span-writer. */
968static void
969write_rgba_span_rgba( const GLcontext *ctx, GLuint n, GLint x, GLint y,
970                      CONST GLchan rgba[][4], const GLubyte mask[] )
971{
972   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
973   GLuint *ptr4 = (GLuint *) PIXELADDR4(x, y);
974   const GLuint *rgba4 = (const GLuint *) rgba;
975   GLuint i;
976   ASSERT(CHAN_TYPE == GL_UNSIGNED_BYTE);
977   if (mask) {
978      for (i = 0; i < n; i++) {
979         if (mask[i]) {
980            ptr4[i] = rgba4[i];
981         }
982      }
983   }
984   else {
985      MEMCPY( ptr4, rgba4, n * 4 );
986   }
987}
988
989
990/* Write RGB pixels to an RGBA (or permuted) buffer. */
991static void
992write_rgb_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
993                CONST GLchan rgb[][3], const GLubyte mask[] )
994{
995   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
996   GLchan *p = PIXELADDR4(x, y);
997   GLuint i;
998   if (mask) {
999      for (i = 0; i < n; i++, p+=4) {
1000         if (mask[i]) {
1001            PACK_RGBA(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], CHAN_MAX);
1002         }
1003      }
1004   }
1005   else {
1006      for (i = 0; i < n; i++, p+=4) {
1007         PACK_RGBA(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], CHAN_MAX);
1008      }
1009   }
1010}
1011
1012
1013
1014static void
1015write_monocolor_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1016                      const GLchan color[4], const GLubyte mask[] )
1017{
1018   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1019   GLchan *p = PIXELADDR4(x, y);
1020   GLuint i;
1021   for (i = 0; i < n; i++, p += 4) {
1022      if (mask[i]) {
1023         PACK_RGBA(p, color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP]);
1024      }
1025   }
1026}
1027
1028
1029
1030static void
1031write_rgba_pixels( const GLcontext *ctx, GLuint n,
1032                   const GLint x[], const GLint y[],
1033                   CONST GLchan rgba[][4], const GLubyte mask[] )
1034{
1035   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1036   GLuint i;
1037   for (i = 0; i < n; i++) {
1038      if (mask[i]) {
1039         GLchan *p = PIXELADDR4(x[i], y[i]);
1040         PACK_RGBA(p, rgba[i][RCOMP], rgba[i][GCOMP],
1041                      rgba[i][BCOMP], rgba[i][ACOMP]);
1042      }
1043   }
1044}
1045
1046
1047
1048static void
1049write_monocolor_pixels( const GLcontext *ctx, GLuint n,
1050                        const GLint x[], const GLint y[],
1051                        const GLchan color[4], const GLubyte mask[] )
1052{
1053   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1054   GLuint i;
1055   for (i = 0; i < n; i++) {
1056      if (mask[i]) {
1057         GLchan *p = PIXELADDR4(x[i], y[i]);
1058         PACK_RGBA(p, color[RCOMP], color[GCOMP], color[BCOMP], color[ACOMP]);
1059      }
1060   }
1061}
1062
1063
1064static void
1065read_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1066                GLchan rgba[][4] )
1067{
1068   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1069   GLuint i;
1070   GLchan *p = PIXELADDR4(x, y);
1071   for (i = 0; i < n; i++, p += 4) {
1072      rgba[i][RCOMP] = UNPACK_RED(p);
1073      rgba[i][GCOMP] = UNPACK_GREEN(p);
1074      rgba[i][BCOMP] = UNPACK_BLUE(p);
1075      rgba[i][ACOMP] = UNPACK_ALPHA(p);
1076   }
1077}
1078
1079
1080/* Read RGBA pixels from an RGBA buffer */
1081static void
1082read_rgba_span_rgba( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1083                     GLchan rgba[][4] )
1084{
1085   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1086   GLuint *ptr4 = (GLuint *) PIXELADDR4(x, y);
1087   MEMCPY( rgba, ptr4, n * 4 * sizeof(GLchan) );
1088}
1089
1090
1091static void
1092read_rgba_pixels( const GLcontext *ctx,
1093                  GLuint n, const GLint x[], const GLint y[],
1094                  GLchan rgba[][4], const GLubyte mask[] )
1095{
1096   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1097   GLuint i;
1098   for (i = 0; i < n; i++) {
1099      if (mask[i]) {
1100         const GLchan *p = PIXELADDR4(x[i], y[i]);
1101         rgba[i][RCOMP] = UNPACK_RED(p);
1102         rgba[i][GCOMP] = UNPACK_GREEN(p);
1103         rgba[i][BCOMP] = UNPACK_BLUE(p);
1104         rgba[i][ACOMP] = UNPACK_ALPHA(p);
1105      }
1106   }
1107}
1108
1109/**********************************************************************/
1110/*****                3 byte RGB pixel support funcs              *****/
1111/**********************************************************************/
1112
1113/* Write RGBA pixels to an RGB buffer. */
1114static void
1115write_rgba_span_RGB( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1116                     CONST GLchan rgba[][4], const GLubyte mask[] )
1117{
1118   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1119   GLchan *p = PIXELADDR3(x, y);
1120   GLuint i;
1121   if (mask) {
1122      for (i = 0; i < n; i++, p += 3) {
1123         if (mask[i]) {
1124            PACK_RGB(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1125         }
1126      }
1127   }
1128   else {
1129      for (i = 0; i < n; i++, p += 3) {
1130         PACK_RGB(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1131      }
1132   }
1133}
1134
1135/* Write RGBA pixels to an BGR buffer. */
1136static void
1137write_rgba_span_BGR( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1138                     CONST GLchan rgba[][4], const GLubyte mask[] )
1139{
1140   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1141   GLchan *p = PIXELADDR3(x, y);
1142   GLuint i;
1143   if (mask) {
1144      for (i = 0; i < n; i++, p += 3) {
1145         if (mask[i]) {
1146            PACK_BGR(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1147         }
1148      }
1149   }
1150   else {
1151      for (i = 0; i < n; i++, p += 3) {
1152         PACK_BGR(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1153      }
1154   }
1155}
1156
1157/* Write RGB pixels to an RGB buffer. */
1158static void
1159write_rgb_span_RGB( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1160                    CONST GLchan rgb[][3], const GLubyte mask[] )
1161{
1162   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1163   GLchan *p = PIXELADDR3(x, y);
1164   GLuint i;
1165   if (mask) {
1166      for (i = 0; i < n; i++, p += 3) {
1167         if (mask[i]) {
1168            PACK_RGB(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1169         }
1170      }
1171   }
1172   else {
1173      for (i = 0; i < n; i++, p += 3) {
1174         PACK_RGB(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1175      }
1176   }
1177}
1178
1179/* Write RGB pixels to an BGR buffer. */
1180static void
1181write_rgb_span_BGR( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1182                    CONST GLchan rgb[][3], const GLubyte mask[] )
1183{
1184   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1185   GLchan *p = PIXELADDR3(x, y);
1186   GLuint i;
1187   if (mask) {
1188      for (i = 0; i < n; i++, p += 3) {
1189         if (mask[i]) {
1190            PACK_BGR(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1191         }
1192      }
1193   }
1194   else {
1195      for (i = 0; i < n; i++, p += 3) {
1196         PACK_BGR(p, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1197      }
1198   }
1199}
1200
1201
1202static void
1203write_monocolor_span_RGB( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1204                          const GLchan color[4], const GLubyte mask[] )
1205{
1206   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1207   GLchan *p = PIXELADDR3(x, y);
1208   GLuint i;
1209   for (i = 0; i < n; i++, p += 3) {
1210      if (mask[i]) {
1211         PACK_RGB(p, color[RCOMP], color[GCOMP], color[BCOMP]);
1212      }
1213   }
1214}
1215
1216static void
1217write_monocolor_span_BGR( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1218                          const GLchan color[4], const GLubyte mask[] )
1219{
1220   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1221   GLchan *p = PIXELADDR3(x, y);
1222   GLuint i;
1223   for (i = 0; i < n; i++, p += 3) {
1224      if (mask[i]) {
1225         PACK_BGR(p, color[RCOMP], color[GCOMP], color[BCOMP]);
1226      }
1227   }
1228}
1229
1230static void
1231write_rgba_pixels_RGB( const GLcontext *ctx, GLuint n,
1232                       const GLint x[], const GLint y[],
1233                       CONST GLchan rgba[][4], const GLubyte mask[] )
1234{
1235   const OSMesaContext osmesa = (const OSMesaContext) ctx;
1236   GLuint i;
1237   for (i = 0; i < n; i++) {
1238      if (mask[i]) {
1239         GLchan *p = PIXELADDR3(x[i], y[i]);
1240         PACK_RGB(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1241      }
1242   }
1243}
1244
1245static void
1246write_rgba_pixels_BGR( const GLcontext *ctx, GLuint n,
1247                       const GLint x[], const GLint y[],
1248                       CONST GLchan rgba[][4], const GLubyte mask[] )
1249{
1250   const OSMesaContext osmesa = (const OSMesaContext) ctx;
1251   GLuint i;
1252   for (i = 0; i < n; i++) {
1253      if (mask[i]) {
1254         GLchan *p = PIXELADDR3(x[i], y[i]);
1255         PACK_BGR(p, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1256      }
1257   }
1258}
1259
1260static void
1261write_monocolor_pixels_RGB( const GLcontext *ctx,
1262                            GLuint n, const GLint x[], const GLint y[],
1263                            const GLchan color[4], const GLubyte mask[] )
1264{
1265   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1266   GLuint i;
1267   for (i = 0; i < n; i++) {
1268      if (mask[i]) {
1269         GLchan *p = PIXELADDR3(x[i], y[i]);
1270         PACK_RGB(p, color[RCOMP], color[GCOMP], color[BCOMP]);
1271      }
1272   }
1273}
1274
1275static void
1276write_monocolor_pixels_BGR( const GLcontext *ctx,
1277                            GLuint n, const GLint x[], const GLint y[],
1278                            const GLchan color[4], const GLubyte mask[] )
1279{
1280   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1281   GLuint i;
1282   for (i = 0; i < n; i++) {
1283      if (mask[i]) {
1284         GLchan *p = PIXELADDR3(x[i], y[i]);
1285         PACK_BGR(p, color[RCOMP], color[GCOMP], color[BCOMP]);
1286      }
1287   }
1288}
1289
1290static void
1291read_rgba_span3( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1292                 GLchan rgba[][4] )
1293{
1294   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1295   GLuint i;
1296   const GLchan *p = PIXELADDR3(x, y);
1297   for (i = 0; i < n; i++, p += 3) {
1298      rgba[i][RCOMP] = UNPACK_RED(p);
1299      rgba[i][GCOMP] = UNPACK_GREEN(p);
1300      rgba[i][BCOMP] = UNPACK_BLUE(p);
1301      rgba[i][ACOMP] = CHAN_MAX;
1302   }
1303}
1304
1305static void
1306read_rgba_pixels3( const GLcontext *ctx,
1307                   GLuint n, const GLint x[], const GLint y[],
1308                   GLchan rgba[][4], const GLubyte mask[] )
1309{
1310   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1311   GLuint i;
1312   for (i = 0; i < n; i++) {
1313      if (mask[i]) {
1314         const GLchan *p = PIXELADDR3(x[i], y[i]);
1315         rgba[i][RCOMP] = UNPACK_RED(p);
1316         rgba[i][GCOMP] = UNPACK_GREEN(p);
1317         rgba[i][BCOMP] = UNPACK_BLUE(p);
1318         rgba[i][ACOMP] = CHAN_MAX;
1319      }
1320   }
1321}
1322
1323
1324/**********************************************************************/
1325/*****                2 byte RGB pixel support funcs              *****/
1326/**********************************************************************/
1327
1328/* Write RGBA pixels to an RGB_565 buffer. */
1329static void
1330write_rgba_span2( const GLcontext *ctx,
1331                  GLuint n, GLint x, GLint y,
1332                  CONST GLchan rgba[][4], const GLubyte mask[] )
1333{
1334   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1335   GLushort *ptr2 = (GLushort *) PIXELADDR2(x, y);
1336   GLuint i;
1337   if (mask) {
1338      for (i = 0; i < n; i++, ptr2++) {
1339         if (mask[i]) {
1340            PACK_RGB_565(*ptr2, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1341         }
1342      }
1343   }
1344   else {
1345      for (i = 0; i < n; i++, ptr2++) {
1346         PACK_RGB_565(*ptr2, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1347      }
1348   }
1349}
1350
1351
1352/* Write RGB pixels to an RGB_565 buffer. */
1353static void
1354write_rgb_span2( const GLcontext *ctx,
1355                 GLuint n, GLint x, GLint y,
1356                 CONST GLchan rgb[][3], const GLubyte mask[] )
1357{
1358   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1359   GLushort *ptr2 = (GLushort *) PIXELADDR2(x, y);
1360   GLuint i;
1361   if (mask) {
1362      for (i = 0; i < n; i++, ptr2++) {
1363         if (mask[i]) {
1364            PACK_RGB_565(*ptr2, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1365         }
1366      }
1367   }
1368   else {
1369      for (i = 0; i < n; i++, ptr2++) {
1370         PACK_RGB_565(*ptr2, rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP]);
1371      }
1372   }
1373}
1374
1375
1376static void
1377write_monocolor_span2( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1378                       const GLchan color[4], const GLubyte mask[] )
1379{
1380   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1381   GLushort pixel;
1382   GLushort *ptr2 = (GLushort *) PIXELADDR2(x, y);
1383   GLuint i;
1384   PACK_RGB_565(pixel, color[RCOMP], color[GCOMP], color[BCOMP]);
1385   for (i = 0; i < n; i++, ptr2++) {
1386      if (mask[i]) {
1387         *ptr2 = pixel;
1388      }
1389   }
1390}
1391
1392
1393static void
1394write_rgba_pixels2( const GLcontext *ctx,
1395                    GLuint n, const GLint x[], const GLint y[],
1396                    CONST GLchan rgba[][4], const GLubyte mask[] )
1397{
1398   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1399   GLuint i;
1400   for (i = 0; i < n; i++) {
1401      if (mask[i]) {
1402         GLushort *ptr2 = (GLushort *) PIXELADDR2(x[i],y[i]);
1403         PACK_RGB_565(*ptr2, rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]);
1404      }
1405   }
1406}
1407
1408static void
1409write_monocolor_pixels2( const GLcontext *ctx,
1410                         GLuint n, const GLint x[], const GLint y[],
1411                         const GLchan color[4], const GLubyte mask[] )
1412{
1413   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1414   GLuint i;
1415   GLushort pixel;
1416   PACK_RGB_565(pixel, color[RCOMP], color[GCOMP], color[BCOMP]);
1417   for (i = 0; i < n; i++) {
1418      if (mask[i]) {
1419         GLushort *ptr2 = (GLushort *) PIXELADDR2(x[i],y[i]);
1420         *ptr2 = pixel;
1421      }
1422   }
1423}
1424
1425static void
1426read_rgba_span2( const GLcontext *ctx,
1427                 GLuint n, GLint x, GLint y,
1428                 GLchan rgba[][4] )
1429{
1430   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1431   GLuint i;
1432   const GLushort *ptr2 = (const GLushort *) PIXELADDR2(x, y);
1433   for (i = 0; i < n; i++, ptr2++) {
1434      /* This should be fixed to get the low bits right */
1435      rgba[i][RCOMP] = (*ptr2 >> 8) & 0xFe;
1436      rgba[i][GCOMP] = (*ptr2 >> 3) & 0xFc;
1437      rgba[i][BCOMP] = (*ptr2 << 3) & 0xFe;
1438      rgba[i][ACOMP] = 0;
1439   }
1440}
1441
1442static void
1443read_rgba_pixels2( const GLcontext *ctx,
1444                   GLuint n, const GLint x[], const GLint y[],
1445                   GLchan rgba[][4], const GLubyte mask[] )
1446{
1447   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1448   GLuint i;
1449   for (i = 0; i < n; i++) {
1450      if (mask[i]) {
1451         /* This should be fixed to get the low bits right */
1452         const GLushort *ptr2 = (const GLushort *) PIXELADDR2(x[i],y[i]);
1453         rgba[i][RCOMP] = (*ptr2 >> 8) & 0xFE;
1454         rgba[i][GCOMP] = (*ptr2 >> 3) & 0xFC;
1455         rgba[i][BCOMP] = (*ptr2 << 3) & 0xFE;
1456         rgba[i][ACOMP] = 0;
1457      }
1458   }
1459}
1460
1461
1462
1463/**********************************************************************/
1464/*****        Read/write spans/arrays of CI pixels                *****/
1465/**********************************************************************/
1466
1467/* Write 32-bit color index to buffer */
1468static void
1469write_index32_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1470                    const GLuint index[], const GLubyte mask[] )
1471{
1472   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1473   GLchan *ptr1 = PIXELADDR1(x, y);
1474   GLuint i;
1475   if (mask) {
1476      for (i=0;i<n;i++,ptr1++) {
1477         if (mask[i]) {
1478            *ptr1 = (GLchan) index[i];
1479         }
1480      }
1481   }
1482   else {
1483      for (i=0;i<n;i++,ptr1++) {
1484         *ptr1 = (GLchan) index[i];
1485      }
1486   }
1487}
1488
1489
1490/* Write 8-bit color index to buffer */
1491static void
1492write_index8_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1493                   const GLubyte index[], const GLubyte mask[] )
1494{
1495   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1496   GLchan *ptr1 = PIXELADDR1(x, y);
1497   GLuint i;
1498   if (mask) {
1499      for (i=0;i<n;i++,ptr1++) {
1500         if (mask[i]) {
1501            *ptr1 = (GLchan) index[i];
1502         }
1503      }
1504   }
1505   else {
1506      MEMCPY(ptr1, index, n * sizeof(GLchan));
1507   }
1508}
1509
1510
1511static void
1512write_monoindex_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
1513                      GLuint colorIndex, const GLubyte mask[] )
1514{
1515   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1516   GLchan *ptr1 = PIXELADDR1(x, y);
1517   GLuint i;
1518   for (i=0;i<n;i++,ptr1++) {
1519      if (mask[i]) {
1520         *ptr1 = (GLchan) colorIndex;
1521      }
1522   }
1523}
1524
1525
1526static void
1527write_index_pixels( const GLcontext *ctx,
1528                    GLuint n, const GLint x[], const GLint y[],
1529                    const GLuint index[], const GLubyte mask[] )
1530{
1531   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1532   GLuint i;
1533   for (i=0;i<n;i++) {
1534      if (mask[i]) {
1535         GLchan *ptr1 = PIXELADDR1(x[i], y[i]);
1536         *ptr1 = (GLchan) index[i];
1537      }
1538   }
1539}
1540
1541
1542static void
1543write_monoindex_pixels( const GLcontext *ctx,
1544                        GLuint n, const GLint x[], const GLint y[],
1545                        GLuint colorIndex, const GLubyte mask[] )
1546{
1547   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1548   GLuint i;
1549   for (i=0;i<n;i++) {
1550      if (mask[i]) {
1551         GLchan *ptr1 = PIXELADDR1(x[i], y[i]);
1552         *ptr1 = (GLchan) colorIndex;
1553      }
1554   }
1555}
1556
1557
1558static void
1559read_index_span( const GLcontext *ctx,
1560                 GLuint n, GLint x, GLint y, GLuint index[] )
1561{
1562   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1563   GLuint i;
1564   const GLchan *ptr1 = (const GLchan *) PIXELADDR1(x, y);
1565   for (i=0;i<n;i++,ptr1++) {
1566      index[i] = (GLuint) *ptr1;
1567   }
1568}
1569
1570
1571static void
1572read_index_pixels( const GLcontext *ctx,
1573                   GLuint n, const GLint x[], const GLint y[],
1574                   GLuint index[], const GLubyte mask[] )
1575{
1576   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1577   GLuint i;
1578   for (i=0;i<n;i++) {
1579      if (mask[i] ) {
1580         const GLchan *ptr1 = PIXELADDR1(x[i], y[i]);
1581         index[i] = (GLuint) *ptr1;
1582      }
1583   }
1584}
1585
1586
1587
1588/**********************************************************************/
1589/*****                   Optimized line rendering                 *****/
1590/**********************************************************************/
1591
1592
1593/*
1594 * Draw a flat-shaded, RGB line into an osmesa buffer.
1595 */
1596static void
1597flat_rgba_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 )
1598{
1599   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1600   const GLchan *color = vert1->color;
1601
1602#define INTERP_XY 1
1603#define CLIP_HACK 1
1604#define PLOT(X, Y)						\
1605do {								\
1606   GLchan *p = PIXELADDR4(X, Y);				\
1607   PACK_RGBA(p, color[0], color[1], color[2], color[3]);	\
1608} while (0)
1609
1610#ifdef WIN32
1611#include "..\swrast\s_linetemp.h"
1612#else
1613#include "swrast/s_linetemp.h"
1614#endif
1615}
1616
1617
1618/*
1619 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
1620 */
1621static void
1622flat_rgba_z_line(GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1)
1623{
1624   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1625   const GLchan *color = vert1->color;
1626
1627#define INTERP_XY 1
1628#define INTERP_Z 1
1629#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1630#define CLIP_HACK 1
1631#define PLOT(X, Y)					\
1632do {							\
1633   if (Z < *zPtr) {					\
1634      GLchan *p = PIXELADDR4(X, Y);			\
1635      PACK_RGBA(p, color[RCOMP], color[GCOMP],		\
1636                   color[BCOMP], color[ACOMP]);		\
1637      *zPtr = Z;					\
1638   }							\
1639} while (0)
1640
1641
1642#ifdef WIN32
1643#include "..\swrast\s_linetemp.h"
1644#else
1645#include "swrast/s_linetemp.h"
1646#endif
1647}
1648
1649
1650/*
1651 * Draw a flat-shaded, alpha-blended, RGB line into an osmesa buffer.
1652 * XXX update for GLchan
1653 */
1654static void
1655flat_blend_rgba_line( GLcontext *ctx,
1656                      const SWvertex *vert0, const SWvertex *vert1 )
1657{
1658   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1659   const GLint rshift = osmesa->rshift;
1660   const GLint gshift = osmesa->gshift;
1661   const GLint bshift = osmesa->bshift;
1662   const GLint avalue = vert0->color[3];
1663   const GLint msavalue = CHAN_MAX - avalue;
1664   const GLint rvalue = vert1->color[0]*avalue;
1665   const GLint gvalue = vert1->color[1]*avalue;
1666   const GLint bvalue = vert1->color[2]*avalue;
1667
1668#define INTERP_XY 1
1669#define CLIP_HACK 1
1670#define PLOT(X,Y)					\
1671   { GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y);	\
1672     GLuint  pixel = 0;					\
1673     pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);\
1674     pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);\
1675     pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);\
1676     *ptr4 = pixel;					\
1677   }
1678
1679#if 0  /* XXX use this in the future */
1680#define PLOT(X,Y)							\
1681   {									\
1682      GLchan *pixel = (GLchan *) PIXELADDR4(X, Y);			\
1683      pixel[rInd] = (pixel[rInd] * msavalue + rvalue) >> CHAN_BITS;	\
1684      pixel[gInd] = (pixel[gInd] * msavalue + gvalue) >> CHAN_BITS;	\
1685      pixel[bInd] = (pixel[bInd] * msavalue + bvalue) >> CHAN_BITS;	\
1686      pixel[aInd] = (pixel[aInd] * msavalue + avalue) >> CHAN_BITS;	\
1687   }
1688#endif
1689
1690#ifdef WIN32
1691#include "..\swrast\s_linetemp.h"
1692#else
1693#include "swrast/s_linetemp.h"
1694#endif
1695}
1696
1697
1698/*
1699 * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer.
1700 * But don't write to Z buffer.
1701 * XXX update for GLchan
1702 */
1703static void
1704flat_blend_rgba_z_line( GLcontext *ctx,
1705                        const SWvertex *vert0, const SWvertex *vert1 )
1706{
1707   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1708   const GLint rshift = osmesa->rshift;
1709   const GLint gshift = osmesa->gshift;
1710   const GLint bshift = osmesa->bshift;
1711   const GLint avalue = vert0->color[3];
1712   const GLint msavalue = 256 - avalue;
1713   const GLint rvalue = vert1->color[0]*avalue;
1714   const GLint gvalue = vert1->color[1]*avalue;
1715   const GLint bvalue = vert1->color[2]*avalue;
1716
1717#define INTERP_XY 1
1718#define INTERP_Z 1
1719#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1720#define CLIP_HACK 1
1721#define PLOT(X,Y)							\
1722	if (Z < *zPtr) {						\
1723	   GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y);			\
1724	   GLuint  pixel = 0;						\
1725	   pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);	\
1726	   pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);	\
1727	   pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);	\
1728	   *ptr4 = pixel; 						\
1729	}
1730
1731#if 0  /* XXX use this in the future */
1732#define PLOT(X,Y)							\
1733   if (Z < *zPtr) {							\
1734      GLchan *pixel = (GLchan *) PIXELADDR4(X, Y);			\
1735      pixel[rInd] = (pixel[rInd] * msavalue + rvalue) >> CHAN_BITS;	\
1736      pixel[gInd] = (pixel[gInd] * msavalue + gvalue) >> CHAN_BITS;	\
1737      pixel[bInd] = (pixel[bInd] * msavalue + bvalue) >> CHAN_BITS;	\
1738      pixel[aInd] = (pixel[aInd] * msavalue + avalue) >> CHAN_BITS;	\
1739   }
1740#endif
1741
1742#ifdef WIN32
1743#include "..\swrast\s_linetemp.h"
1744#else
1745#include "swrast/s_linetemp.h"
1746#endif
1747}
1748
1749
1750/*
1751 * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer.
1752 * XXX update for GLchan
1753 */
1754static void
1755flat_blend_rgba_z_line_write( GLcontext *ctx,
1756                              const SWvertex *vert0, const SWvertex *vert1 )
1757{
1758   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1759   const GLint rshift = osmesa->rshift;
1760   const GLint gshift = osmesa->gshift;
1761   const GLint bshift = osmesa->bshift;
1762   const GLint avalue = vert0->color[3];
1763   const GLint msavalue = 256 - avalue;
1764   const GLint rvalue = vert1->color[0]*avalue;
1765   const GLint gvalue = vert1->color[1]*avalue;
1766   const GLint bvalue = vert1->color[2]*avalue;
1767
1768#define INTERP_XY 1
1769#define INTERP_Z 1
1770#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1771#define CLIP_HACK 1
1772#define PLOT(X,Y)							\
1773	if (Z < *zPtr) {						\
1774	   GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y);			\
1775	   GLuint  pixel = 0;						\
1776	   pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);	\
1777	   pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);	\
1778	   pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);	\
1779	   *ptr4 = pixel;						\
1780	   *zPtr = Z;							\
1781	}
1782
1783#if 0  /* XXX use this in the future */
1784#define PLOT(X,Y)							\
1785   if (Z < *zPtr) {							\
1786      GLchan *pixel = (GLchan *) PIXELADDR4(X, Y);			\
1787      pixel[rInd] = (pixel[rInd] * msavalue + rvalue) >> CHAN_BITS;	\
1788      pixel[gInd] = (pixel[gInd] * msavalue + gvalue) >> CHAN_BITS;	\
1789      pixel[bInd] = (pixel[bInd] * msavalue + bvalue) >> CHAN_BITS;	\
1790      pixel[aInd] = (pixel[aInd] * msavalue + avalue) >> CHAN_BITS;	\
1791      *zPtr = Z;							\
1792   }
1793#endif
1794
1795#ifdef WIN32
1796#include "..\swrast\s_linetemp.h"
1797#else
1798#include "swrast/s_linetemp.h"
1799#endif
1800}
1801
1802
1803/*
1804 * Analyze context state to see if we can provide a fast line drawing
1805 * function, like those in lines.c.  Otherwise, return NULL.
1806 */
1807static swrast_line_func
1808osmesa_choose_line_function( GLcontext *ctx )
1809{
1810   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1811   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1812
1813   if (CHAN_BITS != 8)                    return NULL;
1814   if (ctx->RenderMode != GL_RENDER)      return NULL;
1815   if (ctx->Line.SmoothFlag)              return NULL;
1816   if (ctx->Texture._EnabledUnits)        return NULL;
1817   if (ctx->Light.ShadeModel != GL_FLAT)  return NULL;
1818   if (ctx->Line.Width != 1.0F)           return NULL;
1819   if (ctx->Line.StippleFlag)             return NULL;
1820   if (ctx->Line.SmoothFlag)              return NULL;
1821   if (osmesa->format != OSMESA_RGBA &&
1822       osmesa->format != OSMESA_BGRA &&
1823       osmesa->format != OSMESA_ARGB)     return NULL;
1824
1825   if (swrast->_RasterMask==DEPTH_BIT
1826       && ctx->Depth.Func==GL_LESS
1827       && ctx->Depth.Mask==GL_TRUE
1828       && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
1829      return (swrast_line_func) flat_rgba_z_line;
1830   }
1831
1832   if (swrast->_RasterMask == 0) {
1833      return (swrast_line_func) flat_rgba_line;
1834   }
1835
1836   if (swrast->_RasterMask==(DEPTH_BIT|BLEND_BIT)
1837       && ctx->Depth.Func==GL_LESS
1838       && ctx->Depth.Mask==GL_TRUE
1839       && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
1840       && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
1841       && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
1842       && ctx->Color.BlendSrcA==GL_SRC_ALPHA
1843       && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
1844       && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
1845      return (swrast_line_func) flat_blend_rgba_z_line_write;
1846   }
1847
1848   if (swrast->_RasterMask==(DEPTH_BIT|BLEND_BIT)
1849       && ctx->Depth.Func==GL_LESS
1850       && ctx->Depth.Mask==GL_FALSE
1851       && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
1852       && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
1853       && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
1854       && ctx->Color.BlendSrcA==GL_SRC_ALPHA
1855       && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
1856       && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
1857      return (swrast_line_func) flat_blend_rgba_z_line;
1858   }
1859
1860   if (swrast->_RasterMask==BLEND_BIT
1861       && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
1862       && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
1863       && ctx->Color.BlendSrcA==GL_SRC_ALPHA
1864       && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
1865       && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
1866      return (swrast_line_func) flat_blend_rgba_line;
1867   }
1868
1869   return (swrast_line_func) NULL;
1870}
1871
1872
1873/**********************************************************************/
1874/*****                 Optimized triangle rendering               *****/
1875/**********************************************************************/
1876
1877
1878/*
1879 * Smooth-shaded, z-less triangle, RGBA color.
1880 */
1881static void smooth_rgba_z_triangle( GLcontext *ctx,
1882				    const SWvertex *v0,
1883                                    const SWvertex *v1,
1884                                    const SWvertex *v2 )
1885{
1886   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1887#define INTERP_Z 1
1888#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1889#define INTERP_RGB 1
1890#define INTERP_ALPHA 1
1891#define RENDER_SPAN( span )					\
1892   GLuint i;							\
1893   GLchan *img = PIXELADDR4(span.x, span.y); 			\
1894   for (i = 0; i < span.end; i++, img += 4) {			\
1895      const GLdepth z = FixedToDepth(span.z);			\
1896      if (z < zRow[i]) {					\
1897         PACK_RGBA(img, FixedToChan(span.red),			\
1898            FixedToChan(span.green), FixedToChan(span.blue),	\
1899            FixedToChan(span.alpha));				\
1900         zRow[i] = z;						\
1901      }								\
1902      span.red += span.redStep;					\
1903      span.green += span.greenStep;				\
1904      span.blue += span.blueStep;				\
1905      span.alpha += span.alphaStep;				\
1906      span.z += span.zStep;					\
1907   }
1908
1909#ifdef WIN32
1910#include "..\swrast\s_tritemp.h"
1911#else
1912#include "swrast/s_tritemp.h"
1913#endif
1914}
1915
1916
1917
1918
1919/*
1920 * Flat-shaded, z-less triangle, RGBA color.
1921 */
1922static void flat_rgba_z_triangle( GLcontext *ctx,
1923				  const SWvertex *v0,
1924                                  const SWvertex *v1,
1925                                  const SWvertex *v2 )
1926{
1927   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1928#define INTERP_Z 1
1929#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1930#define SETUP_CODE						\
1931   GLuint pixel;						\
1932   PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1],	\
1933                                v2->color[2], v2->color[3]);
1934
1935#define RENDER_SPAN( span )				\
1936   GLuint i;						\
1937   GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y);	\
1938   for (i = 0; i < span.end; i++) {			\
1939      const GLdepth z = FixedToDepth(span.z);		\
1940      if (z < zRow[i]) {				\
1941         img[i] = pixel;				\
1942         zRow[i] = z;					\
1943      }							\
1944      span.z += span.zStep;				\
1945   }
1946
1947#ifdef WIN32
1948#include "..\swrast\s_tritemp.h"
1949#else
1950#include "swrast/s_tritemp.h"
1951#endif
1952}
1953
1954
1955
1956/*
1957 * Return pointer to an accelerated triangle function if possible.
1958 */
1959static swrast_tri_func
1960osmesa_choose_triangle_function( GLcontext *ctx )
1961{
1962   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
1963   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
1964
1965   if (CHAN_BITS != 8)                  return (swrast_tri_func) NULL;
1966   if (ctx->RenderMode != GL_RENDER)    return (swrast_tri_func) NULL;
1967   if (ctx->Polygon.SmoothFlag)         return (swrast_tri_func) NULL;
1968   if (ctx->Polygon.StippleFlag)        return (swrast_tri_func) NULL;
1969   if (ctx->Texture._EnabledUnits)      return (swrast_tri_func) NULL;
1970   if (osmesa->format != OSMESA_RGBA &&
1971       osmesa->format != OSMESA_BGRA &&
1972       osmesa->format != OSMESA_ARGB)   return (swrast_tri_func) NULL;
1973   if (ctx->Polygon.CullFlag &&
1974       ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
1975                                        return (swrast_tri_func) NULL;
1976
1977   if (swrast->_RasterMask == DEPTH_BIT &&
1978       ctx->Depth.Func == GL_LESS &&
1979       ctx->Depth.Mask == GL_TRUE &&
1980       ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
1981      if (ctx->Light.ShadeModel == GL_SMOOTH) {
1982         return (swrast_tri_func) smooth_rgba_z_triangle;
1983      }
1984      else {
1985         return (swrast_tri_func) flat_rgba_z_triangle;
1986      }
1987   }
1988   return (swrast_tri_func) NULL;
1989}
1990
1991
1992
1993/* Override for the swrast triangle-selection function.  Try to use one
1994 * of our internal triangle functions, otherwise fall back to the
1995 * standard swrast functions.
1996 */
1997static void osmesa_choose_triangle( GLcontext *ctx )
1998{
1999   SWcontext *swrast = SWRAST_CONTEXT(ctx);
2000
2001   swrast->Triangle = osmesa_choose_triangle_function( ctx );
2002   if (!swrast->Triangle)
2003      _swrast_choose_triangle( ctx );
2004}
2005
2006static void osmesa_choose_line( GLcontext *ctx )
2007{
2008   SWcontext *swrast = SWRAST_CONTEXT(ctx);
2009
2010   swrast->Line = osmesa_choose_line_function( ctx );
2011   if (!swrast->Line)
2012      _swrast_choose_line( ctx );
2013}
2014
2015
2016#define OSMESA_NEW_LINE   (_NEW_LINE | \
2017                           _NEW_TEXTURE | \
2018                           _NEW_LIGHT | \
2019                           _NEW_DEPTH | \
2020                           _NEW_RENDERMODE | \
2021                           _SWRAST_NEW_RASTERMASK)
2022
2023#define OSMESA_NEW_TRIANGLE (_NEW_POLYGON | \
2024                             _NEW_TEXTURE | \
2025                             _NEW_LIGHT | \
2026                             _NEW_DEPTH | \
2027                             _NEW_RENDERMODE | \
2028                             _SWRAST_NEW_RASTERMASK)
2029
2030
2031/* Extend the software rasterizer with our line and triangle
2032 * functions.
2033 */
2034static void osmesa_register_swrast_functions( GLcontext *ctx )
2035{
2036   SWcontext *swrast = SWRAST_CONTEXT( ctx );
2037
2038   swrast->choose_line = osmesa_choose_line;
2039   swrast->choose_triangle = osmesa_choose_triangle;
2040
2041   swrast->invalidate_line |= OSMESA_NEW_LINE;
2042   swrast->invalidate_triangle |= OSMESA_NEW_TRIANGLE;
2043}
2044
2045
2046static const GLubyte *get_string( GLcontext *ctx, GLenum name )
2047{
2048   (void) ctx;
2049   switch (name) {
2050      case GL_RENDERER:
2051#if CHAN_BITS == 32
2052         return (const GLubyte *) "Mesa OffScreen32";
2053#elif CHAN_BITS == 16
2054         return (const GLubyte *) "Mesa OffScreen16";
2055#else
2056         return (const GLubyte *) "Mesa OffScreen";
2057#endif
2058      default:
2059         return NULL;
2060   }
2061}
2062
2063
2064static void osmesa_update_state( GLcontext *ctx, GLuint new_state )
2065{
2066   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
2067   struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx );
2068   TNLcontext *tnl = TNL_CONTEXT(ctx);
2069
2070   ASSERT((void *) osmesa == (void *) ctx->DriverCtx);
2071
2072   /*
2073    * XXX these function pointers could be initialized just once during
2074    * context creation since they don't depend on any state changes.
2075    */
2076
2077   ctx->Driver.GetString = get_string;
2078   ctx->Driver.UpdateState = osmesa_update_state;
2079   ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
2080   ctx->Driver.GetBufferSize = buffer_size;
2081
2082   ctx->Driver.Accum = _swrast_Accum;
2083   ctx->Driver.Bitmap = _swrast_Bitmap;
2084   ctx->Driver.Clear = clear;
2085   ctx->Driver.CopyPixels = _swrast_CopyPixels;
2086   ctx->Driver.DrawPixels = _swrast_DrawPixels;
2087   ctx->Driver.ReadPixels = _swrast_ReadPixels;
2088   ctx->Driver.DrawBuffer = _swrast_DrawBuffer;
2089
2090   ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
2091   ctx->Driver.TexImage1D = _mesa_store_teximage1d;
2092   ctx->Driver.TexImage2D = _mesa_store_teximage2d;
2093   ctx->Driver.TexImage3D = _mesa_store_teximage3d;
2094   ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
2095   ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
2096   ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
2097   ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
2098
2099   ctx->Driver.CompressedTexImage1D = _mesa_store_compressed_teximage1d;
2100   ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d;
2101   ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d;
2102   ctx->Driver.CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d;
2103   ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d;
2104   ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d;
2105
2106   ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
2107   ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
2108   ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
2109   ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
2110   ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
2111   ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
2112   ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
2113   ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
2114   ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
2115
2116   swdd->SetBuffer = set_buffer;
2117
2118   /* RGB(A) span/pixel functions */
2119   if (osmesa->format == OSMESA_RGB) {
2120      swdd->WriteRGBASpan = write_rgba_span_RGB;
2121      swdd->WriteRGBSpan = write_rgb_span_RGB;
2122      swdd->WriteMonoRGBASpan = write_monocolor_span_RGB;
2123      swdd->WriteRGBAPixels = write_rgba_pixels_RGB;
2124      swdd->WriteMonoRGBAPixels = write_monocolor_pixels_RGB;
2125      swdd->ReadRGBASpan = read_rgba_span3;
2126      swdd->ReadRGBAPixels = read_rgba_pixels3;
2127   }
2128   else if (osmesa->format == OSMESA_BGR) {
2129      swdd->WriteRGBASpan = write_rgba_span_BGR;
2130      swdd->WriteRGBSpan = write_rgb_span_BGR;
2131      swdd->WriteMonoRGBASpan = write_monocolor_span_BGR;
2132      swdd->WriteRGBAPixels = write_rgba_pixels_BGR;
2133      swdd->WriteMonoRGBAPixels = write_monocolor_pixels_BGR;
2134      swdd->ReadRGBASpan = read_rgba_span3;
2135      swdd->ReadRGBAPixels = read_rgba_pixels3;
2136   }
2137   else if (osmesa->format == OSMESA_RGB_565) {
2138      swdd->WriteRGBASpan = write_rgba_span2;
2139      swdd->WriteRGBSpan = write_rgb_span2;
2140      swdd->WriteMonoRGBASpan = write_monocolor_span2;
2141      swdd->WriteRGBAPixels = write_rgba_pixels2;
2142      swdd->WriteMonoRGBAPixels = write_monocolor_pixels2;
2143      swdd->ReadRGBASpan = read_rgba_span2;
2144      swdd->ReadRGBAPixels = read_rgba_pixels2;
2145   }
2146   else {
2147      /* 4 GLchan / pixel in frame buffer */
2148      swdd->WriteRGBSpan = write_rgb_span;
2149      swdd->WriteRGBAPixels = write_rgba_pixels;
2150      swdd->WriteMonoRGBASpan = write_monocolor_span;
2151      swdd->WriteMonoRGBAPixels = write_monocolor_pixels;
2152      if (osmesa->format == OSMESA_RGBA &&
2153          CHAN_TYPE == GL_UNSIGNED_BYTE &&
2154          RCOMP==0 && GCOMP==1 && BCOMP==2 && ACOMP==3) {
2155         /* special, fast case */
2156         swdd->WriteRGBASpan = write_rgba_span_rgba;
2157         swdd->ReadRGBASpan = read_rgba_span_rgba;
2158      }
2159      else {
2160         swdd->WriteRGBASpan = write_rgba_span;
2161         swdd->ReadRGBASpan = read_rgba_span;
2162      }
2163      swdd->ReadRGBAPixels = read_rgba_pixels;
2164   }
2165
2166   /* CI span/pixel functions */
2167   swdd->WriteCI32Span = write_index32_span;
2168   swdd->WriteCI8Span = write_index8_span;
2169   swdd->WriteMonoCISpan = write_monoindex_span;
2170   swdd->WriteCI32Pixels = write_index_pixels;
2171   swdd->WriteMonoCIPixels = write_monoindex_pixels;
2172   swdd->ReadCI32Span = read_index_span;
2173   swdd->ReadCI32Pixels = read_index_pixels;
2174
2175   tnl->Driver.RunPipeline = _tnl_run_pipeline;
2176
2177   _swrast_InvalidateState( ctx, new_state );
2178   _swsetup_InvalidateState( ctx, new_state );
2179   _ac_InvalidateState( ctx, new_state );
2180   _tnl_InvalidateState( ctx, new_state );
2181}
2182