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