osmesa.c revision 9499e017b7e05411a32b3e4fa94885eaec0d7277
1/* $Id: osmesa.c,v 1.24 2000/10/30 16:32:43 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 3.3 6 * 7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 27 28/* 29 * Off-Screen Mesa rendering / Rendering into client memory space 30 * 31 * Note on thread safety: this driver is thread safe. All 32 * functions are reentrant. The notion of current context is 33 * managed by the core _mesa_make_current() and _mesa_get_current_context() 34 * functions. Those functions are thread-safe. 35 */ 36 37 38#ifdef PC_HEADER 39#include "all.h" 40#else 41#include "glheader.h" 42#include "GL/osmesa.h" 43#include "context.h" 44#include "depth.h" 45#include "macros.h" 46#include "mem.h" 47#include "matrix.h" 48#include "types.h" 49#include "vb.h" 50#include "extensions.h" 51#endif 52 53 54/* 55 * This is the OS/Mesa context struct. 56 * Notice how it includes a GLcontext. By doing this we're mimicking 57 * C++ inheritance/derivation. 58 * Later, we can cast a GLcontext pointer into an OSMesaContext pointer 59 * or vice versa. 60 */ 61struct osmesa_context { 62 GLcontext gl_ctx; /* The core GL/Mesa context */ 63 GLvisual *gl_visual; /* Describes the buffers */ 64 GLframebuffer *gl_buffer; /* Depth, stencil, accum, etc buffers */ 65 GLenum format; /* either GL_RGBA or GL_COLOR_INDEX */ 66 void *buffer; /* the image buffer */ 67 GLint width, height; /* size of image buffer */ 68 GLuint pixel; /* current color index or RGBA pixel value */ 69 GLuint clearpixel; /* pixel for clearing the color buffer */ 70 GLint rowlength; /* number of pixels per row */ 71 GLint userRowLength; /* user-specified number of pixels per row */ 72 GLint rshift, gshift; /* bit shifts for RGBA formats */ 73 GLint bshift, ashift; 74 GLint rind, gind, bind; /* index offsets for RGBA formats */ 75 void *rowaddr[MAX_HEIGHT]; /* address of first pixel in each image row */ 76 GLboolean yup; /* TRUE -> Y increases upward */ 77 /* FALSE -> Y increases downward */ 78}; 79 80 81 82/* A forward declaration: */ 83static void osmesa_update_state( GLcontext *ctx ); 84 85 86 87/**********************************************************************/ 88/***** Public Functions *****/ 89/**********************************************************************/ 90 91 92/* 93 * Create an Off-Screen Mesa rendering context. The only attribute needed is 94 * an RGBA vs Color-Index mode flag. 95 * 96 * Input: format - either GL_RGBA or GL_COLOR_INDEX 97 * sharelist - specifies another OSMesaContext with which to share 98 * display lists. NULL indicates no sharing. 99 * Return: an OSMesaContext or 0 if error 100 */ 101OSMesaContext GLAPIENTRY 102OSMesaCreateContext( GLenum format, OSMesaContext sharelist ) 103{ 104 return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS, 105 8, 16, sharelist); 106} 107 108 109 110/* 111 * New in Mesa 3.5 112 * 113 * Create context and specify size of ancillary buffers. 114 */ 115OSMesaContext GLAPIENTRY 116OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, 117 GLint accumBits, OSMesaContext sharelist ) 118{ 119 OSMesaContext osmesa; 120 GLint rshift, gshift, bshift, ashift; 121 GLint rind, gind, bind; 122 GLint indexBits, redBits, greenBits, blueBits, alphaBits; 123 GLboolean rgbmode; 124 GLboolean swalpha; 125 GLuint i4 = 1; 126 GLubyte *i1 = (GLubyte *) &i4; 127 GLint little_endian = *i1; 128 129 swalpha = GL_FALSE; 130 rind = gind = bind = 0; 131 if (format==OSMESA_COLOR_INDEX) { 132 indexBits = 8; 133 rshift = gshift = bshift = ashift = 0; 134 rgbmode = GL_FALSE; 135 } 136 else if (format==OSMESA_RGBA) { 137 indexBits = 0; 138 redBits = 8; 139 greenBits = 8; 140 blueBits = 8; 141 alphaBits = 8; 142 if (little_endian) { 143 rshift = 0; 144 gshift = 8; 145 bshift = 16; 146 ashift = 24; 147 } 148 else { 149 rshift = 24; 150 gshift = 16; 151 bshift = 8; 152 ashift = 0; 153 } 154 rgbmode = GL_TRUE; 155 } 156 else if (format==OSMESA_BGRA) { 157 indexBits = 0; 158 redBits = 8; 159 greenBits = 8; 160 blueBits = 8; 161 alphaBits = 8; 162 if (little_endian) { 163 ashift = 0; 164 rshift = 8; 165 gshift = 16; 166 bshift = 24; 167 } 168 else { 169 bshift = 24; 170 gshift = 16; 171 rshift = 8; 172 ashift = 0; 173 } 174 rgbmode = GL_TRUE; 175 } 176 else if (format==OSMESA_ARGB) { 177 indexBits = 0; 178 redBits = 8; 179 greenBits = 8; 180 blueBits = 8; 181 alphaBits = 8; 182 if (little_endian) { 183 bshift = 0; 184 gshift = 8; 185 rshift = 16; 186 ashift = 24; 187 } 188 else { 189 ashift = 24; 190 rshift = 16; 191 gshift = 8; 192 bshift = 0; 193 } 194 rgbmode = GL_TRUE; 195 } 196 else if (format==OSMESA_RGB) { 197 indexBits = 0; 198 redBits = 8; 199 greenBits = 8; 200 blueBits = 8; 201 alphaBits = 0; 202 bshift = 0; 203 gshift = 8; 204 rshift = 16; 205 ashift = 24; 206 bind = 2; 207 gind = 1; 208 rind = 0; 209 rgbmode = GL_TRUE; 210 swalpha = GL_TRUE; 211 } 212 else if (format==OSMESA_BGR) { 213 indexBits = 0; 214 redBits = 8; 215 greenBits = 8; 216 blueBits = 8; 217 alphaBits = 0; 218 bshift = 0; 219 gshift = 8; 220 rshift = 16; 221 ashift = 24; 222 bind = 0; 223 gind = 1; 224 rind = 2; 225 rgbmode = GL_TRUE; 226 swalpha = GL_TRUE; 227 } 228 else { 229 return NULL; 230 } 231 232 233 osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context); 234 if (osmesa) { 235 osmesa->gl_visual = _mesa_create_visual( rgbmode, 236 GL_FALSE, /* double buffer */ 237 GL_FALSE, /* stereo */ 238 redBits, 239 greenBits, 240 blueBits, 241 alphaBits, 242 indexBits, 243 depthBits, 244 stencilBits, 245 accumBits, 246 accumBits, 247 accumBits, 248 alphaBits ? accumBits : 0, 249 1 /* num samples */ 250 ); 251 if (!osmesa->gl_visual) { 252 FREE(osmesa); 253 return NULL; 254 } 255 256 if (!_mesa_initialize_context(&osmesa->gl_ctx, 257 osmesa->gl_visual, 258 sharelist ? &sharelist->gl_ctx 259 : (GLcontext *) NULL, 260 (void *) osmesa, GL_TRUE )) { 261 _mesa_destroy_visual( osmesa->gl_visual ); 262 FREE(osmesa); 263 return NULL; 264 } 265 gl_extensions_enable(&(osmesa->gl_ctx),"GL_HP_occlusion_test"); 266 gl_extensions_enable(&(osmesa->gl_ctx), "GL_ARB_texture_cube_map"); 267 gl_extensions_enable(&(osmesa->gl_ctx), "GL_EXT_texture_env_combine"); 268 269 osmesa->gl_buffer = _mesa_create_framebuffer( osmesa->gl_visual, 270 osmesa->gl_visual->DepthBits > 0, 271 osmesa->gl_visual->StencilBits > 0, 272 osmesa->gl_visual->AccumRedBits > 0, 273 osmesa->gl_visual->AlphaBits > 0 ); 274 275 if (!osmesa->gl_buffer) { 276 _mesa_destroy_visual( osmesa->gl_visual ); 277 _mesa_free_context_data( &osmesa->gl_ctx ); 278 FREE(osmesa); 279 return NULL; 280 } 281 osmesa->format = format; 282 osmesa->buffer = NULL; 283 osmesa->width = 0; 284 osmesa->height = 0; 285 osmesa->pixel = 0; 286 osmesa->clearpixel = 0; 287 osmesa->userRowLength = 0; 288 osmesa->rowlength = 0; 289 osmesa->yup = GL_TRUE; 290 osmesa->rshift = rshift; 291 osmesa->gshift = gshift; 292 osmesa->bshift = bshift; 293 osmesa->ashift = ashift; 294 osmesa->rind = rind; 295 osmesa->gind = gind; 296 osmesa->bind = bind; 297 } 298 return osmesa; 299} 300 301 302 303 304/* 305 * Destroy an Off-Screen Mesa rendering context. 306 * 307 * Input: ctx - the context to destroy 308 */ 309void GLAPIENTRY OSMesaDestroyContext( OSMesaContext ctx ) 310{ 311 if (ctx) { 312 _mesa_destroy_visual( ctx->gl_visual ); 313 _mesa_destroy_framebuffer( ctx->gl_buffer ); 314 _mesa_free_context_data( &ctx->gl_ctx ); 315 FREE( ctx ); 316 } 317} 318 319 320 321/* 322 * Recompute the values of the context's rowaddr array. 323 */ 324static void compute_row_addresses( OSMesaContext ctx ) 325{ 326 GLint i; 327 328 if (ctx->yup) { 329 /* Y=0 is bottom line of window */ 330 if (ctx->format==OSMESA_COLOR_INDEX) { 331 /* 1-byte CI mode */ 332 GLubyte *origin = (GLubyte *) ctx->buffer; 333 for (i=0;i<MAX_HEIGHT;i++) { 334 ctx->rowaddr[i] = origin + i * ctx->rowlength; 335 } 336 } 337 else { 338 if ((ctx->format==OSMESA_RGB) || (ctx->format==OSMESA_BGR)) { 339 /* 3-byte RGB mode */ 340 GLubyte *origin = (GLubyte *) ctx->buffer; 341 for (i=0;i<MAX_HEIGHT;i++) { 342 ctx->rowaddr[i] = origin + (i * (ctx->rowlength*3)); 343 } 344 } else { 345 /* 4-byte RGBA mode */ 346 GLuint *origin = (GLuint *) ctx->buffer; 347 for (i=0;i<MAX_HEIGHT;i++) { 348 ctx->rowaddr[i] = origin + i * ctx->rowlength; 349 } 350 } 351 } 352 } 353 else { 354 /* Y=0 is top line of window */ 355 if (ctx->format==OSMESA_COLOR_INDEX) { 356 /* 1-byte CI mode */ 357 GLubyte *origin = (GLubyte *) ctx->buffer; 358 for (i=0;i<MAX_HEIGHT;i++) { 359 ctx->rowaddr[i] = origin + (ctx->height-i-1) * ctx->rowlength; 360 } 361 } 362 else { 363 if ((ctx->format==OSMESA_RGB) || (ctx->format==OSMESA_BGR)) { 364 /* 3-byte RGB mode */ 365 GLubyte *origin = (GLubyte *) ctx->buffer; 366 for (i=0;i<MAX_HEIGHT;i++) { 367 ctx->rowaddr[i] = origin + ((ctx->height-i-1) * (ctx->rowlength*3)); 368 } 369 } else { 370 /* 4-byte RGBA mode */ 371 GLuint *origin = (GLuint *) ctx->buffer; 372 for (i=0;i<MAX_HEIGHT;i++) { 373 ctx->rowaddr[i] = origin + (ctx->height-i-1) * ctx->rowlength; 374 } 375 } 376 } 377 } 378} 379 380 381/* 382 * Bind an OSMesaContext to an image buffer. The image buffer is just a 383 * block of memory which the client provides. Its size must be at least 384 * as large as width*height*sizeof(type). Its address should be a multiple 385 * of 4 if using RGBA mode. 386 * 387 * Image data is stored in the order of glDrawPixels: row-major order 388 * with the lower-left image pixel stored in the first array position 389 * (ie. bottom-to-top). 390 * 391 * Since the only type initially supported is GL_UNSIGNED_BYTE, if the 392 * context is in RGBA mode, each pixel will be stored as a 4-byte RGBA 393 * value. If the context is in color indexed mode, each pixel will be 394 * stored as a 1-byte value. 395 * 396 * If the context's viewport hasn't been initialized yet, it will now be 397 * initialized to (0,0,width,height). 398 * 399 * Input: ctx - the rendering context 400 * buffer - the image buffer memory 401 * type - data type for pixel components, only GL_UNSIGNED_BYTE 402 * supported now 403 * width, height - size of image buffer in pixels, at least 1 404 * Return: GL_TRUE if success, GL_FALSE if error because of invalid ctx, 405 * invalid buffer address, type!=GL_UNSIGNED_BYTE, width<1, height<1, 406 * width>internal limit or height>internal limit. 407 */ 408GLboolean GLAPIENTRY 409OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type, 410 GLsizei width, GLsizei height ) 411{ 412 if (!ctx || !buffer || type!=GL_UNSIGNED_BYTE 413 || width<1 || height<1 || width>MAX_WIDTH || height>MAX_HEIGHT) { 414 return GL_FALSE; 415 } 416 417 osmesa_update_state( &ctx->gl_ctx ); 418 _mesa_make_current( &ctx->gl_ctx, ctx->gl_buffer ); 419 420 ctx->buffer = buffer; 421 ctx->width = width; 422 ctx->height = height; 423 if (ctx->userRowLength) 424 ctx->rowlength = ctx->userRowLength; 425 else 426 ctx->rowlength = width; 427 428 compute_row_addresses( ctx ); 429 430 /* init viewport */ 431 if (ctx->gl_ctx.Viewport.Width==0) { 432 /* initialize viewport and scissor box to buffer size */ 433 _mesa_Viewport( 0, 0, width, height ); 434 ctx->gl_ctx.Scissor.Width = width; 435 ctx->gl_ctx.Scissor.Height = height; 436 } 437 438 return GL_TRUE; 439} 440 441 442 443OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void ) 444{ 445 GLcontext *ctx = _mesa_get_current_context(); 446 if (ctx) 447 return (OSMesaContext) ctx; 448 else 449 return NULL; 450} 451 452 453 454void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value ) 455{ 456 OSMesaContext ctx = OSMesaGetCurrentContext(); 457 458 switch (pname) { 459 case OSMESA_ROW_LENGTH: 460 if (value<0) { 461 gl_error( &ctx->gl_ctx, GL_INVALID_VALUE, 462 "OSMesaPixelStore(value)" ); 463 return; 464 } 465 ctx->userRowLength = value; 466 ctx->rowlength = value; 467 break; 468 case OSMESA_Y_UP: 469 ctx->yup = value ? GL_TRUE : GL_FALSE; 470 break; 471 default: 472 gl_error( &ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" ); 473 return; 474 } 475 476 compute_row_addresses( ctx ); 477} 478 479 480void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value ) 481{ 482 OSMesaContext ctx = OSMesaGetCurrentContext(); 483 484 switch (pname) { 485 case OSMESA_WIDTH: 486 *value = ctx->width; 487 return; 488 case OSMESA_HEIGHT: 489 *value = ctx->height; 490 return; 491 case OSMESA_FORMAT: 492 *value = ctx->format; 493 return; 494 case OSMESA_TYPE: 495 *value = GL_UNSIGNED_BYTE; 496 return; 497 case OSMESA_ROW_LENGTH: 498 *value = ctx->rowlength; 499 return; 500 case OSMESA_Y_UP: 501 *value = ctx->yup; 502 return; 503 default: 504 gl_error(&ctx->gl_ctx, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)"); 505 return; 506 } 507} 508 509/* 510 * Return the depth buffer associated with an OSMesa context. 511 * Input: c - the OSMesa context 512 * Output: width, height - size of buffer in pixels 513 * bytesPerValue - bytes per depth value (2 or 4) 514 * buffer - pointer to depth buffer values 515 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 516 */ 517GLboolean GLAPIENTRY 518OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height, 519 GLint *bytesPerValue, void **buffer ) 520{ 521 if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) { 522 *width = 0; 523 *height = 0; 524 *bytesPerValue = 0; 525 *buffer = 0; 526 return GL_FALSE; 527 } 528 else { 529 *width = c->gl_buffer->Width; 530 *height = c->gl_buffer->Height; 531 *bytesPerValue = sizeof(GLdepth); 532 *buffer = c->gl_buffer->DepthBuffer; 533 return GL_TRUE; 534 } 535} 536 537/* 538 * Return the color buffer associated with an OSMesa context. 539 * Input: c - the OSMesa context 540 * Output: width, height - size of buffer in pixels 541 * format - the pixel format (OSMESA_FORMAT) 542 * buffer - pointer to color buffer values 543 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 544 */ 545GLboolean GLAPIENTRY 546OSMesaGetColorBuffer( OSMesaContext c, GLint *width, 547 GLint *height, GLint *format, void **buffer ) 548{ 549 if (!c->buffer) { 550 *width = 0; 551 *height = 0; 552 *format = 0; 553 *buffer = 0; 554 return GL_FALSE; 555 } 556 else { 557 *width = c->width; 558 *height = c->height; 559 *format = c->format; 560 *buffer = c->buffer; 561 return GL_TRUE; 562 } 563} 564 565/**********************************************************************/ 566/*** Device Driver Functions ***/ 567/**********************************************************************/ 568 569 570/* 571 * Useful macros: 572 */ 573#define PACK_RGBA(R,G,B,A) ( ((R) << osmesa->rshift) \ 574 | ((G) << osmesa->gshift) \ 575 | ((B) << osmesa->bshift) \ 576 | ((A) << osmesa->ashift) ) 577 578#define PACK_RGBA2(R,G,B,A) ( ((R) << rshift) \ 579 | ((G) << gshift) \ 580 | ((B) << bshift) \ 581 | ((A) << ashift) ) 582 583#define UNPACK_RED(P) (((P) >> osmesa->rshift) & 0xff) 584#define UNPACK_GREEN(P) (((P) >> osmesa->gshift) & 0xff) 585#define UNPACK_BLUE(P) (((P) >> osmesa->bshift) & 0xff) 586#define UNPACK_ALPHA(P) (((P) >> osmesa->ashift) & 0xff) 587 588#define PIXELADDR1(X,Y) ((GLubyte *) osmesa->rowaddr[Y] + (X)) 589#define PIXELADDR3(X,Y) ((GLubyte *) osmesa->rowaddr[Y] + ((X)*3)) 590#define PIXELADDR4(X,Y) ((GLuint *) osmesa->rowaddr[Y] + (X)) 591 592 593 594 595static GLboolean set_draw_buffer( GLcontext *ctx, GLenum mode ) 596{ 597 (void) ctx; 598 if (mode==GL_FRONT_LEFT) { 599 return GL_TRUE; 600 } 601 else { 602 return GL_FALSE; 603 } 604} 605 606 607static void set_read_buffer( GLcontext *ctx, GLframebuffer *buffer, GLenum mode ) 608{ 609 /* separate read buffer not supported */ 610 ASSERT(buffer == ctx->DrawBuffer); 611 ASSERT(mode == GL_FRONT_LEFT); 612} 613 614 615static void clear_index( GLcontext *ctx, GLuint index ) 616{ 617 OSMesaContext osmesa = (OSMesaContext) ctx; 618 osmesa->clearpixel = index; 619} 620 621 622 623static void clear_color( GLcontext *ctx, 624 GLchan r, GLchan g, GLchan b, GLchan a ) 625{ 626 OSMesaContext osmesa = (OSMesaContext) ctx; 627 osmesa->clearpixel = PACK_RGBA( r, g, b, a ); 628} 629 630 631 632static GLbitfield clear( GLcontext *ctx, GLbitfield mask, GLboolean all, 633 GLint x, GLint y, GLint width, GLint height ) 634{ 635 OSMesaContext osmesa = (OSMesaContext) ctx; 636 const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask; 637 638 /* we can't handle color or index masking */ 639 if (*colorMask != 0xffffffff || ctx->Color.IndexMask != 0xffffffff) 640 return mask; 641 642 /* sanity check - we only have a front-left buffer */ 643 ASSERT((mask & (DD_FRONT_RIGHT_BIT | DD_BACK_LEFT_BIT | DD_BACK_RIGHT_BIT)) == 0); 644 645 if (mask & DD_FRONT_LEFT_BIT) { 646 if (osmesa->format==OSMESA_COLOR_INDEX) { 647 if (all) { 648 /* Clear whole CI buffer */ 649 MEMSET(osmesa->buffer, osmesa->clearpixel, 650 osmesa->rowlength * osmesa->height); 651 } 652 else { 653 /* Clear part of CI buffer */ 654 GLint i, j; 655 for (i=0;i<height;i++) { 656 GLubyte *ptr1 = PIXELADDR1( x, (y+i) ); 657 for (j=0;j<width;j++) { 658 *ptr1++ = osmesa->clearpixel; 659 } 660 } 661 } 662 } 663 else if ((osmesa->format==OSMESA_RGB)||(osmesa->format==OSMESA_BGR)) { 664 GLubyte rval = UNPACK_RED(osmesa->clearpixel); 665 GLubyte gval = UNPACK_GREEN(osmesa->clearpixel); 666 GLubyte bval = UNPACK_BLUE(osmesa->clearpixel); 667 GLint rind = osmesa->rind; 668 GLint gind = osmesa->gind; 669 GLint bind = osmesa->bind; 670 if (all) { 671 GLuint i, n; 672 GLubyte *ptr3 = (GLubyte *) osmesa->buffer; 673 /* Clear whole RGB buffer */ 674 n = osmesa->rowlength * osmesa->height; 675 for (i=0;i<n;i++) { 676 ptr3[rind] = rval; 677 ptr3[gind] = gval; 678 ptr3[bind] = bval; 679 ptr3 += 3; 680 } 681 } 682 else { 683 /* Clear part of RGB buffer */ 684 GLint i, j; 685 for (i=0;i<height;i++) { 686 GLubyte *ptr3 = PIXELADDR3( x, (y+i) ); 687 for (j=0;j<width;j++) { 688 ptr3[rind] = rval; 689 ptr3[gind] = gval; 690 ptr3[bind] = bval; 691 ptr3 += 3; 692 } 693 } 694 } 695 } 696 else { 697 if (all) { 698 /* Clear whole RGBA buffer */ 699 GLuint i, n, *ptr4; 700 n = osmesa->rowlength * osmesa->height; 701 ptr4 = (GLuint *) osmesa->buffer; 702 if (osmesa->clearpixel) { 703 for (i=0;i<n;i++) { 704 *ptr4++ = osmesa->clearpixel; 705 } 706 } 707 else { 708 BZERO(ptr4, n * sizeof(GLuint)); 709 } 710 } 711 else { 712 /* Clear part of RGBA buffer */ 713 GLint i, j; 714 for (i=0;i<height;i++) { 715 GLuint *ptr4 = PIXELADDR4( x, (y+i) ); 716 for (j=0;j<width;j++) { 717 *ptr4++ = osmesa->clearpixel; 718 } 719 } 720 } 721 } 722 } 723 /* have Mesa clear all other buffers */ 724 return mask & (~DD_FRONT_LEFT_BIT); 725} 726 727 728 729static void set_index( GLcontext *ctx, GLuint index ) 730{ 731 OSMesaContext osmesa = (OSMesaContext) ctx; 732 osmesa->pixel = index; 733} 734 735 736 737static void set_color( GLcontext *ctx, 738 GLchan r, GLchan g, GLchan b, GLchan a ) 739{ 740 OSMesaContext osmesa = (OSMesaContext) ctx; 741 osmesa->pixel = PACK_RGBA( r, g, b, a ); 742} 743 744 745 746static void buffer_size( GLcontext *ctx, GLuint *width, GLuint *height ) 747{ 748 OSMesaContext osmesa = (OSMesaContext) ctx; 749 *width = osmesa->width; 750 *height = osmesa->height; 751} 752 753 754/**********************************************************************/ 755/***** Read/write spans/arrays of RGBA pixels *****/ 756/**********************************************************************/ 757 758/* Write RGBA pixels to an RGBA (or permuted) buffer. */ 759static void write_rgba_span( const GLcontext *ctx, 760 GLuint n, GLint x, GLint y, 761 CONST GLchan rgba[][4], const GLubyte mask[] ) 762{ 763 OSMesaContext osmesa = (OSMesaContext) ctx; 764 GLuint *ptr4 = PIXELADDR4( x, y ); 765 GLuint i; 766 GLint rshift = osmesa->rshift; 767 GLint gshift = osmesa->gshift; 768 GLint bshift = osmesa->bshift; 769 GLint ashift = osmesa->ashift; 770 if (mask) { 771 for (i=0;i<n;i++,ptr4++) { 772 if (mask[i]) { 773 *ptr4 = PACK_RGBA2( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] ); 774 } 775 } 776 } 777 else { 778 for (i=0;i<n;i++,ptr4++) { 779 *ptr4 = PACK_RGBA2( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] ); 780 } 781 } 782} 783 784 785/* Write RGBA pixels to an RGBA buffer. This is the fastest span-writer. */ 786static void write_rgba_span_rgba( const GLcontext *ctx, 787 GLuint n, GLint x, GLint y, 788 CONST GLchan rgba[][4], 789 const GLubyte mask[] ) 790{ 791 OSMesaContext osmesa = (OSMesaContext) ctx; 792 GLuint *ptr4 = PIXELADDR4( x, y ); 793 const GLuint *rgba4 = (const GLuint *) rgba; 794 GLuint i; 795 if (mask) { 796 for (i=0;i<n;i++) { 797 if (mask[i]) { 798 ptr4[i] = rgba4[i]; 799 } 800 } 801 } 802 else { 803 MEMCPY( ptr4, rgba4, n * 4 ); 804 } 805} 806 807 808/* Write RGB pixels to an RGBA (or permuted) buffer. */ 809static void write_rgb_span( const GLcontext *ctx, 810 GLuint n, GLint x, GLint y, 811 CONST GLchan rgb[][3], const GLubyte mask[] ) 812{ 813 OSMesaContext osmesa = (OSMesaContext) ctx; 814 GLuint *ptr4 = PIXELADDR4( x, y ); 815 GLuint i; 816 GLint rshift = osmesa->rshift; 817 GLint gshift = osmesa->gshift; 818 GLint bshift = osmesa->bshift; 819 GLint ashift = osmesa->ashift; 820 if (mask) { 821 for (i=0;i<n;i++,ptr4++) { 822 if (mask[i]) { 823 *ptr4 = PACK_RGBA2( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255 ); 824 } 825 } 826 } 827 else { 828 for (i=0;i<n;i++,ptr4++) { 829 *ptr4 = PACK_RGBA2( rgb[i][RCOMP], rgb[i][GCOMP], rgb[i][BCOMP], 255); 830 } 831 } 832} 833 834 835 836static void write_monocolor_span( const GLcontext *ctx, 837 GLuint n, GLint x, GLint y, 838 const GLubyte mask[] ) 839{ 840 OSMesaContext osmesa = (OSMesaContext) ctx; 841 GLuint *ptr4 = PIXELADDR4(x,y); 842 GLuint i; 843 for (i=0;i<n;i++,ptr4++) { 844 if (mask[i]) { 845 *ptr4 = osmesa->pixel; 846 } 847 } 848} 849 850 851 852static void write_rgba_pixels( const GLcontext *ctx, 853 GLuint n, const GLint x[], const GLint y[], 854 CONST GLchan rgba[][4], const GLubyte mask[] ) 855{ 856 OSMesaContext osmesa = (OSMesaContext) ctx; 857 GLuint i; 858 GLint rshift = osmesa->rshift; 859 GLint gshift = osmesa->gshift; 860 GLint bshift = osmesa->bshift; 861 GLint ashift = osmesa->ashift; 862 for (i=0;i<n;i++) { 863 if (mask[i]) { 864 GLuint *ptr4 = PIXELADDR4(x[i],y[i]); 865 *ptr4 = PACK_RGBA2( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] ); 866 } 867 } 868} 869 870 871 872static void write_monocolor_pixels( const GLcontext *ctx, 873 GLuint n, const GLint x[], const GLint y[], 874 const GLubyte mask[] ) 875{ 876 OSMesaContext osmesa = (OSMesaContext) ctx; 877 GLuint i; 878 for (i=0;i<n;i++) { 879 if (mask[i]) { 880 GLuint *ptr4 = PIXELADDR4(x[i],y[i]); 881 *ptr4 = osmesa->pixel; 882 } 883 } 884} 885 886 887static void read_rgba_span( const GLcontext *ctx, GLuint n, GLint x, GLint y, 888 GLchan rgba[][4] ) 889{ 890 OSMesaContext osmesa = (OSMesaContext) ctx; 891 GLuint i; 892 GLuint *ptr4 = PIXELADDR4(x,y); 893 for (i=0;i<n;i++) { 894 GLuint pixel = *ptr4++; 895 rgba[i][RCOMP] = UNPACK_RED(pixel); 896 rgba[i][GCOMP] = UNPACK_GREEN(pixel); 897 rgba[i][BCOMP] = UNPACK_BLUE(pixel); 898 rgba[i][ACOMP] = UNPACK_ALPHA(pixel); 899 } 900} 901 902 903/* Read RGBA pixels from an RGBA buffer */ 904static void read_rgba_span_rgba( const GLcontext *ctx, 905 GLuint n, GLint x, GLint y, 906 GLchan rgba[][4] ) 907{ 908 OSMesaContext osmesa = (OSMesaContext) ctx; 909 GLuint *ptr4 = PIXELADDR4(x,y); 910 MEMCPY( rgba, ptr4, n * 4 * sizeof(GLchan) ); 911} 912 913 914static void read_rgba_pixels( const GLcontext *ctx, 915 GLuint n, const GLint x[], const GLint y[], 916 GLchan rgba[][4], const GLubyte mask[] ) 917{ 918 OSMesaContext osmesa = (OSMesaContext) ctx; 919 GLuint i; 920 for (i=0;i<n;i++) { 921 if (mask[i]) { 922 GLuint *ptr4 = PIXELADDR4(x[i],y[i]); 923 GLuint pixel = *ptr4; 924 rgba[i][RCOMP] = UNPACK_RED(pixel); 925 rgba[i][GCOMP] = UNPACK_GREEN(pixel); 926 rgba[i][BCOMP] = UNPACK_BLUE(pixel); 927 rgba[i][ACOMP] = UNPACK_ALPHA(pixel); 928 } 929 } 930} 931 932/**********************************************************************/ 933/***** 3 byte RGB pixel support funcs *****/ 934/**********************************************************************/ 935 936/* Write RGBA pixels to an RGB or BGR buffer. */ 937static void write_rgba_span3( const GLcontext *ctx, 938 GLuint n, GLint x, GLint y, 939 CONST GLchan rgba[][4], const GLubyte mask[] ) 940{ 941 OSMesaContext osmesa = (OSMesaContext) ctx; 942 GLubyte *ptr3 = PIXELADDR3( x, y); 943 GLuint i; 944 GLint rind = osmesa->rind; 945 GLint gind = osmesa->gind; 946 GLint bind = osmesa->bind; 947 if (mask) { 948 for (i=0;i<n;i++,ptr3+=3) { 949 if (mask[i]) { 950 ptr3[rind] = rgba[i][RCOMP]; 951 ptr3[gind] = rgba[i][GCOMP]; 952 ptr3[bind] = rgba[i][BCOMP]; 953 } 954 } 955 } 956 else { 957 for (i=0;i<n;i++,ptr3+=3) { 958 ptr3[rind] = rgba[i][RCOMP]; 959 ptr3[gind] = rgba[i][GCOMP]; 960 ptr3[bind] = rgba[i][BCOMP]; 961 } 962 } 963} 964 965/* Write RGB pixels to an RGB or BGR buffer. */ 966static void write_rgb_span3( const GLcontext *ctx, 967 GLuint n, GLint x, GLint y, 968 CONST GLchan rgb[][3], const GLubyte mask[] ) 969{ 970 OSMesaContext osmesa = (OSMesaContext) ctx; 971 GLubyte *ptr3 = PIXELADDR3( x, y); 972 GLuint i; 973 GLint rind = osmesa->rind; 974 GLint gind = osmesa->gind; 975 GLint bind = osmesa->bind; 976 if (mask) { 977 for (i=0;i<n;i++,ptr3+=3) { 978 if (mask[i]) { 979 ptr3[rind] = rgb[i][RCOMP]; 980 ptr3[gind] = rgb[i][GCOMP]; 981 ptr3[bind] = rgb[i][BCOMP]; 982 } 983 } 984 } 985 else { 986 for (i=0;i<n;i++,ptr3+=3) { 987 ptr3[rind] = rgb[i][RCOMP]; 988 ptr3[gind] = rgb[i][GCOMP]; 989 ptr3[bind] = rgb[i][BCOMP]; 990 } 991 } 992} 993 994 995static void write_monocolor_span3( const GLcontext *ctx, 996 GLuint n, GLint x, GLint y, 997 const GLubyte mask[] ) 998{ 999 OSMesaContext osmesa = (OSMesaContext) ctx; 1000 1001 GLubyte rval = UNPACK_RED(osmesa->pixel); 1002 GLubyte gval = UNPACK_GREEN(osmesa->pixel); 1003 GLubyte bval = UNPACK_BLUE(osmesa->pixel); 1004 GLint rind = osmesa->rind; 1005 GLint gind = osmesa->gind; 1006 GLint bind = osmesa->bind; 1007 GLubyte *ptr3 = PIXELADDR3( x, y); 1008 GLuint i; 1009 for (i=0;i<n;i++,ptr3+=3) { 1010 if (mask[i]) { 1011 ptr3[rind] = rval; 1012 ptr3[gind] = gval; 1013 ptr3[bind] = bval; 1014 } 1015 } 1016} 1017 1018static void write_rgba_pixels3( const GLcontext *ctx, 1019 GLuint n, const GLint x[], const GLint y[], 1020 CONST GLchan rgba[][4], const GLubyte mask[] ) 1021{ 1022 OSMesaContext osmesa = (OSMesaContext) ctx; 1023 GLuint i; 1024 GLint rind = osmesa->rind; 1025 GLint gind = osmesa->gind; 1026 GLint bind = osmesa->bind; 1027 for (i=0;i<n;i++) { 1028 if (mask[i]) { 1029 GLubyte *ptr3 = PIXELADDR3(x[i],y[i]); 1030 ptr3[rind] = rgba[i][RCOMP]; 1031 ptr3[gind] = rgba[i][GCOMP]; 1032 ptr3[bind] = rgba[i][BCOMP]; 1033 } 1034 } 1035} 1036 1037static void write_monocolor_pixels3( const GLcontext *ctx, 1038 GLuint n, const GLint x[], const GLint y[], 1039 const GLubyte mask[] ) 1040{ 1041 OSMesaContext osmesa = (OSMesaContext) ctx; 1042 GLuint i; 1043 GLint rind = osmesa->rind; 1044 GLint gind = osmesa->gind; 1045 GLint bind = osmesa->bind; 1046 GLubyte rval = UNPACK_RED(osmesa->pixel); 1047 GLubyte gval = UNPACK_GREEN(osmesa->pixel); 1048 GLubyte bval = UNPACK_BLUE(osmesa->pixel); 1049 for (i=0;i<n;i++) { 1050 if (mask[i]) { 1051 GLubyte *ptr3 = PIXELADDR3(x[i],y[i]); 1052 ptr3[rind] = rval; 1053 ptr3[gind] = gval; 1054 ptr3[bind] = bval; 1055 } 1056 } 1057} 1058 1059static void read_rgba_span3( const GLcontext *ctx, 1060 GLuint n, GLint x, GLint y, 1061 GLchan rgba[][4] ) 1062{ 1063 OSMesaContext osmesa = (OSMesaContext) ctx; 1064 GLuint i; 1065 GLint rind = osmesa->rind; 1066 GLint gind = osmesa->gind; 1067 GLint bind = osmesa->bind; 1068 const GLubyte *ptr3 = PIXELADDR3( x, y); 1069 for (i=0;i<n;i++,ptr3+=3) { 1070 rgba[i][RCOMP] = ptr3[rind]; 1071 rgba[i][GCOMP] = ptr3[gind]; 1072 rgba[i][BCOMP] = ptr3[bind]; 1073 rgba[i][ACOMP] = 0; 1074 } 1075} 1076 1077static void read_rgba_pixels3( const GLcontext *ctx, 1078 GLuint n, const GLint x[], const GLint y[], 1079 GLchan rgba[][4], const GLubyte mask[] ) 1080{ 1081 OSMesaContext osmesa = (OSMesaContext) ctx; 1082 GLuint i; 1083 GLint rind = osmesa->rind; 1084 GLint gind = osmesa->gind; 1085 GLint bind = osmesa->bind; 1086 for (i=0;i<n;i++) { 1087 if (mask[i]) { 1088 const GLubyte *ptr3 = PIXELADDR3(x[i],y[i]); 1089 rgba[i][RCOMP] = ptr3[rind]; 1090 rgba[i][GCOMP] = ptr3[gind]; 1091 rgba[i][BCOMP] = ptr3[bind]; 1092 rgba[i][ACOMP] = 0; 1093 } 1094 } 1095} 1096 1097 1098/**********************************************************************/ 1099/***** Read/write spans/arrays of CI pixels *****/ 1100/**********************************************************************/ 1101 1102/* Write 32-bit color index to buffer */ 1103static void write_index32_span( const GLcontext *ctx, 1104 GLuint n, GLint x, GLint y, 1105 const GLuint index[], const GLubyte mask[] ) 1106{ 1107 OSMesaContext osmesa = (OSMesaContext) ctx; 1108 GLubyte *ptr1 = PIXELADDR1(x,y); 1109 GLuint i; 1110 if (mask) { 1111 for (i=0;i<n;i++,ptr1++) { 1112 if (mask[i]) { 1113 *ptr1 = (GLubyte) index[i]; 1114 } 1115 } 1116 } 1117 else { 1118 for (i=0;i<n;i++,ptr1++) { 1119 *ptr1 = (GLubyte) index[i]; 1120 } 1121 } 1122} 1123 1124 1125/* Write 8-bit color index to buffer */ 1126static void write_index8_span( const GLcontext *ctx, 1127 GLuint n, GLint x, GLint y, 1128 const GLubyte index[], const GLubyte mask[] ) 1129{ 1130 OSMesaContext osmesa = (OSMesaContext) ctx; 1131 GLubyte *ptr1 = PIXELADDR1(x,y); 1132 GLuint i; 1133 if (mask) { 1134 for (i=0;i<n;i++,ptr1++) { 1135 if (mask[i]) { 1136 *ptr1 = (GLubyte) index[i]; 1137 } 1138 } 1139 } 1140 else { 1141 MEMCPY( ptr1, index, n ); 1142 } 1143} 1144 1145 1146static void write_monoindex_span( const GLcontext *ctx, 1147 GLuint n, GLint x, GLint y, 1148 const GLubyte mask[] ) 1149{ 1150 OSMesaContext osmesa = (OSMesaContext) ctx; 1151 GLubyte *ptr1 = PIXELADDR1(x,y); 1152 GLuint i; 1153 for (i=0;i<n;i++,ptr1++) { 1154 if (mask[i]) { 1155 *ptr1 = (GLubyte) osmesa->pixel; 1156 } 1157 } 1158} 1159 1160 1161static void write_index_pixels( const GLcontext *ctx, 1162 GLuint n, const GLint x[], const GLint y[], 1163 const GLuint index[], const GLubyte mask[] ) 1164{ 1165 OSMesaContext osmesa = (OSMesaContext) ctx; 1166 GLuint i; 1167 for (i=0;i<n;i++) { 1168 if (mask[i]) { 1169 GLubyte *ptr1 = PIXELADDR1(x[i],y[i]); 1170 *ptr1 = (GLubyte) index[i]; 1171 } 1172 } 1173} 1174 1175 1176static void write_monoindex_pixels( const GLcontext *ctx, 1177 GLuint n, const GLint x[], const GLint y[], 1178 const GLubyte mask[] ) 1179{ 1180 OSMesaContext osmesa = (OSMesaContext) ctx; 1181 GLuint i; 1182 for (i=0;i<n;i++) { 1183 if (mask[i]) { 1184 GLubyte *ptr1 = PIXELADDR1(x[i],y[i]); 1185 *ptr1 = (GLubyte) osmesa->pixel; 1186 } 1187 } 1188} 1189 1190 1191static void read_index_span( const GLcontext *ctx, 1192 GLuint n, GLint x, GLint y, GLuint index[] ) 1193{ 1194 OSMesaContext osmesa = (OSMesaContext) ctx; 1195 GLuint i; 1196 const GLubyte *ptr1 = PIXELADDR1(x,y); 1197 for (i=0;i<n;i++,ptr1++) { 1198 index[i] = (GLuint) *ptr1; 1199 } 1200} 1201 1202 1203static void read_index_pixels( const GLcontext *ctx, 1204 GLuint n, const GLint x[], const GLint y[], 1205 GLuint index[], const GLubyte mask[] ) 1206{ 1207 OSMesaContext osmesa = (OSMesaContext) ctx; 1208 GLuint i; 1209 for (i=0;i<n;i++) { 1210 if (mask[i] ) { 1211 const GLubyte *ptr1 = PIXELADDR1(x[i],y[i]); 1212 index[i] = (GLuint) *ptr1; 1213 } 1214 } 1215} 1216 1217 1218 1219/**********************************************************************/ 1220/***** Optimized line rendering *****/ 1221/**********************************************************************/ 1222 1223 1224/* 1225 * Draw a flat-shaded, RGB line into an osmesa buffer. 1226 */ 1227static void flat_rgba_line( GLcontext *ctx, 1228 GLuint vert0, GLuint vert1, GLuint pvert ) 1229{ 1230 OSMesaContext osmesa = (OSMesaContext) ctx; 1231 GLubyte *color = ctx->VB->ColorPtr->data[pvert]; 1232 unsigned long pixel = PACK_RGBA( color[0], color[1], color[2], color[3] ); 1233 1234#define INTERP_XY 1 1235#define CLIP_HACK 1 1236#define PLOT(X,Y) { GLuint *ptr4 = PIXELADDR4(X,Y); *ptr4 = pixel; } 1237 1238#ifdef WIN32 1239#include "..\linetemp.h" 1240#else 1241#include "linetemp.h" 1242#endif 1243} 1244 1245 1246/* 1247 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer. 1248 */ 1249static void flat_rgba_z_line( GLcontext *ctx, 1250 GLuint vert0, GLuint vert1, GLuint pvert ) 1251{ 1252 OSMesaContext osmesa = (OSMesaContext) ctx; 1253 GLubyte *color = ctx->VB->ColorPtr->data[pvert]; 1254 unsigned long pixel = PACK_RGBA( color[0], color[1], color[2], color[3] ); 1255 1256#define INTERP_XY 1 1257#define INTERP_Z 1 1258#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1259#define CLIP_HACK 1 1260#define PLOT(X,Y) \ 1261 if (Z < *zPtr) { \ 1262 GLuint *ptr4 = PIXELADDR4(X,Y); \ 1263 *ptr4 = pixel; \ 1264 *zPtr = Z; \ 1265 } 1266 1267#ifdef WIN32 1268#include "..\linetemp.h" 1269#else 1270#include "linetemp.h" 1271#endif 1272} 1273 1274 1275/* 1276 * Draw a flat-shaded, alpha-blended, RGB line into an osmesa buffer. 1277 */ 1278static void flat_blend_rgba_line( GLcontext *ctx, 1279 GLuint vert0, GLuint vert1, GLuint pvert ) 1280{ 1281 OSMesaContext osmesa = (OSMesaContext) ctx; 1282 struct vertex_buffer *VB = ctx->VB; 1283 GLint rshift = osmesa->rshift; 1284 GLint gshift = osmesa->gshift; 1285 GLint bshift = osmesa->bshift; 1286 GLint avalue = VB->ColorPtr->data[pvert][3]; 1287 GLint msavalue = 255 - avalue; 1288 GLint rvalue = VB->ColorPtr->data[pvert][0]*avalue; 1289 GLint gvalue = VB->ColorPtr->data[pvert][1]*avalue; 1290 GLint bvalue = VB->ColorPtr->data[pvert][2]*avalue; 1291 1292#define INTERP_XY 1 1293#define CLIP_HACK 1 1294#define PLOT(X,Y) \ 1295 { GLuint *ptr4 = PIXELADDR4(X,Y); \ 1296 GLuint pixel = 0; \ 1297 pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);\ 1298 pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);\ 1299 pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);\ 1300 *ptr4 = pixel; \ 1301 } 1302 1303#ifdef WIN32 1304#include "..\linetemp.h" 1305#else 1306#include "linetemp.h" 1307#endif 1308} 1309 1310 1311/* 1312 * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer. 1313 */ 1314static void flat_blend_rgba_z_line( GLcontext *ctx, 1315 GLuint vert0, GLuint vert1, GLuint pvert ) 1316{ 1317 OSMesaContext osmesa = (OSMesaContext) ctx; 1318 struct vertex_buffer *VB = ctx->VB; 1319 GLint rshift = osmesa->rshift; 1320 GLint gshift = osmesa->gshift; 1321 GLint bshift = osmesa->bshift; 1322 GLint avalue = VB->ColorPtr->data[pvert][3]; 1323 GLint msavalue = 256 - avalue; 1324 GLint rvalue = VB->ColorPtr->data[pvert][0]*avalue; 1325 GLint gvalue = VB->ColorPtr->data[pvert][1]*avalue; 1326 GLint bvalue = VB->ColorPtr->data[pvert][2]*avalue; 1327 1328#define INTERP_XY 1 1329#define INTERP_Z 1 1330#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1331#define CLIP_HACK 1 1332#define PLOT(X,Y) \ 1333 if (Z < *zPtr) { \ 1334 GLuint *ptr4 = PIXELADDR4(X,Y); \ 1335 GLuint pixel = 0; \ 1336 pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift); \ 1337 pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift); \ 1338 pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift); \ 1339 *ptr4 = pixel; \ 1340 } 1341 1342#ifdef WIN32 1343#include "..\linetemp.h" 1344#else 1345#include "linetemp.h" 1346#endif 1347} 1348 1349 1350/* 1351 * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer. 1352 */ 1353static void flat_blend_rgba_z_line_write( GLcontext *ctx, 1354 GLuint vert0, GLuint vert1, GLuint pvert ) 1355{ 1356 OSMesaContext osmesa = (OSMesaContext) ctx; 1357 struct vertex_buffer *VB = ctx->VB; 1358 GLint rshift = osmesa->rshift; 1359 GLint gshift = osmesa->gshift; 1360 GLint bshift = osmesa->bshift; 1361 GLint avalue = VB->ColorPtr->data[pvert][3]; 1362 GLint msavalue = 256 - avalue; 1363 GLint rvalue = VB->ColorPtr->data[pvert][0]*avalue; 1364 GLint gvalue = VB->ColorPtr->data[pvert][1]*avalue; 1365 GLint bvalue = VB->ColorPtr->data[pvert][2]*avalue; 1366 1367#define INTERP_XY 1 1368#define INTERP_Z 1 1369#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1370#define CLIP_HACK 1 1371#define PLOT(X,Y) \ 1372 if (Z < *zPtr) { \ 1373 GLuint *ptr4 = PIXELADDR4(X,Y); \ 1374 GLuint pixel = 0; \ 1375 pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift); \ 1376 pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift); \ 1377 pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift); \ 1378 *ptr4 = pixel; \ 1379 *zPtr = Z; \ 1380 } 1381 1382#ifdef WIN32 1383#include "..\linetemp.h" 1384#else 1385#include "linetemp.h" 1386#endif 1387} 1388 1389 1390/* 1391 * Analyze context state to see if we can provide a fast line drawing 1392 * function, like those in lines.c. Otherwise, return NULL. 1393 */ 1394static line_func choose_line_function( GLcontext *ctx ) 1395{ 1396 OSMesaContext osmesa = (OSMesaContext) ctx; 1397 1398 if (ctx->Line.SmoothFlag) return NULL; 1399 if (ctx->Texture.ReallyEnabled) return NULL; 1400 if (ctx->Light.ShadeModel!=GL_FLAT) return NULL; 1401 1402 if (ctx->Line.Width==1.0F 1403 && ctx->Line.StippleFlag==GL_FALSE) { 1404 1405 if (ctx->RasterMask==DEPTH_BIT 1406 && ctx->Depth.Func==GL_LESS 1407 && ctx->Depth.Mask==GL_TRUE 1408 && ctx->Visual.DepthBits == DEFAULT_SOFTWARE_DEPTH_BITS) { 1409 switch(osmesa->format) { 1410 case OSMESA_RGBA: 1411 case OSMESA_BGRA: 1412 case OSMESA_ARGB: 1413 return flat_rgba_z_line; 1414 default: 1415 return NULL; 1416 } 1417 } 1418 1419 if (ctx->RasterMask==0) { 1420 switch(osmesa->format) { 1421 case OSMESA_RGBA: 1422 case OSMESA_BGRA: 1423 case OSMESA_ARGB: 1424 return flat_rgba_line; 1425 default: 1426 return NULL; 1427 } 1428 } 1429 1430 if (ctx->RasterMask==(DEPTH_BIT|BLEND_BIT) 1431 && ctx->Depth.Func==GL_LESS 1432 && ctx->Depth.Mask==GL_TRUE 1433 && ctx->Visual.DepthBits == DEFAULT_SOFTWARE_DEPTH_BITS 1434 && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA 1435 && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA 1436 && ctx->Color.BlendSrcA==GL_SRC_ALPHA 1437 && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA 1438 && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { 1439 switch(osmesa->format) { 1440 case OSMESA_RGBA: 1441 case OSMESA_BGRA: 1442 case OSMESA_ARGB: 1443 return flat_blend_rgba_z_line_write; 1444 default: 1445 return NULL; 1446 } 1447 } 1448 1449 if (ctx->RasterMask==(DEPTH_BIT|BLEND_BIT) 1450 && ctx->Depth.Func==GL_LESS 1451 && ctx->Depth.Mask==GL_FALSE 1452 && ctx->Visual.DepthBits == DEFAULT_SOFTWARE_DEPTH_BITS 1453 && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA 1454 && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA 1455 && ctx->Color.BlendSrcA==GL_SRC_ALPHA 1456 && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA 1457 && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { 1458 switch(osmesa->format) { 1459 case OSMESA_RGBA: 1460 case OSMESA_BGRA: 1461 case OSMESA_ARGB: 1462 return flat_blend_rgba_z_line; 1463 default: 1464 return NULL; 1465 } 1466 } 1467 1468 if (ctx->RasterMask==BLEND_BIT 1469 && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA 1470 && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA 1471 && ctx->Color.BlendSrcA==GL_SRC_ALPHA 1472 && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA 1473 && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { 1474 switch(osmesa->format) { 1475 case OSMESA_RGBA: 1476 case OSMESA_BGRA: 1477 case OSMESA_ARGB: 1478 return flat_blend_rgba_line; 1479 default: 1480 return NULL; 1481 } 1482 } 1483 1484 } 1485 return NULL; 1486} 1487 1488 1489/**********************************************************************/ 1490/***** Optimized triangle rendering *****/ 1491/**********************************************************************/ 1492 1493 1494/* 1495 * Smooth-shaded, z-less triangle, RGBA color. 1496 */ 1497static void smooth_rgba_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1, 1498 GLuint v2, GLuint pv ) 1499{ 1500 OSMesaContext osmesa = (OSMesaContext) ctx; 1501 GLint rshift = osmesa->rshift; 1502 GLint gshift = osmesa->gshift; 1503 GLint bshift = osmesa->bshift; 1504 GLint ashift = osmesa->ashift; 1505 (void) pv; 1506 1507#define INTERP_Z 1 1508#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1509#define INTERP_RGB 1 1510#define INTERP_ALPHA 1 1511#define INNER_LOOP( LEFT, RIGHT, Y ) \ 1512{ \ 1513 GLint i, len = RIGHT-LEFT; \ 1514 GLuint *img = PIXELADDR4(LEFT,Y); \ 1515 for (i=0;i<len;i++,img++) { \ 1516 GLdepth z = FixedToDepth(ffz); \ 1517 if (z < zRow[i]) { \ 1518 *img = PACK_RGBA2( FixedToInt(ffr), FixedToInt(ffg), \ 1519 FixedToInt(ffb), FixedToInt(ffa) ); \ 1520 zRow[i] = z; \ 1521 } \ 1522 ffr += fdrdx; ffg += fdgdx; ffb += fdbdx; ffa += fdadx;\ 1523 ffz += fdzdx; \ 1524 } \ 1525} 1526#ifdef WIN32 1527#include "..\tritemp.h" 1528#else 1529#include "tritemp.h" 1530#endif 1531} 1532 1533 1534 1535 1536/* 1537 * Flat-shaded, z-less triangle, RGBA color. 1538 */ 1539static void flat_rgba_z_triangle( GLcontext *ctx, GLuint v0, GLuint v1, 1540 GLuint v2, GLuint pv ) 1541{ 1542 OSMesaContext osmesa = (OSMesaContext) ctx; 1543#define INTERP_Z 1 1544#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 1545#define SETUP_CODE \ 1546 GLubyte r = VB->ColorPtr->data[pv][0]; \ 1547 GLubyte g = VB->ColorPtr->data[pv][1]; \ 1548 GLubyte b = VB->ColorPtr->data[pv][2]; \ 1549 GLubyte a = VB->ColorPtr->data[pv][3]; \ 1550 GLuint pixel = PACK_RGBA(r,g,b,a); 1551 1552#define INNER_LOOP( LEFT, RIGHT, Y ) \ 1553{ \ 1554 GLint i, len = RIGHT-LEFT; \ 1555 GLuint *img = PIXELADDR4(LEFT,Y); \ 1556 for (i=0;i<len;i++,img++) { \ 1557 GLdepth z = FixedToDepth(ffz); \ 1558 if (z < zRow[i]) { \ 1559 *img = pixel; \ 1560 zRow[i] = z; \ 1561 } \ 1562 ffz += fdzdx; \ 1563 } \ 1564} 1565#ifdef WIN32 1566#include "..\tritemp.h" 1567#else 1568#include "tritemp.h" 1569#endif 1570} 1571 1572 1573 1574/* 1575 * Return pointer to an accelerated triangle function if possible. 1576 */ 1577static triangle_func choose_triangle_function( GLcontext *ctx ) 1578{ 1579 OSMesaContext osmesa = (OSMesaContext) ctx; 1580 1581 if ((osmesa->format==OSMESA_RGB)||(osmesa->format==OSMESA_BGR)) return NULL; 1582 1583 if (ctx->Polygon.SmoothFlag) return NULL; 1584 if (ctx->Polygon.StippleFlag) return NULL; 1585 if (ctx->Texture.ReallyEnabled) return NULL; 1586 1587 if (ctx->RasterMask==DEPTH_BIT 1588 && ctx->Depth.Func==GL_LESS 1589 && ctx->Depth.Mask==GL_TRUE 1590 && ctx->Visual.DepthBits == DEFAULT_SOFTWARE_DEPTH_BITS 1591 && osmesa->format!=OSMESA_COLOR_INDEX) { 1592 if (ctx->Light.ShadeModel==GL_SMOOTH) { 1593 return smooth_rgba_z_triangle; 1594 } 1595 else { 1596 return flat_rgba_z_triangle; 1597 } 1598 } 1599 return NULL; 1600} 1601 1602 1603 1604static const GLubyte *get_string( GLcontext *ctx, GLenum name ) 1605{ 1606 (void) ctx; 1607 switch (name) { 1608 case GL_RENDERER: 1609 return (const GLubyte *) "Mesa OffScreen"; 1610 default: 1611 return NULL; 1612 } 1613} 1614 1615 1616static void osmesa_update_state( GLcontext *ctx ) 1617{ 1618 OSMesaContext osmesa = (OSMesaContext) ctx; 1619 1620 ASSERT((void *) osmesa == (void *) ctx->DriverCtx); 1621 1622 ctx->Driver.GetString = get_string; 1623 ctx->Driver.UpdateState = osmesa_update_state; 1624 1625 ctx->Driver.SetDrawBuffer = set_draw_buffer; 1626 ctx->Driver.SetReadBuffer = set_read_buffer; 1627 ctx->Driver.Color = set_color; 1628 ctx->Driver.Index = set_index; 1629 ctx->Driver.ClearIndex = clear_index; 1630 ctx->Driver.ClearColor = clear_color; 1631 ctx->Driver.Clear = clear; 1632 1633 ctx->Driver.GetBufferSize = buffer_size; 1634 1635 ctx->Driver.PointsFunc = NULL; 1636 ctx->Driver.LineFunc = choose_line_function( ctx ); 1637 ctx->Driver.TriangleFunc = choose_triangle_function( ctx ); 1638 1639 1640 /* RGB(A) span/pixel functions */ 1641 if ((osmesa->format==OSMESA_RGB) || (osmesa->format==OSMESA_BGR)) { 1642 /* 3 bytes / pixel in frame buffer */ 1643 ctx->Driver.WriteRGBASpan = write_rgba_span3; 1644 ctx->Driver.WriteRGBSpan = write_rgb_span3; 1645 ctx->Driver.WriteRGBAPixels = write_rgba_pixels3; 1646 ctx->Driver.WriteMonoRGBASpan = write_monocolor_span3; 1647 ctx->Driver.WriteMonoRGBAPixels = write_monocolor_pixels3; 1648 ctx->Driver.ReadRGBASpan = read_rgba_span3; 1649 ctx->Driver.ReadRGBAPixels = read_rgba_pixels3; 1650 } 1651 else { 1652 /* 4 bytes / pixel in frame buffer */ 1653 if (osmesa->format==OSMESA_RGBA 1654 && RCOMP==0 && GCOMP==1 && BCOMP==2 && ACOMP==3) 1655 ctx->Driver.WriteRGBASpan = write_rgba_span_rgba; 1656 else 1657 ctx->Driver.WriteRGBASpan = write_rgba_span; 1658 ctx->Driver.WriteRGBSpan = write_rgb_span; 1659 ctx->Driver.WriteRGBAPixels = write_rgba_pixels; 1660 ctx->Driver.WriteMonoRGBASpan = write_monocolor_span; 1661 ctx->Driver.WriteMonoRGBAPixels = write_monocolor_pixels; 1662 if (osmesa->format==OSMESA_RGBA 1663 && RCOMP==0 && GCOMP==1 && BCOMP==2 && ACOMP==3) 1664 ctx->Driver.ReadRGBASpan = read_rgba_span_rgba; 1665 else 1666 ctx->Driver.ReadRGBASpan = read_rgba_span; 1667 ctx->Driver.ReadRGBAPixels = read_rgba_pixels; 1668 } 1669 1670 /* CI span/pixel functions */ 1671 ctx->Driver.WriteCI32Span = write_index32_span; 1672 ctx->Driver.WriteCI8Span = write_index8_span; 1673 ctx->Driver.WriteMonoCISpan = write_monoindex_span; 1674 ctx->Driver.WriteCI32Pixels = write_index_pixels; 1675 ctx->Driver.WriteMonoCIPixels = write_monoindex_pixels; 1676 ctx->Driver.ReadCI32Span = read_index_span; 1677 ctx->Driver.ReadCI32Pixels = read_index_pixels; 1678} 1679