osmesa.c revision 9b990c81c0f3b80988d159dd054ef3c0637d2d9e
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.5.3 4 * 5 * Copyright (C) 1999-2007 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 "main/glheader.h" 37#include "GL/osmesa.h" 38#include "main/context.h" 39#include "main/extensions.h" 40#include "main/formats.h" 41#include "main/framebuffer.h" 42#include "main/imports.h" 43#include "main/mtypes.h" 44#include "main/renderbuffer.h" 45#include "swrast/swrast.h" 46#include "swrast_setup/swrast_setup.h" 47#include "swrast/s_context.h" 48#include "swrast/s_lines.h" 49#include "swrast/s_triangle.h" 50#include "tnl/tnl.h" 51#include "tnl/t_context.h" 52#include "tnl/t_pipeline.h" 53#include "drivers/common/driverfuncs.h" 54#include "drivers/common/meta.h" 55#include "vbo/vbo.h" 56 57 58 59/** 60 * OSMesa rendering context, derived from core Mesa GLcontext. 61 */ 62struct osmesa_context 63{ 64 GLcontext mesa; /*< Base class - this must be first */ 65 GLvisual *gl_visual; /*< Describes the buffers */ 66 struct gl_renderbuffer *rb; /*< The user's colorbuffer */ 67 GLframebuffer *gl_buffer; /*< The framebuffer, containing user's rb */ 68 GLenum format; /*< User-specified context format */ 69 GLint userRowLength; /*< user-specified number of pixels per row */ 70 GLint rInd, gInd, bInd, aInd;/*< index offsets for RGBA formats */ 71 GLvoid *rowaddr[MAX_HEIGHT]; /*< address of first pixel in each image row */ 72 GLboolean yup; /*< TRUE -> Y increases upward */ 73 /*< FALSE -> Y increases downward */ 74}; 75 76 77static INLINE OSMesaContext 78OSMESA_CONTEXT(GLcontext *ctx) 79{ 80 /* Just cast, since we're using structure containment */ 81 return (OSMesaContext) ctx; 82} 83 84 85/**********************************************************************/ 86/*** Private Device Driver Functions ***/ 87/**********************************************************************/ 88 89 90static const GLubyte * 91get_string( GLcontext *ctx, GLenum name ) 92{ 93 (void) ctx; 94 switch (name) { 95 case GL_RENDERER: 96#if CHAN_BITS == 32 97 return (const GLubyte *) "Mesa OffScreen32"; 98#elif CHAN_BITS == 16 99 return (const GLubyte *) "Mesa OffScreen16"; 100#else 101 return (const GLubyte *) "Mesa OffScreen"; 102#endif 103 default: 104 return NULL; 105 } 106} 107 108 109static void 110osmesa_update_state( GLcontext *ctx, GLuint new_state ) 111{ 112 /* easy - just propogate */ 113 _swrast_InvalidateState( ctx, new_state ); 114 _swsetup_InvalidateState( ctx, new_state ); 115 _tnl_InvalidateState( ctx, new_state ); 116 _vbo_InvalidateState( ctx, new_state ); 117} 118 119 120 121/**********************************************************************/ 122/***** Read/write spans/arrays of pixels *****/ 123/**********************************************************************/ 124 125/* 8-bit RGBA */ 126#define NAME(PREFIX) PREFIX##_RGBA8 127#define RB_TYPE GLubyte 128#define SPAN_VARS \ 129 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 130#define INIT_PIXEL_PTR(P, X, Y) \ 131 GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X) 132#define INC_PIXEL_PTR(P) P += 4 133#define STORE_PIXEL(DST, X, Y, VALUE) \ 134 DST[0] = VALUE[RCOMP]; \ 135 DST[1] = VALUE[GCOMP]; \ 136 DST[2] = VALUE[BCOMP]; \ 137 DST[3] = VALUE[ACOMP] 138#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ 139 DST[0] = VALUE[RCOMP]; \ 140 DST[1] = VALUE[GCOMP]; \ 141 DST[2] = VALUE[BCOMP]; \ 142 DST[3] = 255 143#define FETCH_PIXEL(DST, SRC) \ 144 DST[RCOMP] = SRC[0]; \ 145 DST[GCOMP] = SRC[1]; \ 146 DST[BCOMP] = SRC[2]; \ 147 DST[ACOMP] = SRC[3] 148#include "swrast/s_spantemp.h" 149 150/* 16-bit RGBA */ 151#define NAME(PREFIX) PREFIX##_RGBA16 152#define RB_TYPE GLushort 153#define SPAN_VARS \ 154 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 155#define INIT_PIXEL_PTR(P, X, Y) \ 156 GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X) 157#define INC_PIXEL_PTR(P) P += 4 158#define STORE_PIXEL(DST, X, Y, VALUE) \ 159 DST[0] = VALUE[RCOMP]; \ 160 DST[1] = VALUE[GCOMP]; \ 161 DST[2] = VALUE[BCOMP]; \ 162 DST[3] = VALUE[ACOMP] 163#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ 164 DST[0] = VALUE[RCOMP]; \ 165 DST[1] = VALUE[GCOMP]; \ 166 DST[2] = VALUE[BCOMP]; \ 167 DST[3] = 65535 168#define FETCH_PIXEL(DST, SRC) \ 169 DST[RCOMP] = SRC[0]; \ 170 DST[GCOMP] = SRC[1]; \ 171 DST[BCOMP] = SRC[2]; \ 172 DST[ACOMP] = SRC[3] 173#include "swrast/s_spantemp.h" 174 175/* 32-bit RGBA */ 176#define NAME(PREFIX) PREFIX##_RGBA32 177#define RB_TYPE GLfloat 178#define SPAN_VARS \ 179 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 180#define INIT_PIXEL_PTR(P, X, Y) \ 181 GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X) 182#define INC_PIXEL_PTR(P) P += 4 183#define STORE_PIXEL(DST, X, Y, VALUE) \ 184 DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \ 185 DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \ 186 DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \ 187 DST[3] = CLAMP((VALUE[ACOMP]), 0.0F, 1.0F) 188#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ 189 DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \ 190 DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \ 191 DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \ 192 DST[3] = 1.0F 193#define FETCH_PIXEL(DST, SRC) \ 194 DST[RCOMP] = SRC[0]; \ 195 DST[GCOMP] = SRC[1]; \ 196 DST[BCOMP] = SRC[2]; \ 197 DST[ACOMP] = SRC[3] 198#include "swrast/s_spantemp.h" 199 200 201/* 8-bit BGRA */ 202#define NAME(PREFIX) PREFIX##_BGRA8 203#define RB_TYPE GLubyte 204#define SPAN_VARS \ 205 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 206#define INIT_PIXEL_PTR(P, X, Y) \ 207 GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X) 208#define INC_PIXEL_PTR(P) P += 4 209#define STORE_PIXEL(DST, X, Y, VALUE) \ 210 DST[2] = VALUE[RCOMP]; \ 211 DST[1] = VALUE[GCOMP]; \ 212 DST[0] = VALUE[BCOMP]; \ 213 DST[3] = VALUE[ACOMP] 214#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ 215 DST[2] = VALUE[RCOMP]; \ 216 DST[1] = VALUE[GCOMP]; \ 217 DST[0] = VALUE[BCOMP]; \ 218 DST[3] = 255 219#define FETCH_PIXEL(DST, SRC) \ 220 DST[RCOMP] = SRC[2]; \ 221 DST[GCOMP] = SRC[1]; \ 222 DST[BCOMP] = SRC[0]; \ 223 DST[ACOMP] = SRC[3] 224#include "swrast/s_spantemp.h" 225 226/* 16-bit BGRA */ 227#define NAME(PREFIX) PREFIX##_BGRA16 228#define RB_TYPE GLushort 229#define SPAN_VARS \ 230 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 231#define INIT_PIXEL_PTR(P, X, Y) \ 232 GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X) 233#define INC_PIXEL_PTR(P) P += 4 234#define STORE_PIXEL(DST, X, Y, VALUE) \ 235 DST[2] = VALUE[RCOMP]; \ 236 DST[1] = VALUE[GCOMP]; \ 237 DST[0] = VALUE[BCOMP]; \ 238 DST[3] = VALUE[ACOMP] 239#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ 240 DST[2] = VALUE[RCOMP]; \ 241 DST[1] = VALUE[GCOMP]; \ 242 DST[0] = VALUE[BCOMP]; \ 243 DST[3] = 65535 244#define FETCH_PIXEL(DST, SRC) \ 245 DST[RCOMP] = SRC[2]; \ 246 DST[GCOMP] = SRC[1]; \ 247 DST[BCOMP] = SRC[0]; \ 248 DST[ACOMP] = SRC[3] 249#include "swrast/s_spantemp.h" 250 251/* 32-bit BGRA */ 252#define NAME(PREFIX) PREFIX##_BGRA32 253#define RB_TYPE GLfloat 254#define SPAN_VARS \ 255 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 256#define INIT_PIXEL_PTR(P, X, Y) \ 257 GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X) 258#define INC_PIXEL_PTR(P) P += 4 259#define STORE_PIXEL(DST, X, Y, VALUE) \ 260 DST[2] = VALUE[RCOMP]; \ 261 DST[1] = VALUE[GCOMP]; \ 262 DST[0] = VALUE[BCOMP]; \ 263 DST[3] = VALUE[ACOMP] 264#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ 265 DST[2] = VALUE[RCOMP]; \ 266 DST[1] = VALUE[GCOMP]; \ 267 DST[0] = VALUE[BCOMP]; \ 268 DST[3] = 1.0F 269#define FETCH_PIXEL(DST, SRC) \ 270 DST[RCOMP] = SRC[2]; \ 271 DST[GCOMP] = SRC[1]; \ 272 DST[BCOMP] = SRC[0]; \ 273 DST[ACOMP] = SRC[3] 274#include "swrast/s_spantemp.h" 275 276 277/* 8-bit ARGB */ 278#define NAME(PREFIX) PREFIX##_ARGB8 279#define RB_TYPE GLubyte 280#define SPAN_VARS \ 281 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 282#define INIT_PIXEL_PTR(P, X, Y) \ 283 GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 4 * (X) 284#define INC_PIXEL_PTR(P) P += 4 285#define STORE_PIXEL(DST, X, Y, VALUE) \ 286 DST[1] = VALUE[RCOMP]; \ 287 DST[2] = VALUE[GCOMP]; \ 288 DST[3] = VALUE[BCOMP]; \ 289 DST[0] = VALUE[ACOMP] 290#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ 291 DST[1] = VALUE[RCOMP]; \ 292 DST[2] = VALUE[GCOMP]; \ 293 DST[3] = VALUE[BCOMP]; \ 294 DST[0] = 255 295#define FETCH_PIXEL(DST, SRC) \ 296 DST[RCOMP] = SRC[1]; \ 297 DST[GCOMP] = SRC[2]; \ 298 DST[BCOMP] = SRC[3]; \ 299 DST[ACOMP] = SRC[0] 300#include "swrast/s_spantemp.h" 301 302/* 16-bit ARGB */ 303#define NAME(PREFIX) PREFIX##_ARGB16 304#define RB_TYPE GLushort 305#define SPAN_VARS \ 306 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 307#define INIT_PIXEL_PTR(P, X, Y) \ 308 GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 4 * (X) 309#define INC_PIXEL_PTR(P) P += 4 310#define STORE_PIXEL(DST, X, Y, VALUE) \ 311 DST[1] = VALUE[RCOMP]; \ 312 DST[2] = VALUE[GCOMP]; \ 313 DST[3] = VALUE[BCOMP]; \ 314 DST[0] = VALUE[ACOMP] 315#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ 316 DST[1] = VALUE[RCOMP]; \ 317 DST[2] = VALUE[GCOMP]; \ 318 DST[3] = VALUE[BCOMP]; \ 319 DST[0] = 65535 320#define FETCH_PIXEL(DST, SRC) \ 321 DST[RCOMP] = SRC[1]; \ 322 DST[GCOMP] = SRC[2]; \ 323 DST[BCOMP] = SRC[3]; \ 324 DST[ACOMP] = SRC[0] 325#include "swrast/s_spantemp.h" 326 327/* 32-bit ARGB */ 328#define NAME(PREFIX) PREFIX##_ARGB32 329#define RB_TYPE GLfloat 330#define SPAN_VARS \ 331 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 332#define INIT_PIXEL_PTR(P, X, Y) \ 333 GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 4 * (X) 334#define INC_PIXEL_PTR(P) P += 4 335#define STORE_PIXEL(DST, X, Y, VALUE) \ 336 DST[1] = VALUE[RCOMP]; \ 337 DST[2] = VALUE[GCOMP]; \ 338 DST[3] = VALUE[BCOMP]; \ 339 DST[0] = VALUE[ACOMP] 340#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \ 341 DST[1] = VALUE[RCOMP]; \ 342 DST[2] = VALUE[GCOMP]; \ 343 DST[3] = VALUE[BCOMP]; \ 344 DST[0] = 1.0F 345#define FETCH_PIXEL(DST, SRC) \ 346 DST[RCOMP] = SRC[1]; \ 347 DST[GCOMP] = SRC[2]; \ 348 DST[BCOMP] = SRC[3]; \ 349 DST[ACOMP] = SRC[0] 350#include "swrast/s_spantemp.h" 351 352 353/* 8-bit RGB */ 354#define NAME(PREFIX) PREFIX##_RGB8 355#define RB_TYPE GLubyte 356#define SPAN_VARS \ 357 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 358#define INIT_PIXEL_PTR(P, X, Y) \ 359 GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 3 * (X) 360#define INC_PIXEL_PTR(P) P += 3 361#define STORE_PIXEL(DST, X, Y, VALUE) \ 362 DST[0] = VALUE[RCOMP]; \ 363 DST[1] = VALUE[GCOMP]; \ 364 DST[2] = VALUE[BCOMP] 365#define FETCH_PIXEL(DST, SRC) \ 366 DST[RCOMP] = SRC[0]; \ 367 DST[GCOMP] = SRC[1]; \ 368 DST[BCOMP] = SRC[2]; \ 369 DST[ACOMP] = 255 370#include "swrast/s_spantemp.h" 371 372/* 16-bit RGB */ 373#define NAME(PREFIX) PREFIX##_RGB16 374#define RB_TYPE GLushort 375#define SPAN_VARS \ 376 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 377#define INIT_PIXEL_PTR(P, X, Y) \ 378 GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 3 * (X) 379#define INC_PIXEL_PTR(P) P += 3 380#define STORE_PIXEL(DST, X, Y, VALUE) \ 381 DST[0] = VALUE[RCOMP]; \ 382 DST[1] = VALUE[GCOMP]; \ 383 DST[2] = VALUE[BCOMP] 384#define FETCH_PIXEL(DST, SRC) \ 385 DST[RCOMP] = SRC[0]; \ 386 DST[GCOMP] = SRC[1]; \ 387 DST[BCOMP] = SRC[2]; \ 388 DST[ACOMP] = 65535U 389#include "swrast/s_spantemp.h" 390 391/* 32-bit RGB */ 392#define NAME(PREFIX) PREFIX##_RGB32 393#define RB_TYPE GLfloat 394#define SPAN_VARS \ 395 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 396#define INIT_PIXEL_PTR(P, X, Y) \ 397 GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 3 * (X) 398#define INC_PIXEL_PTR(P) P += 3 399#define STORE_PIXEL(DST, X, Y, VALUE) \ 400 DST[0] = VALUE[RCOMP]; \ 401 DST[1] = VALUE[GCOMP]; \ 402 DST[2] = VALUE[BCOMP] 403#define FETCH_PIXEL(DST, SRC) \ 404 DST[RCOMP] = SRC[0]; \ 405 DST[GCOMP] = SRC[1]; \ 406 DST[BCOMP] = SRC[2]; \ 407 DST[ACOMP] = 1.0F 408#include "swrast/s_spantemp.h" 409 410 411/* 8-bit BGR */ 412#define NAME(PREFIX) PREFIX##_BGR8 413#define RB_TYPE GLubyte 414#define SPAN_VARS \ 415 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 416#define INIT_PIXEL_PTR(P, X, Y) \ 417 GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + 3 * (X) 418#define INC_PIXEL_PTR(P) P += 3 419#define STORE_PIXEL(DST, X, Y, VALUE) \ 420 DST[2] = VALUE[RCOMP]; \ 421 DST[1] = VALUE[GCOMP]; \ 422 DST[0] = VALUE[BCOMP] 423#define FETCH_PIXEL(DST, SRC) \ 424 DST[RCOMP] = SRC[2]; \ 425 DST[GCOMP] = SRC[1]; \ 426 DST[BCOMP] = SRC[0]; \ 427 DST[ACOMP] = 255 428#include "swrast/s_spantemp.h" 429 430/* 16-bit BGR */ 431#define NAME(PREFIX) PREFIX##_BGR16 432#define RB_TYPE GLushort 433#define SPAN_VARS \ 434 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 435#define INIT_PIXEL_PTR(P, X, Y) \ 436 GLushort *P = (GLushort *) osmesa->rowaddr[Y] + 3 * (X) 437#define INC_PIXEL_PTR(P) P += 3 438#define STORE_PIXEL(DST, X, Y, VALUE) \ 439 DST[2] = VALUE[RCOMP]; \ 440 DST[1] = VALUE[GCOMP]; \ 441 DST[0] = VALUE[BCOMP] 442#define FETCH_PIXEL(DST, SRC) \ 443 DST[RCOMP] = SRC[2]; \ 444 DST[GCOMP] = SRC[1]; \ 445 DST[BCOMP] = SRC[0]; \ 446 DST[ACOMP] = 65535 447#include "swrast/s_spantemp.h" 448 449/* 32-bit BGR */ 450#define NAME(PREFIX) PREFIX##_BGR32 451#define RB_TYPE GLfloat 452#define SPAN_VARS \ 453 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 454#define INIT_PIXEL_PTR(P, X, Y) \ 455 GLfloat *P = (GLfloat *) osmesa->rowaddr[Y] + 3 * (X) 456#define INC_PIXEL_PTR(P) P += 3 457#define STORE_PIXEL(DST, X, Y, VALUE) \ 458 DST[2] = VALUE[RCOMP]; \ 459 DST[1] = VALUE[GCOMP]; \ 460 DST[0] = VALUE[BCOMP] 461#define FETCH_PIXEL(DST, SRC) \ 462 DST[RCOMP] = SRC[2]; \ 463 DST[GCOMP] = SRC[1]; \ 464 DST[BCOMP] = SRC[0]; \ 465 DST[ACOMP] = 1.0F 466#include "swrast/s_spantemp.h" 467 468 469/* 16-bit 5/6/5 RGB */ 470#define NAME(PREFIX) PREFIX##_RGB_565 471#define RB_TYPE GLubyte 472#define SPAN_VARS \ 473 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 474#define INIT_PIXEL_PTR(P, X, Y) \ 475 GLushort *P = (GLushort *) osmesa->rowaddr[Y] + (X) 476#define INC_PIXEL_PTR(P) P += 1 477#define STORE_PIXEL(DST, X, Y, VALUE) \ 478 *DST = ( (((VALUE[RCOMP]) & 0xf8) << 8) | (((VALUE[GCOMP]) & 0xfc) << 3) | ((VALUE[BCOMP]) >> 3) ) 479#define FETCH_PIXEL(DST, SRC) \ 480 DST[RCOMP] = ( (((*SRC) >> 8) & 0xf8) | (((*SRC) >> 11) & 0x7) ); \ 481 DST[GCOMP] = ( (((*SRC) >> 3) & 0xfc) | (((*SRC) >> 5) & 0x3) ); \ 482 DST[BCOMP] = ( (((*SRC) << 3) & 0xf8) | (((*SRC) ) & 0x7) ); \ 483 DST[ACOMP] = CHAN_MAX 484#include "swrast/s_spantemp.h" 485 486 487/** 488 * Macros for optimized line/triangle rendering. 489 * Only for 8-bit channel, RGBA, BGRA, ARGB formats. 490 */ 491 492#define PACK_RGBA(DST, R, G, B, A) \ 493do { \ 494 (DST)[osmesa->rInd] = R; \ 495 (DST)[osmesa->gInd] = G; \ 496 (DST)[osmesa->bInd] = B; \ 497 (DST)[osmesa->aInd] = A; \ 498} while (0) 499 500#define PIXELADDR4(X,Y) ((GLchan *) osmesa->rowaddr[Y] + 4 * (X)) 501 502 503/** 504 * Draw a flat-shaded, RGB line into an osmesa buffer. 505 */ 506#define NAME flat_rgba_line 507#define CLIP_HACK 1 508#define SETUP_CODE \ 509 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \ 510 const GLchan *color = vert1->color; 511 512#define PLOT(X, Y) \ 513do { \ 514 GLchan *p = PIXELADDR4(X, Y); \ 515 PACK_RGBA(p, color[0], color[1], color[2], color[3]); \ 516} while (0) 517 518#ifdef WIN32 519#include "..\swrast\s_linetemp.h" 520#else 521#include "swrast/s_linetemp.h" 522#endif 523 524 525 526/** 527 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer. 528 */ 529#define NAME flat_rgba_z_line 530#define CLIP_HACK 1 531#define INTERP_Z 1 532#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 533#define SETUP_CODE \ 534 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \ 535 const GLchan *color = vert1->color; 536 537#define PLOT(X, Y) \ 538do { \ 539 if (Z < *zPtr) { \ 540 GLchan *p = PIXELADDR4(X, Y); \ 541 PACK_RGBA(p, color[RCOMP], color[GCOMP], \ 542 color[BCOMP], color[ACOMP]); \ 543 *zPtr = Z; \ 544 } \ 545} while (0) 546 547#ifdef WIN32 548#include "..\swrast\s_linetemp.h" 549#else 550#include "swrast/s_linetemp.h" 551#endif 552 553 554 555/** 556 * Analyze context state to see if we can provide a fast line drawing 557 * function. Otherwise, return NULL. 558 */ 559static swrast_line_func 560osmesa_choose_line_function( GLcontext *ctx ) 561{ 562 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 563 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 564 565 if (osmesa->rb->DataType != GL_UNSIGNED_BYTE) 566 return NULL; 567 568 if (ctx->RenderMode != GL_RENDER) return NULL; 569 if (ctx->Line.SmoothFlag) return NULL; 570 if (ctx->Texture._EnabledUnits) return NULL; 571 if (ctx->Light.ShadeModel != GL_FLAT) return NULL; 572 if (ctx->Line.Width != 1.0F) return NULL; 573 if (ctx->Line.StippleFlag) return NULL; 574 if (ctx->Line.SmoothFlag) return NULL; 575 if (osmesa->format != OSMESA_RGBA && 576 osmesa->format != OSMESA_BGRA && 577 osmesa->format != OSMESA_ARGB) return NULL; 578 579 if (swrast->_RasterMask==DEPTH_BIT 580 && ctx->Depth.Func==GL_LESS 581 && ctx->Depth.Mask==GL_TRUE 582 && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) { 583 return (swrast_line_func) flat_rgba_z_line; 584 } 585 586 if (swrast->_RasterMask == 0) { 587 return (swrast_line_func) flat_rgba_line; 588 } 589 590 return (swrast_line_func) NULL; 591} 592 593 594/**********************************************************************/ 595/***** Optimized triangle rendering *****/ 596/**********************************************************************/ 597 598 599/* 600 * Smooth-shaded, z-less triangle, RGBA color. 601 */ 602#define NAME smooth_rgba_z_triangle 603#define INTERP_Z 1 604#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 605#define INTERP_RGB 1 606#define INTERP_ALPHA 1 607#define SETUP_CODE \ 608 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 609#define RENDER_SPAN( span ) { \ 610 GLuint i; \ 611 GLchan *img = PIXELADDR4(span.x, span.y); \ 612 for (i = 0; i < span.end; i++, img += 4) { \ 613 const GLuint z = FixedToDepth(span.z); \ 614 if (z < zRow[i]) { \ 615 PACK_RGBA(img, FixedToChan(span.red), \ 616 FixedToChan(span.green), FixedToChan(span.blue), \ 617 FixedToChan(span.alpha)); \ 618 zRow[i] = z; \ 619 } \ 620 span.red += span.redStep; \ 621 span.green += span.greenStep; \ 622 span.blue += span.blueStep; \ 623 span.alpha += span.alphaStep; \ 624 span.z += span.zStep; \ 625 } \ 626} 627#ifdef WIN32 628#include "..\swrast\s_tritemp.h" 629#else 630#include "swrast/s_tritemp.h" 631#endif 632 633 634 635/* 636 * Flat-shaded, z-less triangle, RGBA color. 637 */ 638#define NAME flat_rgba_z_triangle 639#define INTERP_Z 1 640#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE 641#define SETUP_CODE \ 642 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); \ 643 GLuint pixel; \ 644 PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1], \ 645 v2->color[2], v2->color[3]); 646 647#define RENDER_SPAN( span ) { \ 648 GLuint i; \ 649 GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y); \ 650 for (i = 0; i < span.end; i++) { \ 651 const GLuint z = FixedToDepth(span.z); \ 652 if (z < zRow[i]) { \ 653 img[i] = pixel; \ 654 zRow[i] = z; \ 655 } \ 656 span.z += span.zStep; \ 657 } \ 658} 659#ifdef WIN32 660#include "..\swrast\s_tritemp.h" 661#else 662#include "swrast/s_tritemp.h" 663#endif 664 665 666 667/** 668 * Return pointer to an optimized triangle function if possible. 669 */ 670static swrast_tri_func 671osmesa_choose_triangle_function( GLcontext *ctx ) 672{ 673 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 674 const SWcontext *swrast = SWRAST_CONTEXT(ctx); 675 676 if (osmesa->rb->DataType != GL_UNSIGNED_BYTE) 677 return (swrast_tri_func) NULL; 678 679 if (ctx->RenderMode != GL_RENDER) return (swrast_tri_func) NULL; 680 if (ctx->Polygon.SmoothFlag) return (swrast_tri_func) NULL; 681 if (ctx->Polygon.StippleFlag) return (swrast_tri_func) NULL; 682 if (ctx->Texture._EnabledUnits) return (swrast_tri_func) NULL; 683 if (osmesa->format != OSMESA_RGBA && 684 osmesa->format != OSMESA_BGRA && 685 osmesa->format != OSMESA_ARGB) return (swrast_tri_func) NULL; 686 if (ctx->Polygon.CullFlag && 687 ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) 688 return (swrast_tri_func) NULL; 689 690 if (swrast->_RasterMask == DEPTH_BIT && 691 ctx->Depth.Func == GL_LESS && 692 ctx->Depth.Mask == GL_TRUE && 693 ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) { 694 if (ctx->Light.ShadeModel == GL_SMOOTH) { 695 return (swrast_tri_func) smooth_rgba_z_triangle; 696 } 697 else { 698 return (swrast_tri_func) flat_rgba_z_triangle; 699 } 700 } 701 return (swrast_tri_func) NULL; 702} 703 704 705 706/* Override for the swrast triangle-selection function. Try to use one 707 * of our internal triangle functions, otherwise fall back to the 708 * standard swrast functions. 709 */ 710static void 711osmesa_choose_triangle( GLcontext *ctx ) 712{ 713 SWcontext *swrast = SWRAST_CONTEXT(ctx); 714 715 swrast->Triangle = osmesa_choose_triangle_function( ctx ); 716 if (!swrast->Triangle) 717 _swrast_choose_triangle( ctx ); 718} 719 720static void 721osmesa_choose_line( GLcontext *ctx ) 722{ 723 SWcontext *swrast = SWRAST_CONTEXT(ctx); 724 725 swrast->Line = osmesa_choose_line_function( ctx ); 726 if (!swrast->Line) 727 _swrast_choose_line( ctx ); 728} 729 730 731 732/** 733 * Recompute the values of the context's rowaddr array. 734 */ 735static void 736compute_row_addresses( OSMesaContext osmesa ) 737{ 738 GLint bytesPerPixel, bytesPerRow, i; 739 GLubyte *origin = (GLubyte *) osmesa->rb->Data; 740 GLint bpc; /* bytes per channel */ 741 GLint rowlength; /* in pixels */ 742 GLint height = osmesa->rb->Height; 743 744 if (osmesa->userRowLength) 745 rowlength = osmesa->userRowLength; 746 else 747 rowlength = osmesa->rb->Width; 748 749 if (osmesa->rb->DataType == GL_UNSIGNED_BYTE) 750 bpc = 1; 751 else if (osmesa->rb->DataType == GL_UNSIGNED_SHORT) 752 bpc = 2; 753 else if (osmesa->rb->DataType == GL_FLOAT) 754 bpc = 4; 755 else { 756 _mesa_problem(&osmesa->mesa, 757 "Unexpected datatype in osmesa::compute_row_addresses"); 758 return; 759 } 760 761 if ((osmesa->format == OSMESA_RGB) || (osmesa->format == OSMESA_BGR)) { 762 /* RGB mode */ 763 bytesPerPixel = 3 * bpc; 764 } 765 else if (osmesa->format == OSMESA_RGB_565) { 766 /* 5/6/5 RGB pixel in 16 bits */ 767 bytesPerPixel = 2; 768 } 769 else { 770 /* RGBA mode */ 771 bytesPerPixel = 4 * bpc; 772 } 773 774 bytesPerRow = rowlength * bytesPerPixel; 775 776 if (osmesa->yup) { 777 /* Y=0 is bottom line of window */ 778 for (i = 0; i < height; i++) { 779 osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + i * bytesPerRow); 780 } 781 } 782 else { 783 /* Y=0 is top line of window */ 784 for (i = 0; i < height; i++) { 785 GLint j = height - i - 1; 786 osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + j * bytesPerRow); 787 } 788 } 789} 790 791 792 793/** 794 * Don't use _mesa_delete_renderbuffer since we can't free rb->Data. 795 */ 796static void 797osmesa_delete_renderbuffer(struct gl_renderbuffer *rb) 798{ 799 free(rb); 800} 801 802 803/** 804 * Allocate renderbuffer storage. We don't actually allocate any storage 805 * since we're using a user-provided buffer. 806 * Just set up all the gl_renderbuffer methods. 807 */ 808static GLboolean 809osmesa_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb, 810 GLenum internalFormat, GLuint width, GLuint height) 811{ 812 const OSMesaContext osmesa = OSMESA_CONTEXT(ctx); 813 GLint bpc; /* bits per channel */ 814 815 if (rb->DataType == GL_UNSIGNED_BYTE) 816 bpc = 8; 817 else if (rb->DataType == GL_UNSIGNED_SHORT) 818 bpc = 16; 819 else 820 bpc = 32; 821 822 /* Note: we can ignoring internalFormat for "window-system" renderbuffers */ 823 (void) internalFormat; 824 825 if (osmesa->format == OSMESA_RGBA) { 826 if (rb->DataType == GL_UNSIGNED_BYTE) { 827 rb->GetRow = get_row_RGBA8; 828 rb->GetValues = get_values_RGBA8; 829 rb->PutRow = put_row_RGBA8; 830 rb->PutRowRGB = put_row_rgb_RGBA8; 831 rb->PutMonoRow = put_mono_row_RGBA8; 832 rb->PutValues = put_values_RGBA8; 833 rb->PutMonoValues = put_mono_values_RGBA8; 834 } 835 else if (rb->DataType == GL_UNSIGNED_SHORT) { 836 rb->GetRow = get_row_RGBA16; 837 rb->GetValues = get_values_RGBA16; 838 rb->PutRow = put_row_RGBA16; 839 rb->PutRowRGB = put_row_rgb_RGBA16; 840 rb->PutMonoRow = put_mono_row_RGBA16; 841 rb->PutValues = put_values_RGBA16; 842 rb->PutMonoValues = put_mono_values_RGBA16; 843 } 844 else { 845 rb->GetRow = get_row_RGBA32; 846 rb->GetValues = get_values_RGBA32; 847 rb->PutRow = put_row_RGBA32; 848 rb->PutRowRGB = put_row_rgb_RGBA32; 849 rb->PutMonoRow = put_mono_row_RGBA32; 850 rb->PutValues = put_values_RGBA32; 851 rb->PutMonoValues = put_mono_values_RGBA32; 852 } 853 } 854 else if (osmesa->format == OSMESA_BGRA) { 855 if (rb->DataType == GL_UNSIGNED_BYTE) { 856 rb->GetRow = get_row_BGRA8; 857 rb->GetValues = get_values_BGRA8; 858 rb->PutRow = put_row_BGRA8; 859 rb->PutRowRGB = put_row_rgb_BGRA8; 860 rb->PutMonoRow = put_mono_row_BGRA8; 861 rb->PutValues = put_values_BGRA8; 862 rb->PutMonoValues = put_mono_values_BGRA8; 863 } 864 else if (rb->DataType == GL_UNSIGNED_SHORT) { 865 rb->GetRow = get_row_BGRA16; 866 rb->GetValues = get_values_BGRA16; 867 rb->PutRow = put_row_BGRA16; 868 rb->PutRowRGB = put_row_rgb_BGRA16; 869 rb->PutMonoRow = put_mono_row_BGRA16; 870 rb->PutValues = put_values_BGRA16; 871 rb->PutMonoValues = put_mono_values_BGRA16; 872 } 873 else { 874 rb->GetRow = get_row_BGRA32; 875 rb->GetValues = get_values_BGRA32; 876 rb->PutRow = put_row_BGRA32; 877 rb->PutRowRGB = put_row_rgb_BGRA32; 878 rb->PutMonoRow = put_mono_row_BGRA32; 879 rb->PutValues = put_values_BGRA32; 880 rb->PutMonoValues = put_mono_values_BGRA32; 881 } 882 } 883 else if (osmesa->format == OSMESA_ARGB) { 884 if (rb->DataType == GL_UNSIGNED_BYTE) { 885 rb->GetRow = get_row_ARGB8; 886 rb->GetValues = get_values_ARGB8; 887 rb->PutRow = put_row_ARGB8; 888 rb->PutRowRGB = put_row_rgb_ARGB8; 889 rb->PutMonoRow = put_mono_row_ARGB8; 890 rb->PutValues = put_values_ARGB8; 891 rb->PutMonoValues = put_mono_values_ARGB8; 892 } 893 else if (rb->DataType == GL_UNSIGNED_SHORT) { 894 rb->GetRow = get_row_ARGB16; 895 rb->GetValues = get_values_ARGB16; 896 rb->PutRow = put_row_ARGB16; 897 rb->PutRowRGB = put_row_rgb_ARGB16; 898 rb->PutMonoRow = put_mono_row_ARGB16; 899 rb->PutValues = put_values_ARGB16; 900 rb->PutMonoValues = put_mono_values_ARGB16; 901 } 902 else { 903 rb->GetRow = get_row_ARGB32; 904 rb->GetValues = get_values_ARGB32; 905 rb->PutRow = put_row_ARGB32; 906 rb->PutRowRGB = put_row_rgb_ARGB32; 907 rb->PutMonoRow = put_mono_row_ARGB32; 908 rb->PutValues = put_values_ARGB32; 909 rb->PutMonoValues = put_mono_values_ARGB32; 910 } 911 } 912 else if (osmesa->format == OSMESA_RGB) { 913 if (rb->DataType == GL_UNSIGNED_BYTE) { 914 rb->GetRow = get_row_RGB8; 915 rb->GetValues = get_values_RGB8; 916 rb->PutRow = put_row_RGB8; 917 rb->PutRowRGB = put_row_rgb_RGB8; 918 rb->PutMonoRow = put_mono_row_RGB8; 919 rb->PutValues = put_values_RGB8; 920 rb->PutMonoValues = put_mono_values_RGB8; 921 } 922 else if (rb->DataType == GL_UNSIGNED_SHORT) { 923 rb->GetRow = get_row_RGB16; 924 rb->GetValues = get_values_RGB16; 925 rb->PutRow = put_row_RGB16; 926 rb->PutRowRGB = put_row_rgb_RGB16; 927 rb->PutMonoRow = put_mono_row_RGB16; 928 rb->PutValues = put_values_RGB16; 929 rb->PutMonoValues = put_mono_values_RGB16; 930 } 931 else { 932 rb->GetRow = get_row_RGB32; 933 rb->GetValues = get_values_RGB32; 934 rb->PutRow = put_row_RGB32; 935 rb->PutRowRGB = put_row_rgb_RGB32; 936 rb->PutMonoRow = put_mono_row_RGB32; 937 rb->PutValues = put_values_RGB32; 938 rb->PutMonoValues = put_mono_values_RGB32; 939 } 940 } 941 else if (osmesa->format == OSMESA_BGR) { 942 if (rb->DataType == GL_UNSIGNED_BYTE) { 943 rb->GetRow = get_row_BGR8; 944 rb->GetValues = get_values_BGR8; 945 rb->PutRow = put_row_BGR8; 946 rb->PutRowRGB = put_row_rgb_BGR8; 947 rb->PutMonoRow = put_mono_row_BGR8; 948 rb->PutValues = put_values_BGR8; 949 rb->PutMonoValues = put_mono_values_BGR8; 950 } 951 else if (rb->DataType == GL_UNSIGNED_SHORT) { 952 rb->GetRow = get_row_BGR16; 953 rb->GetValues = get_values_BGR16; 954 rb->PutRow = put_row_BGR16; 955 rb->PutRowRGB = put_row_rgb_BGR16; 956 rb->PutMonoRow = put_mono_row_BGR16; 957 rb->PutValues = put_values_BGR16; 958 rb->PutMonoValues = put_mono_values_BGR16; 959 } 960 else { 961 rb->GetRow = get_row_BGR32; 962 rb->GetValues = get_values_BGR32; 963 rb->PutRow = put_row_BGR32; 964 rb->PutRowRGB = put_row_rgb_BGR32; 965 rb->PutMonoRow = put_mono_row_BGR32; 966 rb->PutValues = put_values_BGR32; 967 rb->PutMonoValues = put_mono_values_BGR32; 968 } 969 } 970 else if (osmesa->format == OSMESA_RGB_565) { 971 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 972 rb->GetRow = get_row_RGB_565; 973 rb->GetValues = get_values_RGB_565; 974 rb->PutRow = put_row_RGB_565; 975 rb->PutRowRGB = put_row_rgb_RGB_565; 976 rb->PutMonoRow = put_mono_row_RGB_565; 977 rb->PutValues = put_values_RGB_565; 978 rb->PutMonoValues = put_mono_values_RGB_565; 979 } 980 else { 981 _mesa_problem(ctx, "bad pixel format in osmesa renderbuffer_storage"); 982 } 983 984 rb->Width = width; 985 rb->Height = height; 986 987 compute_row_addresses( osmesa ); 988 989 return GL_TRUE; 990} 991 992 993/** 994 * Allocate a new renderbuffer to describe the user-provided color buffer. 995 */ 996static struct gl_renderbuffer * 997new_osmesa_renderbuffer(GLcontext *ctx, GLenum format, GLenum type) 998{ 999 const GLuint name = 0; 1000 struct gl_renderbuffer *rb = _mesa_new_renderbuffer(ctx, name); 1001 if (rb) { 1002 rb->RefCount = 1; 1003 rb->Delete = osmesa_delete_renderbuffer; 1004 rb->AllocStorage = osmesa_renderbuffer_storage; 1005 1006 rb->InternalFormat = GL_RGBA; 1007 switch (type) { 1008 case GL_UNSIGNED_BYTE: 1009 rb->Format = MESA_FORMAT_RGBA8888; 1010 break; 1011 case GL_UNSIGNED_SHORT: 1012 rb->Format = MESA_FORMAT_RGBA_16; 1013 break; 1014 case GL_FLOAT: 1015 rb->Format = MESA_FORMAT_RGBA_FLOAT32; 1016 break; 1017 default: 1018 assert(0 && "Unexpected type in new_osmesa_renderbuffer()"); 1019 rb->Format = MESA_FORMAT_RGBA8888; 1020 } 1021 rb->_BaseFormat = GL_RGBA; 1022 rb->DataType = type; 1023 } 1024 return rb; 1025} 1026 1027 1028/**********************************************************************/ 1029/***** Public Functions *****/ 1030/**********************************************************************/ 1031 1032 1033/** 1034 * Create an Off-Screen Mesa rendering context. The only attribute needed is 1035 * an RGBA vs Color-Index mode flag. 1036 * 1037 * Input: format - Must be GL_RGBA 1038 * sharelist - specifies another OSMesaContext with which to share 1039 * display lists. NULL indicates no sharing. 1040 * Return: an OSMesaContext or 0 if error 1041 */ 1042GLAPI OSMesaContext GLAPIENTRY 1043OSMesaCreateContext( GLenum format, OSMesaContext sharelist ) 1044{ 1045 return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS, 1046 8, 0, sharelist); 1047} 1048 1049 1050 1051/** 1052 * New in Mesa 3.5 1053 * 1054 * Create context and specify size of ancillary buffers. 1055 */ 1056GLAPI OSMesaContext GLAPIENTRY 1057OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits, 1058 GLint accumBits, OSMesaContext sharelist ) 1059{ 1060 OSMesaContext osmesa; 1061 struct dd_function_table functions; 1062 GLint rind, gind, bind, aind; 1063 GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0; 1064 1065 rind = gind = bind = aind = 0; 1066 if (format==OSMESA_RGBA) { 1067 redBits = CHAN_BITS; 1068 greenBits = CHAN_BITS; 1069 blueBits = CHAN_BITS; 1070 alphaBits = CHAN_BITS; 1071 rind = 0; 1072 gind = 1; 1073 bind = 2; 1074 aind = 3; 1075 } 1076 else if (format==OSMESA_BGRA) { 1077 redBits = CHAN_BITS; 1078 greenBits = CHAN_BITS; 1079 blueBits = CHAN_BITS; 1080 alphaBits = CHAN_BITS; 1081 bind = 0; 1082 gind = 1; 1083 rind = 2; 1084 aind = 3; 1085 } 1086 else if (format==OSMESA_ARGB) { 1087 redBits = CHAN_BITS; 1088 greenBits = CHAN_BITS; 1089 blueBits = CHAN_BITS; 1090 alphaBits = CHAN_BITS; 1091 aind = 0; 1092 rind = 1; 1093 gind = 2; 1094 bind = 3; 1095 } 1096 else if (format==OSMESA_RGB) { 1097 redBits = CHAN_BITS; 1098 greenBits = CHAN_BITS; 1099 blueBits = CHAN_BITS; 1100 alphaBits = 0; 1101 rind = 0; 1102 gind = 1; 1103 bind = 2; 1104 } 1105 else if (format==OSMESA_BGR) { 1106 redBits = CHAN_BITS; 1107 greenBits = CHAN_BITS; 1108 blueBits = CHAN_BITS; 1109 alphaBits = 0; 1110 rind = 2; 1111 gind = 1; 1112 bind = 0; 1113 } 1114#if CHAN_TYPE == GL_UNSIGNED_BYTE 1115 else if (format==OSMESA_RGB_565) { 1116 redBits = 5; 1117 greenBits = 6; 1118 blueBits = 5; 1119 alphaBits = 0; 1120 rind = 0; /* not used */ 1121 gind = 0; 1122 bind = 0; 1123 } 1124#endif 1125 else { 1126 return NULL; 1127 } 1128 1129 osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context); 1130 if (osmesa) { 1131 osmesa->gl_visual = _mesa_create_visual( GL_FALSE, /* double buffer */ 1132 GL_FALSE, /* stereo */ 1133 redBits, 1134 greenBits, 1135 blueBits, 1136 alphaBits, 1137 depthBits, 1138 stencilBits, 1139 accumBits, 1140 accumBits, 1141 accumBits, 1142 alphaBits ? accumBits : 0, 1143 1 /* num samples */ 1144 ); 1145 if (!osmesa->gl_visual) { 1146 free(osmesa); 1147 return NULL; 1148 } 1149 1150 /* Initialize device driver function table */ 1151 _mesa_init_driver_functions(&functions); 1152 /* override with our functions */ 1153 functions.GetString = get_string; 1154 functions.UpdateState = osmesa_update_state; 1155 functions.GetBufferSize = NULL; 1156 1157 if (!_mesa_initialize_context(&osmesa->mesa, 1158 osmesa->gl_visual, 1159 sharelist ? &sharelist->mesa 1160 : (GLcontext *) NULL, 1161 &functions, (void *) osmesa)) { 1162 _mesa_destroy_visual( osmesa->gl_visual ); 1163 free(osmesa); 1164 return NULL; 1165 } 1166 1167 _mesa_enable_sw_extensions(&(osmesa->mesa)); 1168 _mesa_enable_1_3_extensions(&(osmesa->mesa)); 1169 _mesa_enable_1_4_extensions(&(osmesa->mesa)); 1170 _mesa_enable_1_5_extensions(&(osmesa->mesa)); 1171 _mesa_enable_2_0_extensions(&(osmesa->mesa)); 1172 _mesa_enable_2_1_extensions(&(osmesa->mesa)); 1173 1174 osmesa->gl_buffer = _mesa_create_framebuffer(osmesa->gl_visual); 1175 if (!osmesa->gl_buffer) { 1176 _mesa_destroy_visual( osmesa->gl_visual ); 1177 _mesa_free_context_data( &osmesa->mesa ); 1178 free(osmesa); 1179 return NULL; 1180 } 1181 1182 /* Create depth/stencil/accum buffers. We'll create the color 1183 * buffer later in OSMesaMakeCurrent(). 1184 */ 1185 _mesa_add_soft_renderbuffers(osmesa->gl_buffer, 1186 GL_FALSE, /* color */ 1187 osmesa->gl_visual->haveDepthBuffer, 1188 osmesa->gl_visual->haveStencilBuffer, 1189 osmesa->gl_visual->haveAccumBuffer, 1190 GL_FALSE, /* alpha */ 1191 GL_FALSE /* aux */ ); 1192 1193 osmesa->format = format; 1194 osmesa->userRowLength = 0; 1195 osmesa->yup = GL_TRUE; 1196 osmesa->rInd = rind; 1197 osmesa->gInd = gind; 1198 osmesa->bInd = bind; 1199 osmesa->aInd = aind; 1200 1201 _mesa_meta_init(&osmesa->mesa); 1202 1203 /* Initialize the software rasterizer and helper modules. */ 1204 { 1205 GLcontext *ctx = &osmesa->mesa; 1206 SWcontext *swrast; 1207 TNLcontext *tnl; 1208 1209 if (!_swrast_CreateContext( ctx ) || 1210 !_vbo_CreateContext( ctx ) || 1211 !_tnl_CreateContext( ctx ) || 1212 !_swsetup_CreateContext( ctx )) { 1213 _mesa_destroy_visual(osmesa->gl_visual); 1214 _mesa_free_context_data(ctx); 1215 free(osmesa); 1216 return NULL; 1217 } 1218 1219 _swsetup_Wakeup( ctx ); 1220 1221 /* use default TCL pipeline */ 1222 tnl = TNL_CONTEXT(ctx); 1223 tnl->Driver.RunPipeline = _tnl_run_pipeline; 1224 1225 /* Extend the software rasterizer with our optimized line and triangle 1226 * drawing functions. 1227 */ 1228 swrast = SWRAST_CONTEXT( ctx ); 1229 swrast->choose_line = osmesa_choose_line; 1230 swrast->choose_triangle = osmesa_choose_triangle; 1231 } 1232 } 1233 return osmesa; 1234} 1235 1236 1237/** 1238 * Destroy an Off-Screen Mesa rendering context. 1239 * 1240 * \param osmesa the context to destroy 1241 */ 1242GLAPI void GLAPIENTRY 1243OSMesaDestroyContext( OSMesaContext osmesa ) 1244{ 1245 if (osmesa) { 1246 if (osmesa->rb) 1247 _mesa_reference_renderbuffer(&osmesa->rb, NULL); 1248 1249 _mesa_meta_free( &osmesa->mesa ); 1250 1251 _swsetup_DestroyContext( &osmesa->mesa ); 1252 _tnl_DestroyContext( &osmesa->mesa ); 1253 _vbo_DestroyContext( &osmesa->mesa ); 1254 _swrast_DestroyContext( &osmesa->mesa ); 1255 1256 _mesa_destroy_visual( osmesa->gl_visual ); 1257 _mesa_reference_framebuffer( &osmesa->gl_buffer, NULL ); 1258 1259 _mesa_free_context_data( &osmesa->mesa ); 1260 free( osmesa ); 1261 } 1262} 1263 1264 1265/** 1266 * Bind an OSMesaContext to an image buffer. The image buffer is just a 1267 * block of memory which the client provides. Its size must be at least 1268 * as large as width*height*sizeof(type). Its address should be a multiple 1269 * of 4 if using RGBA mode. 1270 * 1271 * Image data is stored in the order of glDrawPixels: row-major order 1272 * with the lower-left image pixel stored in the first array position 1273 * (ie. bottom-to-top). 1274 * 1275 * If the context's viewport hasn't been initialized yet, it will now be 1276 * initialized to (0,0,width,height). 1277 * 1278 * Input: osmesa - the rendering context 1279 * buffer - the image buffer memory 1280 * type - data type for pixel components 1281 * Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5 1282 * are supported. But if Mesa's been compiled with CHAN_BITS==16 1283 * then type may be GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE. And if 1284 * Mesa's been build with CHAN_BITS==32 then type may be GL_FLOAT, 1285 * GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE. 1286 * width, height - size of image buffer in pixels, at least 1 1287 * Return: GL_TRUE if success, GL_FALSE if error because of invalid osmesa, 1288 * invalid buffer address, invalid type, width<1, height<1, 1289 * width>internal limit or height>internal limit. 1290 */ 1291GLAPI GLboolean GLAPIENTRY 1292OSMesaMakeCurrent( OSMesaContext osmesa, void *buffer, GLenum type, 1293 GLsizei width, GLsizei height ) 1294{ 1295 if (!osmesa || !buffer || 1296 width < 1 || height < 1 || 1297 width > MAX_WIDTH || height > MAX_HEIGHT) { 1298 return GL_FALSE; 1299 } 1300 1301 if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5) { 1302 return GL_FALSE; 1303 } 1304 1305#if 0 1306 if (!(type == GL_UNSIGNED_BYTE || 1307 (type == GL_UNSIGNED_SHORT && CHAN_BITS >= 16) || 1308 (type == GL_FLOAT && CHAN_BITS == 32))) { 1309 /* i.e. is sizeof(type) * 8 > CHAN_BITS? */ 1310 return GL_FALSE; 1311 } 1312#endif 1313 1314 osmesa_update_state( &osmesa->mesa, 0 ); 1315 1316 /* Call this periodically to detect when the user has begun using 1317 * GL rendering from multiple threads. 1318 */ 1319 _glapi_check_multithread(); 1320 1321 1322 /* Create a front/left color buffer which wraps the user-provided buffer. 1323 * There is no back color buffer. 1324 * If the user tries to use a 8, 16 or 32-bit/channel buffer that 1325 * doesn't match what Mesa was compiled for (CHAN_BITS) the 1326 * _mesa_add_renderbuffer() function will create a "wrapper" renderbuffer 1327 * that converts rendering from CHAN_BITS to the user-requested channel 1328 * size. 1329 */ 1330 osmesa->rb = new_osmesa_renderbuffer(&osmesa->mesa, osmesa->format, type); 1331 _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, osmesa->rb); 1332 assert(osmesa->rb->RefCount == 2); 1333 1334 /* Set renderbuffer fields. Set width/height = 0 to force 1335 * osmesa_renderbuffer_storage() being called by _mesa_resize_framebuffer() 1336 */ 1337 osmesa->rb->Data = buffer; 1338 osmesa->rb->Width = osmesa->rb->Height = 0; 1339 1340 /* Set the framebuffer's size. This causes the 1341 * osmesa_renderbuffer_storage() function to get called. 1342 */ 1343 _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height); 1344 osmesa->gl_buffer->Initialized = GL_TRUE; /* XXX TEMPORARY? */ 1345 1346 _mesa_make_current( &osmesa->mesa, osmesa->gl_buffer, osmesa->gl_buffer ); 1347 1348 /* Remove renderbuffer attachment, then re-add. This installs the 1349 * renderbuffer adaptor/wrapper if needed (for bpp conversion). 1350 */ 1351 _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT); 1352 _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT, osmesa->rb); 1353 1354 1355 /* this updates the visual's red/green/blue/alphaBits fields */ 1356 _mesa_update_framebuffer_visual(osmesa->gl_buffer); 1357 1358 /* update the framebuffer size */ 1359 _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height); 1360 1361 return GL_TRUE; 1362} 1363 1364 1365 1366GLAPI OSMesaContext GLAPIENTRY 1367OSMesaGetCurrentContext( void ) 1368{ 1369 GLcontext *ctx = _mesa_get_current_context(); 1370 if (ctx) 1371 return (OSMesaContext) ctx; 1372 else 1373 return NULL; 1374} 1375 1376 1377 1378GLAPI void GLAPIENTRY 1379OSMesaPixelStore( GLint pname, GLint value ) 1380{ 1381 OSMesaContext osmesa = OSMesaGetCurrentContext(); 1382 1383 switch (pname) { 1384 case OSMESA_ROW_LENGTH: 1385 if (value<0) { 1386 _mesa_error( &osmesa->mesa, GL_INVALID_VALUE, 1387 "OSMesaPixelStore(value)" ); 1388 return; 1389 } 1390 osmesa->userRowLength = value; 1391 break; 1392 case OSMESA_Y_UP: 1393 osmesa->yup = value ? GL_TRUE : GL_FALSE; 1394 break; 1395 default: 1396 _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" ); 1397 return; 1398 } 1399 1400 compute_row_addresses( osmesa ); 1401} 1402 1403 1404GLAPI void GLAPIENTRY 1405OSMesaGetIntegerv( GLint pname, GLint *value ) 1406{ 1407 OSMesaContext osmesa = OSMesaGetCurrentContext(); 1408 1409 switch (pname) { 1410 case OSMESA_WIDTH: 1411 if (osmesa->gl_buffer) 1412 *value = osmesa->gl_buffer->Width; 1413 else 1414 *value = 0; 1415 return; 1416 case OSMESA_HEIGHT: 1417 if (osmesa->gl_buffer) 1418 *value = osmesa->gl_buffer->Height; 1419 else 1420 *value = 0; 1421 return; 1422 case OSMESA_FORMAT: 1423 *value = osmesa->format; 1424 return; 1425 case OSMESA_TYPE: 1426 /* current color buffer's data type */ 1427 if (osmesa->rb) { 1428 *value = osmesa->rb->DataType; 1429 } 1430 else { 1431 *value = 0; 1432 } 1433 return; 1434 case OSMESA_ROW_LENGTH: 1435 *value = osmesa->userRowLength; 1436 return; 1437 case OSMESA_Y_UP: 1438 *value = osmesa->yup; 1439 return; 1440 case OSMESA_MAX_WIDTH: 1441 *value = MAX_WIDTH; 1442 return; 1443 case OSMESA_MAX_HEIGHT: 1444 *value = MAX_HEIGHT; 1445 return; 1446 default: 1447 _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)"); 1448 return; 1449 } 1450} 1451 1452 1453/** 1454 * Return the depth buffer associated with an OSMesa context. 1455 * Input: c - the OSMesa context 1456 * Output: width, height - size of buffer in pixels 1457 * bytesPerValue - bytes per depth value (2 or 4) 1458 * buffer - pointer to depth buffer values 1459 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 1460 */ 1461GLAPI GLboolean GLAPIENTRY 1462OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height, 1463 GLint *bytesPerValue, void **buffer ) 1464{ 1465 struct gl_renderbuffer *rb = NULL; 1466 1467 if (c->gl_buffer) 1468 rb = c->gl_buffer->Attachment[BUFFER_DEPTH].Renderbuffer; 1469 1470 if (!rb || !rb->Data) { 1471 *width = 0; 1472 *height = 0; 1473 *bytesPerValue = 0; 1474 *buffer = 0; 1475 return GL_FALSE; 1476 } 1477 else { 1478 *width = rb->Width; 1479 *height = rb->Height; 1480 if (c->gl_visual->depthBits <= 16) 1481 *bytesPerValue = sizeof(GLushort); 1482 else 1483 *bytesPerValue = sizeof(GLuint); 1484 *buffer = rb->Data; 1485 return GL_TRUE; 1486 } 1487} 1488 1489 1490/** 1491 * Return the color buffer associated with an OSMesa context. 1492 * Input: c - the OSMesa context 1493 * Output: width, height - size of buffer in pixels 1494 * format - the pixel format (OSMESA_FORMAT) 1495 * buffer - pointer to color buffer values 1496 * Return: GL_TRUE or GL_FALSE to indicate success or failure. 1497 */ 1498GLAPI GLboolean GLAPIENTRY 1499OSMesaGetColorBuffer( OSMesaContext osmesa, GLint *width, 1500 GLint *height, GLint *format, void **buffer ) 1501{ 1502 if (osmesa->rb && osmesa->rb->Data) { 1503 *width = osmesa->rb->Width; 1504 *height = osmesa->rb->Height; 1505 *format = osmesa->format; 1506 *buffer = osmesa->rb->Data; 1507 return GL_TRUE; 1508 } 1509 else { 1510 *width = 0; 1511 *height = 0; 1512 *format = 0; 1513 *buffer = 0; 1514 return GL_FALSE; 1515 } 1516} 1517 1518 1519struct name_function 1520{ 1521 const char *Name; 1522 OSMESAproc Function; 1523}; 1524 1525static struct name_function functions[] = { 1526 { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext }, 1527 { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt }, 1528 { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext }, 1529 { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent }, 1530 { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext }, 1531 { "OSMesaPixelsStore", (OSMESAproc) OSMesaPixelStore }, 1532 { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv }, 1533 { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer }, 1534 { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer }, 1535 { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress }, 1536 { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp }, 1537 { NULL, NULL } 1538}; 1539 1540 1541GLAPI OSMESAproc GLAPIENTRY 1542OSMesaGetProcAddress( const char *funcName ) 1543{ 1544 int i; 1545 for (i = 0; functions[i].Name; i++) { 1546 if (strcmp(functions[i].Name, funcName) == 0) 1547 return functions[i].Function; 1548 } 1549 return _glapi_get_proc_address(funcName); 1550} 1551 1552 1553GLAPI void GLAPIENTRY 1554OSMesaColorClamp(GLboolean enable) 1555{ 1556 OSMesaContext osmesa = OSMesaGetCurrentContext(); 1557 1558 if (enable == GL_TRUE) { 1559 osmesa->mesa.Color.ClampFragmentColor = GL_TRUE; 1560 } 1561 else { 1562 osmesa->mesa.Color.ClampFragmentColor = GL_FIXED_ONLY_ARB; 1563 } 1564} 1565 1566 1567