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