mesa: Make the drivers call a non-code-generated dispatch table setup.
[mesa.git] / src / mesa / drivers / osmesa / osmesa.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5.3
4 *
5 * Copyright (C) 1999-2007 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 "main/glheader.h"
37 #include "GL/osmesa.h"
38 #include "main/api_exec.h"
39 #include "main/context.h"
40 #include "main/extensions.h"
41 #include "main/formats.h"
42 #include "main/framebuffer.h"
43 #include "main/imports.h"
44 #include "main/macros.h"
45 #include "main/mtypes.h"
46 #include "main/renderbuffer.h"
47 #include "main/version.h"
48 #include "main/vtxfmt.h"
49 #include "swrast/swrast.h"
50 #include "swrast_setup/swrast_setup.h"
51 #include "swrast/s_context.h"
52 #include "swrast/s_lines.h"
53 #include "swrast/s_renderbuffer.h"
54 #include "swrast/s_triangle.h"
55 #include "tnl/tnl.h"
56 #include "tnl/t_context.h"
57 #include "tnl/t_pipeline.h"
58 #include "drivers/common/driverfuncs.h"
59 #include "drivers/common/meta.h"
60 #include "vbo/vbo.h"
61
62
63 #define OSMESA_RENDERBUFFER_CLASS 0x053
64
65
66 /**
67 * OSMesa rendering context, derived from core Mesa struct gl_context.
68 */
69 struct osmesa_context
70 {
71 struct gl_context mesa; /*< Base class - this must be first */
72 struct gl_config *gl_visual; /*< Describes the buffers */
73 struct swrast_renderbuffer *srb; /*< The user's colorbuffer */
74 struct gl_framebuffer *gl_buffer; /*< The framebuffer, containing user's rb */
75 GLenum format; /*< User-specified context format */
76 GLint userRowLength; /*< user-specified number of pixels per row */
77 GLint rInd, gInd, bInd, aInd;/*< index offsets for RGBA formats */
78 GLvoid *rowaddr[SWRAST_MAX_HEIGHT]; /*< address of first pixel in each image row */
79 GLboolean yup; /*< TRUE -> Y increases upward */
80 /*< FALSE -> Y increases downward */
81 GLenum DataType;
82 };
83
84
85 static INLINE OSMesaContext
86 OSMESA_CONTEXT(struct gl_context *ctx)
87 {
88 /* Just cast, since we're using structure containment */
89 return (OSMesaContext) ctx;
90 }
91
92
93 /**********************************************************************/
94 /*** Private Device Driver Functions ***/
95 /**********************************************************************/
96
97
98 static const GLubyte *
99 get_string( struct gl_context *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( struct gl_context *ctx, GLuint new_state )
119 {
120 /* easy - just propogate */
121 _swrast_InvalidateState( ctx, new_state );
122 _swsetup_InvalidateState( ctx, new_state );
123 _tnl_InvalidateState( ctx, new_state );
124 _vbo_InvalidateState( ctx, new_state );
125 }
126
127
128
129 /**
130 * Macros for optimized line/triangle rendering.
131 * Only for 8-bit channel, RGBA, BGRA, ARGB formats.
132 */
133
134 #define PACK_RGBA(DST, R, G, B, A) \
135 do { \
136 (DST)[osmesa->rInd] = R; \
137 (DST)[osmesa->gInd] = G; \
138 (DST)[osmesa->bInd] = B; \
139 (DST)[osmesa->aInd] = A; \
140 } while (0)
141
142 #define PIXELADDR4(X,Y) ((GLchan *) osmesa->rowaddr[Y] + 4 * (X))
143
144
145 /**
146 * Draw a flat-shaded, RGB line into an osmesa buffer.
147 */
148 #define NAME flat_rgba_line
149 #define CLIP_HACK 1
150 #define SETUP_CODE \
151 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \
152 const GLchan *color = vert1->color;
153
154 #define PLOT(X, Y) \
155 do { \
156 GLchan *p = PIXELADDR4(X, Y); \
157 PACK_RGBA(p, color[0], color[1], color[2], color[3]); \
158 } while (0)
159
160 #include "swrast/s_linetemp.h"
161
162
163
164 /**
165 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
166 */
167 #define NAME flat_rgba_z_line
168 #define CLIP_HACK 1
169 #define INTERP_Z 1
170 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
171 #define SETUP_CODE \
172 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \
173 const GLchan *color = vert1->color;
174
175 #define PLOT(X, Y) \
176 do { \
177 if (Z < *zPtr) { \
178 GLchan *p = PIXELADDR4(X, Y); \
179 PACK_RGBA(p, color[RCOMP], color[GCOMP], \
180 color[BCOMP], color[ACOMP]); \
181 *zPtr = Z; \
182 } \
183 } while (0)
184
185 #include "swrast/s_linetemp.h"
186
187
188
189 /**
190 * Analyze context state to see if we can provide a fast line drawing
191 * function. Otherwise, return NULL.
192 */
193 static swrast_line_func
194 osmesa_choose_line_function( struct gl_context *ctx )
195 {
196 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
197 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
198
199 if (ctx->RenderMode != GL_RENDER) return NULL;
200 if (ctx->Line.SmoothFlag) return NULL;
201 if (ctx->Texture._EnabledUnits) return NULL;
202 if (ctx->Light.ShadeModel != GL_FLAT) return NULL;
203 if (ctx->Line.Width != 1.0F) return NULL;
204 if (ctx->Line.StippleFlag) return NULL;
205 if (ctx->Line.SmoothFlag) return NULL;
206 if (osmesa->format != OSMESA_RGBA &&
207 osmesa->format != OSMESA_BGRA &&
208 osmesa->format != OSMESA_ARGB) return NULL;
209
210 if (swrast->_RasterMask==DEPTH_BIT
211 && ctx->Depth.Func==GL_LESS
212 && ctx->Depth.Mask==GL_TRUE
213 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
214 return (swrast_line_func) flat_rgba_z_line;
215 }
216
217 if (swrast->_RasterMask == 0) {
218 return (swrast_line_func) flat_rgba_line;
219 }
220
221 return (swrast_line_func) NULL;
222 }
223
224
225 /**********************************************************************/
226 /***** Optimized triangle rendering *****/
227 /**********************************************************************/
228
229
230 /*
231 * Smooth-shaded, z-less triangle, RGBA color.
232 */
233 #define NAME smooth_rgba_z_triangle
234 #define INTERP_Z 1
235 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
236 #define INTERP_RGB 1
237 #define INTERP_ALPHA 1
238 #define SETUP_CODE \
239 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
240 #define RENDER_SPAN( span ) { \
241 GLuint i; \
242 GLchan *img = PIXELADDR4(span.x, span.y); \
243 for (i = 0; i < span.end; i++, img += 4) { \
244 const GLuint z = FixedToDepth(span.z); \
245 if (z < zRow[i]) { \
246 PACK_RGBA(img, FixedToChan(span.red), \
247 FixedToChan(span.green), FixedToChan(span.blue), \
248 FixedToChan(span.alpha)); \
249 zRow[i] = z; \
250 } \
251 span.red += span.redStep; \
252 span.green += span.greenStep; \
253 span.blue += span.blueStep; \
254 span.alpha += span.alphaStep; \
255 span.z += span.zStep; \
256 } \
257 }
258 #include "swrast/s_tritemp.h"
259
260
261
262 /*
263 * Flat-shaded, z-less triangle, RGBA color.
264 */
265 #define NAME flat_rgba_z_triangle
266 #define INTERP_Z 1
267 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
268 #define SETUP_CODE \
269 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \
270 GLuint pixel; \
271 PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1], \
272 v2->color[2], v2->color[3]);
273
274 #define RENDER_SPAN( span ) { \
275 GLuint i; \
276 GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y); \
277 for (i = 0; i < span.end; i++) { \
278 const GLuint z = FixedToDepth(span.z); \
279 if (z < zRow[i]) { \
280 img[i] = pixel; \
281 zRow[i] = z; \
282 } \
283 span.z += span.zStep; \
284 } \
285 }
286
287 #include "swrast/s_tritemp.h"
288
289
290
291 /**
292 * Return pointer to an optimized triangle function if possible.
293 */
294 static swrast_tri_func
295 osmesa_choose_triangle_function( struct gl_context *ctx )
296 {
297 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
298 const SWcontext *swrast = SWRAST_CONTEXT(ctx);
299
300 if (ctx->RenderMode != GL_RENDER) return (swrast_tri_func) NULL;
301 if (ctx->Polygon.SmoothFlag) return (swrast_tri_func) NULL;
302 if (ctx->Polygon.StippleFlag) return (swrast_tri_func) NULL;
303 if (ctx->Texture._EnabledUnits) return (swrast_tri_func) NULL;
304 if (osmesa->format != OSMESA_RGBA &&
305 osmesa->format != OSMESA_BGRA &&
306 osmesa->format != OSMESA_ARGB) return (swrast_tri_func) NULL;
307 if (ctx->Polygon.CullFlag &&
308 ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
309 return (swrast_tri_func) NULL;
310
311 if (swrast->_RasterMask == DEPTH_BIT &&
312 ctx->Depth.Func == GL_LESS &&
313 ctx->Depth.Mask == GL_TRUE &&
314 ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
315 if (ctx->Light.ShadeModel == GL_SMOOTH) {
316 return (swrast_tri_func) smooth_rgba_z_triangle;
317 }
318 else {
319 return (swrast_tri_func) flat_rgba_z_triangle;
320 }
321 }
322 return (swrast_tri_func) NULL;
323 }
324
325
326
327 /* Override for the swrast triangle-selection function. Try to use one
328 * of our internal triangle functions, otherwise fall back to the
329 * standard swrast functions.
330 */
331 static void
332 osmesa_choose_triangle( struct gl_context *ctx )
333 {
334 SWcontext *swrast = SWRAST_CONTEXT(ctx);
335
336 swrast->Triangle = osmesa_choose_triangle_function( ctx );
337 if (!swrast->Triangle)
338 _swrast_choose_triangle( ctx );
339 }
340
341 static void
342 osmesa_choose_line( struct gl_context *ctx )
343 {
344 SWcontext *swrast = SWRAST_CONTEXT(ctx);
345
346 swrast->Line = osmesa_choose_line_function( ctx );
347 if (!swrast->Line)
348 _swrast_choose_line( ctx );
349 }
350
351
352
353 /**
354 * Recompute the values of the context's rowaddr array.
355 */
356 static void
357 compute_row_addresses( OSMesaContext osmesa )
358 {
359 GLint bytesPerRow, i;
360 GLubyte *origin = (GLubyte *) osmesa->srb->Buffer;
361 GLint rowlength; /* in pixels */
362 GLint height = osmesa->srb->Base.Height;
363
364 if (osmesa->userRowLength)
365 rowlength = osmesa->userRowLength;
366 else
367 rowlength = osmesa->srb->Base.Width;
368
369 bytesPerRow = rowlength * _mesa_get_format_bytes(osmesa->srb->Base.Format);
370
371 if (osmesa->yup) {
372 /* Y=0 is bottom line of window */
373 for (i = 0; i < height; i++) {
374 osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + i * bytesPerRow);
375 }
376 }
377 else {
378 /* Y=0 is top line of window */
379 for (i = 0; i < height; i++) {
380 GLint j = height - i - 1;
381 osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + j * bytesPerRow);
382 }
383 }
384 }
385
386
387
388 /**
389 * Don't use _mesa_delete_renderbuffer since we can't free rb->Buffer.
390 */
391 static void
392 osmesa_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
393 {
394 _mesa_delete_renderbuffer(ctx, rb);
395 }
396
397
398 /**
399 * Allocate renderbuffer storage. We don't actually allocate any storage
400 * since we're using a user-provided buffer.
401 * Just set up all the gl_renderbuffer methods.
402 */
403 static GLboolean
404 osmesa_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
405 GLenum internalFormat, GLuint width, GLuint height)
406 {
407 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
408
409 /* Note: we can ignoring internalFormat for "window-system" renderbuffers */
410 (void) internalFormat;
411
412 /* Given the user-provided format and type, figure out which MESA_FORMAT_x
413 * to use.
414 * XXX There aren't Mesa formats for all the possible combinations here!
415 * XXX Specifically, there's only RGBA-order 16-bit/channel and float
416 * XXX formats.
417 * XXX The 8-bit/channel formats should all be OK.
418 */
419 if (osmesa->format == OSMESA_RGBA) {
420 if (osmesa->DataType == GL_UNSIGNED_BYTE) {
421 if (_mesa_little_endian())
422 rb->Format = MESA_FORMAT_RGBA8888_REV;
423 else
424 rb->Format = MESA_FORMAT_RGBA8888;
425 }
426 else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
427 rb->Format = MESA_FORMAT_RGBA_16;
428 }
429 else {
430 rb->Format = MESA_FORMAT_RGBA_FLOAT32;
431 }
432 }
433 else if (osmesa->format == OSMESA_BGRA) {
434 if (osmesa->DataType == GL_UNSIGNED_BYTE) {
435 if (_mesa_little_endian())
436 rb->Format = MESA_FORMAT_ARGB8888;
437 else
438 rb->Format = MESA_FORMAT_ARGB8888_REV;
439 }
440 else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
441 _mesa_warning(ctx, "Unsupported OSMesa format BGRA/GLushort");
442 rb->Format = MESA_FORMAT_RGBA_16; /* not exactly right */
443 }
444 else {
445 _mesa_warning(ctx, "Unsupported OSMesa format BGRA/GLfloat");
446 rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */
447 }
448 }
449 else if (osmesa->format == OSMESA_ARGB) {
450 if (osmesa->DataType == GL_UNSIGNED_BYTE) {
451 if (_mesa_little_endian())
452 rb->Format = MESA_FORMAT_ARGB8888_REV;
453 else
454 rb->Format = MESA_FORMAT_ARGB8888;
455 }
456 else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
457 _mesa_warning(ctx, "Unsupported OSMesa format ARGB/GLushort");
458 rb->Format = MESA_FORMAT_RGBA_16; /* not exactly right */
459 }
460 else {
461 _mesa_warning(ctx, "Unsupported OSMesa format ARGB/GLfloat");
462 rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */
463 }
464 }
465 else if (osmesa->format == OSMESA_RGB) {
466 if (osmesa->DataType == GL_UNSIGNED_BYTE) {
467 rb->Format = MESA_FORMAT_RGB888;
468 }
469 else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
470 _mesa_warning(ctx, "Unsupported OSMesa format RGB/GLushort");
471 rb->Format = MESA_FORMAT_RGBA_16; /* not exactly right */
472 }
473 else {
474 _mesa_warning(ctx, "Unsupported OSMesa format RGB/GLfloat");
475 rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */
476 }
477 }
478 else if (osmesa->format == OSMESA_BGR) {
479 if (osmesa->DataType == GL_UNSIGNED_BYTE) {
480 rb->Format = MESA_FORMAT_BGR888;
481 }
482 else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
483 _mesa_warning(ctx, "Unsupported OSMesa format BGR/GLushort");
484 rb->Format = MESA_FORMAT_RGBA_16; /* not exactly right */
485 }
486 else {
487 _mesa_warning(ctx, "Unsupported OSMesa format BGR/GLfloat");
488 rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */
489 }
490 }
491 else if (osmesa->format == OSMESA_RGB_565) {
492 ASSERT(osmesa->DataType == GL_UNSIGNED_BYTE);
493 rb->Format = MESA_FORMAT_RGB565;
494 }
495 else {
496 _mesa_problem(ctx, "bad pixel format in osmesa renderbuffer_storage");
497 }
498
499 rb->Width = width;
500 rb->Height = height;
501
502 compute_row_addresses( osmesa );
503
504 return GL_TRUE;
505 }
506
507
508 /**
509 * Allocate a new renderbuffer to describe the user-provided color buffer.
510 */
511 static struct swrast_renderbuffer *
512 new_osmesa_renderbuffer(struct gl_context *ctx, GLenum format, GLenum type)
513 {
514 const GLuint name = 0;
515 struct swrast_renderbuffer *srb = CALLOC_STRUCT(swrast_renderbuffer);
516
517 if (srb) {
518 _mesa_init_renderbuffer(&srb->Base, name);
519
520 srb->Base.ClassID = OSMESA_RENDERBUFFER_CLASS;
521 srb->Base.RefCount = 1;
522 srb->Base.Delete = osmesa_delete_renderbuffer;
523 srb->Base.AllocStorage = osmesa_renderbuffer_storage;
524
525 srb->Base.InternalFormat = GL_RGBA;
526 srb->Base._BaseFormat = GL_RGBA;
527
528 return srb;
529 }
530 return NULL;
531 }
532
533
534
535 static void
536 osmesa_MapRenderbuffer(struct gl_context *ctx,
537 struct gl_renderbuffer *rb,
538 GLuint x, GLuint y, GLuint w, GLuint h,
539 GLbitfield mode,
540 GLubyte **mapOut, GLint *rowStrideOut)
541 {
542 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
543
544 if (rb->ClassID == OSMESA_RENDERBUFFER_CLASS) {
545 /* this is an OSMesa renderbuffer which wraps user memory */
546 struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
547 const GLuint bpp = _mesa_get_format_bytes(rb->Format);
548 GLint rowStride; /* in bytes */
549
550 if (osmesa->userRowLength)
551 rowStride = osmesa->userRowLength * bpp;
552 else
553 rowStride = rb->Width * bpp;
554
555 if (!osmesa->yup) {
556 /* Y=0 is top line of window */
557 y = rb->Height - y - 1;
558 *rowStrideOut = -rowStride;
559 }
560 else {
561 *rowStrideOut = rowStride;
562 }
563
564 *mapOut = (GLubyte *) srb->Buffer + y * rowStride + x * bpp;
565 }
566 else {
567 _swrast_map_soft_renderbuffer(ctx, rb, x, y, w, h, mode,
568 mapOut, rowStrideOut);
569 }
570 }
571
572
573 static void
574 osmesa_UnmapRenderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
575 {
576 if (rb->ClassID == OSMESA_RENDERBUFFER_CLASS) {
577 /* no-op */
578 }
579 else {
580 _swrast_unmap_soft_renderbuffer(ctx, rb);
581 }
582 }
583
584
585 /**********************************************************************/
586 /***** Public Functions *****/
587 /**********************************************************************/
588
589
590 /**
591 * Create an Off-Screen Mesa rendering context. The only attribute needed is
592 * an RGBA vs Color-Index mode flag.
593 *
594 * Input: format - Must be GL_RGBA
595 * sharelist - specifies another OSMesaContext with which to share
596 * display lists. NULL indicates no sharing.
597 * Return: an OSMesaContext or 0 if error
598 */
599 GLAPI OSMesaContext GLAPIENTRY
600 OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
601 {
602 return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS,
603 8, 0, sharelist);
604 }
605
606
607
608 /**
609 * New in Mesa 3.5
610 *
611 * Create context and specify size of ancillary buffers.
612 */
613 GLAPI OSMesaContext GLAPIENTRY
614 OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
615 GLint accumBits, OSMesaContext sharelist )
616 {
617 OSMesaContext osmesa;
618 struct dd_function_table functions;
619 GLint rind, gind, bind, aind;
620 GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
621
622 rind = gind = bind = aind = 0;
623 if (format==OSMESA_RGBA) {
624 redBits = CHAN_BITS;
625 greenBits = CHAN_BITS;
626 blueBits = CHAN_BITS;
627 alphaBits = CHAN_BITS;
628 rind = 0;
629 gind = 1;
630 bind = 2;
631 aind = 3;
632 }
633 else if (format==OSMESA_BGRA) {
634 redBits = CHAN_BITS;
635 greenBits = CHAN_BITS;
636 blueBits = CHAN_BITS;
637 alphaBits = CHAN_BITS;
638 bind = 0;
639 gind = 1;
640 rind = 2;
641 aind = 3;
642 }
643 else if (format==OSMESA_ARGB) {
644 redBits = CHAN_BITS;
645 greenBits = CHAN_BITS;
646 blueBits = CHAN_BITS;
647 alphaBits = CHAN_BITS;
648 aind = 0;
649 rind = 1;
650 gind = 2;
651 bind = 3;
652 }
653 else if (format==OSMESA_RGB) {
654 redBits = CHAN_BITS;
655 greenBits = CHAN_BITS;
656 blueBits = CHAN_BITS;
657 alphaBits = 0;
658 rind = 0;
659 gind = 1;
660 bind = 2;
661 }
662 else if (format==OSMESA_BGR) {
663 redBits = CHAN_BITS;
664 greenBits = CHAN_BITS;
665 blueBits = CHAN_BITS;
666 alphaBits = 0;
667 rind = 2;
668 gind = 1;
669 bind = 0;
670 }
671 #if CHAN_TYPE == GL_UNSIGNED_BYTE
672 else if (format==OSMESA_RGB_565) {
673 redBits = 5;
674 greenBits = 6;
675 blueBits = 5;
676 alphaBits = 0;
677 rind = 0; /* not used */
678 gind = 0;
679 bind = 0;
680 }
681 #endif
682 else {
683 return NULL;
684 }
685
686 osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
687 if (osmesa) {
688 osmesa->gl_visual = _mesa_create_visual( GL_FALSE, /* double buffer */
689 GL_FALSE, /* stereo */
690 redBits,
691 greenBits,
692 blueBits,
693 alphaBits,
694 depthBits,
695 stencilBits,
696 accumBits,
697 accumBits,
698 accumBits,
699 alphaBits ? accumBits : 0,
700 1 /* num samples */
701 );
702 if (!osmesa->gl_visual) {
703 free(osmesa);
704 return NULL;
705 }
706
707 /* Initialize device driver function table */
708 _mesa_init_driver_functions(&functions);
709 /* override with our functions */
710 functions.GetString = get_string;
711 functions.UpdateState = osmesa_update_state;
712 functions.GetBufferSize = NULL;
713
714 if (!_mesa_initialize_context(&osmesa->mesa,
715 API_OPENGL_COMPAT,
716 osmesa->gl_visual,
717 sharelist ? &sharelist->mesa
718 : (struct gl_context *) NULL,
719 &functions)) {
720 _mesa_destroy_visual( osmesa->gl_visual );
721 free(osmesa);
722 return NULL;
723 }
724
725 _mesa_enable_sw_extensions(&(osmesa->mesa));
726 _mesa_enable_1_3_extensions(&(osmesa->mesa));
727 _mesa_enable_1_4_extensions(&(osmesa->mesa));
728 _mesa_enable_1_5_extensions(&(osmesa->mesa));
729 _mesa_enable_2_0_extensions(&(osmesa->mesa));
730 _mesa_enable_2_1_extensions(&(osmesa->mesa));
731
732 osmesa->gl_buffer = _mesa_create_framebuffer(osmesa->gl_visual);
733 if (!osmesa->gl_buffer) {
734 _mesa_destroy_visual( osmesa->gl_visual );
735 _mesa_free_context_data( &osmesa->mesa );
736 free(osmesa);
737 return NULL;
738 }
739
740 /* Create depth/stencil/accum buffers. We'll create the color
741 * buffer later in OSMesaMakeCurrent().
742 */
743 _swrast_add_soft_renderbuffers(osmesa->gl_buffer,
744 GL_FALSE, /* color */
745 osmesa->gl_visual->haveDepthBuffer,
746 osmesa->gl_visual->haveStencilBuffer,
747 osmesa->gl_visual->haveAccumBuffer,
748 GL_FALSE, /* alpha */
749 GL_FALSE /* aux */ );
750
751 osmesa->format = format;
752 osmesa->userRowLength = 0;
753 osmesa->yup = GL_TRUE;
754 osmesa->rInd = rind;
755 osmesa->gInd = gind;
756 osmesa->bInd = bind;
757 osmesa->aInd = aind;
758
759 _mesa_meta_init(&osmesa->mesa);
760
761 /* Initialize the software rasterizer and helper modules. */
762 {
763 struct gl_context *ctx = &osmesa->mesa;
764 SWcontext *swrast;
765 TNLcontext *tnl;
766
767 if (!_swrast_CreateContext( ctx ) ||
768 !_vbo_CreateContext( ctx ) ||
769 !_tnl_CreateContext( ctx ) ||
770 !_swsetup_CreateContext( ctx )) {
771 _mesa_destroy_visual(osmesa->gl_visual);
772 _mesa_free_context_data(ctx);
773 free(osmesa);
774 return NULL;
775 }
776
777 _swsetup_Wakeup( ctx );
778
779 /* use default TCL pipeline */
780 tnl = TNL_CONTEXT(ctx);
781 tnl->Driver.RunPipeline = _tnl_run_pipeline;
782
783 ctx->Driver.MapRenderbuffer = osmesa_MapRenderbuffer;
784 ctx->Driver.UnmapRenderbuffer = osmesa_UnmapRenderbuffer;
785
786 /* Extend the software rasterizer with our optimized line and triangle
787 * drawing functions.
788 */
789 swrast = SWRAST_CONTEXT( ctx );
790 swrast->choose_line = osmesa_choose_line;
791 swrast->choose_triangle = osmesa_choose_triangle;
792
793 _mesa_compute_version(ctx);
794
795 /* Exec table initialization requires the version to be computed */
796 _mesa_initialize_dispatch_tables(ctx);
797 _mesa_initialize_vbo_vtxfmt(ctx);
798 }
799 }
800 return osmesa;
801 }
802
803
804 /**
805 * Destroy an Off-Screen Mesa rendering context.
806 *
807 * \param osmesa the context to destroy
808 */
809 GLAPI void GLAPIENTRY
810 OSMesaDestroyContext( OSMesaContext osmesa )
811 {
812 if (osmesa) {
813 if (osmesa->srb)
814 _mesa_reference_renderbuffer((struct gl_renderbuffer **) &osmesa->srb, NULL);
815
816 _mesa_meta_free( &osmesa->mesa );
817
818 _swsetup_DestroyContext( &osmesa->mesa );
819 _tnl_DestroyContext( &osmesa->mesa );
820 _vbo_DestroyContext( &osmesa->mesa );
821 _swrast_DestroyContext( &osmesa->mesa );
822
823 _mesa_destroy_visual( osmesa->gl_visual );
824 _mesa_reference_framebuffer( &osmesa->gl_buffer, NULL );
825
826 _mesa_free_context_data( &osmesa->mesa );
827 free( osmesa );
828 }
829 }
830
831
832 /**
833 * Bind an OSMesaContext to an image buffer. The image buffer is just a
834 * block of memory which the client provides. Its size must be at least
835 * as large as width*height*sizeof(type). Its address should be a multiple
836 * of 4 if using RGBA mode.
837 *
838 * Image data is stored in the order of glDrawPixels: row-major order
839 * with the lower-left image pixel stored in the first array position
840 * (ie. bottom-to-top).
841 *
842 * If the context's viewport hasn't been initialized yet, it will now be
843 * initialized to (0,0,width,height).
844 *
845 * Input: osmesa - the rendering context
846 * buffer - the image buffer memory
847 * type - data type for pixel components
848 * Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5
849 * are supported. But if Mesa's been compiled with CHAN_BITS==16
850 * then type may be GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE. And if
851 * Mesa's been build with CHAN_BITS==32 then type may be GL_FLOAT,
852 * GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE.
853 * width, height - size of image buffer in pixels, at least 1
854 * Return: GL_TRUE if success, GL_FALSE if error because of invalid osmesa,
855 * invalid buffer address, invalid type, width<1, height<1,
856 * width>internal limit or height>internal limit.
857 */
858 GLAPI GLboolean GLAPIENTRY
859 OSMesaMakeCurrent( OSMesaContext osmesa, void *buffer, GLenum type,
860 GLsizei width, GLsizei height )
861 {
862 if (!osmesa || !buffer ||
863 width < 1 || height < 1 ||
864 width > SWRAST_MAX_WIDTH || height > SWRAST_MAX_HEIGHT) {
865 return GL_FALSE;
866 }
867
868 if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5) {
869 return GL_FALSE;
870 }
871
872 #if 0
873 if (!(type == GL_UNSIGNED_BYTE ||
874 (type == GL_UNSIGNED_SHORT && CHAN_BITS >= 16) ||
875 (type == GL_FLOAT && CHAN_BITS == 32))) {
876 /* i.e. is sizeof(type) * 8 > CHAN_BITS? */
877 return GL_FALSE;
878 }
879 #endif
880
881 osmesa_update_state( &osmesa->mesa, 0 );
882
883 /* Call this periodically to detect when the user has begun using
884 * GL rendering from multiple threads.
885 */
886 _glapi_check_multithread();
887
888
889 /* Create a front/left color buffer which wraps the user-provided buffer.
890 * There is no back color buffer.
891 * If the user tries to use a 8, 16 or 32-bit/channel buffer that
892 * doesn't match what Mesa was compiled for (CHAN_BITS) the
893 * _mesa_add_renderbuffer() function will create a "wrapper" renderbuffer
894 * that converts rendering from CHAN_BITS to the user-requested channel
895 * size.
896 */
897 if (!osmesa->srb) {
898 osmesa->srb = new_osmesa_renderbuffer(&osmesa->mesa, osmesa->format, type);
899 _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT);
900 _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT,
901 &osmesa->srb->Base);
902 assert(osmesa->srb->Base.RefCount == 2);
903 }
904
905 osmesa->DataType = type;
906
907 /* Set renderbuffer fields. Set width/height = 0 to force
908 * osmesa_renderbuffer_storage() being called by _mesa_resize_framebuffer()
909 */
910 osmesa->srb->Buffer = buffer;
911 osmesa->srb->Base.Width = osmesa->srb->Base.Height = 0;
912
913 /* Set the framebuffer's size. This causes the
914 * osmesa_renderbuffer_storage() function to get called.
915 */
916 _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
917 osmesa->gl_buffer->Initialized = GL_TRUE; /* XXX TEMPORARY? */
918
919 _mesa_make_current( &osmesa->mesa, osmesa->gl_buffer, osmesa->gl_buffer );
920
921 /* Remove renderbuffer attachment, then re-add. This installs the
922 * renderbuffer adaptor/wrapper if needed (for bpp conversion).
923 */
924 _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT);
925 _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT,
926 &osmesa->srb->Base);
927
928
929 /* this updates the visual's red/green/blue/alphaBits fields */
930 _mesa_update_framebuffer_visual(&osmesa->mesa, osmesa->gl_buffer);
931
932 /* update the framebuffer size */
933 _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
934
935 return GL_TRUE;
936 }
937
938
939
940 GLAPI OSMesaContext GLAPIENTRY
941 OSMesaGetCurrentContext( void )
942 {
943 struct gl_context *ctx = _mesa_get_current_context();
944 if (ctx)
945 return (OSMesaContext) ctx;
946 else
947 return NULL;
948 }
949
950
951
952 GLAPI void GLAPIENTRY
953 OSMesaPixelStore( GLint pname, GLint value )
954 {
955 OSMesaContext osmesa = OSMesaGetCurrentContext();
956
957 switch (pname) {
958 case OSMESA_ROW_LENGTH:
959 if (value<0) {
960 _mesa_error( &osmesa->mesa, GL_INVALID_VALUE,
961 "OSMesaPixelStore(value)" );
962 return;
963 }
964 osmesa->userRowLength = value;
965 break;
966 case OSMESA_Y_UP:
967 osmesa->yup = value ? GL_TRUE : GL_FALSE;
968 break;
969 default:
970 _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
971 return;
972 }
973
974 compute_row_addresses( osmesa );
975 }
976
977
978 GLAPI void GLAPIENTRY
979 OSMesaGetIntegerv( GLint pname, GLint *value )
980 {
981 OSMesaContext osmesa = OSMesaGetCurrentContext();
982
983 switch (pname) {
984 case OSMESA_WIDTH:
985 if (osmesa->gl_buffer)
986 *value = osmesa->gl_buffer->Width;
987 else
988 *value = 0;
989 return;
990 case OSMESA_HEIGHT:
991 if (osmesa->gl_buffer)
992 *value = osmesa->gl_buffer->Height;
993 else
994 *value = 0;
995 return;
996 case OSMESA_FORMAT:
997 *value = osmesa->format;
998 return;
999 case OSMESA_TYPE:
1000 /* current color buffer's data type */
1001 *value = osmesa->DataType;
1002 return;
1003 case OSMESA_ROW_LENGTH:
1004 *value = osmesa->userRowLength;
1005 return;
1006 case OSMESA_Y_UP:
1007 *value = osmesa->yup;
1008 return;
1009 case OSMESA_MAX_WIDTH:
1010 *value = SWRAST_MAX_WIDTH;
1011 return;
1012 case OSMESA_MAX_HEIGHT:
1013 *value = SWRAST_MAX_HEIGHT;
1014 return;
1015 default:
1016 _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
1017 return;
1018 }
1019 }
1020
1021
1022 /**
1023 * Return the depth buffer associated with an OSMesa context.
1024 * Input: c - the OSMesa context
1025 * Output: width, height - size of buffer in pixels
1026 * bytesPerValue - bytes per depth value (2 or 4)
1027 * buffer - pointer to depth buffer values
1028 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
1029 */
1030 GLAPI GLboolean GLAPIENTRY
1031 OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
1032 GLint *bytesPerValue, void **buffer )
1033 {
1034 struct swrast_renderbuffer *srb = NULL;
1035
1036 if (c->gl_buffer)
1037 srb = swrast_renderbuffer(c->gl_buffer->
1038 Attachment[BUFFER_DEPTH].Renderbuffer);
1039
1040 if (!srb || !srb->Buffer) {
1041 *width = 0;
1042 *height = 0;
1043 *bytesPerValue = 0;
1044 *buffer = 0;
1045 return GL_FALSE;
1046 }
1047 else {
1048 *width = srb->Base.Width;
1049 *height = srb->Base.Height;
1050 if (c->gl_visual->depthBits <= 16)
1051 *bytesPerValue = sizeof(GLushort);
1052 else
1053 *bytesPerValue = sizeof(GLuint);
1054 *buffer = (void *) srb->Buffer;
1055 return GL_TRUE;
1056 }
1057 }
1058
1059
1060 /**
1061 * Return the color buffer associated with an OSMesa context.
1062 * Input: c - the OSMesa context
1063 * Output: width, height - size of buffer in pixels
1064 * format - the pixel format (OSMESA_FORMAT)
1065 * buffer - pointer to color buffer values
1066 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
1067 */
1068 GLAPI GLboolean GLAPIENTRY
1069 OSMesaGetColorBuffer( OSMesaContext osmesa, GLint *width,
1070 GLint *height, GLint *format, void **buffer )
1071 {
1072 if (osmesa->srb && osmesa->srb->Buffer) {
1073 *width = osmesa->srb->Base.Width;
1074 *height = osmesa->srb->Base.Height;
1075 *format = osmesa->format;
1076 *buffer = (void *) osmesa->srb->Buffer;
1077 return GL_TRUE;
1078 }
1079 else {
1080 *width = 0;
1081 *height = 0;
1082 *format = 0;
1083 *buffer = 0;
1084 return GL_FALSE;
1085 }
1086 }
1087
1088
1089 struct name_function
1090 {
1091 const char *Name;
1092 OSMESAproc Function;
1093 };
1094
1095 static struct name_function functions[] = {
1096 { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
1097 { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
1098 { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
1099 { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
1100 { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
1101 { "OSMesaPixelsStore", (OSMESAproc) OSMesaPixelStore },
1102 { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
1103 { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
1104 { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
1105 { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
1106 { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp },
1107 { NULL, NULL }
1108 };
1109
1110
1111 GLAPI OSMESAproc GLAPIENTRY
1112 OSMesaGetProcAddress( const char *funcName )
1113 {
1114 int i;
1115 for (i = 0; functions[i].Name; i++) {
1116 if (strcmp(functions[i].Name, funcName) == 0)
1117 return functions[i].Function;
1118 }
1119 return _glapi_get_proc_address(funcName);
1120 }
1121
1122
1123 GLAPI void GLAPIENTRY
1124 OSMesaColorClamp(GLboolean enable)
1125 {
1126 OSMesaContext osmesa = OSMesaGetCurrentContext();
1127
1128 if (enable == GL_TRUE) {
1129 osmesa->mesa.Color.ClampFragmentColor = GL_TRUE;
1130 }
1131 else {
1132 osmesa->mesa.Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
1133 }
1134 }
1135
1136
1137 /**
1138 * When GLX_INDIRECT_RENDERING is defined, some symbols are missing in
1139 * libglapi.a. We need to define them here.
1140 */
1141 #ifdef GLX_INDIRECT_RENDERING
1142
1143 #define GL_GLEXT_PROTOTYPES
1144 #include "GL/gl.h"
1145 #include "glapi/glapi.h"
1146 #include "glapi/glapitable.h"
1147
1148 #if defined(USE_MGL_NAMESPACE)
1149 #define NAME(func) mgl##func
1150 #else
1151 #define NAME(func) gl##func
1152 #endif
1153
1154 #define DISPATCH(FUNC, ARGS, MESSAGE) \
1155 GET_DISPATCH()->FUNC ARGS
1156
1157 #define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \
1158 return GET_DISPATCH()->FUNC ARGS
1159
1160 /* skip normal ones */
1161 #define _GLAPI_SKIP_NORMAL_ENTRY_POINTS
1162 #include "glapi/glapitemp.h"
1163
1164 #endif /* GLX_INDIRECT_RENDERING */