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