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