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