osmesa.c revision 9b990c81c0f3b80988d159dd054ef3c0637d2d9e
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      switch (type) {
1008      case GL_UNSIGNED_BYTE:
1009         rb->Format = MESA_FORMAT_RGBA8888;
1010         break;
1011      case GL_UNSIGNED_SHORT:
1012         rb->Format = MESA_FORMAT_RGBA_16;
1013         break;
1014      case GL_FLOAT:
1015         rb->Format = MESA_FORMAT_RGBA_FLOAT32;
1016         break;
1017      default:
1018         assert(0 && "Unexpected type in new_osmesa_renderbuffer()");
1019         rb->Format = MESA_FORMAT_RGBA8888;
1020      }
1021      rb->_BaseFormat = GL_RGBA;
1022      rb->DataType = type;
1023   }
1024   return rb;
1025}
1026
1027
1028/**********************************************************************/
1029/*****                    Public Functions                        *****/
1030/**********************************************************************/
1031
1032
1033/**
1034 * Create an Off-Screen Mesa rendering context.  The only attribute needed is
1035 * an RGBA vs Color-Index mode flag.
1036 *
1037 * Input:  format - Must be GL_RGBA
1038 *         sharelist - specifies another OSMesaContext with which to share
1039 *                     display lists.  NULL indicates no sharing.
1040 * Return:  an OSMesaContext or 0 if error
1041 */
1042GLAPI OSMesaContext GLAPIENTRY
1043OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
1044{
1045   return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS,
1046                                 8, 0, sharelist);
1047}
1048
1049
1050
1051/**
1052 * New in Mesa 3.5
1053 *
1054 * Create context and specify size of ancillary buffers.
1055 */
1056GLAPI OSMesaContext GLAPIENTRY
1057OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
1058                        GLint accumBits, OSMesaContext sharelist )
1059{
1060   OSMesaContext osmesa;
1061   struct dd_function_table functions;
1062   GLint rind, gind, bind, aind;
1063   GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
1064
1065   rind = gind = bind = aind = 0;
1066   if (format==OSMESA_RGBA) {
1067      redBits = CHAN_BITS;
1068      greenBits = CHAN_BITS;
1069      blueBits = CHAN_BITS;
1070      alphaBits = CHAN_BITS;
1071      rind = 0;
1072      gind = 1;
1073      bind = 2;
1074      aind = 3;
1075   }
1076   else if (format==OSMESA_BGRA) {
1077      redBits = CHAN_BITS;
1078      greenBits = CHAN_BITS;
1079      blueBits = CHAN_BITS;
1080      alphaBits = CHAN_BITS;
1081      bind = 0;
1082      gind = 1;
1083      rind = 2;
1084      aind = 3;
1085   }
1086   else if (format==OSMESA_ARGB) {
1087      redBits = CHAN_BITS;
1088      greenBits = CHAN_BITS;
1089      blueBits = CHAN_BITS;
1090      alphaBits = CHAN_BITS;
1091      aind = 0;
1092      rind = 1;
1093      gind = 2;
1094      bind = 3;
1095   }
1096   else if (format==OSMESA_RGB) {
1097      redBits = CHAN_BITS;
1098      greenBits = CHAN_BITS;
1099      blueBits = CHAN_BITS;
1100      alphaBits = 0;
1101      rind = 0;
1102      gind = 1;
1103      bind = 2;
1104   }
1105   else if (format==OSMESA_BGR) {
1106      redBits = CHAN_BITS;
1107      greenBits = CHAN_BITS;
1108      blueBits = CHAN_BITS;
1109      alphaBits = 0;
1110      rind = 2;
1111      gind = 1;
1112      bind = 0;
1113   }
1114#if CHAN_TYPE == GL_UNSIGNED_BYTE
1115   else if (format==OSMESA_RGB_565) {
1116      redBits = 5;
1117      greenBits = 6;
1118      blueBits = 5;
1119      alphaBits = 0;
1120      rind = 0; /* not used */
1121      gind = 0;
1122      bind = 0;
1123   }
1124#endif
1125   else {
1126      return NULL;
1127   }
1128
1129   osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
1130   if (osmesa) {
1131      osmesa->gl_visual = _mesa_create_visual( GL_FALSE,    /* double buffer */
1132                                               GL_FALSE,    /* stereo */
1133                                               redBits,
1134                                               greenBits,
1135                                               blueBits,
1136                                               alphaBits,
1137                                               depthBits,
1138                                               stencilBits,
1139                                               accumBits,
1140                                               accumBits,
1141                                               accumBits,
1142                                               alphaBits ? accumBits : 0,
1143                                               1            /* num samples */
1144                                               );
1145      if (!osmesa->gl_visual) {
1146         free(osmesa);
1147         return NULL;
1148      }
1149
1150      /* Initialize device driver function table */
1151      _mesa_init_driver_functions(&functions);
1152      /* override with our functions */
1153      functions.GetString = get_string;
1154      functions.UpdateState = osmesa_update_state;
1155      functions.GetBufferSize = NULL;
1156
1157      if (!_mesa_initialize_context(&osmesa->mesa,
1158                                    osmesa->gl_visual,
1159                                    sharelist ? &sharelist->mesa
1160                                              : (GLcontext *) NULL,
1161                                    &functions, (void *) osmesa)) {
1162         _mesa_destroy_visual( osmesa->gl_visual );
1163         free(osmesa);
1164         return NULL;
1165      }
1166
1167      _mesa_enable_sw_extensions(&(osmesa->mesa));
1168      _mesa_enable_1_3_extensions(&(osmesa->mesa));
1169      _mesa_enable_1_4_extensions(&(osmesa->mesa));
1170      _mesa_enable_1_5_extensions(&(osmesa->mesa));
1171      _mesa_enable_2_0_extensions(&(osmesa->mesa));
1172      _mesa_enable_2_1_extensions(&(osmesa->mesa));
1173
1174      osmesa->gl_buffer = _mesa_create_framebuffer(osmesa->gl_visual);
1175      if (!osmesa->gl_buffer) {
1176         _mesa_destroy_visual( osmesa->gl_visual );
1177         _mesa_free_context_data( &osmesa->mesa );
1178         free(osmesa);
1179         return NULL;
1180      }
1181
1182      /* Create depth/stencil/accum buffers.  We'll create the color
1183       * buffer later in OSMesaMakeCurrent().
1184       */
1185      _mesa_add_soft_renderbuffers(osmesa->gl_buffer,
1186                                   GL_FALSE, /* color */
1187                                   osmesa->gl_visual->haveDepthBuffer,
1188                                   osmesa->gl_visual->haveStencilBuffer,
1189                                   osmesa->gl_visual->haveAccumBuffer,
1190                                   GL_FALSE, /* alpha */
1191                                   GL_FALSE /* aux */ );
1192
1193      osmesa->format = format;
1194      osmesa->userRowLength = 0;
1195      osmesa->yup = GL_TRUE;
1196      osmesa->rInd = rind;
1197      osmesa->gInd = gind;
1198      osmesa->bInd = bind;
1199      osmesa->aInd = aind;
1200
1201      _mesa_meta_init(&osmesa->mesa);
1202
1203      /* Initialize the software rasterizer and helper modules. */
1204      {
1205	 GLcontext *ctx = &osmesa->mesa;
1206         SWcontext *swrast;
1207         TNLcontext *tnl;
1208
1209	 if (!_swrast_CreateContext( ctx ) ||
1210             !_vbo_CreateContext( ctx ) ||
1211             !_tnl_CreateContext( ctx ) ||
1212             !_swsetup_CreateContext( ctx )) {
1213            _mesa_destroy_visual(osmesa->gl_visual);
1214            _mesa_free_context_data(ctx);
1215            free(osmesa);
1216            return NULL;
1217         }
1218
1219	 _swsetup_Wakeup( ctx );
1220
1221         /* use default TCL pipeline */
1222         tnl = TNL_CONTEXT(ctx);
1223         tnl->Driver.RunPipeline = _tnl_run_pipeline;
1224
1225         /* Extend the software rasterizer with our optimized line and triangle
1226          * drawing functions.
1227          */
1228         swrast = SWRAST_CONTEXT( ctx );
1229         swrast->choose_line = osmesa_choose_line;
1230         swrast->choose_triangle = osmesa_choose_triangle;
1231      }
1232   }
1233   return osmesa;
1234}
1235
1236
1237/**
1238 * Destroy an Off-Screen Mesa rendering context.
1239 *
1240 * \param osmesa  the context to destroy
1241 */
1242GLAPI void GLAPIENTRY
1243OSMesaDestroyContext( OSMesaContext osmesa )
1244{
1245   if (osmesa) {
1246      if (osmesa->rb)
1247         _mesa_reference_renderbuffer(&osmesa->rb, NULL);
1248
1249      _mesa_meta_free( &osmesa->mesa );
1250
1251      _swsetup_DestroyContext( &osmesa->mesa );
1252      _tnl_DestroyContext( &osmesa->mesa );
1253      _vbo_DestroyContext( &osmesa->mesa );
1254      _swrast_DestroyContext( &osmesa->mesa );
1255
1256      _mesa_destroy_visual( osmesa->gl_visual );
1257      _mesa_reference_framebuffer( &osmesa->gl_buffer, NULL );
1258
1259      _mesa_free_context_data( &osmesa->mesa );
1260      free( osmesa );
1261   }
1262}
1263
1264
1265/**
1266 * Bind an OSMesaContext to an image buffer.  The image buffer is just a
1267 * block of memory which the client provides.  Its size must be at least
1268 * as large as width*height*sizeof(type).  Its address should be a multiple
1269 * of 4 if using RGBA mode.
1270 *
1271 * Image data is stored in the order of glDrawPixels:  row-major order
1272 * with the lower-left image pixel stored in the first array position
1273 * (ie. bottom-to-top).
1274 *
1275 * If the context's viewport hasn't been initialized yet, it will now be
1276 * initialized to (0,0,width,height).
1277 *
1278 * Input:  osmesa - the rendering context
1279 *         buffer - the image buffer memory
1280 *         type - data type for pixel components
1281 *            Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5
1282 *            are supported.  But if Mesa's been compiled with CHAN_BITS==16
1283 *            then type may be GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE.  And if
1284 *            Mesa's been build with CHAN_BITS==32 then type may be GL_FLOAT,
1285 *            GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE.
1286 *         width, height - size of image buffer in pixels, at least 1
1287 * Return:  GL_TRUE if success, GL_FALSE if error because of invalid osmesa,
1288 *          invalid buffer address, invalid type, width<1, height<1,
1289 *          width>internal limit or height>internal limit.
1290 */
1291GLAPI GLboolean GLAPIENTRY
1292OSMesaMakeCurrent( OSMesaContext osmesa, void *buffer, GLenum type,
1293                   GLsizei width, GLsizei height )
1294{
1295   if (!osmesa || !buffer ||
1296       width < 1 || height < 1 ||
1297       width > MAX_WIDTH || height > MAX_HEIGHT) {
1298      return GL_FALSE;
1299   }
1300
1301   if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5) {
1302      return GL_FALSE;
1303   }
1304
1305#if 0
1306   if (!(type == GL_UNSIGNED_BYTE ||
1307         (type == GL_UNSIGNED_SHORT && CHAN_BITS >= 16) ||
1308         (type == GL_FLOAT && CHAN_BITS == 32))) {
1309      /* i.e. is sizeof(type) * 8 > CHAN_BITS? */
1310      return GL_FALSE;
1311   }
1312#endif
1313
1314   osmesa_update_state( &osmesa->mesa, 0 );
1315
1316   /* Call this periodically to detect when the user has begun using
1317    * GL rendering from multiple threads.
1318    */
1319   _glapi_check_multithread();
1320
1321
1322   /* Create a front/left color buffer which wraps the user-provided buffer.
1323    * There is no back color buffer.
1324    * If the user tries to use a 8, 16 or 32-bit/channel buffer that
1325    * doesn't match what Mesa was compiled for (CHAN_BITS) the
1326    * _mesa_add_renderbuffer() function will create a "wrapper" renderbuffer
1327    * that converts rendering from CHAN_BITS to the user-requested channel
1328    * size.
1329    */
1330   osmesa->rb = new_osmesa_renderbuffer(&osmesa->mesa, osmesa->format, type);
1331   _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, osmesa->rb);
1332   assert(osmesa->rb->RefCount == 2);
1333
1334   /* Set renderbuffer fields.  Set width/height = 0 to force
1335    * osmesa_renderbuffer_storage() being called by _mesa_resize_framebuffer()
1336    */
1337   osmesa->rb->Data = buffer;
1338   osmesa->rb->Width = osmesa->rb->Height = 0;
1339
1340   /* Set the framebuffer's size.  This causes the
1341    * osmesa_renderbuffer_storage() function to get called.
1342    */
1343   _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
1344   osmesa->gl_buffer->Initialized = GL_TRUE; /* XXX TEMPORARY? */
1345
1346   _mesa_make_current( &osmesa->mesa, osmesa->gl_buffer, osmesa->gl_buffer );
1347
1348   /* Remove renderbuffer attachment, then re-add.  This installs the
1349    * renderbuffer adaptor/wrapper if needed (for bpp conversion).
1350    */
1351   _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT);
1352   _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, osmesa->rb);
1353
1354
1355   /* this updates the visual's red/green/blue/alphaBits fields */
1356   _mesa_update_framebuffer_visual(osmesa->gl_buffer);
1357
1358   /* update the framebuffer size */
1359   _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
1360
1361   return GL_TRUE;
1362}
1363
1364
1365
1366GLAPI OSMesaContext GLAPIENTRY
1367OSMesaGetCurrentContext( void )
1368{
1369   GLcontext *ctx = _mesa_get_current_context();
1370   if (ctx)
1371      return (OSMesaContext) ctx;
1372   else
1373      return NULL;
1374}
1375
1376
1377
1378GLAPI void GLAPIENTRY
1379OSMesaPixelStore( GLint pname, GLint value )
1380{
1381   OSMesaContext osmesa = OSMesaGetCurrentContext();
1382
1383   switch (pname) {
1384      case OSMESA_ROW_LENGTH:
1385         if (value<0) {
1386            _mesa_error( &osmesa->mesa, GL_INVALID_VALUE,
1387                      "OSMesaPixelStore(value)" );
1388            return;
1389         }
1390         osmesa->userRowLength = value;
1391         break;
1392      case OSMESA_Y_UP:
1393         osmesa->yup = value ? GL_TRUE : GL_FALSE;
1394         break;
1395      default:
1396         _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
1397         return;
1398   }
1399
1400   compute_row_addresses( osmesa );
1401}
1402
1403
1404GLAPI void GLAPIENTRY
1405OSMesaGetIntegerv( GLint pname, GLint *value )
1406{
1407   OSMesaContext osmesa = OSMesaGetCurrentContext();
1408
1409   switch (pname) {
1410      case OSMESA_WIDTH:
1411         if (osmesa->gl_buffer)
1412            *value = osmesa->gl_buffer->Width;
1413         else
1414            *value = 0;
1415         return;
1416      case OSMESA_HEIGHT:
1417         if (osmesa->gl_buffer)
1418            *value = osmesa->gl_buffer->Height;
1419         else
1420            *value = 0;
1421         return;
1422      case OSMESA_FORMAT:
1423         *value = osmesa->format;
1424         return;
1425      case OSMESA_TYPE:
1426         /* current color buffer's data type */
1427         if (osmesa->rb) {
1428            *value = osmesa->rb->DataType;
1429         }
1430         else {
1431            *value = 0;
1432         }
1433         return;
1434      case OSMESA_ROW_LENGTH:
1435         *value = osmesa->userRowLength;
1436         return;
1437      case OSMESA_Y_UP:
1438         *value = osmesa->yup;
1439         return;
1440      case OSMESA_MAX_WIDTH:
1441         *value = MAX_WIDTH;
1442         return;
1443      case OSMESA_MAX_HEIGHT:
1444         *value = MAX_HEIGHT;
1445         return;
1446      default:
1447         _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
1448         return;
1449   }
1450}
1451
1452
1453/**
1454 * Return the depth buffer associated with an OSMesa context.
1455 * Input:  c - the OSMesa context
1456 * Output:  width, height - size of buffer in pixels
1457 *          bytesPerValue - bytes per depth value (2 or 4)
1458 *          buffer - pointer to depth buffer values
1459 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1460 */
1461GLAPI GLboolean GLAPIENTRY
1462OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
1463                      GLint *bytesPerValue, void **buffer )
1464{
1465   struct gl_renderbuffer *rb = NULL;
1466
1467   if (c->gl_buffer)
1468      rb = c->gl_buffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1469
1470   if (!rb || !rb->Data) {
1471      *width = 0;
1472      *height = 0;
1473      *bytesPerValue = 0;
1474      *buffer = 0;
1475      return GL_FALSE;
1476   }
1477   else {
1478      *width = rb->Width;
1479      *height = rb->Height;
1480      if (c->gl_visual->depthBits <= 16)
1481         *bytesPerValue = sizeof(GLushort);
1482      else
1483         *bytesPerValue = sizeof(GLuint);
1484      *buffer = rb->Data;
1485      return GL_TRUE;
1486   }
1487}
1488
1489
1490/**
1491 * Return the color buffer associated with an OSMesa context.
1492 * Input:  c - the OSMesa context
1493 * Output:  width, height - size of buffer in pixels
1494 *          format - the pixel format (OSMESA_FORMAT)
1495 *          buffer - pointer to color buffer values
1496 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1497 */
1498GLAPI GLboolean GLAPIENTRY
1499OSMesaGetColorBuffer( OSMesaContext osmesa, GLint *width,
1500                      GLint *height, GLint *format, void **buffer )
1501{
1502   if (osmesa->rb && osmesa->rb->Data) {
1503      *width = osmesa->rb->Width;
1504      *height = osmesa->rb->Height;
1505      *format = osmesa->format;
1506      *buffer = osmesa->rb->Data;
1507      return GL_TRUE;
1508   }
1509   else {
1510      *width = 0;
1511      *height = 0;
1512      *format = 0;
1513      *buffer = 0;
1514      return GL_FALSE;
1515   }
1516}
1517
1518
1519struct name_function
1520{
1521   const char *Name;
1522   OSMESAproc Function;
1523};
1524
1525static struct name_function functions[] = {
1526   { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
1527   { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
1528   { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
1529   { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
1530   { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
1531   { "OSMesaPixelsStore", (OSMESAproc) OSMesaPixelStore },
1532   { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
1533   { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
1534   { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
1535   { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
1536   { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp },
1537   { NULL, NULL }
1538};
1539
1540
1541GLAPI OSMESAproc GLAPIENTRY
1542OSMesaGetProcAddress( const char *funcName )
1543{
1544   int i;
1545   for (i = 0; functions[i].Name; i++) {
1546      if (strcmp(functions[i].Name, funcName) == 0)
1547         return functions[i].Function;
1548   }
1549   return _glapi_get_proc_address(funcName);
1550}
1551
1552
1553GLAPI void GLAPIENTRY
1554OSMesaColorClamp(GLboolean enable)
1555{
1556   OSMesaContext osmesa = OSMesaGetCurrentContext();
1557
1558   if (enable == GL_TRUE) {
1559      osmesa->mesa.Color.ClampFragmentColor = GL_TRUE;
1560   }
1561   else {
1562      osmesa->mesa.Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
1563   }
1564}
1565
1566
1567