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