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 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 * 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 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 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 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 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 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 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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