osmesa.c revision b2e460018375f699198073a6167e0ee96ba1d267
1/* $Id: osmesa.c,v 1.13 2000/03/31 01:07:13 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  3.3
6 *
7 * Copyright (C) 1999-2000  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 gl_make_current() and gl_get_current_context()
34 * functions.  Those functions are thread-safe.
35 */
36
37
38#ifdef PC_HEADER
39#include "all.h"
40#else
41#include <stdlib.h>
42#include <string.h>
43#include "GL/osmesa.h"
44#include "context.h"
45#include "depth.h"
46#include "mem.h"
47#include "matrix.h"
48#include "types.h"
49#include "vb.h"
50#include "extensions.h"
51#endif
52
53
54/*
55 * This is the OS/Mesa context struct.
56 * Notice how it includes a GLcontext.  By doing this we're mimicking
57 * C++ inheritance/derivation.
58 * Later, we can cast a GLcontext pointer into an OSMesaContext pointer
59 * or vice versa.
60 */
61struct osmesa_context {
62   GLcontext gl_ctx;		/* The core GL/Mesa context */
63   GLvisual *gl_visual;		/* Describes the buffers */
64   GLframebuffer *gl_buffer;	/* Depth, stencil, accum, etc buffers */
65   GLenum format;		/* either GL_RGBA or GL_COLOR_INDEX */
66   void *buffer;		/* the image buffer */
67   GLint width, height;		/* size of image buffer */
68   GLuint pixel;		/* current color index or RGBA pixel value */
69   GLuint clearpixel;		/* pixel for clearing the color buffer */
70   GLint rowlength;		/* number of pixels per row */
71   GLint userRowLength;		/* user-specified number of pixels per row */
72   GLint rshift, gshift;	/* bit shifts for RGBA formats */
73   GLint bshift, ashift;
74   GLint rind, gind, bind;	/* index offsets for RGBA formats */
75   void *rowaddr[MAX_HEIGHT];	/* address of first pixel in each image row */
76   GLboolean yup;		/* TRUE  -> Y increases upward */
77				/* FALSE -> Y increases downward */
78};
79
80
81
82/* A forward declaration: */
83static void osmesa_update_state( GLcontext *ctx );
84
85
86
87/**********************************************************************/
88/*****                    Public Functions                        *****/
89/**********************************************************************/
90
91
92/*
93 * Create an Off-Screen Mesa rendering context.  The only attribute needed is
94 * an RGBA vs Color-Index mode flag.
95 *
96 * Input:  format - either GL_RGBA or GL_COLOR_INDEX
97 *         sharelist - specifies another OSMesaContext with which to share
98 *                     display lists.  NULL indicates no sharing.
99 * Return:  an OSMesaContext or 0 if error
100 */
101OSMesaContext GLAPIENTRY
102OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
103{
104   OSMesaContext osmesa;
105   GLint rshift, gshift, bshift, ashift;
106   GLint rind, gind, bind;
107   GLint indexBits, alphaBits;
108   GLboolean rgbmode;
109   GLboolean swalpha;
110   GLuint i4 = 1;
111   GLubyte *i1 = (GLubyte *) &i4;
112   GLint little_endian = *i1;
113
114   swalpha = GL_FALSE;
115   rind = gind = bind = 0;
116   if (format==OSMESA_COLOR_INDEX) {
117      indexBits = 8;
118      rshift = gshift = bshift = ashift = 0;
119      rgbmode = GL_FALSE;
120   }
121   else if (format==OSMESA_RGBA) {
122      indexBits = 0;
123      alphaBits = 8;
124      if (little_endian) {
125         rshift = 0;
126         gshift = 8;
127         bshift = 16;
128         ashift = 24;
129      }
130      else {
131         rshift = 24;
132         gshift = 16;
133         bshift = 8;
134         ashift = 0;
135      }
136      rgbmode = GL_TRUE;
137   }
138   else if (format==OSMESA_BGRA) {
139      indexBits = 0;
140      alphaBits = 8;
141      if (little_endian) {
142         ashift = 0;
143         rshift = 8;
144         gshift = 16;
145         bshift = 24;
146      }
147      else {
148         bshift = 24;
149         gshift = 16;
150         rshift = 8;
151         ashift = 0;
152      }
153      rgbmode = GL_TRUE;
154   }
155   else if (format==OSMESA_ARGB) {
156      indexBits = 0;
157      alphaBits = 8;
158      if (little_endian) {
159         bshift = 0;
160         gshift = 8;
161         rshift = 16;
162         ashift = 24;
163      }
164      else {
165         ashift = 24;
166         rshift = 16;
167         gshift = 8;
168         bshift = 0;
169      }
170      rgbmode = GL_TRUE;
171   }
172   else if (format==OSMESA_RGB) {
173      indexBits = 0;
174      alphaBits = 0;
175      bshift = 0;
176      gshift = 8;
177      rshift = 16;
178      ashift = 24;
179      bind = 2;
180      gind = 1;
181      rind = 0;
182      rgbmode = GL_TRUE;
183      swalpha = GL_TRUE;
184   }
185   else if (format==OSMESA_BGR) {
186      indexBits = 0;
187      alphaBits = 0;
188      bshift = 0;
189      gshift = 8;
190      rshift = 16;
191      ashift = 24;
192      bind = 0;
193      gind = 1;
194      rind = 2;
195      rgbmode = GL_TRUE;
196      swalpha = GL_TRUE;
197   }
198   else {
199      return NULL;
200   }
201
202
203   osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
204   if (osmesa) {
205      osmesa->gl_visual = gl_create_visual( rgbmode,
206                                            swalpha,    /* software alpha */
207                                            GL_FALSE,	/* double buffer */
208                                            GL_FALSE,	/* stereo */
209                                            DEFAULT_SOFTWARE_DEPTH_BITS,
210                                            STENCIL_BITS,
211                                            rgbmode ? ACCUM_BITS : 0,
212                                            indexBits,
213                                            8, 8, 8, alphaBits );
214      if (!osmesa->gl_visual) {
215         return NULL;
216      }
217
218      if (!gl_initialize_context_data(&osmesa->gl_ctx,
219                                      osmesa->gl_visual,
220                                      sharelist ? &sharelist->gl_ctx
221                                                : (GLcontext *) NULL,
222                                      (void *) osmesa, GL_TRUE )) {
223         gl_destroy_visual( osmesa->gl_visual );
224         FREE(osmesa);
225         return NULL;
226      }
227      gl_extensions_enable(&(osmesa->gl_ctx),"GL_HP_occlusion_test");
228
229      osmesa->gl_buffer = gl_create_framebuffer( osmesa->gl_visual,
230                                           osmesa->gl_visual->DepthBits > 0,
231                                           osmesa->gl_visual->StencilBits > 0,
232                                           osmesa->gl_visual->AccumRedBits > 0,
233                                           osmesa->gl_visual->AlphaBits > 0 );
234
235      if (!osmesa->gl_buffer) {
236         gl_destroy_visual( osmesa->gl_visual );
237         gl_free_context_data( &osmesa->gl_ctx );
238         FREE(osmesa);
239         return NULL;
240      }
241      osmesa->format = format;
242      osmesa->buffer = NULL;
243      osmesa->width = 0;
244      osmesa->height = 0;
245      osmesa->pixel = 0;
246      osmesa->clearpixel = 0;
247      osmesa->userRowLength = 0;
248      osmesa->rowlength = 0;
249      osmesa->yup = GL_TRUE;
250      osmesa->rshift = rshift;
251      osmesa->gshift = gshift;
252      osmesa->bshift = bshift;
253      osmesa->ashift = ashift;
254      osmesa->rind = rind;
255      osmesa->gind = gind;
256      osmesa->bind = bind;
257   }
258   return osmesa;
259}
260
261
262
263/*
264 * Destroy an Off-Screen Mesa rendering context.
265 *
266 * Input:  ctx - the context to destroy
267 */
268void GLAPIENTRY OSMesaDestroyContext( OSMesaContext ctx )
269{
270   if (ctx) {
271      gl_destroy_visual( ctx->gl_visual );
272      gl_destroy_framebuffer( ctx->gl_buffer );
273      gl_free_context_data( &ctx->gl_ctx );
274      FREE( ctx );
275   }
276}
277
278
279
280/*
281 * Recompute the values of the context's rowaddr array.
282 */
283static void compute_row_addresses( OSMesaContext ctx )
284{
285   GLint i;
286
287   if (ctx->yup) {
288      /* Y=0 is bottom line of window */
289      if (ctx->format==OSMESA_COLOR_INDEX) {
290         /* 1-byte CI mode */
291         GLubyte *origin = (GLubyte *) ctx->buffer;
292         for (i=0;i<MAX_HEIGHT;i++) {
293            ctx->rowaddr[i] = origin + i * ctx->rowlength;
294         }
295      }
296      else {
297         if ((ctx->format==OSMESA_RGB) || (ctx->format==OSMESA_BGR)) {
298            /* 3-byte RGB mode */
299            GLubyte *origin = (GLubyte *) ctx->buffer;
300            for (i=0;i<MAX_HEIGHT;i++) {
301               ctx->rowaddr[i] = origin + (i * (ctx->rowlength*3));
302            }
303         } else {
304            /* 4-byte RGBA mode */
305            GLuint *origin = (GLuint *) ctx->buffer;
306            for (i=0;i<MAX_HEIGHT;i++) {
307               ctx->rowaddr[i] = origin + i * ctx->rowlength;
308            }
309         }
310      }
311   }
312   else {
313      /* Y=0 is top line of window */
314      if (ctx->format==OSMESA_COLOR_INDEX) {
315         /* 1-byte CI mode */
316         GLubyte *origin = (GLubyte *) ctx->buffer;
317         for (i=0;i<MAX_HEIGHT;i++) {
318            ctx->rowaddr[i] = origin + (ctx->height-i-1) * ctx->rowlength;
319         }
320      }
321      else {
322         if ((ctx->format==OSMESA_RGB) || (ctx->format==OSMESA_BGR)) {
323            /* 3-byte RGB mode */
324            GLubyte *origin = (GLubyte *) ctx->buffer;
325            for (i=0;i<MAX_HEIGHT;i++) {
326               ctx->rowaddr[i] = origin + ((ctx->height-i-1) * (ctx->rowlength*3));
327            }
328         } else {
329            /* 4-byte RGBA mode */
330            GLuint *origin = (GLuint *) ctx->buffer;
331            for (i=0;i<MAX_HEIGHT;i++) {
332               ctx->rowaddr[i] = origin + (ctx->height-i-1) * ctx->rowlength;
333            }
334         }
335      }
336   }
337}
338
339
340/*
341 * Bind an OSMesaContext to an image buffer.  The image buffer is just a
342 * block of memory which the client provides.  Its size must be at least
343 * as large as width*height*sizeof(type).  Its address should be a multiple
344 * of 4 if using RGBA mode.
345 *
346 * Image data is stored in the order of glDrawPixels:  row-major order
347 * with the lower-left image pixel stored in the first array position
348 * (ie. bottom-to-top).
349 *
350 * Since the only type initially supported is GL_UNSIGNED_BYTE, if the
351 * context is in RGBA mode, each pixel will be stored as a 4-byte RGBA
352 * value.  If the context is in color indexed mode, each pixel will be
353 * stored as a 1-byte value.
354 *
355 * If the context's viewport hasn't been initialized yet, it will now be
356 * initialized to (0,0,width,height).
357 *
358 * Input:  ctx - the rendering context
359 *         buffer - the image buffer memory
360 *         type - data type for pixel components, only GL_UNSIGNED_BYTE
361 *                supported now
362 *         width, height - size of image buffer in pixels, at least 1
363 * Return:  GL_TRUE if success, GL_FALSE if error because of invalid ctx,
364 *          invalid buffer address, type!=GL_UNSIGNED_BYTE, width<1, height<1,
365 *          width>internal limit or height>internal limit.
366 */
367GLboolean GLAPIENTRY
368OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type,
369                   GLsizei width, GLsizei height )
370{
371   if (!ctx || !buffer || type!=GL_UNSIGNED_BYTE
372       || width<1 || height<1 || width>MAX_WIDTH || height>MAX_HEIGHT) {
373      return GL_FALSE;
374   }
375
376   osmesa_update_state( &ctx->gl_ctx );
377   gl_make_current( &ctx->gl_ctx, ctx->gl_buffer );
378
379   ctx->buffer = buffer;
380   ctx->width = width;
381   ctx->height = height;
382   if (ctx->userRowLength)
383      ctx->rowlength = ctx->userRowLength;
384   else
385      ctx->rowlength = width;
386
387   compute_row_addresses( ctx );
388
389   /* init viewport */
390   if (ctx->gl_ctx.Viewport.Width==0) {
391      /* initialize viewport and scissor box to buffer size */
392      _mesa_Viewport( 0, 0, width, height );
393      ctx->gl_ctx.Scissor.Width = width;
394      ctx->gl_ctx.Scissor.Height = height;
395   }
396
397   return GL_TRUE;
398}
399
400
401
402OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void )
403{
404   GLcontext *ctx = gl_get_current_context();
405   if (ctx)
406      return (OSMesaContext) ctx;
407   else
408      return NULL;
409}
410
411
412
413void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value )
414{
415   OSMesaContext ctx = OSMesaGetCurrentContext();
416
417   switch (pname) {
418      case OSMESA_ROW_LENGTH:
419         if (value<0) {
420            gl_error( &ctx->gl_ctx, GL_INVALID_VALUE,
421                      "OSMesaPixelStore(value)" );
422            return;
423         }
424         ctx->userRowLength = value;
425         ctx->rowlength = value;
426         break;
427      case OSMESA_Y_UP:
428         ctx->yup = value ? GL_TRUE : GL_FALSE;
429         break;
430      default:
431         gl_error( &ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
432         return;
433   }
434
435   compute_row_addresses( ctx );
436}
437
438
439void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value )
440{
441   OSMesaContext ctx = OSMesaGetCurrentContext();
442
443   switch (pname) {
444      case OSMESA_WIDTH:
445         *value = ctx->width;
446         return;
447      case OSMESA_HEIGHT:
448         *value = ctx->height;
449         return;
450      case OSMESA_FORMAT:
451         *value = ctx->format;
452         return;
453      case OSMESA_TYPE:
454         *value = GL_UNSIGNED_BYTE;
455         return;
456      case OSMESA_ROW_LENGTH:
457         *value = ctx->rowlength;
458         return;
459      case OSMESA_Y_UP:
460         *value = ctx->yup;
461         return;
462      default:
463         gl_error(&ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
464         return;
465   }
466}
467
468/*
469 * Return the depth buffer associated with an OSMesa context.
470 * Input:  c - the OSMesa context
471 * Output:  width, height - size of buffer in pixels
472 *          bytesPerValue - bytes per depth value (2 or 4)
473 *          buffer - pointer to depth buffer values
474 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
475 */
476GLboolean GLAPIENTRY OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
477                                GLint *bytesPerValue, void **buffer )
478{
479   if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) {
480      *width = 0;
481      *height = 0;
482      *bytesPerValue = 0;
483      *buffer = 0;
484      return GL_FALSE;
485   }
486   else {
487      *width = c->gl_buffer->Width;
488      *height = c->gl_buffer->Height;
489      *bytesPerValue = sizeof(GLdepth);
490      *buffer = c->gl_buffer->DepthBuffer;
491      return GL_TRUE;
492   }
493}
494
495/*
496 * Return the color buffer associated with an OSMesa context.
497 * Input:  c - the OSMesa context
498 * Output:  width, height - size of buffer in pixels
499 *          format - the pixel format (OSMESA_FORMAT)
500 *          buffer - pointer to color buffer values
501 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
502 */
503GLboolean GLAPIENTRY OSMesaGetColorBuffer( OSMesaContext c, GLint *width,
504                        GLint *height, GLint *format, void **buffer )
505{
506   if (!c->buffer) {
507      *width = 0;
508      *height = 0;
509      *format = 0;
510      *buffer = 0;
511      return GL_FALSE;
512   } else {
513      *width = c->width;
514      *height = c->height;
515      *format = c->format;
516      *buffer = c->buffer;
517      return GL_TRUE;
518   }
519}
520
521/**********************************************************************/
522/*** Device Driver Functions                                        ***/
523/**********************************************************************/
524
525
526/*
527 * Useful macros:
528 */
529#define PACK_RGBA(R,G,B,A)  (  ((R) << osmesa->rshift) \
530                             | ((G) << osmesa->gshift) \
531                             | ((B) << osmesa->bshift) \
532                             | ((A) << osmesa->ashift) )
533
534#define PACK_RGBA2(R,G,B,A)  (  ((R) << rshift) \
535                              | ((G) << gshift) \
536                              | ((B) << bshift) \
537                              | ((A) << ashift) )
538
539#define UNPACK_RED(P)      (((P) >> osmesa->rshift) & 0xff)
540#define UNPACK_GREEN(P)    (((P) >> osmesa->gshift) & 0xff)
541#define UNPACK_BLUE(P)     (((P) >> osmesa->bshift) & 0xff)
542#define UNPACK_ALPHA(P)    (((P) >> osmesa->ashift) & 0xff)
543
544#define PIXELADDR1(X,Y)  ((GLubyte *) osmesa->rowaddr[Y] + (X))
545#define PIXELADDR3(X,Y)  ((GLubyte *) osmesa->rowaddr[Y] + ((X)*3))
546#define PIXELADDR4(X,Y)  ((GLuint *)  osmesa->rowaddr[Y] + (X))
547
548
549
550
551static GLboolean set_draw_buffer( GLcontext *ctx, GLenum mode )
552{
553   (void) ctx;
554   if (mode==GL_FRONT_LEFT) {
555      return GL_TRUE;
556   }
557   else {
558      return GL_FALSE;
559   }
560}
561
562
563static void set_read_buffer( GLcontext *ctx, GLframebuffer *buffer, GLenum mode )
564{
565   /* separate read buffer not supported */
566   ASSERT(buffer == ctx->DrawBuffer);
567   ASSERT(mode == GL_FRONT_LEFT);
568}
569
570
571static void clear_index( GLcontext *ctx, GLuint index )
572{
573   OSMesaContext osmesa = (OSMesaContext) ctx;
574   osmesa->clearpixel = index;
575}
576
577
578
579static void clear_color( GLcontext *ctx,
580                         GLubyte r, GLubyte g, GLubyte b, GLubyte a )
581{
582   OSMesaContext osmesa = (OSMesaContext) ctx;
583   osmesa->clearpixel = PACK_RGBA( r, g, b, a );
584}
585
586
587
588static GLbitfield clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
589                         GLint x, GLint y, GLint width, GLint height )
590{
591   OSMesaContext osmesa = (OSMesaContext) ctx;
592   const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
593
594   /* we can't handle color or index masking */
595   if (*colorMask != 0xffffffff || ctx->Color.IndexMask != 0xffffffff)
596      return mask;
597
598   /* sanity check - we only have a front-left buffer */
599   ASSERT((mask & (DD_FRONT_RIGHT_BIT | DD_BACK_LEFT_BIT | DD_BACK_RIGHT_BIT)) == 0);
600
601   if (mask & DD_FRONT_LEFT_BIT) {
602      if (osmesa->format==OSMESA_COLOR_INDEX) {
603         if (all) {
604            /* Clear whole CI buffer */
605            MEMSET(osmesa->buffer, osmesa->clearpixel,
606                   osmesa->rowlength * osmesa->height);
607         }
608         else {
609            /* Clear part of CI buffer */
610            GLint i, j;
611            for (i=0;i<height;i++) {
612               GLubyte *ptr1 = PIXELADDR1( x, (y+i) );
613               for (j=0;j<width;j++) {
614                  *ptr1++ = osmesa->clearpixel;
615               }
616            }
617         }
618      }
619      else if ((osmesa->format==OSMESA_RGB)||(osmesa->format==OSMESA_BGR)) {
620         GLubyte rval = UNPACK_RED(osmesa->clearpixel);
621         GLubyte gval = UNPACK_GREEN(osmesa->clearpixel);
622         GLubyte bval = UNPACK_BLUE(osmesa->clearpixel);
623         GLint   rind = osmesa->rind;
624         GLint   gind = osmesa->gind;
625         GLint   bind = osmesa->bind;
626         if (all) {
627            GLuint  i, n;
628            GLubyte *ptr3 = (GLubyte *) osmesa->buffer;
629            /* Clear whole RGB buffer */
630            n = osmesa->rowlength * osmesa->height;
631            for (i=0;i<n;i++) {
632               ptr3[rind] = rval;
633               ptr3[gind] = gval;
634               ptr3[bind] = bval;
635               ptr3 += 3;
636            }
637         }
638         else {
639            /* Clear part of RGB buffer */
640            GLint i, j;
641            for (i=0;i<height;i++) {
642               GLubyte *ptr3 = PIXELADDR3( x, (y+i) );
643               for (j=0;j<width;j++) {
644                  ptr3[rind] = rval;
645                  ptr3[gind] = gval;
646                  ptr3[bind] = bval;
647                  ptr3 += 3;
648               }
649            }
650         }
651      }
652      else {
653         if (all) {
654            /* Clear whole RGBA buffer */
655            GLuint i, n, *ptr4;
656            n = osmesa->rowlength * osmesa->height;
657            ptr4 = (GLuint *) osmesa->buffer;
658            for (i=0;i<n;i++) {
659               *ptr4++ = osmesa->clearpixel;
660            }
661         }
662         else {
663            /* Clear part of RGBA buffer */
664            GLint i, j;
665            for (i=0;i<height;i++) {
666               GLuint *ptr4 = PIXELADDR4( x, (y+i) );
667               for (j=0;j<width;j++) {
668                  *ptr4++ = osmesa->clearpixel;
669               }
670            }
671         }
672      }
673   }
674   /* have Mesa clear all other buffers */
675   return mask & (~DD_FRONT_LEFT_BIT);
676}
677
678
679
680static void set_index( GLcontext *ctx, GLuint index )
681{
682   OSMesaContext osmesa = (OSMesaContext) ctx;
683   osmesa->pixel = index;
684}
685
686
687
688static void set_color( GLcontext *ctx,
689                       GLubyte r, GLubyte g, GLubyte b, GLubyte a )
690{
691   OSMesaContext osmesa = (OSMesaContext) ctx;
692   osmesa->pixel = PACK_RGBA( r, g, b, a );
693}
694
695
696
697static void buffer_size( GLcontext *ctx, GLuint *width, GLuint *height )
698{
699   OSMesaContext osmesa = (OSMesaContext) ctx;
700   *width = osmesa->width;
701   *height = osmesa->height;
702}
703
704
705/**********************************************************************/
706/*****        Read/write spans/arrays of RGBA pixels              *****/
707/**********************************************************************/
708
709/* Write RGBA pixels to an RGBA (or permuted) buffer. */
710static void write_rgba_span( const GLcontext *ctx,
711                             GLuint n, GLint x, GLint y,
712                             CONST GLubyte rgba[][4], const GLubyte mask[] )
713{
714   OSMesaContext osmesa = (OSMesaContext) ctx;
715   GLuint *ptr4 = PIXELADDR4( x, y );
716   GLuint i;
717   GLint rshift = osmesa->rshift;
718   GLint gshift = osmesa->gshift;
719   GLint bshift = osmesa->bshift;
720   GLint ashift = osmesa->ashift;
721   if (mask) {
722      for (i=0;i<n;i++,ptr4++) {
723         if (mask[i]) {
724            *ptr4 = PACK_RGBA2( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
725         }
726      }
727   }
728   else {
729      for (i=0;i<n;i++,ptr4++) {
730         *ptr4 = PACK_RGBA2( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
731      }
732   }
733}
734
735
736/* Write RGBA pixels to an RGBA buffer.  This is the fastest span-writer. */
737static void write_rgba_span_rgba( const GLcontext *ctx,
738                                  GLuint n, GLint x, GLint y,
739                                  CONST GLubyte rgba[][4],
740                                  const GLubyte mask[] )
741{
742   OSMesaContext osmesa = (OSMesaContext) ctx;
743   GLuint *ptr4 = PIXELADDR4( x, y );
744   const GLuint *rgba4 = (const GLuint *) rgba;
745   GLuint i;
746   if (mask) {
747      for (i=0;i<n;i++) {
748         if (mask[i]) {
749            ptr4[i] = rgba4[i];
750         }
751      }
752   }
753   else {
754      MEMCPY( ptr4, rgba4, n * 4 );
755   }
756}
757
758
759/* Write RGB pixels to an RGBA (or permuted) buffer. */
760static void write_rgb_span( const GLcontext *ctx,
761                            GLuint n, GLint x, GLint y,
762                            CONST GLubyte rgb[][3], const GLubyte mask[] )
763{
764   OSMesaContext osmesa = (OSMesaContext) ctx;
765   GLuint *ptr4 = PIXELADDR4( x, y );
766   GLuint i;
767   GLint rshift = osmesa->rshift;
768   GLint gshift = osmesa->gshift;
769   GLint bshift = osmesa->bshift;
770   GLint ashift = osmesa->ashift;
771   if (mask) {
772      for (i=0;i<n;i++,ptr4++) {
773         if (mask[i]) {
774            *ptr4 = PACK_RGBA2( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255 );
775         }
776      }
777   }
778   else {
779      for (i=0;i<n;i++,ptr4++) {
780         *ptr4 = PACK_RGBA2( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255);
781      }
782   }
783}
784
785
786
787static void write_monocolor_span( const GLcontext *ctx,
788                                  GLuint n, GLint x, GLint y,
789				  const GLubyte mask[] )
790{
791   OSMesaContext osmesa = (OSMesaContext) ctx;
792   GLuint *ptr4 = PIXELADDR4(x,y);
793   GLuint i;
794   for (i=0;i<n;i++,ptr4++) {
795      if (mask[i]) {
796         *ptr4 = osmesa->pixel;
797      }
798   }
799}
800
801
802
803static void write_rgba_pixels( const GLcontext *ctx,
804                               GLuint n, const GLint x[], const GLint y[],
805                               CONST GLubyte rgba[][4], const GLubyte mask[] )
806{
807   OSMesaContext osmesa = (OSMesaContext) ctx;
808   GLuint i;
809   GLint rshift = osmesa->rshift;
810   GLint gshift = osmesa->gshift;
811   GLint bshift = osmesa->bshift;
812   GLint ashift = osmesa->ashift;
813   for (i=0;i<n;i++) {
814      if (mask[i]) {
815         GLuint *ptr4 = PIXELADDR4(x[i],y[i]);
816         *ptr4 = PACK_RGBA2( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] );
817      }
818   }
819}
820
821
822
823static void write_monocolor_pixels( const GLcontext *ctx,
824                                    GLuint n, const GLint x[], const GLint y[],
825				    const GLubyte mask[] )
826{
827   OSMesaContext osmesa = (OSMesaContext) ctx;
828   GLuint i;
829   for (i=0;i<n;i++) {
830      if (mask[i]) {
831         GLuint *ptr4 = PIXELADDR4(x[i],y[i]);
832         *ptr4 = osmesa->pixel;
833      }
834   }
835}
836
837
838static void read_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y,
839                             GLubyte rgba[][4] )
840{
841   OSMesaContext osmesa = (OSMesaContext) ctx;
842   GLuint i;
843   GLuint *ptr4 = PIXELADDR4(x,y);
844   for (i=0;i<n;i++) {
845      GLuint pixel = *ptr4++;
846      rgba[i][RCOMP] = UNPACK_RED(pixel);
847      rgba[i][GCOMP] = UNPACK_GREEN(pixel);
848      rgba[i][BCOMP] = UNPACK_BLUE(pixel);
849      rgba[i][ACOMP] = UNPACK_ALPHA(pixel);
850   }
851}
852
853
854/* Read RGBA pixels from an RGBA buffer */
855static void read_rgba_span_rgba( const GLcontext *ctx,
856                                 GLuint n, GLint x, GLint y,
857                                 GLubyte rgba[][4] )
858{
859   OSMesaContext osmesa = (OSMesaContext) ctx;
860   GLuint *ptr4 = PIXELADDR4(x,y);
861   MEMCPY( rgba, ptr4, n * 4 * sizeof(GLubyte) );
862}
863
864
865static void read_rgba_pixels( const GLcontext *ctx,
866                               GLuint n, const GLint x[], const GLint y[],
867			       GLubyte rgba[][4], const GLubyte mask[] )
868{
869   OSMesaContext osmesa = (OSMesaContext) ctx;
870   GLuint i;
871   for (i=0;i<n;i++) {
872      if (mask[i]) {
873         GLuint *ptr4 = PIXELADDR4(x[i],y[i]);
874         GLuint pixel = *ptr4;
875         rgba[i][RCOMP] = UNPACK_RED(pixel);
876         rgba[i][GCOMP] = UNPACK_GREEN(pixel);
877         rgba[i][BCOMP] = UNPACK_BLUE(pixel);
878         rgba[i][ACOMP] = UNPACK_ALPHA(pixel);
879      }
880   }
881}
882
883/**********************************************************************/
884/*****                3 byte RGB pixel support funcs              *****/
885/**********************************************************************/
886
887/* Write RGBA pixels to an RGB or BGR buffer. */
888static void write_rgba_span3( const GLcontext *ctx,
889                              GLuint n, GLint x, GLint y,
890                              CONST GLubyte rgba[][4], const GLubyte mask[] )
891{
892   OSMesaContext osmesa = (OSMesaContext) ctx;
893   GLubyte *ptr3 = PIXELADDR3( x, y);
894   GLuint i;
895   GLint rind = osmesa->rind;
896   GLint gind = osmesa->gind;
897   GLint bind = osmesa->bind;
898   if (mask) {
899      for (i=0;i<n;i++,ptr3+=3) {
900         if (mask[i]) {
901            ptr3[rind] = rgba[i][RCOMP];
902            ptr3[gind] = rgba[i][GCOMP];
903            ptr3[bind] = rgba[i][BCOMP];
904         }
905      }
906   }
907   else {
908      for (i=0;i<n;i++,ptr3+=3) {
909         ptr3[rind] = rgba[i][RCOMP];
910         ptr3[gind] = rgba[i][GCOMP];
911         ptr3[bind] = rgba[i][BCOMP];
912      }
913   }
914}
915
916/* Write RGB pixels to an RGB or BGR buffer. */
917static void write_rgb_span3( const GLcontext *ctx,
918                             GLuint n, GLint x, GLint y,
919                             CONST GLubyte rgb[][3], const GLubyte mask[] )
920{
921   OSMesaContext osmesa = (OSMesaContext) ctx;
922   GLubyte *ptr3 = PIXELADDR3( x, y);
923   GLuint i;
924   GLint rind = osmesa->rind;
925   GLint gind = osmesa->gind;
926   GLint bind = osmesa->bind;
927   if (mask) {
928      for (i=0;i<n;i++,ptr3+=3) {
929         if (mask[i]) {
930            ptr3[rind] = rgb[i][RCOMP];
931            ptr3[gind] = rgb[i][GCOMP];
932            ptr3[bind] = rgb[i][BCOMP];
933         }
934      }
935   }
936   else {
937      for (i=0;i<n;i++,ptr3+=3) {
938         ptr3[rind] = rgb[i][RCOMP];
939         ptr3[gind] = rgb[i][GCOMP];
940         ptr3[bind] = rgb[i][BCOMP];
941      }
942   }
943}
944
945
946static void write_monocolor_span3( const GLcontext *ctx,
947                                  GLuint n, GLint x, GLint y,
948				  const GLubyte mask[] )
949{
950   OSMesaContext osmesa = (OSMesaContext) ctx;
951
952   GLubyte rval = UNPACK_RED(osmesa->pixel);
953   GLubyte gval = UNPACK_GREEN(osmesa->pixel);
954   GLubyte bval = UNPACK_BLUE(osmesa->pixel);
955   GLint   rind = osmesa->rind;
956   GLint   gind = osmesa->gind;
957   GLint   bind = osmesa->bind;
958
959
960   GLubyte *ptr3 = PIXELADDR3( x, y);
961   GLuint i;
962   for (i=0;i<n;i++,ptr3+=3) {
963      if (mask[i]) {
964         ptr3[rind] = rval;
965         ptr3[gind] = gval;
966         ptr3[bind] = bval;
967      }
968   }
969}
970
971static void write_rgba_pixels3( const GLcontext *ctx,
972                                GLuint n, const GLint x[], const GLint y[],
973                                CONST GLubyte rgba[][4], const GLubyte mask[] )
974{
975   OSMesaContext osmesa = (OSMesaContext) ctx;
976   GLuint i;
977   GLint rind = osmesa->rind;
978   GLint gind = osmesa->gind;
979   GLint bind = osmesa->bind;
980   for (i=0;i<n;i++) {
981      if (mask[i]) {
982         GLubyte *ptr3 = PIXELADDR3(x[i],y[i]);
983         ptr3[rind] = rgba[i][RCOMP];
984         ptr3[gind] = rgba[i][GCOMP];
985         ptr3[bind] = rgba[i][BCOMP];
986      }
987   }
988}
989
990static void write_monocolor_pixels3( const GLcontext *ctx,
991                                    GLuint n, const GLint x[], const GLint y[],
992				    const GLubyte mask[] )
993{
994   OSMesaContext osmesa = (OSMesaContext) ctx;
995   GLuint i;
996   GLint rind = osmesa->rind;
997   GLint gind = osmesa->gind;
998   GLint bind = osmesa->bind;
999   GLubyte rval = UNPACK_RED(osmesa->pixel);
1000   GLubyte gval = UNPACK_GREEN(osmesa->pixel);
1001   GLubyte bval = UNPACK_BLUE(osmesa->pixel);
1002   for (i=0;i<n;i++) {
1003      if (mask[i]) {
1004         GLubyte *ptr3 = PIXELADDR3(x[i],y[i]);
1005         ptr3[rind] = rval;
1006         ptr3[gind] = gval;
1007         ptr3[bind] = bval;
1008      }
1009   }
1010}
1011
1012static void read_rgba_span3( const GLcontext *ctx,
1013                             GLuint n, GLint x, GLint y,
1014                             GLubyte rgba[][4] )
1015{
1016   OSMesaContext osmesa = (OSMesaContext) ctx;
1017   GLuint i;
1018   GLint rind = osmesa->rind;
1019   GLint gind = osmesa->gind;
1020   GLint bind = osmesa->bind;
1021   GLubyte *ptr3 = PIXELADDR3( x, y);
1022   for (i=0;i<n;i++,ptr3+=3) {
1023      rgba[i][RCOMP] = ptr3[rind];
1024      rgba[i][GCOMP] = ptr3[gind];
1025      rgba[i][BCOMP] = ptr3[bind];
1026      rgba[i][ACOMP] = 0;
1027   }
1028}
1029
1030static void read_rgba_pixels3( const GLcontext *ctx,
1031                               GLuint n, const GLint x[], const GLint y[],
1032			       GLubyte rgba[][4], const GLubyte mask[] )
1033{
1034   OSMesaContext osmesa = (OSMesaContext) ctx;
1035   GLuint i;
1036   GLint rind = osmesa->rind;
1037   GLint gind = osmesa->gind;
1038   GLint bind = osmesa->bind;
1039   for (i=0;i<n;i++) {
1040      if (mask[i]) {
1041         GLubyte *ptr3 = PIXELADDR3(x[i],y[i]);
1042         rgba[i][RCOMP] = ptr3[rind];
1043         rgba[i][GCOMP] = ptr3[gind];
1044         rgba[i][BCOMP] = ptr3[bind];
1045         rgba[i][ACOMP] = 0;
1046      }
1047   }
1048}
1049
1050
1051/**********************************************************************/
1052/*****        Read/write spans/arrays of CI pixels                *****/
1053/**********************************************************************/
1054
1055/* Write 32-bit color index to buffer */
1056static void write_index32_span( const GLcontext *ctx,
1057                                GLuint n, GLint x, GLint y,
1058                                const GLuint index[], const GLubyte mask[] )
1059{
1060   OSMesaContext osmesa = (OSMesaContext) ctx;
1061   GLubyte *ptr1 = PIXELADDR1(x,y);
1062   GLuint i;
1063   if (mask) {
1064      for (i=0;i<n;i++,ptr1++) {
1065         if (mask[i]) {
1066            *ptr1 = (GLubyte) index[i];
1067         }
1068      }
1069   }
1070   else {
1071      for (i=0;i<n;i++,ptr1++) {
1072         *ptr1 = (GLubyte) index[i];
1073      }
1074   }
1075}
1076
1077
1078/* Write 8-bit color index to buffer */
1079static void write_index8_span( const GLcontext *ctx,
1080                               GLuint n, GLint x, GLint y,
1081                               const GLubyte index[], const GLubyte mask[] )
1082{
1083   OSMesaContext osmesa = (OSMesaContext) ctx;
1084   GLubyte *ptr1 = PIXELADDR1(x,y);
1085   GLuint i;
1086   if (mask) {
1087      for (i=0;i<n;i++,ptr1++) {
1088         if (mask[i]) {
1089            *ptr1 = (GLubyte) index[i];
1090         }
1091      }
1092   }
1093   else {
1094      MEMCPY( ptr1, index, n );
1095   }
1096}
1097
1098
1099static void write_monoindex_span( const GLcontext *ctx,
1100                                  GLuint n, GLint x, GLint y,
1101				  const GLubyte mask[] )
1102{
1103   OSMesaContext osmesa = (OSMesaContext) ctx;
1104   GLubyte *ptr1 = PIXELADDR1(x,y);
1105   GLuint i;
1106   for (i=0;i<n;i++,ptr1++) {
1107      if (mask[i]) {
1108         *ptr1 = (GLubyte) osmesa->pixel;
1109      }
1110   }
1111}
1112
1113
1114static void write_index_pixels( const GLcontext *ctx,
1115                                GLuint n, const GLint x[], const GLint y[],
1116			        const GLuint index[], const GLubyte mask[] )
1117{
1118   OSMesaContext osmesa = (OSMesaContext) ctx;
1119   GLuint i;
1120   for (i=0;i<n;i++) {
1121      if (mask[i]) {
1122         GLubyte *ptr1 = PIXELADDR1(x[i],y[i]);
1123         *ptr1 = (GLubyte) index[i];
1124      }
1125   }
1126}
1127
1128
1129static void write_monoindex_pixels( const GLcontext *ctx,
1130                                    GLuint n, const GLint x[], const GLint y[],
1131				    const GLubyte mask[] )
1132{
1133   OSMesaContext osmesa = (OSMesaContext) ctx;
1134   GLuint i;
1135   for (i=0;i<n;i++) {
1136      if (mask[i]) {
1137         GLubyte *ptr1 = PIXELADDR1(x[i],y[i]);
1138         *ptr1 = (GLubyte) osmesa->pixel;
1139      }
1140   }
1141}
1142
1143
1144static void read_index_span( const GLcontext *ctx,
1145                             GLuint n, GLint x, GLint y, GLuint index[] )
1146{
1147   OSMesaContext osmesa = (OSMesaContext) ctx;
1148   GLuint i;
1149   GLubyte *ptr1 = PIXELADDR1(x,y);
1150   for (i=0;i<n;i++,ptr1++) {
1151      index[i] = (GLuint) *ptr1;
1152   }
1153}
1154
1155
1156static void read_index_pixels( const GLcontext *ctx,
1157                               GLuint n, const GLint x[], const GLint y[],
1158			       GLuint index[], const GLubyte mask[] )
1159{
1160   OSMesaContext osmesa = (OSMesaContext) ctx;
1161   GLuint i;
1162   for (i=0;i<n;i++) {
1163      if (mask[i] ) {
1164         GLubyte *ptr1 = PIXELADDR1(x[i],y[i]);
1165         index[i] = (GLuint) *ptr1;
1166      }
1167   }
1168}
1169
1170
1171
1172/**********************************************************************/
1173/*****                   Optimized line rendering                 *****/
1174/**********************************************************************/
1175
1176
1177/*
1178 * Draw a flat-shaded, RGB line into an osmesa buffer.
1179 */
1180static void flat_rgba_line( GLcontext *ctx,
1181                            GLuint vert0, GLuint vert1, GLuint pvert )
1182{
1183   OSMesaContext osmesa = (OSMesaContext) ctx;
1184   GLubyte *color = ctx->VB->ColorPtr->data[pvert];
1185   unsigned long pixel = PACK_RGBA( color[0], color[1], color[2], color[3] );
1186
1187#define INTERP_XY 1
1188#define CLIP_HACK 1
1189#define PLOT(X,Y) { GLuint *ptr4 = PIXELADDR4(X,Y); *ptr4 = pixel; }
1190
1191#ifdef WIN32
1192#include "..\linetemp.h"
1193#else
1194#include "linetemp.h"
1195#endif
1196}
1197
1198
1199/*
1200 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
1201 */
1202static void flat_rgba_z_line( GLcontext *ctx,
1203                              GLuint vert0, GLuint vert1, GLuint pvert )
1204{
1205   OSMesaContext osmesa = (OSMesaContext) ctx;
1206   GLubyte *color = ctx->VB->ColorPtr->data[pvert];
1207   unsigned long pixel = PACK_RGBA( color[0], color[1], color[2], color[3] );
1208
1209#define INTERP_XY 1
1210#define INTERP_Z 1
1211#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1212#define CLIP_HACK 1
1213#define PLOT(X,Y)				\
1214	if (Z < *zPtr) {			\
1215	   GLuint *ptr4 = PIXELADDR4(X,Y);	\
1216	   *ptr4 = pixel;			\
1217	   *zPtr = Z;				\
1218	}
1219
1220#ifdef WIN32
1221#include "..\linetemp.h"
1222#else
1223#include "linetemp.h"
1224#endif
1225}
1226
1227
1228/*
1229 * Draw a flat-shaded, alpha-blended, RGB line into an osmesa buffer.
1230 */
1231static void flat_blend_rgba_line( GLcontext *ctx,
1232                                  GLuint vert0, GLuint vert1, GLuint pvert )
1233{
1234   OSMesaContext osmesa = (OSMesaContext) ctx;
1235   struct vertex_buffer *VB = ctx->VB;
1236   GLint rshift = osmesa->rshift;
1237   GLint gshift = osmesa->gshift;
1238   GLint bshift = osmesa->bshift;
1239   GLint avalue = VB->ColorPtr->data[pvert][3];
1240   GLint msavalue = 255 - avalue;
1241   GLint rvalue = VB->ColorPtr->data[pvert][0]*avalue;
1242   GLint gvalue = VB->ColorPtr->data[pvert][1]*avalue;
1243   GLint bvalue = VB->ColorPtr->data[pvert][2]*avalue;
1244
1245#define INTERP_XY 1
1246#define CLIP_HACK 1
1247#define PLOT(X,Y)					\
1248   { GLuint *ptr4 = PIXELADDR4(X,Y); \
1249     GLuint  pixel = 0; \
1250     pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);\
1251     pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);\
1252     pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);\
1253     *ptr4 = pixel; \
1254   }
1255
1256#ifdef WIN32
1257#include "..\linetemp.h"
1258#else
1259#include "linetemp.h"
1260#endif
1261}
1262
1263
1264/*
1265 * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer.
1266 */
1267static void flat_blend_rgba_z_line( GLcontext *ctx,
1268                                   GLuint vert0, GLuint vert1, GLuint pvert )
1269{
1270   OSMesaContext osmesa = (OSMesaContext) ctx;
1271   struct vertex_buffer *VB = ctx->VB;
1272   GLint rshift = osmesa->rshift;
1273   GLint gshift = osmesa->gshift;
1274   GLint bshift = osmesa->bshift;
1275   GLint avalue = VB->ColorPtr->data[pvert][3];
1276   GLint msavalue = 256 - avalue;
1277   GLint rvalue = VB->ColorPtr->data[pvert][0]*avalue;
1278   GLint gvalue = VB->ColorPtr->data[pvert][1]*avalue;
1279   GLint bvalue = VB->ColorPtr->data[pvert][2]*avalue;
1280
1281#define INTERP_XY 1
1282#define INTERP_Z 1
1283#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1284#define CLIP_HACK 1
1285#define PLOT(X,Y)									\
1286	if (Z < *zPtr) {								\
1287	   GLuint *ptr4 = PIXELADDR4(X,Y);						\
1288	   GLuint  pixel = 0;								\
1289	   pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);	\
1290	   pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);	\
1291	   pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);	\
1292	   *ptr4 = pixel; 								\
1293	}
1294
1295#ifdef WIN32
1296#include "..\linetemp.h"
1297#else
1298#include "linetemp.h"
1299#endif
1300}
1301
1302
1303/*
1304 * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer.
1305 */
1306static void flat_blend_rgba_z_line_write( GLcontext *ctx,
1307                                   GLuint vert0, GLuint vert1, GLuint pvert )
1308{
1309   OSMesaContext osmesa = (OSMesaContext) ctx;
1310   struct vertex_buffer *VB = ctx->VB;
1311   GLint rshift = osmesa->rshift;
1312   GLint gshift = osmesa->gshift;
1313   GLint bshift = osmesa->bshift;
1314   GLint avalue = VB->ColorPtr->data[pvert][3];
1315   GLint msavalue = 256 - avalue;
1316   GLint rvalue = VB->ColorPtr->data[pvert][0]*avalue;
1317   GLint gvalue = VB->ColorPtr->data[pvert][1]*avalue;
1318   GLint bvalue = VB->ColorPtr->data[pvert][2]*avalue;
1319
1320#define INTERP_XY 1
1321#define INTERP_Z 1
1322#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1323#define CLIP_HACK 1
1324#define PLOT(X,Y)									\
1325	if (Z < *zPtr) {								\
1326	   GLuint *ptr4 = PIXELADDR4(X,Y);						\
1327	   GLuint  pixel = 0;								\
1328	   pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);	\
1329	   pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);	\
1330	   pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);	\
1331	   *ptr4 = pixel;								\
1332	   *zPtr = Z;									\
1333	}
1334
1335#ifdef WIN32
1336#include "..\linetemp.h"
1337#else
1338#include "linetemp.h"
1339#endif
1340}
1341
1342
1343/*
1344 * Analyze context state to see if we can provide a fast line drawing
1345 * function, like those in lines.c.  Otherwise, return NULL.
1346 */
1347static line_func choose_line_function( GLcontext *ctx )
1348{
1349   OSMesaContext osmesa = (OSMesaContext) ctx;
1350
1351   if (ctx->Line.SmoothFlag)              return NULL;
1352   if (ctx->Texture.Enabled)              return NULL;
1353   if (ctx->Light.ShadeModel!=GL_FLAT)    return NULL;
1354
1355   if (ctx->Line.Width==1.0F
1356       && ctx->Line.StippleFlag==GL_FALSE) {
1357
1358       if (ctx->RasterMask==DEPTH_BIT
1359           && ctx->Depth.Func==GL_LESS
1360           && ctx->Depth.Mask==GL_TRUE
1361           && ctx->Visual->DepthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
1362           switch(osmesa->format) {
1363       		case OSMESA_RGBA:
1364       		case OSMESA_BGRA:
1365       		case OSMESA_ARGB:
1366       			return flat_rgba_z_line;
1367       		default:
1368       			return NULL;
1369           }
1370       }
1371
1372       if (ctx->RasterMask==0) {
1373           switch(osmesa->format) {
1374       		case OSMESA_RGBA:
1375       		case OSMESA_BGRA:
1376       		case OSMESA_ARGB:
1377       			return flat_rgba_line;
1378       		default:
1379       			return NULL;
1380           }
1381       }
1382
1383       if (ctx->RasterMask==(DEPTH_BIT|BLEND_BIT)
1384           && ctx->Depth.Func==GL_LESS
1385           && ctx->Depth.Mask==GL_TRUE
1386           && ctx->Visual->DepthBits == DEFAULT_SOFTWARE_DEPTH_BITS
1387           && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
1388           && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
1389           && ctx->Color.BlendSrcA==GL_SRC_ALPHA
1390           && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
1391           && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
1392           switch(osmesa->format) {
1393       		case OSMESA_RGBA:
1394       		case OSMESA_BGRA:
1395       		case OSMESA_ARGB:
1396       			return flat_blend_rgba_z_line_write;
1397       		default:
1398       			return NULL;
1399           }
1400       }
1401
1402       if (ctx->RasterMask==(DEPTH_BIT|BLEND_BIT)
1403           && ctx->Depth.Func==GL_LESS
1404           && ctx->Depth.Mask==GL_FALSE
1405           && ctx->Visual->DepthBits == DEFAULT_SOFTWARE_DEPTH_BITS
1406           && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
1407           && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
1408           && ctx->Color.BlendSrcA==GL_SRC_ALPHA
1409           && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
1410           && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
1411           switch(osmesa->format) {
1412       		case OSMESA_RGBA:
1413       		case OSMESA_BGRA:
1414       		case OSMESA_ARGB:
1415       			return flat_blend_rgba_z_line;
1416       		default:
1417       			return NULL;
1418           }
1419       }
1420
1421       if (ctx->RasterMask==BLEND_BIT
1422           && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
1423           && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
1424           && ctx->Color.BlendSrcA==GL_SRC_ALPHA
1425           && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
1426           && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
1427           switch(osmesa->format) {
1428       		case OSMESA_RGBA:
1429       		case OSMESA_BGRA:
1430       		case OSMESA_ARGB:
1431       			return flat_blend_rgba_line;
1432       		default:
1433       			return NULL;
1434           }
1435       }
1436
1437   }
1438   return NULL;
1439}
1440
1441
1442/**********************************************************************/
1443/*****                 Optimized triangle rendering               *****/
1444/**********************************************************************/
1445
1446
1447/*
1448 * Smooth-shaded, z-less triangle, RGBA color.
1449 */
1450static void smooth_rgba_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
1451                                    GLuint v2, GLuint pv )
1452{
1453   OSMesaContext osmesa = (OSMesaContext) ctx;
1454   GLint rshift = osmesa->rshift;
1455   GLint gshift = osmesa->gshift;
1456   GLint bshift = osmesa->bshift;
1457   GLint ashift = osmesa->ashift;
1458   (void) pv;
1459
1460#define INTERP_Z 1
1461#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1462#define INTERP_RGB 1
1463#define INTERP_ALPHA 1
1464#define INNER_LOOP( LEFT, RIGHT, Y )				\
1465{								\
1466   GLint i, len = RIGHT-LEFT;					\
1467   GLuint *img = PIXELADDR4(LEFT,Y);   				\
1468   for (i=0;i<len;i++,img++) {					\
1469      GLdepth z = FixedToDepth(ffz);				\
1470      if (z < zRow[i]) {					\
1471         *img = PACK_RGBA2( FixedToInt(ffr), FixedToInt(ffg),	\
1472		            FixedToInt(ffb), FixedToInt(ffa) );	\
1473         zRow[i] = z;						\
1474      }								\
1475      ffr += fdrdx;  ffg += fdgdx;  ffb += fdbdx;  ffa += fdadx;\
1476      ffz += fdzdx;						\
1477   }								\
1478}
1479#ifdef WIN32
1480#include "..\tritemp.h"
1481#else
1482#include "tritemp.h"
1483#endif
1484}
1485
1486
1487
1488
1489/*
1490 * Flat-shaded, z-less triangle, RGBA color.
1491 */
1492static void flat_rgba_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
1493                                   GLuint v2, GLuint pv )
1494{
1495   OSMesaContext osmesa = (OSMesaContext) ctx;
1496#define INTERP_Z 1
1497#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1498#define SETUP_CODE			\
1499   GLubyte r = VB->ColorPtr->data[pv][0];	\
1500   GLubyte g = VB->ColorPtr->data[pv][1];	\
1501   GLubyte b = VB->ColorPtr->data[pv][2];	\
1502   GLubyte a = VB->ColorPtr->data[pv][3];	\
1503   GLuint pixel = PACK_RGBA(r,g,b,a);
1504
1505#define INNER_LOOP( LEFT, RIGHT, Y )	\
1506{					\
1507   GLint i, len = RIGHT-LEFT;		\
1508   GLuint *img = PIXELADDR4(LEFT,Y);   	\
1509   for (i=0;i<len;i++,img++) {		\
1510      GLdepth z = FixedToDepth(ffz);	\
1511      if (z < zRow[i]) {		\
1512         *img = pixel;			\
1513         zRow[i] = z;			\
1514      }					\
1515      ffz += fdzdx;			\
1516   }					\
1517}
1518#ifdef WIN32
1519#include "..\tritemp.h"
1520#else
1521#include "tritemp.h"
1522#endif
1523}
1524
1525
1526
1527/*
1528 * Return pointer to an accelerated triangle function if possible.
1529 */
1530static triangle_func choose_triangle_function( GLcontext *ctx )
1531{
1532   OSMesaContext osmesa = (OSMesaContext) ctx;
1533
1534   if ((osmesa->format==OSMESA_RGB)||(osmesa->format==OSMESA_BGR)) return NULL;
1535
1536   if (ctx->Polygon.SmoothFlag)     return NULL;
1537   if (ctx->Polygon.StippleFlag)    return NULL;
1538   if (ctx->Texture.Enabled)        return NULL;
1539
1540   if (ctx->RasterMask==DEPTH_BIT
1541       && ctx->Depth.Func==GL_LESS
1542       && ctx->Depth.Mask==GL_TRUE
1543       && ctx->Visual->DepthBits == DEFAULT_SOFTWARE_DEPTH_BITS
1544       && osmesa->format!=OSMESA_COLOR_INDEX) {
1545      if (ctx->Light.ShadeModel==GL_SMOOTH) {
1546         return smooth_rgba_z_triangle;
1547      }
1548      else {
1549         return flat_rgba_z_triangle;
1550      }
1551   }
1552   return NULL;
1553}
1554
1555
1556
1557/**********************************************************************/
1558/*****                 Occlusion rendering routines               *****/
1559/**********************************************************************/
1560
1561#define OCC_STD_MASK_TEST \
1562   if (ctx->OcclusionResult) return; \
1563   if (mask) { \
1564      GLuint i; \
1565      for (i=0;i<n;i++) if (mask[i]) { \
1566           ((GLcontext *)ctx)->OcclusionResult = GL_TRUE; \
1567           return; \
1568	} \
1569   } else { \
1570      ((GLcontext *)ctx)->OcclusionResult = GL_TRUE; \
1571   } \
1572   return;
1573
1574/**
1575*** Color Index
1576**/
1577
1578static void write_index32_span_occ( const GLcontext *ctx,
1579                                    GLuint n, GLint x, GLint y,
1580                                    const GLuint index[], const GLubyte mask[] )
1581{
1582   OCC_STD_MASK_TEST
1583}
1584
1585
1586static void write_index8_span_occ( const GLcontext *ctx,
1587                                   GLuint n, GLint x, GLint y,
1588                                   const GLubyte index[], const GLubyte mask[] )
1589{
1590   OCC_STD_MASK_TEST
1591}
1592
1593
1594static void write_monoindex_span_occ( const GLcontext *ctx,
1595                                      GLuint n, GLint x, GLint y,
1596                                      const GLubyte mask[] )
1597{
1598   OCC_STD_MASK_TEST
1599}
1600
1601
1602static void write_index_pixels_occ( const GLcontext *ctx,
1603                                    GLuint n, const GLint x[], const GLint y[],
1604                                    const GLuint index[], const GLubyte mask[] )
1605{
1606   OCC_STD_MASK_TEST
1607}
1608
1609
1610static void write_monoindex_pixels_occ( const GLcontext *ctx,
1611                                        GLuint n, const GLint x[], const GLint y[],
1612                                        const GLubyte mask[] )
1613{
1614   OCC_STD_MASK_TEST
1615}
1616
1617/**
1618*** RGB/RGBA
1619**/
1620static void write_rgba_span_occ( const GLcontext *ctx,
1621                                 GLuint n, GLint x, GLint y,
1622                                 CONST GLubyte rgba[][4], const GLubyte mask[] )
1623{
1624   OCC_STD_MASK_TEST
1625}
1626
1627
1628static void write_rgb_span_occ( const GLcontext *ctx,
1629                                GLuint n, GLint x, GLint y,
1630                                CONST GLubyte rgb[][3],
1631                                const GLubyte mask[] )
1632{
1633   OCC_STD_MASK_TEST
1634}
1635
1636
1637static void write_rgba_pixels_occ( const GLcontext *ctx,
1638                                   GLuint n, const GLint x[], const GLint y[],
1639                                   CONST GLubyte rgba[][4], const GLubyte mask[] )
1640{
1641   OCC_STD_MASK_TEST
1642}
1643
1644
1645static void write_monocolor_span_occ( const GLcontext *ctx,
1646                                      GLuint n, GLint x, GLint y,
1647                                      const GLubyte mask[] )
1648{
1649   OCC_STD_MASK_TEST
1650}
1651
1652
1653static void write_monocolor_pixels_occ( const GLcontext *ctx,
1654                                        GLuint n, const GLint x[], const GLint y[],
1655                                        const GLubyte mask[] )
1656{
1657   OCC_STD_MASK_TEST
1658}
1659
1660
1661/**
1662*** Line Drawing
1663**/
1664static void line_occ( GLcontext *ctx,
1665                      GLuint vert0, GLuint vert1, GLuint pvert )
1666{
1667   ctx->OcclusionResult = GL_TRUE;
1668}
1669
1670
1671static void line_z_occ( GLcontext *ctx,
1672                        GLuint vert0, GLuint vert1, GLuint pvert )
1673{
1674   if (ctx->OcclusionResult) return;
1675
1676#define INTERP_XY 1
1677#define INTERP_Z 1
1678#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1679#define CLIP_HACK 1
1680#define PLOT(X,Y)                               \
1681        if (Z < *zPtr) {                        \
1682           ctx->OcclusionResult = GL_TRUE;          \
1683           return;                              \
1684        }
1685
1686#ifdef WIN32
1687#include "..\linetemp.h"
1688#else
1689#include "linetemp.h"
1690#endif
1691}
1692
1693
1694/**
1695*** Triangle Drawing
1696**/
1697static void triangle_occ( GLcontext *ctx, GLuint v0, GLuint v1,
1698                          GLuint v2, GLuint pv )
1699{
1700   ctx->OcclusionResult = GL_TRUE;
1701}
1702
1703
1704static void triangle_z_occ( GLcontext *ctx, GLuint v0, GLuint v1,
1705                            GLuint v2, GLuint pv )
1706{
1707   if (ctx->OcclusionResult) return;
1708
1709#define INTERP_Z 1
1710#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1711#define INNER_LOOP( LEFT, RIGHT, Y )    \
1712{                                       \
1713   GLint i, len = RIGHT-LEFT;           \
1714   for (i=0;i<len;i++) {                \
1715      GLdepth z = FixedToDepth(ffz);    \
1716      if (z < zRow[i]) {                \
1717         ctx->OcclusionResult = GL_TRUE;    \
1718         return;                        \
1719      }                                 \
1720      ffz += fdzdx;                     \
1721   }                                    \
1722}
1723#ifdef WIN32
1724#include "..\tritemp.h"
1725#else
1726#include "tritemp.h"
1727#endif
1728}
1729
1730
1731static const GLubyte *get_string( GLcontext *ctx, GLenum name )
1732{
1733   (void) ctx;
1734   switch (name) {
1735      case GL_RENDERER:
1736         return (const GLubyte *) "Mesa OffScreen";
1737      default:
1738         return NULL;
1739   }
1740}
1741
1742
1743static void osmesa_update_state( GLcontext *ctx )
1744{
1745   OSMesaContext osmesa = (OSMesaContext) ctx;
1746
1747   ASSERT((void *) osmesa == (void *) ctx->DriverCtx);
1748
1749   ctx->Driver.GetString = get_string;
1750   ctx->Driver.UpdateState = osmesa_update_state;
1751
1752   ctx->Driver.SetDrawBuffer = set_draw_buffer;
1753   ctx->Driver.SetReadBuffer = set_read_buffer;
1754   ctx->Driver.Color = set_color;
1755   ctx->Driver.Index = set_index;
1756   ctx->Driver.ClearIndex = clear_index;
1757   ctx->Driver.ClearColor = clear_color;
1758   ctx->Driver.Clear = clear;
1759
1760   ctx->Driver.GetBufferSize = buffer_size;
1761
1762   ctx->Driver.PointsFunc = NULL;
1763   ctx->Driver.LineFunc = choose_line_function( ctx );
1764   ctx->Driver.TriangleFunc = choose_triangle_function( ctx );
1765
1766
1767   /* RGB(A) span/pixel functions */
1768   if ((osmesa->format==OSMESA_RGB) || (osmesa->format==OSMESA_BGR)) {
1769      /* 3 bytes / pixel in frame buffer */
1770      ctx->Driver.WriteRGBASpan = write_rgba_span3;
1771      ctx->Driver.WriteRGBSpan = write_rgb_span3;
1772      ctx->Driver.WriteRGBAPixels = write_rgba_pixels3;
1773      ctx->Driver.WriteMonoRGBASpan = write_monocolor_span3;
1774      ctx->Driver.WriteMonoRGBAPixels = write_monocolor_pixels3;
1775      ctx->Driver.ReadRGBASpan = read_rgba_span3;
1776      ctx->Driver.ReadRGBAPixels = read_rgba_pixels3;
1777   }
1778   else {
1779      /* 4 bytes / pixel in frame buffer */
1780      if (osmesa->format==OSMESA_RGBA
1781          && RCOMP==0 && GCOMP==1 && BCOMP==2 && ACOMP==3)
1782         ctx->Driver.WriteRGBASpan = write_rgba_span_rgba;
1783      else
1784         ctx->Driver.WriteRGBASpan = write_rgba_span;
1785      ctx->Driver.WriteRGBSpan = write_rgb_span;
1786      ctx->Driver.WriteRGBAPixels = write_rgba_pixels;
1787      ctx->Driver.WriteMonoRGBASpan = write_monocolor_span;
1788      ctx->Driver.WriteMonoRGBAPixels = write_monocolor_pixels;
1789      if (osmesa->format==OSMESA_RGBA
1790          && RCOMP==0 && GCOMP==1 && BCOMP==2 && ACOMP==3)
1791         ctx->Driver.ReadRGBASpan = read_rgba_span_rgba;
1792      else
1793         ctx->Driver.ReadRGBASpan = read_rgba_span;
1794      ctx->Driver.ReadRGBAPixels = read_rgba_pixels;
1795   }
1796
1797   /* CI span/pixel functions */
1798   ctx->Driver.WriteCI32Span = write_index32_span;
1799   ctx->Driver.WriteCI8Span = write_index8_span;
1800   ctx->Driver.WriteMonoCISpan = write_monoindex_span;
1801   ctx->Driver.WriteCI32Pixels = write_index_pixels;
1802   ctx->Driver.WriteMonoCIPixels = write_monoindex_pixels;
1803   ctx->Driver.ReadCI32Span = read_index_span;
1804   ctx->Driver.ReadCI32Pixels = read_index_pixels;
1805
1806   /* Occlusion test cases:
1807    * If no buffers have been selected for writing,
1808    * we swap in occlusion routines that:
1809    *  (1) check the current flag and return if set
1810    *  (2) set the flag if any pixel would be updated
1811    * Note: all the other buffer writing routines will
1812    * always set the visible flag so in cases of "improper"
1813    * extension use will just cause unnecessary rasterization
1814    * to occur.  The image will be correct in any case.
1815    */
1816   if ((ctx->Depth.OcclusionTest) &&
1817       (((!ctx->Visual->RGBAflag) &&
1818       (ctx->Color.IndexMask == 0)) ||
1819       ((ctx->Visual->RGBAflag) &&
1820       (ctx->Color.ColorMask[0] == 0) &&
1821       (ctx->Color.ColorMask[1] == 0) &&
1822       (ctx->Color.ColorMask[2] == 0) &&
1823       (ctx->Color.ColorMask[3] == 0))) &&
1824       (ctx->Depth.Func == GL_LESS) &&
1825       (ctx->Stencil.Enabled == GL_FALSE)) {
1826
1827      ctx->Driver.WriteCI32Span = write_index32_span_occ;
1828      ctx->Driver.WriteCI8Span = write_index8_span_occ;
1829      ctx->Driver.WriteMonoCISpan = write_monoindex_span_occ;
1830      ctx->Driver.WriteCI32Pixels = write_index_pixels_occ;
1831      ctx->Driver.WriteMonoCIPixels = write_monoindex_pixels_occ;
1832
1833      ctx->Driver.WriteRGBASpan = write_rgba_span_occ;
1834      ctx->Driver.WriteRGBSpan = write_rgb_span_occ;
1835      ctx->Driver.WriteRGBAPixels = write_rgba_pixels_occ;
1836      ctx->Driver.WriteMonoRGBASpan = write_monocolor_span_occ;
1837      ctx->Driver.WriteMonoRGBAPixels = write_monocolor_pixels_occ;
1838
1839      if (ctx->RasterMask & DEPTH_BIT) {
1840         ctx->Driver.LineFunc = line_z_occ;
1841         ctx->Driver.TriangleFunc = triangle_z_occ;
1842      } else {
1843         ctx->Driver.LineFunc = line_occ;
1844         ctx->Driver.TriangleFunc = triangle_occ;
1845      }
1846   } else {
1847      ctx->OcclusionResult = GL_TRUE;
1848   }
1849}
1850