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