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