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