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