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