small cleanup, remove some warnings
[mesa.git] / src / mesa / drivers / osmesa / osmesa.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.3
4 *
5 * Copyright (C) 1999-2005 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 if (!_swrast_CreateContext( ctx ) ||
984 !_ac_CreateContext( ctx ) ||
985 !_tnl_CreateContext( ctx ) ||
986 !_swsetup_CreateContext( ctx )) {
987 _mesa_destroy_visual(osmesa->gl_visual);
988 _mesa_free_context_data(ctx);
989 _mesa_free(osmesa);
990 return NULL;
991 }
992
993 _swsetup_Wakeup( ctx );
994 hook_in_driver_functions( ctx );
995 }
996 }
997 return osmesa;
998 }
999
1000
1001 /*
1002 * Destroy an Off-Screen Mesa rendering context.
1003 *
1004 * Input: ctx - the context to destroy
1005 */
1006 GLAPI void GLAPIENTRY
1007 OSMesaDestroyContext( OSMesaContext ctx )
1008 {
1009 if (ctx) {
1010 _swsetup_DestroyContext( &ctx->mesa );
1011 _tnl_DestroyContext( &ctx->mesa );
1012 _ac_DestroyContext( &ctx->mesa );
1013 _swrast_DestroyContext( &ctx->mesa );
1014
1015 _mesa_destroy_visual( ctx->gl_visual );
1016 _mesa_destroy_framebuffer( ctx->gl_buffer );
1017 _mesa_free_context_data( &ctx->mesa );
1018 FREE( ctx );
1019 }
1020 }
1021
1022
1023 /*
1024 * Recompute the values of the context's rowaddr array.
1025 */
1026 static void
1027 compute_row_addresses( OSMesaContext ctx )
1028 {
1029 GLint bytesPerPixel, bytesPerRow, i;
1030 GLubyte *origin = (GLubyte *) ctx->buffer;
1031
1032 if (ctx->format == OSMESA_COLOR_INDEX) {
1033 /* CI mode */
1034 bytesPerPixel = 1 * sizeof(GLchan);
1035 }
1036 else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) {
1037 /* RGB mode */
1038 bytesPerPixel = 3 * sizeof(GLchan);
1039 }
1040 else if (ctx->format == OSMESA_RGB_565) {
1041 /* 5/6/5 RGB pixel in 16 bits */
1042 bytesPerPixel = 2;
1043 }
1044 else {
1045 /* RGBA mode */
1046 bytesPerPixel = 4 * sizeof(GLchan);
1047 }
1048
1049 bytesPerRow = ctx->rowlength * bytesPerPixel;
1050
1051 if (ctx->yup) {
1052 /* Y=0 is bottom line of window */
1053 for (i = 0; i < MAX_HEIGHT; i++) {
1054 ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow);
1055 }
1056 }
1057 else {
1058 /* Y=0 is top line of window */
1059 for (i = 0; i < MAX_HEIGHT; i++) {
1060 GLint j = ctx->height - i - 1;
1061 ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow);
1062 }
1063 }
1064 }
1065
1066
1067 /*
1068 * Bind an OSMesaContext to an image buffer. The image buffer is just a
1069 * block of memory which the client provides. Its size must be at least
1070 * as large as width*height*sizeof(type). Its address should be a multiple
1071 * of 4 if using RGBA mode.
1072 *
1073 * Image data is stored in the order of glDrawPixels: row-major order
1074 * with the lower-left image pixel stored in the first array position
1075 * (ie. bottom-to-top).
1076 *
1077 * If the context's viewport hasn't been initialized yet, it will now be
1078 * initialized to (0,0,width,height).
1079 *
1080 * Input: ctx - the rendering context
1081 * buffer - the image buffer memory
1082 * type - data type for pixel components
1083 * Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5
1084 * are supported. But if Mesa's been compiled with CHAN_BITS==16
1085 * then type must be GL_UNSIGNED_SHORT. And if Mesa's been build
1086 * with CHAN_BITS==32 then type must be GL_FLOAT.
1087 * width, height - size of image buffer in pixels, at least 1
1088 * Return: GL_TRUE if success, GL_FALSE if error because of invalid ctx,
1089 * invalid buffer address, invalid type, width<1, height<1,
1090 * width>internal limit or height>internal limit.
1091 */
1092 GLAPI GLboolean GLAPIENTRY
1093 OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type,
1094 GLsizei width, GLsizei height )
1095 {
1096 if (!ctx || !buffer ||
1097 width < 1 || height < 1 ||
1098 width > MAX_WIDTH || height > MAX_HEIGHT) {
1099 return GL_FALSE;
1100 }
1101
1102 if (ctx->format == OSMESA_RGB_565) {
1103 if (type != GL_UNSIGNED_SHORT_5_6_5)
1104 return GL_FALSE;
1105 }
1106 else if (type != CHAN_TYPE) {
1107 return GL_FALSE;
1108 }
1109
1110 /* Need to set these before calling _mesa_make_current() since the first
1111 * time the context is bound, _mesa_make_current() will call our
1112 * get_buffer_size() function to initialize the viewport. These are the
1113 * values returned by get_buffer_size():
1114 */
1115 ctx->buffer = buffer;
1116 ctx->width = width;
1117 ctx->height = height;
1118
1119 osmesa_update_state( &ctx->mesa, 0 );
1120 _mesa_make_current( &ctx->mesa, ctx->gl_buffer );
1121
1122 if (ctx->userRowLength)
1123 ctx->rowlength = ctx->userRowLength;
1124 else
1125 ctx->rowlength = width;
1126
1127 compute_row_addresses( ctx );
1128
1129 /* this will make ensure we recognize the new buffer size */
1130 _mesa_ResizeBuffersMESA();
1131
1132 /* Added by Gerk Huisma: */
1133 _tnl_MakeCurrent( &ctx->mesa, ctx->mesa.DrawBuffer,
1134 ctx->mesa.ReadBuffer );
1135
1136 return GL_TRUE;
1137 }
1138
1139
1140
1141 GLAPI OSMesaContext GLAPIENTRY
1142 OSMesaGetCurrentContext( void )
1143 {
1144 GLcontext *ctx = _mesa_get_current_context();
1145 if (ctx)
1146 return (OSMesaContext) ctx;
1147 else
1148 return NULL;
1149 }
1150
1151
1152
1153 GLAPI void GLAPIENTRY
1154 OSMesaPixelStore( GLint pname, GLint value )
1155 {
1156 OSMesaContext osmesa = OSMesaGetCurrentContext();
1157
1158 switch (pname) {
1159 case OSMESA_ROW_LENGTH:
1160 if (value<0) {
1161 _mesa_error( &osmesa->mesa, GL_INVALID_VALUE,
1162 "OSMesaPixelStore(value)" );
1163 return;
1164 }
1165 osmesa->userRowLength = value;
1166 osmesa->rowlength = value ? value : osmesa->width;
1167 break;
1168 case OSMESA_Y_UP:
1169 osmesa->yup = value ? GL_TRUE : GL_FALSE;
1170 break;
1171 default:
1172 _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
1173 return;
1174 }
1175
1176 compute_row_addresses( osmesa );
1177 }
1178
1179
1180 GLAPI void GLAPIENTRY
1181 OSMesaGetIntegerv( GLint pname, GLint *value )
1182 {
1183 OSMesaContext osmesa = OSMesaGetCurrentContext();
1184
1185 switch (pname) {
1186 case OSMESA_WIDTH:
1187 *value = osmesa->width;
1188 return;
1189 case OSMESA_HEIGHT:
1190 *value = osmesa->height;
1191 return;
1192 case OSMESA_FORMAT:
1193 *value = osmesa->format;
1194 return;
1195 case OSMESA_TYPE:
1196 *value = CHAN_TYPE;
1197 return;
1198 case OSMESA_ROW_LENGTH:
1199 *value = osmesa->userRowLength;
1200 return;
1201 case OSMESA_Y_UP:
1202 *value = osmesa->yup;
1203 return;
1204 case OSMESA_MAX_WIDTH:
1205 *value = MAX_WIDTH;
1206 return;
1207 case OSMESA_MAX_HEIGHT:
1208 *value = MAX_HEIGHT;
1209 return;
1210 default:
1211 _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
1212 return;
1213 }
1214 }
1215
1216 /*
1217 * Return the depth buffer associated with an OSMesa context.
1218 * Input: c - the OSMesa context
1219 * Output: width, height - size of buffer in pixels
1220 * bytesPerValue - bytes per depth value (2 or 4)
1221 * buffer - pointer to depth buffer values
1222 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
1223 */
1224 GLAPI GLboolean GLAPIENTRY
1225 OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
1226 GLint *bytesPerValue, void **buffer )
1227 {
1228 if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) {
1229 *width = 0;
1230 *height = 0;
1231 *bytesPerValue = 0;
1232 *buffer = 0;
1233 return GL_FALSE;
1234 }
1235 else {
1236 *width = c->gl_buffer->Width;
1237 *height = c->gl_buffer->Height;
1238 if (c->gl_visual->depthBits <= 16)
1239 *bytesPerValue = sizeof(GLushort);
1240 else
1241 *bytesPerValue = sizeof(GLuint);
1242 *buffer = c->gl_buffer->DepthBuffer;
1243 return GL_TRUE;
1244 }
1245 }
1246
1247 /*
1248 * Return the color buffer associated with an OSMesa context.
1249 * Input: c - the OSMesa context
1250 * Output: width, height - size of buffer in pixels
1251 * format - the pixel format (OSMESA_FORMAT)
1252 * buffer - pointer to color buffer values
1253 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
1254 */
1255 GLAPI GLboolean GLAPIENTRY
1256 OSMesaGetColorBuffer( OSMesaContext c, GLint *width,
1257 GLint *height, GLint *format, void **buffer )
1258 {
1259 if (!c->buffer) {
1260 *width = 0;
1261 *height = 0;
1262 *format = 0;
1263 *buffer = 0;
1264 return GL_FALSE;
1265 }
1266 else {
1267 *width = c->width;
1268 *height = c->height;
1269 *format = c->format;
1270 *buffer = c->buffer;
1271 return GL_TRUE;
1272 }
1273 }
1274
1275
1276 struct name_function
1277 {
1278 const char *Name;
1279 OSMESAproc Function;
1280 };
1281
1282 static struct name_function functions[] = {
1283 { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
1284 { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
1285 { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
1286 { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
1287 { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
1288 { "OSMesaPixelsStore", (OSMESAproc) OSMesaPixelStore },
1289 { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
1290 { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
1291 { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
1292 { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
1293 { NULL, NULL }
1294 };
1295
1296
1297 GLAPI OSMESAproc GLAPIENTRY
1298 OSMesaGetProcAddress( const char *funcName )
1299 {
1300 int i;
1301 for (i = 0; functions[i].Name; i++) {
1302 if (_mesa_strcmp(functions[i].Name, funcName) == 0)
1303 return functions[i].Function;
1304 }
1305 return _glapi_get_proc_address(funcName);
1306 }