osmesa.c revision 9c799cdc49e9200f5a1c7c7d9787d5729b5b0082
1/* $Id: osmesa.c,v 1.97 2002/11/13 16:57:44 brianp Exp $ */ 2 3/* 4 * Mesa 3-D graphics library 5 * Version: 5.0 6 * 7 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included 17 * in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 27 28/* 29 * Off-Screen Mesa rendering / Rendering into client memory space 30 * 31 * Note on thread safety: this driver is thread safe. All 32 * functions are reentrant. The notion of current context is 33 * managed by the core _mesa_make_current() and _mesa_get_current_context() 34 * functions. Those functions are thread-safe. 35 */ 36 37 38#include "glheader.h" 39#include "GL/osmesa.h" 40#include "buffers.h" 41#include "context.h" 42#include "colormac.h" 43#include "depth.h" 44#include "extensions.h" 45#include "imports.h" 46#include "macros.h" 47#include "matrix.h" 48#include "mmath.h" 49#include "mtypes.h" 50#include "texformat.h" 51#include "texstore.h" 52#include "array_cache/acache.h" 53#include "swrast/swrast.h" 54#include "swrast_setup/swrast_setup.h" 55#include "swrast/s_context.h" 56#include "swrast/s_depth.h" 57#include "swrast/s_lines.h" 58#include "swrast/s_triangle.h" 59#include "tnl/tnl.h" 60#include "tnl/t_context.h" 61#include "tnl/t_pipeline.h" 62 63 64 65/* 66 * This is the OS/Mesa context struct. 67 * Notice how it includes a GLcontext. By doing this we're mimicking 68 * C++ inheritance/derivation. 69 * Later, we can cast a GLcontext pointer into an OSMesaContext pointer 70 * or vice versa. 71 */ 72struct osmesa_context { 73 GLcontext gl_ctx; /* The core GL/Mesa context */ 74 GLvisual *gl_visual; /* Describes the buffers */ 75 GLframebuffer *gl_buffer; /* Depth, stencil, accum, etc buffers */ 76 GLenum format; /* either GL_RGBA or GL_COLOR_INDEX */ 77 void *buffer; /* the image buffer */ 78 GLint width, height; /* size of image buffer */ 79 GLint rowlength; /* number of pixels per row */ 80 GLint userRowLength; /* user-specified number of pixels per row */ 81 GLint rshift, gshift; /* bit shifts for RGBA formats */ 82 GLint bshift, ashift; 83 GLint rInd, gInd, bInd, aInd;/* index offsets for RGBA formats */ 84 GLchan *rowaddr[MAX_HEIGHT]; /* address of first pixel in each image row */ 85 GLboolean yup; /* TRUE -> Y increases upward */ 86 /* FALSE -> Y increases downward */ 87}; 88 89 90#define OSMESA_CONTEXT(ctx) ((OSMesaContext) (ctx->DriverCtx)) 91 92 93 94/**********************************************************************/ 95/*** Private Device Driver Functions ***/ 96/**********************************************************************/ 97 98 99static const GLubyte * 100get_string( GLcontext *ctx, GLenum name ) 101{ 102 (void) ctx; 103 switch (name) { 104 case GL_RENDERER: 105#if CHAN_BITS == 32 106 return (const GLubyte *) "Mesa OffScreen32"; 107#elif CHAN_BITS == 16 108 return (const GLubyte *) "Mesa OffScreen16"; 109#else 110 return (const GLubyte *) "Mesa OffScreen"; 111#endif 112 default: 113 return NULL; 114 } 115} 116 117 118static void 119osmesa_update_state( GLcontext *ctx, GLuint new_state ) 120{ 121 /* easy - just propogate */ 122 _swrast_InvalidateState( ctx, new_state ); 123 _swsetup_InvalidateState( ctx, new_state ); 124 _ac_InvalidateState( ctx, new_state ); 125 _tnl_InvalidateState( ctx, new_state ); 126} 127 128 129static void 130set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit ) 131{ 132 /* separate read buffer not supported */ 133 ASSERT(buffer == ctx->DrawBuffer); 134 ASSERT(bufferBit == FRONT_LEFT_BIT); 135} 136 137 138static void 139get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) 140{ 141 /* don't use GET_CURRENT_CONTEXT(ctx) here - it's a problem on Windows */ 142 GLcontext *ctx = (GLcontext *) _glapi_get_context(); 143 (void) buffer; 144 if (ctx) { 145 OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 146 *width = osmesa->width; 147 *height = osmesa->height; 148 } 149} 150 151 152static void 153clear( GLcontext *ctx, GLbitfield mask, GLboolean all, 154 GLint x, GLint y, GLint width, GLint height ) 155{ 156 OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 157 const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask; 158 159 /* sanity check - we only have a front-left buffer */ 160 ASSERT((mask & (DD_FRONT_RIGHT_BIT | 161 DD_BACK_LEFT_BIT | 162 DD_BACK_RIGHT_BIT)) == 0); 163 164 /* use optimized clear for common cases (clear whole buffer to black) */ 165 if (mask & DD_FRONT_LEFT_BIT) { 166 if (osmesa->format == OSMESA_COLOR_INDEX) { 167 if (ctx->Color.ClearIndex == 0 && 168 ctx->Color.IndexMask == ~0 && 169 osmesa->rowlength == osmesa->width && 170 all) { 171 /* clear whole buffer to zeros */ 172 _mesa_bzero(osmesa->buffer, 173 osmesa->width * osmesa->height * sizeof(GLchan)); 174 mask &= ~DD_FRONT_LEFT_BIT; 175 } 176 } 177 else { 178 /* RGB[A] format */ 179 if (*colorMask == 0xffffffff && 180 ctx->Color.ClearColor[0] == 0.0F && 181 ctx->Color.ClearColor[1] == 0.0F && 182 ctx->Color.ClearColor[2] == 0.0F && 183 ctx->Color.ClearColor[3] == 0.0F && 184 osmesa->rowlength == osmesa->width && 185 all) { 186 GLint bytesPerPixel; 187 /* clear whole buffer to black */ 188 if (osmesa->format == OSMESA_RGBA || 189 osmesa->format == OSMESA_BGRA || 190 osmesa->format == OSMESA_ARGB) 191 bytesPerPixel = 4 * sizeof(GLchan); 192 else if (osmesa->format == OSMESA_RGB || 193 osmesa->format == OSMESA_BGR) 194 bytesPerPixel = 3 * sizeof(GLchan); 195 else if (osmesa->format == OSMESA_RGB_565) 196 bytesPerPixel = sizeof(GLushort); 197 else { 198 _mesa_problem(ctx, "bad pixel format in osmesa_clear()"); 199 return; 200 } 201 _mesa_bzero(osmesa->buffer, 202 bytesPerPixel * osmesa->width * osmesa->height); 203 mask &= ~DD_FRONT_LEFT_BIT; 204 } 205 } 206 } 207 208 if (mask) { 209 /* software fallback (spans) for everything else. */ 210 _swrast_Clear(ctx, mask, all, x, y, width, height); 211 } 212} 213 214 215/**********************************************************************/ 216/***** Read/write spans/arrays of pixels *****/ 217/**********************************************************************/ 218 219 220/* RGBA */ 221#define NAME(PREFIX) PREFIX##_RGBA 222#define SPAN_VARS \ 223 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 224#define INIT_PIXEL_PTR(P, X, Y) \ 225 GLchan *P = osmesa->rowaddr[Y] + 4 * (X) 226#define INC_PIXEL_PTR(P) P += 4 227#if CHAN_TYPE == GL_FLOAT 228#define STORE_RGB_PIXEL(P, R, G, B) \ 229 P[0] = MAX2((R), 0.0F); 230 P[1] = MAX2((G), 0.0F); 231 P[2] = MAX2((B), 0.0F); 232 P[3] = CHAN_MAXF 233#define STORE_RGBA_PIXEL(P, R, G, B, A) \ 234 P[0] = MAX2((R), 0.0F); 235 P[1] = MAX2((G), 0.0F); 236 P[2] = MAX2((B), 0.0F); 237 P[3] = CLAMP((A), 0.0F, CHAN_MAXF) 238#else 239#define STORE_RGB_PIXEL(P, R, G, B) \ 240 P[0] = R; P[1] = G; P[2] = B; P[3] = CHAN_MAX 241#define STORE_RGBA_PIXEL(P, R, G, B, A) \ 242 P[0] = R; P[1] = G; P[2] = B; P[3] = A 243#endif 244#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ 245 R = P[0]; G = P[1]; B = P[2]; A = P[3] 246#include "swrast/s_spantemp.h" 247 248/* BGRA */ 249#define NAME(PREFIX) PREFIX##_BGRA 250#define SPAN_VARS \ 251 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 252#define INIT_PIXEL_PTR(P, X, Y) \ 253 GLchan *P = osmesa->rowaddr[Y] + 4 * (X) 254#define INC_PIXEL_PTR(P) P += 4 255#define STORE_RGB_PIXEL(P, R, G, B) \ 256 P[2] = R; P[1] = G; P[0] = B; P[3] = CHAN_MAX 257#define STORE_RGBA_PIXEL(P, R, G, B, A) \ 258 P[2] = R; P[1] = G; P[0] = B; P[3] = A 259#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ 260 R = P[2]; G = P[1]; B = P[0]; A = P[3] 261#include "swrast/s_spantemp.h" 262 263/* ARGB */ 264#define NAME(PREFIX) PREFIX##_ARGB 265#define SPAN_VARS \ 266 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 267#define INIT_PIXEL_PTR(P, X, Y) \ 268 GLchan *P = osmesa->rowaddr[Y] + 4 * (X) 269#define INC_PIXEL_PTR(P) P += 4 270#define STORE_RGB_PIXEL(P, R, G, B) \ 271 P[1] = R; P[2] = G; P[3] = B; P[0] = CHAN_MAX 272#define STORE_RGBA_PIXEL(P, R, G, B, A) \ 273 P[1] = R; P[2] = G; P[3] = B; P[0] = A 274#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ 275 R = P[1]; G = P[2]; B = P[3]; A = P[0] 276#include "swrast/s_spantemp.h" 277 278/* RGB */ 279#define NAME(PREFIX) PREFIX##_RGB 280#define SPAN_VARS \ 281 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 282#define INIT_PIXEL_PTR(P, X, Y) \ 283 GLchan *P = osmesa->rowaddr[Y] + 4 * (X) 284#define INC_PIXEL_PTR(P) P += 4 285#define STORE_RGB_PIXEL(P, R, G, B) \ 286 P[0] = R; P[1] = G; P[2] = B 287#define STORE_RGBA_PIXEL(P, R, G, B, A) \ 288 P[0] = R; P[1] = G; P[2] = B 289#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ 290 R = P[0]; G = P[1]; B = P[2]; A = CHAN_MAX 291#include "swrast/s_spantemp.h" 292 293/* BGR */ 294#define NAME(PREFIX) PREFIX##_BGR 295#define SPAN_VARS \ 296 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 297#define INIT_PIXEL_PTR(P, X, Y) \ 298 GLchan *P = osmesa->rowaddr[Y] + 4 * (X) 299#define INC_PIXEL_PTR(P) P += 4 300#define STORE_RGB_PIXEL(P, R, G, B) \ 301 P[0] = B; P[1] = G; P[2] = R 302#define STORE_RGBA_PIXEL(P, R, G, B, A) \ 303 P[0] = B; P[1] = G; P[2] = R 304#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ 305 B = P[0]; G = P[1]; R = P[2]; A = CHAN_MAX 306#include "swrast/s_spantemp.h" 307 308/* 16-bit BGR */ 309#define NAME(PREFIX) PREFIX##_RGB_565 310#define SPAN_VARS \ 311 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 312#define INIT_PIXEL_PTR(P, X, Y) \ 313 GLushort *P = (GLushort *) osmesa->rowaddr[Y] + (X) 314#define INC_PIXEL_PTR(P) P += 1 315#define STORE_RGB_PIXEL(P, R, G, B) \ 316 *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) ) 317#define STORE_RGBA_PIXEL(P, R, G, B, A) \ 318 *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) ) 319#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ 320 R = ( (((*P) >> 8) & 0xf8) | (((*P) >> 11) & 0x7) ); \ 321 G = ( (((*P) >> 3) & 0xfc) | (((*P) >> 5) & 0x3) ); \ 322 B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \ 323 A = CHAN_MAX 324#include "swrast/s_spantemp.h" 325 326/* color index */ 327#define NAME(PREFIX) PREFIX##_CI 328#define SPAN_VARS \ 329 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 330#define INIT_PIXEL_PTR(P, X, Y) \ 331 GLchan *P = osmesa->rowaddr[Y] + (X) 332#define INC_PIXEL_PTR(P) P += 1 333#define STORE_CI_PIXEL(P, CI) \ 334 P[0] = CI 335#define FETCH_CI_PIXEL(CI, P) \ 336 CI = P[0] 337#include "swrast/s_spantemp.h" 338 339 340/**********************************************************************/ 341/***** Optimized line rendering *****/ 342/**********************************************************************/ 343 344 345#if CHAN_TYPE == GL_FLOAT 346#define PACK_RGBA(DST, R, G, B, A) \ 347do { \ 348 (DST)[0] = MAX2( R, 0.0F ); \ 349 (DST)[1] = MAX2( G, 0.0F ); \ 350 (DST)[2] = MAX2( B, 0.0F ); \ 351 (DST)[3] = CLAMP(A, 0.0F, CHAN_MAXF);\ 352} while (0) 353#else 354#define PACK_RGBA(DST, R, G, B, A) \ 355do { \ 356 (DST)[osmesa->rInd] = R; \ 357 (DST)[osmesa->gInd] = G; \ 358 (DST)[osmesa->bInd] = B; \ 359 (DST)[osmesa->aInd] = A; \ 360} while (0) 361#endif 362 363#define PACK_RGB(DST, R, G, B) \ 364do { \ 365 (DST)[0] = R; \ 366 (DST)[1] = G; \ 367 (DST)[2] = B; \ 368} while (0) 369 370#define PACK_BGR(DST, R, G, B) \ 371do { \ 372 (DST)[0] = B; \ 373 (DST)[1] = G; \ 374 (DST)[2] = R; \ 375} while (0) 376 377#define PACK_RGB_565(DST, R, G, B) \ 378do { \ 379 (DST) = (((int) (R) << 8) & 0xf800) | (((int) (G) << 3) & 0x7e0) | ((int) (B) >> 3);\ 380} while (0) 381 382#define UNPACK_RED(P) ( (P)[osmesa->rInd] ) 383#define UNPACK_GREEN(P) ( (P)[osmesa->gInd] ) 384#define UNPACK_BLUE(P) ( (P)[osmesa->bInd] ) 385#define UNPACK_ALPHA(P) ( (P)[osmesa->aInd] ) 386 387#define PIXELADDR1(X,Y) (osmesa->rowaddr[Y] + (X)) 388#define PIXELADDR2(X,Y) (osmesa->rowaddr[Y] + 2 * (X)) 389#define PIXELADDR3(X,Y) (osmesa->rowaddr[Y] + 3 * (X)) 390#define PIXELADDR4(X,Y) (osmesa->rowaddr[Y] + 4 * (X)) 391 392 393/* 394 * Draw a flat-shaded, RGB line into an osmesa buffer. 395 */ 396static void 397flat_rgba_line( GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1 ) 398{ 399 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 400 const GLchan *color = vert1->color; 401 402#define INTERP_XY 1 403#define CLIP_HACK 1 404#define PLOT(X, Y) \ 405do { \ 406 GLchan *p = PIXELADDR4(X, Y); \ 407 PACK_RGBA(p, color[0], color[1], color[2], color[3]); \ 408} while (0) 409 410#ifdef WIN32 411#include "..\swrast\s_linetemp.h" 412#else 413#include "swrast/s_linetemp.h" 414#endif 415} 416 417 418/* 419 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer. 420 */ 421static void 422flat_rgba_z_line(GLcontext *ctx, const SWvertex *vert0, const SWvertex *vert1) 423{ 424 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 425 const GLchan *color = vert1->color; 426 427#define INTERP_XY 1 428#define INTERP_Z 1 429#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 430#define CLIP_HACK 1 431#define PLOT(X, Y) \ 432do { \ 433 if (Z < *zPtr) { \ 434 GLchan *p = PIXELADDR4(X, Y); \ 435 PACK_RGBA(p, color[RCOMP], color[GCOMP], \ 436 color[BCOMP], color[ACOMP]); \ 437 *zPtr = Z; \ 438 } \ 439} while (0) 440 441 442#ifdef WIN32 443#include "..\swrast\s_linetemp.h" 444#else 445#include "swrast/s_linetemp.h" 446#endif 447} 448 449 450/* 451 * Draw a flat-shaded, alpha-blended, RGB line into an osmesa buffer. 452 * XXX update for GLchan 453 */ 454static void 455flat_blend_rgba_line( GLcontext *ctx, 456 const SWvertex *vert0, const SWvertex *vert1 ) 457{ 458 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 459 const GLint rshift = osmesa->rshift; 460 const GLint gshift = osmesa->gshift; 461 const GLint bshift = osmesa->bshift; 462 const GLint avalue = vert0->color[3]; 463 const GLint msavalue = CHAN_MAX - avalue; 464 const GLint rvalue = vert1->color[0]*avalue; 465 const GLint gvalue = vert1->color[1]*avalue; 466 const GLint bvalue = vert1->color[2]*avalue; 467 468#define INTERP_XY 1 469#define CLIP_HACK 1 470#define PLOT(X,Y) \ 471 { GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y); \ 472 GLuint pixel = 0; \ 473 pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift);\ 474 pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift);\ 475 pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift);\ 476 *ptr4 = pixel; \ 477 } 478 479#if 0 /* XXX use this in the future */ 480#define PLOT(X,Y) \ 481 { \ 482 GLchan *pixel = (GLchan *) PIXELADDR4(X, Y); \ 483 pixel[rInd] = (pixel[rInd] * msavalue + rvalue) >> CHAN_BITS; \ 484 pixel[gInd] = (pixel[gInd] * msavalue + gvalue) >> CHAN_BITS; \ 485 pixel[bInd] = (pixel[bInd] * msavalue + bvalue) >> CHAN_BITS; \ 486 pixel[aInd] = (pixel[aInd] * msavalue + avalue) >> CHAN_BITS; \ 487 } 488#endif 489 490#ifdef WIN32 491#include "..\swrast\s_linetemp.h" 492#else 493#include "swrast/s_linetemp.h" 494#endif 495} 496 497 498/* 499 * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer. 500 * But don't write to Z buffer. 501 * XXX update for GLchan 502 */ 503static void 504flat_blend_rgba_z_line( GLcontext *ctx, 505 const SWvertex *vert0, const SWvertex *vert1 ) 506{ 507 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 508 const GLint rshift = osmesa->rshift; 509 const GLint gshift = osmesa->gshift; 510 const GLint bshift = osmesa->bshift; 511 const GLint avalue = vert0->color[3]; 512 const GLint msavalue = 256 - avalue; 513 const GLint rvalue = vert1->color[0]*avalue; 514 const GLint gvalue = vert1->color[1]*avalue; 515 const GLint bvalue = vert1->color[2]*avalue; 516 517#define INTERP_XY 1 518#define INTERP_Z 1 519#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 520#define CLIP_HACK 1 521#define PLOT(X,Y) \ 522 if (Z < *zPtr) { \ 523 GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y); \ 524 GLuint pixel = 0; \ 525 pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift); \ 526 pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift); \ 527 pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift); \ 528 *ptr4 = pixel; \ 529 } 530 531#if 0 /* XXX use this in the future */ 532#define PLOT(X,Y) \ 533 if (Z < *zPtr) { \ 534 GLchan *pixel = (GLchan *) PIXELADDR4(X, Y); \ 535 pixel[rInd] = (pixel[rInd] * msavalue + rvalue) >> CHAN_BITS; \ 536 pixel[gInd] = (pixel[gInd] * msavalue + gvalue) >> CHAN_BITS; \ 537 pixel[bInd] = (pixel[bInd] * msavalue + bvalue) >> CHAN_BITS; \ 538 pixel[aInd] = (pixel[aInd] * msavalue + avalue) >> CHAN_BITS; \ 539 } 540#endif 541 542#ifdef WIN32 543#include "..\swrast\s_linetemp.h" 544#else 545#include "swrast/s_linetemp.h" 546#endif 547} 548 549 550/* 551 * Draw a flat-shaded, Z-less, alpha-blended, RGB line into an osmesa buffer. 552 * XXX update for GLchan 553 */ 554static void 555flat_blend_rgba_z_line_write( GLcontext *ctx, 556 const SWvertex *vert0, const SWvertex *vert1 ) 557{ 558 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 559 const GLint rshift = osmesa->rshift; 560 const GLint gshift = osmesa->gshift; 561 const GLint bshift = osmesa->bshift; 562 const GLint avalue = vert0->color[3]; 563 const GLint msavalue = 256 - avalue; 564 const GLint rvalue = vert1->color[0]*avalue; 565 const GLint gvalue = vert1->color[1]*avalue; 566 const GLint bvalue = vert1->color[2]*avalue; 567 568#define INTERP_XY 1 569#define INTERP_Z 1 570#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 571#define CLIP_HACK 1 572#define PLOT(X,Y) \ 573 if (Z < *zPtr) { \ 574 GLuint *ptr4 = (GLuint *) PIXELADDR4(X, Y); \ 575 GLuint pixel = 0; \ 576 pixel |=((((((*ptr4) >> rshift) & 0xff)*msavalue+rvalue)>>8) << rshift); \ 577 pixel |=((((((*ptr4) >> gshift) & 0xff)*msavalue+gvalue)>>8) << gshift); \ 578 pixel |=((((((*ptr4) >> bshift) & 0xff)*msavalue+bvalue)>>8) << bshift); \ 579 *ptr4 = pixel; \ 580 *zPtr = Z; \ 581 } 582 583#if 0 /* XXX use this in the future */ 584#define PLOT(X,Y) \ 585 if (Z < *zPtr) { \ 586 GLchan *pixel = (GLchan *) PIXELADDR4(X, Y); \ 587 pixel[rInd] = (pixel[rInd] * msavalue + rvalue) >> CHAN_BITS; \ 588 pixel[gInd] = (pixel[gInd] * msavalue + gvalue) >> CHAN_BITS; \ 589 pixel[bInd] = (pixel[bInd] * msavalue + bvalue) >> CHAN_BITS; \ 590 pixel[aInd] = (pixel[aInd] * msavalue + avalue) >> CHAN_BITS; \ 591 *zPtr = Z; \ 592 } 593#endif 594 595#ifdef WIN32 596#include "..\swrast\s_linetemp.h" 597#else 598#include "swrast/s_linetemp.h" 599#endif 600} 601 602 603/* 604 * Analyze context state to see if we can provide a fast line drawing 605 * function, like those in lines.c. Otherwise, return NULL. 606 */ 607static swrast_line_func 608osmesa_choose_line_function( GLcontext *ctx ) 609{ 610 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 611 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 612 613 if (CHAN_BITS != 8) return NULL; 614 if (ctx->RenderMode != GL_RENDER) return NULL; 615 if (ctx->Line.SmoothFlag) return NULL; 616 if (ctx->Texture._EnabledUnits) return NULL; 617 if (ctx->Light.ShadeModel != GL_FLAT) return NULL; 618 if (ctx->Line.Width != 1.0F) return NULL; 619 if (ctx->Line.StippleFlag) return NULL; 620 if (ctx->Line.SmoothFlag) return NULL; 621 if (osmesa->format != OSMESA_RGBA && 622 osmesa->format != OSMESA_BGRA && 623 osmesa->format != OSMESA_ARGB) return NULL; 624 625 if (swrast->_RasterMask==DEPTH_BIT 626 && ctx->Depth.Func==GL_LESS 627 && ctx->Depth.Mask==GL_TRUE 628 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) { 629 return (swrast_line_func) flat_rgba_z_line; 630 } 631 632 if (swrast->_RasterMask == 0) { 633 return (swrast_line_func) flat_rgba_line; 634 } 635 636 if (swrast->_RasterMask==(DEPTH_BIT|BLEND_BIT) 637 && ctx->Depth.Func==GL_LESS 638 && ctx->Depth.Mask==GL_TRUE 639 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS 640 && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA 641 && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA 642 && ctx->Color.BlendSrcA==GL_SRC_ALPHA 643 && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA 644 && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { 645 return (swrast_line_func) flat_blend_rgba_z_line_write; 646 } 647 648 if (swrast->_RasterMask==(DEPTH_BIT|BLEND_BIT) 649 && ctx->Depth.Func==GL_LESS 650 && ctx->Depth.Mask==GL_FALSE 651 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS 652 && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA 653 && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA 654 && ctx->Color.BlendSrcA==GL_SRC_ALPHA 655 && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA 656 && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { 657 return (swrast_line_func) flat_blend_rgba_z_line; 658 } 659 660 if (swrast->_RasterMask==BLEND_BIT 661 && ctx->Color.BlendSrcRGB==GL_SRC_ALPHA 662 && ctx->Color.BlendDstRGB==GL_ONE_MINUS_SRC_ALPHA 663 && ctx->Color.BlendSrcA==GL_SRC_ALPHA 664 && ctx->Color.BlendDstA==GL_ONE_MINUS_SRC_ALPHA 665 && ctx->Color.BlendEquation==GL_FUNC_ADD_EXT) { 666 return (swrast_line_func) flat_blend_rgba_line; 667 } 668 669 return (swrast_line_func) NULL; 670} 671 672 673/**********************************************************************/ 674/***** Optimized triangle rendering *****/ 675/**********************************************************************/ 676 677 678/* 679 * Smooth-shaded, z-less triangle, RGBA color. 680 */ 681#define NAME smooth_rgba_z_triangle 682#define INTERP_Z 1 683#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 684#define INTERP_RGB 1 685#define INTERP_ALPHA 1 686#define SETUP_CODE \ 687 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 688#define RENDER_SPAN( span ) \ 689 GLuint i; \ 690 GLchan *img = PIXELADDR4(span.x, span.y); \ 691 for (i = 0; i < span.end; i++, img += 4) { \ 692 const GLdepth z = FixedToDepth(span.z); \ 693 if (z < zRow[i]) { \ 694 PACK_RGBA(img, FixedToChan(span.red), \ 695 FixedToChan(span.green), FixedToChan(span.blue), \ 696 FixedToChan(span.alpha)); \ 697 zRow[i] = z; \ 698 } \ 699 span.red += span.redStep; \ 700 span.green += span.greenStep; \ 701 span.blue += span.blueStep; \ 702 span.alpha += span.alphaStep; \ 703 span.z += span.zStep; \ 704 } 705#ifdef WIN32 706#include "..\swrast\s_tritemp.h" 707#else 708#include "swrast/s_tritemp.h" 709#endif 710 711 712 713/* 714 * Flat-shaded, z-less triangle, RGBA color. 715 */ 716#define NAME flat_rgba_z_triangle 717#define INTERP_Z 1 718#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 719#define SETUP_CODE \ 720 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \ 721 GLuint pixel; \ 722 PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1], \ 723 v2->color[2], v2->color[3]); 724 725#define RENDER_SPAN( span ) \ 726 GLuint i; \ 727 GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y); \ 728 for (i = 0; i < span.end; i++) { \ 729 const GLdepth z = FixedToDepth(span.z); \ 730 if (z < zRow[i]) { \ 731 img[i] = pixel; \ 732 zRow[i] = z; \ 733 } \ 734 span.z += span.zStep; \ 735 } 736#ifdef WIN32 737#include "..\swrast\s_tritemp.h" 738#else 739#include "swrast/s_tritemp.h" 740#endif 741 742 743 744/* 745 * Return pointer to an accelerated triangle function if possible. 746 */ 747static swrast_tri_func 748osmesa_choose_triangle_function( GLcontext *ctx ) 749{ 750 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 751 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 752 753 if (CHAN_BITS != 8) return (swrast_tri_func) NULL; 754 if (ctx->RenderMode != GL_RENDER) return (swrast_tri_func) NULL; 755 if (ctx->Polygon.SmoothFlag) return (swrast_tri_func) NULL; 756 if (ctx->Polygon.StippleFlag) return (swrast_tri_func) NULL; 757 if (ctx->Texture._EnabledUnits) return (swrast_tri_func) NULL; 758 if (osmesa->format != OSMESA_RGBA && 759 osmesa->format != OSMESA_BGRA && 760 osmesa->format != OSMESA_ARGB) return (swrast_tri_func) NULL; 761 if (ctx->Polygon.CullFlag && 762 ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) 763 return (swrast_tri_func) NULL; 764 765 if (swrast->_RasterMask == DEPTH_BIT && 766 ctx->Depth.Func == GL_LESS && 767 ctx->Depth.Mask == GL_TRUE && 768 ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) { 769 if (ctx->Light.ShadeModel == GL_SMOOTH) { 770 return (swrast_tri_func) smooth_rgba_z_triangle; 771 } 772 else { 773 return (swrast_tri_func) flat_rgba_z_triangle; 774 } 775 } 776 return (swrast_tri_func) NULL; 777} 778 779 780 781/* Override for the swrast triangle-selection function. Try to use one 782 * of our internal triangle functions, otherwise fall back to the 783 * standard swrast functions. 784 */ 785static void 786osmesa_choose_triangle( GLcontext *ctx ) 787{ 788 SWcontext *swrast = SWRAST_CONTEXT(ctx); 789 790 swrast->Triangle = osmesa_choose_triangle_function( ctx ); 791 if (!swrast->Triangle) 792 _swrast_choose_triangle( ctx ); 793} 794 795static void 796osmesa_choose_line( GLcontext *ctx ) 797{ 798 SWcontext *swrast = SWRAST_CONTEXT(ctx); 799 800 swrast->Line = osmesa_choose_line_function( ctx ); 801 if (!swrast->Line) 802 _swrast_choose_line( ctx ); 803} 804 805 806#define OSMESA_NEW_LINE (_NEW_LINE | \ 807 _NEW_TEXTURE | \ 808 _NEW_LIGHT | \ 809 _NEW_DEPTH | \ 810 _NEW_RENDERMODE | \ 811 _SWRAST_NEW_RASTERMASK) 812 813#define OSMESA_NEW_TRIANGLE (_NEW_POLYGON | \ 814 _NEW_TEXTURE | \ 815 _NEW_LIGHT | \ 816 _NEW_DEPTH | \ 817 _NEW_RENDERMODE | \ 818 _SWRAST_NEW_RASTERMASK) 819 820/* one-time, per-context initialization */ 821static void 822hook_in_driver_functions( GLcontext *ctx ) 823{ 824 OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 825 SWcontext *swrast = SWRAST_CONTEXT( ctx ); 826 struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx ); 827 TNLcontext *tnl = TNL_CONTEXT(ctx); 828 829 ASSERT((void *) osmesa == (void *) ctx->DriverCtx); 830 831 /* use default TCL pipeline */ 832 tnl->Driver.RunPipeline = _tnl_run_pipeline; 833 834 ctx->Driver.GetString = get_string; 835 ctx->Driver.UpdateState = osmesa_update_state; 836 ctx->Driver.ResizeBuffers = _swrast_alloc_buffers; 837 ctx->Driver.GetBufferSize = get_buffer_size; 838 839 ctx->Driver.Accum = _swrast_Accum; 840 ctx->Driver.Bitmap = _swrast_Bitmap; 841 ctx->Driver.Clear = clear; /* = _swrast_Clear */ 842 ctx->Driver.CopyPixels = _swrast_CopyPixels; 843 ctx->Driver.DrawPixels = _swrast_DrawPixels; 844 ctx->Driver.ReadPixels = _swrast_ReadPixels; 845 ctx->Driver.DrawBuffer = _swrast_DrawBuffer; 846 847 ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format; 848 ctx->Driver.TexImage1D = _mesa_store_teximage1d; 849 ctx->Driver.TexImage2D = _mesa_store_teximage2d; 850 ctx->Driver.TexImage3D = _mesa_store_teximage3d; 851 ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d; 852 ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d; 853 ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; 854 ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; 855 856 ctx->Driver.CompressedTexImage1D = _mesa_store_compressed_teximage1d; 857 ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d; 858 ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d; 859 ctx->Driver.CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d; 860 ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d; 861 ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d; 862 863 ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d; 864 ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; 865 ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d; 866 ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d; 867 ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; 868 ctx->Driver.CopyColorTable = _swrast_CopyColorTable; 869 ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; 870 ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; 871 ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; 872 873 swdd->SetBuffer = set_buffer; 874 875 /* RGB(A) span/pixel functions */ 876 if (osmesa->format == OSMESA_RGB) { 877 swdd->WriteRGBASpan = write_rgba_span_RGB; 878 swdd->WriteRGBSpan = write_rgb_span_RGB; 879 swdd->WriteMonoRGBASpan = write_monorgba_span_RGB; 880 swdd->WriteRGBAPixels = write_rgba_pixels_RGB; 881 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB; 882 swdd->ReadRGBASpan = read_rgba_span_RGB; 883 swdd->ReadRGBAPixels = read_rgba_pixels_RGB; 884 } 885 else if (osmesa->format == OSMESA_BGR) { 886 swdd->WriteRGBASpan = write_rgba_span_BGR; 887 swdd->WriteRGBSpan = write_rgb_span_BGR; 888 swdd->WriteMonoRGBASpan = write_monorgba_span_BGR; 889 swdd->WriteRGBAPixels = write_rgba_pixels_BGR; 890 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGR; 891 swdd->ReadRGBASpan = read_rgba_span_BGR; 892 swdd->ReadRGBAPixels = read_rgba_pixels_BGR; 893 } 894 else if (osmesa->format == OSMESA_RGB_565) { 895 swdd->WriteRGBASpan = write_rgba_span_RGB_565; 896 swdd->WriteRGBSpan = write_rgb_span_RGB_565; 897 swdd->WriteMonoRGBASpan = write_monorgba_span_RGB_565; 898 swdd->WriteRGBAPixels = write_rgba_pixels_RGB_565; 899 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB_565; 900 swdd->ReadRGBASpan = read_rgba_span_RGB_565; 901 swdd->ReadRGBAPixels = read_rgba_pixels_RGB_565; 902 } 903 else if (osmesa->format == OSMESA_RGBA) { 904 swdd->WriteRGBASpan = write_rgba_span_RGBA; 905 swdd->WriteRGBSpan = write_rgb_span_RGBA; 906 swdd->WriteMonoRGBASpan = write_monorgba_span_RGBA; 907 swdd->WriteRGBAPixels = write_rgba_pixels_RGBA; 908 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGBA; 909 swdd->ReadRGBASpan = read_rgba_span_RGBA; 910 swdd->ReadRGBAPixels = read_rgba_pixels_RGBA; 911 } 912 else if (osmesa->format == OSMESA_BGRA) { 913 swdd->WriteRGBASpan = write_rgba_span_BGRA; 914 swdd->WriteRGBSpan = write_rgb_span_BGRA; 915 swdd->WriteMonoRGBASpan = write_monorgba_span_BGRA; 916 swdd->WriteRGBAPixels = write_rgba_pixels_BGRA; 917 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGRA; 918 swdd->ReadRGBASpan = read_rgba_span_BGRA; 919 swdd->ReadRGBAPixels = read_rgba_pixels_BGRA; 920 } 921 else if (osmesa->format == OSMESA_ARGB) { 922 swdd->WriteRGBASpan = write_rgba_span_ARGB; 923 swdd->WriteRGBSpan = write_rgb_span_ARGB; 924 swdd->WriteMonoRGBASpan = write_monorgba_span_ARGB; 925 swdd->WriteRGBAPixels = write_rgba_pixels_ARGB; 926 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_ARGB; 927 swdd->ReadRGBASpan = read_rgba_span_ARGB; 928 swdd->ReadRGBAPixels = read_rgba_pixels_ARGB; 929 } 930 else if (osmesa->format == OSMESA_COLOR_INDEX) { 931 swdd->WriteCI32Span = write_index32_span_CI; 932 swdd->WriteCI8Span = write_index8_span_CI; 933 swdd->WriteMonoCISpan = write_monoindex_span_CI; 934 swdd->WriteCI32Pixels = write_index_pixels_CI; 935 swdd->WriteMonoCIPixels = write_monoindex_pixels_CI; 936 swdd->ReadCI32Span = read_index_span_CI; 937 swdd->ReadCI32Pixels = read_index_pixels_CI; 938 } 939 else { 940 _mesa_problem(ctx, "bad pixel format in osmesa_update_state!\n"); 941 } 942 943 /* Extend the software rasterizer with our optimized line and triangle 944 * drawin functions. 945 */ 946 swrast->choose_line = osmesa_choose_line; 947 swrast->choose_triangle = osmesa_choose_triangle; 948 swrast->invalidate_line |= OSMESA_NEW_LINE; 949 swrast->invalidate_triangle |= OSMESA_NEW_TRIANGLE; 950} 951 952 953 954 955/**********************************************************************/ 956/***** Public Functions *****/ 957/**********************************************************************/ 958 959 960/* 961 * Create an Off-Screen Mesa rendering context. The only attribute needed is 962 * an RGBA vs Color-Index mode flag. 963 * 964 * Input: format - either GL_RGBA or GL_COLOR_INDEX 965 * sharelist - specifies another OSMesaContext with which to share 966 * display lists. NULL indicates no sharing. 967 * Return: an OSMesaContext or 0 if error 968 */ 969GLAPI OSMesaContext GLAPIENTRY 970OSMesaCreateContext( GLenum format, OSMesaContext sharelist ) 971{ 972 return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS, 973 8, 16, sharelist); 974} 975 976 977 978/* 979 * New in Mesa 3.5 980 * 981 * Create context and specify size of ancillary buffers. 982 */ 983GLAPI OSMesaContext GLAPIENTRY 984OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, 985 GLint accumBits, OSMesaContext sharelist ) 986{ 987 OSMesaContext osmesa; 988 GLint rshift, gshift, bshift, ashift; 989 GLint rind, gind, bind, aind; 990 GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0; 991 GLboolean rgbmode; 992 const GLuint i4 = 1; 993 const GLubyte *i1 = (GLubyte *) &i4; 994 const GLint little_endian = *i1; 995 996 rind = gind = bind = aind = 0; 997 if (format==OSMESA_COLOR_INDEX) { 998 indexBits = 8; 999 rshift = gshift = bshift = ashift = 0; 1000 rgbmode = GL_FALSE; 1001 } 1002 else if (format==OSMESA_RGBA) { 1003 indexBits = 0; 1004 redBits = CHAN_BITS; 1005 greenBits = CHAN_BITS; 1006 blueBits = CHAN_BITS; 1007 alphaBits = CHAN_BITS; 1008 rind = 0; 1009 gind = 1; 1010 bind = 2; 1011 aind = 3; 1012 if (little_endian) { 1013 rshift = 0; 1014 gshift = 8; 1015 bshift = 16; 1016 ashift = 24; 1017 } 1018 else { 1019 rshift = 24; 1020 gshift = 16; 1021 bshift = 8; 1022 ashift = 0; 1023 } 1024 rgbmode = GL_TRUE; 1025 } 1026 else if (format==OSMESA_BGRA) { 1027 indexBits = 0; 1028 redBits = CHAN_BITS; 1029 greenBits = CHAN_BITS; 1030 blueBits = CHAN_BITS; 1031 alphaBits = CHAN_BITS; 1032 bind = 0; 1033 gind = 1; 1034 rind = 2; 1035 aind = 3; 1036 if (little_endian) { 1037 bshift = 0; 1038 gshift = 8; 1039 rshift = 16; 1040 ashift = 24; 1041 } 1042 else { 1043 bshift = 24; 1044 gshift = 16; 1045 rshift = 8; 1046 ashift = 0; 1047 } 1048 rgbmode = GL_TRUE; 1049 } 1050 else if (format==OSMESA_ARGB) { 1051 indexBits = 0; 1052 redBits = CHAN_BITS; 1053 greenBits = CHAN_BITS; 1054 blueBits = CHAN_BITS; 1055 alphaBits = CHAN_BITS; 1056 aind = 0; 1057 rind = 1; 1058 gind = 2; 1059 bind = 3; 1060 if (little_endian) { 1061 ashift = 0; 1062 rshift = 8; 1063 gshift = 16; 1064 bshift = 24; 1065 } 1066 else { 1067 ashift = 24; 1068 rshift = 16; 1069 gshift = 8; 1070 bshift = 0; 1071 } 1072 rgbmode = GL_TRUE; 1073 } 1074 else if (format==OSMESA_RGB) { 1075 indexBits = 0; 1076 redBits = CHAN_BITS; 1077 greenBits = CHAN_BITS; 1078 blueBits = CHAN_BITS; 1079 alphaBits = 0; 1080 bshift = 0; 1081 gshift = 8; 1082 rshift = 16; 1083 ashift = 24; 1084 rind = 0; 1085 gind = 1; 1086 bind = 2; 1087 rgbmode = GL_TRUE; 1088 } 1089 else if (format==OSMESA_BGR) { 1090 indexBits = 0; 1091 redBits = CHAN_BITS; 1092 greenBits = CHAN_BITS; 1093 blueBits = CHAN_BITS; 1094 alphaBits = 0; 1095 bshift = 0; 1096 gshift = 8; 1097 rshift = 16; 1098 ashift = 24; 1099 rind = 2; 1100 gind = 1; 1101 bind = 0; 1102 rgbmode = GL_TRUE; 1103 } 1104 else if (format==OSMESA_RGB_565) { 1105 indexBits = 0; 1106 redBits = 5; 1107 greenBits = 6; 1108 blueBits = 5; 1109 alphaBits = 0; 1110 rshift = 11; 1111 gshift = 5; 1112 bshift = 0; 1113 ashift = 0; 1114 rind = 0; /* not used */ 1115 gind = 0; 1116 bind = 0; 1117 rgbmode = GL_TRUE; 1118 } 1119 else { 1120 return NULL; 1121 } 1122 1123 1124 osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context); 1125 if (osmesa) { 1126 osmesa->gl_visual = _mesa_create_visual( rgbmode, 1127 GL_FALSE, /* double buffer */ 1128 GL_FALSE, /* stereo */ 1129 redBits, 1130 greenBits, 1131 blueBits, 1132 alphaBits, 1133 indexBits, 1134 depthBits, 1135 stencilBits, 1136 accumBits, 1137 accumBits, 1138 accumBits, 1139 alphaBits ? accumBits : 0, 1140 1 /* num samples */ 1141 ); 1142 if (!osmesa->gl_visual) { 1143 FREE(osmesa); 1144 return NULL; 1145 } 1146 1147 if (!_mesa_initialize_context(&osmesa->gl_ctx, 1148 osmesa->gl_visual, 1149 sharelist ? &sharelist->gl_ctx 1150 : (GLcontext *) NULL, 1151 (void *) osmesa, 1152 GL_FALSE)) { 1153 _mesa_destroy_visual( osmesa->gl_visual ); 1154 FREE(osmesa); 1155 return NULL; 1156 } 1157 1158 _mesa_enable_sw_extensions(&(osmesa->gl_ctx)); 1159 _mesa_enable_1_3_extensions(&(osmesa->gl_ctx)); 1160 /*_mesa_enable_1_4_extensions(&(osmesa->gl_ctx));*/ 1161 1162 osmesa->gl_buffer = _mesa_create_framebuffer( osmesa->gl_visual, 1163 (GLboolean) ( osmesa->gl_visual->depthBits > 0 ), 1164 (GLboolean) ( osmesa->gl_visual->stencilBits > 0 ), 1165 (GLboolean) ( osmesa->gl_visual->accumRedBits > 0 ), 1166 GL_FALSE /* s/w alpha */ ); 1167 1168 if (!osmesa->gl_buffer) { 1169 _mesa_destroy_visual( osmesa->gl_visual ); 1170 _mesa_free_context_data( &osmesa->gl_ctx ); 1171 FREE(osmesa); 1172 return NULL; 1173 } 1174 osmesa->format = format; 1175 osmesa->buffer = NULL; 1176 osmesa->width = 0; 1177 osmesa->height = 0; 1178 osmesa->userRowLength = 0; 1179 osmesa->rowlength = 0; 1180 osmesa->yup = GL_TRUE; 1181 osmesa->rshift = rshift; 1182 osmesa->gshift = gshift; 1183 osmesa->bshift = bshift; 1184 osmesa->ashift = ashift; 1185 osmesa->rInd = rind; 1186 osmesa->gInd = gind; 1187 osmesa->bInd = bind; 1188 osmesa->aInd = aind; 1189 1190 /* Initialize the software rasterizer and helper modules. */ 1191 { 1192 GLcontext *ctx = &osmesa->gl_ctx; 1193 1194 _swrast_CreateContext( ctx ); 1195 _ac_CreateContext( ctx ); 1196 _tnl_CreateContext( ctx ); 1197 _swsetup_CreateContext( ctx ); 1198 1199 _swsetup_Wakeup( ctx ); 1200 hook_in_driver_functions( ctx ); 1201 } 1202 } 1203 return osmesa; 1204} 1205 1206 1207/* 1208 * Destroy an Off-Screen Mesa rendering context. 1209 * 1210 * Input: ctx - the context to destroy 1211 */ 1212GLAPI void GLAPIENTRY 1213OSMesaDestroyContext( OSMesaContext ctx ) 1214{ 1215 if (ctx) { 1216 _swsetup_DestroyContext( &ctx->gl_ctx ); 1217 _tnl_DestroyContext( &ctx->gl_ctx ); 1218 _ac_DestroyContext( &ctx->gl_ctx ); 1219 _swrast_DestroyContext( &ctx->gl_ctx ); 1220 1221 _mesa_destroy_visual( ctx->gl_visual ); 1222 _mesa_destroy_framebuffer( ctx->gl_buffer ); 1223 _mesa_free_context_data( &ctx->gl_ctx ); 1224 FREE( ctx ); 1225 } 1226} 1227 1228 1229/* 1230 * Recompute the values of the context's rowaddr array. 1231 */ 1232static void 1233compute_row_addresses( OSMesaContext ctx ) 1234{ 1235 GLint bytesPerPixel, bytesPerRow, i; 1236 GLubyte *origin = (GLubyte *) ctx->buffer; 1237 1238 if (ctx->format == OSMESA_COLOR_INDEX) { 1239 /* CI mode */ 1240 bytesPerPixel = 1 * sizeof(GLchan); 1241 } 1242 else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) { 1243 /* RGB mode */ 1244 bytesPerPixel = 3 * sizeof(GLchan); 1245 } 1246 else if (ctx->format == OSMESA_RGB_565) { 1247 /* 5/6/5 RGB pixel in 16 bits */ 1248 bytesPerPixel = 2; 1249 } 1250 else { 1251 /* RGBA mode */ 1252 bytesPerPixel = 4 * sizeof(GLchan); 1253 } 1254 1255 bytesPerRow = ctx->rowlength * bytesPerPixel; 1256 1257 if (ctx->yup) { 1258 /* Y=0 is bottom line of window */ 1259 for (i = 0; i < MAX_HEIGHT; i++) { 1260 ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow); 1261 } 1262 } 1263 else { 1264 /* Y=0 is top line of window */ 1265 for (i = 0; i < MAX_HEIGHT; i++) { 1266 GLint j = ctx->height - i - 1; 1267 ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow); 1268 } 1269 } 1270} 1271 1272 1273/* 1274 * Bind an OSMesaContext to an image buffer. The image buffer is just a 1275 * block of memory which the client provides. Its size must be at least 1276 * as large as width*height*sizeof(type). Its address should be a multiple 1277 * of 4 if using RGBA mode. 1278 * 1279 * Image data is stored in the order of glDrawPixels: row-major order 1280 * with the lower-left image pixel stored in the first array position 1281 * (ie. bottom-to-top). 1282 * 1283 * If the context's viewport hasn't been initialized yet, it will now be 1284 * initialized to (0,0,width,height). 1285 * 1286 * Input: ctx - the rendering context 1287 * buffer - the image buffer memory 1288 * type - data type for pixel components 1289 * Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5 1290 * are supported. But if Mesa's been compiled with CHAN_BITS==16 1291 * then type must be GL_UNSIGNED_SHORT. And if Mesa's been build 1292 * with CHAN_BITS==32 then type must be GL_FLOAT. 1293 * width, height - size of image buffer in pixels, at least 1 1294 * Return: GL_TRUE if success, GL_FALSE if error because of invalid ctx, 1295 * invalid buffer address, invalid type, width<1, height<1, 1296 * width>internal limit or height>internal limit. 1297 */ 1298GLAPI GLboolean GLAPIENTRY 1299OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type, 1300 GLsizei width, GLsizei height ) 1301{ 1302 if (!ctx || !buffer || 1303 width < 1 || height < 1 || 1304 width > MAX_WIDTH || height > MAX_HEIGHT) { 1305 return GL_FALSE; 1306 } 1307 1308 if (ctx->format == OSMESA_RGB_565) { 1309 if (type != GL_UNSIGNED_SHORT_5_6_5) 1310 return GL_FALSE; 1311 } 1312 else if (type != CHAN_TYPE) { 1313 return GL_FALSE; 1314 } 1315 1316 osmesa_update_state( &ctx->gl_ctx, 0 ); 1317 _mesa_make_current( &ctx->gl_ctx, ctx->gl_buffer ); 1318 1319 ctx->buffer = buffer; 1320 ctx->width = width; 1321 ctx->height = height; 1322 if (ctx->userRowLength) 1323 ctx->rowlength = ctx->userRowLength; 1324 else 1325 ctx->rowlength = width; 1326 1327 compute_row_addresses( ctx ); 1328 1329 /* init viewport */ 1330 if (ctx->gl_ctx.Viewport.Width == 0) { 1331 /* initialize viewport and scissor box to buffer size */ 1332 _mesa_Viewport( 0, 0, width, height ); 1333 ctx->gl_ctx.Scissor.Width = width; 1334 ctx->gl_ctx.Scissor.Height = height; 1335 } 1336 else { 1337 /* this will make ensure we recognize the new buffer size */ 1338 _mesa_ResizeBuffersMESA(); 1339 } 1340 1341 /* Added by Gerk Huisma: */ 1342 _tnl_MakeCurrent( &ctx->gl_ctx, ctx->gl_ctx.DrawBuffer, 1343 ctx->gl_ctx.ReadBuffer ); 1344 1345 return GL_TRUE; 1346} 1347 1348 1349 1350GLAPI OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void ) 1351{ 1352 GLcontext *ctx = _mesa_get_current_context(); 1353 if (ctx) 1354 return (OSMesaContext) ctx; 1355 else 1356 return NULL; 1357} 1358 1359 1360 1361GLAPI void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value ) 1362{ 1363 OSMesaContext osmesa = OSMesaGetCurrentContext(); 1364 1365 switch (pname) { 1366 case OSMESA_ROW_LENGTH: 1367 if (value<0) { 1368 _mesa_error( &osmesa->gl_ctx, GL_INVALID_VALUE, 1369 "OSMesaPixelStore(value)" ); 1370 return; 1371 } 1372 osmesa->userRowLength = value; 1373 osmesa->rowlength = value ? value : osmesa->width; 1374 break; 1375 case OSMESA_Y_UP: 1376 osmesa->yup = value ? GL_TRUE : GL_FALSE; 1377 break; 1378 default: 1379 _mesa_error( &osmesa->gl_ctx, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" ); 1380 return; 1381 } 1382 1383 compute_row_addresses( osmesa ); 1384} 1385 1386 1387GLAPI void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value ) 1388{ 1389 OSMesaContext osmesa = OSMesaGetCurrentContext(); 1390 1391 switch (pname) { 1392 case OSMESA_WIDTH: 1393 *value = osmesa->width; 1394 return; 1395 case OSMESA_HEIGHT: 1396 *value = osmesa->height; 1397 return; 1398 case OSMESA_FORMAT: 1399 *value = osmesa->format; 1400 return; 1401 case OSMESA_TYPE: 1402 *value = CHAN_TYPE; 1403 return; 1404 case OSMESA_ROW_LENGTH: 1405 *value = osmesa->userRowLength; 1406 return; 1407 case OSMESA_Y_UP: 1408 *value = osmesa->yup; 1409 return; 1410 case OSMESA_MAX_WIDTH: 1411 *value = MAX_WIDTH; 1412 return; 1413 case OSMESA_MAX_HEIGHT: 1414 *value = MAX_HEIGHT; 1415 return; 1416 default: 1417 _mesa_error(&osmesa->gl_ctx, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)"); 1418 return; 1419 } 1420} 1421 1422/* 1423 * Return the depth buffer associated with an OSMesa context. 1424 * Input: c - the OSMesa context 1425 * Output: width, height - size of buffer in pixels 1426 * bytesPerValue - bytes per depth value (2 or 4) 1427 * buffer - pointer to depth buffer values 1428 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 1429 */ 1430GLAPI GLboolean GLAPIENTRY 1431OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height, 1432 GLint *bytesPerValue, void **buffer ) 1433{ 1434 if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) { 1435 *width = 0; 1436 *height = 0; 1437 *bytesPerValue = 0; 1438 *buffer = 0; 1439 return GL_FALSE; 1440 } 1441 else { 1442 *width = c->gl_buffer->Width; 1443 *height = c->gl_buffer->Height; 1444 if (c->gl_visual->depthBits <= 16) 1445 *bytesPerValue = sizeof(GLushort); 1446 else 1447 *bytesPerValue = sizeof(GLuint); 1448 *buffer = c->gl_buffer->DepthBuffer; 1449 return GL_TRUE; 1450 } 1451} 1452 1453/* 1454 * Return the color buffer associated with an OSMesa context. 1455 * Input: c - the OSMesa context 1456 * Output: width, height - size of buffer in pixels 1457 * format - the pixel format (OSMESA_FORMAT) 1458 * buffer - pointer to color buffer values 1459 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 1460 */ 1461GLAPI GLboolean GLAPIENTRY 1462OSMesaGetColorBuffer( OSMesaContext c, GLint *width, 1463 GLint *height, GLint *format, void **buffer ) 1464{ 1465 if (!c->buffer) { 1466 *width = 0; 1467 *height = 0; 1468 *format = 0; 1469 *buffer = 0; 1470 return GL_FALSE; 1471 } 1472 else { 1473 *width = c->width; 1474 *height = c->height; 1475 *format = c->format; 1476 *buffer = c->buffer; 1477 return GL_TRUE; 1478 } 1479} 1480 1481 1482 1483struct name_address { 1484 const char *Name; 1485 GLvoid *Address; 1486}; 1487 1488static struct name_address functions[] = { 1489 { "OSMesaCreateContext", (void *) OSMesaCreateContext }, 1490 { "OSMesaCreateContextExt", (void *) OSMesaCreateContextExt }, 1491 { "OSMesaDestroyContext", (void *) OSMesaDestroyContext }, 1492 { "OSMesaMakeCurrent", (void *) OSMesaMakeCurrent }, 1493 { "OSMesaGetCurrentContext", (void *) OSMesaGetCurrentContext }, 1494 { "OSMesaPixelsStore", (void *) OSMesaPixelStore }, 1495 { "OSMesaGetIntegerv", (void *) OSMesaGetIntegerv }, 1496 { "OSMesaGetDepthBuffer", (void *) OSMesaGetDepthBuffer }, 1497 { "OSMesaGetColorBuffer", (void *) OSMesaGetColorBuffer }, 1498 { "OSMesaGetProcAddress", (void *) OSMesaGetProcAddress }, 1499 { NULL, NULL } 1500}; 1501 1502GLAPI void * GLAPIENTRY 1503OSMesaGetProcAddress( const char *funcName ) 1504{ 1505 int i; 1506 for (i = 0; functions[i].Name; i++) { 1507 if (_mesa_strcmp(functions[i].Name, funcName) == 0) 1508 return (void *) functions[i].Address; 1509 } 1510 return (void *) _glapi_get_proc_address(funcName); 1511} 1512