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