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