osmesa.c revision 5dce1e5c420872ae096854841a9665f8d3d649fb
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, X, Y, 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, X, Y, 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, X, Y, R, G, B) \ 241 P[0] = R; P[1] = G; P[2] = B; P[3] = CHAN_MAX 242#define STORE_RGBA_PIXEL(P, X, Y, 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, X, Y, R, G, B) \ 257 P[2] = R; P[1] = G; P[0] = B; P[3] = CHAN_MAX 258#define STORE_RGBA_PIXEL(P, X, Y, 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, X, Y, R, G, B) \ 272 P[1] = R; P[2] = G; P[3] = B; P[0] = CHAN_MAX 273#define STORE_RGBA_PIXEL(P, X, Y, 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, X, Y, R, G, B) \ 287 P[0] = R; P[1] = G; P[2] = B 288#define STORE_RGBA_PIXEL(P, X, Y, 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, X, Y, R, G, B) \ 302 P[0] = B; P[1] = G; P[2] = R 303#define STORE_RGBA_PIXEL(P, X, Y, 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, X, Y, R, G, B) \ 318 *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) ) 319#define STORE_RGBA_PIXEL(P, X, Y, 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 const GLint accumBits = (format == GL_COLOR_INDEX) ? 0 : 16; 797 return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS, 798 8, accumBits, sharelist); 799} 800 801 802 803/* 804 * New in Mesa 3.5 805 * 806 * Create context and specify size of ancillary buffers. 807 */ 808GLAPI OSMesaContext GLAPIENTRY 809OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, 810 GLint accumBits, OSMesaContext sharelist ) 811{ 812 OSMesaContext osmesa; 813 GLint rshift, gshift, bshift, ashift; 814 GLint rind, gind, bind, aind; 815 GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0; 816 GLboolean rgbmode; 817 const GLuint i4 = 1; 818 const GLubyte *i1 = (GLubyte *) &i4; 819 const GLint little_endian = *i1; 820 821 rind = gind = bind = aind = 0; 822 if (format==OSMESA_COLOR_INDEX) { 823 indexBits = 8; 824 rshift = gshift = bshift = ashift = 0; 825 rgbmode = GL_FALSE; 826 } 827 else if (format==OSMESA_RGBA) { 828 indexBits = 0; 829 redBits = CHAN_BITS; 830 greenBits = CHAN_BITS; 831 blueBits = CHAN_BITS; 832 alphaBits = CHAN_BITS; 833 rind = 0; 834 gind = 1; 835 bind = 2; 836 aind = 3; 837 if (little_endian) { 838 rshift = 0; 839 gshift = 8; 840 bshift = 16; 841 ashift = 24; 842 } 843 else { 844 rshift = 24; 845 gshift = 16; 846 bshift = 8; 847 ashift = 0; 848 } 849 rgbmode = GL_TRUE; 850 } 851 else if (format==OSMESA_BGRA) { 852 indexBits = 0; 853 redBits = CHAN_BITS; 854 greenBits = CHAN_BITS; 855 blueBits = CHAN_BITS; 856 alphaBits = CHAN_BITS; 857 bind = 0; 858 gind = 1; 859 rind = 2; 860 aind = 3; 861 if (little_endian) { 862 bshift = 0; 863 gshift = 8; 864 rshift = 16; 865 ashift = 24; 866 } 867 else { 868 bshift = 24; 869 gshift = 16; 870 rshift = 8; 871 ashift = 0; 872 } 873 rgbmode = GL_TRUE; 874 } 875 else if (format==OSMESA_ARGB) { 876 indexBits = 0; 877 redBits = CHAN_BITS; 878 greenBits = CHAN_BITS; 879 blueBits = CHAN_BITS; 880 alphaBits = CHAN_BITS; 881 aind = 0; 882 rind = 1; 883 gind = 2; 884 bind = 3; 885 if (little_endian) { 886 ashift = 0; 887 rshift = 8; 888 gshift = 16; 889 bshift = 24; 890 } 891 else { 892 ashift = 24; 893 rshift = 16; 894 gshift = 8; 895 bshift = 0; 896 } 897 rgbmode = GL_TRUE; 898 } 899 else if (format==OSMESA_RGB) { 900 indexBits = 0; 901 redBits = CHAN_BITS; 902 greenBits = CHAN_BITS; 903 blueBits = CHAN_BITS; 904 alphaBits = 0; 905 bshift = 0; 906 gshift = 8; 907 rshift = 16; 908 ashift = 24; 909 rind = 0; 910 gind = 1; 911 bind = 2; 912 rgbmode = GL_TRUE; 913 } 914 else if (format==OSMESA_BGR) { 915 indexBits = 0; 916 redBits = CHAN_BITS; 917 greenBits = CHAN_BITS; 918 blueBits = CHAN_BITS; 919 alphaBits = 0; 920 bshift = 0; 921 gshift = 8; 922 rshift = 16; 923 ashift = 24; 924 rind = 2; 925 gind = 1; 926 bind = 0; 927 rgbmode = GL_TRUE; 928 } 929#if CHAN_TYPE == GL_UNSIGNED_BYTE 930 else if (format==OSMESA_RGB_565) { 931 indexBits = 0; 932 redBits = 5; 933 greenBits = 6; 934 blueBits = 5; 935 alphaBits = 0; 936 rshift = 11; 937 gshift = 5; 938 bshift = 0; 939 ashift = 0; 940 rind = 0; /* not used */ 941 gind = 0; 942 bind = 0; 943 rgbmode = GL_TRUE; 944 } 945#endif 946 else { 947 return NULL; 948 } 949 950 951 osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context); 952 if (osmesa) { 953 osmesa->gl_visual = _mesa_create_visual( rgbmode, 954 GL_FALSE, /* double buffer */ 955 GL_FALSE, /* stereo */ 956 redBits, 957 greenBits, 958 blueBits, 959 alphaBits, 960 indexBits, 961 depthBits, 962 stencilBits, 963 accumBits, 964 accumBits, 965 accumBits, 966 alphaBits ? accumBits : 0, 967 1 /* num samples */ 968 ); 969 if (!osmesa->gl_visual) { 970 FREE(osmesa); 971 return NULL; 972 } 973 974 /* Setup these pointers here since they're using for making the default 975 * and proxy texture objects. Actually, we don't really need to do 976 * this since we're using the default fallback functions which 977 * _mesa_initialize_context() would plug in if needed. 978 */ 979 osmesa->mesa.Driver.NewTextureObject = _mesa_new_texture_object; 980 osmesa->mesa.Driver.DeleteTexture = _mesa_delete_texture_object; 981 982 if (!_mesa_initialize_context(&osmesa->mesa, 983 osmesa->gl_visual, 984 sharelist ? &sharelist->mesa 985 : (GLcontext *) NULL, 986 (void *) osmesa, 987 GL_FALSE)) { 988 _mesa_destroy_visual( osmesa->gl_visual ); 989 FREE(osmesa); 990 return NULL; 991 } 992 993 _mesa_enable_sw_extensions(&(osmesa->mesa)); 994 _mesa_enable_1_3_extensions(&(osmesa->mesa)); 995 _mesa_enable_1_4_extensions(&(osmesa->mesa)); 996 _mesa_enable_1_5_extensions(&(osmesa->mesa)); 997 998 osmesa->gl_buffer = _mesa_create_framebuffer( osmesa->gl_visual, 999 (GLboolean) ( osmesa->gl_visual->depthBits > 0 ), 1000 (GLboolean) ( osmesa->gl_visual->stencilBits > 0 ), 1001 (GLboolean) ( osmesa->gl_visual->accumRedBits > 0 ), 1002 GL_FALSE /* s/w alpha */ ); 1003 1004 if (!osmesa->gl_buffer) { 1005 _mesa_destroy_visual( osmesa->gl_visual ); 1006 _mesa_free_context_data( &osmesa->mesa ); 1007 FREE(osmesa); 1008 return NULL; 1009 } 1010 osmesa->format = format; 1011 osmesa->buffer = NULL; 1012 osmesa->width = 0; 1013 osmesa->height = 0; 1014 osmesa->userRowLength = 0; 1015 osmesa->rowlength = 0; 1016 osmesa->yup = GL_TRUE; 1017 osmesa->rshift = rshift; 1018 osmesa->gshift = gshift; 1019 osmesa->bshift = bshift; 1020 osmesa->ashift = ashift; 1021 osmesa->rInd = rind; 1022 osmesa->gInd = gind; 1023 osmesa->bInd = bind; 1024 osmesa->aInd = aind; 1025 1026 /* Initialize the software rasterizer and helper modules. */ 1027 { 1028 GLcontext *ctx = &osmesa->mesa; 1029 1030 _swrast_CreateContext( ctx ); 1031 _ac_CreateContext( ctx ); 1032 _tnl_CreateContext( ctx ); 1033 _swsetup_CreateContext( ctx ); 1034 1035 _swsetup_Wakeup( ctx ); 1036 hook_in_driver_functions( ctx ); 1037 } 1038 } 1039 return osmesa; 1040} 1041 1042 1043/* 1044 * Destroy an Off-Screen Mesa rendering context. 1045 * 1046 * Input: ctx - the context to destroy 1047 */ 1048GLAPI void GLAPIENTRY 1049OSMesaDestroyContext( OSMesaContext ctx ) 1050{ 1051 if (ctx) { 1052 _swsetup_DestroyContext( &ctx->mesa ); 1053 _tnl_DestroyContext( &ctx->mesa ); 1054 _ac_DestroyContext( &ctx->mesa ); 1055 _swrast_DestroyContext( &ctx->mesa ); 1056 1057 _mesa_destroy_visual( ctx->gl_visual ); 1058 _mesa_destroy_framebuffer( ctx->gl_buffer ); 1059 _mesa_free_context_data( &ctx->mesa ); 1060 FREE( ctx ); 1061 } 1062} 1063 1064 1065/* 1066 * Recompute the values of the context's rowaddr array. 1067 */ 1068static void 1069compute_row_addresses( OSMesaContext ctx ) 1070{ 1071 GLint bytesPerPixel, bytesPerRow, i; 1072 GLubyte *origin = (GLubyte *) ctx->buffer; 1073 1074 if (ctx->format == OSMESA_COLOR_INDEX) { 1075 /* CI mode */ 1076 bytesPerPixel = 1 * sizeof(GLchan); 1077 } 1078 else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) { 1079 /* RGB mode */ 1080 bytesPerPixel = 3 * sizeof(GLchan); 1081 } 1082 else if (ctx->format == OSMESA_RGB_565) { 1083 /* 5/6/5 RGB pixel in 16 bits */ 1084 bytesPerPixel = 2; 1085 } 1086 else { 1087 /* RGBA mode */ 1088 bytesPerPixel = 4 * sizeof(GLchan); 1089 } 1090 1091 bytesPerRow = ctx->rowlength * bytesPerPixel; 1092 1093 if (ctx->yup) { 1094 /* Y=0 is bottom line of window */ 1095 for (i = 0; i < MAX_HEIGHT; i++) { 1096 ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow); 1097 } 1098 } 1099 else { 1100 /* Y=0 is top line of window */ 1101 for (i = 0; i < MAX_HEIGHT; i++) { 1102 GLint j = ctx->height - i - 1; 1103 ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow); 1104 } 1105 } 1106} 1107 1108 1109/* 1110 * Bind an OSMesaContext to an image buffer. The image buffer is just a 1111 * block of memory which the client provides. Its size must be at least 1112 * as large as width*height*sizeof(type). Its address should be a multiple 1113 * of 4 if using RGBA mode. 1114 * 1115 * Image data is stored in the order of glDrawPixels: row-major order 1116 * with the lower-left image pixel stored in the first array position 1117 * (ie. bottom-to-top). 1118 * 1119 * If the context's viewport hasn't been initialized yet, it will now be 1120 * initialized to (0,0,width,height). 1121 * 1122 * Input: ctx - the rendering context 1123 * buffer - the image buffer memory 1124 * type - data type for pixel components 1125 * Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5 1126 * are supported. But if Mesa's been compiled with CHAN_BITS==16 1127 * then type must be GL_UNSIGNED_SHORT. And if Mesa's been build 1128 * with CHAN_BITS==32 then type must be GL_FLOAT. 1129 * width, height - size of image buffer in pixels, at least 1 1130 * Return: GL_TRUE if success, GL_FALSE if error because of invalid ctx, 1131 * invalid buffer address, invalid type, width<1, height<1, 1132 * width>internal limit or height>internal limit. 1133 */ 1134GLAPI GLboolean GLAPIENTRY 1135OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type, 1136 GLsizei width, GLsizei height ) 1137{ 1138 if (!ctx || !buffer || 1139 width < 1 || height < 1 || 1140 width > MAX_WIDTH || height > MAX_HEIGHT) { 1141 return GL_FALSE; 1142 } 1143 1144 if (ctx->format == OSMESA_RGB_565) { 1145 if (type != GL_UNSIGNED_SHORT_5_6_5) 1146 return GL_FALSE; 1147 } 1148 else if (type != CHAN_TYPE) { 1149 return GL_FALSE; 1150 } 1151 1152 osmesa_update_state( &ctx->mesa, 0 ); 1153 _mesa_make_current( &ctx->mesa, ctx->gl_buffer ); 1154 1155 ctx->buffer = buffer; 1156 ctx->width = width; 1157 ctx->height = height; 1158 if (ctx->userRowLength) 1159 ctx->rowlength = ctx->userRowLength; 1160 else 1161 ctx->rowlength = width; 1162 1163 compute_row_addresses( ctx ); 1164 1165 /* init viewport */ 1166 if (ctx->mesa.Viewport.Width == 0) { 1167 /* initialize viewport and scissor box to buffer size */ 1168 _mesa_Viewport( 0, 0, width, height ); 1169 ctx->mesa.Scissor.Width = width; 1170 ctx->mesa.Scissor.Height = height; 1171 } 1172 else { 1173 /* this will make ensure we recognize the new buffer size */ 1174 _mesa_ResizeBuffersMESA(); 1175 } 1176 1177 /* Added by Gerk Huisma: */ 1178 _tnl_MakeCurrent( &ctx->mesa, ctx->mesa.DrawBuffer, 1179 ctx->mesa.ReadBuffer ); 1180 1181 return GL_TRUE; 1182} 1183 1184 1185 1186GLAPI OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void ) 1187{ 1188 GLcontext *ctx = _mesa_get_current_context(); 1189 if (ctx) 1190 return (OSMesaContext) ctx; 1191 else 1192 return NULL; 1193} 1194 1195 1196 1197GLAPI void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value ) 1198{ 1199 OSMesaContext osmesa = OSMesaGetCurrentContext(); 1200 1201 switch (pname) { 1202 case OSMESA_ROW_LENGTH: 1203 if (value<0) { 1204 _mesa_error( &osmesa->mesa, GL_INVALID_VALUE, 1205 "OSMesaPixelStore(value)" ); 1206 return; 1207 } 1208 osmesa->userRowLength = value; 1209 osmesa->rowlength = value ? value : osmesa->width; 1210 break; 1211 case OSMESA_Y_UP: 1212 osmesa->yup = value ? GL_TRUE : GL_FALSE; 1213 break; 1214 default: 1215 _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" ); 1216 return; 1217 } 1218 1219 compute_row_addresses( osmesa ); 1220} 1221 1222 1223GLAPI void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value ) 1224{ 1225 OSMesaContext osmesa = OSMesaGetCurrentContext(); 1226 1227 switch (pname) { 1228 case OSMESA_WIDTH: 1229 *value = osmesa->width; 1230 return; 1231 case OSMESA_HEIGHT: 1232 *value = osmesa->height; 1233 return; 1234 case OSMESA_FORMAT: 1235 *value = osmesa->format; 1236 return; 1237 case OSMESA_TYPE: 1238 *value = CHAN_TYPE; 1239 return; 1240 case OSMESA_ROW_LENGTH: 1241 *value = osmesa->userRowLength; 1242 return; 1243 case OSMESA_Y_UP: 1244 *value = osmesa->yup; 1245 return; 1246 case OSMESA_MAX_WIDTH: 1247 *value = MAX_WIDTH; 1248 return; 1249 case OSMESA_MAX_HEIGHT: 1250 *value = MAX_HEIGHT; 1251 return; 1252 default: 1253 _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)"); 1254 return; 1255 } 1256} 1257 1258/* 1259 * Return the depth buffer associated with an OSMesa context. 1260 * Input: c - the OSMesa context 1261 * Output: width, height - size of buffer in pixels 1262 * bytesPerValue - bytes per depth value (2 or 4) 1263 * buffer - pointer to depth buffer values 1264 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 1265 */ 1266GLAPI GLboolean GLAPIENTRY 1267OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height, 1268 GLint *bytesPerValue, void **buffer ) 1269{ 1270 if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) { 1271 *width = 0; 1272 *height = 0; 1273 *bytesPerValue = 0; 1274 *buffer = 0; 1275 return GL_FALSE; 1276 } 1277 else { 1278 *width = c->gl_buffer->Width; 1279 *height = c->gl_buffer->Height; 1280 if (c->gl_visual->depthBits <= 16) 1281 *bytesPerValue = sizeof(GLushort); 1282 else 1283 *bytesPerValue = sizeof(GLuint); 1284 *buffer = c->gl_buffer->DepthBuffer; 1285 return GL_TRUE; 1286 } 1287} 1288 1289/* 1290 * Return the color buffer associated with an OSMesa context. 1291 * Input: c - the OSMesa context 1292 * Output: width, height - size of buffer in pixels 1293 * format - the pixel format (OSMESA_FORMAT) 1294 * buffer - pointer to color buffer values 1295 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 1296 */ 1297GLAPI GLboolean GLAPIENTRY 1298OSMesaGetColorBuffer( OSMesaContext c, GLint *width, 1299 GLint *height, GLint *format, void **buffer ) 1300{ 1301 if (!c->buffer) { 1302 *width = 0; 1303 *height = 0; 1304 *format = 0; 1305 *buffer = 0; 1306 return GL_FALSE; 1307 } 1308 else { 1309 *width = c->width; 1310 *height = c->height; 1311 *format = c->format; 1312 *buffer = c->buffer; 1313 return GL_TRUE; 1314 } 1315} 1316 1317 1318 1319struct name_address { 1320 const char *Name; 1321 GLvoid *Address; 1322}; 1323 1324static struct name_address functions[] = { 1325 { "OSMesaCreateContext", (void *) OSMesaCreateContext }, 1326 { "OSMesaCreateContextExt", (void *) OSMesaCreateContextExt }, 1327 { "OSMesaDestroyContext", (void *) OSMesaDestroyContext }, 1328 { "OSMesaMakeCurrent", (void *) OSMesaMakeCurrent }, 1329 { "OSMesaGetCurrentContext", (void *) OSMesaGetCurrentContext }, 1330 { "OSMesaPixelsStore", (void *) OSMesaPixelStore }, 1331 { "OSMesaGetIntegerv", (void *) OSMesaGetIntegerv }, 1332 { "OSMesaGetDepthBuffer", (void *) OSMesaGetDepthBuffer }, 1333 { "OSMesaGetColorBuffer", (void *) OSMesaGetColorBuffer }, 1334 { "OSMesaGetProcAddress", (void *) OSMesaGetProcAddress }, 1335 { NULL, NULL } 1336}; 1337 1338GLAPI void * GLAPIENTRY 1339OSMesaGetProcAddress( const char *funcName ) 1340{ 1341 int i; 1342 for (i = 0; functions[i].Name; i++) { 1343 if (_mesa_strcmp(functions[i].Name, funcName) == 0) 1344 return (void *) functions[i].Address; 1345 } 1346 return (void *) _glapi_get_proc_address(funcName); 1347} 1348