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