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