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