osmesa.c revision 894844a8d956a0ee5f95836331dc318f49fdb845
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.1 4 * 5 * Copyright (C) 1999-2004 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 "bufferobj.h" 40#include "context.h" 41#include "colormac.h" 42#include "depth.h" 43#include "extensions.h" 44#include "imports.h" 45#include "macros.h" 46#include "matrix.h" 47#include "mtypes.h" 48#include "texformat.h" 49#include "texobj.h" 50#include "teximage.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#include "drivers/common/driverfuncs.h" 63 64 65 66/* 67 * This is the OS/Mesa context struct. 68 * Notice how it includes a GLcontext. By doing this we're mimicking 69 * C++ inheritance/derivation. 70 * Later, we can cast a GLcontext pointer into an OSMesaContext pointer 71 * or vice versa. 72 */ 73struct osmesa_context { 74 GLcontext mesa; /* The core GL/Mesa context */ 75 GLvisual *gl_visual; /* Describes the buffers */ 76 GLframebuffer *gl_buffer; /* Depth, stencil, accum, etc buffers */ 77 GLenum format; /* either GL_RGBA or GL_COLOR_INDEX */ 78 void *buffer; /* the image buffer */ 79 GLint width, height; /* size of image buffer */ 80 GLint rowlength; /* number of pixels per row */ 81 GLint userRowLength; /* user-specified number of pixels per row */ 82 GLint rshift, gshift; /* bit shifts for RGBA formats */ 83 GLint bshift, ashift; 84 GLint rInd, gInd, bInd, aInd;/* index offsets for RGBA formats */ 85 GLchan *rowaddr[MAX_HEIGHT]; /* address of first pixel in each image row */ 86 GLboolean yup; /* TRUE -> Y increases upward */ 87 /* FALSE -> Y increases downward */ 88}; 89 90 91/* Just cast, since we're using structure containment */ 92#define OSMESA_CONTEXT(ctx) ((OSMesaContext) (ctx->DriverCtx)) 93 94 95 96/**********************************************************************/ 97/*** Private Device Driver Functions ***/ 98/**********************************************************************/ 99 100 101static const GLubyte * 102get_string( GLcontext *ctx, GLenum name ) 103{ 104 (void) ctx; 105 switch (name) { 106 case GL_RENDERER: 107#if CHAN_BITS == 32 108 return (const GLubyte *) "Mesa OffScreen32"; 109#elif CHAN_BITS == 16 110 return (const GLubyte *) "Mesa OffScreen16"; 111#else 112 return (const GLubyte *) "Mesa OffScreen"; 113#endif 114 default: 115 return NULL; 116 } 117} 118 119 120static void 121osmesa_update_state( GLcontext *ctx, GLuint new_state ) 122{ 123 /* easy - just propogate */ 124 _swrast_InvalidateState( ctx, new_state ); 125 _swsetup_InvalidateState( ctx, new_state ); 126 _ac_InvalidateState( ctx, new_state ); 127 _tnl_InvalidateState( ctx, new_state ); 128} 129 130 131static void 132set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit ) 133{ 134 /* separate read buffer not supported */ 135 ASSERT(buffer == ctx->DrawBuffer); 136 ASSERT(bufferBit == DD_FRONT_LEFT_BIT); 137} 138 139 140static void 141get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) 142{ 143 /* don't use GET_CURRENT_CONTEXT(ctx) here - it's a problem on Windows */ 144 GLcontext *ctx = (GLcontext *) _glapi_get_context(); 145 (void) buffer; 146 if (ctx) { 147 OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 148 *width = osmesa->width; 149 *height = osmesa->height; 150 } 151} 152 153 154static void 155clear( GLcontext *ctx, GLbitfield mask, GLboolean all, 156 GLint x, GLint y, GLint width, GLint height ) 157{ 158 OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 159 const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask; 160 161 /* sanity check - we only have a front-left buffer */ 162 ASSERT((mask & (DD_FRONT_RIGHT_BIT | 163 DD_BACK_LEFT_BIT | 164 DD_BACK_RIGHT_BIT)) == 0); 165 166 /* use optimized clear for common cases (clear whole buffer to black) */ 167 if (mask & DD_FRONT_LEFT_BIT) { 168 if (osmesa->format == OSMESA_COLOR_INDEX) { 169 if (ctx->Color.ClearIndex == 0 && 170 ctx->Color.IndexMask == (GLuint) ~0 && 171 osmesa->rowlength == osmesa->width && 172 all) { 173 /* clear whole buffer to zeros */ 174 _mesa_bzero(osmesa->buffer, 175 osmesa->width * osmesa->height * sizeof(GLchan)); 176 mask &= ~DD_FRONT_LEFT_BIT; 177 } 178 } 179 else { 180 /* RGB[A] format */ 181 if (*colorMask == 0xffffffff && 182 ctx->Color.ClearColor[0] == 0.0F && 183 ctx->Color.ClearColor[1] == 0.0F && 184 ctx->Color.ClearColor[2] == 0.0F && 185 ctx->Color.ClearColor[3] == 0.0F && 186 osmesa->rowlength == osmesa->width && 187 all) { 188 GLint bytesPerPixel; 189 /* clear whole buffer to black */ 190 if (osmesa->format == OSMESA_RGBA || 191 osmesa->format == OSMESA_BGRA || 192 osmesa->format == OSMESA_ARGB) 193 bytesPerPixel = 4 * sizeof(GLchan); 194 else if (osmesa->format == OSMESA_RGB || 195 osmesa->format == OSMESA_BGR) 196 bytesPerPixel = 3 * sizeof(GLchan); 197 else if (osmesa->format == OSMESA_RGB_565) 198 bytesPerPixel = sizeof(GLushort); 199 else { 200 _mesa_problem(ctx, "bad pixel format in osmesa_clear()"); 201 return; 202 } 203 _mesa_bzero(osmesa->buffer, 204 bytesPerPixel * osmesa->width * osmesa->height); 205 mask &= ~DD_FRONT_LEFT_BIT; 206 } 207 } 208 } 209 210 if (mask) { 211 /* software fallback (spans) for everything else. */ 212 _swrast_Clear(ctx, mask, all, x, y, width, height); 213 } 214} 215 216 217/**********************************************************************/ 218/***** Read/write spans/arrays of pixels *****/ 219/**********************************************************************/ 220 221 222/* RGBA */ 223#define NAME(PREFIX) PREFIX##_RGBA 224#define SPAN_VARS \ 225 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 226#define INIT_PIXEL_PTR(P, X, Y) \ 227 GLchan *P = osmesa->rowaddr[Y] + 4 * (X) 228#define INC_PIXEL_PTR(P) P += 4 229#if CHAN_TYPE == GL_FLOAT 230#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \ 231 P[0] = MAX2((R), 0.0F); \ 232 P[1] = MAX2((G), 0.0F); \ 233 P[2] = MAX2((B), 0.0F); \ 234 P[3] = CHAN_MAXF 235#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \ 236 P[0] = MAX2((R), 0.0F); \ 237 P[1] = MAX2((G), 0.0F); \ 238 P[2] = MAX2((B), 0.0F); \ 239 P[3] = CLAMP((A), 0.0F, CHAN_MAXF) 240#else 241#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \ 242 P[0] = R; P[1] = G; P[2] = B; P[3] = CHAN_MAX 243#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \ 244 P[0] = R; P[1] = G; P[2] = B; P[3] = A 245#endif 246#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ 247 R = P[0]; G = P[1]; B = P[2]; A = P[3] 248#include "swrast/s_spantemp.h" 249 250/* BGRA */ 251#define NAME(PREFIX) PREFIX##_BGRA 252#define SPAN_VARS \ 253 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 254#define INIT_PIXEL_PTR(P, X, Y) \ 255 GLchan *P = osmesa->rowaddr[Y] + 4 * (X) 256#define INC_PIXEL_PTR(P) P += 4 257#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \ 258 P[2] = R; P[1] = G; P[0] = B; P[3] = CHAN_MAX 259#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \ 260 P[2] = R; P[1] = G; P[0] = B; P[3] = A 261#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ 262 R = P[2]; G = P[1]; B = P[0]; A = P[3] 263#include "swrast/s_spantemp.h" 264 265/* ARGB */ 266#define NAME(PREFIX) PREFIX##_ARGB 267#define SPAN_VARS \ 268 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 269#define INIT_PIXEL_PTR(P, X, Y) \ 270 GLchan *P = osmesa->rowaddr[Y] + 4 * (X) 271#define INC_PIXEL_PTR(P) P += 4 272#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \ 273 P[1] = R; P[2] = G; P[3] = B; P[0] = CHAN_MAX 274#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \ 275 P[1] = R; P[2] = G; P[3] = B; P[0] = A 276#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ 277 R = P[1]; G = P[2]; B = P[3]; A = P[0] 278#include "swrast/s_spantemp.h" 279 280/* RGB */ 281#define NAME(PREFIX) PREFIX##_RGB 282#define SPAN_VARS \ 283 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 284#define INIT_PIXEL_PTR(P, X, Y) \ 285 GLchan *P = osmesa->rowaddr[Y] + 3 * (X) 286#define INC_PIXEL_PTR(P) P += 3 287#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \ 288 P[0] = R; P[1] = G; P[2] = B 289#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \ 290 P[0] = R; P[1] = G; P[2] = B 291#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ 292 R = P[0]; G = P[1]; B = P[2]; A = CHAN_MAX 293#include "swrast/s_spantemp.h" 294 295/* BGR */ 296#define NAME(PREFIX) PREFIX##_BGR 297#define SPAN_VARS \ 298 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 299#define INIT_PIXEL_PTR(P, X, Y) \ 300 GLchan *P = osmesa->rowaddr[Y] + 3 * (X) 301#define INC_PIXEL_PTR(P) P += 3 302#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \ 303 P[0] = B; P[1] = G; P[2] = R 304#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \ 305 P[0] = B; P[1] = G; P[2] = R 306#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ 307 B = P[0]; G = P[1]; R = P[2]; A = CHAN_MAX 308#include "swrast/s_spantemp.h" 309 310/* 16-bit BGR */ 311#if CHAN_TYPE == GL_UNSIGNED_BYTE 312#define NAME(PREFIX) PREFIX##_RGB_565 313#define SPAN_VARS \ 314 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 315#define INIT_PIXEL_PTR(P, X, Y) \ 316 GLushort *P = (GLushort *) osmesa->rowaddr[Y] + (X) 317#define INC_PIXEL_PTR(P) P += 1 318#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \ 319 *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) ) 320#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \ 321 *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) ) 322#define FETCH_RGBA_PIXEL(R, G, B, A, P) \ 323 R = ( (((*P) >> 8) & 0xf8) | (((*P) >> 11) & 0x7) ); \ 324 G = ( (((*P) >> 3) & 0xfc) | (((*P) >> 5) & 0x3) ); \ 325 B = ( (((*P) << 3) & 0xf8) | (((*P) ) & 0x7) ); \ 326 A = CHAN_MAX 327#include "swrast/s_spantemp.h" 328#endif 329 330/* color index */ 331#define NAME(PREFIX) PREFIX##_CI 332#define SPAN_VARS \ 333 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 334#define INIT_PIXEL_PTR(P, X, Y) \ 335 GLchan *P = osmesa->rowaddr[Y] + (X) 336#define INC_PIXEL_PTR(P) P += 1 337#define STORE_CI_PIXEL(P, CI) \ 338 P[0] = CI 339#define FETCH_CI_PIXEL(CI, P) \ 340 CI = P[0] 341#include "swrast/s_spantemp.h" 342 343 344/**********************************************************************/ 345/***** Optimized line rendering *****/ 346/**********************************************************************/ 347 348 349#if CHAN_TYPE == GL_FLOAT 350#define PACK_RGBA(DST, R, G, B, A) \ 351do { \ 352 (DST)[0] = MAX2( R, 0.0F ); \ 353 (DST)[1] = MAX2( G, 0.0F ); \ 354 (DST)[2] = MAX2( B, 0.0F ); \ 355 (DST)[3] = CLAMP(A, 0.0F, CHAN_MAXF);\ 356} while (0) 357#else 358#define PACK_RGBA(DST, R, G, B, A) \ 359do { \ 360 (DST)[osmesa->rInd] = R; \ 361 (DST)[osmesa->gInd] = G; \ 362 (DST)[osmesa->bInd] = B; \ 363 (DST)[osmesa->aInd] = A; \ 364} while (0) 365#endif 366 367#define PACK_RGB(DST, R, G, B) \ 368do { \ 369 (DST)[0] = R; \ 370 (DST)[1] = G; \ 371 (DST)[2] = B; \ 372} while (0) 373 374#define PACK_BGR(DST, R, G, B) \ 375do { \ 376 (DST)[0] = B; \ 377 (DST)[1] = G; \ 378 (DST)[2] = R; \ 379} while (0) 380 381#define PACK_RGB_565(DST, R, G, B) \ 382do { \ 383 (DST) = (((int) (R) << 8) & 0xf800) | (((int) (G) << 3) & 0x7e0) | ((int) (B) >> 3);\ 384} while (0) 385 386#define UNPACK_RED(P) ( (P)[osmesa->rInd] ) 387#define UNPACK_GREEN(P) ( (P)[osmesa->gInd] ) 388#define UNPACK_BLUE(P) ( (P)[osmesa->bInd] ) 389#define UNPACK_ALPHA(P) ( (P)[osmesa->aInd] ) 390 391#define PIXELADDR1(X,Y) (osmesa->rowaddr[Y] + (X)) 392#define PIXELADDR2(X,Y) (osmesa->rowaddr[Y] + 2 * (X)) 393#define PIXELADDR3(X,Y) (osmesa->rowaddr[Y] + 3 * (X)) 394#define PIXELADDR4(X,Y) (osmesa->rowaddr[Y] + 4 * (X)) 395 396 397/* 398 * Draw a flat-shaded, RGB line into an osmesa buffer. 399 */ 400#define NAME flat_rgba_line 401#define CLIP_HACK 1 402#define SETUP_CODE \ 403 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \ 404 const GLchan *color = vert1->color; 405 406#define PLOT(X, Y) \ 407do { \ 408 GLchan *p = PIXELADDR4(X, Y); \ 409 PACK_RGBA(p, color[0], color[1], color[2], color[3]); \ 410} while (0) 411 412#ifdef WIN32 413#include "..\swrast\s_linetemp.h" 414#else 415#include "swrast/s_linetemp.h" 416#endif 417 418 419 420/* 421 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer. 422 */ 423#define NAME flat_rgba_z_line 424#define CLIP_HACK 1 425#define INTERP_Z 1 426#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 427#define SETUP_CODE \ 428 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \ 429 const GLchan *color = vert1->color; 430 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#ifdef WIN32 442#include "..\swrast\s_linetemp.h" 443#else 444#include "swrast/s_linetemp.h" 445#endif 446 447 448 449/* 450 * Analyze context state to see if we can provide a fast line drawing 451 * function, like those in lines.c. Otherwise, return NULL. 452 */ 453static swrast_line_func 454osmesa_choose_line_function( GLcontext *ctx ) 455{ 456 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 457 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 458 459 if (CHAN_BITS != 8) return NULL; 460 if (ctx->RenderMode != GL_RENDER) return NULL; 461 if (ctx->Line.SmoothFlag) return NULL; 462 if (ctx->Texture._EnabledUnits) return NULL; 463 if (ctx->Light.ShadeModel != GL_FLAT) return NULL; 464 if (ctx->Line.Width != 1.0F) return NULL; 465 if (ctx->Line.StippleFlag) return NULL; 466 if (ctx->Line.SmoothFlag) return NULL; 467 if (osmesa->format != OSMESA_RGBA && 468 osmesa->format != OSMESA_BGRA && 469 osmesa->format != OSMESA_ARGB) return NULL; 470 471 if (swrast->_RasterMask==DEPTH_BIT 472 && ctx->Depth.Func==GL_LESS 473 && ctx->Depth.Mask==GL_TRUE 474 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) { 475 return (swrast_line_func) flat_rgba_z_line; 476 } 477 478 if (swrast->_RasterMask == 0) { 479 return (swrast_line_func) flat_rgba_line; 480 } 481 482 return (swrast_line_func) NULL; 483} 484 485 486/**********************************************************************/ 487/***** Optimized triangle rendering *****/ 488/**********************************************************************/ 489 490 491/* 492 * Smooth-shaded, z-less triangle, RGBA color. 493 */ 494#define NAME smooth_rgba_z_triangle 495#define INTERP_Z 1 496#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 497#define INTERP_RGB 1 498#define INTERP_ALPHA 1 499#define SETUP_CODE \ 500 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 501#define RENDER_SPAN( span ) \ 502 GLuint i; \ 503 GLchan *img = PIXELADDR4(span.x, span.y); \ 504 for (i = 0; i < span.end; i++, img += 4) { \ 505 const GLdepth z = FixedToDepth(span.z); \ 506 if (z < zRow[i]) { \ 507 PACK_RGBA(img, FixedToChan(span.red), \ 508 FixedToChan(span.green), FixedToChan(span.blue), \ 509 FixedToChan(span.alpha)); \ 510 zRow[i] = z; \ 511 } \ 512 span.red += span.redStep; \ 513 span.green += span.greenStep; \ 514 span.blue += span.blueStep; \ 515 span.alpha += span.alphaStep; \ 516 span.z += span.zStep; \ 517 } 518#ifdef WIN32 519#include "..\swrast\s_tritemp.h" 520#else 521#include "swrast/s_tritemp.h" 522#endif 523 524 525 526/* 527 * Flat-shaded, z-less triangle, RGBA color. 528 */ 529#define NAME flat_rgba_z_triangle 530#define INTERP_Z 1 531#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 532#define SETUP_CODE \ 533 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \ 534 GLuint pixel; \ 535 PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1], \ 536 v2->color[2], v2->color[3]); 537 538#define RENDER_SPAN( span ) \ 539 GLuint i; \ 540 GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y); \ 541 for (i = 0; i < span.end; i++) { \ 542 const GLdepth z = FixedToDepth(span.z); \ 543 if (z < zRow[i]) { \ 544 img[i] = pixel; \ 545 zRow[i] = z; \ 546 } \ 547 span.z += span.zStep; \ 548 } 549#ifdef WIN32 550#include "..\swrast\s_tritemp.h" 551#else 552#include "swrast/s_tritemp.h" 553#endif 554 555 556 557/* 558 * Return pointer to an accelerated triangle function if possible. 559 */ 560static swrast_tri_func 561osmesa_choose_triangle_function( GLcontext *ctx ) 562{ 563 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 564 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 565 566 if (CHAN_BITS != 8) return (swrast_tri_func) NULL; 567 if (ctx->RenderMode != GL_RENDER) return (swrast_tri_func) NULL; 568 if (ctx->Polygon.SmoothFlag) return (swrast_tri_func) NULL; 569 if (ctx->Polygon.StippleFlag) return (swrast_tri_func) NULL; 570 if (ctx->Texture._EnabledUnits) return (swrast_tri_func) NULL; 571 if (osmesa->format != OSMESA_RGBA && 572 osmesa->format != OSMESA_BGRA && 573 osmesa->format != OSMESA_ARGB) return (swrast_tri_func) NULL; 574 if (ctx->Polygon.CullFlag && 575 ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) 576 return (swrast_tri_func) NULL; 577 578 if (swrast->_RasterMask == DEPTH_BIT && 579 ctx->Depth.Func == GL_LESS && 580 ctx->Depth.Mask == GL_TRUE && 581 ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) { 582 if (ctx->Light.ShadeModel == GL_SMOOTH) { 583 return (swrast_tri_func) smooth_rgba_z_triangle; 584 } 585 else { 586 return (swrast_tri_func) flat_rgba_z_triangle; 587 } 588 } 589 return (swrast_tri_func) NULL; 590} 591 592 593 594/* Override for the swrast triangle-selection function. Try to use one 595 * of our internal triangle functions, otherwise fall back to the 596 * standard swrast functions. 597 */ 598static void 599osmesa_choose_triangle( GLcontext *ctx ) 600{ 601 SWcontext *swrast = SWRAST_CONTEXT(ctx); 602 603 swrast->Triangle = osmesa_choose_triangle_function( ctx ); 604 if (!swrast->Triangle) 605 _swrast_choose_triangle( ctx ); 606} 607 608static void 609osmesa_choose_line( GLcontext *ctx ) 610{ 611 SWcontext *swrast = SWRAST_CONTEXT(ctx); 612 613 swrast->Line = osmesa_choose_line_function( ctx ); 614 if (!swrast->Line) 615 _swrast_choose_line( ctx ); 616} 617 618 619#define OSMESA_NEW_LINE (_NEW_LINE | \ 620 _NEW_TEXTURE | \ 621 _NEW_LIGHT | \ 622 _NEW_DEPTH | \ 623 _NEW_RENDERMODE | \ 624 _SWRAST_NEW_RASTERMASK) 625 626#define OSMESA_NEW_TRIANGLE (_NEW_POLYGON | \ 627 _NEW_TEXTURE | \ 628 _NEW_LIGHT | \ 629 _NEW_DEPTH | \ 630 _NEW_RENDERMODE | \ 631 _SWRAST_NEW_RASTERMASK) 632 633 634/* one-time, per-context initialization */ 635static void 636hook_in_driver_functions( GLcontext *ctx ) 637{ 638 OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 639 SWcontext *swrast = SWRAST_CONTEXT( ctx ); 640 struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx ); 641 TNLcontext *tnl = TNL_CONTEXT(ctx); 642 643 ASSERT((void *) osmesa == (void *) ctx->DriverCtx); 644 645 /* use default TCL pipeline */ 646 tnl->Driver.RunPipeline = _tnl_run_pipeline; 647 648 swdd->SetBuffer = set_buffer; 649 650 /* RGB(A) span/pixel functions */ 651 if (osmesa->format == OSMESA_RGB) { 652 swdd->WriteRGBASpan = write_rgba_span_RGB; 653 swdd->WriteRGBSpan = write_rgb_span_RGB; 654 swdd->WriteMonoRGBASpan = write_monorgba_span_RGB; 655 swdd->WriteRGBAPixels = write_rgba_pixels_RGB; 656 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB; 657 swdd->ReadRGBASpan = read_rgba_span_RGB; 658 swdd->ReadRGBAPixels = read_rgba_pixels_RGB; 659 } 660 else if (osmesa->format == OSMESA_BGR) { 661 swdd->WriteRGBASpan = write_rgba_span_BGR; 662 swdd->WriteRGBSpan = write_rgb_span_BGR; 663 swdd->WriteMonoRGBASpan = write_monorgba_span_BGR; 664 swdd->WriteRGBAPixels = write_rgba_pixels_BGR; 665 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGR; 666 swdd->ReadRGBASpan = read_rgba_span_BGR; 667 swdd->ReadRGBAPixels = read_rgba_pixels_BGR; 668 } 669#if CHAN_TYPE == GL_UNSIGNED_BYTE 670 else if (osmesa->format == OSMESA_RGB_565) { 671 swdd->WriteRGBASpan = write_rgba_span_RGB_565; 672 swdd->WriteRGBSpan = write_rgb_span_RGB_565; 673 swdd->WriteMonoRGBASpan = write_monorgba_span_RGB_565; 674 swdd->WriteRGBAPixels = write_rgba_pixels_RGB_565; 675 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB_565; 676 swdd->ReadRGBASpan = read_rgba_span_RGB_565; 677 swdd->ReadRGBAPixels = read_rgba_pixels_RGB_565; 678 } 679#endif 680 else if (osmesa->format == OSMESA_RGBA) { 681 swdd->WriteRGBASpan = write_rgba_span_RGBA; 682 swdd->WriteRGBSpan = write_rgb_span_RGBA; 683 swdd->WriteMonoRGBASpan = write_monorgba_span_RGBA; 684 swdd->WriteRGBAPixels = write_rgba_pixels_RGBA; 685 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGBA; 686 swdd->ReadRGBASpan = read_rgba_span_RGBA; 687 swdd->ReadRGBAPixels = read_rgba_pixels_RGBA; 688 } 689 else if (osmesa->format == OSMESA_BGRA) { 690 swdd->WriteRGBASpan = write_rgba_span_BGRA; 691 swdd->WriteRGBSpan = write_rgb_span_BGRA; 692 swdd->WriteMonoRGBASpan = write_monorgba_span_BGRA; 693 swdd->WriteRGBAPixels = write_rgba_pixels_BGRA; 694 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGRA; 695 swdd->ReadRGBASpan = read_rgba_span_BGRA; 696 swdd->ReadRGBAPixels = read_rgba_pixels_BGRA; 697 } 698 else if (osmesa->format == OSMESA_ARGB) { 699 swdd->WriteRGBASpan = write_rgba_span_ARGB; 700 swdd->WriteRGBSpan = write_rgb_span_ARGB; 701 swdd->WriteMonoRGBASpan = write_monorgba_span_ARGB; 702 swdd->WriteRGBAPixels = write_rgba_pixels_ARGB; 703 swdd->WriteMonoRGBAPixels = write_monorgba_pixels_ARGB; 704 swdd->ReadRGBASpan = read_rgba_span_ARGB; 705 swdd->ReadRGBAPixels = read_rgba_pixels_ARGB; 706 } 707 else if (osmesa->format == OSMESA_COLOR_INDEX) { 708 swdd->WriteCI32Span = write_index32_span_CI; 709 swdd->WriteCI8Span = write_index8_span_CI; 710 swdd->WriteMonoCISpan = write_monoindex_span_CI; 711 swdd->WriteCI32Pixels = write_index_pixels_CI; 712 swdd->WriteMonoCIPixels = write_monoindex_pixels_CI; 713 swdd->ReadCI32Span = read_index_span_CI; 714 swdd->ReadCI32Pixels = read_index_pixels_CI; 715 } 716 else { 717 _mesa_problem(ctx, "bad pixel format in osmesa_update_state!\n"); 718 } 719 720 /* Extend the software rasterizer with our optimized line and triangle 721 * drawin functions. 722 */ 723 swrast->choose_line = osmesa_choose_line; 724 swrast->choose_triangle = osmesa_choose_triangle; 725 swrast->invalidate_line |= OSMESA_NEW_LINE; 726 swrast->invalidate_triangle |= OSMESA_NEW_TRIANGLE; 727} 728 729 730 731 732/**********************************************************************/ 733/***** Public Functions *****/ 734/**********************************************************************/ 735 736 737/* 738 * Create an Off-Screen Mesa rendering context. The only attribute needed is 739 * an RGBA vs Color-Index mode flag. 740 * 741 * Input: format - either GL_RGBA or GL_COLOR_INDEX 742 * sharelist - specifies another OSMesaContext with which to share 743 * display lists. NULL indicates no sharing. 744 * Return: an OSMesaContext or 0 if error 745 */ 746GLAPI OSMesaContext GLAPIENTRY 747OSMesaCreateContext( GLenum format, OSMesaContext sharelist ) 748{ 749 const GLint accumBits = (format == OSMESA_COLOR_INDEX) ? 0 : 16; 750 return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS, 751 8, accumBits, sharelist); 752} 753 754 755 756/* 757 * New in Mesa 3.5 758 * 759 * Create context and specify size of ancillary buffers. 760 */ 761GLAPI OSMesaContext GLAPIENTRY 762OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, 763 GLint accumBits, OSMesaContext sharelist ) 764{ 765 OSMesaContext osmesa; 766 struct dd_function_table functions; 767 GLint rshift, gshift, bshift, ashift; 768 GLint rind, gind, bind, aind; 769 GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0; 770 GLboolean rgbmode; 771 const GLuint i4 = 1; 772 const GLubyte *i1 = (GLubyte *) &i4; 773 const GLint little_endian = *i1; 774 775 rind = gind = bind = aind = 0; 776 if (format==OSMESA_COLOR_INDEX) { 777 indexBits = 8; 778 rshift = gshift = bshift = ashift = 0; 779 rgbmode = GL_FALSE; 780 } 781 else if (format==OSMESA_RGBA) { 782 indexBits = 0; 783 redBits = CHAN_BITS; 784 greenBits = CHAN_BITS; 785 blueBits = CHAN_BITS; 786 alphaBits = CHAN_BITS; 787 rind = 0; 788 gind = 1; 789 bind = 2; 790 aind = 3; 791 if (little_endian) { 792 rshift = 0; 793 gshift = 8; 794 bshift = 16; 795 ashift = 24; 796 } 797 else { 798 rshift = 24; 799 gshift = 16; 800 bshift = 8; 801 ashift = 0; 802 } 803 rgbmode = GL_TRUE; 804 } 805 else if (format==OSMESA_BGRA) { 806 indexBits = 0; 807 redBits = CHAN_BITS; 808 greenBits = CHAN_BITS; 809 blueBits = CHAN_BITS; 810 alphaBits = CHAN_BITS; 811 bind = 0; 812 gind = 1; 813 rind = 2; 814 aind = 3; 815 if (little_endian) { 816 bshift = 0; 817 gshift = 8; 818 rshift = 16; 819 ashift = 24; 820 } 821 else { 822 bshift = 24; 823 gshift = 16; 824 rshift = 8; 825 ashift = 0; 826 } 827 rgbmode = GL_TRUE; 828 } 829 else if (format==OSMESA_ARGB) { 830 indexBits = 0; 831 redBits = CHAN_BITS; 832 greenBits = CHAN_BITS; 833 blueBits = CHAN_BITS; 834 alphaBits = CHAN_BITS; 835 aind = 0; 836 rind = 1; 837 gind = 2; 838 bind = 3; 839 if (little_endian) { 840 ashift = 0; 841 rshift = 8; 842 gshift = 16; 843 bshift = 24; 844 } 845 else { 846 ashift = 24; 847 rshift = 16; 848 gshift = 8; 849 bshift = 0; 850 } 851 rgbmode = GL_TRUE; 852 } 853 else if (format==OSMESA_RGB) { 854 indexBits = 0; 855 redBits = CHAN_BITS; 856 greenBits = CHAN_BITS; 857 blueBits = CHAN_BITS; 858 alphaBits = 0; 859 bshift = 0; 860 gshift = 8; 861 rshift = 16; 862 ashift = 24; 863 rind = 0; 864 gind = 1; 865 bind = 2; 866 rgbmode = GL_TRUE; 867 } 868 else if (format==OSMESA_BGR) { 869 indexBits = 0; 870 redBits = CHAN_BITS; 871 greenBits = CHAN_BITS; 872 blueBits = CHAN_BITS; 873 alphaBits = 0; 874 bshift = 0; 875 gshift = 8; 876 rshift = 16; 877 ashift = 24; 878 rind = 2; 879 gind = 1; 880 bind = 0; 881 rgbmode = GL_TRUE; 882 } 883#if CHAN_TYPE == GL_UNSIGNED_BYTE 884 else if (format==OSMESA_RGB_565) { 885 indexBits = 0; 886 redBits = 5; 887 greenBits = 6; 888 blueBits = 5; 889 alphaBits = 0; 890 rshift = 11; 891 gshift = 5; 892 bshift = 0; 893 ashift = 0; 894 rind = 0; /* not used */ 895 gind = 0; 896 bind = 0; 897 rgbmode = GL_TRUE; 898 } 899#endif 900 else { 901 return NULL; 902 } 903 904 905 osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context); 906 if (osmesa) { 907 osmesa->gl_visual = _mesa_create_visual( rgbmode, 908 GL_FALSE, /* double buffer */ 909 GL_FALSE, /* stereo */ 910 redBits, 911 greenBits, 912 blueBits, 913 alphaBits, 914 indexBits, 915 depthBits, 916 stencilBits, 917 accumBits, 918 accumBits, 919 accumBits, 920 alphaBits ? accumBits : 0, 921 1 /* num samples */ 922 ); 923 if (!osmesa->gl_visual) { 924 FREE(osmesa); 925 return NULL; 926 } 927 928 /* Initialize device driver function table */ 929 _mesa_init_driver_functions(&functions); 930 /* override with our functions */ 931 functions.GetString = get_string; 932 functions.UpdateState = osmesa_update_state; 933 functions.GetBufferSize = get_buffer_size; 934 functions.Clear = clear; 935 936 if (!_mesa_initialize_context(&osmesa->mesa, 937 osmesa->gl_visual, 938 sharelist ? &sharelist->mesa 939 : (GLcontext *) NULL, 940 &functions, (void *) osmesa)) { 941 _mesa_destroy_visual( osmesa->gl_visual ); 942 FREE(osmesa); 943 return NULL; 944 } 945 946 _mesa_enable_sw_extensions(&(osmesa->mesa)); 947 _mesa_enable_1_3_extensions(&(osmesa->mesa)); 948 _mesa_enable_1_4_extensions(&(osmesa->mesa)); 949 _mesa_enable_1_5_extensions(&(osmesa->mesa)); 950 951 osmesa->gl_buffer = _mesa_create_framebuffer( osmesa->gl_visual, 952 (GLboolean) ( osmesa->gl_visual->depthBits > 0 ), 953 (GLboolean) ( osmesa->gl_visual->stencilBits > 0 ), 954 (GLboolean) ( osmesa->gl_visual->accumRedBits > 0 ), 955 GL_FALSE /* s/w alpha */ ); 956 957 if (!osmesa->gl_buffer) { 958 _mesa_destroy_visual( osmesa->gl_visual ); 959 _mesa_free_context_data( &osmesa->mesa ); 960 FREE(osmesa); 961 return NULL; 962 } 963 osmesa->format = format; 964 osmesa->buffer = NULL; 965 osmesa->width = 0; 966 osmesa->height = 0; 967 osmesa->userRowLength = 0; 968 osmesa->rowlength = 0; 969 osmesa->yup = GL_TRUE; 970 osmesa->rshift = rshift; 971 osmesa->gshift = gshift; 972 osmesa->bshift = bshift; 973 osmesa->ashift = ashift; 974 osmesa->rInd = rind; 975 osmesa->gInd = gind; 976 osmesa->bInd = bind; 977 osmesa->aInd = aind; 978 979 /* Initialize the software rasterizer and helper modules. */ 980 { 981 GLcontext *ctx = &osmesa->mesa; 982 983 _swrast_CreateContext( ctx ); 984 _ac_CreateContext( ctx ); 985 _tnl_CreateContext( ctx ); 986 _swsetup_CreateContext( ctx ); 987 988 _swsetup_Wakeup( ctx ); 989 hook_in_driver_functions( ctx ); 990 } 991 } 992 return osmesa; 993} 994 995 996/* 997 * Destroy an Off-Screen Mesa rendering context. 998 * 999 * Input: ctx - the context to destroy 1000 */ 1001GLAPI void GLAPIENTRY 1002OSMesaDestroyContext( OSMesaContext ctx ) 1003{ 1004 if (ctx) { 1005 _swsetup_DestroyContext( &ctx->mesa ); 1006 _tnl_DestroyContext( &ctx->mesa ); 1007 _ac_DestroyContext( &ctx->mesa ); 1008 _swrast_DestroyContext( &ctx->mesa ); 1009 1010 _mesa_destroy_visual( ctx->gl_visual ); 1011 _mesa_destroy_framebuffer( ctx->gl_buffer ); 1012 _mesa_free_context_data( &ctx->mesa ); 1013 FREE( ctx ); 1014 } 1015} 1016 1017 1018/* 1019 * Recompute the values of the context's rowaddr array. 1020 */ 1021static void 1022compute_row_addresses( OSMesaContext ctx ) 1023{ 1024 GLint bytesPerPixel, bytesPerRow, i; 1025 GLubyte *origin = (GLubyte *) ctx->buffer; 1026 1027 if (ctx->format == OSMESA_COLOR_INDEX) { 1028 /* CI mode */ 1029 bytesPerPixel = 1 * sizeof(GLchan); 1030 } 1031 else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) { 1032 /* RGB mode */ 1033 bytesPerPixel = 3 * sizeof(GLchan); 1034 } 1035 else if (ctx->format == OSMESA_RGB_565) { 1036 /* 5/6/5 RGB pixel in 16 bits */ 1037 bytesPerPixel = 2; 1038 } 1039 else { 1040 /* RGBA mode */ 1041 bytesPerPixel = 4 * sizeof(GLchan); 1042 } 1043 1044 bytesPerRow = ctx->rowlength * bytesPerPixel; 1045 1046 if (ctx->yup) { 1047 /* Y=0 is bottom line of window */ 1048 for (i = 0; i < MAX_HEIGHT; i++) { 1049 ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow); 1050 } 1051 } 1052 else { 1053 /* Y=0 is top line of window */ 1054 for (i = 0; i < MAX_HEIGHT; i++) { 1055 GLint j = ctx->height - i - 1; 1056 ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow); 1057 } 1058 } 1059} 1060 1061 1062/* 1063 * Bind an OSMesaContext to an image buffer. The image buffer is just a 1064 * block of memory which the client provides. Its size must be at least 1065 * as large as width*height*sizeof(type). Its address should be a multiple 1066 * of 4 if using RGBA mode. 1067 * 1068 * Image data is stored in the order of glDrawPixels: row-major order 1069 * with the lower-left image pixel stored in the first array position 1070 * (ie. bottom-to-top). 1071 * 1072 * If the context's viewport hasn't been initialized yet, it will now be 1073 * initialized to (0,0,width,height). 1074 * 1075 * Input: ctx - the rendering context 1076 * buffer - the image buffer memory 1077 * type - data type for pixel components 1078 * Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5 1079 * are supported. But if Mesa's been compiled with CHAN_BITS==16 1080 * then type must be GL_UNSIGNED_SHORT. And if Mesa's been build 1081 * with CHAN_BITS==32 then type must be GL_FLOAT. 1082 * width, height - size of image buffer in pixels, at least 1 1083 * Return: GL_TRUE if success, GL_FALSE if error because of invalid ctx, 1084 * invalid buffer address, invalid type, width<1, height<1, 1085 * width>internal limit or height>internal limit. 1086 */ 1087GLAPI GLboolean GLAPIENTRY 1088OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type, 1089 GLsizei width, GLsizei height ) 1090{ 1091 if (!ctx || !buffer || 1092 width < 1 || height < 1 || 1093 width > MAX_WIDTH || height > MAX_HEIGHT) { 1094 return GL_FALSE; 1095 } 1096 1097 if (ctx->format == OSMESA_RGB_565) { 1098 if (type != GL_UNSIGNED_SHORT_5_6_5) 1099 return GL_FALSE; 1100 } 1101 else if (type != CHAN_TYPE) { 1102 return GL_FALSE; 1103 } 1104 1105 osmesa_update_state( &ctx->mesa, 0 ); 1106 _mesa_make_current( &ctx->mesa, ctx->gl_buffer ); 1107 1108 ctx->buffer = buffer; 1109 ctx->width = width; 1110 ctx->height = height; 1111 if (ctx->userRowLength) 1112 ctx->rowlength = ctx->userRowLength; 1113 else 1114 ctx->rowlength = width; 1115 1116 compute_row_addresses( ctx ); 1117 1118 /* init viewport */ 1119 if (ctx->mesa.Viewport.Width == 0) { 1120 /* initialize viewport and scissor box to buffer size */ 1121 _mesa_Viewport( 0, 0, width, height ); 1122 ctx->mesa.Scissor.Width = width; 1123 ctx->mesa.Scissor.Height = height; 1124 } 1125 else { 1126 /* this will make ensure we recognize the new buffer size */ 1127 _mesa_ResizeBuffersMESA(); 1128 } 1129 1130 /* Added by Gerk Huisma: */ 1131 _tnl_MakeCurrent( &ctx->mesa, ctx->mesa.DrawBuffer, 1132 ctx->mesa.ReadBuffer ); 1133 1134 return GL_TRUE; 1135} 1136 1137 1138 1139GLAPI OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void ) 1140{ 1141 GLcontext *ctx = _mesa_get_current_context(); 1142 if (ctx) 1143 return (OSMesaContext) ctx; 1144 else 1145 return NULL; 1146} 1147 1148 1149 1150GLAPI void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value ) 1151{ 1152 OSMesaContext osmesa = OSMesaGetCurrentContext(); 1153 1154 switch (pname) { 1155 case OSMESA_ROW_LENGTH: 1156 if (value<0) { 1157 _mesa_error( &osmesa->mesa, GL_INVALID_VALUE, 1158 "OSMesaPixelStore(value)" ); 1159 return; 1160 } 1161 osmesa->userRowLength = value; 1162 osmesa->rowlength = value ? value : osmesa->width; 1163 break; 1164 case OSMESA_Y_UP: 1165 osmesa->yup = value ? GL_TRUE : GL_FALSE; 1166 break; 1167 default: 1168 _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" ); 1169 return; 1170 } 1171 1172 compute_row_addresses( osmesa ); 1173} 1174 1175 1176GLAPI void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value ) 1177{ 1178 OSMesaContext osmesa = OSMesaGetCurrentContext(); 1179 1180 switch (pname) { 1181 case OSMESA_WIDTH: 1182 *value = osmesa->width; 1183 return; 1184 case OSMESA_HEIGHT: 1185 *value = osmesa->height; 1186 return; 1187 case OSMESA_FORMAT: 1188 *value = osmesa->format; 1189 return; 1190 case OSMESA_TYPE: 1191 *value = CHAN_TYPE; 1192 return; 1193 case OSMESA_ROW_LENGTH: 1194 *value = osmesa->userRowLength; 1195 return; 1196 case OSMESA_Y_UP: 1197 *value = osmesa->yup; 1198 return; 1199 case OSMESA_MAX_WIDTH: 1200 *value = MAX_WIDTH; 1201 return; 1202 case OSMESA_MAX_HEIGHT: 1203 *value = MAX_HEIGHT; 1204 return; 1205 default: 1206 _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)"); 1207 return; 1208 } 1209} 1210 1211/* 1212 * Return the depth buffer associated with an OSMesa context. 1213 * Input: c - the OSMesa context 1214 * Output: width, height - size of buffer in pixels 1215 * bytesPerValue - bytes per depth value (2 or 4) 1216 * buffer - pointer to depth buffer values 1217 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 1218 */ 1219GLAPI GLboolean GLAPIENTRY 1220OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height, 1221 GLint *bytesPerValue, void **buffer ) 1222{ 1223 if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) { 1224 *width = 0; 1225 *height = 0; 1226 *bytesPerValue = 0; 1227 *buffer = 0; 1228 return GL_FALSE; 1229 } 1230 else { 1231 *width = c->gl_buffer->Width; 1232 *height = c->gl_buffer->Height; 1233 if (c->gl_visual->depthBits <= 16) 1234 *bytesPerValue = sizeof(GLushort); 1235 else 1236 *bytesPerValue = sizeof(GLuint); 1237 *buffer = c->gl_buffer->DepthBuffer; 1238 return GL_TRUE; 1239 } 1240} 1241 1242/* 1243 * Return the color buffer associated with an OSMesa context. 1244 * Input: c - the OSMesa context 1245 * Output: width, height - size of buffer in pixels 1246 * format - the pixel format (OSMESA_FORMAT) 1247 * buffer - pointer to color buffer values 1248 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 1249 */ 1250GLAPI GLboolean GLAPIENTRY 1251OSMesaGetColorBuffer( OSMesaContext c, GLint *width, 1252 GLint *height, GLint *format, void **buffer ) 1253{ 1254 if (!c->buffer) { 1255 *width = 0; 1256 *height = 0; 1257 *format = 0; 1258 *buffer = 0; 1259 return GL_FALSE; 1260 } 1261 else { 1262 *width = c->width; 1263 *height = c->height; 1264 *format = c->format; 1265 *buffer = c->buffer; 1266 return GL_TRUE; 1267 } 1268} 1269 1270 1271 1272struct name_address { 1273 const char *Name; 1274 GLvoid *Address; 1275}; 1276 1277static struct name_address functions[] = { 1278 { "OSMesaCreateContext", (void *) OSMesaCreateContext }, 1279 { "OSMesaCreateContextExt", (void *) OSMesaCreateContextExt }, 1280 { "OSMesaDestroyContext", (void *) OSMesaDestroyContext }, 1281 { "OSMesaMakeCurrent", (void *) OSMesaMakeCurrent }, 1282 { "OSMesaGetCurrentContext", (void *) OSMesaGetCurrentContext }, 1283 { "OSMesaPixelsStore", (void *) OSMesaPixelStore }, 1284 { "OSMesaGetIntegerv", (void *) OSMesaGetIntegerv }, 1285 { "OSMesaGetDepthBuffer", (void *) OSMesaGetDepthBuffer }, 1286 { "OSMesaGetColorBuffer", (void *) OSMesaGetColorBuffer }, 1287 { "OSMesaGetProcAddress", (void *) OSMesaGetProcAddress }, 1288 { NULL, NULL } 1289}; 1290 1291GLAPI void * GLAPIENTRY 1292OSMesaGetProcAddress( const char *funcName ) 1293{ 1294 int i; 1295 for (i = 0; functions[i].Name; i++) { 1296 if (_mesa_strcmp(functions[i].Name, funcName) == 0) 1297 return (void *) functions[i].Address; 1298 } 1299 return (void *) _glapi_get_proc_address(funcName); 1300} 1301