osmesa: Fix osmesa_context.DataType type.
[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[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.Delete = osmesa_delete_renderbuffer;
519 srb->Base.AllocStorage = osmesa_renderbuffer_storage;
520
521 srb->Base.InternalFormat = GL_RGBA;
522 srb->Base._BaseFormat = GL_RGBA;
523
524 return srb;
525 }
526 return NULL;
527 }
528
529
530
531 static void
532 osmesa_MapRenderbuffer(struct gl_context *ctx,
533 struct gl_renderbuffer *rb,
534 GLuint x, GLuint y, GLuint w, GLuint h,
535 GLbitfield mode,
536 GLubyte **mapOut, GLint *rowStrideOut)
537 {
538 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
539
540 if (rb->ClassID == OSMESA_RENDERBUFFER_CLASS) {
541 /* this is an OSMesa renderbuffer which wraps user memory */
542 struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
543 const GLuint bpp = _mesa_get_format_bytes(rb->Format);
544 GLint rowStride; /* in bytes */
545
546 if (osmesa->userRowLength)
547 rowStride = osmesa->userRowLength * bpp;
548 else
549 rowStride = rb->Width * bpp;
550
551 if (!osmesa->yup) {
552 /* Y=0 is top line of window */
553 y = rb->Height - y - 1;
554 *rowStrideOut = -rowStride;
555 }
556 else {
557 *rowStrideOut = rowStride;
558 }
559
560 *mapOut = (GLubyte *) srb->Buffer + y * rowStride + x * bpp;
561 }
562 else {
563 _swrast_map_soft_renderbuffer(ctx, rb, x, y, w, h, mode,
564 mapOut, rowStrideOut);
565 }
566 }
567
568
569 static void
570 osmesa_UnmapRenderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
571 {
572 if (rb->ClassID == OSMESA_RENDERBUFFER_CLASS) {
573 /* no-op */
574 }
575 else {
576 _swrast_unmap_soft_renderbuffer(ctx, rb);
577 }
578 }
579
580
581 /**********************************************************************/
582 /***** Public Functions *****/
583 /**********************************************************************/
584
585
586 /**
587 * Create an Off-Screen Mesa rendering context. The only attribute needed is
588 * an RGBA vs Color-Index mode flag.
589 *
590 * Input: format - Must be GL_RGBA
591 * sharelist - specifies another OSMesaContext with which to share
592 * display lists. NULL indicates no sharing.
593 * Return: an OSMesaContext or 0 if error
594 */
595 GLAPI OSMesaContext GLAPIENTRY
596 OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
597 {
598 return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS,
599 8, 0, sharelist);
600 }
601
602
603
604 /**
605 * New in Mesa 3.5
606 *
607 * Create context and specify size of ancillary buffers.
608 */
609 GLAPI OSMesaContext GLAPIENTRY
610 OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
611 GLint accumBits, OSMesaContext sharelist )
612 {
613 OSMesaContext osmesa;
614 struct dd_function_table functions;
615 GLint rind, gind, bind, aind;
616 GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
617
618 rind = gind = bind = aind = 0;
619 if (format==OSMESA_RGBA) {
620 redBits = CHAN_BITS;
621 greenBits = CHAN_BITS;
622 blueBits = CHAN_BITS;
623 alphaBits = CHAN_BITS;
624 rind = 0;
625 gind = 1;
626 bind = 2;
627 aind = 3;
628 }
629 else if (format==OSMESA_BGRA) {
630 redBits = CHAN_BITS;
631 greenBits = CHAN_BITS;
632 blueBits = CHAN_BITS;
633 alphaBits = CHAN_BITS;
634 bind = 0;
635 gind = 1;
636 rind = 2;
637 aind = 3;
638 }
639 else if (format==OSMESA_ARGB) {
640 redBits = CHAN_BITS;
641 greenBits = CHAN_BITS;
642 blueBits = CHAN_BITS;
643 alphaBits = CHAN_BITS;
644 aind = 0;
645 rind = 1;
646 gind = 2;
647 bind = 3;
648 }
649 else if (format==OSMESA_RGB) {
650 redBits = CHAN_BITS;
651 greenBits = CHAN_BITS;
652 blueBits = CHAN_BITS;
653 alphaBits = 0;
654 rind = 0;
655 gind = 1;
656 bind = 2;
657 }
658 else if (format==OSMESA_BGR) {
659 redBits = CHAN_BITS;
660 greenBits = CHAN_BITS;
661 blueBits = CHAN_BITS;
662 alphaBits = 0;
663 rind = 2;
664 gind = 1;
665 bind = 0;
666 }
667 #if CHAN_TYPE == GL_UNSIGNED_BYTE
668 else if (format==OSMESA_RGB_565) {
669 redBits = 5;
670 greenBits = 6;
671 blueBits = 5;
672 alphaBits = 0;
673 rind = 0; /* not used */
674 gind = 0;
675 bind = 0;
676 }
677 #endif
678 else {
679 return NULL;
680 }
681
682 osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
683 if (osmesa) {
684 osmesa->gl_visual = _mesa_create_visual( GL_FALSE, /* double buffer */
685 GL_FALSE, /* stereo */
686 redBits,
687 greenBits,
688 blueBits,
689 alphaBits,
690 depthBits,
691 stencilBits,
692 accumBits,
693 accumBits,
694 accumBits,
695 alphaBits ? accumBits : 0,
696 1 /* num samples */
697 );
698 if (!osmesa->gl_visual) {
699 free(osmesa);
700 return NULL;
701 }
702
703 /* Initialize device driver function table */
704 _mesa_init_driver_functions(&functions);
705 /* override with our functions */
706 functions.GetString = get_string;
707 functions.UpdateState = osmesa_update_state;
708 functions.GetBufferSize = NULL;
709
710 if (!_mesa_initialize_context(&osmesa->mesa,
711 API_OPENGL,
712 osmesa->gl_visual,
713 sharelist ? &sharelist->mesa
714 : (struct gl_context *) NULL,
715 &functions, (void *) osmesa)) {
716 _mesa_destroy_visual( osmesa->gl_visual );
717 free(osmesa);
718 return NULL;
719 }
720
721 _mesa_enable_sw_extensions(&(osmesa->mesa));
722 _mesa_enable_1_3_extensions(&(osmesa->mesa));
723 _mesa_enable_1_4_extensions(&(osmesa->mesa));
724 _mesa_enable_1_5_extensions(&(osmesa->mesa));
725 _mesa_enable_2_0_extensions(&(osmesa->mesa));
726 _mesa_enable_2_1_extensions(&(osmesa->mesa));
727
728 osmesa->gl_buffer = _mesa_create_framebuffer(osmesa->gl_visual);
729 if (!osmesa->gl_buffer) {
730 _mesa_destroy_visual( osmesa->gl_visual );
731 _mesa_free_context_data( &osmesa->mesa );
732 free(osmesa);
733 return NULL;
734 }
735
736 /* Create depth/stencil/accum buffers. We'll create the color
737 * buffer later in OSMesaMakeCurrent().
738 */
739 _swrast_add_soft_renderbuffers(osmesa->gl_buffer,
740 GL_FALSE, /* color */
741 osmesa->gl_visual->haveDepthBuffer,
742 osmesa->gl_visual->haveStencilBuffer,
743 osmesa->gl_visual->haveAccumBuffer,
744 GL_FALSE, /* alpha */
745 GL_FALSE /* aux */ );
746
747 osmesa->format = format;
748 osmesa->userRowLength = 0;
749 osmesa->yup = GL_TRUE;
750 osmesa->rInd = rind;
751 osmesa->gInd = gind;
752 osmesa->bInd = bind;
753 osmesa->aInd = aind;
754
755 _mesa_meta_init(&osmesa->mesa);
756
757 /* Initialize the software rasterizer and helper modules. */
758 {
759 struct gl_context *ctx = &osmesa->mesa;
760 SWcontext *swrast;
761 TNLcontext *tnl;
762
763 if (!_swrast_CreateContext( ctx ) ||
764 !_vbo_CreateContext( ctx ) ||
765 !_tnl_CreateContext( ctx ) ||
766 !_swsetup_CreateContext( ctx )) {
767 _mesa_destroy_visual(osmesa->gl_visual);
768 _mesa_free_context_data(ctx);
769 free(osmesa);
770 return NULL;
771 }
772
773 _swsetup_Wakeup( ctx );
774
775 /* use default TCL pipeline */
776 tnl = TNL_CONTEXT(ctx);
777 tnl->Driver.RunPipeline = _tnl_run_pipeline;
778
779 ctx->Driver.MapRenderbuffer = osmesa_MapRenderbuffer;
780 ctx->Driver.UnmapRenderbuffer = osmesa_UnmapRenderbuffer;
781
782 /* Extend the software rasterizer with our optimized line and triangle
783 * drawing functions.
784 */
785 swrast = SWRAST_CONTEXT( ctx );
786 swrast->choose_line = osmesa_choose_line;
787 swrast->choose_triangle = osmesa_choose_triangle;
788 }
789 }
790 return osmesa;
791 }
792
793
794 /**
795 * Destroy an Off-Screen Mesa rendering context.
796 *
797 * \param osmesa the context to destroy
798 */
799 GLAPI void GLAPIENTRY
800 OSMesaDestroyContext( OSMesaContext osmesa )
801 {
802 if (osmesa) {
803 if (osmesa->srb)
804 _mesa_reference_renderbuffer((struct gl_renderbuffer **) &osmesa->srb, NULL);
805
806 _mesa_meta_free( &osmesa->mesa );
807
808 _swsetup_DestroyContext( &osmesa->mesa );
809 _tnl_DestroyContext( &osmesa->mesa );
810 _vbo_DestroyContext( &osmesa->mesa );
811 _swrast_DestroyContext( &osmesa->mesa );
812
813 _mesa_destroy_visual( osmesa->gl_visual );
814 _mesa_reference_framebuffer( &osmesa->gl_buffer, NULL );
815
816 _mesa_free_context_data( &osmesa->mesa );
817 free( osmesa );
818 }
819 }
820
821
822 /**
823 * Bind an OSMesaContext to an image buffer. The image buffer is just a
824 * block of memory which the client provides. Its size must be at least
825 * as large as width*height*sizeof(type). Its address should be a multiple
826 * of 4 if using RGBA mode.
827 *
828 * Image data is stored in the order of glDrawPixels: row-major order
829 * with the lower-left image pixel stored in the first array position
830 * (ie. bottom-to-top).
831 *
832 * If the context's viewport hasn't been initialized yet, it will now be
833 * initialized to (0,0,width,height).
834 *
835 * Input: osmesa - the rendering context
836 * buffer - the image buffer memory
837 * type - data type for pixel components
838 * Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5
839 * are supported. But if Mesa's been compiled with CHAN_BITS==16
840 * then type may be GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE. And if
841 * Mesa's been build with CHAN_BITS==32 then type may be GL_FLOAT,
842 * GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE.
843 * width, height - size of image buffer in pixels, at least 1
844 * Return: GL_TRUE if success, GL_FALSE if error because of invalid osmesa,
845 * invalid buffer address, invalid type, width<1, height<1,
846 * width>internal limit or height>internal limit.
847 */
848 GLAPI GLboolean GLAPIENTRY
849 OSMesaMakeCurrent( OSMesaContext osmesa, void *buffer, GLenum type,
850 GLsizei width, GLsizei height )
851 {
852 if (!osmesa || !buffer ||
853 width < 1 || height < 1 ||
854 width > MAX_WIDTH || height > MAX_HEIGHT) {
855 return GL_FALSE;
856 }
857
858 if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5) {
859 return GL_FALSE;
860 }
861
862 #if 0
863 if (!(type == GL_UNSIGNED_BYTE ||
864 (type == GL_UNSIGNED_SHORT && CHAN_BITS >= 16) ||
865 (type == GL_FLOAT && CHAN_BITS == 32))) {
866 /* i.e. is sizeof(type) * 8 > CHAN_BITS? */
867 return GL_FALSE;
868 }
869 #endif
870
871 osmesa_update_state( &osmesa->mesa, 0 );
872
873 /* Call this periodically to detect when the user has begun using
874 * GL rendering from multiple threads.
875 */
876 _glapi_check_multithread();
877
878
879 /* Create a front/left color buffer which wraps the user-provided buffer.
880 * There is no back color buffer.
881 * If the user tries to use a 8, 16 or 32-bit/channel buffer that
882 * doesn't match what Mesa was compiled for (CHAN_BITS) the
883 * _mesa_add_renderbuffer() function will create a "wrapper" renderbuffer
884 * that converts rendering from CHAN_BITS to the user-requested channel
885 * size.
886 */
887 if (!osmesa->srb) {
888 osmesa->srb = new_osmesa_renderbuffer(&osmesa->mesa, osmesa->format, type);
889 _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT);
890 _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT,
891 &osmesa->srb->Base);
892 assert(osmesa->srb->Base.RefCount == 2);
893 }
894
895 osmesa->DataType = type;
896
897 /* Set renderbuffer fields. Set width/height = 0 to force
898 * osmesa_renderbuffer_storage() being called by _mesa_resize_framebuffer()
899 */
900 osmesa->srb->Buffer = buffer;
901 osmesa->srb->Base.Width = osmesa->srb->Base.Height = 0;
902
903 /* Set the framebuffer's size. This causes the
904 * osmesa_renderbuffer_storage() function to get called.
905 */
906 _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
907 osmesa->gl_buffer->Initialized = GL_TRUE; /* XXX TEMPORARY? */
908
909 _mesa_make_current( &osmesa->mesa, osmesa->gl_buffer, osmesa->gl_buffer );
910
911 /* Remove renderbuffer attachment, then re-add. This installs the
912 * renderbuffer adaptor/wrapper if needed (for bpp conversion).
913 */
914 _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT);
915 _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT,
916 &osmesa->srb->Base);
917
918
919 /* this updates the visual's red/green/blue/alphaBits fields */
920 _mesa_update_framebuffer_visual(&osmesa->mesa, osmesa->gl_buffer);
921
922 /* update the framebuffer size */
923 _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
924
925 return GL_TRUE;
926 }
927
928
929
930 GLAPI OSMesaContext GLAPIENTRY
931 OSMesaGetCurrentContext( void )
932 {
933 struct gl_context *ctx = _mesa_get_current_context();
934 if (ctx)
935 return (OSMesaContext) ctx;
936 else
937 return NULL;
938 }
939
940
941
942 GLAPI void GLAPIENTRY
943 OSMesaPixelStore( GLint pname, GLint value )
944 {
945 OSMesaContext osmesa = OSMesaGetCurrentContext();
946
947 switch (pname) {
948 case OSMESA_ROW_LENGTH:
949 if (value<0) {
950 _mesa_error( &osmesa->mesa, GL_INVALID_VALUE,
951 "OSMesaPixelStore(value)" );
952 return;
953 }
954 osmesa->userRowLength = value;
955 break;
956 case OSMESA_Y_UP:
957 osmesa->yup = value ? GL_TRUE : GL_FALSE;
958 break;
959 default:
960 _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
961 return;
962 }
963
964 compute_row_addresses( osmesa );
965 }
966
967
968 GLAPI void GLAPIENTRY
969 OSMesaGetIntegerv( GLint pname, GLint *value )
970 {
971 OSMesaContext osmesa = OSMesaGetCurrentContext();
972
973 switch (pname) {
974 case OSMESA_WIDTH:
975 if (osmesa->gl_buffer)
976 *value = osmesa->gl_buffer->Width;
977 else
978 *value = 0;
979 return;
980 case OSMESA_HEIGHT:
981 if (osmesa->gl_buffer)
982 *value = osmesa->gl_buffer->Height;
983 else
984 *value = 0;
985 return;
986 case OSMESA_FORMAT:
987 *value = osmesa->format;
988 return;
989 case OSMESA_TYPE:
990 /* current color buffer's data type */
991 *value = osmesa->DataType;
992 return;
993 case OSMESA_ROW_LENGTH:
994 *value = osmesa->userRowLength;
995 return;
996 case OSMESA_Y_UP:
997 *value = osmesa->yup;
998 return;
999 case OSMESA_MAX_WIDTH:
1000 *value = MAX_WIDTH;
1001 return;
1002 case OSMESA_MAX_HEIGHT:
1003 *value = MAX_HEIGHT;
1004 return;
1005 default:
1006 _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
1007 return;
1008 }
1009 }
1010
1011
1012 /**
1013 * Return the depth buffer associated with an OSMesa context.
1014 * Input: c - the OSMesa context
1015 * Output: width, height - size of buffer in pixels
1016 * bytesPerValue - bytes per depth value (2 or 4)
1017 * buffer - pointer to depth buffer values
1018 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
1019 */
1020 GLAPI GLboolean GLAPIENTRY
1021 OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
1022 GLint *bytesPerValue, void **buffer )
1023 {
1024 struct swrast_renderbuffer *srb = NULL;
1025
1026 if (c->gl_buffer)
1027 srb = swrast_renderbuffer(c->gl_buffer->
1028 Attachment[BUFFER_DEPTH].Renderbuffer);
1029
1030 if (!srb || !srb->Buffer) {
1031 *width = 0;
1032 *height = 0;
1033 *bytesPerValue = 0;
1034 *buffer = 0;
1035 return GL_FALSE;
1036 }
1037 else {
1038 *width = srb->Base.Width;
1039 *height = srb->Base.Height;
1040 if (c->gl_visual->depthBits <= 16)
1041 *bytesPerValue = sizeof(GLushort);
1042 else
1043 *bytesPerValue = sizeof(GLuint);
1044 *buffer = (void *) srb->Buffer;
1045 return GL_TRUE;
1046 }
1047 }
1048
1049
1050 /**
1051 * Return the color buffer associated with an OSMesa context.
1052 * Input: c - the OSMesa context
1053 * Output: width, height - size of buffer in pixels
1054 * format - the pixel format (OSMESA_FORMAT)
1055 * buffer - pointer to color buffer values
1056 * Return: GL_TRUE or GL_FALSE to indicate success or failure.
1057 */
1058 GLAPI GLboolean GLAPIENTRY
1059 OSMesaGetColorBuffer( OSMesaContext osmesa, GLint *width,
1060 GLint *height, GLint *format, void **buffer )
1061 {
1062 if (osmesa->srb && osmesa->srb->Buffer) {
1063 *width = osmesa->srb->Base.Width;
1064 *height = osmesa->srb->Base.Height;
1065 *format = osmesa->format;
1066 *buffer = (void *) osmesa->srb->Buffer;
1067 return GL_TRUE;
1068 }
1069 else {
1070 *width = 0;
1071 *height = 0;
1072 *format = 0;
1073 *buffer = 0;
1074 return GL_FALSE;
1075 }
1076 }
1077
1078
1079 struct name_function
1080 {
1081 const char *Name;
1082 OSMESAproc Function;
1083 };
1084
1085 static struct name_function functions[] = {
1086 { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
1087 { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
1088 { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
1089 { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
1090 { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
1091 { "OSMesaPixelsStore", (OSMESAproc) OSMesaPixelStore },
1092 { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
1093 { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
1094 { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
1095 { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
1096 { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp },
1097 { NULL, NULL }
1098 };
1099
1100
1101 GLAPI OSMESAproc GLAPIENTRY
1102 OSMesaGetProcAddress( const char *funcName )
1103 {
1104 int i;
1105 for (i = 0; functions[i].Name; i++) {
1106 if (strcmp(functions[i].Name, funcName) == 0)
1107 return functions[i].Function;
1108 }
1109 return _glapi_get_proc_address(funcName);
1110 }
1111
1112
1113 GLAPI void GLAPIENTRY
1114 OSMesaColorClamp(GLboolean enable)
1115 {
1116 OSMesaContext osmesa = OSMesaGetCurrentContext();
1117
1118 if (enable == GL_TRUE) {
1119 osmesa->mesa.Color.ClampFragmentColor = GL_TRUE;
1120 }
1121 else {
1122 osmesa->mesa.Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
1123 }
1124 }
1125
1126
1127 /**
1128 * When GLX_INDIRECT_RENDERING is defined, some symbols are missing in
1129 * libglapi.a. We need to define them here.
1130 */
1131 #ifdef GLX_INDIRECT_RENDERING
1132
1133 #define GL_GLEXT_PROTOTYPES
1134 #include "GL/gl.h"
1135 #include "glapi/glapi.h"
1136 #include "glapi/glapitable.h"
1137
1138 #if defined(USE_MGL_NAMESPACE)
1139 #define NAME(func) mgl##func
1140 #else
1141 #define NAME(func) gl##func
1142 #endif
1143
1144 #define DISPATCH(FUNC, ARGS, MESSAGE) \
1145 GET_DISPATCH()->FUNC ARGS
1146
1147 #define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) \
1148 return GET_DISPATCH()->FUNC ARGS
1149
1150 /* skip normal ones */
1151 #define _GLAPI_SKIP_NORMAL_ENTRY_POINTS
1152 #include "glapi/glapitemp.h"
1153
1154 #endif /* GLX_INDIRECT_RENDERING */