Implemented support for software-based AUX color buffers.
[mesa.git] / src / mesa / drivers / osmesa / osmesa.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.1
4 *
5 * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26 /*
27 * Off-Screen Mesa rendering / Rendering into client memory space
28 *
29 * Note on thread safety: this driver is thread safe. All
30 * functions are reentrant. The notion of current context is
31 * managed by the core _mesa_make_current() and _mesa_get_current_context()
32 * functions. Those functions are thread-safe.
33 */
34
35
36 #include "glheader.h"
37 #include "GL/osmesa.h"
38 #include "buffers.h"
39 #include "bufferobj.h"
40 #include "context.h"
41 #include "colormac.h"
42 #include "depth.h"
43 #include "extensions.h"
44 #include "imports.h"
45 #include "macros.h"
46 #include "matrix.h"
47 #include "mtypes.h"
48 #include "texformat.h"
49 #include "texobj.h"
50 #include "teximage.h"
51 #include "texstore.h"
52 #include "array_cache/acache.h"
53 #include "swrast/swrast.h"
54 #include "swrast_setup/swrast_setup.h"
55 #include "swrast/s_context.h"
56 #include "swrast/s_depth.h"
57 #include "swrast/s_lines.h"
58 #include "swrast/s_triangle.h"
59 #include "tnl/tnl.h"
60 #include "tnl/t_context.h"
61 #include "tnl/t_pipeline.h"
62 #include "drivers/common/driverfuncs.h"
63
64
65
66 /*
67 * This is the OS/Mesa context struct.
68 * Notice how it includes a GLcontext. By doing this we're mimicking
69 * C++ inheritance/derivation.
70 * Later, we can cast a GLcontext pointer into an OSMesaContext pointer
71 * or vice versa.
72 */
73 struct osmesa_context {
74 GLcontext mesa; /* The core GL/Mesa context */
75 GLvisual *gl_visual; /* Describes the buffers */
76 GLframebuffer *gl_buffer; /* Depth, stencil, accum, etc buffers */
77 GLenum format; /* either GL_RGBA or GL_COLOR_INDEX */
78 void *buffer; /* the image buffer */
79 GLint width, height; /* size of image buffer */
80 GLint rowlength; /* number of pixels per row */
81 GLint userRowLength; /* user-specified number of pixels per row */
82 GLint rshift, gshift; /* bit shifts for RGBA formats */
83 GLint bshift, ashift;
84 GLint rInd, gInd, bInd, aInd;/* index offsets for RGBA formats */
85 GLchan *rowaddr[MAX_HEIGHT]; /* address of first pixel in each image row */
86 GLboolean yup; /* TRUE -> Y increases upward */
87 /* FALSE -> Y increases downward */
88 };
89
90
91 /* Just cast, since we're using structure containment */
92 #define OSMESA_CONTEXT(ctx) ((OSMesaContext) (ctx->DriverCtx))
93
94
95
96 /**********************************************************************/
97 /*** Private Device Driver Functions ***/
98 /**********************************************************************/
99
100
101 static const GLubyte *
102 get_string( GLcontext *ctx, GLenum name )
103 {
104 (void) ctx;
105 switch (name) {
106 case GL_RENDERER:
107 #if CHAN_BITS == 32
108 return (const GLubyte *) "Mesa OffScreen32";
109 #elif CHAN_BITS == 16
110 return (const GLubyte *) "Mesa OffScreen16";
111 #else
112 return (const GLubyte *) "Mesa OffScreen";
113 #endif
114 default:
115 return NULL;
116 }
117 }
118
119
120 static void
121 osmesa_update_state( GLcontext *ctx, GLuint new_state )
122 {
123 /* easy - just propogate */
124 _swrast_InvalidateState( ctx, new_state );
125 _swsetup_InvalidateState( ctx, new_state );
126 _ac_InvalidateState( ctx, new_state );
127 _tnl_InvalidateState( ctx, new_state );
128 }
129
130
131 static void
132 set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit )
133 {
134 /* separate read buffer not supported */
135 ASSERT(buffer == ctx->DrawBuffer);
136 ASSERT(bufferBit == DD_FRONT_LEFT_BIT);
137 }
138
139
140 static void
141 get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
142 {
143 /* don't use GET_CURRENT_CONTEXT(ctx) here - it's a problem on Windows */
144 GLcontext *ctx = (GLcontext *) _glapi_get_context();
145 (void) buffer;
146 if (ctx) {
147 OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
148 *width = osmesa->width;
149 *height = osmesa->height;
150 }
151 }
152
153
154 static void
155 clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
156 GLint x, GLint y, GLint width, GLint height )
157 {
158 OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
159 const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
160
161 /* sanity check - we only have a front-left buffer */
162 ASSERT((mask & (DD_FRONT_RIGHT_BIT |
163 DD_BACK_LEFT_BIT |
164 DD_BACK_RIGHT_BIT)) == 0);
165
166 /* use optimized clear for common cases (clear whole buffer to black) */
167 if (mask & DD_FRONT_LEFT_BIT) {
168 if (osmesa->format == OSMESA_COLOR_INDEX) {
169 if (ctx->Color.ClearIndex == 0 &&
170 ctx->Color.IndexMask == (GLuint) ~0 &&
171 osmesa->rowlength == osmesa->width &&
172 all) {
173 /* clear whole buffer to zeros */
174 _mesa_bzero(osmesa->buffer,
175 osmesa->width * osmesa->height * sizeof(GLchan));
176 mask &= ~DD_FRONT_LEFT_BIT;
177 }
178 }
179 else {
180 /* RGB[A] format */
181 if (*colorMask == 0xffffffff &&
182 ctx->Color.ClearColor[0] == 0.0F &&
183 ctx->Color.ClearColor[1] == 0.0F &&
184 ctx->Color.ClearColor[2] == 0.0F &&
185 ctx->Color.ClearColor[3] == 0.0F &&
186 osmesa->rowlength == osmesa->width &&
187 all) {
188 GLint bytesPerPixel;
189 /* clear whole buffer to black */
190 if (osmesa->format == OSMESA_RGBA ||
191 osmesa->format == OSMESA_BGRA ||
192 osmesa->format == OSMESA_ARGB)
193 bytesPerPixel = 4 * sizeof(GLchan);
194 else if (osmesa->format == OSMESA_RGB ||
195 osmesa->format == OSMESA_BGR)
196 bytesPerPixel = 3 * sizeof(GLchan);
197 else if (osmesa->format == OSMESA_RGB_565)
198 bytesPerPixel = sizeof(GLushort);
199 else {
200 _mesa_problem(ctx, "bad pixel format in osmesa_clear()");
201 return;
202 }
203 _mesa_bzero(osmesa->buffer,
204 bytesPerPixel * osmesa->width * osmesa->height);
205 mask &= ~DD_FRONT_LEFT_BIT;
206 }
207 }
208 }
209
210 if (mask) {
211 /* software fallback (spans) for everything else. */
212 _swrast_Clear(ctx, mask, all, x, y, width, height);
213 }
214 }
215
216
217 /**********************************************************************/
218 /***** Read/write spans/arrays of pixels *****/
219 /**********************************************************************/
220
221
222 /* RGBA */
223 #define NAME(PREFIX) PREFIX##_RGBA
224 #define SPAN_VARS \
225 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
226 #define INIT_PIXEL_PTR(P, X, Y) \
227 GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
228 #define INC_PIXEL_PTR(P) P += 4
229 #if CHAN_TYPE == GL_FLOAT
230 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
231 P[0] = MAX2((R), 0.0F); \
232 P[1] = MAX2((G), 0.0F); \
233 P[2] = MAX2((B), 0.0F); \
234 P[3] = CHAN_MAXF
235 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
236 P[0] = MAX2((R), 0.0F); \
237 P[1] = MAX2((G), 0.0F); \
238 P[2] = MAX2((B), 0.0F); \
239 P[3] = CLAMP((A), 0.0F, CHAN_MAXF)
240 #else
241 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
242 P[0] = R; P[1] = G; P[2] = B; P[3] = CHAN_MAX
243 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
244 P[0] = R; P[1] = G; P[2] = B; P[3] = A
245 #endif
246 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
247 R = P[0]; G = P[1]; B = P[2]; A = P[3]
248 #include "swrast/s_spantemp.h"
249
250 /* BGRA */
251 #define NAME(PREFIX) PREFIX##_BGRA
252 #define SPAN_VARS \
253 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
254 #define INIT_PIXEL_PTR(P, X, Y) \
255 GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
256 #define INC_PIXEL_PTR(P) P += 4
257 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
258 P[2] = R; P[1] = G; P[0] = B; P[3] = CHAN_MAX
259 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
260 P[2] = R; P[1] = G; P[0] = B; P[3] = A
261 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
262 R = P[2]; G = P[1]; B = P[0]; A = P[3]
263 #include "swrast/s_spantemp.h"
264
265 /* ARGB */
266 #define NAME(PREFIX) PREFIX##_ARGB
267 #define SPAN_VARS \
268 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
269 #define INIT_PIXEL_PTR(P, X, Y) \
270 GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
271 #define INC_PIXEL_PTR(P) P += 4
272 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
273 P[1] = R; P[2] = G; P[3] = B; P[0] = CHAN_MAX
274 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
275 P[1] = R; P[2] = G; P[3] = B; P[0] = A
276 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
277 R = P[1]; G = P[2]; B = P[3]; A = P[0]
278 #include "swrast/s_spantemp.h"
279
280 /* RGB */
281 #define NAME(PREFIX) PREFIX##_RGB
282 #define SPAN_VARS \
283 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
284 #define INIT_PIXEL_PTR(P, X, Y) \
285 GLchan *P = osmesa->rowaddr[Y] + 3 * (X)
286 #define INC_PIXEL_PTR(P) P += 3
287 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
288 P[0] = R; P[1] = G; P[2] = B
289 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
290 P[0] = R; P[1] = G; P[2] = B
291 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
292 R = P[0]; G = P[1]; B = P[2]; A = CHAN_MAX
293 #include "swrast/s_spantemp.h"
294
295 /* BGR */
296 #define NAME(PREFIX) PREFIX##_BGR
297 #define SPAN_VARS \
298 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
299 #define INIT_PIXEL_PTR(P, X, Y) \
300 GLchan *P = osmesa->rowaddr[Y] + 3 * (X)
301 #define INC_PIXEL_PTR(P) P += 3
302 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
303 P[0] = B; P[1] = G; P[2] = R
304 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
305 P[0] = B; P[1] = G; P[2] = R
306 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
307 B = P[0]; G = P[1]; R = P[2]; A = CHAN_MAX
308 #include "swrast/s_spantemp.h"
309
310 /* 16-bit BGR */
311 #if CHAN_TYPE == GL_UNSIGNED_BYTE
312 #define NAME(PREFIX) PREFIX##_RGB_565
313 #define SPAN_VARS \
314 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
315 #define INIT_PIXEL_PTR(P, X, Y) \
316 GLushort *P = (GLushort *) osmesa->rowaddr[Y] + (X)
317 #define INC_PIXEL_PTR(P) P += 1
318 #define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
319 *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
320 #define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
321 *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
322 #define FETCH_RGBA_PIXEL(R, G, B, A, P) \
323 R = ( (((*P) >> 8) & 0xf8) | (((*P) >> 11) & 0x7) ); \
324 G = ( (((*P) >> 3) & 0xfc) | (((*P) >> 5) & 0x3) ); \
325 B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \
326 A = CHAN_MAX
327 #include "swrast/s_spantemp.h"
328 #endif
329
330 /* color index */
331 #define NAME(PREFIX) PREFIX##_CI
332 #define SPAN_VARS \
333 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
334 #define INIT_PIXEL_PTR(P, X, Y) \
335 GLchan *P = osmesa->rowaddr[Y] + (X)
336 #define INC_PIXEL_PTR(P) P += 1
337 #define STORE_CI_PIXEL(P, CI) \
338 P[0] = CI
339 #define FETCH_CI_PIXEL(CI, P) \
340 CI = P[0]
341 #include "swrast/s_spantemp.h"
342
343
344 /**********************************************************************/
345 /***** Optimized line rendering *****/
346 /**********************************************************************/
347
348
349 #if CHAN_TYPE == GL_FLOAT
350 #define PACK_RGBA(DST, R, G, B, A) \
351 do { \
352 (DST)[0] = MAX2( R, 0.0F ); \
353 (DST)[1] = MAX2( G, 0.0F ); \
354 (DST)[2] = MAX2( B, 0.0F ); \
355 (DST)[3] = CLAMP(A, 0.0F, CHAN_MAXF);\
356 } while (0)
357 #else
358 #define PACK_RGBA(DST, R, G, B, A) \
359 do { \
360 (DST)[osmesa->rInd] = R; \
361 (DST)[osmesa->gInd] = G; \
362 (DST)[osmesa->bInd] = B; \
363 (DST)[osmesa->aInd] = A; \
364 } while (0)
365 #endif
366
367 #define PACK_RGB(DST, R, G, B) \
368 do { \
369 (DST)[0] = R; \
370 (DST)[1] = G; \
371 (DST)[2] = B; \
372 } while (0)
373
374 #define PACK_BGR(DST, R, G, B) \
375 do { \
376 (DST)[0] = B; \
377 (DST)[1] = G; \
378 (DST)[2] = R; \
379 } while (0)
380
381 #define PACK_RGB_565(DST, R, G, B) \
382 do { \
383 (DST) = (((int) (R) << 8) & 0xf800) | (((int) (G) << 3) & 0x7e0) | ((int) (B) >> 3);\
384 } while (0)
385
386 #define UNPACK_RED(P) ( (P)[osmesa->rInd] )
387 #define UNPACK_GREEN(P) ( (P)[osmesa->gInd] )
388 #define UNPACK_BLUE(P) ( (P)[osmesa->bInd] )
389 #define UNPACK_ALPHA(P) ( (P)[osmesa->aInd] )
390
391 #define PIXELADDR1(X,Y) (osmesa->rowaddr[Y] + (X))
392 #define PIXELADDR2(X,Y) (osmesa->rowaddr[Y] + 2 * (X))
393 #define PIXELADDR3(X,Y) (osmesa->rowaddr[Y] + 3 * (X))
394 #define PIXELADDR4(X,Y) (osmesa->rowaddr[Y] + 4 * (X))
395
396
397 /*
398 * Draw a flat-shaded, RGB line into an osmesa buffer.
399 */
400 #define NAME flat_rgba_line
401 #define CLIP_HACK 1
402 #define SETUP_CODE \
403 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \
404 const GLchan *color = vert1->color;
405
406 #define PLOT(X, Y) \
407 do { \
408 GLchan *p = PIXELADDR4(X, Y); \
409 PACK_RGBA(p, color[0], color[1], color[2], color[3]); \
410 } while (0)
411
412 #ifdef WIN32
413 #include "..\swrast\s_linetemp.h"
414 #else
415 #include "swrast/s_linetemp.h"
416 #endif
417
418
419
420 /*
421 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
422 */
423 #define NAME flat_rgba_z_line
424 #define CLIP_HACK 1
425 #define INTERP_Z 1
426 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
427 #define SETUP_CODE \
428 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \
429 const GLchan *color = vert1->color;
430
431 #define PLOT(X, Y) \
432 do { \
433 if (Z < *zPtr) { \
434 GLchan *p = PIXELADDR4(X, Y); \
435 PACK_RGBA(p, color[RCOMP], color[GCOMP], \
436 color[BCOMP], color[ACOMP]); \
437 *zPtr = Z; \
438 } \
439 } while (0)
440
441 #ifdef WIN32
442 #include "..\swrast\s_linetemp.h"
443 #else
444 #include "swrast/s_linetemp.h"
445 #endif
446
447
448
449 /*
450 * Analyze context state to see if we can provide a fast line drawing
451 * function, like those in lines.c. Otherwise, return NULL.
452 */
453 static swrast_line_func
454 osmesa_choose_line_function( GLcontext *ctx )
455 {
456 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
457 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
458
459 if (CHAN_BITS != 8) return NULL;
460 if (ctx->RenderMode != GL_RENDER) return NULL;
461 if (ctx->Line.SmoothFlag) return NULL;
462 if (ctx->Texture._EnabledUnits) return NULL;
463 if (ctx->Light.ShadeModel != GL_FLAT) return NULL;
464 if (ctx->Line.Width != 1.0F) return NULL;
465 if (ctx->Line.StippleFlag) return NULL;
466 if (ctx->Line.SmoothFlag) return NULL;
467 if (osmesa->format != OSMESA_RGBA &&
468 osmesa->format != OSMESA_BGRA &&
469 osmesa->format != OSMESA_ARGB) return NULL;
470
471 if (swrast->_RasterMask==DEPTH_BIT
472 && ctx->Depth.Func==GL_LESS
473 && ctx->Depth.Mask==GL_TRUE
474 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
475 return (swrast_line_func) flat_rgba_z_line;
476 }
477
478 if (swrast->_RasterMask == 0) {
479 return (swrast_line_func) flat_rgba_line;
480 }
481
482 return (swrast_line_func) NULL;
483 }
484
485
486 /**********************************************************************/
487 /***** Optimized triangle rendering *****/
488 /**********************************************************************/
489
490
491 /*
492 * Smooth-shaded, z-less triangle, RGBA color.
493 */
494 #define NAME smooth_rgba_z_triangle
495 #define INTERP_Z 1
496 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
497 #define INTERP_RGB 1
498 #define INTERP_ALPHA 1
499 #define SETUP_CODE \
500 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
501 #define RENDER_SPAN( span ) \
502 GLuint i; \
503 GLchan *img = PIXELADDR4(span.x, span.y); \
504 for (i = 0; i < span.end; i++, img += 4) { \
505 const GLdepth z = FixedToDepth(span.z); \
506 if (z < zRow[i]) { \
507 PACK_RGBA(img, FixedToChan(span.red), \
508 FixedToChan(span.green), FixedToChan(span.blue), \
509 FixedToChan(span.alpha)); \
510 zRow[i] = z; \
511 } \
512 span.red += span.redStep; \
513 span.green += span.greenStep; \
514 span.blue += span.blueStep; \
515 span.alpha += span.alphaStep; \
516 span.z += span.zStep; \
517 }
518 #ifdef WIN32
519 #include "..\swrast\s_tritemp.h"
520 #else
521 #include "swrast/s_tritemp.h"
522 #endif
523
524
525
526 /*
527 * Flat-shaded, z-less triangle, RGBA color.
528 */
529 #define NAME flat_rgba_z_triangle
530 #define INTERP_Z 1
531 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
532 #define SETUP_CODE \
533 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \
534 GLuint pixel; \
535 PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1], \
536 v2->color[2], v2->color[3]);
537
538 #define RENDER_SPAN( span ) \
539 GLuint i; \
540 GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y); \
541 for (i = 0; i < span.end; i++) { \
542 const GLdepth z = FixedToDepth(span.z); \
543 if (z < zRow[i]) { \
544 img[i] = pixel; \
545 zRow[i] = z; \
546 } \
547 span.z += span.zStep; \
548 }
549 #ifdef WIN32
550 #include "..\swrast\s_tritemp.h"
551 #else
552 #include "swrast/s_tritemp.h"
553 #endif
554
555
556
557 /*
558 * Return pointer to an accelerated triangle function if possible.
559 */
560 static swrast_tri_func
561 osmesa_choose_triangle_function( GLcontext *ctx )
562 {
563 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
564 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
565
566 if (CHAN_BITS != 8) return (swrast_tri_func) NULL;
567 if (ctx->RenderMode != GL_RENDER) return (swrast_tri_func) NULL;
568 if (ctx->Polygon.SmoothFlag) return (swrast_tri_func) NULL;
569 if (ctx->Polygon.StippleFlag) return (swrast_tri_func) NULL;
570 if (ctx->Texture._EnabledUnits) return (swrast_tri_func) NULL;
571 if (osmesa->format != OSMESA_RGBA &&
572 osmesa->format != OSMESA_BGRA &&
573 osmesa->format != OSMESA_ARGB) return (swrast_tri_func) NULL;
574 if (ctx->Polygon.CullFlag &&
575 ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
576 return (swrast_tri_func) NULL;
577
578 if (swrast->_RasterMask == DEPTH_BIT &&
579 ctx->Depth.Func == GL_LESS &&
580 ctx->Depth.Mask == GL_TRUE &&
581 ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
582 if (ctx->Light.ShadeModel == GL_SMOOTH) {
583 return (swrast_tri_func) smooth_rgba_z_triangle;
584 }
585 else {
586 return (swrast_tri_func) flat_rgba_z_triangle;
587 }
588 }
589 return (swrast_tri_func) NULL;
590 }
591
592
593
594 /* Override for the swrast triangle-selection function. Try to use one
595 * of our internal triangle functions, otherwise fall back to the
596 * standard swrast functions.
597 */
598 static void
599 osmesa_choose_triangle( GLcontext *ctx )
600 {
601 SWcontext *swrast = SWRAST_CONTEXT(ctx);
602
603 swrast->Triangle = osmesa_choose_triangle_function( ctx );
604 if (!swrast->Triangle)
605 _swrast_choose_triangle( ctx );
606 }
607
608 static void
609 osmesa_choose_line( GLcontext *ctx )
610 {
611 SWcontext *swrast = SWRAST_CONTEXT(ctx);
612
613 swrast->Line = osmesa_choose_line_function( ctx );
614 if (!swrast->Line)
615 _swrast_choose_line( ctx );
616 }
617
618
619 #define OSMESA_NEW_LINE (_NEW_LINE | \
620 _NEW_TEXTURE | \
621 _NEW_LIGHT | \
622 _NEW_DEPTH | \
623 _NEW_RENDERMODE | \
624 _SWRAST_NEW_RASTERMASK)
625
626 #define OSMESA_NEW_TRIANGLE (_NEW_POLYGON | \
627 _NEW_TEXTURE | \
628 _NEW_LIGHT | \
629 _NEW_DEPTH | \
630 _NEW_RENDERMODE | \
631 _SWRAST_NEW_RASTERMASK)
632
633
634 /* one-time, per-context initialization */
635 static void
636 hook_in_driver_functions( GLcontext *ctx )
637 {
638 OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
639 SWcontext *swrast = SWRAST_CONTEXT( ctx );
640 struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx );
641 TNLcontext *tnl = TNL_CONTEXT(ctx);
642
643 ASSERT((void *) osmesa == (void *) ctx->DriverCtx);
644
645 /* use default TCL pipeline */
646 tnl->Driver.RunPipeline = _tnl_run_pipeline;
647
648 swdd->SetBuffer = set_buffer;
649
650 /* RGB(A) span/pixel functions */
651 if (osmesa->format == OSMESA_RGB) {
652 swdd->WriteRGBASpan = write_rgba_span_RGB;
653 swdd->WriteRGBSpan = write_rgb_span_RGB;
654 swdd->WriteMonoRGBASpan = write_monorgba_span_RGB;
655 swdd->WriteRGBAPixels = write_rgba_pixels_RGB;
656 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB;
657 swdd->ReadRGBASpan = read_rgba_span_RGB;
658 swdd->ReadRGBAPixels = read_rgba_pixels_RGB;
659 }
660 else if (osmesa->format == OSMESA_BGR) {
661 swdd->WriteRGBASpan = write_rgba_span_BGR;
662 swdd->WriteRGBSpan = write_rgb_span_BGR;
663 swdd->WriteMonoRGBASpan = write_monorgba_span_BGR;
664 swdd->WriteRGBAPixels = write_rgba_pixels_BGR;
665 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGR;
666 swdd->ReadRGBASpan = read_rgba_span_BGR;
667 swdd->ReadRGBAPixels = read_rgba_pixels_BGR;
668 }
669 #if CHAN_TYPE == GL_UNSIGNED_BYTE
670 else if (osmesa->format == OSMESA_RGB_565) {
671 swdd->WriteRGBASpan = write_rgba_span_RGB_565;
672 swdd->WriteRGBSpan = write_rgb_span_RGB_565;
673 swdd->WriteMonoRGBASpan = write_monorgba_span_RGB_565;
674 swdd->WriteRGBAPixels = write_rgba_pixels_RGB_565;
675 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB_565;
676 swdd->ReadRGBASpan = read_rgba_span_RGB_565;
677 swdd->ReadRGBAPixels = read_rgba_pixels_RGB_565;
678 }
679 #endif
680 else if (osmesa->format == OSMESA_RGBA) {
681 swdd->WriteRGBASpan = write_rgba_span_RGBA;
682 swdd->WriteRGBSpan = write_rgb_span_RGBA;
683 swdd->WriteMonoRGBASpan = write_monorgba_span_RGBA;
684 swdd->WriteRGBAPixels = write_rgba_pixels_RGBA;
685 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGBA;
686 swdd->ReadRGBASpan = read_rgba_span_RGBA;
687 swdd->ReadRGBAPixels = read_rgba_pixels_RGBA;
688 }
689 else if (osmesa->format == OSMESA_BGRA) {
690 swdd->WriteRGBASpan = write_rgba_span_BGRA;
691 swdd->WriteRGBSpan = write_rgb_span_BGRA;
692 swdd->WriteMonoRGBASpan = write_monorgba_span_BGRA;
693 swdd->WriteRGBAPixels = write_rgba_pixels_BGRA;
694 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGRA;
695 swdd->ReadRGBASpan = read_rgba_span_BGRA;
696 swdd->ReadRGBAPixels = read_rgba_pixels_BGRA;
697 }
698 else if (osmesa->format == OSMESA_ARGB) {
699 swdd->WriteRGBASpan = write_rgba_span_ARGB;
700 swdd->WriteRGBSpan = write_rgb_span_ARGB;
701 swdd->WriteMonoRGBASpan = write_monorgba_span_ARGB;
702 swdd->WriteRGBAPixels = write_rgba_pixels_ARGB;
703 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_ARGB;
704 swdd->ReadRGBASpan = read_rgba_span_ARGB;
705 swdd->ReadRGBAPixels = read_rgba_pixels_ARGB;
706 }
707 else if (osmesa->format == OSMESA_COLOR_INDEX) {
708 swdd->WriteCI32Span = write_index32_span_CI;
709 swdd->WriteCI8Span = write_index8_span_CI;
710 swdd->WriteMonoCISpan = write_monoindex_span_CI;
711 swdd->WriteCI32Pixels = write_index_pixels_CI;
712 swdd->WriteMonoCIPixels = write_monoindex_pixels_CI;
713 swdd->ReadCI32Span = read_index_span_CI;
714 swdd->ReadCI32Pixels = read_index_pixels_CI;
715 }
716 else {
717 _mesa_problem(ctx, "bad pixel format in osmesa_update_state!\n");
718 }
719
720 /* Extend the software rasterizer with our optimized line and triangle
721 * drawin functions.
722 */
723 swrast->choose_line = osmesa_choose_line;
724 swrast->choose_triangle = osmesa_choose_triangle;
725 swrast->invalidate_line |= OSMESA_NEW_LINE;
726 swrast->invalidate_triangle |= OSMESA_NEW_TRIANGLE;
727 }
728
729
730
731
732 /**********************************************************************/
733 /***** Public Functions *****/
734 /**********************************************************************/
735
736
737 /*
738 * Create an Off-Screen Mesa rendering context. The only attribute needed is
739 * an RGBA vs Color-Index mode flag.
740 *
741 * Input: format - either GL_RGBA or GL_COLOR_INDEX
742 * sharelist - specifies another OSMesaContext with which to share
743 * display lists. NULL indicates no sharing.
744 * Return: an OSMesaContext or 0 if error
745 */
746 GLAPI OSMesaContext GLAPIENTRY
747 OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
748 {
749 const GLint accumBits = (format == OSMESA_COLOR_INDEX) ? 0 : 16;
750 return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS,
751 8, accumBits, sharelist);
752 }
753
754
755
756 /*
757 * New in Mesa 3.5
758 *
759 * Create context and specify size of ancillary buffers.
760 */
761 GLAPI OSMesaContext GLAPIENTRY
762 OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
763 GLint accumBits, OSMesaContext sharelist )
764 {
765 OSMesaContext osmesa;
766 struct dd_function_table functions;
767 GLint rshift, gshift, bshift, ashift;
768 GLint rind, gind, bind, aind;
769 GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
770 GLboolean rgbmode;
771 const GLuint i4 = 1;
772 const GLubyte *i1 = (GLubyte *) &i4;
773 const GLint little_endian = *i1;
774
775 rind = gind = bind = aind = 0;
776 if (format==OSMESA_COLOR_INDEX) {
777 indexBits = 8;
778 rshift = gshift = bshift = ashift = 0;
779 rgbmode = GL_FALSE;
780 }
781 else if (format==OSMESA_RGBA) {
782 indexBits = 0;
783 redBits = CHAN_BITS;
784 greenBits = CHAN_BITS;
785 blueBits = CHAN_BITS;
786 alphaBits = CHAN_BITS;
787 rind = 0;
788 gind = 1;
789 bind = 2;
790 aind = 3;
791 if (little_endian) {
792 rshift = 0;
793 gshift = 8;
794 bshift = 16;
795 ashift = 24;
796 }
797 else {
798 rshift = 24;
799 gshift = 16;
800 bshift = 8;
801 ashift = 0;
802 }
803 rgbmode = GL_TRUE;
804 }
805 else if (format==OSMESA_BGRA) {
806 indexBits = 0;
807 redBits = CHAN_BITS;
808 greenBits = CHAN_BITS;
809 blueBits = CHAN_BITS;
810 alphaBits = CHAN_BITS;
811 bind = 0;
812 gind = 1;
813 rind = 2;
814 aind = 3;
815 if (little_endian) {
816 bshift = 0;
817 gshift = 8;
818 rshift = 16;
819 ashift = 24;
820 }
821 else {
822 bshift = 24;
823 gshift = 16;
824 rshift = 8;
825 ashift = 0;
826 }
827 rgbmode = GL_TRUE;
828 }
829 else if (format==OSMESA_ARGB) {
830 indexBits = 0;
831 redBits = CHAN_BITS;
832 greenBits = CHAN_BITS;
833 blueBits = CHAN_BITS;
834 alphaBits = CHAN_BITS;
835 aind = 0;
836 rind = 1;
837 gind = 2;
838 bind = 3;
839 if (little_endian) {
840 ashift = 0;
841 rshift = 8;
842 gshift = 16;
843 bshift = 24;
844 }
845 else {
846 ashift = 24;
847 rshift = 16;
848 gshift = 8;
849 bshift = 0;
850 }
851 rgbmode = GL_TRUE;
852 }
853 else if (format==OSMESA_RGB) {
854 indexBits = 0;
855 redBits = CHAN_BITS;
856 greenBits = CHAN_BITS;
857 blueBits = CHAN_BITS;
858 alphaBits = 0;
859 bshift = 0;
860 gshift = 8;
861 rshift = 16;
862 ashift = 24;
863 rind = 0;
864 gind = 1;
865 bind = 2;
866 rgbmode = GL_TRUE;
867 }
868 else if (format==OSMESA_BGR) {
869 indexBits = 0;
870 redBits = CHAN_BITS;
871 greenBits = CHAN_BITS;
872 blueBits = CHAN_BITS;
873 alphaBits = 0;
874 bshift = 0;
875 gshift = 8;
876 rshift = 16;
877 ashift = 24;
878 rind = 2;
879 gind = 1;
880 bind = 0;
881 rgbmode = GL_TRUE;
882 }
883 #if CHAN_TYPE == GL_UNSIGNED_BYTE
884 else if (format==OSMESA_RGB_565) {
885 indexBits = 0;
886 redBits = 5;
887 greenBits = 6;
888 blueBits = 5;
889 alphaBits = 0;
890 rshift = 11;
891 gshift = 5;
892 bshift = 0;
893 ashift = 0;
894 rind = 0; /* not used */
895 gind = 0;
896 bind = 0;
897 rgbmode = GL_TRUE;
898 }
899 #endif
900 else {
901 return NULL;
902 }
903
904
905 osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
906 if (osmesa) {
907 osmesa->gl_visual = _mesa_create_visual( rgbmode,
908 GL_FALSE, /* double buffer */
909 GL_FALSE, /* stereo */
910 redBits,
911 greenBits,
912 blueBits,
913 alphaBits,
914 indexBits,
915 depthBits,
916 stencilBits,
917 accumBits,
918 accumBits,
919 accumBits,
920 alphaBits ? accumBits : 0,
921 1 /* num samples */
922 );
923 if (!osmesa->gl_visual) {
924 FREE(osmesa);
925 return NULL;
926 }
927
928 /* Initialize device driver function table */
929 _mesa_init_driver_functions(&functions);
930 /* override with our functions */
931 functions.GetString = get_string;
932 functions.UpdateState = osmesa_update_state;
933 functions.GetBufferSize = get_buffer_size;
934 functions.Clear = clear;
935
936 if (!_mesa_initialize_context(&osmesa->mesa,
937 osmesa->gl_visual,
938 sharelist ? &sharelist->mesa
939 : (GLcontext *) NULL,
940 &functions, (void *) osmesa)) {
941 _mesa_destroy_visual( osmesa->gl_visual );
942 FREE(osmesa);
943 return NULL;
944 }
945
946 _mesa_enable_sw_extensions(&(osmesa->mesa));
947 _mesa_enable_1_3_extensions(&(osmesa->mesa));
948 _mesa_enable_1_4_extensions(&(osmesa->mesa));
949 _mesa_enable_1_5_extensions(&(osmesa->mesa));
950
951 osmesa->gl_buffer = _mesa_create_framebuffer( osmesa->gl_visual,
952 (GLboolean) ( osmesa->gl_visual->depthBits > 0 ),
953 (GLboolean) ( osmesa->gl_visual->stencilBits > 0 ),
954 (GLboolean) ( osmesa->gl_visual->accumRedBits > 0 ),
955 GL_FALSE /* s/w alpha */ );
956
957 if (!osmesa->gl_buffer) {
958 _mesa_destroy_visual( osmesa->gl_visual );
959 _mesa_free_context_data( &osmesa->mesa );
960 FREE(osmesa);
961 return NULL;
962 }
963 osmesa->format = format;
964 osmesa->buffer = NULL;
965 osmesa->width = 0;
966 osmesa->height = 0;
967 osmesa->userRowLength = 0;
968 osmesa->rowlength = 0;
969 osmesa->yup = GL_TRUE;
970 osmesa->rshift = rshift;
971 osmesa->gshift = gshift;
972 osmesa->bshift = bshift;
973 osmesa->ashift = ashift;
974 osmesa->rInd = rind;
975 osmesa->gInd = gind;
976 osmesa->bInd = bind;
977 osmesa->aInd = aind;
978
979 /* Initialize the software rasterizer and helper modules. */
980 {
981 GLcontext *ctx = &osmesa->mesa;
982
983 _swrast_CreateContext( ctx );
984 _ac_CreateContext( ctx );
985 _tnl_CreateContext( ctx );
986 _swsetup_CreateContext( ctx );
987
988 _swsetup_Wakeup( ctx );
989 hook_in_driver_functions( ctx );
990 }
991 }
992 return osmesa;
993 }
994
995
996 /*
997 * Destroy an Off-Screen Mesa rendering context.
998 *
999 * Input: ctx - the context to destroy
1000 */
1001 GLAPI void GLAPIENTRY
1002 OSMesaDestroyContext( OSMesaContext ctx )
1003 {
1004 if (ctx) {
1005 _swsetup_DestroyContext( &ctx->mesa );
1006 _tnl_DestroyContext( &ctx->mesa );
1007 _ac_DestroyContext( &ctx->mesa );
1008 _swrast_DestroyContext( &ctx->mesa );
1009
1010 _mesa_destroy_visual( ctx->gl_visual );
1011 _mesa_destroy_framebuffer( ctx->gl_buffer );
1012 _mesa_free_context_data( &ctx->mesa );
1013 FREE( ctx );
1014 }
1015 }
1016
1017
1018 /*
1019 * Recompute the values of the context's rowaddr array.
1020 */
1021 static void
1022 compute_row_addresses( OSMesaContext ctx )
1023 {
1024 GLint bytesPerPixel, bytesPerRow, i;
1025 GLubyte *origin = (GLubyte *) ctx->buffer;
1026
1027 if (ctx->format == OSMESA_COLOR_INDEX) {
1028 /* CI mode */
1029 bytesPerPixel = 1 * sizeof(GLchan);
1030 }
1031 else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) {
1032 /* RGB mode */
1033 bytesPerPixel = 3 * sizeof(GLchan);
1034 }
1035 else if (ctx->format == OSMESA_RGB_565) {
1036 /* 5/6/5 RGB pixel in 16 bits */
1037 bytesPerPixel = 2;
1038 }
1039 else {
1040 /* RGBA mode */
1041 bytesPerPixel = 4 * sizeof(GLchan);
1042 }
1043
1044 bytesPerRow = ctx->rowlength * bytesPerPixel;
1045
1046 if (ctx->yup) {
1047 /* Y=0 is bottom line of window */
1048 for (i = 0; i < MAX_HEIGHT; i++) {
1049 ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow);
1050 }
1051 }
1052 else {
1053 /* Y=0 is top line of window */
1054 for (i = 0; i < MAX_HEIGHT; i++) {
1055 GLint j = ctx->height - i - 1;
1056 ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow);
1057 }
1058 }
1059 }
1060
1061
1062 /*
1063 * Bind an OSMesaContext to an image buffer. The image buffer is just a
1064 * block of memory which the client provides. Its size must be at least
1065 * as large as width*height*sizeof(type). Its address should be a multiple
1066 * of 4 if using RGBA mode.
1067 *
1068 * Image data is stored in the order of glDrawPixels: row-major order
1069 * with the lower-left image pixel stored in the first array position
1070 * (ie. bottom-to-top).
1071 *
1072 * If the context's viewport hasn't been initialized yet, it will now be
1073 * initialized to (0,0,width,height).
1074 *
1075 * Input: ctx - the rendering context
1076 * buffer - the image buffer memory
1077 * type - data type for pixel components
1078 * Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5
1079 * are supported. But if Mesa's been compiled with CHAN_BITS==16
1080 * then type must be GL_UNSIGNED_SHORT. And if Mesa's been build
1081 * with CHAN_BITS==32 then type must be GL_FLOAT.
1082 * width, height - size of image buffer in pixels, at least 1
1083 * Return: GL_TRUE if success, GL_FALSE if error because of invalid ctx,
1084 * invalid buffer address, invalid type, width<1, height<1,
1085 * width>internal limit or height>internal limit.
1086 */
1087 GLAPI GLboolean GLAPIENTRY
1088 OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type,
1089 GLsizei width, GLsizei height )
1090 {
1091 if (!ctx || !buffer ||
1092 width < 1 || height < 1 ||
1093 width > MAX_WIDTH || height > MAX_HEIGHT) {
1094 return GL_FALSE;
1095 }
1096
1097 if (ctx->format == OSMESA_RGB_565) {
1098 if (type != GL_UNSIGNED_SHORT_5_6_5)
1099 return GL_FALSE;
1100 }
1101 else if (type != CHAN_TYPE) {
1102 return GL_FALSE;
1103 }
1104
1105 osmesa_update_state( &ctx->mesa, 0 );
1106 _mesa_make_current( &ctx->mesa, ctx->gl_buffer );
1107
1108 ctx->buffer = buffer;
1109 ctx->width = width;
1110 ctx->height = height;
1111 if (ctx->userRowLength)
1112 ctx->rowlength = ctx->userRowLength;
1113 else
1114 ctx->rowlength = width;
1115
1116 compute_row_addresses( ctx );
1117
1118 /* init viewport */
1119 if (ctx->mesa.Viewport.Width == 0) {
1120 /* initialize viewport and scissor box to buffer size */
1121 _mesa_Viewport( 0, 0, width, height );
1122 ctx->mesa.Scissor.Width = width;
1123 ctx->mesa.Scissor.Height = height;
1124 }
1125 else {
1126 /* this will make ensure we recognize the new buffer size */
1127 _mesa_ResizeBuffersMESA();
1128 }
1129
1130 /* Added by Gerk Huisma: */
1131 _tnl_MakeCurrent( &ctx->mesa, ctx->mesa.DrawBuffer,
1132 ctx->mesa.ReadBuffer );
1133
1134 return GL_TRUE;
1135 }
1136
1137
1138
1139 GLAPI OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void )
1140 {
1141 GLcontext *ctx = _mesa_get_current_context();
1142 if (ctx)
1143 return (OSMesaContext) ctx;
1144 else
1145 return NULL;
1146 }
1147
1148
1149
1150 GLAPI void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value )
1151 {
1152 OSMesaContext osmesa = OSMesaGetCurrentContext();
1153
1154 switch (pname) {
1155 case OSMESA_ROW_LENGTH:
1156 if (value<0) {
1157 _mesa_error( &osmesa->mesa, GL_INVALID_VALUE,
1158 "OSMesaPixelStore(value)" );
1159 return;
1160 }
1161 osmesa->userRowLength = value;
1162 osmesa->rowlength = value ? value : osmesa->width;
1163 break;
1164 case OSMESA_Y_UP:
1165 osmesa->yup = value ? GL_TRUE : GL_FALSE;
1166 break;
1167 default:
1168 _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
1169 return;
1170 }
1171
1172 compute_row_addresses( osmesa );
1173 }
1174
1175
1176 GLAPI void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value )
1177 {
1178 OSMesaContext osmesa = OSMesaGetCurrentContext();
1179
1180 switch (pname) {
1181 case OSMESA_WIDTH:
1182 *value = osmesa->width;
1183 return;
1184 case OSMESA_HEIGHT:
1185 *value = osmesa->height;
1186 return;
1187 case OSMESA_FORMAT:
1188 *value = osmesa->format;
1189 return;
1190 case OSMESA_TYPE:
1191 *value = CHAN_TYPE;
1192 return;
1193 case OSMESA_ROW_LENGTH:
1194 *value = osmesa->userRowLength;
1195 return;
1196 case OSMESA_Y_UP:
1197 *value = osmesa->yup;
1198 return;
1199 case OSMESA_MAX_WIDTH:
1200 *value = MAX_WIDTH;
1201 return;
1202 case OSMESA_MAX_HEIGHT:
1203 *value = MAX_HEIGHT;
1204 return;
1205 default:
1206 _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
1207 return;
1208 }
1209 }
1210
1211 /*
1212 * Return the depth buffer associated with an OSMesa context.
1213 * Input: c - the OSMesa context
1214 * Output: width, height - size of buffer in pixels
1215 * bytesPerValue - bytes per depth value (2 or 4)
1216 * buffer - pointer to depth buffer values
1217 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
1218 */
1219 GLAPI GLboolean GLAPIENTRY
1220 OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
1221 GLint *bytesPerValue, void **buffer )
1222 {
1223 if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) {
1224 *width = 0;
1225 *height = 0;
1226 *bytesPerValue = 0;
1227 *buffer = 0;
1228 return GL_FALSE;
1229 }
1230 else {
1231 *width = c->gl_buffer->Width;
1232 *height = c->gl_buffer->Height;
1233 if (c->gl_visual->depthBits <= 16)
1234 *bytesPerValue = sizeof(GLushort);
1235 else
1236 *bytesPerValue = sizeof(GLuint);
1237 *buffer = c->gl_buffer->DepthBuffer;
1238 return GL_TRUE;
1239 }
1240 }
1241
1242 /*
1243 * Return the color buffer associated with an OSMesa context.
1244 * Input: c - the OSMesa context
1245 * Output: width, height - size of buffer in pixels
1246 * format - the pixel format (OSMESA_FORMAT)
1247 * buffer - pointer to color buffer values
1248 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
1249 */
1250 GLAPI GLboolean GLAPIENTRY
1251 OSMesaGetColorBuffer( OSMesaContext c, GLint *width,
1252 GLint *height, GLint *format, void **buffer )
1253 {
1254 if (!c->buffer) {
1255 *width = 0;
1256 *height = 0;
1257 *format = 0;
1258 *buffer = 0;
1259 return GL_FALSE;
1260 }
1261 else {
1262 *width = c->width;
1263 *height = c->height;
1264 *format = c->format;
1265 *buffer = c->buffer;
1266 return GL_TRUE;
1267 }
1268 }
1269
1270
1271
1272 struct name_address {
1273 const char *Name;
1274 GLvoid *Address;
1275 };
1276
1277 static struct name_address functions[] = {
1278 { "OSMesaCreateContext", (void *) OSMesaCreateContext },
1279 { "OSMesaCreateContextExt", (void *) OSMesaCreateContextExt },
1280 { "OSMesaDestroyContext", (void *) OSMesaDestroyContext },
1281 { "OSMesaMakeCurrent", (void *) OSMesaMakeCurrent },
1282 { "OSMesaGetCurrentContext", (void *) OSMesaGetCurrentContext },
1283 { "OSMesaPixelsStore", (void *) OSMesaPixelStore },
1284 { "OSMesaGetIntegerv", (void *) OSMesaGetIntegerv },
1285 { "OSMesaGetDepthBuffer", (void *) OSMesaGetDepthBuffer },
1286 { "OSMesaGetColorBuffer", (void *) OSMesaGetColorBuffer },
1287 { "OSMesaGetProcAddress", (void *) OSMesaGetProcAddress },
1288 { NULL, NULL }
1289 };
1290
1291 GLAPI void * GLAPIENTRY
1292 OSMesaGetProcAddress( const char *funcName )
1293 {
1294 int i;
1295 for (i = 0; functions[i].Name; i++) {
1296 if (_mesa_strcmp(functions[i].Name, funcName) == 0)
1297 return (void *) functions[i].Address;
1298 }
1299 return (void *) _glapi_get_proc_address(funcName);
1300 }