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