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