osmesa.c revision 9c799cdc49e9200f5a1c7c7d9787d5729b5b0082
1/* $Id: osmesa.c,v 1.97 2002/11/13 16:57:44 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  5.0
6 *
7 * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28/*
29 * Off-Screen Mesa rendering / Rendering into client memory space
30 *
31 * Note on thread safety:  this driver is thread safe.  All
32 * functions are reentrant.  The notion of current context is
33 * managed by the core _mesa_make_current() and _mesa_get_current_context()
34 * functions.  Those functions are thread-safe.
35 */
36
37
38#include "glheader.h"
39#include "GL/osmesa.h"
40#include "buffers.h"
41#include "context.h"
42#include "colormac.h"
43#include "depth.h"
44#include "extensions.h"
45#include "imports.h"
46#include "macros.h"
47#include "matrix.h"
48#include "mmath.h"
49#include "mtypes.h"
50#include "texformat.h"
51#include "texstore.h"
52#include "array_cache/acache.h"
53#include "swrast/swrast.h"
54#include "swrast_setup/swrast_setup.h"
55#include "swrast/s_context.h"
56#include "swrast/s_depth.h"
57#include "swrast/s_lines.h"
58#include "swrast/s_triangle.h"
59#include "tnl/tnl.h"
60#include "tnl/t_context.h"
61#include "tnl/t_pipeline.h"
62
63
64
65/*
66 * This is the OS/Mesa context struct.
67 * Notice how it includes a GLcontext.  By doing this we're mimicking
68 * C++ inheritance/derivation.
69 * Later, we can cast a GLcontext pointer into an OSMesaContext pointer
70 * or vice versa.
71 */
72struct osmesa_context {
73   GLcontext gl_ctx;		/* The core GL/Mesa context */
74   GLvisual *gl_visual;		/* Describes the buffers */
75   GLframebuffer *gl_buffer;	/* Depth, stencil, accum, etc buffers */
76   GLenum format;		/* either GL_RGBA or GL_COLOR_INDEX */
77   void *buffer;		/* the image buffer */
78   GLint width, height;		/* size of image buffer */
79   GLint rowlength;		/* number of pixels per row */
80   GLint userRowLength;		/* user-specified number of pixels per row */
81   GLint rshift, gshift;	/* bit shifts for RGBA formats */
82   GLint bshift, ashift;
83   GLint rInd, gInd, bInd, aInd;/* index offsets for RGBA formats */
84   GLchan *rowaddr[MAX_HEIGHT];	/* address of first pixel in each image row */
85   GLboolean yup;		/* TRUE  -> Y increases upward */
86				/* FALSE -> Y increases downward */
87};
88
89
90#define OSMESA_CONTEXT(ctx)  ((OSMesaContext) (ctx->DriverCtx))
91
92
93
94/**********************************************************************/
95/*** Private Device Driver Functions                                ***/
96/**********************************************************************/
97
98
99static const GLubyte *
100get_string( GLcontext *ctx, GLenum name )
101{
102   (void) ctx;
103   switch (name) {
104      case GL_RENDERER:
105#if CHAN_BITS == 32
106         return (const GLubyte *) "Mesa OffScreen32";
107#elif CHAN_BITS == 16
108         return (const GLubyte *) "Mesa OffScreen16";
109#else
110         return (const GLubyte *) "Mesa OffScreen";
111#endif
112      default:
113         return NULL;
114   }
115}
116
117
118static void
119osmesa_update_state( GLcontext *ctx, GLuint new_state )
120{
121   /* easy - just propogate */
122   _swrast_InvalidateState( ctx, new_state );
123   _swsetup_InvalidateState( ctx, new_state );
124   _ac_InvalidateState( ctx, new_state );
125   _tnl_InvalidateState( ctx, new_state );
126}
127
128
129static void
130set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit )
131{
132   /* separate read buffer not supported */
133   ASSERT(buffer == ctx->DrawBuffer);
134   ASSERT(bufferBit == FRONT_LEFT_BIT);
135}
136
137
138static void
139get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
140{
141   /* don't use GET_CURRENT_CONTEXT(ctx) here - it's a problem on Windows */
142   GLcontext *ctx = (GLcontext *) _glapi_get_context();
143   (void) buffer;
144   if (ctx) {
145      OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
146      *width = osmesa->width;
147      *height = osmesa->height;
148   }
149}
150
151
152static void
153clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
154       GLint x, GLint y, GLint width, GLint height )
155{
156   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
157   const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
158
159   /* sanity check - we only have a front-left buffer */
160   ASSERT((mask & (DD_FRONT_RIGHT_BIT |
161                   DD_BACK_LEFT_BIT |
162                   DD_BACK_RIGHT_BIT)) == 0);
163
164   /* use optimized clear for common cases (clear whole buffer to black) */
165   if (mask & DD_FRONT_LEFT_BIT) {
166      if (osmesa->format == OSMESA_COLOR_INDEX) {
167         if (ctx->Color.ClearIndex == 0 &&
168             ctx->Color.IndexMask == ~0 &&
169             osmesa->rowlength == osmesa->width &&
170             all) {
171            /* clear whole buffer to zeros */
172            _mesa_bzero(osmesa->buffer,
173                        osmesa->width * osmesa->height * sizeof(GLchan));
174            mask &= ~DD_FRONT_LEFT_BIT;
175         }
176      }
177      else {
178         /* RGB[A] format */
179         if (*colorMask == 0xffffffff &&
180             ctx->Color.ClearColor[0] == 0.0F &&
181             ctx->Color.ClearColor[1] == 0.0F &&
182             ctx->Color.ClearColor[2] == 0.0F &&
183             ctx->Color.ClearColor[3] == 0.0F &&
184             osmesa->rowlength == osmesa->width &&
185             all) {
186            GLint bytesPerPixel;
187            /* clear whole buffer to black */
188            if (osmesa->format == OSMESA_RGBA ||
189                osmesa->format == OSMESA_BGRA ||
190                osmesa->format == OSMESA_ARGB)
191               bytesPerPixel = 4 * sizeof(GLchan);
192            else if (osmesa->format == OSMESA_RGB ||
193                     osmesa->format == OSMESA_BGR)
194               bytesPerPixel = 3 * sizeof(GLchan);
195            else if (osmesa->format == OSMESA_RGB_565)
196               bytesPerPixel = sizeof(GLushort);
197            else {
198               _mesa_problem(ctx, "bad pixel format in osmesa_clear()");
199               return;
200            }
201            _mesa_bzero(osmesa->buffer,
202                        bytesPerPixel * osmesa->width * osmesa->height);
203            mask &= ~DD_FRONT_LEFT_BIT;
204         }
205      }
206   }
207
208   if (mask) {
209      /* software fallback (spans) for everything else. */
210      _swrast_Clear(ctx, mask, all, x, y, width, height);
211   }
212}
213
214
215/**********************************************************************/
216/*****        Read/write spans/arrays of pixels                   *****/
217/**********************************************************************/
218
219
220/* RGBA */
221#define NAME(PREFIX) PREFIX##_RGBA
222#define SPAN_VARS \
223   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
224#define INIT_PIXEL_PTR(P, X, Y) \
225   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
226#define INC_PIXEL_PTR(P) P += 4
227#if CHAN_TYPE == GL_FLOAT
228#define STORE_RGB_PIXEL(P, R, G, B) \
229   P[0] = MAX2((R), 0.0F);
230   P[1] = MAX2((G), 0.0F);
231   P[2] = MAX2((B), 0.0F);
232   P[3] = CHAN_MAXF
233#define STORE_RGBA_PIXEL(P, R, G, B, A) \
234   P[0] = MAX2((R), 0.0F);
235   P[1] = MAX2((G), 0.0F);
236   P[2] = MAX2((B), 0.0F);
237   P[3] = CLAMP((A), 0.0F, CHAN_MAXF)
238#else
239#define STORE_RGB_PIXEL(P, R, G, B) \
240   P[0] = R;  P[1] = G;  P[2] = B;  P[3] = CHAN_MAX
241#define STORE_RGBA_PIXEL(P, R, G, B, A) \
242   P[0] = R;  P[1] = G;  P[2] = B;  P[3] = A
243#endif
244#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
245   R = P[0];  G = P[1];  B = P[2];  A = P[3]
246#include "swrast/s_spantemp.h"
247
248/* BGRA */
249#define NAME(PREFIX) PREFIX##_BGRA
250#define SPAN_VARS \
251   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
252#define INIT_PIXEL_PTR(P, X, Y) \
253   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
254#define INC_PIXEL_PTR(P) P += 4
255#define STORE_RGB_PIXEL(P, R, G, B) \
256   P[2] = R;  P[1] = G;  P[0] = B;  P[3] = CHAN_MAX
257#define STORE_RGBA_PIXEL(P, R, G, B, A) \
258   P[2] = R;  P[1] = G;  P[0] = B;  P[3] = A
259#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
260   R = P[2];  G = P[1];  B = P[0];  A = P[3]
261#include "swrast/s_spantemp.h"
262
263/* ARGB */
264#define NAME(PREFIX) PREFIX##_ARGB
265#define SPAN_VARS \
266   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
267#define INIT_PIXEL_PTR(P, X, Y) \
268   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
269#define INC_PIXEL_PTR(P) P += 4
270#define STORE_RGB_PIXEL(P, R, G, B) \
271   P[1] = R;  P[2] = G;  P[3] = B;  P[0] = CHAN_MAX
272#define STORE_RGBA_PIXEL(P, R, G, B, A) \
273   P[1] = R;  P[2] = G;  P[3] = B;  P[0] = A
274#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
275   R = P[1];  G = P[2];  B = P[3];  A = P[0]
276#include "swrast/s_spantemp.h"
277
278/* RGB */
279#define NAME(PREFIX) PREFIX##_RGB
280#define SPAN_VARS \
281   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
282#define INIT_PIXEL_PTR(P, X, Y) \
283   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
284#define INC_PIXEL_PTR(P) P += 4
285#define STORE_RGB_PIXEL(P, R, G, B) \
286   P[0] = R;  P[1] = G;  P[2] = B
287#define STORE_RGBA_PIXEL(P, R, G, B, A) \
288   P[0] = R;  P[1] = G;  P[2] = B
289#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
290   R = P[0];  G = P[1];  B = P[2];  A = CHAN_MAX
291#include "swrast/s_spantemp.h"
292
293/* BGR */
294#define NAME(PREFIX) PREFIX##_BGR
295#define SPAN_VARS \
296   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
297#define INIT_PIXEL_PTR(P, X, Y) \
298   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
299#define INC_PIXEL_PTR(P) P += 4
300#define STORE_RGB_PIXEL(P, R, G, B) \
301   P[0] = B;  P[1] = G;  P[2] = R
302#define STORE_RGBA_PIXEL(P, R, G, B, A) \
303   P[0] = B;  P[1] = G;  P[2] = R
304#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
305   B = P[0];  G = P[1];  R = P[2];  A = CHAN_MAX
306#include "swrast/s_spantemp.h"
307
308/* 16-bit BGR */
309#define NAME(PREFIX) PREFIX##_RGB_565
310#define SPAN_VARS \
311   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
312#define INIT_PIXEL_PTR(P, X, Y) \
313   GLushort *P = (GLushort *) osmesa->rowaddr[Y] + (X)
314#define INC_PIXEL_PTR(P) P += 1
315#define STORE_RGB_PIXEL(P, R, G, B) \
316   *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
317#define STORE_RGBA_PIXEL(P, R, G, B, A) \
318   *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
319#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
320   R = ( (((*P) >> 8) & 0xf8) | (((*P) >> 11) & 0x7) ); \
321   G = ( (((*P) >> 3) & 0xfc) | (((*P) >>  5) & 0x3) ); \
322   B = ( (((*P) << 3) & 0xf8) | (((*P)      ) & 0x7) ); \
323   A = CHAN_MAX
324#include "swrast/s_spantemp.h"
325
326/* color index */
327#define NAME(PREFIX) PREFIX##_CI
328#define SPAN_VARS \
329   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
330#define INIT_PIXEL_PTR(P, X, Y) \
331   GLchan *P = osmesa->rowaddr[Y] + (X)
332#define INC_PIXEL_PTR(P) P += 1
333#define STORE_CI_PIXEL(P, CI) \
334   P[0] = CI
335#define FETCH_CI_PIXEL(CI, P) \
336   CI = P[0]
337#include "swrast/s_spantemp.h"
338
339
340/**********************************************************************/
341/*****                   Optimized line rendering                 *****/
342/**********************************************************************/
343
344
345#if CHAN_TYPE == GL_FLOAT
346#define PACK_RGBA(DST, R, G, B, A)	\
347do {					\
348   (DST)[0] = MAX2( R, 0.0F );		\
349   (DST)[1] = MAX2( G, 0.0F );		\
350   (DST)[2] = MAX2( B, 0.0F );		\
351   (DST)[3] = CLAMP(A, 0.0F, CHAN_MAXF);\
352} while (0)
353#else
354#define PACK_RGBA(DST, R, G, B, A)	\
355do {					\
356   (DST)[osmesa->rInd] = R;		\
357   (DST)[osmesa->gInd] = G;		\
358   (DST)[osmesa->bInd] = B;		\
359   (DST)[osmesa->aInd] = A;		\
360} while (0)
361#endif
362
363#define PACK_RGB(DST, R, G, B)  \
364do {				\
365   (DST)[0] = R;		\
366   (DST)[1] = G;		\
367   (DST)[2] = B;		\
368} while (0)
369
370#define PACK_BGR(DST, R, G, B)  \
371do {				\
372   (DST)[0] = B;		\
373   (DST)[1] = G;		\
374   (DST)[2] = R;		\
375} while (0)
376
377#define PACK_RGB_565(DST, R, G, B)					\
378do {									\
379   (DST) = (((int) (R) << 8) & 0xf800) | (((int) (G) << 3) & 0x7e0) | ((int) (B) >> 3);\
380} while (0)
381
382#define UNPACK_RED(P)      ( (P)[osmesa->rInd] )
383#define UNPACK_GREEN(P)    ( (P)[osmesa->gInd] )
384#define UNPACK_BLUE(P)     ( (P)[osmesa->bInd] )
385#define UNPACK_ALPHA(P)    ( (P)[osmesa->aInd] )
386
387#define PIXELADDR1(X,Y)  (osmesa->rowaddr[Y] + (X))
388#define PIXELADDR2(X,Y)  (osmesa->rowaddr[Y] + 2 * (X))
389#define PIXELADDR3(X,Y)  (osmesa->rowaddr[Y] + 3 * (X))
390#define PIXELADDR4(X,Y)  (osmesa->rowaddr[Y] + 4 * (X))
391
392
393/*
394 * Draw a flat-shaded, RGB line into an osmesa buffer.
395 */
396static void
397flat_rgba_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 )
398{
399   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
400   const GLchan *color = vert1->color;
401
402#define INTERP_XY 1
403#define CLIP_HACK 1
404#define PLOT(X, Y)						\
405do {								\
406   GLchan *p = PIXELADDR4(X, Y);				\
407   PACK_RGBA(p, color[0], color[1], color[2], color[3]);	\
408} while (0)
409
410#ifdef WIN32
411#include "..\swrast\s_linetemp.h"
412#else
413#include "swrast/s_linetemp.h"
414#endif
415}
416
417
418/*
419 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
420 */
421static void
422flat_rgba_z_line(GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1)
423{
424   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
425   const GLchan *color = vert1->color;
426
427#define INTERP_XY 1
428#define INTERP_Z 1
429#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
430#define CLIP_HACK 1
431#define PLOT(X, Y)					\
432do {							\
433   if (Z < *zPtr) {					\
434      GLchan *p = PIXELADDR4(X, Y);			\
435      PACK_RGBA(p, color[RCOMP], color[GCOMP],		\
436                   color[BCOMP], color[ACOMP]);		\
437      *zPtr = Z;					\
438   }							\
439} while (0)
440
441
442#ifdef WIN32
443#include "..\swrast\s_linetemp.h"
444#else
445#include "swrast/s_linetemp.h"
446#endif
447}
448
449
450/*
451 * Draw a flat-shaded, alpha-blended, RGB line into an osmesa buffer.
452 * XXX update for GLchan
453 */
454static void
455flat_blend_rgba_line( GLcontext *ctx,
456                      const SWvertex *vert0, const SWvertex *vert1 )
457{
458   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
459   const GLint rshift = osmesa->rshift;
460   const GLint gshift = osmesa->gshift;
461   const GLint bshift = osmesa->bshift;
462   const GLint avalue = vert0->color[3];
463   const GLint msavalue = CHAN_MAX - avalue;
464   const GLint rvalue = vert1->color[0]*avalue;
465   const GLint gvalue = vert1->color[1]*avalue;
466   const GLint bvalue = vert1->color[2]*avalue;
467
468#define INTERP_XY 1
469#define CLIP_HACK 1
470#define PLOT(X,Y)					\
471   { GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y);	\
472     GLuint  pixel = 0;					\
473     pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);\
474     pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);\
475     pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);\
476     *ptr4 = pixel;					\
477   }
478
479#if 0  /* XXX use this in the future */
480#define PLOT(X,Y)							\
481   {									\
482      GLchan *pixel = (GLchan *) PIXELADDR4(X, Y);			\
483      pixel[rInd] = (pixel[rInd] * msavalue + rvalue) >> CHAN_BITS;	\
484      pixel[gInd] = (pixel[gInd] * msavalue + gvalue) >> CHAN_BITS;	\
485      pixel[bInd] = (pixel[bInd] * msavalue + bvalue) >> CHAN_BITS;	\
486      pixel[aInd] = (pixel[aInd] * msavalue + avalue) >> CHAN_BITS;	\
487   }
488#endif
489
490#ifdef WIN32
491#include "..\swrast\s_linetemp.h"
492#else
493#include "swrast/s_linetemp.h"
494#endif
495}
496
497
498/*
499 * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer.
500 * But don't write to Z buffer.
501 * XXX update for GLchan
502 */
503static void
504flat_blend_rgba_z_line( GLcontext *ctx,
505                        const SWvertex *vert0, const SWvertex *vert1 )
506{
507   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
508   const GLint rshift = osmesa->rshift;
509   const GLint gshift = osmesa->gshift;
510   const GLint bshift = osmesa->bshift;
511   const GLint avalue = vert0->color[3];
512   const GLint msavalue = 256 - avalue;
513   const GLint rvalue = vert1->color[0]*avalue;
514   const GLint gvalue = vert1->color[1]*avalue;
515   const GLint bvalue = vert1->color[2]*avalue;
516
517#define INTERP_XY 1
518#define INTERP_Z 1
519#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
520#define CLIP_HACK 1
521#define PLOT(X,Y)							\
522	if (Z < *zPtr) {						\
523	   GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y);			\
524	   GLuint  pixel = 0;						\
525	   pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);	\
526	   pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);	\
527	   pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);	\
528	   *ptr4 = pixel; 						\
529	}
530
531#if 0  /* XXX use this in the future */
532#define PLOT(X,Y)							\
533   if (Z < *zPtr) {							\
534      GLchan *pixel = (GLchan *) PIXELADDR4(X, Y);			\
535      pixel[rInd] = (pixel[rInd] * msavalue + rvalue) >> CHAN_BITS;	\
536      pixel[gInd] = (pixel[gInd] * msavalue + gvalue) >> CHAN_BITS;	\
537      pixel[bInd] = (pixel[bInd] * msavalue + bvalue) >> CHAN_BITS;	\
538      pixel[aInd] = (pixel[aInd] * msavalue + avalue) >> CHAN_BITS;	\
539   }
540#endif
541
542#ifdef WIN32
543#include "..\swrast\s_linetemp.h"
544#else
545#include "swrast/s_linetemp.h"
546#endif
547}
548
549
550/*
551 * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer.
552 * XXX update for GLchan
553 */
554static void
555flat_blend_rgba_z_line_write( GLcontext *ctx,
556                              const SWvertex *vert0, const SWvertex *vert1 )
557{
558   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
559   const GLint rshift = osmesa->rshift;
560   const GLint gshift = osmesa->gshift;
561   const GLint bshift = osmesa->bshift;
562   const GLint avalue = vert0->color[3];
563   const GLint msavalue = 256 - avalue;
564   const GLint rvalue = vert1->color[0]*avalue;
565   const GLint gvalue = vert1->color[1]*avalue;
566   const GLint bvalue = vert1->color[2]*avalue;
567
568#define INTERP_XY 1
569#define INTERP_Z 1
570#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
571#define CLIP_HACK 1
572#define PLOT(X,Y)							\
573	if (Z < *zPtr) {						\
574	   GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y);			\
575	   GLuint  pixel = 0;						\
576	   pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);	\
577	   pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);	\
578	   pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);	\
579	   *ptr4 = pixel;						\
580	   *zPtr = Z;							\
581	}
582
583#if 0  /* XXX use this in the future */
584#define PLOT(X,Y)							\
585   if (Z < *zPtr) {							\
586      GLchan *pixel = (GLchan *) PIXELADDR4(X, Y);			\
587      pixel[rInd] = (pixel[rInd] * msavalue + rvalue) >> CHAN_BITS;	\
588      pixel[gInd] = (pixel[gInd] * msavalue + gvalue) >> CHAN_BITS;	\
589      pixel[bInd] = (pixel[bInd] * msavalue + bvalue) >> CHAN_BITS;	\
590      pixel[aInd] = (pixel[aInd] * msavalue + avalue) >> CHAN_BITS;	\
591      *zPtr = Z;							\
592   }
593#endif
594
595#ifdef WIN32
596#include "..\swrast\s_linetemp.h"
597#else
598#include "swrast/s_linetemp.h"
599#endif
600}
601
602
603/*
604 * Analyze context state to see if we can provide a fast line drawing
605 * function, like those in lines.c.  Otherwise, return NULL.
606 */
607static swrast_line_func
608osmesa_choose_line_function( GLcontext *ctx )
609{
610   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
611   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
612
613   if (CHAN_BITS != 8)                    return NULL;
614   if (ctx->RenderMode != GL_RENDER)      return NULL;
615   if (ctx->Line.SmoothFlag)              return NULL;
616   if (ctx->Texture._EnabledUnits)        return NULL;
617   if (ctx->Light.ShadeModel != GL_FLAT)  return NULL;
618   if (ctx->Line.Width != 1.0F)           return NULL;
619   if (ctx->Line.StippleFlag)             return NULL;
620   if (ctx->Line.SmoothFlag)              return NULL;
621   if (osmesa->format != OSMESA_RGBA &&
622       osmesa->format != OSMESA_BGRA &&
623       osmesa->format != OSMESA_ARGB)     return NULL;
624
625   if (swrast->_RasterMask==DEPTH_BIT
626       && ctx->Depth.Func==GL_LESS
627       && ctx->Depth.Mask==GL_TRUE
628       && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
629      return (swrast_line_func) flat_rgba_z_line;
630   }
631
632   if (swrast->_RasterMask == 0) {
633      return (swrast_line_func) flat_rgba_line;
634   }
635
636   if (swrast->_RasterMask==(DEPTH_BIT|BLEND_BIT)
637       && ctx->Depth.Func==GL_LESS
638       && ctx->Depth.Mask==GL_TRUE
639       && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
640       && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
641       && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
642       && ctx->Color.BlendSrcA==GL_SRC_ALPHA
643       && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
644       && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
645      return (swrast_line_func) flat_blend_rgba_z_line_write;
646   }
647
648   if (swrast->_RasterMask==(DEPTH_BIT|BLEND_BIT)
649       && ctx->Depth.Func==GL_LESS
650       && ctx->Depth.Mask==GL_FALSE
651       && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS
652       && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
653       && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
654       && ctx->Color.BlendSrcA==GL_SRC_ALPHA
655       && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
656       && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
657      return (swrast_line_func) flat_blend_rgba_z_line;
658   }
659
660   if (swrast->_RasterMask==BLEND_BIT
661       && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA
662       && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA
663       && ctx->Color.BlendSrcA==GL_SRC_ALPHA
664       && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA
665       && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) {
666      return (swrast_line_func) flat_blend_rgba_line;
667   }
668
669   return (swrast_line_func) NULL;
670}
671
672
673/**********************************************************************/
674/*****                 Optimized triangle rendering               *****/
675/**********************************************************************/
676
677
678/*
679 * Smooth-shaded, z-less triangle, RGBA color.
680 */
681#define NAME smooth_rgba_z_triangle
682#define INTERP_Z 1
683#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
684#define INTERP_RGB 1
685#define INTERP_ALPHA 1
686#define SETUP_CODE \
687   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
688#define RENDER_SPAN( span )					\
689   GLuint i;							\
690   GLchan *img = PIXELADDR4(span.x, span.y); 			\
691   for (i = 0; i < span.end; i++, img += 4) {			\
692      const GLdepth z = FixedToDepth(span.z);			\
693      if (z < zRow[i]) {					\
694         PACK_RGBA(img, FixedToChan(span.red),			\
695            FixedToChan(span.green), FixedToChan(span.blue),	\
696            FixedToChan(span.alpha));				\
697         zRow[i] = z;						\
698      }								\
699      span.red += span.redStep;					\
700      span.green += span.greenStep;				\
701      span.blue += span.blueStep;				\
702      span.alpha += span.alphaStep;				\
703      span.z += span.zStep;					\
704   }
705#ifdef WIN32
706#include "..\swrast\s_tritemp.h"
707#else
708#include "swrast/s_tritemp.h"
709#endif
710
711
712
713/*
714 * Flat-shaded, z-less triangle, RGBA color.
715 */
716#define NAME flat_rgba_z_triangle
717#define INTERP_Z 1
718#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
719#define SETUP_CODE						\
720   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);		\
721   GLuint pixel;						\
722   PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1],	\
723                                v2->color[2], v2->color[3]);
724
725#define RENDER_SPAN( span )				\
726   GLuint i;						\
727   GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y);	\
728   for (i = 0; i < span.end; i++) {			\
729      const GLdepth z = FixedToDepth(span.z);		\
730      if (z < zRow[i]) {				\
731         img[i] = pixel;				\
732         zRow[i] = z;					\
733      }							\
734      span.z += span.zStep;				\
735   }
736#ifdef WIN32
737#include "..\swrast\s_tritemp.h"
738#else
739#include "swrast/s_tritemp.h"
740#endif
741
742
743
744/*
745 * Return pointer to an accelerated triangle function if possible.
746 */
747static swrast_tri_func
748osmesa_choose_triangle_function( GLcontext *ctx )
749{
750   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
751   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
752
753   if (CHAN_BITS != 8)                  return (swrast_tri_func) NULL;
754   if (ctx->RenderMode != GL_RENDER)    return (swrast_tri_func) NULL;
755   if (ctx->Polygon.SmoothFlag)         return (swrast_tri_func) NULL;
756   if (ctx->Polygon.StippleFlag)        return (swrast_tri_func) NULL;
757   if (ctx->Texture._EnabledUnits)      return (swrast_tri_func) NULL;
758   if (osmesa->format != OSMESA_RGBA &&
759       osmesa->format != OSMESA_BGRA &&
760       osmesa->format != OSMESA_ARGB)   return (swrast_tri_func) NULL;
761   if (ctx->Polygon.CullFlag &&
762       ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
763                                        return (swrast_tri_func) NULL;
764
765   if (swrast->_RasterMask == DEPTH_BIT &&
766       ctx->Depth.Func == GL_LESS &&
767       ctx->Depth.Mask == GL_TRUE &&
768       ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
769      if (ctx->Light.ShadeModel == GL_SMOOTH) {
770         return (swrast_tri_func) smooth_rgba_z_triangle;
771      }
772      else {
773         return (swrast_tri_func) flat_rgba_z_triangle;
774      }
775   }
776   return (swrast_tri_func) NULL;
777}
778
779
780
781/* Override for the swrast triangle-selection function.  Try to use one
782 * of our internal triangle functions, otherwise fall back to the
783 * standard swrast functions.
784 */
785static void
786osmesa_choose_triangle( GLcontext *ctx )
787{
788   SWcontext *swrast = SWRAST_CONTEXT(ctx);
789
790   swrast->Triangle = osmesa_choose_triangle_function( ctx );
791   if (!swrast->Triangle)
792      _swrast_choose_triangle( ctx );
793}
794
795static void
796osmesa_choose_line( GLcontext *ctx )
797{
798   SWcontext *swrast = SWRAST_CONTEXT(ctx);
799
800   swrast->Line = osmesa_choose_line_function( ctx );
801   if (!swrast->Line)
802      _swrast_choose_line( ctx );
803}
804
805
806#define OSMESA_NEW_LINE   (_NEW_LINE | \
807                           _NEW_TEXTURE | \
808                           _NEW_LIGHT | \
809                           _NEW_DEPTH | \
810                           _NEW_RENDERMODE | \
811                           _SWRAST_NEW_RASTERMASK)
812
813#define OSMESA_NEW_TRIANGLE (_NEW_POLYGON | \
814                             _NEW_TEXTURE | \
815                             _NEW_LIGHT | \
816                             _NEW_DEPTH | \
817                             _NEW_RENDERMODE | \
818                             _SWRAST_NEW_RASTERMASK)
819
820/* one-time, per-context initialization */
821static void
822hook_in_driver_functions( GLcontext *ctx )
823{
824   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
825   SWcontext *swrast = SWRAST_CONTEXT( ctx );
826   struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx );
827   TNLcontext *tnl = TNL_CONTEXT(ctx);
828
829   ASSERT((void *) osmesa == (void *) ctx->DriverCtx);
830
831   /* use default TCL pipeline */
832   tnl->Driver.RunPipeline = _tnl_run_pipeline;
833
834   ctx->Driver.GetString = get_string;
835   ctx->Driver.UpdateState = osmesa_update_state;
836   ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
837   ctx->Driver.GetBufferSize = get_buffer_size;
838
839   ctx->Driver.Accum = _swrast_Accum;
840   ctx->Driver.Bitmap = _swrast_Bitmap;
841   ctx->Driver.Clear = clear;  /* = _swrast_Clear */
842   ctx->Driver.CopyPixels = _swrast_CopyPixels;
843   ctx->Driver.DrawPixels = _swrast_DrawPixels;
844   ctx->Driver.ReadPixels = _swrast_ReadPixels;
845   ctx->Driver.DrawBuffer = _swrast_DrawBuffer;
846
847   ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format;
848   ctx->Driver.TexImage1D = _mesa_store_teximage1d;
849   ctx->Driver.TexImage2D = _mesa_store_teximage2d;
850   ctx->Driver.TexImage3D = _mesa_store_teximage3d;
851   ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d;
852   ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d;
853   ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
854   ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
855
856   ctx->Driver.CompressedTexImage1D = _mesa_store_compressed_teximage1d;
857   ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d;
858   ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d;
859   ctx->Driver.CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d;
860   ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d;
861   ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d;
862
863   ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
864   ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
865   ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
866   ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
867   ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
868   ctx->Driver.CopyColorTable = _swrast_CopyColorTable;
869   ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable;
870   ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D;
871   ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D;
872
873   swdd->SetBuffer = set_buffer;
874
875   /* RGB(A) span/pixel functions */
876   if (osmesa->format == OSMESA_RGB) {
877      swdd->WriteRGBASpan = write_rgba_span_RGB;
878      swdd->WriteRGBSpan = write_rgb_span_RGB;
879      swdd->WriteMonoRGBASpan = write_monorgba_span_RGB;
880      swdd->WriteRGBAPixels = write_rgba_pixels_RGB;
881      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB;
882      swdd->ReadRGBASpan = read_rgba_span_RGB;
883      swdd->ReadRGBAPixels = read_rgba_pixels_RGB;
884   }
885   else if (osmesa->format == OSMESA_BGR) {
886      swdd->WriteRGBASpan = write_rgba_span_BGR;
887      swdd->WriteRGBSpan = write_rgb_span_BGR;
888      swdd->WriteMonoRGBASpan = write_monorgba_span_BGR;
889      swdd->WriteRGBAPixels = write_rgba_pixels_BGR;
890      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGR;
891      swdd->ReadRGBASpan = read_rgba_span_BGR;
892      swdd->ReadRGBAPixels = read_rgba_pixels_BGR;
893   }
894   else if (osmesa->format == OSMESA_RGB_565) {
895      swdd->WriteRGBASpan = write_rgba_span_RGB_565;
896      swdd->WriteRGBSpan = write_rgb_span_RGB_565;
897      swdd->WriteMonoRGBASpan = write_monorgba_span_RGB_565;
898      swdd->WriteRGBAPixels = write_rgba_pixels_RGB_565;
899      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB_565;
900      swdd->ReadRGBASpan = read_rgba_span_RGB_565;
901      swdd->ReadRGBAPixels = read_rgba_pixels_RGB_565;
902   }
903   else if (osmesa->format == OSMESA_RGBA) {
904      swdd->WriteRGBASpan = write_rgba_span_RGBA;
905      swdd->WriteRGBSpan = write_rgb_span_RGBA;
906      swdd->WriteMonoRGBASpan = write_monorgba_span_RGBA;
907      swdd->WriteRGBAPixels = write_rgba_pixels_RGBA;
908      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGBA;
909      swdd->ReadRGBASpan = read_rgba_span_RGBA;
910      swdd->ReadRGBAPixels = read_rgba_pixels_RGBA;
911   }
912   else if (osmesa->format == OSMESA_BGRA) {
913      swdd->WriteRGBASpan = write_rgba_span_BGRA;
914      swdd->WriteRGBSpan = write_rgb_span_BGRA;
915      swdd->WriteMonoRGBASpan = write_monorgba_span_BGRA;
916      swdd->WriteRGBAPixels = write_rgba_pixels_BGRA;
917      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGRA;
918      swdd->ReadRGBASpan = read_rgba_span_BGRA;
919      swdd->ReadRGBAPixels = read_rgba_pixels_BGRA;
920   }
921   else if (osmesa->format == OSMESA_ARGB) {
922      swdd->WriteRGBASpan = write_rgba_span_ARGB;
923      swdd->WriteRGBSpan = write_rgb_span_ARGB;
924      swdd->WriteMonoRGBASpan = write_monorgba_span_ARGB;
925      swdd->WriteRGBAPixels = write_rgba_pixels_ARGB;
926      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_ARGB;
927      swdd->ReadRGBASpan = read_rgba_span_ARGB;
928      swdd->ReadRGBAPixels = read_rgba_pixels_ARGB;
929   }
930   else if (osmesa->format == OSMESA_COLOR_INDEX) {
931      swdd->WriteCI32Span = write_index32_span_CI;
932      swdd->WriteCI8Span = write_index8_span_CI;
933      swdd->WriteMonoCISpan = write_monoindex_span_CI;
934      swdd->WriteCI32Pixels = write_index_pixels_CI;
935      swdd->WriteMonoCIPixels = write_monoindex_pixels_CI;
936      swdd->ReadCI32Span = read_index_span_CI;
937      swdd->ReadCI32Pixels = read_index_pixels_CI;
938   }
939   else {
940      _mesa_problem(ctx, "bad pixel format in osmesa_update_state!\n");
941   }
942
943   /* Extend the software rasterizer with our optimized line and triangle
944    * drawin functions.
945    */
946   swrast->choose_line = osmesa_choose_line;
947   swrast->choose_triangle = osmesa_choose_triangle;
948   swrast->invalidate_line |= OSMESA_NEW_LINE;
949   swrast->invalidate_triangle |= OSMESA_NEW_TRIANGLE;
950}
951
952
953
954
955/**********************************************************************/
956/*****                    Public Functions                        *****/
957/**********************************************************************/
958
959
960/*
961 * Create an Off-Screen Mesa rendering context.  The only attribute needed is
962 * an RGBA vs Color-Index mode flag.
963 *
964 * Input:  format - either GL_RGBA or GL_COLOR_INDEX
965 *         sharelist - specifies another OSMesaContext with which to share
966 *                     display lists.  NULL indicates no sharing.
967 * Return:  an OSMesaContext or 0 if error
968 */
969GLAPI OSMesaContext GLAPIENTRY
970OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
971{
972   return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS,
973                                 8, 16, sharelist);
974}
975
976
977
978/*
979 * New in Mesa 3.5
980 *
981 * Create context and specify size of ancillary buffers.
982 */
983GLAPI OSMesaContext GLAPIENTRY
984OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
985                        GLint accumBits, OSMesaContext sharelist )
986{
987   OSMesaContext osmesa;
988   GLint rshift, gshift, bshift, ashift;
989   GLint rind, gind, bind, aind;
990   GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
991   GLboolean rgbmode;
992   const GLuint i4 = 1;
993   const GLubyte *i1 = (GLubyte *) &i4;
994   const GLint little_endian = *i1;
995
996   rind = gind = bind = aind = 0;
997   if (format==OSMESA_COLOR_INDEX) {
998      indexBits = 8;
999      rshift = gshift = bshift = ashift = 0;
1000      rgbmode = GL_FALSE;
1001   }
1002   else if (format==OSMESA_RGBA) {
1003      indexBits = 0;
1004      redBits = CHAN_BITS;
1005      greenBits = CHAN_BITS;
1006      blueBits = CHAN_BITS;
1007      alphaBits = CHAN_BITS;
1008      rind = 0;
1009      gind = 1;
1010      bind = 2;
1011      aind = 3;
1012      if (little_endian) {
1013         rshift = 0;
1014         gshift = 8;
1015         bshift = 16;
1016         ashift = 24;
1017      }
1018      else {
1019         rshift = 24;
1020         gshift = 16;
1021         bshift = 8;
1022         ashift = 0;
1023      }
1024      rgbmode = GL_TRUE;
1025   }
1026   else if (format==OSMESA_BGRA) {
1027      indexBits = 0;
1028      redBits = CHAN_BITS;
1029      greenBits = CHAN_BITS;
1030      blueBits = CHAN_BITS;
1031      alphaBits = CHAN_BITS;
1032      bind = 0;
1033      gind = 1;
1034      rind = 2;
1035      aind = 3;
1036      if (little_endian) {
1037         bshift = 0;
1038         gshift = 8;
1039         rshift = 16;
1040         ashift = 24;
1041      }
1042      else {
1043         bshift = 24;
1044         gshift = 16;
1045         rshift = 8;
1046         ashift = 0;
1047      }
1048      rgbmode = GL_TRUE;
1049   }
1050   else if (format==OSMESA_ARGB) {
1051      indexBits = 0;
1052      redBits = CHAN_BITS;
1053      greenBits = CHAN_BITS;
1054      blueBits = CHAN_BITS;
1055      alphaBits = CHAN_BITS;
1056      aind = 0;
1057      rind = 1;
1058      gind = 2;
1059      bind = 3;
1060      if (little_endian) {
1061         ashift = 0;
1062         rshift = 8;
1063         gshift = 16;
1064         bshift = 24;
1065      }
1066      else {
1067         ashift = 24;
1068         rshift = 16;
1069         gshift = 8;
1070         bshift = 0;
1071      }
1072      rgbmode = GL_TRUE;
1073   }
1074   else if (format==OSMESA_RGB) {
1075      indexBits = 0;
1076      redBits = CHAN_BITS;
1077      greenBits = CHAN_BITS;
1078      blueBits = CHAN_BITS;
1079      alphaBits = 0;
1080      bshift = 0;
1081      gshift = 8;
1082      rshift = 16;
1083      ashift = 24;
1084      rind = 0;
1085      gind = 1;
1086      bind = 2;
1087      rgbmode = GL_TRUE;
1088   }
1089   else if (format==OSMESA_BGR) {
1090      indexBits = 0;
1091      redBits = CHAN_BITS;
1092      greenBits = CHAN_BITS;
1093      blueBits = CHAN_BITS;
1094      alphaBits = 0;
1095      bshift = 0;
1096      gshift = 8;
1097      rshift = 16;
1098      ashift = 24;
1099      rind = 2;
1100      gind = 1;
1101      bind = 0;
1102      rgbmode = GL_TRUE;
1103   }
1104   else if (format==OSMESA_RGB_565) {
1105      indexBits = 0;
1106      redBits = 5;
1107      greenBits = 6;
1108      blueBits = 5;
1109      alphaBits = 0;
1110      rshift = 11;
1111      gshift = 5;
1112      bshift = 0;
1113      ashift = 0;
1114      rind = 0; /* not used */
1115      gind = 0;
1116      bind = 0;
1117      rgbmode = GL_TRUE;
1118   }
1119   else {
1120      return NULL;
1121   }
1122
1123
1124   osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
1125   if (osmesa) {
1126      osmesa->gl_visual = _mesa_create_visual( rgbmode,
1127                                               GL_FALSE,    /* double buffer */
1128                                               GL_FALSE,    /* stereo */
1129                                               redBits,
1130                                               greenBits,
1131                                               blueBits,
1132                                               alphaBits,
1133                                               indexBits,
1134                                               depthBits,
1135                                               stencilBits,
1136                                               accumBits,
1137                                               accumBits,
1138                                               accumBits,
1139                                               alphaBits ? accumBits : 0,
1140                                               1            /* num samples */
1141                                               );
1142      if (!osmesa->gl_visual) {
1143         FREE(osmesa);
1144         return NULL;
1145      }
1146
1147      if (!_mesa_initialize_context(&osmesa->gl_ctx,
1148                                    osmesa->gl_visual,
1149                                    sharelist ? &sharelist->gl_ctx
1150                                              : (GLcontext *) NULL,
1151                                    (void *) osmesa,
1152                                    GL_FALSE)) {
1153         _mesa_destroy_visual( osmesa->gl_visual );
1154         FREE(osmesa);
1155         return NULL;
1156      }
1157
1158      _mesa_enable_sw_extensions(&(osmesa->gl_ctx));
1159      _mesa_enable_1_3_extensions(&(osmesa->gl_ctx));
1160      /*_mesa_enable_1_4_extensions(&(osmesa->gl_ctx));*/
1161
1162      osmesa->gl_buffer = _mesa_create_framebuffer( osmesa->gl_visual,
1163                           (GLboolean) ( osmesa->gl_visual->depthBits > 0 ),
1164                           (GLboolean) ( osmesa->gl_visual->stencilBits > 0 ),
1165                           (GLboolean) ( osmesa->gl_visual->accumRedBits > 0 ),
1166                           GL_FALSE /* s/w alpha */ );
1167
1168      if (!osmesa->gl_buffer) {
1169         _mesa_destroy_visual( osmesa->gl_visual );
1170         _mesa_free_context_data( &osmesa->gl_ctx );
1171         FREE(osmesa);
1172         return NULL;
1173      }
1174      osmesa->format = format;
1175      osmesa->buffer = NULL;
1176      osmesa->width = 0;
1177      osmesa->height = 0;
1178      osmesa->userRowLength = 0;
1179      osmesa->rowlength = 0;
1180      osmesa->yup = GL_TRUE;
1181      osmesa->rshift = rshift;
1182      osmesa->gshift = gshift;
1183      osmesa->bshift = bshift;
1184      osmesa->ashift = ashift;
1185      osmesa->rInd = rind;
1186      osmesa->gInd = gind;
1187      osmesa->bInd = bind;
1188      osmesa->aInd = aind;
1189
1190      /* Initialize the software rasterizer and helper modules. */
1191      {
1192	 GLcontext *ctx = &osmesa->gl_ctx;
1193
1194	 _swrast_CreateContext( ctx );
1195	 _ac_CreateContext( ctx );
1196	 _tnl_CreateContext( ctx );
1197	 _swsetup_CreateContext( ctx );
1198
1199	 _swsetup_Wakeup( ctx );
1200         hook_in_driver_functions( ctx );
1201      }
1202   }
1203   return osmesa;
1204}
1205
1206
1207/*
1208 * Destroy an Off-Screen Mesa rendering context.
1209 *
1210 * Input:  ctx - the context to destroy
1211 */
1212GLAPI void GLAPIENTRY
1213OSMesaDestroyContext( OSMesaContext ctx )
1214{
1215   if (ctx) {
1216      _swsetup_DestroyContext( &ctx->gl_ctx );
1217      _tnl_DestroyContext( &ctx->gl_ctx );
1218      _ac_DestroyContext( &ctx->gl_ctx );
1219      _swrast_DestroyContext( &ctx->gl_ctx );
1220
1221      _mesa_destroy_visual( ctx->gl_visual );
1222      _mesa_destroy_framebuffer( ctx->gl_buffer );
1223      _mesa_free_context_data( &ctx->gl_ctx );
1224      FREE( ctx );
1225   }
1226}
1227
1228
1229/*
1230 * Recompute the values of the context's rowaddr array.
1231 */
1232static void
1233compute_row_addresses( OSMesaContext ctx )
1234{
1235   GLint bytesPerPixel, bytesPerRow, i;
1236   GLubyte *origin = (GLubyte *) ctx->buffer;
1237
1238   if (ctx->format == OSMESA_COLOR_INDEX) {
1239      /* CI mode */
1240      bytesPerPixel = 1 * sizeof(GLchan);
1241   }
1242   else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) {
1243      /* RGB mode */
1244      bytesPerPixel = 3 * sizeof(GLchan);
1245   }
1246   else if (ctx->format == OSMESA_RGB_565) {
1247      /* 5/6/5 RGB pixel in 16 bits */
1248      bytesPerPixel = 2;
1249   }
1250   else {
1251      /* RGBA mode */
1252      bytesPerPixel = 4 * sizeof(GLchan);
1253   }
1254
1255   bytesPerRow = ctx->rowlength * bytesPerPixel;
1256
1257   if (ctx->yup) {
1258      /* Y=0 is bottom line of window */
1259      for (i = 0; i < MAX_HEIGHT; i++) {
1260         ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow);
1261      }
1262   }
1263   else {
1264      /* Y=0 is top line of window */
1265      for (i = 0; i < MAX_HEIGHT; i++) {
1266         GLint j = ctx->height - i - 1;
1267         ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow);
1268      }
1269   }
1270}
1271
1272
1273/*
1274 * Bind an OSMesaContext to an image buffer.  The image buffer is just a
1275 * block of memory which the client provides.  Its size must be at least
1276 * as large as width*height*sizeof(type).  Its address should be a multiple
1277 * of 4 if using RGBA mode.
1278 *
1279 * Image data is stored in the order of glDrawPixels:  row-major order
1280 * with the lower-left image pixel stored in the first array position
1281 * (ie. bottom-to-top).
1282 *
1283 * If the context's viewport hasn't been initialized yet, it will now be
1284 * initialized to (0,0,width,height).
1285 *
1286 * Input:  ctx - the rendering context
1287 *         buffer - the image buffer memory
1288 *         type - data type for pixel components
1289 *            Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5
1290 *            are supported.  But if Mesa's been compiled with CHAN_BITS==16
1291 *            then type must be GL_UNSIGNED_SHORT.  And if Mesa's been build
1292 *            with CHAN_BITS==32 then type must be GL_FLOAT.
1293 *         width, height - size of image buffer in pixels, at least 1
1294 * Return:  GL_TRUE if success, GL_FALSE if error because of invalid ctx,
1295 *          invalid buffer address, invalid type, width<1, height<1,
1296 *          width>internal limit or height>internal limit.
1297 */
1298GLAPI GLboolean GLAPIENTRY
1299OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type,
1300                   GLsizei width, GLsizei height )
1301{
1302   if (!ctx || !buffer ||
1303       width < 1 || height < 1 ||
1304       width > MAX_WIDTH || height > MAX_HEIGHT) {
1305      return GL_FALSE;
1306   }
1307
1308   if (ctx->format == OSMESA_RGB_565) {
1309      if (type != GL_UNSIGNED_SHORT_5_6_5)
1310         return GL_FALSE;
1311   }
1312   else if (type != CHAN_TYPE) {
1313      return GL_FALSE;
1314   }
1315
1316   osmesa_update_state( &ctx->gl_ctx, 0 );
1317   _mesa_make_current( &ctx->gl_ctx, ctx->gl_buffer );
1318
1319   ctx->buffer = buffer;
1320   ctx->width = width;
1321   ctx->height = height;
1322   if (ctx->userRowLength)
1323      ctx->rowlength = ctx->userRowLength;
1324   else
1325      ctx->rowlength = width;
1326
1327   compute_row_addresses( ctx );
1328
1329   /* init viewport */
1330   if (ctx->gl_ctx.Viewport.Width == 0) {
1331      /* initialize viewport and scissor box to buffer size */
1332      _mesa_Viewport( 0, 0, width, height );
1333      ctx->gl_ctx.Scissor.Width = width;
1334      ctx->gl_ctx.Scissor.Height = height;
1335   }
1336   else {
1337      /* this will make ensure we recognize the new buffer size */
1338      _mesa_ResizeBuffersMESA();
1339   }
1340
1341   /* Added by Gerk Huisma: */
1342   _tnl_MakeCurrent( &ctx->gl_ctx, ctx->gl_ctx.DrawBuffer,
1343                     ctx->gl_ctx.ReadBuffer );
1344
1345   return GL_TRUE;
1346}
1347
1348
1349
1350GLAPI OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void )
1351{
1352   GLcontext *ctx = _mesa_get_current_context();
1353   if (ctx)
1354      return (OSMesaContext) ctx;
1355   else
1356      return NULL;
1357}
1358
1359
1360
1361GLAPI void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value )
1362{
1363   OSMesaContext osmesa = OSMesaGetCurrentContext();
1364
1365   switch (pname) {
1366      case OSMESA_ROW_LENGTH:
1367         if (value<0) {
1368            _mesa_error( &osmesa->gl_ctx, GL_INVALID_VALUE,
1369                      "OSMesaPixelStore(value)" );
1370            return;
1371         }
1372         osmesa->userRowLength = value;
1373         osmesa->rowlength = value ? value : osmesa->width;
1374         break;
1375      case OSMESA_Y_UP:
1376         osmesa->yup = value ? GL_TRUE : GL_FALSE;
1377         break;
1378      default:
1379         _mesa_error( &osmesa->gl_ctx, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
1380         return;
1381   }
1382
1383   compute_row_addresses( osmesa );
1384}
1385
1386
1387GLAPI void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value )
1388{
1389   OSMesaContext osmesa = OSMesaGetCurrentContext();
1390
1391   switch (pname) {
1392      case OSMESA_WIDTH:
1393         *value = osmesa->width;
1394         return;
1395      case OSMESA_HEIGHT:
1396         *value = osmesa->height;
1397         return;
1398      case OSMESA_FORMAT:
1399         *value = osmesa->format;
1400         return;
1401      case OSMESA_TYPE:
1402         *value = CHAN_TYPE;
1403         return;
1404      case OSMESA_ROW_LENGTH:
1405         *value = osmesa->userRowLength;
1406         return;
1407      case OSMESA_Y_UP:
1408         *value = osmesa->yup;
1409         return;
1410      case OSMESA_MAX_WIDTH:
1411         *value = MAX_WIDTH;
1412         return;
1413      case OSMESA_MAX_HEIGHT:
1414         *value = MAX_HEIGHT;
1415         return;
1416      default:
1417         _mesa_error(&osmesa->gl_ctx, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
1418         return;
1419   }
1420}
1421
1422/*
1423 * Return the depth buffer associated with an OSMesa context.
1424 * Input:  c - the OSMesa context
1425 * Output:  width, height - size of buffer in pixels
1426 *          bytesPerValue - bytes per depth value (2 or 4)
1427 *          buffer - pointer to depth buffer values
1428 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1429 */
1430GLAPI GLboolean GLAPIENTRY
1431OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
1432                      GLint *bytesPerValue, void **buffer )
1433{
1434   if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) {
1435      *width = 0;
1436      *height = 0;
1437      *bytesPerValue = 0;
1438      *buffer = 0;
1439      return GL_FALSE;
1440   }
1441   else {
1442      *width = c->gl_buffer->Width;
1443      *height = c->gl_buffer->Height;
1444      if (c->gl_visual->depthBits <= 16)
1445         *bytesPerValue = sizeof(GLushort);
1446      else
1447         *bytesPerValue = sizeof(GLuint);
1448      *buffer = c->gl_buffer->DepthBuffer;
1449      return GL_TRUE;
1450   }
1451}
1452
1453/*
1454 * Return the color buffer associated with an OSMesa context.
1455 * Input:  c - the OSMesa context
1456 * Output:  width, height - size of buffer in pixels
1457 *          format - the pixel format (OSMESA_FORMAT)
1458 *          buffer - pointer to color buffer values
1459 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1460 */
1461GLAPI GLboolean GLAPIENTRY
1462OSMesaGetColorBuffer( OSMesaContext c, GLint *width,
1463                      GLint *height, GLint *format, void **buffer )
1464{
1465   if (!c->buffer) {
1466      *width = 0;
1467      *height = 0;
1468      *format = 0;
1469      *buffer = 0;
1470      return GL_FALSE;
1471   }
1472   else {
1473      *width = c->width;
1474      *height = c->height;
1475      *format = c->format;
1476      *buffer = c->buffer;
1477      return GL_TRUE;
1478   }
1479}
1480
1481
1482
1483struct name_address {
1484   const char *Name;
1485   GLvoid *Address;
1486};
1487
1488static struct name_address functions[] = {
1489   { "OSMesaCreateContext", (void *) OSMesaCreateContext },
1490   { "OSMesaCreateContextExt", (void *) OSMesaCreateContextExt },
1491   { "OSMesaDestroyContext", (void *) OSMesaDestroyContext },
1492   { "OSMesaMakeCurrent", (void *) OSMesaMakeCurrent },
1493   { "OSMesaGetCurrentContext", (void *) OSMesaGetCurrentContext },
1494   { "OSMesaPixelsStore", (void *) OSMesaPixelStore },
1495   { "OSMesaGetIntegerv", (void *) OSMesaGetIntegerv },
1496   { "OSMesaGetDepthBuffer", (void *) OSMesaGetDepthBuffer },
1497   { "OSMesaGetColorBuffer", (void *) OSMesaGetColorBuffer },
1498   { "OSMesaGetProcAddress", (void *) OSMesaGetProcAddress },
1499   { NULL, NULL }
1500};
1501
1502GLAPI void * GLAPIENTRY
1503OSMesaGetProcAddress( const char *funcName )
1504{
1505   int i;
1506   for (i = 0; functions[i].Name; i++) {
1507      if (_mesa_strcmp(functions[i].Name, funcName) == 0)
1508         return (void *) functions[i].Address;
1509   }
1510   return (void *) _glapi_get_proc_address(funcName);
1511}
1512