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] */ 43extern 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 174static inline GLfloat INT_AS_FLT(GLint i) 175{ 176 fi_type tmp; 177 tmp.i = i; 178 return tmp.f; 179} 180 181static 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) */ 217static inline GLboolean 218TEST_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 ) \ 230do { \ 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 */ 238static inline void 239COPY_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 */ 250static inline void 251COPY_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) \ 259do { \ 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) \ 271do { \ 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 ) \ 278do { \ 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 ) \ 287do { \ 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 ) \ 296do { \ 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 ) \ 305do { \ 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 ) \ 314do { \ 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 ) \ 323do { \ 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 ) \ 332do { \ 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 ) \ 341do { \ 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 ) \ 350do { \ 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 ) \ 375do { \ 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 ) \ 383do { \ 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 ) \ 391do { \ 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 ) \ 400do { \ 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 ) \ 408do { \ 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 ) \ 416do { \ 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 ) \ 424do { \ 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 ) \ 432do { \ 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 ) \ 440do { \ 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 ) \ 448do { \ 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 ) \ 456do { \ 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 ) \ 464do { \ 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 ) \ 472do { \ 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 ) \ 480do { \ 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 ) \ 498do { \ 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 ) \ 505do { \ 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 ) \ 512do { \ 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 ) \ 520do { \ 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 ) \ 527do { \ 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 ) \ 534do { \ 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 ) \ 541do { \ 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 ) \ 548do { \ 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 ) \ 555do { \ 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 ) \ 562do { \ 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 ) \ 569do { \ 570 (DST)[0] *= S; \ 571 (DST)[1] *= S; \ 572} while (0) 573 574/** In-place scalar addition */ 575#define ACC_SCALAR_2V( DST, S ) \ 576do { \ 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 ) \ 583do { \ 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 */ 594static inline void 595COPY_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 619static inline GLfloat 620LINTERP(GLfloat t, GLfloat out, GLfloat in) 621{ 622 return out + t * (in - out); 623} 624 625static inline void 626INTERP_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 633static inline void 634INTERP_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 */ 662static inline void 663CROSS3(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 */ 672static inline GLfloat 673DOT2(const GLfloat a[2], const GLfloat b[2]) 674{ 675 return a[0] * b[0] + a[1] * b[1]; 676} 677 678static inline GLfloat 679DOT3(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 684static inline GLfloat 685DOT4(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 691static inline GLfloat 692LEN_SQUARED_3FV(const GLfloat v[3]) 693{ 694 return DOT3(v, v); 695} 696 697static inline GLfloat 698LEN_SQUARED_2FV(const GLfloat v[2]) 699{ 700 return DOT2(v, v); 701} 702 703 704static inline GLfloat 705LEN_3FV(const GLfloat v[3]) 706{ 707 return SQRTF(LEN_SQUARED_3FV(v)); 708} 709 710static inline GLfloat 711LEN_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. */ 718static inline void 719NORMALIZE_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