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