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