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