osmesa.c revision 8d73aa6d1ae6e89bb2cd8f52f5586d569a4b6eeb
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/* color index */
488#define NAME(PREFIX) PREFIX##_CI
489#define CI_MODE
490#define RB_TYPE GLubyte
491#define SPAN_VARS \
492   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
493#define INIT_PIXEL_PTR(P, X, Y) \
494   GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + (X)
495#define INC_PIXEL_PTR(P) P += 1
496#define STORE_PIXEL(DST, X, Y, VALUE) \
497   *DST = VALUE[0]
498#define FETCH_PIXEL(DST, SRC) \
499   DST = SRC[0]
500#include "swrast/s_spantemp.h"
501
502
503
504
505/**
506 * Macros for optimized line/triangle rendering.
507 * Only for 8-bit channel, RGBA, BGRA, ARGB formats.
508 */
509
510#define PACK_RGBA(DST, R, G, B, A)	\
511do {					\
512   (DST)[osmesa->rInd] = R;		\
513   (DST)[osmesa->gInd] = G;		\
514   (DST)[osmesa->bInd] = B;		\
515   (DST)[osmesa->aInd] = A;		\
516} while (0)
517
518#define PIXELADDR4(X,Y)  ((GLchan *) osmesa->rowaddr[Y] + 4 * (X))
519
520
521/**
522 * Draw a flat-shaded, RGB line into an osmesa buffer.
523 */
524#define NAME flat_rgba_line
525#define CLIP_HACK 1
526#define SETUP_CODE						\
527   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);		\
528   const GLchan *color = vert1->color;
529
530#define PLOT(X, Y)						\
531do {								\
532   GLchan *p = PIXELADDR4(X, Y);				\
533   PACK_RGBA(p, color[0], color[1], color[2], color[3]);	\
534} while (0)
535
536#ifdef WIN32
537#include "..\swrast\s_linetemp.h"
538#else
539#include "swrast/s_linetemp.h"
540#endif
541
542
543
544/**
545 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
546 */
547#define NAME flat_rgba_z_line
548#define CLIP_HACK 1
549#define INTERP_Z 1
550#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
551#define SETUP_CODE					\
552   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);	\
553   const GLchan *color = vert1->color;
554
555#define PLOT(X, Y)					\
556do {							\
557   if (Z < *zPtr) {					\
558      GLchan *p = PIXELADDR4(X, Y);			\
559      PACK_RGBA(p, color[RCOMP], color[GCOMP],		\
560                   color[BCOMP], color[ACOMP]);		\
561      *zPtr = Z;					\
562   }							\
563} while (0)
564
565#ifdef WIN32
566#include "..\swrast\s_linetemp.h"
567#else
568#include "swrast/s_linetemp.h"
569#endif
570
571
572
573/**
574 * Analyze context state to see if we can provide a fast line drawing
575 * function.  Otherwise, return NULL.
576 */
577static swrast_line_func
578osmesa_choose_line_function( GLcontext *ctx )
579{
580   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
581   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
582
583   if (osmesa->rb->DataType != GL_UNSIGNED_BYTE)
584      return NULL;
585
586   if (ctx->RenderMode != GL_RENDER)      return NULL;
587   if (ctx->Line.SmoothFlag)              return NULL;
588   if (ctx->Texture._EnabledUnits)        return NULL;
589   if (ctx->Light.ShadeModel != GL_FLAT)  return NULL;
590   if (ctx->Line.Width != 1.0F)           return NULL;
591   if (ctx->Line.StippleFlag)             return NULL;
592   if (ctx->Line.SmoothFlag)              return NULL;
593   if (osmesa->format != OSMESA_RGBA &&
594       osmesa->format != OSMESA_BGRA &&
595       osmesa->format != OSMESA_ARGB)     return NULL;
596
597   if (swrast->_RasterMask==DEPTH_BIT
598       && ctx->Depth.Func==GL_LESS
599       && ctx->Depth.Mask==GL_TRUE
600       && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
601      return (swrast_line_func) flat_rgba_z_line;
602   }
603
604   if (swrast->_RasterMask == 0) {
605      return (swrast_line_func) flat_rgba_line;
606   }
607
608   return (swrast_line_func) NULL;
609}
610
611
612/**********************************************************************/
613/*****                 Optimized triangle rendering               *****/
614/**********************************************************************/
615
616
617/*
618 * Smooth-shaded, z-less triangle, RGBA color.
619 */
620#define NAME smooth_rgba_z_triangle
621#define INTERP_Z 1
622#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
623#define INTERP_RGB 1
624#define INTERP_ALPHA 1
625#define SETUP_CODE \
626   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
627#define RENDER_SPAN( span ) {					\
628   GLuint i;							\
629   GLchan *img = PIXELADDR4(span.x, span.y); 			\
630   for (i = 0; i < span.end; i++, img += 4) {			\
631      const GLuint z = FixedToDepth(span.z);			\
632      if (z < zRow[i]) {					\
633         PACK_RGBA(img, FixedToChan(span.red),			\
634            FixedToChan(span.green), FixedToChan(span.blue),	\
635            FixedToChan(span.alpha));				\
636         zRow[i] = z;						\
637      }								\
638      span.red += span.redStep;					\
639      span.green += span.greenStep;				\
640      span.blue += span.blueStep;				\
641      span.alpha += span.alphaStep;				\
642      span.z += span.zStep;					\
643   }                                                            \
644}
645#ifdef WIN32
646#include "..\swrast\s_tritemp.h"
647#else
648#include "swrast/s_tritemp.h"
649#endif
650
651
652
653/*
654 * Flat-shaded, z-less triangle, RGBA color.
655 */
656#define NAME flat_rgba_z_triangle
657#define INTERP_Z 1
658#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
659#define SETUP_CODE						\
660   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);		\
661   GLuint pixel;						\
662   PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1],	\
663                                v2->color[2], v2->color[3]);
664
665#define RENDER_SPAN( span ) {				\
666   GLuint i;						\
667   GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y);	\
668   for (i = 0; i < span.end; i++) {			\
669      const GLuint z = FixedToDepth(span.z);		\
670      if (z < zRow[i]) {				\
671         img[i] = pixel;				\
672         zRow[i] = z;					\
673      }							\
674      span.z += span.zStep;				\
675   }                                                    \
676}
677#ifdef WIN32
678#include "..\swrast\s_tritemp.h"
679#else
680#include "swrast/s_tritemp.h"
681#endif
682
683
684
685/**
686 * Return pointer to an optimized triangle function if possible.
687 */
688static swrast_tri_func
689osmesa_choose_triangle_function( GLcontext *ctx )
690{
691   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
692   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
693
694   if (osmesa->rb->DataType != GL_UNSIGNED_BYTE)
695      return (swrast_tri_func) NULL;
696
697   if (ctx->RenderMode != GL_RENDER)    return (swrast_tri_func) NULL;
698   if (ctx->Polygon.SmoothFlag)         return (swrast_tri_func) NULL;
699   if (ctx->Polygon.StippleFlag)        return (swrast_tri_func) NULL;
700   if (ctx->Texture._EnabledUnits)      return (swrast_tri_func) NULL;
701   if (osmesa->format != OSMESA_RGBA &&
702       osmesa->format != OSMESA_BGRA &&
703       osmesa->format != OSMESA_ARGB)   return (swrast_tri_func) NULL;
704   if (ctx->Polygon.CullFlag &&
705       ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
706                                        return (swrast_tri_func) NULL;
707
708   if (swrast->_RasterMask == DEPTH_BIT &&
709       ctx->Depth.Func == GL_LESS &&
710       ctx->Depth.Mask == GL_TRUE &&
711       ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
712      if (ctx->Light.ShadeModel == GL_SMOOTH) {
713         return (swrast_tri_func) smooth_rgba_z_triangle;
714      }
715      else {
716         return (swrast_tri_func) flat_rgba_z_triangle;
717      }
718   }
719   return (swrast_tri_func) NULL;
720}
721
722
723
724/* Override for the swrast triangle-selection function.  Try to use one
725 * of our internal triangle functions, otherwise fall back to the
726 * standard swrast functions.
727 */
728static void
729osmesa_choose_triangle( GLcontext *ctx )
730{
731   SWcontext *swrast = SWRAST_CONTEXT(ctx);
732
733   swrast->Triangle = osmesa_choose_triangle_function( ctx );
734   if (!swrast->Triangle)
735      _swrast_choose_triangle( ctx );
736}
737
738static void
739osmesa_choose_line( GLcontext *ctx )
740{
741   SWcontext *swrast = SWRAST_CONTEXT(ctx);
742
743   swrast->Line = osmesa_choose_line_function( ctx );
744   if (!swrast->Line)
745      _swrast_choose_line( ctx );
746}
747
748
749
750/**
751 * Recompute the values of the context's rowaddr array.
752 */
753static void
754compute_row_addresses( OSMesaContext osmesa )
755{
756   GLint bytesPerPixel, bytesPerRow, i;
757   GLubyte *origin = (GLubyte *) osmesa->rb->Data;
758   GLint bpc; /* bytes per channel */
759   GLint rowlength; /* in pixels */
760   GLint height = osmesa->rb->Height;
761
762   if (osmesa->userRowLength)
763      rowlength = osmesa->userRowLength;
764   else
765      rowlength = osmesa->rb->Width;
766
767   if (osmesa->rb->DataType == GL_UNSIGNED_BYTE)
768      bpc = 1;
769   else if (osmesa->rb->DataType == GL_UNSIGNED_SHORT)
770      bpc = 2;
771   else if (osmesa->rb->DataType == GL_FLOAT)
772      bpc = 4;
773   else {
774      _mesa_problem(&osmesa->mesa,
775                    "Unexpected datatype in osmesa::compute_row_addresses");
776      return;
777   }
778
779   if (osmesa->format == OSMESA_COLOR_INDEX) {
780      /* CI mode */
781      bytesPerPixel = 1 * sizeof(GLubyte);
782   }
783   else if ((osmesa->format == OSMESA_RGB) || (osmesa->format == OSMESA_BGR)) {
784      /* RGB mode */
785      bytesPerPixel = 3 * bpc;
786   }
787   else if (osmesa->format == OSMESA_RGB_565) {
788      /* 5/6/5 RGB pixel in 16 bits */
789      bytesPerPixel = 2;
790   }
791   else {
792      /* RGBA mode */
793      bytesPerPixel = 4 * bpc;
794   }
795
796   bytesPerRow = rowlength * bytesPerPixel;
797
798   if (osmesa->yup) {
799      /* Y=0 is bottom line of window */
800      for (i = 0; i < height; i++) {
801         osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + i * bytesPerRow);
802      }
803   }
804   else {
805      /* Y=0 is top line of window */
806      for (i = 0; i < height; i++) {
807         GLint j = height - i - 1;
808         osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + j * bytesPerRow);
809      }
810   }
811}
812
813
814
815/**
816 * Don't use _mesa_delete_renderbuffer since we can't free rb->Data.
817 */
818static void
819osmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
820{
821   _mesa_free(rb);
822}
823
824
825/**
826 * Allocate renderbuffer storage.  We don't actually allocate any storage
827 * since we're using a user-provided buffer.
828 * Just set up all the gl_renderbuffer methods.
829 */
830static GLboolean
831osmesa_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
832                            GLenum internalFormat, GLuint width, GLuint height)
833{
834   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
835   GLint bpc; /* bits per channel */
836
837   if (rb->DataType == GL_UNSIGNED_BYTE)
838      bpc = 8;
839   else if (rb->DataType == GL_UNSIGNED_SHORT)
840      bpc = 16;
841   else
842      bpc = 32;
843
844   /* Note: we can ignoring internalFormat for "window-system" renderbuffers */
845   (void) internalFormat;
846
847   if (osmesa->format == OSMESA_RGBA) {
848      if (rb->DataType == GL_UNSIGNED_BYTE) {
849         rb->GetRow = get_row_RGBA8;
850         rb->GetValues = get_values_RGBA8;
851         rb->PutRow = put_row_RGBA8;
852         rb->PutRowRGB = put_row_rgb_RGBA8;
853         rb->PutMonoRow = put_mono_row_RGBA8;
854         rb->PutValues = put_values_RGBA8;
855         rb->PutMonoValues = put_mono_values_RGBA8;
856      }
857      else if (rb->DataType == GL_UNSIGNED_SHORT) {
858         rb->GetRow = get_row_RGBA16;
859         rb->GetValues = get_values_RGBA16;
860         rb->PutRow = put_row_RGBA16;
861         rb->PutRowRGB = put_row_rgb_RGBA16;
862         rb->PutMonoRow = put_mono_row_RGBA16;
863         rb->PutValues = put_values_RGBA16;
864         rb->PutMonoValues = put_mono_values_RGBA16;
865      }
866      else {
867         rb->GetRow = get_row_RGBA32;
868         rb->GetValues = get_values_RGBA32;
869         rb->PutRow = put_row_RGBA32;
870         rb->PutRowRGB = put_row_rgb_RGBA32;
871         rb->PutMonoRow = put_mono_row_RGBA32;
872         rb->PutValues = put_values_RGBA32;
873         rb->PutMonoValues = put_mono_values_RGBA32;
874      }
875   }
876   else if (osmesa->format == OSMESA_BGRA) {
877      if (rb->DataType == GL_UNSIGNED_BYTE) {
878         rb->GetRow = get_row_BGRA8;
879         rb->GetValues = get_values_BGRA8;
880         rb->PutRow = put_row_BGRA8;
881         rb->PutRowRGB = put_row_rgb_BGRA8;
882         rb->PutMonoRow = put_mono_row_BGRA8;
883         rb->PutValues = put_values_BGRA8;
884         rb->PutMonoValues = put_mono_values_BGRA8;
885      }
886      else if (rb->DataType == GL_UNSIGNED_SHORT) {
887         rb->GetRow = get_row_BGRA16;
888         rb->GetValues = get_values_BGRA16;
889         rb->PutRow = put_row_BGRA16;
890         rb->PutRowRGB = put_row_rgb_BGRA16;
891         rb->PutMonoRow = put_mono_row_BGRA16;
892         rb->PutValues = put_values_BGRA16;
893         rb->PutMonoValues = put_mono_values_BGRA16;
894      }
895      else {
896         rb->GetRow = get_row_BGRA32;
897         rb->GetValues = get_values_BGRA32;
898         rb->PutRow = put_row_BGRA32;
899         rb->PutRowRGB = put_row_rgb_BGRA32;
900         rb->PutMonoRow = put_mono_row_BGRA32;
901         rb->PutValues = put_values_BGRA32;
902         rb->PutMonoValues = put_mono_values_BGRA32;
903      }
904   }
905   else if (osmesa->format == OSMESA_ARGB) {
906      if (rb->DataType == GL_UNSIGNED_BYTE) {
907         rb->GetRow = get_row_ARGB8;
908         rb->GetValues = get_values_ARGB8;
909         rb->PutRow = put_row_ARGB8;
910         rb->PutRowRGB = put_row_rgb_ARGB8;
911         rb->PutMonoRow = put_mono_row_ARGB8;
912         rb->PutValues = put_values_ARGB8;
913         rb->PutMonoValues = put_mono_values_ARGB8;
914      }
915      else if (rb->DataType == GL_UNSIGNED_SHORT) {
916         rb->GetRow = get_row_ARGB16;
917         rb->GetValues = get_values_ARGB16;
918         rb->PutRow = put_row_ARGB16;
919         rb->PutRowRGB = put_row_rgb_ARGB16;
920         rb->PutMonoRow = put_mono_row_ARGB16;
921         rb->PutValues = put_values_ARGB16;
922         rb->PutMonoValues = put_mono_values_ARGB16;
923      }
924      else {
925         rb->GetRow = get_row_ARGB32;
926         rb->GetValues = get_values_ARGB32;
927         rb->PutRow = put_row_ARGB32;
928         rb->PutRowRGB = put_row_rgb_ARGB32;
929         rb->PutMonoRow = put_mono_row_ARGB32;
930         rb->PutValues = put_values_ARGB32;
931         rb->PutMonoValues = put_mono_values_ARGB32;
932      }
933   }
934   else if (osmesa->format == OSMESA_RGB) {
935      if (rb->DataType == GL_UNSIGNED_BYTE) {
936         rb->GetRow = get_row_RGB8;
937         rb->GetValues = get_values_RGB8;
938         rb->PutRow = put_row_RGB8;
939         rb->PutRowRGB = put_row_rgb_RGB8;
940         rb->PutMonoRow = put_mono_row_RGB8;
941         rb->PutValues = put_values_RGB8;
942         rb->PutMonoValues = put_mono_values_RGB8;
943      }
944      else if (rb->DataType == GL_UNSIGNED_SHORT) {
945         rb->GetRow = get_row_RGB16;
946         rb->GetValues = get_values_RGB16;
947         rb->PutRow = put_row_RGB16;
948         rb->PutRowRGB = put_row_rgb_RGB16;
949         rb->PutMonoRow = put_mono_row_RGB16;
950         rb->PutValues = put_values_RGB16;
951         rb->PutMonoValues = put_mono_values_RGB16;
952      }
953      else {
954         rb->GetRow = get_row_RGB32;
955         rb->GetValues = get_values_RGB32;
956         rb->PutRow = put_row_RGB32;
957         rb->PutRowRGB = put_row_rgb_RGB32;
958         rb->PutMonoRow = put_mono_row_RGB32;
959         rb->PutValues = put_values_RGB32;
960         rb->PutMonoValues = put_mono_values_RGB32;
961      }
962   }
963   else if (osmesa->format == OSMESA_BGR) {
964      if (rb->DataType == GL_UNSIGNED_BYTE) {
965         rb->GetRow = get_row_BGR8;
966         rb->GetValues = get_values_BGR8;
967         rb->PutRow = put_row_BGR8;
968         rb->PutRowRGB = put_row_rgb_BGR8;
969         rb->PutMonoRow = put_mono_row_BGR8;
970         rb->PutValues = put_values_BGR8;
971         rb->PutMonoValues = put_mono_values_BGR8;
972      }
973      else if (rb->DataType == GL_UNSIGNED_SHORT) {
974         rb->GetRow = get_row_BGR16;
975         rb->GetValues = get_values_BGR16;
976         rb->PutRow = put_row_BGR16;
977         rb->PutRowRGB = put_row_rgb_BGR16;
978         rb->PutMonoRow = put_mono_row_BGR16;
979         rb->PutValues = put_values_BGR16;
980         rb->PutMonoValues = put_mono_values_BGR16;
981      }
982      else {
983         rb->GetRow = get_row_BGR32;
984         rb->GetValues = get_values_BGR32;
985         rb->PutRow = put_row_BGR32;
986         rb->PutRowRGB = put_row_rgb_BGR32;
987         rb->PutMonoRow = put_mono_row_BGR32;
988         rb->PutValues = put_values_BGR32;
989         rb->PutMonoValues = put_mono_values_BGR32;
990      }
991   }
992   else if (osmesa->format == OSMESA_RGB_565) {
993      ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
994      rb->GetRow = get_row_RGB_565;
995      rb->GetValues = get_values_RGB_565;
996      rb->PutRow = put_row_RGB_565;
997      rb->PutRowRGB = put_row_rgb_RGB_565;
998      rb->PutMonoRow = put_mono_row_RGB_565;
999      rb->PutValues = put_values_RGB_565;
1000      rb->PutMonoValues = put_mono_values_RGB_565;
1001   }
1002   else if (osmesa->format == OSMESA_COLOR_INDEX) {
1003      rb->GetRow = get_row_CI;
1004      rb->GetValues = get_values_CI;
1005      rb->PutRow = put_row_CI;
1006      rb->PutMonoRow = put_mono_row_CI;
1007      rb->PutValues = put_values_CI;
1008      rb->PutMonoValues = put_mono_values_CI;
1009   }
1010   else {
1011      _mesa_problem(ctx, "bad pixel format in osmesa renderbuffer_storage");
1012   }
1013
1014   rb->Width = width;
1015   rb->Height = height;
1016
1017   compute_row_addresses( osmesa );
1018
1019   return GL_TRUE;
1020}
1021
1022
1023/**
1024 * Allocate a new renderbuffer to describe the user-provided color buffer.
1025 */
1026static struct gl_renderbuffer *
1027new_osmesa_renderbuffer(GLcontext *ctx, GLenum format, GLenum type)
1028{
1029   const GLuint name = 0;
1030   struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name);
1031   if (rb) {
1032      rb->RefCount = 1;
1033      rb->Delete = osmesa_delete_renderbuffer;
1034      rb->AllocStorage = osmesa_renderbuffer_storage;
1035
1036      if (format == OSMESA_COLOR_INDEX) {
1037         rb->InternalFormat = GL_COLOR_INDEX;
1038         rb->Format = MESA_FORMAT_CI8;
1039         rb->_BaseFormat = GL_COLOR_INDEX;
1040         rb->DataType = GL_UNSIGNED_BYTE;
1041      }
1042      else {
1043         rb->InternalFormat = GL_RGBA;
1044         rb->Format = MESA_FORMAT_RGBA8888;
1045         rb->_BaseFormat = GL_RGBA;
1046         rb->DataType = type;
1047      }
1048   }
1049   return rb;
1050}
1051
1052
1053/**********************************************************************/
1054/*****                    Public Functions                        *****/
1055/**********************************************************************/
1056
1057
1058/**
1059 * Create an Off-Screen Mesa rendering context.  The only attribute needed is
1060 * an RGBA vs Color-Index mode flag.
1061 *
1062 * Input:  format - either GL_RGBA or GL_COLOR_INDEX
1063 *         sharelist - specifies another OSMesaContext with which to share
1064 *                     display lists.  NULL indicates no sharing.
1065 * Return:  an OSMesaContext or 0 if error
1066 */
1067GLAPI OSMesaContext GLAPIENTRY
1068OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
1069{
1070   const GLint accumBits = (format == OSMESA_COLOR_INDEX) ? 0 : 16;
1071   return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS,
1072                                 8, accumBits, sharelist);
1073}
1074
1075
1076
1077/**
1078 * New in Mesa 3.5
1079 *
1080 * Create context and specify size of ancillary buffers.
1081 */
1082GLAPI OSMesaContext GLAPIENTRY
1083OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
1084                        GLint accumBits, OSMesaContext sharelist )
1085{
1086   OSMesaContext osmesa;
1087   struct dd_function_table functions;
1088   GLint rind, gind, bind, aind;
1089   GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
1090   GLboolean rgbmode;
1091   GLenum type = CHAN_TYPE;
1092
1093   rind = gind = bind = aind = 0;
1094   if (format==OSMESA_COLOR_INDEX) {
1095      indexBits = 8;
1096      rgbmode = GL_FALSE;
1097   }
1098   else if (format==OSMESA_RGBA) {
1099      indexBits = 0;
1100      redBits = CHAN_BITS;
1101      greenBits = CHAN_BITS;
1102      blueBits = CHAN_BITS;
1103      alphaBits = CHAN_BITS;
1104      rind = 0;
1105      gind = 1;
1106      bind = 2;
1107      aind = 3;
1108      rgbmode = GL_TRUE;
1109   }
1110   else if (format==OSMESA_BGRA) {
1111      indexBits = 0;
1112      redBits = CHAN_BITS;
1113      greenBits = CHAN_BITS;
1114      blueBits = CHAN_BITS;
1115      alphaBits = CHAN_BITS;
1116      bind = 0;
1117      gind = 1;
1118      rind = 2;
1119      aind = 3;
1120      rgbmode = GL_TRUE;
1121   }
1122   else if (format==OSMESA_ARGB) {
1123      indexBits = 0;
1124      redBits = CHAN_BITS;
1125      greenBits = CHAN_BITS;
1126      blueBits = CHAN_BITS;
1127      alphaBits = CHAN_BITS;
1128      aind = 0;
1129      rind = 1;
1130      gind = 2;
1131      bind = 3;
1132      rgbmode = GL_TRUE;
1133   }
1134   else if (format==OSMESA_RGB) {
1135      indexBits = 0;
1136      redBits = CHAN_BITS;
1137      greenBits = CHAN_BITS;
1138      blueBits = CHAN_BITS;
1139      alphaBits = 0;
1140      rind = 0;
1141      gind = 1;
1142      bind = 2;
1143      rgbmode = GL_TRUE;
1144   }
1145   else if (format==OSMESA_BGR) {
1146      indexBits = 0;
1147      redBits = CHAN_BITS;
1148      greenBits = CHAN_BITS;
1149      blueBits = CHAN_BITS;
1150      alphaBits = 0;
1151      rind = 2;
1152      gind = 1;
1153      bind = 0;
1154      rgbmode = GL_TRUE;
1155   }
1156#if CHAN_TYPE == GL_UNSIGNED_BYTE
1157   else if (format==OSMESA_RGB_565) {
1158      indexBits = 0;
1159      redBits = 5;
1160      greenBits = 6;
1161      blueBits = 5;
1162      alphaBits = 0;
1163      rind = 0; /* not used */
1164      gind = 0;
1165      bind = 0;
1166      rgbmode = GL_TRUE;
1167   }
1168#endif
1169   else {
1170      return NULL;
1171   }
1172
1173   osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
1174   if (osmesa) {
1175      osmesa->gl_visual = _mesa_create_visual( rgbmode,
1176                                               GL_FALSE,    /* double buffer */
1177                                               GL_FALSE,    /* stereo */
1178                                               redBits,
1179                                               greenBits,
1180                                               blueBits,
1181                                               alphaBits,
1182                                               indexBits,
1183                                               depthBits,
1184                                               stencilBits,
1185                                               accumBits,
1186                                               accumBits,
1187                                               accumBits,
1188                                               alphaBits ? accumBits : 0,
1189                                               1            /* num samples */
1190                                               );
1191      if (!osmesa->gl_visual) {
1192         _mesa_free(osmesa);
1193         return NULL;
1194      }
1195
1196      /* Initialize device driver function table */
1197      _mesa_init_driver_functions(&functions);
1198      /* override with our functions */
1199      functions.GetString = get_string;
1200      functions.UpdateState = osmesa_update_state;
1201      functions.GetBufferSize = NULL;
1202
1203      if (!_mesa_initialize_context(&osmesa->mesa,
1204                                    osmesa->gl_visual,
1205                                    sharelist ? &sharelist->mesa
1206                                              : (GLcontext *) NULL,
1207                                    &functions, (void *) osmesa)) {
1208         _mesa_destroy_visual( osmesa->gl_visual );
1209         _mesa_free(osmesa);
1210         return NULL;
1211      }
1212
1213      _mesa_enable_sw_extensions(&(osmesa->mesa));
1214      _mesa_enable_1_3_extensions(&(osmesa->mesa));
1215      _mesa_enable_1_4_extensions(&(osmesa->mesa));
1216      _mesa_enable_1_5_extensions(&(osmesa->mesa));
1217      _mesa_enable_2_0_extensions(&(osmesa->mesa));
1218      _mesa_enable_2_1_extensions(&(osmesa->mesa));
1219
1220      osmesa->gl_buffer = _mesa_create_framebuffer(osmesa->gl_visual);
1221      if (!osmesa->gl_buffer) {
1222         _mesa_destroy_visual( osmesa->gl_visual );
1223         _mesa_free_context_data( &osmesa->mesa );
1224         _mesa_free(osmesa);
1225         return NULL;
1226      }
1227
1228      /* create front color buffer in user-provided memory (no back buffer) */
1229      osmesa->rb = new_osmesa_renderbuffer(&osmesa->mesa, format, type);
1230      _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, osmesa->rb);
1231      assert(osmesa->rb->RefCount == 2);
1232
1233      _mesa_add_soft_renderbuffers(osmesa->gl_buffer,
1234                                   GL_FALSE, /* color */
1235                                   osmesa->gl_visual->haveDepthBuffer,
1236                                   osmesa->gl_visual->haveStencilBuffer,
1237                                   osmesa->gl_visual->haveAccumBuffer,
1238                                   GL_FALSE, /* alpha */
1239                                   GL_FALSE /* aux */ );
1240
1241      osmesa->format = format;
1242      osmesa->userRowLength = 0;
1243      osmesa->yup = GL_TRUE;
1244      osmesa->rInd = rind;
1245      osmesa->gInd = gind;
1246      osmesa->bInd = bind;
1247      osmesa->aInd = aind;
1248
1249      _mesa_meta_init(&osmesa->mesa);
1250
1251      /* Initialize the software rasterizer and helper modules. */
1252      {
1253	 GLcontext *ctx = &osmesa->mesa;
1254         SWcontext *swrast;
1255         TNLcontext *tnl;
1256
1257	 if (!_swrast_CreateContext( ctx ) ||
1258             !_vbo_CreateContext( ctx ) ||
1259             !_tnl_CreateContext( ctx ) ||
1260             !_swsetup_CreateContext( ctx )) {
1261            _mesa_destroy_visual(osmesa->gl_visual);
1262            _mesa_free_context_data(ctx);
1263            _mesa_free(osmesa);
1264            return NULL;
1265         }
1266
1267	 _swsetup_Wakeup( ctx );
1268
1269         /* use default TCL pipeline */
1270         tnl = TNL_CONTEXT(ctx);
1271         tnl->Driver.RunPipeline = _tnl_run_pipeline;
1272
1273         /* Extend the software rasterizer with our optimized line and triangle
1274          * drawing functions.
1275          */
1276         swrast = SWRAST_CONTEXT( ctx );
1277         swrast->choose_line = osmesa_choose_line;
1278         swrast->choose_triangle = osmesa_choose_triangle;
1279      }
1280   }
1281   return osmesa;
1282}
1283
1284
1285/**
1286 * Destroy an Off-Screen Mesa rendering context.
1287 *
1288 * \param osmesa  the context to destroy
1289 */
1290GLAPI void GLAPIENTRY
1291OSMesaDestroyContext( OSMesaContext osmesa )
1292{
1293   if (osmesa) {
1294      if (osmesa->rb)
1295         _mesa_reference_renderbuffer(&osmesa->rb, NULL);
1296
1297      _mesa_meta_free( &osmesa->mesa );
1298
1299      _swsetup_DestroyContext( &osmesa->mesa );
1300      _tnl_DestroyContext( &osmesa->mesa );
1301      _vbo_DestroyContext( &osmesa->mesa );
1302      _swrast_DestroyContext( &osmesa->mesa );
1303
1304      _mesa_destroy_visual( osmesa->gl_visual );
1305      _mesa_reference_framebuffer( &osmesa->gl_buffer, NULL );
1306
1307      _mesa_free_context_data( &osmesa->mesa );
1308      _mesa_free( osmesa );
1309   }
1310}
1311
1312
1313/**
1314 * Bind an OSMesaContext to an image buffer.  The image buffer is just a
1315 * block of memory which the client provides.  Its size must be at least
1316 * as large as width*height*sizeof(type).  Its address should be a multiple
1317 * of 4 if using RGBA mode.
1318 *
1319 * Image data is stored in the order of glDrawPixels:  row-major order
1320 * with the lower-left image pixel stored in the first array position
1321 * (ie. bottom-to-top).
1322 *
1323 * If the context's viewport hasn't been initialized yet, it will now be
1324 * initialized to (0,0,width,height).
1325 *
1326 * Input:  osmesa - the rendering context
1327 *         buffer - the image buffer memory
1328 *         type - data type for pixel components
1329 *            Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5
1330 *            are supported.  But if Mesa's been compiled with CHAN_BITS==16
1331 *            then type may be GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE.  And if
1332 *            Mesa's been build with CHAN_BITS==32 then type may be GL_FLOAT,
1333 *            GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE.
1334 *         width, height - size of image buffer in pixels, at least 1
1335 * Return:  GL_TRUE if success, GL_FALSE if error because of invalid osmesa,
1336 *          invalid buffer address, invalid type, width<1, height<1,
1337 *          width>internal limit or height>internal limit.
1338 */
1339GLAPI GLboolean GLAPIENTRY
1340OSMesaMakeCurrent( OSMesaContext osmesa, void *buffer, GLenum type,
1341                   GLsizei width, GLsizei height )
1342{
1343   if (!osmesa || !buffer ||
1344       width < 1 || height < 1 ||
1345       width > MAX_WIDTH || height > MAX_HEIGHT) {
1346      return GL_FALSE;
1347   }
1348
1349   if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5) {
1350      return GL_FALSE;
1351   }
1352
1353#if 0
1354   if (!(type == GL_UNSIGNED_BYTE ||
1355         (type == GL_UNSIGNED_SHORT && CHAN_BITS >= 16) ||
1356         (type == GL_FLOAT && CHAN_BITS == 32))) {
1357      /* i.e. is sizeof(type) * 8 > CHAN_BITS? */
1358      return GL_FALSE;
1359   }
1360#endif
1361
1362   osmesa_update_state( &osmesa->mesa, 0 );
1363
1364   /* Call this periodically to detect when the user has begun using
1365    * GL rendering from multiple threads.
1366    */
1367   _glapi_check_multithread();
1368
1369   /* Set renderbuffer fields.  Set width/height = 0 to force
1370    * osmesa_renderbuffer_storage() being called by _mesa_resize_framebuffer()
1371    */
1372   osmesa->rb->Data = buffer;
1373   osmesa->rb->DataType = type;
1374   osmesa->rb->Width = osmesa->rb->Height = 0;
1375
1376   /* Set the framebuffer's size.  This causes the
1377    * osmesa_renderbuffer_storage() function to get called.
1378    */
1379   _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
1380   osmesa->gl_buffer->Initialized = GL_TRUE; /* XXX TEMPORARY? */
1381
1382   _mesa_make_current( &osmesa->mesa, osmesa->gl_buffer, osmesa->gl_buffer );
1383
1384   /* Remove renderbuffer attachment, then re-add.  This installs the
1385    * renderbuffer adaptor/wrapper if needed (for bpp conversion).
1386    */
1387   _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT);
1388   _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, osmesa->rb);
1389
1390
1391   /* this updates the visual's red/green/blue/alphaBits fields */
1392   _mesa_update_framebuffer_visual(osmesa->gl_buffer);
1393
1394   /* update the framebuffer size */
1395   _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
1396
1397   return GL_TRUE;
1398}
1399
1400
1401
1402GLAPI OSMesaContext GLAPIENTRY
1403OSMesaGetCurrentContext( void )
1404{
1405   GLcontext *ctx = _mesa_get_current_context();
1406   if (ctx)
1407      return (OSMesaContext) ctx;
1408   else
1409      return NULL;
1410}
1411
1412
1413
1414GLAPI void GLAPIENTRY
1415OSMesaPixelStore( GLint pname, GLint value )
1416{
1417   OSMesaContext osmesa = OSMesaGetCurrentContext();
1418
1419   switch (pname) {
1420      case OSMESA_ROW_LENGTH:
1421         if (value<0) {
1422            _mesa_error( &osmesa->mesa, GL_INVALID_VALUE,
1423                      "OSMesaPixelStore(value)" );
1424            return;
1425         }
1426         osmesa->userRowLength = value;
1427         break;
1428      case OSMESA_Y_UP:
1429         osmesa->yup = value ? GL_TRUE : GL_FALSE;
1430         break;
1431      default:
1432         _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
1433         return;
1434   }
1435
1436   compute_row_addresses( osmesa );
1437}
1438
1439
1440GLAPI void GLAPIENTRY
1441OSMesaGetIntegerv( GLint pname, GLint *value )
1442{
1443   OSMesaContext osmesa = OSMesaGetCurrentContext();
1444
1445   switch (pname) {
1446      case OSMESA_WIDTH:
1447         if (osmesa->gl_buffer)
1448            *value = osmesa->gl_buffer->Width;
1449         else
1450            *value = 0;
1451         return;
1452      case OSMESA_HEIGHT:
1453         if (osmesa->gl_buffer)
1454            *value = osmesa->gl_buffer->Height;
1455         else
1456            *value = 0;
1457         return;
1458      case OSMESA_FORMAT:
1459         *value = osmesa->format;
1460         return;
1461      case OSMESA_TYPE:
1462         /* current color buffer's data type */
1463         if (osmesa->rb) {
1464            *value = osmesa->rb->DataType;
1465         }
1466         else {
1467            *value = 0;
1468         }
1469         return;
1470      case OSMESA_ROW_LENGTH:
1471         *value = osmesa->userRowLength;
1472         return;
1473      case OSMESA_Y_UP:
1474         *value = osmesa->yup;
1475         return;
1476      case OSMESA_MAX_WIDTH:
1477         *value = MAX_WIDTH;
1478         return;
1479      case OSMESA_MAX_HEIGHT:
1480         *value = MAX_HEIGHT;
1481         return;
1482      default:
1483         _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
1484         return;
1485   }
1486}
1487
1488
1489/**
1490 * Return the depth buffer associated with an OSMesa context.
1491 * Input:  c - the OSMesa context
1492 * Output:  width, height - size of buffer in pixels
1493 *          bytesPerValue - bytes per depth value (2 or 4)
1494 *          buffer - pointer to depth buffer values
1495 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1496 */
1497GLAPI GLboolean GLAPIENTRY
1498OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
1499                      GLint *bytesPerValue, void **buffer )
1500{
1501   struct gl_renderbuffer *rb = NULL;
1502
1503   if (c->gl_buffer)
1504      rb = c->gl_buffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1505
1506   if (!rb || !rb->Data) {
1507      *width = 0;
1508      *height = 0;
1509      *bytesPerValue = 0;
1510      *buffer = 0;
1511      return GL_FALSE;
1512   }
1513   else {
1514      *width = rb->Width;
1515      *height = rb->Height;
1516      if (c->gl_visual->depthBits <= 16)
1517         *bytesPerValue = sizeof(GLushort);
1518      else
1519         *bytesPerValue = sizeof(GLuint);
1520      *buffer = rb->Data;
1521      return GL_TRUE;
1522   }
1523}
1524
1525
1526/**
1527 * Return the color buffer associated with an OSMesa context.
1528 * Input:  c - the OSMesa context
1529 * Output:  width, height - size of buffer in pixels
1530 *          format - the pixel format (OSMESA_FORMAT)
1531 *          buffer - pointer to color buffer values
1532 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1533 */
1534GLAPI GLboolean GLAPIENTRY
1535OSMesaGetColorBuffer( OSMesaContext osmesa, GLint *width,
1536                      GLint *height, GLint *format, void **buffer )
1537{
1538   if (osmesa->rb && osmesa->rb->Data) {
1539      *width = osmesa->rb->Width;
1540      *height = osmesa->rb->Height;
1541      *format = osmesa->format;
1542      *buffer = osmesa->rb->Data;
1543      return GL_TRUE;
1544   }
1545   else {
1546      *width = 0;
1547      *height = 0;
1548      *format = 0;
1549      *buffer = 0;
1550      return GL_FALSE;
1551   }
1552}
1553
1554
1555struct name_function
1556{
1557   const char *Name;
1558   OSMESAproc Function;
1559};
1560
1561static struct name_function functions[] = {
1562   { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
1563   { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
1564   { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
1565   { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
1566   { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
1567   { "OSMesaPixelsStore", (OSMESAproc) OSMesaPixelStore },
1568   { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
1569   { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
1570   { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
1571   { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
1572   { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp },
1573   { NULL, NULL }
1574};
1575
1576
1577GLAPI OSMESAproc GLAPIENTRY
1578OSMesaGetProcAddress( const char *funcName )
1579{
1580   int i;
1581   for (i = 0; functions[i].Name; i++) {
1582      if (strcmp(functions[i].Name, funcName) == 0)
1583         return functions[i].Function;
1584   }
1585   return _glapi_get_proc_address(funcName);
1586}
1587
1588
1589GLAPI void GLAPIENTRY
1590OSMesaColorClamp(GLboolean enable)
1591{
1592   OSMesaContext osmesa = OSMesaGetCurrentContext();
1593
1594   if (enable == GL_TRUE) {
1595      osmesa->mesa.Color.ClampFragmentColor = GL_TRUE;
1596   }
1597   else {
1598      osmesa->mesa.Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
1599   }
1600}
1601
1602
1603