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