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