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