osmesa.c revision 5bdc6fdebc0ab59a888fba15136eb4a0ee2790e1
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.5 4 * 5 * Copyright (C) 1999-2006 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] + 3 * (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] + 3 * (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/** 584 * Don't use _mesa_delete_renderbuffer since we can't free rb->Data. 585 */ 586static void 587osmesa_delete_renderbuffer(struct gl_renderbuffer *rb) 588{ 589 _mesa_free(rb); 590} 591 592 593/** 594 * Allocate renderbuffer storage. We don't actually allocate any storage 595 * since we're using a user-provided buffer. 596 * Just set up all the gl_renderbuffer methods. 597 */ 598static GLboolean 599osmesa_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, 600 GLenum internalFormat, GLuint width, GLuint height) 601{ 602 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 603 604 /* Note: we can ignoring internalFormat for "window-system" renderbuffers */ 605 (void) internalFormat; 606 607 if (osmesa->format == OSMESA_RGBA) { 608 rb->GetRow = get_row_RGBA; 609 rb->GetValues = get_values_RGBA; 610 rb->PutRow = put_row_RGBA; 611 rb->PutRowRGB = put_row_rgb_RGBA; 612 rb->PutMonoRow = put_mono_row_RGBA; 613 rb->PutValues = put_values_RGBA; 614 rb->PutMonoValues = put_mono_values_RGBA; 615 rb->RedBits = 616 rb->GreenBits = 617 rb->BlueBits = 618 rb->AlphaBits = 8 * sizeof(GLchan); 619 } 620 else if (osmesa->format == OSMESA_BGRA) { 621 rb->GetRow = get_row_BGRA; 622 rb->GetValues = get_values_BGRA; 623 rb->PutRow = put_row_BGRA; 624 rb->PutRowRGB = put_row_rgb_BGRA; 625 rb->PutMonoRow = put_mono_row_BGRA; 626 rb->PutValues = put_values_BGRA; 627 rb->PutMonoValues = put_mono_values_BGRA; 628 rb->RedBits = 629 rb->GreenBits = 630 rb->BlueBits = 631 rb->AlphaBits = 8 * sizeof(GLchan); 632 } 633 else if (osmesa->format == OSMESA_ARGB) { 634 rb->GetRow = get_row_ARGB; 635 rb->GetValues = get_values_ARGB; 636 rb->PutRow = put_row_ARGB; 637 rb->PutRowRGB = put_row_rgb_ARGB; 638 rb->PutMonoRow = put_mono_row_ARGB; 639 rb->PutValues = put_values_ARGB; 640 rb->PutMonoValues = put_mono_values_ARGB; 641 rb->RedBits = 642 rb->GreenBits = 643 rb->BlueBits = 644 rb->AlphaBits = 8 * sizeof(GLchan); 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 rb->RedBits = 655 rb->GreenBits = 656 rb->BlueBits = 8 * sizeof(GLchan); 657 } 658 else if (osmesa->format == OSMESA_BGR) { 659 rb->GetRow = get_row_BGR; 660 rb->GetValues = get_values_BGR; 661 rb->PutRow = put_row_BGR; 662 rb->PutRowRGB = put_row_rgb_BGR; 663 rb->PutMonoRow = put_mono_row_BGR; 664 rb->PutValues = put_values_BGR; 665 rb->PutMonoValues = put_mono_values_BGR; 666 rb->RedBits = 667 rb->GreenBits = 668 rb->BlueBits = 8 * sizeof(GLchan); 669 } 670#if CHAN_TYPE == GL_UNSIGNED_BYTE 671 else if (osmesa->format == OSMESA_RGB_565) { 672 rb->GetRow = get_row_RGB_565; 673 rb->GetValues = get_values_RGB_565; 674 rb->PutRow = put_row_RGB_565; 675 rb->PutRowRGB = put_row_rgb_RGB_565; 676 rb->PutMonoRow = put_mono_row_RGB_565; 677 rb->PutValues = put_values_RGB_565; 678 rb->PutMonoValues = put_mono_values_RGB_565; 679 rb->RedBits = 5; 680 rb->GreenBits = 6; 681 rb->BlueBits = 5; 682 } 683#endif 684 else if (osmesa->format == OSMESA_COLOR_INDEX) { 685 rb->GetRow = get_row_CI; 686 rb->GetValues = get_values_CI; 687 rb->PutRow = put_row_CI; 688 rb->PutMonoRow = put_mono_row_CI; 689 rb->PutValues = put_values_CI; 690 rb->PutMonoValues = put_mono_values_CI; 691 rb->IndexBits = 8; 692 } 693 else { 694 _mesa_problem(ctx, "bad pixel format in osmesa renderbuffer_storage"); 695 } 696 697 rb->Width = width; 698 rb->Height = height; 699 700 return GL_TRUE; 701} 702 703 704/** 705 * Allocate a new renderbuffer tpo describe the user-provided color buffer. 706 */ 707static struct gl_renderbuffer * 708new_osmesa_renderbuffer(GLenum format) 709{ 710 struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer); 711 if (rb) { 712 const GLuint name = 0; 713 _mesa_init_renderbuffer(rb, name); 714 715 rb->Delete = osmesa_delete_renderbuffer; 716 rb->AllocStorage = osmesa_renderbuffer_storage; 717 718 if (format == OSMESA_COLOR_INDEX) { 719 rb->_BaseFormat = GL_COLOR_INDEX; 720 rb->InternalFormat = GL_COLOR_INDEX; 721 rb->DataType = GL_UNSIGNED_BYTE; 722 } 723 else { 724 rb->_BaseFormat = GL_RGBA; 725 rb->InternalFormat = GL_RGBA; 726 rb->DataType = CHAN_TYPE; 727 } 728 } 729 return rb; 730} 731 732 733 734/**********************************************************************/ 735/***** Public Functions *****/ 736/**********************************************************************/ 737 738 739/* 740 * Create an Off-Screen Mesa rendering context. The only attribute needed is 741 * an RGBA vs Color-Index mode flag. 742 * 743 * Input: format - either GL_RGBA or GL_COLOR_INDEX 744 * sharelist - specifies another OSMesaContext with which to share 745 * display lists. NULL indicates no sharing. 746 * Return: an OSMesaContext or 0 if error 747 */ 748GLAPI OSMesaContext GLAPIENTRY 749OSMesaCreateContext( GLenum format, OSMesaContext sharelist ) 750{ 751 const GLint accumBits = (format == OSMESA_COLOR_INDEX) ? 0 : 16; 752 return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS, 753 8, accumBits, sharelist); 754} 755 756 757 758/* 759 * New in Mesa 3.5 760 * 761 * Create context and specify size of ancillary buffers. 762 */ 763GLAPI OSMesaContext GLAPIENTRY 764OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, 765 GLint accumBits, OSMesaContext sharelist ) 766{ 767 OSMesaContext osmesa; 768 struct dd_function_table functions; 769 GLint rind, gind, bind, aind; 770 GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0; 771 GLboolean rgbmode; 772 773 rind = gind = bind = aind = 0; 774 if (format==OSMESA_COLOR_INDEX) { 775 indexBits = 8; 776 rgbmode = GL_FALSE; 777 } 778 else if (format==OSMESA_RGBA) { 779 indexBits = 0; 780 redBits = CHAN_BITS; 781 greenBits = CHAN_BITS; 782 blueBits = CHAN_BITS; 783 alphaBits = CHAN_BITS; 784 rind = 0; 785 gind = 1; 786 bind = 2; 787 aind = 3; 788 rgbmode = GL_TRUE; 789 } 790 else if (format==OSMESA_BGRA) { 791 indexBits = 0; 792 redBits = CHAN_BITS; 793 greenBits = CHAN_BITS; 794 blueBits = CHAN_BITS; 795 alphaBits = CHAN_BITS; 796 bind = 0; 797 gind = 1; 798 rind = 2; 799 aind = 3; 800 rgbmode = GL_TRUE; 801 } 802 else if (format==OSMESA_ARGB) { 803 indexBits = 0; 804 redBits = CHAN_BITS; 805 greenBits = CHAN_BITS; 806 blueBits = CHAN_BITS; 807 alphaBits = CHAN_BITS; 808 aind = 0; 809 rind = 1; 810 gind = 2; 811 bind = 3; 812 rgbmode = GL_TRUE; 813 } 814 else if (format==OSMESA_RGB) { 815 indexBits = 0; 816 redBits = CHAN_BITS; 817 greenBits = CHAN_BITS; 818 blueBits = CHAN_BITS; 819 alphaBits = 0; 820 rind = 0; 821 gind = 1; 822 bind = 2; 823 rgbmode = GL_TRUE; 824 } 825 else if (format==OSMESA_BGR) { 826 indexBits = 0; 827 redBits = CHAN_BITS; 828 greenBits = CHAN_BITS; 829 blueBits = CHAN_BITS; 830 alphaBits = 0; 831 rind = 2; 832 gind = 1; 833 bind = 0; 834 rgbmode = GL_TRUE; 835 } 836#if CHAN_TYPE == GL_UNSIGNED_BYTE 837 else if (format==OSMESA_RGB_565) { 838 indexBits = 0; 839 redBits = 5; 840 greenBits = 6; 841 blueBits = 5; 842 alphaBits = 0; 843 rind = 0; /* not used */ 844 gind = 0; 845 bind = 0; 846 rgbmode = GL_TRUE; 847 } 848#endif 849 else { 850 return NULL; 851 } 852 853 osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context); 854 if (osmesa) { 855 osmesa->gl_visual = _mesa_create_visual( rgbmode, 856 GL_FALSE, /* double buffer */ 857 GL_FALSE, /* stereo */ 858 redBits, 859 greenBits, 860 blueBits, 861 alphaBits, 862 indexBits, 863 depthBits, 864 stencilBits, 865 accumBits, 866 accumBits, 867 accumBits, 868 alphaBits ? accumBits : 0, 869 1 /* num samples */ 870 ); 871 if (!osmesa->gl_visual) { 872 FREE(osmesa); 873 return NULL; 874 } 875 876 /* Initialize device driver function table */ 877 _mesa_init_driver_functions(&functions); 878 /* override with our functions */ 879 functions.GetString = get_string; 880 functions.UpdateState = osmesa_update_state; 881 functions.GetBufferSize = get_buffer_size; 882 883 if (!_mesa_initialize_context(&osmesa->mesa, 884 osmesa->gl_visual, 885 sharelist ? &sharelist->mesa 886 : (GLcontext *) NULL, 887 &functions, (void *) osmesa)) { 888 _mesa_destroy_visual( osmesa->gl_visual ); 889 FREE(osmesa); 890 return NULL; 891 } 892 893 _mesa_enable_sw_extensions(&(osmesa->mesa)); 894 _mesa_enable_1_3_extensions(&(osmesa->mesa)); 895 _mesa_enable_1_4_extensions(&(osmesa->mesa)); 896 _mesa_enable_1_5_extensions(&(osmesa->mesa)); 897 898 osmesa->gl_buffer = _mesa_create_framebuffer(osmesa->gl_visual); 899 if (!osmesa->gl_buffer) { 900 _mesa_destroy_visual( osmesa->gl_visual ); 901 _mesa_free_context_data( &osmesa->mesa ); 902 FREE(osmesa); 903 return NULL; 904 } 905 906 /* create front color buffer in user-provided memory (no back buffer) */ 907 _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, 908 new_osmesa_renderbuffer(format)); 909 _mesa_add_soft_renderbuffers(osmesa->gl_buffer, 910 GL_FALSE, /* color */ 911 osmesa->gl_visual->haveDepthBuffer, 912 osmesa->gl_visual->haveStencilBuffer, 913 osmesa->gl_visual->haveAccumBuffer, 914 GL_FALSE, /* alpha */ 915 GL_FALSE /* aux */ ); 916 917 osmesa->format = format; 918 osmesa->buffer = NULL; 919 osmesa->width = 0; 920 osmesa->height = 0; 921 osmesa->userRowLength = 0; 922 osmesa->rowlength = 0; 923 osmesa->yup = GL_TRUE; 924 osmesa->rInd = rind; 925 osmesa->gInd = gind; 926 osmesa->bInd = bind; 927 osmesa->aInd = aind; 928 929 /* Initialize the software rasterizer and helper modules. */ 930 { 931 GLcontext *ctx = &osmesa->mesa; 932 SWcontext *swrast; 933 TNLcontext *tnl; 934 935 if (!_swrast_CreateContext( ctx ) || 936 !_ac_CreateContext( ctx ) || 937 !_tnl_CreateContext( ctx ) || 938 !_swsetup_CreateContext( ctx )) { 939 _mesa_destroy_visual(osmesa->gl_visual); 940 _mesa_free_context_data(ctx); 941 _mesa_free(osmesa); 942 return NULL; 943 } 944 945 _swsetup_Wakeup( ctx ); 946 947 /* use default TCL pipeline */ 948 tnl = TNL_CONTEXT(ctx); 949 tnl->Driver.RunPipeline = _tnl_run_pipeline; 950 951 /* Extend the software rasterizer with our optimized line and triangle 952 * drawing functions. 953 */ 954 swrast = SWRAST_CONTEXT( ctx ); 955 swrast->choose_line = osmesa_choose_line; 956 swrast->choose_triangle = osmesa_choose_triangle; 957 } 958 } 959 return osmesa; 960} 961 962 963/* 964 * Destroy an Off-Screen Mesa rendering context. 965 * 966 * Input: ctx - the context to destroy 967 */ 968GLAPI void GLAPIENTRY 969OSMesaDestroyContext( OSMesaContext ctx ) 970{ 971 if (ctx) { 972 _swsetup_DestroyContext( &ctx->mesa ); 973 _tnl_DestroyContext( &ctx->mesa ); 974 _ac_DestroyContext( &ctx->mesa ); 975 _swrast_DestroyContext( &ctx->mesa ); 976 977 _mesa_destroy_visual( ctx->gl_visual ); 978 _mesa_destroy_framebuffer( ctx->gl_buffer ); 979 _mesa_free_context_data( &ctx->mesa ); 980 FREE( ctx ); 981 } 982} 983 984 985/* 986 * Recompute the values of the context's rowaddr array. 987 */ 988static void 989compute_row_addresses( OSMesaContext ctx ) 990{ 991 GLint bytesPerPixel, bytesPerRow, i; 992 GLubyte *origin = (GLubyte *) ctx->buffer; 993 994 if (ctx->format == OSMESA_COLOR_INDEX) { 995 /* CI mode */ 996 bytesPerPixel = 1 * sizeof(GLubyte); 997 } 998 else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) { 999 /* RGB mode */ 1000 bytesPerPixel = 3 * sizeof(GLchan); 1001 } 1002 else if (ctx->format == OSMESA_RGB_565) { 1003 /* 5/6/5 RGB pixel in 16 bits */ 1004 bytesPerPixel = 2; 1005 } 1006 else { 1007 /* RGBA mode */ 1008 bytesPerPixel = 4 * sizeof(GLchan); 1009 } 1010 1011 bytesPerRow = ctx->rowlength * bytesPerPixel; 1012 1013 if (ctx->yup) { 1014 /* Y=0 is bottom line of window */ 1015 for (i = 0; i < MAX_HEIGHT; i++) { 1016 ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow); 1017 } 1018 } 1019 else { 1020 /* Y=0 is top line of window */ 1021 for (i = 0; i < MAX_HEIGHT; i++) { 1022 GLint j = ctx->height - i - 1; 1023 ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow); 1024 } 1025 } 1026} 1027 1028 1029/* 1030 * Bind an OSMesaContext to an image buffer. The image buffer is just a 1031 * block of memory which the client provides. Its size must be at least 1032 * as large as width*height*sizeof(type). Its address should be a multiple 1033 * of 4 if using RGBA mode. 1034 * 1035 * Image data is stored in the order of glDrawPixels: row-major order 1036 * with the lower-left image pixel stored in the first array position 1037 * (ie. bottom-to-top). 1038 * 1039 * If the context's viewport hasn't been initialized yet, it will now be 1040 * initialized to (0,0,width,height). 1041 * 1042 * Input: ctx - the rendering context 1043 * buffer - the image buffer memory 1044 * type - data type for pixel components 1045 * Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5 1046 * are supported. But if Mesa's been compiled with CHAN_BITS==16 1047 * then type must be GL_UNSIGNED_SHORT. And if Mesa's been build 1048 * with CHAN_BITS==32 then type must be GL_FLOAT. 1049 * width, height - size of image buffer in pixels, at least 1 1050 * Return: GL_TRUE if success, GL_FALSE if error because of invalid ctx, 1051 * invalid buffer address, invalid type, width<1, height<1, 1052 * width>internal limit or height>internal limit. 1053 */ 1054GLAPI GLboolean GLAPIENTRY 1055OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type, 1056 GLsizei width, GLsizei height ) 1057{ 1058 if (!ctx || !buffer || 1059 width < 1 || height < 1 || 1060 width > MAX_WIDTH || height > MAX_HEIGHT) { 1061 return GL_FALSE; 1062 } 1063 1064 if (ctx->format == OSMESA_RGB_565) { 1065 if (type != GL_UNSIGNED_SHORT_5_6_5) 1066 return GL_FALSE; 1067 } 1068 else if (type != CHAN_TYPE) { 1069 return GL_FALSE; 1070 } 1071 1072 /* Need to set these before calling _mesa_make_current() since the first 1073 * time the context is bound, _mesa_make_current() will call our 1074 * get_buffer_size() function to initialize the viewport. These are the 1075 * values returned by get_buffer_size(): 1076 */ 1077 ctx->buffer = buffer; 1078 ctx->width = width; 1079 ctx->height = height; 1080 1081 osmesa_update_state( &ctx->mesa, 0 ); 1082 1083 /* Call this periodically to detect when the user has begun using 1084 * GL rendering from multiple threads. 1085 */ 1086 _glapi_check_multithread(); 1087 1088 _mesa_make_current( &ctx->mesa, ctx->gl_buffer, ctx->gl_buffer ); 1089 1090 if (ctx->userRowLength) 1091 ctx->rowlength = ctx->userRowLength; 1092 else 1093 ctx->rowlength = width; 1094 1095 compute_row_addresses( ctx ); 1096 1097 /* this will make ensure we recognize the new buffer size */ 1098 _mesa_resize_framebuffer(&ctx->mesa, ctx->gl_buffer, width, height); 1099 1100 return GL_TRUE; 1101} 1102 1103 1104 1105GLAPI OSMesaContext GLAPIENTRY 1106OSMesaGetCurrentContext( void ) 1107{ 1108 GLcontext *ctx = _mesa_get_current_context(); 1109 if (ctx) 1110 return (OSMesaContext) ctx; 1111 else 1112 return NULL; 1113} 1114 1115 1116 1117GLAPI void GLAPIENTRY 1118OSMesaPixelStore( GLint pname, GLint value ) 1119{ 1120 OSMesaContext osmesa = OSMesaGetCurrentContext(); 1121 1122 switch (pname) { 1123 case OSMESA_ROW_LENGTH: 1124 if (value<0) { 1125 _mesa_error( &osmesa->mesa, GL_INVALID_VALUE, 1126 "OSMesaPixelStore(value)" ); 1127 return; 1128 } 1129 osmesa->userRowLength = value; 1130 osmesa->rowlength = value ? value : osmesa->width; 1131 break; 1132 case OSMESA_Y_UP: 1133 osmesa->yup = value ? GL_TRUE : GL_FALSE; 1134 break; 1135 default: 1136 _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" ); 1137 return; 1138 } 1139 1140 compute_row_addresses( osmesa ); 1141} 1142 1143 1144GLAPI void GLAPIENTRY 1145OSMesaGetIntegerv( GLint pname, GLint *value ) 1146{ 1147 OSMesaContext osmesa = OSMesaGetCurrentContext(); 1148 1149 switch (pname) { 1150 case OSMESA_WIDTH: 1151 *value = osmesa->width; 1152 return; 1153 case OSMESA_HEIGHT: 1154 *value = osmesa->height; 1155 return; 1156 case OSMESA_FORMAT: 1157 *value = osmesa->format; 1158 return; 1159 case OSMESA_TYPE: 1160 *value = CHAN_TYPE; 1161 return; 1162 case OSMESA_ROW_LENGTH: 1163 *value = osmesa->userRowLength; 1164 return; 1165 case OSMESA_Y_UP: 1166 *value = osmesa->yup; 1167 return; 1168 case OSMESA_MAX_WIDTH: 1169 *value = MAX_WIDTH; 1170 return; 1171 case OSMESA_MAX_HEIGHT: 1172 *value = MAX_HEIGHT; 1173 return; 1174 default: 1175 _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)"); 1176 return; 1177 } 1178} 1179 1180/* 1181 * Return the depth buffer associated with an OSMesa context. 1182 * Input: c - the OSMesa context 1183 * Output: width, height - size of buffer in pixels 1184 * bytesPerValue - bytes per depth value (2 or 4) 1185 * buffer - pointer to depth buffer values 1186 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 1187 */ 1188GLAPI GLboolean GLAPIENTRY 1189OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height, 1190 GLint *bytesPerValue, void **buffer ) 1191{ 1192 struct gl_renderbuffer *rb = NULL; 1193 1194 if (c->gl_buffer) 1195 rb = c->gl_buffer->Attachment[BUFFER_DEPTH].Renderbuffer; 1196 1197 if (!rb || !rb->Data) { 1198 /*if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) {*/ 1199 *width = 0; 1200 *height = 0; 1201 *bytesPerValue = 0; 1202 *buffer = 0; 1203 return GL_FALSE; 1204 } 1205 else { 1206 *width = c->gl_buffer->Width; 1207 *height = c->gl_buffer->Height; 1208 if (c->gl_visual->depthBits <= 16) 1209 *bytesPerValue = sizeof(GLushort); 1210 else 1211 *bytesPerValue = sizeof(GLuint); 1212 *buffer = rb->Data; 1213 return GL_TRUE; 1214 } 1215} 1216 1217/* 1218 * Return the color buffer associated with an OSMesa context. 1219 * Input: c - the OSMesa context 1220 * Output: width, height - size of buffer in pixels 1221 * format - the pixel format (OSMESA_FORMAT) 1222 * buffer - pointer to color buffer values 1223 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 1224 */ 1225GLAPI GLboolean GLAPIENTRY 1226OSMesaGetColorBuffer( OSMesaContext c, GLint *width, 1227 GLint *height, GLint *format, void **buffer ) 1228{ 1229 if (!c->buffer) { 1230 *width = 0; 1231 *height = 0; 1232 *format = 0; 1233 *buffer = 0; 1234 return GL_FALSE; 1235 } 1236 else { 1237 *width = c->width; 1238 *height = c->height; 1239 *format = c->format; 1240 *buffer = c->buffer; 1241 return GL_TRUE; 1242 } 1243} 1244 1245 1246struct name_function 1247{ 1248 const char *Name; 1249 OSMESAproc Function; 1250}; 1251 1252static struct name_function functions[] = { 1253 { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext }, 1254 { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt }, 1255 { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext }, 1256 { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent }, 1257 { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext }, 1258 { "OSMesaPixelsStore", (OSMESAproc) OSMesaPixelStore }, 1259 { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv }, 1260 { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer }, 1261 { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer }, 1262 { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress }, 1263 { NULL, NULL } 1264}; 1265 1266 1267GLAPI OSMESAproc GLAPIENTRY 1268OSMesaGetProcAddress( const char *funcName ) 1269{ 1270 int i; 1271 for (i = 0; functions[i].Name; i++) { 1272 if (_mesa_strcmp(functions[i].Name, funcName) == 0) 1273 return functions[i].Function; 1274 } 1275 return _glapi_get_proc_address(funcName); 1276} 1277 1278 1279GLAPI void GLAPIENTRY 1280OSMesaColorClamp(GLboolean enable) 1281{ 1282 OSMesaContext osmesa = OSMesaGetCurrentContext(); 1283 1284 if (enable == GL_TRUE) { 1285 osmesa->mesa.Color.ClampFragmentColor = GL_TRUE; 1286 } 1287 else { 1288 osmesa->mesa.Color.ClampFragmentColor = GL_FIXED_ONLY_ARB; 1289 } 1290} 1291 1292 1293