osmesa.c revision 84351999ec6ad07e0cfc31c0b3a8c86da4134bfe
1/* 2 * Mesa 3-D graphics library 3 * Version: 5.1 4 * 5 * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 26/* 27 * Off-Screen Mesa rendering / Rendering into client memory space 28 * 29 * Note on thread safety: this driver is thread safe. All 30 * functions are reentrant. The notion of current context is 31 * managed by the core _mesa_make_current() and _mesa_get_current_context() 32 * functions. Those functions are thread-safe. 33 */ 34 35 36#include "glheader.h" 37#include "GL/osmesa.h" 38#include "buffers.h" 39#include "context.h" 40#include "colormac.h" 41#include "depth.h" 42#include "extensions.h" 43#include "imports.h" 44#include "macros.h" 45#include "matrix.h" 46#include "mtypes.h" 47#include "texformat.h" 48#include "texobj.h" 49#include "teximage.h" 50#include "texstore.h" 51#include "array_cache/acache.h" 52#include "swrast/swrast.h" 53#include "swrast_setup/swrast_setup.h" 54#include "swrast/s_context.h" 55#include "swrast/s_depth.h" 56#include "swrast/s_lines.h" 57#include "swrast/s_triangle.h" 58#include "tnl/tnl.h" 59#include "tnl/t_context.h" 60#include "tnl/t_pipeline.h" 61 62 63 64/* 65 * This is the OS/Mesa context struct. 66 * Notice how it includes a GLcontext. By doing this we're mimicking 67 * C++ inheritance/derivation. 68 * Later, we can cast a GLcontext pointer into an OSMesaContext pointer 69 * or vice versa. 70 */ 71struct osmesa_context { 72 GLcontext mesa; /* The core GL/Mesa context */ 73 GLvisual *gl_visual; /* Describes the buffers */ 74 GLframebuffer *gl_buffer; /* Depth, stencil, accum, etc buffers */ 75 GLenum format; /* either GL_RGBA or GL_COLOR_INDEX */ 76 void *buffer; /* the image buffer */ 77 GLint width, height; /* size of image buffer */ 78 GLint rowlength; /* number of pixels per row */ 79 GLint userRowLength; /* user-specified number of pixels per row */ 80 GLint rshift, gshift; /* bit shifts for RGBA formats */ 81 GLint bshift, ashift; 82 GLint rInd, gInd, bInd, aInd;/* index offsets for RGBA formats */ 83 GLchan *rowaddr[MAX_HEIGHT]; /* address of first pixel in each image row */ 84 GLboolean yup; /* TRUE -> Y increases upward */ 85 /* FALSE -> Y increases downward */ 86}; 87 88 89/* Just cast, since we're using structure containment */ 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 == (GLuint) ~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#if CHAN_TYPE == GL_UNSIGNED_BYTE 310#define NAME(PREFIX) PREFIX##_RGB_565 311#define SPAN_VARS \ 312 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 313#define INIT_PIXEL_PTR(P, X, Y) \ 314 GLushort *P = (GLushort *) osmesa->rowaddr[Y] + (X) 315#define INC_PIXEL_PTR(P) P += 1 316#define STORE_RGB_PIXEL(P, R, G, B) \ 317 *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) ) 318#define STORE_RGBA_PIXEL(P, R, G, B, A) \ 319 *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) ) 320#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ 321 R = ( (((*P) >> 8) & 0xf8) | (((*P) >> 11) & 0x7) ); \ 322 G = ( (((*P) >> 3) & 0xfc) | (((*P) >> 5) & 0x3) ); \ 323 B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \ 324 A = CHAN_MAX 325#include "swrast/s_spantemp.h" 326#endif 327 328/* color index */ 329#define NAME(PREFIX) PREFIX##_CI 330#define SPAN_VARS \ 331 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 332#define INIT_PIXEL_PTR(P, X, Y) \ 333 GLchan *P = osmesa->rowaddr[Y] + (X) 334#define INC_PIXEL_PTR(P) P += 1 335#define STORE_CI_PIXEL(P, CI) \ 336 P[0] = CI 337#define FETCH_CI_PIXEL(CI, P) \ 338 CI = P[0] 339#include "swrast/s_spantemp.h" 340 341 342/**********************************************************************/ 343/***** Optimized line rendering *****/ 344/**********************************************************************/ 345 346 347#if CHAN_TYPE == GL_FLOAT 348#define PACK_RGBA(DST, R, G, B, A) \ 349do { \ 350 (DST)[0] = MAX2( R, 0.0F ); \ 351 (DST)[1] = MAX2( G, 0.0F ); \ 352 (DST)[2] = MAX2( B, 0.0F ); \ 353 (DST)[3] = CLAMP(A, 0.0F, CHAN_MAXF);\ 354} while (0) 355#else 356#define PACK_RGBA(DST, R, G, B, A) \ 357do { \ 358 (DST)[osmesa->rInd] = R; \ 359 (DST)[osmesa->gInd] = G; \ 360 (DST)[osmesa->bInd] = B; \ 361 (DST)[osmesa->aInd] = A; \ 362} while (0) 363#endif 364 365#define PACK_RGB(DST, R, G, B) \ 366do { \ 367 (DST)[0] = R; \ 368 (DST)[1] = G; \ 369 (DST)[2] = B; \ 370} while (0) 371 372#define PACK_BGR(DST, R, G, B) \ 373do { \ 374 (DST)[0] = B; \ 375 (DST)[1] = G; \ 376 (DST)[2] = R; \ 377} while (0) 378 379#define PACK_RGB_565(DST, R, G, B) \ 380do { \ 381 (DST) = (((int) (R) << 8) & 0xf800) | (((int) (G) << 3) & 0x7e0) | ((int) (B) >> 3);\ 382} while (0) 383 384#define UNPACK_RED(P) ( (P)[osmesa->rInd] ) 385#define UNPACK_GREEN(P) ( (P)[osmesa->gInd] ) 386#define UNPACK_BLUE(P) ( (P)[osmesa->bInd] ) 387#define UNPACK_ALPHA(P) ( (P)[osmesa->aInd] ) 388 389#define PIXELADDR1(X,Y) (osmesa->rowaddr[Y] + (X)) 390#define PIXELADDR2(X,Y) (osmesa->rowaddr[Y] + 2 * (X)) 391#define PIXELADDR3(X,Y) (osmesa->rowaddr[Y] + 3 * (X)) 392#define PIXELADDR4(X,Y) (osmesa->rowaddr[Y] + 4 * (X)) 393 394 395/* 396 * Draw a flat-shaded, RGB line into an osmesa buffer. 397 */ 398#define NAME flat_rgba_line 399#define CLIP_HACK 1 400#define SETUP_CODE \ 401 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \ 402 const GLchan *color = vert1->color; 403 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 */ 421#define NAME flat_rgba_z_line 422#define CLIP_HACK 1 423#define INTERP_Z 1 424#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 425#define SETUP_CODE \ 426 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \ 427 const GLchan *color = vert1->color; 428 429#define PLOT(X, Y) \ 430do { \ 431 if (Z < *zPtr) { \ 432 GLchan *p = PIXELADDR4(X, Y); \ 433 PACK_RGBA(p, color[RCOMP], color[GCOMP], \ 434 color[BCOMP], color[ACOMP]); \ 435 *zPtr = Z; \ 436 } \ 437} while (0) 438 439#ifdef WIN32 440#include "..\swrast\s_linetemp.h" 441#else 442#include "swrast/s_linetemp.h" 443#endif 444 445 446 447/* 448 * Analyze context state to see if we can provide a fast line drawing 449 * function, like those in lines.c. Otherwise, return NULL. 450 */ 451static swrast_line_func 452osmesa_choose_line_function( GLcontext *ctx ) 453{ 454 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 455 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 456 457 if (CHAN_BITS != 8) return NULL; 458 if (ctx->RenderMode != GL_RENDER) return NULL; 459 if (ctx->Line.SmoothFlag) return NULL; 460 if (ctx->Texture._EnabledUnits) return NULL; 461 if (ctx->Light.ShadeModel != GL_FLAT) return NULL; 462 if (ctx->Line.Width != 1.0F) return NULL; 463 if (ctx->Line.StippleFlag) return NULL; 464 if (ctx->Line.SmoothFlag) return NULL; 465 if (osmesa->format != OSMESA_RGBA && 466 osmesa->format != OSMESA_BGRA && 467 osmesa->format != OSMESA_ARGB) return NULL; 468 469 if (swrast->_RasterMask==DEPTH_BIT 470 && ctx->Depth.Func==GL_LESS 471 && ctx->Depth.Mask==GL_TRUE 472 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) { 473 return (swrast_line_func) flat_rgba_z_line; 474 } 475 476 if (swrast->_RasterMask == 0) { 477 return (swrast_line_func) flat_rgba_line; 478 } 479 480 return (swrast_line_func) NULL; 481} 482 483 484/**********************************************************************/ 485/***** Optimized triangle rendering *****/ 486/**********************************************************************/ 487 488 489/* 490 * Smooth-shaded, z-less triangle, RGBA color. 491 */ 492#define NAME smooth_rgba_z_triangle 493#define INTERP_Z 1 494#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 495#define INTERP_RGB 1 496#define INTERP_ALPHA 1 497#define SETUP_CODE \ 498 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 499#define RENDER_SPAN( span ) \ 500 GLuint i; \ 501 GLchan *img = PIXELADDR4(span.x, span.y); \ 502 for (i = 0; i < span.end; i++, img += 4) { \ 503 const GLdepth z = FixedToDepth(span.z); \ 504 if (z < zRow[i]) { \ 505 PACK_RGBA(img, FixedToChan(span.red), \ 506 FixedToChan(span.green), FixedToChan(span.blue), \ 507 FixedToChan(span.alpha)); \ 508 zRow[i] = z; \ 509 } \ 510 span.red += span.redStep; \ 511 span.green += span.greenStep; \ 512 span.blue += span.blueStep; \ 513 span.alpha += span.alphaStep; \ 514 span.z += span.zStep; \ 515 } 516#ifdef WIN32 517#include "..\swrast\s_tritemp.h" 518#else 519#include "swrast/s_tritemp.h" 520#endif 521 522 523 524/* 525 * Flat-shaded, z-less triangle, RGBA color. 526 */ 527#define NAME flat_rgba_z_triangle 528#define INTERP_Z 1 529#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 530#define SETUP_CODE \ 531 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \ 532 GLuint pixel; \ 533 PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1], \ 534 v2->color[2], v2->color[3]); 535 536#define RENDER_SPAN( span ) \ 537 GLuint i; \ 538 GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y); \ 539 for (i = 0; i < span.end; i++) { \ 540 const GLdepth z = FixedToDepth(span.z); \ 541 if (z < zRow[i]) { \ 542 img[i] = pixel; \ 543 zRow[i] = z; \ 544 } \ 545 span.z += span.zStep; \ 546 } 547#ifdef WIN32 548#include "..\swrast\s_tritemp.h" 549#else 550#include "swrast/s_tritemp.h" 551#endif 552 553 554 555/* 556 * Return pointer to an accelerated triangle function if possible. 557 */ 558static swrast_tri_func 559osmesa_choose_triangle_function( GLcontext *ctx ) 560{ 561 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 562 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 563 564 if (CHAN_BITS != 8) return (swrast_tri_func) NULL; 565 if (ctx->RenderMode != GL_RENDER) return (swrast_tri_func) NULL; 566 if (ctx->Polygon.SmoothFlag) return (swrast_tri_func) NULL; 567 if (ctx->Polygon.StippleFlag) return (swrast_tri_func) NULL; 568 if (ctx->Texture._EnabledUnits) return (swrast_tri_func) NULL; 569 if (osmesa->format != OSMESA_RGBA && 570 osmesa->format != OSMESA_BGRA && 571 osmesa->format != OSMESA_ARGB) return (swrast_tri_func) NULL; 572 if (ctx->Polygon.CullFlag && 573 ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) 574 return (swrast_tri_func) NULL; 575 576 if (swrast->_RasterMask == DEPTH_BIT && 577 ctx->Depth.Func == GL_LESS && 578 ctx->Depth.Mask == GL_TRUE && 579 ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) { 580 if (ctx->Light.ShadeModel == GL_SMOOTH) { 581 return (swrast_tri_func) smooth_rgba_z_triangle; 582 } 583 else { 584 return (swrast_tri_func) flat_rgba_z_triangle; 585 } 586 } 587 return (swrast_tri_func) NULL; 588} 589 590 591 592/* Override for the swrast triangle-selection function. Try to use one 593 * of our internal triangle functions, otherwise fall back to the 594 * standard swrast functions. 595 */ 596static void 597osmesa_choose_triangle( GLcontext *ctx ) 598{ 599 SWcontext *swrast = SWRAST_CONTEXT(ctx); 600 601 swrast->Triangle = osmesa_choose_triangle_function( ctx ); 602 if (!swrast->Triangle) 603 _swrast_choose_triangle( ctx ); 604} 605 606static void 607osmesa_choose_line( GLcontext *ctx ) 608{ 609 SWcontext *swrast = SWRAST_CONTEXT(ctx); 610 611 swrast->Line = osmesa_choose_line_function( ctx ); 612 if (!swrast->Line) 613 _swrast_choose_line( ctx ); 614} 615 616 617#define OSMESA_NEW_LINE (_NEW_LINE | \ 618 _NEW_TEXTURE | \ 619 _NEW_LIGHT | \ 620 _NEW_DEPTH | \ 621 _NEW_RENDERMODE | \ 622 _SWRAST_NEW_RASTERMASK) 623 624#define OSMESA_NEW_TRIANGLE (_NEW_POLYGON | \ 625 _NEW_TEXTURE | \ 626 _NEW_LIGHT | \ 627 _NEW_DEPTH | \ 628 _NEW_RENDERMODE | \ 629 _SWRAST_NEW_RASTERMASK) 630 631/* one-time, per-context initialization */ 632static void 633hook_in_driver_functions( GLcontext *ctx ) 634{ 635 OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 636 SWcontext *swrast = SWRAST_CONTEXT( ctx ); 637 struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx ); 638 TNLcontext *tnl = TNL_CONTEXT(ctx); 639 640 ASSERT((void *) osmesa == (void *) ctx->DriverCtx); 641 642 /* use default TCL pipeline */ 643 tnl->Driver.RunPipeline = _tnl_run_pipeline; 644 645 ctx->Driver.GetString = get_string; 646 ctx->Driver.UpdateState = osmesa_update_state; 647 ctx->Driver.ResizeBuffers = _swrast_alloc_buffers; 648 ctx->Driver.GetBufferSize = get_buffer_size; 649 650 ctx->Driver.Accum = _swrast_Accum; 651 ctx->Driver.Bitmap = _swrast_Bitmap; 652 ctx->Driver.Clear = clear; /* uses _swrast_Clear */ 653 ctx->Driver.CopyPixels = _swrast_CopyPixels; 654 ctx->Driver.DrawPixels = _swrast_DrawPixels; 655 ctx->Driver.ReadPixels = _swrast_ReadPixels; 656 ctx->Driver.DrawBuffer = _swrast_DrawBuffer; 657 658 ctx->Driver.ChooseTextureFormat = _mesa_choose_tex_format; 659 ctx->Driver.TexImage1D = _mesa_store_teximage1d; 660 ctx->Driver.TexImage2D = _mesa_store_teximage2d; 661 ctx->Driver.TexImage3D = _mesa_store_teximage3d; 662 ctx->Driver.TexSubImage1D = _mesa_store_texsubimage1d; 663 ctx->Driver.TexSubImage2D = _mesa_store_texsubimage2d; 664 ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d; 665 ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage; 666 667 ctx->Driver.CompressedTexImage1D = _mesa_store_compressed_teximage1d; 668 ctx->Driver.CompressedTexImage2D = _mesa_store_compressed_teximage2d; 669 ctx->Driver.CompressedTexImage3D = _mesa_store_compressed_teximage3d; 670 ctx->Driver.CompressedTexSubImage1D = _mesa_store_compressed_texsubimage1d; 671 ctx->Driver.CompressedTexSubImage2D = _mesa_store_compressed_texsubimage2d; 672 ctx->Driver.CompressedTexSubImage3D = _mesa_store_compressed_texsubimage3d; 673 674 ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d; 675 ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d; 676 ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d; 677 ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d; 678 ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d; 679 ctx->Driver.CopyColorTable = _swrast_CopyColorTable; 680 ctx->Driver.CopyColorSubTable = _swrast_CopyColorSubTable; 681 ctx->Driver.CopyConvolutionFilter1D = _swrast_CopyConvolutionFilter1D; 682 ctx->Driver.CopyConvolutionFilter2D = _swrast_CopyConvolutionFilter2D; 683 684 swdd->SetBuffer = set_buffer; 685 686 /* RGB(A) span/pixel functions */ 687 if (osmesa->format == OSMESA_RGB) { 688 swdd->WriteRGBASpan = write_rgba_span_RGB; 689 swdd->WriteRGBSpan = write_rgb_span_RGB; 690 swdd->WriteMonoRGBASpan = write_monorgba_span_RGB; 691 swdd->WriteRGBAPixels = write_rgba_pixels_RGB; 692 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB; 693 swdd->ReadRGBASpan = read_rgba_span_RGB; 694 swdd->ReadRGBAPixels = read_rgba_pixels_RGB; 695 } 696 else if (osmesa->format == OSMESA_BGR) { 697 swdd->WriteRGBASpan = write_rgba_span_BGR; 698 swdd->WriteRGBSpan = write_rgb_span_BGR; 699 swdd->WriteMonoRGBASpan = write_monorgba_span_BGR; 700 swdd->WriteRGBAPixels = write_rgba_pixels_BGR; 701 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGR; 702 swdd->ReadRGBASpan = read_rgba_span_BGR; 703 swdd->ReadRGBAPixels = read_rgba_pixels_BGR; 704 } 705#if CHAN_TYPE == GL_UNSIGNED_BYTE 706 else if (osmesa->format == OSMESA_RGB_565) { 707 swdd->WriteRGBASpan = write_rgba_span_RGB_565; 708 swdd->WriteRGBSpan = write_rgb_span_RGB_565; 709 swdd->WriteMonoRGBASpan = write_monorgba_span_RGB_565; 710 swdd->WriteRGBAPixels = write_rgba_pixels_RGB_565; 711 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB_565; 712 swdd->ReadRGBASpan = read_rgba_span_RGB_565; 713 swdd->ReadRGBAPixels = read_rgba_pixels_RGB_565; 714 } 715#endif 716 else if (osmesa->format == OSMESA_RGBA) { 717 swdd->WriteRGBASpan = write_rgba_span_RGBA; 718 swdd->WriteRGBSpan = write_rgb_span_RGBA; 719 swdd->WriteMonoRGBASpan = write_monorgba_span_RGBA; 720 swdd->WriteRGBAPixels = write_rgba_pixels_RGBA; 721 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGBA; 722 swdd->ReadRGBASpan = read_rgba_span_RGBA; 723 swdd->ReadRGBAPixels = read_rgba_pixels_RGBA; 724 } 725 else if (osmesa->format == OSMESA_BGRA) { 726 swdd->WriteRGBASpan = write_rgba_span_BGRA; 727 swdd->WriteRGBSpan = write_rgb_span_BGRA; 728 swdd->WriteMonoRGBASpan = write_monorgba_span_BGRA; 729 swdd->WriteRGBAPixels = write_rgba_pixels_BGRA; 730 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGRA; 731 swdd->ReadRGBASpan = read_rgba_span_BGRA; 732 swdd->ReadRGBAPixels = read_rgba_pixels_BGRA; 733 } 734 else if (osmesa->format == OSMESA_ARGB) { 735 swdd->WriteRGBASpan = write_rgba_span_ARGB; 736 swdd->WriteRGBSpan = write_rgb_span_ARGB; 737 swdd->WriteMonoRGBASpan = write_monorgba_span_ARGB; 738 swdd->WriteRGBAPixels = write_rgba_pixels_ARGB; 739 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_ARGB; 740 swdd->ReadRGBASpan = read_rgba_span_ARGB; 741 swdd->ReadRGBAPixels = read_rgba_pixels_ARGB; 742 } 743 else if (osmesa->format == OSMESA_COLOR_INDEX) { 744 swdd->WriteCI32Span = write_index32_span_CI; 745 swdd->WriteCI8Span = write_index8_span_CI; 746 swdd->WriteMonoCISpan = write_monoindex_span_CI; 747 swdd->WriteCI32Pixels = write_index_pixels_CI; 748 swdd->WriteMonoCIPixels = write_monoindex_pixels_CI; 749 swdd->ReadCI32Span = read_index_span_CI; 750 swdd->ReadCI32Pixels = read_index_pixels_CI; 751 } 752 else { 753 _mesa_problem(ctx, "bad pixel format in osmesa_update_state!\n"); 754 } 755 756 /* Extend the software rasterizer with our optimized line and triangle 757 * drawin functions. 758 */ 759 swrast->choose_line = osmesa_choose_line; 760 swrast->choose_triangle = osmesa_choose_triangle; 761 swrast->invalidate_line |= OSMESA_NEW_LINE; 762 swrast->invalidate_triangle |= OSMESA_NEW_TRIANGLE; 763} 764 765 766 767 768/**********************************************************************/ 769/***** Public Functions *****/ 770/**********************************************************************/ 771 772 773/* 774 * Create an Off-Screen Mesa rendering context. The only attribute needed is 775 * an RGBA vs Color-Index mode flag. 776 * 777 * Input: format - either GL_RGBA or GL_COLOR_INDEX 778 * sharelist - specifies another OSMesaContext with which to share 779 * display lists. NULL indicates no sharing. 780 * Return: an OSMesaContext or 0 if error 781 */ 782GLAPI OSMesaContext GLAPIENTRY 783OSMesaCreateContext( GLenum format, OSMesaContext sharelist ) 784{ 785 return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS, 786 8, 16, sharelist); 787} 788 789 790 791/* 792 * New in Mesa 3.5 793 * 794 * Create context and specify size of ancillary buffers. 795 */ 796GLAPI OSMesaContext GLAPIENTRY 797OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, 798 GLint accumBits, OSMesaContext sharelist ) 799{ 800 OSMesaContext osmesa; 801 GLint rshift, gshift, bshift, ashift; 802 GLint rind, gind, bind, aind; 803 GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0; 804 GLboolean rgbmode; 805 const GLuint i4 = 1; 806 const GLubyte *i1 = (GLubyte *) &i4; 807 const GLint little_endian = *i1; 808 809 rind = gind = bind = aind = 0; 810 if (format==OSMESA_COLOR_INDEX) { 811 indexBits = 8; 812 rshift = gshift = bshift = ashift = 0; 813 rgbmode = GL_FALSE; 814 } 815 else if (format==OSMESA_RGBA) { 816 indexBits = 0; 817 redBits = CHAN_BITS; 818 greenBits = CHAN_BITS; 819 blueBits = CHAN_BITS; 820 alphaBits = CHAN_BITS; 821 rind = 0; 822 gind = 1; 823 bind = 2; 824 aind = 3; 825 if (little_endian) { 826 rshift = 0; 827 gshift = 8; 828 bshift = 16; 829 ashift = 24; 830 } 831 else { 832 rshift = 24; 833 gshift = 16; 834 bshift = 8; 835 ashift = 0; 836 } 837 rgbmode = GL_TRUE; 838 } 839 else if (format==OSMESA_BGRA) { 840 indexBits = 0; 841 redBits = CHAN_BITS; 842 greenBits = CHAN_BITS; 843 blueBits = CHAN_BITS; 844 alphaBits = CHAN_BITS; 845 bind = 0; 846 gind = 1; 847 rind = 2; 848 aind = 3; 849 if (little_endian) { 850 bshift = 0; 851 gshift = 8; 852 rshift = 16; 853 ashift = 24; 854 } 855 else { 856 bshift = 24; 857 gshift = 16; 858 rshift = 8; 859 ashift = 0; 860 } 861 rgbmode = GL_TRUE; 862 } 863 else if (format==OSMESA_ARGB) { 864 indexBits = 0; 865 redBits = CHAN_BITS; 866 greenBits = CHAN_BITS; 867 blueBits = CHAN_BITS; 868 alphaBits = CHAN_BITS; 869 aind = 0; 870 rind = 1; 871 gind = 2; 872 bind = 3; 873 if (little_endian) { 874 ashift = 0; 875 rshift = 8; 876 gshift = 16; 877 bshift = 24; 878 } 879 else { 880 ashift = 24; 881 rshift = 16; 882 gshift = 8; 883 bshift = 0; 884 } 885 rgbmode = GL_TRUE; 886 } 887 else if (format==OSMESA_RGB) { 888 indexBits = 0; 889 redBits = CHAN_BITS; 890 greenBits = CHAN_BITS; 891 blueBits = CHAN_BITS; 892 alphaBits = 0; 893 bshift = 0; 894 gshift = 8; 895 rshift = 16; 896 ashift = 24; 897 rind = 0; 898 gind = 1; 899 bind = 2; 900 rgbmode = GL_TRUE; 901 } 902 else if (format==OSMESA_BGR) { 903 indexBits = 0; 904 redBits = CHAN_BITS; 905 greenBits = CHAN_BITS; 906 blueBits = CHAN_BITS; 907 alphaBits = 0; 908 bshift = 0; 909 gshift = 8; 910 rshift = 16; 911 ashift = 24; 912 rind = 2; 913 gind = 1; 914 bind = 0; 915 rgbmode = GL_TRUE; 916 } 917#if CHAN_TYPE == GL_UNSIGNED_BYTE 918 else if (format==OSMESA_RGB_565) { 919 indexBits = 0; 920 redBits = 5; 921 greenBits = 6; 922 blueBits = 5; 923 alphaBits = 0; 924 rshift = 11; 925 gshift = 5; 926 bshift = 0; 927 ashift = 0; 928 rind = 0; /* not used */ 929 gind = 0; 930 bind = 0; 931 rgbmode = GL_TRUE; 932 } 933#endif 934 else { 935 return NULL; 936 } 937 938 939 osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context); 940 if (osmesa) { 941 osmesa->gl_visual = _mesa_create_visual( rgbmode, 942 GL_FALSE, /* double buffer */ 943 GL_FALSE, /* stereo */ 944 redBits, 945 greenBits, 946 blueBits, 947 alphaBits, 948 indexBits, 949 depthBits, 950 stencilBits, 951 accumBits, 952 accumBits, 953 accumBits, 954 alphaBits ? accumBits : 0, 955 1 /* num samples */ 956 ); 957 if (!osmesa->gl_visual) { 958 FREE(osmesa); 959 return NULL; 960 } 961 962 /* Setup these pointers here since they're using for making the default 963 * and proxy texture objects. Actually, we don't really need to do 964 * this since we're using the default fallback functions which 965 * _mesa_initialize_context() would plug in if needed. 966 */ 967 osmesa->mesa.Driver.NewTextureObject = _mesa_new_texture_object; 968 osmesa->mesa.Driver.DeleteTexture = _mesa_delete_texture_object; 969 970 if (!_mesa_initialize_context(&osmesa->mesa, 971 osmesa->gl_visual, 972 sharelist ? &sharelist->mesa 973 : (GLcontext *) NULL, 974 (void *) osmesa, 975 GL_FALSE)) { 976 _mesa_destroy_visual( osmesa->gl_visual ); 977 FREE(osmesa); 978 return NULL; 979 } 980 981 _mesa_enable_sw_extensions(&(osmesa->mesa)); 982 _mesa_enable_1_3_extensions(&(osmesa->mesa)); 983 _mesa_enable_1_4_extensions(&(osmesa->mesa)); 984 _mesa_enable_1_5_extensions(&(osmesa->mesa)); 985 986 osmesa->gl_buffer = _mesa_create_framebuffer( osmesa->gl_visual, 987 (GLboolean) ( osmesa->gl_visual->depthBits > 0 ), 988 (GLboolean) ( osmesa->gl_visual->stencilBits > 0 ), 989 (GLboolean) ( osmesa->gl_visual->accumRedBits > 0 ), 990 GL_FALSE /* s/w alpha */ ); 991 992 if (!osmesa->gl_buffer) { 993 _mesa_destroy_visual( osmesa->gl_visual ); 994 _mesa_free_context_data( &osmesa->mesa ); 995 FREE(osmesa); 996 return NULL; 997 } 998 osmesa->format = format; 999 osmesa->buffer = NULL; 1000 osmesa->width = 0; 1001 osmesa->height = 0; 1002 osmesa->userRowLength = 0; 1003 osmesa->rowlength = 0; 1004 osmesa->yup = GL_TRUE; 1005 osmesa->rshift = rshift; 1006 osmesa->gshift = gshift; 1007 osmesa->bshift = bshift; 1008 osmesa->ashift = ashift; 1009 osmesa->rInd = rind; 1010 osmesa->gInd = gind; 1011 osmesa->bInd = bind; 1012 osmesa->aInd = aind; 1013 1014 /* Initialize the software rasterizer and helper modules. */ 1015 { 1016 GLcontext *ctx = &osmesa->mesa; 1017 1018 _swrast_CreateContext( ctx ); 1019 _ac_CreateContext( ctx ); 1020 _tnl_CreateContext( ctx ); 1021 _swsetup_CreateContext( ctx ); 1022 1023 _swsetup_Wakeup( ctx ); 1024 hook_in_driver_functions( ctx ); 1025 } 1026 } 1027 return osmesa; 1028} 1029 1030 1031/* 1032 * Destroy an Off-Screen Mesa rendering context. 1033 * 1034 * Input: ctx - the context to destroy 1035 */ 1036GLAPI void GLAPIENTRY 1037OSMesaDestroyContext( OSMesaContext ctx ) 1038{ 1039 if (ctx) { 1040 _swsetup_DestroyContext( &ctx->mesa ); 1041 _tnl_DestroyContext( &ctx->mesa ); 1042 _ac_DestroyContext( &ctx->mesa ); 1043 _swrast_DestroyContext( &ctx->mesa ); 1044 1045 _mesa_destroy_visual( ctx->gl_visual ); 1046 _mesa_destroy_framebuffer( ctx->gl_buffer ); 1047 _mesa_free_context_data( &ctx->mesa ); 1048 FREE( ctx ); 1049 } 1050} 1051 1052 1053/* 1054 * Recompute the values of the context's rowaddr array. 1055 */ 1056static void 1057compute_row_addresses( OSMesaContext ctx ) 1058{ 1059 GLint bytesPerPixel, bytesPerRow, i; 1060 GLubyte *origin = (GLubyte *) ctx->buffer; 1061 1062 if (ctx->format == OSMESA_COLOR_INDEX) { 1063 /* CI mode */ 1064 bytesPerPixel = 1 * sizeof(GLchan); 1065 } 1066 else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) { 1067 /* RGB mode */ 1068 bytesPerPixel = 3 * sizeof(GLchan); 1069 } 1070 else if (ctx->format == OSMESA_RGB_565) { 1071 /* 5/6/5 RGB pixel in 16 bits */ 1072 bytesPerPixel = 2; 1073 } 1074 else { 1075 /* RGBA mode */ 1076 bytesPerPixel = 4 * sizeof(GLchan); 1077 } 1078 1079 bytesPerRow = ctx->rowlength * bytesPerPixel; 1080 1081 if (ctx->yup) { 1082 /* Y=0 is bottom line of window */ 1083 for (i = 0; i < MAX_HEIGHT; i++) { 1084 ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow); 1085 } 1086 } 1087 else { 1088 /* Y=0 is top line of window */ 1089 for (i = 0; i < MAX_HEIGHT; i++) { 1090 GLint j = ctx->height - i - 1; 1091 ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow); 1092 } 1093 } 1094} 1095 1096 1097/* 1098 * Bind an OSMesaContext to an image buffer. The image buffer is just a 1099 * block of memory which the client provides. Its size must be at least 1100 * as large as width*height*sizeof(type). Its address should be a multiple 1101 * of 4 if using RGBA mode. 1102 * 1103 * Image data is stored in the order of glDrawPixels: row-major order 1104 * with the lower-left image pixel stored in the first array position 1105 * (ie. bottom-to-top). 1106 * 1107 * If the context's viewport hasn't been initialized yet, it will now be 1108 * initialized to (0,0,width,height). 1109 * 1110 * Input: ctx - the rendering context 1111 * buffer - the image buffer memory 1112 * type - data type for pixel components 1113 * Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5 1114 * are supported. But if Mesa's been compiled with CHAN_BITS==16 1115 * then type must be GL_UNSIGNED_SHORT. And if Mesa's been build 1116 * with CHAN_BITS==32 then type must be GL_FLOAT. 1117 * width, height - size of image buffer in pixels, at least 1 1118 * Return: GL_TRUE if success, GL_FALSE if error because of invalid ctx, 1119 * invalid buffer address, invalid type, width<1, height<1, 1120 * width>internal limit or height>internal limit. 1121 */ 1122GLAPI GLboolean GLAPIENTRY 1123OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type, 1124 GLsizei width, GLsizei height ) 1125{ 1126 if (!ctx || !buffer || 1127 width < 1 || height < 1 || 1128 width > MAX_WIDTH || height > MAX_HEIGHT) { 1129 return GL_FALSE; 1130 } 1131 1132 if (ctx->format == OSMESA_RGB_565) { 1133 if (type != GL_UNSIGNED_SHORT_5_6_5) 1134 return GL_FALSE; 1135 } 1136 else if (type != CHAN_TYPE) { 1137 return GL_FALSE; 1138 } 1139 1140 osmesa_update_state( &ctx->mesa, 0 ); 1141 _mesa_make_current( &ctx->mesa, ctx->gl_buffer ); 1142 1143 ctx->buffer = buffer; 1144 ctx->width = width; 1145 ctx->height = height; 1146 if (ctx->userRowLength) 1147 ctx->rowlength = ctx->userRowLength; 1148 else 1149 ctx->rowlength = width; 1150 1151 compute_row_addresses( ctx ); 1152 1153 /* init viewport */ 1154 if (ctx->mesa.Viewport.Width == 0) { 1155 /* initialize viewport and scissor box to buffer size */ 1156 _mesa_Viewport( 0, 0, width, height ); 1157 ctx->mesa.Scissor.Width = width; 1158 ctx->mesa.Scissor.Height = height; 1159 } 1160 else { 1161 /* this will make ensure we recognize the new buffer size */ 1162 _mesa_ResizeBuffersMESA(); 1163 } 1164 1165 /* Added by Gerk Huisma: */ 1166 _tnl_MakeCurrent( &ctx->mesa, ctx->mesa.DrawBuffer, 1167 ctx->mesa.ReadBuffer ); 1168 1169 return GL_TRUE; 1170} 1171 1172 1173 1174GLAPI OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void ) 1175{ 1176 GLcontext *ctx = _mesa_get_current_context(); 1177 if (ctx) 1178 return (OSMesaContext) ctx; 1179 else 1180 return NULL; 1181} 1182 1183 1184 1185GLAPI void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value ) 1186{ 1187 OSMesaContext osmesa = OSMesaGetCurrentContext(); 1188 1189 switch (pname) { 1190 case OSMESA_ROW_LENGTH: 1191 if (value<0) { 1192 _mesa_error( &osmesa->mesa, GL_INVALID_VALUE, 1193 "OSMesaPixelStore(value)" ); 1194 return; 1195 } 1196 osmesa->userRowLength = value; 1197 osmesa->rowlength = value ? value : osmesa->width; 1198 break; 1199 case OSMESA_Y_UP: 1200 osmesa->yup = value ? GL_TRUE : GL_FALSE; 1201 break; 1202 default: 1203 _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" ); 1204 return; 1205 } 1206 1207 compute_row_addresses( osmesa ); 1208} 1209 1210 1211GLAPI void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value ) 1212{ 1213 OSMesaContext osmesa = OSMesaGetCurrentContext(); 1214 1215 switch (pname) { 1216 case OSMESA_WIDTH: 1217 *value = osmesa->width; 1218 return; 1219 case OSMESA_HEIGHT: 1220 *value = osmesa->height; 1221 return; 1222 case OSMESA_FORMAT: 1223 *value = osmesa->format; 1224 return; 1225 case OSMESA_TYPE: 1226 *value = CHAN_TYPE; 1227 return; 1228 case OSMESA_ROW_LENGTH: 1229 *value = osmesa->userRowLength; 1230 return; 1231 case OSMESA_Y_UP: 1232 *value = osmesa->yup; 1233 return; 1234 case OSMESA_MAX_WIDTH: 1235 *value = MAX_WIDTH; 1236 return; 1237 case OSMESA_MAX_HEIGHT: 1238 *value = MAX_HEIGHT; 1239 return; 1240 default: 1241 _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)"); 1242 return; 1243 } 1244} 1245 1246/* 1247 * Return the depth buffer associated with an OSMesa context. 1248 * Input: c - the OSMesa context 1249 * Output: width, height - size of buffer in pixels 1250 * bytesPerValue - bytes per depth value (2 or 4) 1251 * buffer - pointer to depth buffer values 1252 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 1253 */ 1254GLAPI GLboolean GLAPIENTRY 1255OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height, 1256 GLint *bytesPerValue, void **buffer ) 1257{ 1258 if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) { 1259 *width = 0; 1260 *height = 0; 1261 *bytesPerValue = 0; 1262 *buffer = 0; 1263 return GL_FALSE; 1264 } 1265 else { 1266 *width = c->gl_buffer->Width; 1267 *height = c->gl_buffer->Height; 1268 if (c->gl_visual->depthBits <= 16) 1269 *bytesPerValue = sizeof(GLushort); 1270 else 1271 *bytesPerValue = sizeof(GLuint); 1272 *buffer = c->gl_buffer->DepthBuffer; 1273 return GL_TRUE; 1274 } 1275} 1276 1277/* 1278 * Return the color buffer associated with an OSMesa context. 1279 * Input: c - the OSMesa context 1280 * Output: width, height - size of buffer in pixels 1281 * format - the pixel format (OSMESA_FORMAT) 1282 * buffer - pointer to color buffer values 1283 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 1284 */ 1285GLAPI GLboolean GLAPIENTRY 1286OSMesaGetColorBuffer( OSMesaContext c, GLint *width, 1287 GLint *height, GLint *format, void **buffer ) 1288{ 1289 if (!c->buffer) { 1290 *width = 0; 1291 *height = 0; 1292 *format = 0; 1293 *buffer = 0; 1294 return GL_FALSE; 1295 } 1296 else { 1297 *width = c->width; 1298 *height = c->height; 1299 *format = c->format; 1300 *buffer = c->buffer; 1301 return GL_TRUE; 1302 } 1303} 1304 1305 1306 1307struct name_address { 1308 const char *Name; 1309 GLvoid *Address; 1310}; 1311 1312static struct name_address functions[] = { 1313 { "OSMesaCreateContext", (void *) OSMesaCreateContext }, 1314 { "OSMesaCreateContextExt", (void *) OSMesaCreateContextExt }, 1315 { "OSMesaDestroyContext", (void *) OSMesaDestroyContext }, 1316 { "OSMesaMakeCurrent", (void *) OSMesaMakeCurrent }, 1317 { "OSMesaGetCurrentContext", (void *) OSMesaGetCurrentContext }, 1318 { "OSMesaPixelsStore", (void *) OSMesaPixelStore }, 1319 { "OSMesaGetIntegerv", (void *) OSMesaGetIntegerv }, 1320 { "OSMesaGetDepthBuffer", (void *) OSMesaGetDepthBuffer }, 1321 { "OSMesaGetColorBuffer", (void *) OSMesaGetColorBuffer }, 1322 { "OSMesaGetProcAddress", (void *) OSMesaGetProcAddress }, 1323 { NULL, NULL } 1324}; 1325 1326GLAPI void * GLAPIENTRY 1327OSMesaGetProcAddress( const char *funcName ) 1328{ 1329 int i; 1330 for (i = 0; functions[i].Name; i++) { 1331 if (_mesa_strcmp(functions[i].Name, funcName) == 0) 1332 return (void *) functions[i].Address; 1333 } 1334 return (void *) _glapi_get_proc_address(funcName); 1335} 1336