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