osmesa.c revision 48f5deab94be832a782a440f55a7bc742d50a62f
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.5.1
4 *
5 * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26/*
27 * Off-Screen Mesa rendering / Rendering into client memory space
28 *
29 * Note on thread safety:  this driver is thread safe.  All
30 * functions are reentrant.  The notion of current context is
31 * managed by the core _mesa_make_current() and _mesa_get_current_context()
32 * functions.  Those functions are thread-safe.
33 */
34
35
36#include "glheader.h"
37#include "GL/osmesa.h"
38#include "context.h"
39#include "extensions.h"
40#include "framebuffer.h"
41#include "imports.h"
42#include "mtypes.h"
43#include "renderbuffer.h"
44#include "swrast/swrast.h"
45#include "swrast_setup/swrast_setup.h"
46#include "swrast/s_context.h"
47#include "swrast/s_lines.h"
48#include "swrast/s_triangle.h"
49#include "tnl/tnl.h"
50#include "tnl/t_context.h"
51#include "tnl/t_pipeline.h"
52#include "drivers/common/driverfuncs.h"
53#include "vbo/vbo.h"
54
55
56
57/**
58 * OSMesa rendering context, derived from core Mesa GLcontext.
59 */
60struct osmesa_context
61{
62   GLcontext mesa;		/*< Base class - this must be first */
63   GLvisual *gl_visual;		/*< Describes the buffers */
64   struct gl_renderbuffer *rb;  /*< The user's colorbuffer */
65   GLframebuffer *gl_buffer;	/*< The framebuffer, containing user's rb */
66   GLenum format;		/*< User-specified context format */
67   GLint userRowLength;		/*< user-specified number of pixels per row */
68   GLint rInd, gInd, bInd, aInd;/*< index offsets for RGBA formats */
69   GLvoid *rowaddr[MAX_HEIGHT];	/*< address of first pixel in each image row */
70   GLboolean yup;		/*< TRUE  -> Y increases upward */
71				/*< FALSE -> Y increases downward */
72};
73
74
75static INLINE OSMesaContext
76OSMESA_CONTEXT(GLcontext *ctx)
77{
78   /* Just cast, since we're using structure containment */
79   return (OSMesaContext) ctx;
80}
81
82
83/**********************************************************************/
84/*** Private Device Driver Functions                                ***/
85/**********************************************************************/
86
87
88static const GLubyte *
89get_string( GLcontext *ctx, GLenum name )
90{
91   (void) ctx;
92   switch (name) {
93      case GL_RENDERER:
94#if CHAN_BITS == 32
95         return (const GLubyte *) "Mesa OffScreen32";
96#elif CHAN_BITS == 16
97         return (const GLubyte *) "Mesa OffScreen16";
98#else
99         return (const GLubyte *) "Mesa OffScreen";
100#endif
101      default:
102         return NULL;
103   }
104}
105
106
107static void
108osmesa_update_state( GLcontext *ctx, GLuint new_state )
109{
110   /* easy - just propogate */
111   _swrast_InvalidateState( ctx, new_state );
112   _swsetup_InvalidateState( ctx, new_state );
113   _tnl_InvalidateState( ctx, new_state );
114   _vbo_InvalidateState( ctx, new_state );
115}
116
117
118
119/**********************************************************************/
120/*****        Read/write spans/arrays of pixels                   *****/
121/**********************************************************************/
122
123/* 8-bit RGBA */
124#define NAME(PREFIX) PREFIX##_RGBA8
125#define RB_TYPE GLubyte
126#define SPAN_VARS \
127   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
128#define INIT_PIXEL_PTR(P, X, Y) \
129   GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X)
130#define INC_PIXEL_PTR(P) P += 4
131#define STORE_PIXEL(DST, X, Y, VALUE) \
132   DST[0] = VALUE[RCOMP];  \
133   DST[1] = VALUE[GCOMP];  \
134   DST[2] = VALUE[BCOMP];  \
135   DST[3] = VALUE[ACOMP]
136#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
137   DST[0] = VALUE[RCOMP];  \
138   DST[1] = VALUE[GCOMP];  \
139   DST[2] = VALUE[BCOMP];  \
140   DST[3] = 255
141#define FETCH_PIXEL(DST, SRC) \
142   DST[RCOMP] = SRC[0];  \
143   DST[GCOMP] = SRC[1];  \
144   DST[BCOMP] = SRC[2];  \
145   DST[ACOMP] = SRC[3]
146#include "swrast/s_spantemp.h"
147
148/* 16-bit RGBA */
149#define NAME(PREFIX) PREFIX##_RGBA16
150#define RB_TYPE GLushort
151#define SPAN_VARS \
152   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
153#define INIT_PIXEL_PTR(P, X, Y) \
154   GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X)
155#define INC_PIXEL_PTR(P) P += 4
156#define STORE_PIXEL(DST, X, Y, VALUE) \
157   DST[0] = VALUE[RCOMP];  \
158   DST[1] = VALUE[GCOMP];  \
159   DST[2] = VALUE[BCOMP];  \
160   DST[3] = VALUE[ACOMP]
161#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
162   DST[0] = VALUE[RCOMP];  \
163   DST[1] = VALUE[GCOMP];  \
164   DST[2] = VALUE[BCOMP];  \
165   DST[3] = 65535
166#define FETCH_PIXEL(DST, SRC) \
167   DST[RCOMP] = SRC[0];  \
168   DST[GCOMP] = SRC[1];  \
169   DST[BCOMP] = SRC[2];  \
170   DST[ACOMP] = SRC[3]
171#include "swrast/s_spantemp.h"
172
173/* 32-bit RGBA */
174#define NAME(PREFIX) PREFIX##_RGBA32
175#define RB_TYPE GLfloat
176#define SPAN_VARS \
177   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
178#define INIT_PIXEL_PTR(P, X, Y) \
179   GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X)
180#define INC_PIXEL_PTR(P) P += 4
181#define STORE_PIXEL(DST, X, Y, VALUE) \
182   DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \
183   DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \
184   DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \
185   DST[3] = CLAMP((VALUE[ACOMP]), 0.0F, 1.0F)
186#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
187   DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \
188   DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \
189   DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \
190   DST[3] = 1.0F
191#define FETCH_PIXEL(DST, SRC) \
192   DST[RCOMP] = SRC[0];  \
193   DST[GCOMP] = SRC[1];  \
194   DST[BCOMP] = SRC[2];  \
195   DST[ACOMP] = SRC[3]
196#include "swrast/s_spantemp.h"
197
198
199/* 8-bit BGRA */
200#define NAME(PREFIX) PREFIX##_BGRA8
201#define RB_TYPE GLubyte
202#define SPAN_VARS \
203   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
204#define INIT_PIXEL_PTR(P, X, Y) \
205   GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X)
206#define INC_PIXEL_PTR(P) P += 4
207#define STORE_PIXEL(DST, X, Y, VALUE) \
208   DST[2] = VALUE[RCOMP];  \
209   DST[1] = VALUE[GCOMP];  \
210   DST[0] = VALUE[BCOMP];  \
211   DST[3] = VALUE[ACOMP]
212#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
213   DST[2] = VALUE[RCOMP];  \
214   DST[1] = VALUE[GCOMP];  \
215   DST[0] = VALUE[BCOMP];  \
216   DST[3] = 255
217#define FETCH_PIXEL(DST, SRC) \
218   DST[RCOMP] = SRC[2];  \
219   DST[GCOMP] = SRC[1];  \
220   DST[BCOMP] = SRC[0];  \
221   DST[ACOMP] = SRC[3]
222#include "swrast/s_spantemp.h"
223
224/* 16-bit BGRA */
225#define NAME(PREFIX) PREFIX##_BGRA16
226#define RB_TYPE GLushort
227#define SPAN_VARS \
228   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
229#define INIT_PIXEL_PTR(P, X, Y) \
230   GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X)
231#define INC_PIXEL_PTR(P) P += 4
232#define STORE_PIXEL(DST, X, Y, VALUE) \
233   DST[2] = VALUE[RCOMP];  \
234   DST[1] = VALUE[GCOMP];  \
235   DST[0] = VALUE[BCOMP];  \
236   DST[3] = VALUE[ACOMP]
237#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
238   DST[2] = VALUE[RCOMP];  \
239   DST[1] = VALUE[GCOMP];  \
240   DST[0] = VALUE[BCOMP];  \
241   DST[3] = 65535
242#define FETCH_PIXEL(DST, SRC) \
243   DST[RCOMP] = SRC[2];  \
244   DST[GCOMP] = SRC[1];  \
245   DST[BCOMP] = SRC[0];  \
246   DST[ACOMP] = SRC[3]
247#include "swrast/s_spantemp.h"
248
249/* 32-bit BGRA */
250#define NAME(PREFIX) PREFIX##_BGRA32
251#define RB_TYPE GLfloat
252#define SPAN_VARS \
253   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
254#define INIT_PIXEL_PTR(P, X, Y) \
255   GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X)
256#define INC_PIXEL_PTR(P) P += 4
257#define STORE_PIXEL(DST, X, Y, VALUE) \
258   DST[2] = VALUE[RCOMP];  \
259   DST[1] = VALUE[GCOMP];  \
260   DST[0] = VALUE[BCOMP];  \
261   DST[3] = VALUE[ACOMP]
262#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
263   DST[2] = VALUE[RCOMP];  \
264   DST[1] = VALUE[GCOMP];  \
265   DST[0] = VALUE[BCOMP];  \
266   DST[3] = 1.0F
267#define FETCH_PIXEL(DST, SRC) \
268   DST[RCOMP] = SRC[2];  \
269   DST[GCOMP] = SRC[1];  \
270   DST[BCOMP] = SRC[0];  \
271   DST[ACOMP] = SRC[3]
272#include "swrast/s_spantemp.h"
273
274
275/* 8-bit ARGB */
276#define NAME(PREFIX) PREFIX##_ARGB8
277#define RB_TYPE GLubyte
278#define SPAN_VARS \
279   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
280#define INIT_PIXEL_PTR(P, X, Y) \
281   GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X)
282#define INC_PIXEL_PTR(P) P += 4
283#define STORE_PIXEL(DST, X, Y, VALUE) \
284   DST[1] = VALUE[RCOMP];  \
285   DST[2] = VALUE[GCOMP];  \
286   DST[3] = VALUE[BCOMP];  \
287   DST[0] = VALUE[ACOMP]
288#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
289   DST[1] = VALUE[RCOMP];  \
290   DST[2] = VALUE[GCOMP];  \
291   DST[3] = VALUE[BCOMP];  \
292   DST[0] = 255
293#define FETCH_PIXEL(DST, SRC) \
294   DST[RCOMP] = SRC[1];  \
295   DST[GCOMP] = SRC[2];  \
296   DST[BCOMP] = SRC[3];  \
297   DST[ACOMP] = SRC[0]
298#include "swrast/s_spantemp.h"
299
300/* 16-bit ARGB */
301#define NAME(PREFIX) PREFIX##_ARGB16
302#define RB_TYPE GLushort
303#define SPAN_VARS \
304   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
305#define INIT_PIXEL_PTR(P, X, Y) \
306   GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X)
307#define INC_PIXEL_PTR(P) P += 4
308#define STORE_PIXEL(DST, X, Y, VALUE) \
309   DST[1] = VALUE[RCOMP];  \
310   DST[2] = VALUE[GCOMP];  \
311   DST[3] = VALUE[BCOMP];  \
312   DST[0] = VALUE[ACOMP]
313#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
314   DST[1] = VALUE[RCOMP];  \
315   DST[2] = VALUE[GCOMP];  \
316   DST[3] = VALUE[BCOMP];  \
317   DST[0] = 65535
318#define FETCH_PIXEL(DST, SRC) \
319   DST[RCOMP] = SRC[1];  \
320   DST[GCOMP] = SRC[2];  \
321   DST[BCOMP] = SRC[3];  \
322   DST[ACOMP] = SRC[0]
323#include "swrast/s_spantemp.h"
324
325/* 32-bit ARGB */
326#define NAME(PREFIX) PREFIX##_ARGB32
327#define RB_TYPE GLfloat
328#define SPAN_VARS \
329   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
330#define INIT_PIXEL_PTR(P, X, Y) \
331   GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X)
332#define INC_PIXEL_PTR(P) P += 4
333#define STORE_PIXEL(DST, X, Y, VALUE) \
334   DST[1] = VALUE[RCOMP];  \
335   DST[2] = VALUE[GCOMP];  \
336   DST[3] = VALUE[BCOMP];  \
337   DST[0] = VALUE[ACOMP]
338#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
339   DST[1] = VALUE[RCOMP];  \
340   DST[2] = VALUE[GCOMP];  \
341   DST[3] = VALUE[BCOMP];  \
342   DST[0] = 1.0F
343#define FETCH_PIXEL(DST, SRC) \
344   DST[RCOMP] = SRC[1];  \
345   DST[GCOMP] = SRC[2];  \
346   DST[BCOMP] = SRC[3];  \
347   DST[ACOMP] = SRC[0]
348#include "swrast/s_spantemp.h"
349
350
351/* 8-bit RGB */
352#define NAME(PREFIX) PREFIX##_RGB8
353#define RB_TYPE GLubyte
354#define SPAN_VARS \
355   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
356#define INIT_PIXEL_PTR(P, X, Y) \
357   GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 3 * (X)
358#define INC_PIXEL_PTR(P) P += 3
359#define STORE_PIXEL(DST, X, Y, VALUE) \
360   DST[0] = VALUE[RCOMP];  \
361   DST[1] = VALUE[GCOMP];  \
362   DST[2] = VALUE[BCOMP]
363#define FETCH_PIXEL(DST, SRC) \
364   DST[RCOMP] = SRC[0];  \
365   DST[GCOMP] = SRC[1];  \
366   DST[BCOMP] = SRC[2];  \
367   DST[ACOMP] = 255
368#include "swrast/s_spantemp.h"
369
370/* 16-bit RGB */
371#define NAME(PREFIX) PREFIX##_RGB16
372#define RB_TYPE GLushort
373#define SPAN_VARS \
374   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
375#define INIT_PIXEL_PTR(P, X, Y) \
376   GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 3 * (X)
377#define INC_PIXEL_PTR(P) P += 3
378#define STORE_PIXEL(DST, X, Y, VALUE) \
379   DST[0] = VALUE[RCOMP];  \
380   DST[1] = VALUE[GCOMP];  \
381   DST[2] = VALUE[BCOMP]
382#define FETCH_PIXEL(DST, SRC) \
383   DST[RCOMP] = SRC[0];  \
384   DST[GCOMP] = SRC[1];  \
385   DST[BCOMP] = SRC[2];  \
386   DST[ACOMP] = 65535U
387#include "swrast/s_spantemp.h"
388
389/* 32-bit RGB */
390#define NAME(PREFIX) PREFIX##_RGB32
391#define RB_TYPE GLfloat
392#define SPAN_VARS \
393   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
394#define INIT_PIXEL_PTR(P, X, Y) \
395   GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 3 * (X)
396#define INC_PIXEL_PTR(P) P += 3
397#define STORE_PIXEL(DST, X, Y, VALUE) \
398   DST[0] = VALUE[RCOMP];  \
399   DST[1] = VALUE[GCOMP];  \
400   DST[2] = VALUE[BCOMP]
401#define FETCH_PIXEL(DST, SRC) \
402   DST[RCOMP] = SRC[0];  \
403   DST[GCOMP] = SRC[1];  \
404   DST[BCOMP] = SRC[2];  \
405   DST[ACOMP] = 1.0F
406#include "swrast/s_spantemp.h"
407
408
409/* 8-bit BGR */
410#define NAME(PREFIX) PREFIX##_BGR8
411#define RB_TYPE GLubyte
412#define SPAN_VARS \
413   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
414#define INIT_PIXEL_PTR(P, X, Y) \
415   GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 3 * (X)
416#define INC_PIXEL_PTR(P) P += 3
417#define STORE_PIXEL(DST, X, Y, VALUE) \
418   DST[2] = VALUE[RCOMP];  \
419   DST[1] = VALUE[GCOMP];  \
420   DST[0] = VALUE[BCOMP]
421#define FETCH_PIXEL(DST, SRC) \
422   DST[RCOMP] = SRC[2];  \
423   DST[GCOMP] = SRC[1];  \
424   DST[BCOMP] = SRC[0];  \
425   DST[ACOMP] = 255
426#include "swrast/s_spantemp.h"
427
428/* 16-bit BGR */
429#define NAME(PREFIX) PREFIX##_BGR16
430#define RB_TYPE GLushort
431#define SPAN_VARS \
432   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
433#define INIT_PIXEL_PTR(P, X, Y) \
434   GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 3 * (X)
435#define INC_PIXEL_PTR(P) P += 3
436#define STORE_PIXEL(DST, X, Y, VALUE) \
437   DST[2] = VALUE[RCOMP];  \
438   DST[1] = VALUE[GCOMP];  \
439   DST[0] = VALUE[BCOMP]
440#define FETCH_PIXEL(DST, SRC) \
441   DST[RCOMP] = SRC[2];  \
442   DST[GCOMP] = SRC[1];  \
443   DST[BCOMP] = SRC[0];  \
444   DST[ACOMP] = 65535
445#include "swrast/s_spantemp.h"
446
447/* 32-bit BGR */
448#define NAME(PREFIX) PREFIX##_BGR32
449#define RB_TYPE GLfloat
450#define SPAN_VARS \
451   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
452#define INIT_PIXEL_PTR(P, X, Y) \
453   GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 3 * (X)
454#define INC_PIXEL_PTR(P) P += 3
455#define STORE_PIXEL(DST, X, Y, VALUE) \
456   DST[2] = VALUE[RCOMP];  \
457   DST[1] = VALUE[GCOMP];  \
458   DST[0] = VALUE[BCOMP]
459#define FETCH_PIXEL(DST, SRC) \
460   DST[RCOMP] = SRC[2];  \
461   DST[GCOMP] = SRC[1];  \
462   DST[BCOMP] = SRC[0];  \
463   DST[ACOMP] = 1.0F
464#include "swrast/s_spantemp.h"
465
466
467/* 16-bit 5/6/5 RGB */
468#define NAME(PREFIX) PREFIX##_RGB_565
469#define RB_TYPE GLubyte
470#define SPAN_VARS \
471   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
472#define INIT_PIXEL_PTR(P, X, Y) \
473   GLushort *P = (GLushort *) osmesa->rowaddr[Y] + (X)
474#define INC_PIXEL_PTR(P) P += 1
475#define STORE_PIXEL(DST, X, Y, VALUE) \
476   *DST = ( (((VALUE[RCOMP]) & 0xf8) << 8) | (((VALUE[GCOMP]) & 0xfc) << 3) | ((VALUE[BCOMP]) >> 3) )
477#define FETCH_PIXEL(DST, SRC) \
478   DST[RCOMP] = ( (((*SRC) >> 8) & 0xf8) | (((*SRC) >> 11) & 0x7) ); \
479   DST[GCOMP] = ( (((*SRC) >> 3) & 0xfc) | (((*SRC) >>  5) & 0x3) ); \
480   DST[BCOMP] = ( (((*SRC) << 3) & 0xf8) | (((*SRC)      ) & 0x7) ); \
481   DST[ACOMP] = CHAN_MAX
482#include "swrast/s_spantemp.h"
483
484
485/* color index */
486#define NAME(PREFIX) PREFIX##_CI
487#define CI_MODE
488#define RB_TYPE GLubyte
489#define SPAN_VARS \
490   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
491#define INIT_PIXEL_PTR(P, X, Y) \
492   GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + (X)
493#define INC_PIXEL_PTR(P) P += 1
494#define STORE_PIXEL(DST, X, Y, VALUE) \
495   *DST = VALUE[0]
496#define FETCH_PIXEL(DST, SRC) \
497   DST = SRC[0]
498#include "swrast/s_spantemp.h"
499
500
501
502
503/**
504 * Macros for optimized line/triangle rendering.
505 * Only for 8-bit channel, RGBA, BGRA, ARGB formats.
506 */
507
508#define PACK_RGBA(DST, R, G, B, A)	\
509do {					\
510   (DST)[osmesa->rInd] = R;		\
511   (DST)[osmesa->gInd] = G;		\
512   (DST)[osmesa->bInd] = B;		\
513   (DST)[osmesa->aInd] = A;		\
514} while (0)
515
516#define PIXELADDR4(X,Y)  ((GLchan *) osmesa->rowaddr[Y] + 4 * (X))
517
518
519/**
520 * Draw a flat-shaded, RGB line into an osmesa buffer.
521 */
522#define NAME flat_rgba_line
523#define CLIP_HACK 1
524#define SETUP_CODE						\
525   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);		\
526   const GLchan *color = vert1->color;
527
528#define PLOT(X, Y)						\
529do {								\
530   GLchan *p = PIXELADDR4(X, Y);				\
531   PACK_RGBA(p, color[0], color[1], color[2], color[3]);	\
532} while (0)
533
534#ifdef WIN32
535#include "..\swrast\s_linetemp.h"
536#else
537#include "swrast/s_linetemp.h"
538#endif
539
540
541
542/**
543 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
544 */
545#define NAME flat_rgba_z_line
546#define CLIP_HACK 1
547#define INTERP_Z 1
548#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
549#define SETUP_CODE					\
550   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);	\
551   const GLchan *color = vert1->color;
552
553#define PLOT(X, Y)					\
554do {							\
555   if (Z < *zPtr) {					\
556      GLchan *p = PIXELADDR4(X, Y);			\
557      PACK_RGBA(p, color[RCOMP], color[GCOMP],		\
558                   color[BCOMP], color[ACOMP]);		\
559      *zPtr = Z;					\
560   }							\
561} while (0)
562
563#ifdef WIN32
564#include "..\swrast\s_linetemp.h"
565#else
566#include "swrast/s_linetemp.h"
567#endif
568
569
570
571/**
572 * Analyze context state to see if we can provide a fast line drawing
573 * function.  Otherwise, return NULL.
574 */
575static swrast_line_func
576osmesa_choose_line_function( GLcontext *ctx )
577{
578   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
579   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
580
581   if (osmesa->rb->DataType != GL_UNSIGNED_BYTE)
582      return NULL;
583
584   if (ctx->RenderMode != GL_RENDER)      return NULL;
585   if (ctx->Line.SmoothFlag)              return NULL;
586   if (ctx->Texture._EnabledUnits)        return NULL;
587   if (ctx->Light.ShadeModel != GL_FLAT)  return NULL;
588   if (ctx->Line.Width != 1.0F)           return NULL;
589   if (ctx->Line.StippleFlag)             return NULL;
590   if (ctx->Line.SmoothFlag)              return NULL;
591   if (osmesa->format != OSMESA_RGBA &&
592       osmesa->format != OSMESA_BGRA &&
593       osmesa->format != OSMESA_ARGB)     return NULL;
594
595   if (swrast->_RasterMask==DEPTH_BIT
596       && ctx->Depth.Func==GL_LESS
597       && ctx->Depth.Mask==GL_TRUE
598       && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
599      return (swrast_line_func) flat_rgba_z_line;
600   }
601
602   if (swrast->_RasterMask == 0) {
603      return (swrast_line_func) flat_rgba_line;
604   }
605
606   return (swrast_line_func) NULL;
607}
608
609
610/**********************************************************************/
611/*****                 Optimized triangle rendering               *****/
612/**********************************************************************/
613
614
615/*
616 * Smooth-shaded, z-less triangle, RGBA color.
617 */
618#define NAME smooth_rgba_z_triangle
619#define INTERP_Z 1
620#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
621#define INTERP_RGB 1
622#define INTERP_ALPHA 1
623#define SETUP_CODE \
624   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
625#define RENDER_SPAN( span ) {					\
626   GLuint i;							\
627   GLchan *img = PIXELADDR4(span.x, span.y); 			\
628   for (i = 0; i < span.end; i++, img += 4) {			\
629      const GLuint z = FixedToDepth(span.z);			\
630      if (z < zRow[i]) {					\
631         PACK_RGBA(img, FixedToChan(span.red),			\
632            FixedToChan(span.green), FixedToChan(span.blue),	\
633            FixedToChan(span.alpha));				\
634         zRow[i] = z;						\
635      }								\
636      span.red += span.redStep;					\
637      span.green += span.greenStep;				\
638      span.blue += span.blueStep;				\
639      span.alpha += span.alphaStep;				\
640      span.z += span.zStep;					\
641   }                                                            \
642}
643#ifdef WIN32
644#include "..\swrast\s_tritemp.h"
645#else
646#include "swrast/s_tritemp.h"
647#endif
648
649
650
651/*
652 * Flat-shaded, z-less triangle, RGBA color.
653 */
654#define NAME flat_rgba_z_triangle
655#define INTERP_Z 1
656#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
657#define SETUP_CODE						\
658   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);		\
659   GLuint pixel;						\
660   PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1],	\
661                                v2->color[2], v2->color[3]);
662
663#define RENDER_SPAN( span ) {				\
664   GLuint i;						\
665   GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y);	\
666   for (i = 0; i < span.end; i++) {			\
667      const GLuint z = FixedToDepth(span.z);		\
668      if (z < zRow[i]) {				\
669         img[i] = pixel;				\
670         zRow[i] = z;					\
671      }							\
672      span.z += span.zStep;				\
673   }                                                    \
674}
675#ifdef WIN32
676#include "..\swrast\s_tritemp.h"
677#else
678#include "swrast/s_tritemp.h"
679#endif
680
681
682
683/**
684 * Return pointer to an optimized triangle function if possible.
685 */
686static swrast_tri_func
687osmesa_choose_triangle_function( GLcontext *ctx )
688{
689   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
690   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
691
692   if (osmesa->rb->DataType != GL_UNSIGNED_BYTE)
693      return (swrast_tri_func) NULL;
694
695   if (ctx->RenderMode != GL_RENDER)    return (swrast_tri_func) NULL;
696   if (ctx->Polygon.SmoothFlag)         return (swrast_tri_func) NULL;
697   if (ctx->Polygon.StippleFlag)        return (swrast_tri_func) NULL;
698   if (ctx->Texture._EnabledUnits)      return (swrast_tri_func) NULL;
699   if (osmesa->format != OSMESA_RGBA &&
700       osmesa->format != OSMESA_BGRA &&
701       osmesa->format != OSMESA_ARGB)   return (swrast_tri_func) NULL;
702   if (ctx->Polygon.CullFlag &&
703       ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
704                                        return (swrast_tri_func) NULL;
705
706   if (swrast->_RasterMask == DEPTH_BIT &&
707       ctx->Depth.Func == GL_LESS &&
708       ctx->Depth.Mask == GL_TRUE &&
709       ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
710      if (ctx->Light.ShadeModel == GL_SMOOTH) {
711         return (swrast_tri_func) smooth_rgba_z_triangle;
712      }
713      else {
714         return (swrast_tri_func) flat_rgba_z_triangle;
715      }
716   }
717   return (swrast_tri_func) NULL;
718}
719
720
721
722/* Override for the swrast triangle-selection function.  Try to use one
723 * of our internal triangle functions, otherwise fall back to the
724 * standard swrast functions.
725 */
726static void
727osmesa_choose_triangle( GLcontext *ctx )
728{
729   SWcontext *swrast = SWRAST_CONTEXT(ctx);
730
731   swrast->Triangle = osmesa_choose_triangle_function( ctx );
732   if (!swrast->Triangle)
733      _swrast_choose_triangle( ctx );
734}
735
736static void
737osmesa_choose_line( GLcontext *ctx )
738{
739   SWcontext *swrast = SWRAST_CONTEXT(ctx);
740
741   swrast->Line = osmesa_choose_line_function( ctx );
742   if (!swrast->Line)
743      _swrast_choose_line( ctx );
744}
745
746
747
748/**
749 * Recompute the values of the context's rowaddr array.
750 */
751static void
752compute_row_addresses( OSMesaContext osmesa )
753{
754   GLint bytesPerPixel, bytesPerRow, i;
755   GLubyte *origin = (GLubyte *) osmesa->rb->Data;
756   GLint bpc; /* bytes per channel */
757   GLint rowlength; /* in pixels */
758   GLint height = osmesa->rb->Height;
759
760   if (osmesa->userRowLength)
761      rowlength = osmesa->userRowLength;
762   else
763      rowlength = osmesa->rb->Width;
764
765   if (osmesa->rb->DataType == GL_UNSIGNED_BYTE)
766      bpc = 1;
767   else if (osmesa->rb->DataType == GL_UNSIGNED_SHORT)
768      bpc = 2;
769   else if (osmesa->rb->DataType == GL_FLOAT)
770      bpc = 4;
771   else {
772      _mesa_problem(&osmesa->mesa,
773                    "Unexpected datatype in osmesa::compute_row_addresses");
774      return;
775   }
776
777   if (osmesa->format == OSMESA_COLOR_INDEX) {
778      /* CI mode */
779      bytesPerPixel = 1 * sizeof(GLubyte);
780   }
781   else if ((osmesa->format == OSMESA_RGB) || (osmesa->format == OSMESA_BGR)) {
782      /* RGB mode */
783      bytesPerPixel = 3 * bpc;
784   }
785   else if (osmesa->format == OSMESA_RGB_565) {
786      /* 5/6/5 RGB pixel in 16 bits */
787      bytesPerPixel = 2;
788   }
789   else {
790      /* RGBA mode */
791      bytesPerPixel = 4 * bpc;
792   }
793
794   bytesPerRow = rowlength * bytesPerPixel;
795
796   if (osmesa->yup) {
797      /* Y=0 is bottom line of window */
798      for (i = 0; i < height; i++) {
799         osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + i * bytesPerRow);
800      }
801   }
802   else {
803      /* Y=0 is top line of window */
804      for (i = 0; i < height; i++) {
805         GLint j = height - i - 1;
806         osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + j * bytesPerRow);
807      }
808   }
809}
810
811
812
813/**
814 * Don't use _mesa_delete_renderbuffer since we can't free rb->Data.
815 */
816static void
817osmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
818{
819   _mesa_free(rb);
820}
821
822
823/**
824 * Allocate renderbuffer storage.  We don't actually allocate any storage
825 * since we're using a user-provided buffer.
826 * Just set up all the gl_renderbuffer methods.
827 */
828static GLboolean
829osmesa_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
830                            GLenum internalFormat, GLuint width, GLuint height)
831{
832   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
833   GLint bpc; /* bits per channel */
834
835   if (rb->DataType == GL_UNSIGNED_BYTE)
836      bpc = 8;
837   else if (rb->DataType == GL_UNSIGNED_SHORT)
838      bpc = 16;
839   else
840      bpc = 32;
841
842   rb->RedBits =
843   rb->GreenBits =
844   rb->BlueBits =
845   rb->AlphaBits = bpc;
846
847   /* Note: we can ignoring internalFormat for "window-system" renderbuffers */
848   (void) internalFormat;
849
850   if (osmesa->format == OSMESA_RGBA) {
851      if (rb->DataType == GL_UNSIGNED_BYTE) {
852         rb->GetRow = get_row_RGBA8;
853         rb->GetValues = get_values_RGBA8;
854         rb->PutRow = put_row_RGBA8;
855         rb->PutRowRGB = put_row_rgb_RGBA8;
856         rb->PutMonoRow = put_mono_row_RGBA8;
857         rb->PutValues = put_values_RGBA8;
858         rb->PutMonoValues = put_mono_values_RGBA8;
859      }
860      else if (rb->DataType == GL_UNSIGNED_SHORT) {
861         rb->GetRow = get_row_RGBA16;
862         rb->GetValues = get_values_RGBA16;
863         rb->PutRow = put_row_RGBA16;
864         rb->PutRowRGB = put_row_rgb_RGBA16;
865         rb->PutMonoRow = put_mono_row_RGBA16;
866         rb->PutValues = put_values_RGBA16;
867         rb->PutMonoValues = put_mono_values_RGBA16;
868      }
869      else {
870         rb->GetRow = get_row_RGBA32;
871         rb->GetValues = get_values_RGBA32;
872         rb->PutRow = put_row_RGBA32;
873         rb->PutRowRGB = put_row_rgb_RGBA32;
874         rb->PutMonoRow = put_mono_row_RGBA32;
875         rb->PutValues = put_values_RGBA32;
876         rb->PutMonoValues = put_mono_values_RGBA32;
877      }
878      rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = bpc;
879   }
880   else if (osmesa->format == OSMESA_BGRA) {
881      if (rb->DataType == GL_UNSIGNED_BYTE) {
882         rb->GetRow = get_row_BGRA8;
883         rb->GetValues = get_values_BGRA8;
884         rb->PutRow = put_row_BGRA8;
885         rb->PutRowRGB = put_row_rgb_BGRA8;
886         rb->PutMonoRow = put_mono_row_BGRA8;
887         rb->PutValues = put_values_BGRA8;
888         rb->PutMonoValues = put_mono_values_BGRA8;
889      }
890      else if (rb->DataType == GL_UNSIGNED_SHORT) {
891         rb->GetRow = get_row_BGRA16;
892         rb->GetValues = get_values_BGRA16;
893         rb->PutRow = put_row_BGRA16;
894         rb->PutRowRGB = put_row_rgb_BGRA16;
895         rb->PutMonoRow = put_mono_row_BGRA16;
896         rb->PutValues = put_values_BGRA16;
897         rb->PutMonoValues = put_mono_values_BGRA16;
898      }
899      else {
900         rb->GetRow = get_row_BGRA32;
901         rb->GetValues = get_values_BGRA32;
902         rb->PutRow = put_row_BGRA32;
903         rb->PutRowRGB = put_row_rgb_BGRA32;
904         rb->PutMonoRow = put_mono_row_BGRA32;
905         rb->PutValues = put_values_BGRA32;
906         rb->PutMonoValues = put_mono_values_BGRA32;
907      }
908      rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = bpc;
909   }
910   else if (osmesa->format == OSMESA_ARGB) {
911      if (rb->DataType == GL_UNSIGNED_BYTE) {
912         rb->GetRow = get_row_ARGB8;
913         rb->GetValues = get_values_ARGB8;
914         rb->PutRow = put_row_ARGB8;
915         rb->PutRowRGB = put_row_rgb_ARGB8;
916         rb->PutMonoRow = put_mono_row_ARGB8;
917         rb->PutValues = put_values_ARGB8;
918         rb->PutMonoValues = put_mono_values_ARGB8;
919      }
920      else if (rb->DataType == GL_UNSIGNED_SHORT) {
921         rb->GetRow = get_row_ARGB16;
922         rb->GetValues = get_values_ARGB16;
923         rb->PutRow = put_row_ARGB16;
924         rb->PutRowRGB = put_row_rgb_ARGB16;
925         rb->PutMonoRow = put_mono_row_ARGB16;
926         rb->PutValues = put_values_ARGB16;
927         rb->PutMonoValues = put_mono_values_ARGB16;
928      }
929      else {
930         rb->GetRow = get_row_ARGB32;
931         rb->GetValues = get_values_ARGB32;
932         rb->PutRow = put_row_ARGB32;
933         rb->PutRowRGB = put_row_rgb_ARGB32;
934         rb->PutMonoRow = put_mono_row_ARGB32;
935         rb->PutValues = put_values_ARGB32;
936         rb->PutMonoValues = put_mono_values_ARGB32;
937      }
938      rb->RedBits = rb->GreenBits = rb->BlueBits = rb->AlphaBits = bpc;
939   }
940   else if (osmesa->format == OSMESA_RGB) {
941      if (rb->DataType == GL_UNSIGNED_BYTE) {
942         rb->GetRow = get_row_RGB8;
943         rb->GetValues = get_values_RGB8;
944         rb->PutRow = put_row_RGB8;
945         rb->PutRowRGB = put_row_rgb_RGB8;
946         rb->PutMonoRow = put_mono_row_RGB8;
947         rb->PutValues = put_values_RGB8;
948         rb->PutMonoValues = put_mono_values_RGB8;
949      }
950      else if (rb->DataType == GL_UNSIGNED_SHORT) {
951         rb->GetRow = get_row_RGB16;
952         rb->GetValues = get_values_RGB16;
953         rb->PutRow = put_row_RGB16;
954         rb->PutRowRGB = put_row_rgb_RGB16;
955         rb->PutMonoRow = put_mono_row_RGB16;
956         rb->PutValues = put_values_RGB16;
957         rb->PutMonoValues = put_mono_values_RGB16;
958      }
959      else {
960         rb->GetRow = get_row_RGB32;
961         rb->GetValues = get_values_RGB32;
962         rb->PutRow = put_row_RGB32;
963         rb->PutRowRGB = put_row_rgb_RGB32;
964         rb->PutMonoRow = put_mono_row_RGB32;
965         rb->PutValues = put_values_RGB32;
966         rb->PutMonoValues = put_mono_values_RGB32;
967      }
968      rb->RedBits = rb->GreenBits = rb->BlueBits = bpc;
969   }
970   else if (osmesa->format == OSMESA_BGR) {
971      if (rb->DataType == GL_UNSIGNED_BYTE) {
972         rb->GetRow = get_row_BGR8;
973         rb->GetValues = get_values_BGR8;
974         rb->PutRow = put_row_BGR8;
975         rb->PutRowRGB = put_row_rgb_BGR8;
976         rb->PutMonoRow = put_mono_row_BGR8;
977         rb->PutValues = put_values_BGR8;
978         rb->PutMonoValues = put_mono_values_BGR8;
979      }
980      else if (rb->DataType == GL_UNSIGNED_SHORT) {
981         rb->GetRow = get_row_BGR16;
982         rb->GetValues = get_values_BGR16;
983         rb->PutRow = put_row_BGR16;
984         rb->PutRowRGB = put_row_rgb_BGR16;
985         rb->PutMonoRow = put_mono_row_BGR16;
986         rb->PutValues = put_values_BGR16;
987         rb->PutMonoValues = put_mono_values_BGR16;
988      }
989      else {
990         rb->GetRow = get_row_BGR32;
991         rb->GetValues = get_values_BGR32;
992         rb->PutRow = put_row_BGR32;
993         rb->PutRowRGB = put_row_rgb_BGR32;
994         rb->PutMonoRow = put_mono_row_BGR32;
995         rb->PutValues = put_values_BGR32;
996         rb->PutMonoValues = put_mono_values_BGR32;
997      }
998      rb->RedBits = rb->GreenBits = rb->BlueBits = bpc;
999   }
1000   else if (osmesa->format == OSMESA_RGB_565) {
1001      ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
1002      rb->GetRow = get_row_RGB_565;
1003      rb->GetValues = get_values_RGB_565;
1004      rb->PutRow = put_row_RGB_565;
1005      rb->PutRowRGB = put_row_rgb_RGB_565;
1006      rb->PutMonoRow = put_mono_row_RGB_565;
1007      rb->PutValues = put_values_RGB_565;
1008      rb->PutMonoValues = put_mono_values_RGB_565;
1009      rb->RedBits = 5;
1010      rb->GreenBits = 6;
1011      rb->BlueBits = 5;
1012   }
1013   else if (osmesa->format == OSMESA_COLOR_INDEX) {
1014      rb->GetRow = get_row_CI;
1015      rb->GetValues = get_values_CI;
1016      rb->PutRow = put_row_CI;
1017      rb->PutMonoRow = put_mono_row_CI;
1018      rb->PutValues = put_values_CI;
1019      rb->PutMonoValues = put_mono_values_CI;
1020      rb->IndexBits = 8;
1021   }
1022   else {
1023      _mesa_problem(ctx, "bad pixel format in osmesa renderbuffer_storage");
1024   }
1025
1026   rb->Width = width;
1027   rb->Height = height;
1028
1029   compute_row_addresses( osmesa );
1030
1031   return GL_TRUE;
1032}
1033
1034
1035/**
1036 * Allocate a new renderbuffer to describe the user-provided color buffer.
1037 */
1038static struct gl_renderbuffer *
1039new_osmesa_renderbuffer(GLcontext *ctx, GLenum format, GLenum type)
1040{
1041   const GLuint name = 0;
1042   struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
1043   if (rb) {
1044      rb->Delete = osmesa_delete_renderbuffer;
1045      rb->AllocStorage = osmesa_renderbuffer_storage;
1046
1047      if (format == OSMESA_COLOR_INDEX) {
1048         rb->InternalFormat = GL_COLOR_INDEX;
1049         rb->_ActualFormat = GL_COLOR_INDEX8_EXT;
1050         rb->_BaseFormat = GL_COLOR_INDEX;
1051         rb->DataType = GL_UNSIGNED_BYTE;
1052      }
1053      else {
1054         rb->InternalFormat = GL_RGBA;
1055         rb->_ActualFormat = GL_RGBA;
1056         rb->_BaseFormat = GL_RGBA;
1057         rb->DataType = type;
1058      }
1059   }
1060   return rb;
1061}
1062
1063
1064/**********************************************************************/
1065/*****                    Public Functions                        *****/
1066/**********************************************************************/
1067
1068
1069/**
1070 * Create an Off-Screen Mesa rendering context.  The only attribute needed is
1071 * an RGBA vs Color-Index mode flag.
1072 *
1073 * Input:  format - either GL_RGBA or GL_COLOR_INDEX
1074 *         sharelist - specifies another OSMesaContext with which to share
1075 *                     display lists.  NULL indicates no sharing.
1076 * Return:  an OSMesaContext or 0 if error
1077 */
1078GLAPI OSMesaContext GLAPIENTRY
1079OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
1080{
1081   const GLint accumBits = (format == OSMESA_COLOR_INDEX) ? 0 : 16;
1082   return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS,
1083                                 8, accumBits, sharelist);
1084}
1085
1086
1087
1088/**
1089 * New in Mesa 3.5
1090 *
1091 * Create context and specify size of ancillary buffers.
1092 */
1093GLAPI OSMesaContext GLAPIENTRY
1094OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
1095                        GLint accumBits, OSMesaContext sharelist )
1096{
1097   OSMesaContext osmesa;
1098   struct dd_function_table functions;
1099   GLint rind, gind, bind, aind;
1100   GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
1101   GLboolean rgbmode;
1102   GLenum type = CHAN_TYPE;
1103
1104   rind = gind = bind = aind = 0;
1105   if (format==OSMESA_COLOR_INDEX) {
1106      indexBits = 8;
1107      rgbmode = GL_FALSE;
1108   }
1109   else if (format==OSMESA_RGBA) {
1110      indexBits = 0;
1111      redBits = CHAN_BITS;
1112      greenBits = CHAN_BITS;
1113      blueBits = CHAN_BITS;
1114      alphaBits = CHAN_BITS;
1115      rind = 0;
1116      gind = 1;
1117      bind = 2;
1118      aind = 3;
1119      rgbmode = GL_TRUE;
1120   }
1121   else if (format==OSMESA_BGRA) {
1122      indexBits = 0;
1123      redBits = CHAN_BITS;
1124      greenBits = CHAN_BITS;
1125      blueBits = CHAN_BITS;
1126      alphaBits = CHAN_BITS;
1127      bind = 0;
1128      gind = 1;
1129      rind = 2;
1130      aind = 3;
1131      rgbmode = GL_TRUE;
1132   }
1133   else if (format==OSMESA_ARGB) {
1134      indexBits = 0;
1135      redBits = CHAN_BITS;
1136      greenBits = CHAN_BITS;
1137      blueBits = CHAN_BITS;
1138      alphaBits = CHAN_BITS;
1139      aind = 0;
1140      rind = 1;
1141      gind = 2;
1142      bind = 3;
1143      rgbmode = GL_TRUE;
1144   }
1145   else if (format==OSMESA_RGB) {
1146      indexBits = 0;
1147      redBits = CHAN_BITS;
1148      greenBits = CHAN_BITS;
1149      blueBits = CHAN_BITS;
1150      alphaBits = 0;
1151      rind = 0;
1152      gind = 1;
1153      bind = 2;
1154      rgbmode = GL_TRUE;
1155   }
1156   else if (format==OSMESA_BGR) {
1157      indexBits = 0;
1158      redBits = CHAN_BITS;
1159      greenBits = CHAN_BITS;
1160      blueBits = CHAN_BITS;
1161      alphaBits = 0;
1162      rind = 2;
1163      gind = 1;
1164      bind = 0;
1165      rgbmode = GL_TRUE;
1166   }
1167#if CHAN_TYPE == GL_UNSIGNED_BYTE
1168   else if (format==OSMESA_RGB_565) {
1169      indexBits = 0;
1170      redBits = 5;
1171      greenBits = 6;
1172      blueBits = 5;
1173      alphaBits = 0;
1174      rind = 0; /* not used */
1175      gind = 0;
1176      bind = 0;
1177      rgbmode = GL_TRUE;
1178   }
1179#endif
1180   else {
1181      return NULL;
1182   }
1183
1184   osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
1185   if (osmesa) {
1186      osmesa->gl_visual = _mesa_create_visual( rgbmode,
1187                                               GL_FALSE,    /* double buffer */
1188                                               GL_FALSE,    /* stereo */
1189                                               redBits,
1190                                               greenBits,
1191                                               blueBits,
1192                                               alphaBits,
1193                                               indexBits,
1194                                               depthBits,
1195                                               stencilBits,
1196                                               accumBits,
1197                                               accumBits,
1198                                               accumBits,
1199                                               alphaBits ? accumBits : 0,
1200                                               1            /* num samples */
1201                                               );
1202      if (!osmesa->gl_visual) {
1203         _mesa_free(osmesa);
1204         return NULL;
1205      }
1206
1207      /* Initialize device driver function table */
1208      _mesa_init_driver_functions(&functions);
1209      /* override with our functions */
1210      functions.GetString = get_string;
1211      functions.UpdateState = osmesa_update_state;
1212      functions.GetBufferSize = NULL;
1213
1214      if (!_mesa_initialize_context(&osmesa->mesa,
1215                                    osmesa->gl_visual,
1216                                    sharelist ? &sharelist->mesa
1217                                              : (GLcontext *) NULL,
1218                                    &functions, (void *) osmesa)) {
1219         _mesa_destroy_visual( osmesa->gl_visual );
1220         _mesa_free(osmesa);
1221         return NULL;
1222      }
1223
1224      _mesa_enable_sw_extensions(&(osmesa->mesa));
1225      _mesa_enable_1_3_extensions(&(osmesa->mesa));
1226      _mesa_enable_1_4_extensions(&(osmesa->mesa));
1227      _mesa_enable_1_5_extensions(&(osmesa->mesa));
1228
1229      osmesa->gl_buffer = _mesa_create_framebuffer(osmesa->gl_visual);
1230      if (!osmesa->gl_buffer) {
1231         _mesa_destroy_visual( osmesa->gl_visual );
1232         _mesa_free_context_data( &osmesa->mesa );
1233         _mesa_free(osmesa);
1234         return NULL;
1235      }
1236
1237      /* create front color buffer in user-provided memory (no back buffer) */
1238      osmesa->rb = new_osmesa_renderbuffer(&osmesa->mesa, format, type);
1239      _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, osmesa->rb);
1240
1241      _mesa_add_soft_renderbuffers(osmesa->gl_buffer,
1242                                   GL_FALSE, /* color */
1243                                   osmesa->gl_visual->haveDepthBuffer,
1244                                   osmesa->gl_visual->haveStencilBuffer,
1245                                   osmesa->gl_visual->haveAccumBuffer,
1246                                   GL_FALSE, /* alpha */
1247                                   GL_FALSE /* aux */ );
1248
1249      osmesa->format = format;
1250      osmesa->userRowLength = 0;
1251      osmesa->yup = GL_TRUE;
1252      osmesa->rInd = rind;
1253      osmesa->gInd = gind;
1254      osmesa->bInd = bind;
1255      osmesa->aInd = aind;
1256
1257      /* Initialize the software rasterizer and helper modules. */
1258      {
1259	 GLcontext *ctx = &osmesa->mesa;
1260         SWcontext *swrast;
1261         TNLcontext *tnl;
1262
1263	 if (!_swrast_CreateContext( ctx ) ||
1264             !_vbo_CreateContext( ctx ) ||
1265             !_tnl_CreateContext( ctx ) ||
1266             !_swsetup_CreateContext( ctx )) {
1267            _mesa_destroy_visual(osmesa->gl_visual);
1268            _mesa_free_context_data(ctx);
1269            _mesa_free(osmesa);
1270            return NULL;
1271         }
1272
1273	 _swsetup_Wakeup( ctx );
1274
1275         /* use default TCL pipeline */
1276         tnl = TNL_CONTEXT(ctx);
1277         tnl->Driver.RunPipeline = _tnl_run_pipeline;
1278
1279         /* Extend the software rasterizer with our optimized line and triangle
1280          * drawing functions.
1281          */
1282         swrast = SWRAST_CONTEXT( ctx );
1283         swrast->choose_line = osmesa_choose_line;
1284         swrast->choose_triangle = osmesa_choose_triangle;
1285      }
1286   }
1287   return osmesa;
1288}
1289
1290
1291/**
1292 * Destroy an Off-Screen Mesa rendering context.
1293 *
1294 * \param osmesa  the context to destroy
1295 */
1296GLAPI void GLAPIENTRY
1297OSMesaDestroyContext( OSMesaContext osmesa )
1298{
1299   if (osmesa) {
1300      _swsetup_DestroyContext( &osmesa->mesa );
1301      _tnl_DestroyContext( &osmesa->mesa );
1302      _vbo_DestroyContext( &osmesa->mesa );
1303      _swrast_DestroyContext( &osmesa->mesa );
1304
1305      _mesa_destroy_visual( osmesa->gl_visual );
1306      _mesa_destroy_framebuffer( osmesa->gl_buffer );
1307      _mesa_free_context_data( &osmesa->mesa );
1308      _mesa_free( osmesa );
1309   }
1310}
1311
1312
1313/**
1314 * Bind an OSMesaContext to an image buffer.  The image buffer is just a
1315 * block of memory which the client provides.  Its size must be at least
1316 * as large as width*height*sizeof(type).  Its address should be a multiple
1317 * of 4 if using RGBA mode.
1318 *
1319 * Image data is stored in the order of glDrawPixels:  row-major order
1320 * with the lower-left image pixel stored in the first array position
1321 * (ie. bottom-to-top).
1322 *
1323 * If the context's viewport hasn't been initialized yet, it will now be
1324 * initialized to (0,0,width,height).
1325 *
1326 * Input:  osmesa - the rendering context
1327 *         buffer - the image buffer memory
1328 *         type - data type for pixel components
1329 *            Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5
1330 *            are supported.  But if Mesa's been compiled with CHAN_BITS==16
1331 *            then type may be GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE.  And if
1332 *            Mesa's been build with CHAN_BITS==32 then type may be GL_FLOAT,
1333 *            GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE.
1334 *         width, height - size of image buffer in pixels, at least 1
1335 * Return:  GL_TRUE if success, GL_FALSE if error because of invalid osmesa,
1336 *          invalid buffer address, invalid type, width<1, height<1,
1337 *          width>internal limit or height>internal limit.
1338 */
1339GLAPI GLboolean GLAPIENTRY
1340OSMesaMakeCurrent( OSMesaContext osmesa, void *buffer, GLenum type,
1341                   GLsizei width, GLsizei height )
1342{
1343   if (!osmesa || !buffer ||
1344       width < 1 || height < 1 ||
1345       width > MAX_WIDTH || height > MAX_HEIGHT) {
1346      return GL_FALSE;
1347   }
1348
1349   if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5) {
1350      return GL_FALSE;
1351   }
1352
1353#if 0
1354   if (!(type == GL_UNSIGNED_BYTE ||
1355         (type == GL_UNSIGNED_SHORT && CHAN_BITS >= 16) ||
1356         (type == GL_FLOAT && CHAN_BITS == 32))) {
1357      /* i.e. is sizeof(type) * 8 > CHAN_BITS? */
1358      return GL_FALSE;
1359   }
1360#endif
1361
1362   osmesa_update_state( &osmesa->mesa, 0 );
1363
1364   /* Call this periodically to detect when the user has begun using
1365    * GL rendering from multiple threads.
1366    */
1367   _glapi_check_multithread();
1368
1369   /* Set renderbuffer fields.  Set width/height = 0 to force
1370    * osmesa_renderbuffer_storage() being called by _mesa_resize_framebuffer()
1371    */
1372   osmesa->rb->Data = buffer;
1373   osmesa->rb->DataType = type;
1374   osmesa->rb->Width = osmesa->rb->Height = 0;
1375
1376   /* Set the framebuffer's size.  This causes the
1377    * osmesa_renderbuffer_storage() function to get called.
1378    */
1379   _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
1380   osmesa->gl_buffer->Initialized = GL_TRUE; /* XXX TEMPORARY? */
1381
1382   _mesa_make_current( &osmesa->mesa, osmesa->gl_buffer, osmesa->gl_buffer );
1383
1384   /* Remove renderbuffer attachment, then re-add.  This installs the
1385    * renderbuffer adaptor/wrapper if needed (for bpp conversion).
1386    */
1387   _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT);
1388   _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, osmesa->rb);
1389
1390
1391   /* this updates the visual's red/green/blue/alphaBits fields */
1392   _mesa_update_framebuffer_visual(osmesa->gl_buffer);
1393
1394   /* update the framebuffer size */
1395   _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
1396
1397   return GL_TRUE;
1398}
1399
1400
1401
1402GLAPI OSMesaContext GLAPIENTRY
1403OSMesaGetCurrentContext( void )
1404{
1405   GLcontext *ctx = _mesa_get_current_context();
1406   if (ctx)
1407      return (OSMesaContext) ctx;
1408   else
1409      return NULL;
1410}
1411
1412
1413
1414GLAPI void GLAPIENTRY
1415OSMesaPixelStore( GLint pname, GLint value )
1416{
1417   OSMesaContext osmesa = OSMesaGetCurrentContext();
1418
1419   switch (pname) {
1420      case OSMESA_ROW_LENGTH:
1421         if (value<0) {
1422            _mesa_error( &osmesa->mesa, GL_INVALID_VALUE,
1423                      "OSMesaPixelStore(value)" );
1424            return;
1425         }
1426         osmesa->userRowLength = value;
1427         break;
1428      case OSMESA_Y_UP:
1429         osmesa->yup = value ? GL_TRUE : GL_FALSE;
1430         break;
1431      default:
1432         _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
1433         return;
1434   }
1435
1436   compute_row_addresses( osmesa );
1437}
1438
1439
1440GLAPI void GLAPIENTRY
1441OSMesaGetIntegerv( GLint pname, GLint *value )
1442{
1443   OSMesaContext osmesa = OSMesaGetCurrentContext();
1444
1445   switch (pname) {
1446      case OSMESA_WIDTH:
1447         if (osmesa->gl_buffer)
1448            *value = osmesa->gl_buffer->Width;
1449         else
1450            *value = 0;
1451         return;
1452      case OSMESA_HEIGHT:
1453         if (osmesa->gl_buffer)
1454            *value = osmesa->gl_buffer->Height;
1455         else
1456            *value = 0;
1457         return;
1458      case OSMESA_FORMAT:
1459         *value = osmesa->format;
1460         return;
1461      case OSMESA_TYPE:
1462         /* current color buffer's data type */
1463         if (osmesa->rb) {
1464            *value = osmesa->rb->DataType;
1465         }
1466         else {
1467            *value = 0;
1468         }
1469         return;
1470      case OSMESA_ROW_LENGTH:
1471         *value = osmesa->userRowLength;
1472         return;
1473      case OSMESA_Y_UP:
1474         *value = osmesa->yup;
1475         return;
1476      case OSMESA_MAX_WIDTH:
1477         *value = MAX_WIDTH;
1478         return;
1479      case OSMESA_MAX_HEIGHT:
1480         *value = MAX_HEIGHT;
1481         return;
1482      default:
1483         _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
1484         return;
1485   }
1486}
1487
1488
1489/**
1490 * Return the depth buffer associated with an OSMesa context.
1491 * Input:  c - the OSMesa context
1492 * Output:  width, height - size of buffer in pixels
1493 *          bytesPerValue - bytes per depth value (2 or 4)
1494 *          buffer - pointer to depth buffer values
1495 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1496 */
1497GLAPI GLboolean GLAPIENTRY
1498OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
1499                      GLint *bytesPerValue, void **buffer )
1500{
1501   struct gl_renderbuffer *rb = NULL;
1502
1503   if (c->gl_buffer)
1504      rb = c->gl_buffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1505
1506   if (!rb || !rb->Data) {
1507      *width = 0;
1508      *height = 0;
1509      *bytesPerValue = 0;
1510      *buffer = 0;
1511      return GL_FALSE;
1512   }
1513   else {
1514      *width = rb->Width;
1515      *height = rb->Height;
1516      if (c->gl_visual->depthBits <= 16)
1517         *bytesPerValue = sizeof(GLushort);
1518      else
1519         *bytesPerValue = sizeof(GLuint);
1520      *buffer = rb->Data;
1521      return GL_TRUE;
1522   }
1523}
1524
1525
1526/**
1527 * Return the color buffer associated with an OSMesa context.
1528 * Input:  c - the OSMesa context
1529 * Output:  width, height - size of buffer in pixels
1530 *          format - the pixel format (OSMESA_FORMAT)
1531 *          buffer - pointer to color buffer values
1532 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1533 */
1534GLAPI GLboolean GLAPIENTRY
1535OSMesaGetColorBuffer( OSMesaContext osmesa, GLint *width,
1536                      GLint *height, GLint *format, void **buffer )
1537{
1538   if (osmesa->rb && osmesa->rb->Data) {
1539      *width = osmesa->rb->Width;
1540      *height = osmesa->rb->Height;
1541      *format = osmesa->format;
1542      *buffer = osmesa->rb->Data;
1543      return GL_TRUE;
1544   }
1545   else {
1546      *width = 0;
1547      *height = 0;
1548      *format = 0;
1549      *buffer = 0;
1550      return GL_FALSE;
1551   }
1552}
1553
1554
1555struct name_function
1556{
1557   const char *Name;
1558   OSMESAproc Function;
1559};
1560
1561static struct name_function functions[] = {
1562   { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
1563   { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
1564   { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
1565   { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
1566   { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
1567   { "OSMesaPixelsStore", (OSMESAproc) OSMesaPixelStore },
1568   { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
1569   { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
1570   { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
1571   { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
1572   { NULL, NULL }
1573};
1574
1575
1576GLAPI OSMESAproc GLAPIENTRY
1577OSMesaGetProcAddress( const char *funcName )
1578{
1579   int i;
1580   for (i = 0; functions[i].Name; i++) {
1581      if (_mesa_strcmp(functions[i].Name, funcName) == 0)
1582         return functions[i].Function;
1583   }
1584   return _glapi_get_proc_address(funcName);
1585}
1586
1587
1588GLAPI void GLAPIENTRY
1589OSMesaColorClamp(GLboolean enable)
1590{
1591   OSMesaContext osmesa = OSMesaGetCurrentContext();
1592
1593   if (enable == GL_TRUE) {
1594      osmesa->mesa.Color.ClampFragmentColor = GL_TRUE;
1595   }
1596   else {
1597      osmesa->mesa.Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
1598   }
1599}
1600
1601
1602