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