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