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