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