1 /** 2 * \file macros.h 3 * A collection of useful macros. 4 */ 5 6 /* 7 * Mesa 3-D graphics library 8 * Version: 6.5.2 9 * 10 * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 11 * 12 * Permission is hereby granted, free of charge, to any person obtaining a 13 * copy of this software and associated documentation files (the "Software"), 14 * to deal in the Software without restriction, including without limitation 15 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 16 * and/or sell copies of the Software, and to permit persons to whom the 17 * Software is furnished to do so, subject to the following conditions: 18 * 19 * The above copyright notice and this permission notice shall be included 20 * in all copies or substantial portions of the Software. 21 * 22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 23 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 25 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 27 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 */ 29 30 31 #ifndef MACROS_H 32 #define MACROS_H 33 34 #include "imports.h" 35 36 37 /** 38 * \name Integer / float conversion for colors, normals, etc. 39 */ 40 /*@{*/ 41 42 /** Convert GLubyte in [0,255] to GLfloat in [0.0,1.0] */ 43 extern GLfloat _mesa_ubyte_to_float_color_tab[256]; 44 #define UBYTE_TO_FLOAT(u) _mesa_ubyte_to_float_color_tab[(unsigned int)(u)] 45 46 /** Convert GLfloat in [0.0,1.0] to GLubyte in [0,255] */ 47 #define FLOAT_TO_UBYTE(X) ((GLubyte) (GLint) ((X) * 255.0F)) 48 49 50 /** Convert GLbyte in [-128,127] to GLfloat in [-1.0,1.0] */ 51 #define BYTE_TO_FLOAT(B) ((2.0F * (B) + 1.0F) * (1.0F/255.0F)) 52 53 /** Convert GLfloat in [-1.0,1.0] to GLbyte in [-128,127] */ 54 #define FLOAT_TO_BYTE(X) ( (((GLint) (255.0F * (X))) - 1) / 2 ) 55 56 57 /** Convert GLbyte to GLfloat while preserving zero */ 58 #define BYTE_TO_FLOATZ(B) ((B) == 0 ? 0.0F : BYTE_TO_FLOAT(B)) 59 60 61 /** Convert GLbyte in [-128,127] to GLfloat in [-1.0,1.0], texture/fb data */ 62 #define BYTE_TO_FLOAT_TEX(B) ((B) == -128 ? -1.0F : (B) * (1.0F/127.0F)) 63 64 /** Convert GLfloat in [-1.0,1.0] to GLbyte in [-128,127], texture/fb data */ 65 #define FLOAT_TO_BYTE_TEX(X) CLAMP( (GLint) (127.0F * (X)), -128, 127 ) 66 67 /** Convert GLushort in [0,65535] to GLfloat in [0.0,1.0] */ 68 #define USHORT_TO_FLOAT(S) ((GLfloat) (S) * (1.0F / 65535.0F)) 69 70 /** Convert GLfloat in [0.0,1.0] to GLushort in [0, 65535] */ 71 #define FLOAT_TO_USHORT(X) ((GLuint) ((X) * 65535.0F)) 72 73 74 /** Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0] */ 75 #define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F)) 76 77 /** Convert GLfloat in [-1.0,1.0] to GLshort in [-32768,32767] */ 78 #define FLOAT_TO_SHORT(X) ( (((GLint) (65535.0F * (X))) - 1) / 2 ) 79 80 /** Convert GLshort to GLfloat while preserving zero */ 81 #define SHORT_TO_FLOATZ(S) ((S) == 0 ? 0.0F : SHORT_TO_FLOAT(S)) 82 83 84 /** Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0], texture/fb data */ 85 #define SHORT_TO_FLOAT_TEX(S) ((S) == -32768 ? -1.0F : (S) * (1.0F/32767.0F)) 86 87 /** Convert GLfloat in [-1.0,1.0] to GLshort in [-32768,32767], texture/fb data */ 88 #define FLOAT_TO_SHORT_TEX(X) ( (GLint) (32767.0F * (X)) ) 89 90 91 /** Convert GLuint in [0,4294967295] to GLfloat in [0.0,1.0] */ 92 #define UINT_TO_FLOAT(U) ((GLfloat) ((U) * (1.0F / 4294967295.0))) 93 94 /** Convert GLfloat in [0.0,1.0] to GLuint in [0,4294967295] */ 95 #define FLOAT_TO_UINT(X) ((GLuint) ((X) * 4294967295.0)) 96 97 98 /** Convert GLint in [-2147483648,2147483647] to GLfloat in [-1.0,1.0] */ 99 #define INT_TO_FLOAT(I) ((GLfloat) ((2.0F * (I) + 1.0F) * (1.0F/4294967294.0))) 100 101 /** Convert GLfloat in [-1.0,1.0] to GLint in [-2147483648,2147483647] */ 102 /* causes overflow: 103 #define FLOAT_TO_INT(X) ( (((GLint) (4294967294.0 * (X))) - 1) / 2 ) 104 */ 105 /* a close approximation: */ 106 #define FLOAT_TO_INT(X) ( (GLint) (2147483647.0 * (X)) ) 107 108 /** Convert GLfloat in [-1.0,1.0] to GLint64 in [-(1<<63),(1 << 63) -1] */ 109 #define FLOAT_TO_INT64(X) ( (GLint64) (9223372036854775807.0 * (double)(X)) ) 110 111 112 /** Convert GLint in [-2147483648,2147483647] to GLfloat in [-1.0,1.0], texture/fb data */ 113 #define INT_TO_FLOAT_TEX(I) ((I) == -2147483648 ? -1.0F : (I) * (1.0F/2147483647.0)) 114 115 /** Convert GLfloat in [-1.0,1.0] to GLint in [-2147483648,2147483647], texture/fb data */ 116 #define FLOAT_TO_INT_TEX(X) ( (GLint) (2147483647.0 * (X)) ) 117 118 119 #define BYTE_TO_UBYTE(b) ((GLubyte) ((b) < 0 ? 0 : (GLubyte) (b))) 120 #define SHORT_TO_UBYTE(s) ((GLubyte) ((s) < 0 ? 0 : (GLubyte) ((s) >> 7))) 121 #define USHORT_TO_UBYTE(s) ((GLubyte) ((s) >> 8)) 122 #define INT_TO_UBYTE(i) ((GLubyte) ((i) < 0 ? 0 : (GLubyte) ((i) >> 23))) 123 #define UINT_TO_UBYTE(i) ((GLubyte) ((i) >> 24)) 124 125 126 #define BYTE_TO_USHORT(b) ((b) < 0 ? 0 : ((GLushort) (((b) * 65535) / 255))) 127 #define UBYTE_TO_USHORT(b) (((GLushort) (b) << 8) | (GLushort) (b)) 128 #define SHORT_TO_USHORT(s) ((s) < 0 ? 0 : ((GLushort) (((s) * 65535 / 32767)))) 129 #define INT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 15))) 130 #define UINT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 16))) 131 #define UNCLAMPED_FLOAT_TO_USHORT(us, f) \ 132 us = ( (GLushort) F_TO_I( CLAMP((f), 0.0F, 1.0F) * 65535.0F) ) 133 #define CLAMPED_FLOAT_TO_USHORT(us, f) \ 134 us = ( (GLushort) F_TO_I( (f) * 65535.0F) ) 135 136 #define UNCLAMPED_FLOAT_TO_SHORT(s, f) \ 137 s = ( (GLshort) F_TO_I( CLAMP((f), -1.0F, 1.0F) * 32767.0F) ) 138 139 /*** 140 *** UNCLAMPED_FLOAT_TO_UBYTE: clamp float to [0,1] and map to ubyte in [0,255] 141 *** CLAMPED_FLOAT_TO_UBYTE: map float known to be in [0,1] to ubyte in [0,255] 142 ***/ 143 #if defined(USE_IEEE) && !defined(DEBUG) 144 #define IEEE_0996 0x3f7f0000 /* 0.996 or so */ 145 /* This function/macro is sensitive to precision. Test very carefully 146 * if you change it! 147 */ 148 #define UNCLAMPED_FLOAT_TO_UBYTE(UB, F) \ 149 do { \ 150 fi_type __tmp; \ 151 __tmp.f = (F); \ 152 if (__tmp.i < 0) \ 153 UB = (GLubyte) 0; \ 154 else if (__tmp.i >= IEEE_0996) \ 155 UB = (GLubyte) 255; \ 156 else { \ 157 __tmp.f = __tmp.f * (255.0F/256.0F) + 32768.0F; \ 158 UB = (GLubyte) __tmp.i; \ 159 } \ 160 } while (0) 161 #define CLAMPED_FLOAT_TO_UBYTE(UB, F) \ 162 do { \ 163 fi_type __tmp; \ 164 __tmp.f = (F) * (255.0F/256.0F) + 32768.0F; \ 165 UB = (GLubyte) __tmp.i; \ 166 } while (0) 167 #else 168 #define UNCLAMPED_FLOAT_TO_UBYTE(ub, f) \ 169 ub = ((GLubyte) F_TO_I(CLAMP((f), 0.0F, 1.0F) * 255.0F)) 170 #define CLAMPED_FLOAT_TO_UBYTE(ub, f) \ 171 ub = ((GLubyte) F_TO_I((f) * 255.0F)) 172 #endif 173 174 static inline GLfloat INT_AS_FLT(GLint i) 175 { 176 fi_type tmp; 177 tmp.i = i; 178 return tmp.f; 179 } 180 181 static inline GLfloat UINT_AS_FLT(GLuint u) 182 { 183 fi_type tmp; 184 tmp.u = u; 185 return tmp.f; 186 } 187 188 /*@}*/ 189 190 191 /** Stepping a GLfloat pointer by a byte stride */ 192 #define STRIDE_F(p, i) (p = (GLfloat *)((GLubyte *)p + i)) 193 /** Stepping a GLuint pointer by a byte stride */ 194 #define STRIDE_UI(p, i) (p = (GLuint *)((GLubyte *)p + i)) 195 /** Stepping a GLubyte[4] pointer by a byte stride */ 196 #define STRIDE_4UB(p, i) (p = (GLubyte (*)[4])((GLubyte *)p + i)) 197 /** Stepping a GLfloat[4] pointer by a byte stride */ 198 #define STRIDE_4F(p, i) (p = (GLfloat (*)[4])((GLubyte *)p + i)) 199 /** Stepping a \p t pointer by a byte stride */ 200 #define STRIDE_T(p, t, i) (p = (t)((GLubyte *)p + i)) 201 202 203 /**********************************************************************/ 204 /** \name 4-element vector operations */ 205 /*@{*/ 206 207 /** Zero */ 208 #define ZERO_4V( DST ) (DST)[0] = (DST)[1] = (DST)[2] = (DST)[3] = 0 209 210 /** Test for equality */ 211 #define TEST_EQ_4V(a,b) ((a)[0] == (b)[0] && \ 212 (a)[1] == (b)[1] && \ 213 (a)[2] == (b)[2] && \ 214 (a)[3] == (b)[3]) 215 216 /** Test for equality (unsigned bytes) */ 217 static inline GLboolean 218 TEST_EQ_4UBV(const GLubyte a[4], const GLubyte b[4]) 219 { 220 #if defined(__i386__) 221 return *((const GLuint *) a) == *((const GLuint *) b); 222 #else 223 return TEST_EQ_4V(a, b); 224 #endif 225 } 226 227 228 /** Copy a 4-element vector */ 229 #define COPY_4V( DST, SRC ) \ 230 do { \ 231 (DST)[0] = (SRC)[0]; \ 232 (DST)[1] = (SRC)[1]; \ 233 (DST)[2] = (SRC)[2]; \ 234 (DST)[3] = (SRC)[3]; \ 235 } while (0) 236 237 /** Copy a 4-element unsigned byte vector */ 238 static inline void 239 COPY_4UBV(GLubyte dst[4], const GLubyte src[4]) 240 { 241 #if defined(__i386__) 242 *((GLuint *) dst) = *((GLuint *) src); 243 #else 244 /* The GLuint cast might fail if DST or SRC are not dword-aligned (RISC) */ 245 COPY_4V(dst, src); 246 #endif 247 } 248 249 /** Copy a 4-element float vector */ 250 static inline void 251 COPY_4FV(GLfloat dst[4], const GLfloat src[4]) 252 { 253 /* memcpy seems to be most efficient */ 254 memcpy(dst, src, sizeof(GLfloat) * 4); 255 } 256 257 /** Copy \p SZ elements into a 4-element vector */ 258 #define COPY_SZ_4V(DST, SZ, SRC) \ 259 do { \ 260 switch (SZ) { \ 261 case 4: (DST)[3] = (SRC)[3]; \ 262 case 3: (DST)[2] = (SRC)[2]; \ 263 case 2: (DST)[1] = (SRC)[1]; \ 264 case 1: (DST)[0] = (SRC)[0]; \ 265 } \ 266 } while(0) 267 268 /** Copy \p SZ elements into a homegeneous (4-element) vector, giving 269 * default values to the remaining */ 270 #define COPY_CLEAN_4V(DST, SZ, SRC) \ 271 do { \ 272 ASSIGN_4V( DST, 0, 0, 0, 1 ); \ 273 COPY_SZ_4V( DST, SZ, SRC ); \ 274 } while (0) 275 276 /** Subtraction */ 277 #define SUB_4V( DST, SRCA, SRCB ) \ 278 do { \ 279 (DST)[0] = (SRCA)[0] - (SRCB)[0]; \ 280 (DST)[1] = (SRCA)[1] - (SRCB)[1]; \ 281 (DST)[2] = (SRCA)[2] - (SRCB)[2]; \ 282 (DST)[3] = (SRCA)[3] - (SRCB)[3]; \ 283 } while (0) 284 285 /** Addition */ 286 #define ADD_4V( DST, SRCA, SRCB ) \ 287 do { \ 288 (DST)[0] = (SRCA)[0] + (SRCB)[0]; \ 289 (DST)[1] = (SRCA)[1] + (SRCB)[1]; \ 290 (DST)[2] = (SRCA)[2] + (SRCB)[2]; \ 291 (DST)[3] = (SRCA)[3] + (SRCB)[3]; \ 292 } while (0) 293 294 /** Element-wise multiplication */ 295 #define SCALE_4V( DST, SRCA, SRCB ) \ 296 do { \ 297 (DST)[0] = (SRCA)[0] * (SRCB)[0]; \ 298 (DST)[1] = (SRCA)[1] * (SRCB)[1]; \ 299 (DST)[2] = (SRCA)[2] * (SRCB)[2]; \ 300 (DST)[3] = (SRCA)[3] * (SRCB)[3]; \ 301 } while (0) 302 303 /** In-place addition */ 304 #define ACC_4V( DST, SRC ) \ 305 do { \ 306 (DST)[0] += (SRC)[0]; \ 307 (DST)[1] += (SRC)[1]; \ 308 (DST)[2] += (SRC)[2]; \ 309 (DST)[3] += (SRC)[3]; \ 310 } while (0) 311 312 /** Element-wise multiplication and addition */ 313 #define ACC_SCALE_4V( DST, SRCA, SRCB ) \ 314 do { \ 315 (DST)[0] += (SRCA)[0] * (SRCB)[0]; \ 316 (DST)[1] += (SRCA)[1] * (SRCB)[1]; \ 317 (DST)[2] += (SRCA)[2] * (SRCB)[2]; \ 318 (DST)[3] += (SRCA)[3] * (SRCB)[3]; \ 319 } while (0) 320 321 /** In-place scalar multiplication and addition */ 322 #define ACC_SCALE_SCALAR_4V( DST, S, SRCB ) \ 323 do { \ 324 (DST)[0] += S * (SRCB)[0]; \ 325 (DST)[1] += S * (SRCB)[1]; \ 326 (DST)[2] += S * (SRCB)[2]; \ 327 (DST)[3] += S * (SRCB)[3]; \ 328 } while (0) 329 330 /** Scalar multiplication */ 331 #define SCALE_SCALAR_4V( DST, S, SRCB ) \ 332 do { \ 333 (DST)[0] = S * (SRCB)[0]; \ 334 (DST)[1] = S * (SRCB)[1]; \ 335 (DST)[2] = S * (SRCB)[2]; \ 336 (DST)[3] = S * (SRCB)[3]; \ 337 } while (0) 338 339 /** In-place scalar multiplication */ 340 #define SELF_SCALE_SCALAR_4V( DST, S ) \ 341 do { \ 342 (DST)[0] *= S; \ 343 (DST)[1] *= S; \ 344 (DST)[2] *= S; \ 345 (DST)[3] *= S; \ 346 } while (0) 347 348 /** Assignment */ 349 #define ASSIGN_4V( V, V0, V1, V2, V3 ) \ 350 do { \ 351 V[0] = V0; \ 352 V[1] = V1; \ 353 V[2] = V2; \ 354 V[3] = V3; \ 355 } while(0) 356 357 /*@}*/ 358 359 360 /**********************************************************************/ 361 /** \name 3-element vector operations*/ 362 /*@{*/ 363 364 /** Zero */ 365 #define ZERO_3V( DST ) (DST)[0] = (DST)[1] = (DST)[2] = 0 366 367 /** Test for equality */ 368 #define TEST_EQ_3V(a,b) \ 369 ((a)[0] == (b)[0] && \ 370 (a)[1] == (b)[1] && \ 371 (a)[2] == (b)[2]) 372 373 /** Copy a 3-element vector */ 374 #define COPY_3V( DST, SRC ) \ 375 do { \ 376 (DST)[0] = (SRC)[0]; \ 377 (DST)[1] = (SRC)[1]; \ 378 (DST)[2] = (SRC)[2]; \ 379 } while (0) 380 381 /** Copy a 3-element vector with cast */ 382 #define COPY_3V_CAST( DST, SRC, CAST ) \ 383 do { \ 384 (DST)[0] = (CAST)(SRC)[0]; \ 385 (DST)[1] = (CAST)(SRC)[1]; \ 386 (DST)[2] = (CAST)(SRC)[2]; \ 387 } while (0) 388 389 /** Copy a 3-element float vector */ 390 #define COPY_3FV( DST, SRC ) \ 391 do { \ 392 const GLfloat *_tmp = (SRC); \ 393 (DST)[0] = _tmp[0]; \ 394 (DST)[1] = _tmp[1]; \ 395 (DST)[2] = _tmp[2]; \ 396 } while (0) 397 398 /** Subtraction */ 399 #define SUB_3V( DST, SRCA, SRCB ) \ 400 do { \ 401 (DST)[0] = (SRCA)[0] - (SRCB)[0]; \ 402 (DST)[1] = (SRCA)[1] - (SRCB)[1]; \ 403 (DST)[2] = (SRCA)[2] - (SRCB)[2]; \ 404 } while (0) 405 406 /** Addition */ 407 #define ADD_3V( DST, SRCA, SRCB ) \ 408 do { \ 409 (DST)[0] = (SRCA)[0] + (SRCB)[0]; \ 410 (DST)[1] = (SRCA)[1] + (SRCB)[1]; \ 411 (DST)[2] = (SRCA)[2] + (SRCB)[2]; \ 412 } while (0) 413 414 /** In-place scalar multiplication */ 415 #define SCALE_3V( DST, SRCA, SRCB ) \ 416 do { \ 417 (DST)[0] = (SRCA)[0] * (SRCB)[0]; \ 418 (DST)[1] = (SRCA)[1] * (SRCB)[1]; \ 419 (DST)[2] = (SRCA)[2] * (SRCB)[2]; \ 420 } while (0) 421 422 /** In-place element-wise multiplication */ 423 #define SELF_SCALE_3V( DST, SRC ) \ 424 do { \ 425 (DST)[0] *= (SRC)[0]; \ 426 (DST)[1] *= (SRC)[1]; \ 427 (DST)[2] *= (SRC)[2]; \ 428 } while (0) 429 430 /** In-place addition */ 431 #define ACC_3V( DST, SRC ) \ 432 do { \ 433 (DST)[0] += (SRC)[0]; \ 434 (DST)[1] += (SRC)[1]; \ 435 (DST)[2] += (SRC)[2]; \ 436 } while (0) 437 438 /** Element-wise multiplication and addition */ 439 #define ACC_SCALE_3V( DST, SRCA, SRCB ) \ 440 do { \ 441 (DST)[0] += (SRCA)[0] * (SRCB)[0]; \ 442 (DST)[1] += (SRCA)[1] * (SRCB)[1]; \ 443 (DST)[2] += (SRCA)[2] * (SRCB)[2]; \ 444 } while (0) 445 446 /** Scalar multiplication */ 447 #define SCALE_SCALAR_3V( DST, S, SRCB ) \ 448 do { \ 449 (DST)[0] = S * (SRCB)[0]; \ 450 (DST)[1] = S * (SRCB)[1]; \ 451 (DST)[2] = S * (SRCB)[2]; \ 452 } while (0) 453 454 /** In-place scalar multiplication and addition */ 455 #define ACC_SCALE_SCALAR_3V( DST, S, SRCB ) \ 456 do { \ 457 (DST)[0] += S * (SRCB)[0]; \ 458 (DST)[1] += S * (SRCB)[1]; \ 459 (DST)[2] += S * (SRCB)[2]; \ 460 } while (0) 461 462 /** In-place scalar multiplication */ 463 #define SELF_SCALE_SCALAR_3V( DST, S ) \ 464 do { \ 465 (DST)[0] *= S; \ 466 (DST)[1] *= S; \ 467 (DST)[2] *= S; \ 468 } while (0) 469 470 /** In-place scalar addition */ 471 #define ACC_SCALAR_3V( DST, S ) \ 472 do { \ 473 (DST)[0] += S; \ 474 (DST)[1] += S; \ 475 (DST)[2] += S; \ 476 } while (0) 477 478 /** Assignment */ 479 #define ASSIGN_3V( V, V0, V1, V2 ) \ 480 do { \ 481 V[0] = V0; \ 482 V[1] = V1; \ 483 V[2] = V2; \ 484 } while(0) 485 486 /*@}*/ 487 488 489 /**********************************************************************/ 490 /** \name 2-element vector operations*/ 491 /*@{*/ 492 493 /** Zero */ 494 #define ZERO_2V( DST ) (DST)[0] = (DST)[1] = 0 495 496 /** Copy a 2-element vector */ 497 #define COPY_2V( DST, SRC ) \ 498 do { \ 499 (DST)[0] = (SRC)[0]; \ 500 (DST)[1] = (SRC)[1]; \ 501 } while (0) 502 503 /** Copy a 2-element vector with cast */ 504 #define COPY_2V_CAST( DST, SRC, CAST ) \ 505 do { \ 506 (DST)[0] = (CAST)(SRC)[0]; \ 507 (DST)[1] = (CAST)(SRC)[1]; \ 508 } while (0) 509 510 /** Copy a 2-element float vector */ 511 #define COPY_2FV( DST, SRC ) \ 512 do { \ 513 const GLfloat *_tmp = (SRC); \ 514 (DST)[0] = _tmp[0]; \ 515 (DST)[1] = _tmp[1]; \ 516 } while (0) 517 518 /** Subtraction */ 519 #define SUB_2V( DST, SRCA, SRCB ) \ 520 do { \ 521 (DST)[0] = (SRCA)[0] - (SRCB)[0]; \ 522 (DST)[1] = (SRCA)[1] - (SRCB)[1]; \ 523 } while (0) 524 525 /** Addition */ 526 #define ADD_2V( DST, SRCA, SRCB ) \ 527 do { \ 528 (DST)[0] = (SRCA)[0] + (SRCB)[0]; \ 529 (DST)[1] = (SRCA)[1] + (SRCB)[1]; \ 530 } while (0) 531 532 /** In-place scalar multiplication */ 533 #define SCALE_2V( DST, SRCA, SRCB ) \ 534 do { \ 535 (DST)[0] = (SRCA)[0] * (SRCB)[0]; \ 536 (DST)[1] = (SRCA)[1] * (SRCB)[1]; \ 537 } while (0) 538 539 /** In-place addition */ 540 #define ACC_2V( DST, SRC ) \ 541 do { \ 542 (DST)[0] += (SRC)[0]; \ 543 (DST)[1] += (SRC)[1]; \ 544 } while (0) 545 546 /** Element-wise multiplication and addition */ 547 #define ACC_SCALE_2V( DST, SRCA, SRCB ) \ 548 do { \ 549 (DST)[0] += (SRCA)[0] * (SRCB)[0]; \ 550 (DST)[1] += (SRCA)[1] * (SRCB)[1]; \ 551 } while (0) 552 553 /** Scalar multiplication */ 554 #define SCALE_SCALAR_2V( DST, S, SRCB ) \ 555 do { \ 556 (DST)[0] = S * (SRCB)[0]; \ 557 (DST)[1] = S * (SRCB)[1]; \ 558 } while (0) 559 560 /** In-place scalar multiplication and addition */ 561 #define ACC_SCALE_SCALAR_2V( DST, S, SRCB ) \ 562 do { \ 563 (DST)[0] += S * (SRCB)[0]; \ 564 (DST)[1] += S * (SRCB)[1]; \ 565 } while (0) 566 567 /** In-place scalar multiplication */ 568 #define SELF_SCALE_SCALAR_2V( DST, S ) \ 569 do { \ 570 (DST)[0] *= S; \ 571 (DST)[1] *= S; \ 572 } while (0) 573 574 /** In-place scalar addition */ 575 #define ACC_SCALAR_2V( DST, S ) \ 576 do { \ 577 (DST)[0] += S; \ 578 (DST)[1] += S; \ 579 } while (0) 580 581 /** Assign scalers to short vectors */ 582 #define ASSIGN_2V( V, V0, V1 ) \ 583 do { \ 584 V[0] = V0; \ 585 V[1] = V1; \ 586 } while(0) 587 588 /*@}*/ 589 590 /** Copy \p sz elements into a homegeneous (4-element) vector, giving 591 * default values to the remaining components. 592 * The default values are chosen based on \p type. 593 */ 594 static inline void 595 COPY_CLEAN_4V_TYPE_AS_FLOAT(GLfloat dst[4], int sz, const GLfloat src[4], 596 GLenum type) 597 { 598 switch (type) { 599 case GL_FLOAT: 600 ASSIGN_4V(dst, 0, 0, 0, 1); 601 break; 602 case GL_INT: 603 ASSIGN_4V(dst, INT_AS_FLT(0), INT_AS_FLT(0), 604 INT_AS_FLT(0), INT_AS_FLT(1)); 605 break; 606 case GL_UNSIGNED_INT: 607 ASSIGN_4V(dst, UINT_AS_FLT(0), UINT_AS_FLT(0), 608 UINT_AS_FLT(0), UINT_AS_FLT(1)); 609 break; 610 default: 611 ASSERT(0); 612 } 613 COPY_SZ_4V(dst, sz, src); 614 } 615 616 /** \name Linear interpolation functions */ 617 /*@{*/ 618 619 static inline GLfloat 620 LINTERP(GLfloat t, GLfloat out, GLfloat in) 621 { 622 return out + t * (in - out); 623 } 624 625 static inline void 626 INTERP_3F(GLfloat t, GLfloat dst[3], const GLfloat out[3], const GLfloat in[3]) 627 { 628 dst[0] = LINTERP( t, out[0], in[0] ); 629 dst[1] = LINTERP( t, out[1], in[1] ); 630 dst[2] = LINTERP( t, out[2], in[2] ); 631 } 632 633 static inline void 634 INTERP_4F(GLfloat t, GLfloat dst[4], const GLfloat out[4], const GLfloat in[4]) 635 { 636 dst[0] = LINTERP( t, out[0], in[0] ); 637 dst[1] = LINTERP( t, out[1], in[1] ); 638 dst[2] = LINTERP( t, out[2], in[2] ); 639 dst[3] = LINTERP( t, out[3], in[3] ); 640 } 641 642 /*@}*/ 643 644 645 646 /** Clamp X to [MIN,MAX] */ 647 #define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) ) 648 649 /** Minimum of two values: */ 650 #define MIN2( A, B ) ( (A)<(B) ? (A) : (B) ) 651 652 /** Maximum of two values: */ 653 #define MAX2( A, B ) ( (A)>(B) ? (A) : (B) ) 654 655 /** Minimum and maximum of three values: */ 656 #define MIN3( A, B, C ) ((A) < (B) ? MIN2(A, C) : MIN2(B, C)) 657 #define MAX3( A, B, C ) ((A) > (B) ? MAX2(A, C) : MAX2(B, C)) 658 659 660 661 /** Cross product of two 3-element vectors */ 662 static inline void 663 CROSS3(GLfloat n[3], const GLfloat u[3], const GLfloat v[3]) 664 { 665 n[0] = u[1] * v[2] - u[2] * v[1]; 666 n[1] = u[2] * v[0] - u[0] * v[2]; 667 n[2] = u[0] * v[1] - u[1] * v[0]; 668 } 669 670 671 /** Dot product of two 2-element vectors */ 672 static inline GLfloat 673 DOT2(const GLfloat a[2], const GLfloat b[2]) 674 { 675 return a[0] * b[0] + a[1] * b[1]; 676 } 677 678 static inline GLfloat 679 DOT3(const GLfloat a[3], const GLfloat b[3]) 680 { 681 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; 682 } 683 684 static inline GLfloat 685 DOT4(const GLfloat a[4], const GLfloat b[4]) 686 { 687 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; 688 } 689 690 691 static inline GLfloat 692 LEN_SQUARED_3FV(const GLfloat v[3]) 693 { 694 return DOT3(v, v); 695 } 696 697 static inline GLfloat 698 LEN_SQUARED_2FV(const GLfloat v[2]) 699 { 700 return DOT2(v, v); 701 } 702 703 704 static inline GLfloat 705 LEN_3FV(const GLfloat v[3]) 706 { 707 return SQRTF(LEN_SQUARED_3FV(v)); 708 } 709 710 static inline GLfloat 711 LEN_2FV(const GLfloat v[2]) 712 { 713 return SQRTF(LEN_SQUARED_2FV(v)); 714 } 715 716 717 /* Normalize a 3-element vector to unit length. */ 718 static inline void 719 NORMALIZE_3FV(GLfloat v[3]) 720 { 721 GLfloat len = (GLfloat) LEN_SQUARED_3FV(v); 722 if (len) { 723 len = INV_SQRTF(len); 724 v[0] *= len; 725 v[1] *= len; 726 v[2] *= len; 727 } 728 } 729 730 731 /** Compute ceiling of integer quotient of A divided by B. */ 732 #define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 ) 733 734 735 /** casts to silence warnings with some compilers */ 736 #define ENUM_TO_INT(E) ((GLint)(E)) 737 #define ENUM_TO_FLOAT(E) ((GLfloat)(GLint)(E)) 738 #define ENUM_TO_DOUBLE(E) ((GLdouble)(GLint)(E)) 739 #define ENUM_TO_BOOLEAN(E) ((E) ? GL_TRUE : GL_FALSE) 740 741 742 #endif 743