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