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