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