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