macros.h revision b8e80941
1848b8605Smrg/** 2848b8605Smrg * \file macros.h 3848b8605Smrg * A collection of useful macros. 4848b8605Smrg */ 5848b8605Smrg 6848b8605Smrg/* 7848b8605Smrg * Mesa 3-D graphics library 8848b8605Smrg * 9848b8605Smrg * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. 10848b8605Smrg * 11848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 12848b8605Smrg * copy of this software and associated documentation files (the "Software"), 13848b8605Smrg * to deal in the Software without restriction, including without limitation 14848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 15848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 16848b8605Smrg * Software is furnished to do so, subject to the following conditions: 17848b8605Smrg * 18848b8605Smrg * The above copyright notice and this permission notice shall be included 19848b8605Smrg * in all copies or substantial portions of the Software. 20848b8605Smrg * 21848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 22848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 24848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 25848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 26848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 27848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 28848b8605Smrg */ 29848b8605Smrg 30848b8605Smrg 31848b8605Smrg#ifndef MACROS_H 32848b8605Smrg#define MACROS_H 33848b8605Smrg 34b8e80941Smrg#include "util/macros.h" 35b8e80941Smrg#include "util/u_math.h" 36b8e80941Smrg#include "util/rounding.h" 37848b8605Smrg#include "imports.h" 38848b8605Smrg 39848b8605Smrg 40848b8605Smrg/** 41848b8605Smrg * \name Integer / float conversion for colors, normals, etc. 42848b8605Smrg */ 43848b8605Smrg/*@{*/ 44848b8605Smrg 45848b8605Smrg/** Convert GLubyte in [0,255] to GLfloat in [0.0,1.0] */ 46848b8605Smrgextern GLfloat _mesa_ubyte_to_float_color_tab[256]; 47848b8605Smrg#define UBYTE_TO_FLOAT(u) _mesa_ubyte_to_float_color_tab[(unsigned int)(u)] 48848b8605Smrg 49848b8605Smrg/** Convert GLfloat in [0.0,1.0] to GLubyte in [0,255] */ 50848b8605Smrg#define FLOAT_TO_UBYTE(X) ((GLubyte) (GLint) ((X) * 255.0F)) 51848b8605Smrg 52848b8605Smrg 53848b8605Smrg/** Convert GLbyte in [-128,127] to GLfloat in [-1.0,1.0] */ 54848b8605Smrg#define BYTE_TO_FLOAT(B) ((2.0F * (B) + 1.0F) * (1.0F/255.0F)) 55848b8605Smrg 56848b8605Smrg/** Convert GLfloat in [-1.0,1.0] to GLbyte in [-128,127] */ 57848b8605Smrg#define FLOAT_TO_BYTE(X) ( (((GLint) (255.0F * (X))) - 1) / 2 ) 58848b8605Smrg 59848b8605Smrg 60848b8605Smrg/** Convert GLbyte to GLfloat while preserving zero */ 61848b8605Smrg#define BYTE_TO_FLOATZ(B) ((B) == 0 ? 0.0F : BYTE_TO_FLOAT(B)) 62848b8605Smrg 63848b8605Smrg 64848b8605Smrg/** Convert GLbyte in [-128,127] to GLfloat in [-1.0,1.0], texture/fb data */ 65848b8605Smrg#define BYTE_TO_FLOAT_TEX(B) ((B) == -128 ? -1.0F : (B) * (1.0F/127.0F)) 66848b8605Smrg 67848b8605Smrg/** Convert GLfloat in [-1.0,1.0] to GLbyte in [-128,127], texture/fb data */ 68848b8605Smrg#define FLOAT_TO_BYTE_TEX(X) CLAMP( (GLint) (127.0F * (X)), -128, 127 ) 69848b8605Smrg 70848b8605Smrg/** Convert GLushort in [0,65535] to GLfloat in [0.0,1.0] */ 71848b8605Smrg#define USHORT_TO_FLOAT(S) ((GLfloat) (S) * (1.0F / 65535.0F)) 72848b8605Smrg 73848b8605Smrg/** Convert GLfloat in [0.0,1.0] to GLushort in [0, 65535] */ 74848b8605Smrg#define FLOAT_TO_USHORT(X) ((GLuint) ((X) * 65535.0F)) 75848b8605Smrg 76848b8605Smrg 77848b8605Smrg/** Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0] */ 78848b8605Smrg#define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F)) 79848b8605Smrg 80848b8605Smrg/** Convert GLfloat in [-1.0,1.0] to GLshort in [-32768,32767] */ 81848b8605Smrg#define FLOAT_TO_SHORT(X) ( (((GLint) (65535.0F * (X))) - 1) / 2 ) 82848b8605Smrg 83848b8605Smrg/** Convert GLshort to GLfloat while preserving zero */ 84848b8605Smrg#define SHORT_TO_FLOATZ(S) ((S) == 0 ? 0.0F : SHORT_TO_FLOAT(S)) 85848b8605Smrg 86848b8605Smrg 87848b8605Smrg/** Convert GLshort in [-32768,32767] to GLfloat in [-1.0,1.0], texture/fb data */ 88848b8605Smrg#define SHORT_TO_FLOAT_TEX(S) ((S) == -32768 ? -1.0F : (S) * (1.0F/32767.0F)) 89848b8605Smrg 90848b8605Smrg/** Convert GLfloat in [-1.0,1.0] to GLshort in [-32768,32767], texture/fb data */ 91848b8605Smrg#define FLOAT_TO_SHORT_TEX(X) ( (GLint) (32767.0F * (X)) ) 92848b8605Smrg 93848b8605Smrg 94848b8605Smrg/** Convert GLuint in [0,4294967295] to GLfloat in [0.0,1.0] */ 95848b8605Smrg#define UINT_TO_FLOAT(U) ((GLfloat) ((U) * (1.0F / 4294967295.0))) 96848b8605Smrg 97848b8605Smrg/** Convert GLfloat in [0.0,1.0] to GLuint in [0,4294967295] */ 98848b8605Smrg#define FLOAT_TO_UINT(X) ((GLuint) ((X) * 4294967295.0)) 99848b8605Smrg 100848b8605Smrg 101848b8605Smrg/** Convert GLint in [-2147483648,2147483647] to GLfloat in [-1.0,1.0] */ 102848b8605Smrg#define INT_TO_FLOAT(I) ((GLfloat) ((2.0F * (I) + 1.0F) * (1.0F/4294967294.0))) 103848b8605Smrg 104848b8605Smrg/** Convert GLfloat in [-1.0,1.0] to GLint in [-2147483648,2147483647] */ 105848b8605Smrg/* causes overflow: 106848b8605Smrg#define FLOAT_TO_INT(X) ( (((GLint) (4294967294.0 * (X))) - 1) / 2 ) 107848b8605Smrg*/ 108848b8605Smrg/* a close approximation: */ 109848b8605Smrg#define FLOAT_TO_INT(X) ( (GLint) (2147483647.0 * (X)) ) 110848b8605Smrg 111848b8605Smrg/** Convert GLfloat in [-1.0,1.0] to GLint64 in [-(1<<63),(1 << 63) -1] */ 112848b8605Smrg#define FLOAT_TO_INT64(X) ( (GLint64) (9223372036854775807.0 * (double)(X)) ) 113848b8605Smrg 114848b8605Smrg 115848b8605Smrg/** Convert GLint in [-2147483648,2147483647] to GLfloat in [-1.0,1.0], texture/fb data */ 116848b8605Smrg#define INT_TO_FLOAT_TEX(I) ((I) == -2147483648 ? -1.0F : (I) * (1.0F/2147483647.0)) 117848b8605Smrg 118848b8605Smrg/** Convert GLfloat in [-1.0,1.0] to GLint in [-2147483648,2147483647], texture/fb data */ 119848b8605Smrg#define FLOAT_TO_INT_TEX(X) ( (GLint) (2147483647.0 * (X)) ) 120848b8605Smrg 121848b8605Smrg 122848b8605Smrg#define BYTE_TO_UBYTE(b) ((GLubyte) ((b) < 0 ? 0 : (GLubyte) (b))) 123848b8605Smrg#define SHORT_TO_UBYTE(s) ((GLubyte) ((s) < 0 ? 0 : (GLubyte) ((s) >> 7))) 124848b8605Smrg#define USHORT_TO_UBYTE(s) ((GLubyte) ((s) >> 8)) 125848b8605Smrg#define INT_TO_UBYTE(i) ((GLubyte) ((i) < 0 ? 0 : (GLubyte) ((i) >> 23))) 126848b8605Smrg#define UINT_TO_UBYTE(i) ((GLubyte) ((i) >> 24)) 127848b8605Smrg 128848b8605Smrg 129848b8605Smrg#define BYTE_TO_USHORT(b) ((b) < 0 ? 0 : ((GLushort) (((b) * 65535) / 255))) 130848b8605Smrg#define UBYTE_TO_USHORT(b) (((GLushort) (b) << 8) | (GLushort) (b)) 131848b8605Smrg#define SHORT_TO_USHORT(s) ((s) < 0 ? 0 : ((GLushort) (((s) * 65535 / 32767)))) 132848b8605Smrg#define INT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 15))) 133848b8605Smrg#define UINT_TO_USHORT(i) ((i) < 0 ? 0 : ((GLushort) ((i) >> 16))) 134848b8605Smrg#define UNCLAMPED_FLOAT_TO_USHORT(us, f) \ 135b8e80941Smrg us = ( (GLushort) _mesa_lroundevenf( CLAMP((f), 0.0F, 1.0F) * 65535.0F) ) 136848b8605Smrg#define CLAMPED_FLOAT_TO_USHORT(us, f) \ 137b8e80941Smrg us = ( (GLushort) _mesa_lroundevenf( (f) * 65535.0F) ) 138848b8605Smrg 139848b8605Smrg#define UNCLAMPED_FLOAT_TO_SHORT(s, f) \ 140b8e80941Smrg s = ( (GLshort) _mesa_lroundevenf( CLAMP((f), -1.0F, 1.0F) * 32767.0F) ) 141848b8605Smrg 142848b8605Smrg/*** 143848b8605Smrg *** UNCLAMPED_FLOAT_TO_UBYTE: clamp float to [0,1] and map to ubyte in [0,255] 144848b8605Smrg *** CLAMPED_FLOAT_TO_UBYTE: map float known to be in [0,1] to ubyte in [0,255] 145848b8605Smrg ***/ 146848b8605Smrg#ifndef DEBUG 147848b8605Smrg/* This function/macro is sensitive to precision. Test very carefully 148848b8605Smrg * if you change it! 149848b8605Smrg */ 150848b8605Smrg#define UNCLAMPED_FLOAT_TO_UBYTE(UB, FLT) \ 151848b8605Smrg do { \ 152848b8605Smrg fi_type __tmp; \ 153848b8605Smrg __tmp.f = (FLT); \ 154848b8605Smrg if (__tmp.i < 0) \ 155848b8605Smrg UB = (GLubyte) 0; \ 156848b8605Smrg else if (__tmp.i >= IEEE_ONE) \ 157848b8605Smrg UB = (GLubyte) 255; \ 158848b8605Smrg else { \ 159848b8605Smrg __tmp.f = __tmp.f * (255.0F/256.0F) + 32768.0F; \ 160848b8605Smrg UB = (GLubyte) __tmp.i; \ 161848b8605Smrg } \ 162848b8605Smrg } while (0) 163848b8605Smrg#define CLAMPED_FLOAT_TO_UBYTE(UB, FLT) \ 164848b8605Smrg do { \ 165848b8605Smrg fi_type __tmp; \ 166848b8605Smrg __tmp.f = (FLT) * (255.0F/256.0F) + 32768.0F; \ 167848b8605Smrg UB = (GLubyte) __tmp.i; \ 168848b8605Smrg } while (0) 169848b8605Smrg#else 170848b8605Smrg#define UNCLAMPED_FLOAT_TO_UBYTE(ub, f) \ 171b8e80941Smrg ub = ((GLubyte) _mesa_lroundevenf(CLAMP((f), 0.0F, 1.0F) * 255.0F)) 172848b8605Smrg#define CLAMPED_FLOAT_TO_UBYTE(ub, f) \ 173b8e80941Smrg ub = ((GLubyte) _mesa_lroundevenf((f) * 255.0F)) 174848b8605Smrg#endif 175848b8605Smrg 176b8e80941Smrgstatic fi_type UINT_AS_UNION(GLuint u) 177848b8605Smrg{ 178848b8605Smrg fi_type tmp; 179b8e80941Smrg tmp.u = u; 180b8e80941Smrg return tmp; 181848b8605Smrg} 182848b8605Smrg 183b8e80941Smrgstatic inline fi_type INT_AS_UNION(GLint i) 184848b8605Smrg{ 185848b8605Smrg fi_type tmp; 186b8e80941Smrg tmp.i = i; 187b8e80941Smrg return tmp; 188848b8605Smrg} 189848b8605Smrg 190b8e80941Smrgstatic inline fi_type FLOAT_AS_UNION(GLfloat f) 191848b8605Smrg{ 192848b8605Smrg fi_type tmp; 193848b8605Smrg tmp.f = f; 194b8e80941Smrg return tmp; 195848b8605Smrg} 196848b8605Smrg 197848b8605Smrg/** 198848b8605Smrg * Convert a floating point value to an unsigned fixed point value. 199848b8605Smrg * 200848b8605Smrg * \param frac_bits The number of bits used to store the fractional part. 201848b8605Smrg */ 202b8e80941Smrgstatic inline uint32_t 203848b8605SmrgU_FIXED(float value, uint32_t frac_bits) 204848b8605Smrg{ 205848b8605Smrg value *= (1 << frac_bits); 206848b8605Smrg return value < 0.0f ? 0 : (uint32_t) value; 207848b8605Smrg} 208848b8605Smrg 209848b8605Smrg/** 210848b8605Smrg * Convert a floating point value to an signed fixed point value. 211848b8605Smrg * 212848b8605Smrg * \param frac_bits The number of bits used to store the fractional part. 213848b8605Smrg */ 214b8e80941Smrgstatic inline int32_t 215848b8605SmrgS_FIXED(float value, uint32_t frac_bits) 216848b8605Smrg{ 217848b8605Smrg return (int32_t) (value * (1 << frac_bits)); 218848b8605Smrg} 219848b8605Smrg/*@}*/ 220848b8605Smrg 221848b8605Smrg 222848b8605Smrg/** Stepping a GLfloat pointer by a byte stride */ 223848b8605Smrg#define STRIDE_F(p, i) (p = (GLfloat *)((GLubyte *)p + i)) 224848b8605Smrg/** Stepping a GLuint pointer by a byte stride */ 225848b8605Smrg#define STRIDE_UI(p, i) (p = (GLuint *)((GLubyte *)p + i)) 226848b8605Smrg/** Stepping a GLubyte[4] pointer by a byte stride */ 227848b8605Smrg#define STRIDE_4UB(p, i) (p = (GLubyte (*)[4])((GLubyte *)p + i)) 228848b8605Smrg/** Stepping a GLfloat[4] pointer by a byte stride */ 229848b8605Smrg#define STRIDE_4F(p, i) (p = (GLfloat (*)[4])((GLubyte *)p + i)) 230848b8605Smrg/** Stepping a \p t pointer by a byte stride */ 231848b8605Smrg#define STRIDE_T(p, t, i) (p = (t)((GLubyte *)p + i)) 232848b8605Smrg 233848b8605Smrg 234848b8605Smrg/**********************************************************************/ 235848b8605Smrg/** \name 4-element vector operations */ 236848b8605Smrg/*@{*/ 237848b8605Smrg 238848b8605Smrg/** Zero */ 239848b8605Smrg#define ZERO_4V( DST ) (DST)[0] = (DST)[1] = (DST)[2] = (DST)[3] = 0 240848b8605Smrg 241848b8605Smrg/** Test for equality */ 242848b8605Smrg#define TEST_EQ_4V(a,b) ((a)[0] == (b)[0] && \ 243848b8605Smrg (a)[1] == (b)[1] && \ 244848b8605Smrg (a)[2] == (b)[2] && \ 245848b8605Smrg (a)[3] == (b)[3]) 246848b8605Smrg 247848b8605Smrg/** Test for equality (unsigned bytes) */ 248848b8605Smrgstatic inline GLboolean 249848b8605SmrgTEST_EQ_4UBV(const GLubyte a[4], const GLubyte b[4]) 250848b8605Smrg{ 251848b8605Smrg#if defined(__i386__) 252848b8605Smrg return *((const GLuint *) a) == *((const GLuint *) b); 253848b8605Smrg#else 254848b8605Smrg return TEST_EQ_4V(a, b); 255848b8605Smrg#endif 256848b8605Smrg} 257848b8605Smrg 258848b8605Smrg 259848b8605Smrg/** Copy a 4-element vector */ 260848b8605Smrg#define COPY_4V( DST, SRC ) \ 261848b8605Smrgdo { \ 262848b8605Smrg (DST)[0] = (SRC)[0]; \ 263848b8605Smrg (DST)[1] = (SRC)[1]; \ 264848b8605Smrg (DST)[2] = (SRC)[2]; \ 265848b8605Smrg (DST)[3] = (SRC)[3]; \ 266848b8605Smrg} while (0) 267848b8605Smrg 268848b8605Smrg/** Copy a 4-element unsigned byte vector */ 269848b8605Smrgstatic inline void 270848b8605SmrgCOPY_4UBV(GLubyte dst[4], const GLubyte src[4]) 271848b8605Smrg{ 272848b8605Smrg#if defined(__i386__) 273848b8605Smrg *((GLuint *) dst) = *((GLuint *) src); 274848b8605Smrg#else 275848b8605Smrg /* The GLuint cast might fail if DST or SRC are not dword-aligned (RISC) */ 276848b8605Smrg COPY_4V(dst, src); 277848b8605Smrg#endif 278848b8605Smrg} 279848b8605Smrg 280848b8605Smrg/** Copy \p SZ elements into a 4-element vector */ 281848b8605Smrg#define COPY_SZ_4V(DST, SZ, SRC) \ 282848b8605Smrgdo { \ 283848b8605Smrg switch (SZ) { \ 284848b8605Smrg case 4: (DST)[3] = (SRC)[3]; \ 285848b8605Smrg case 3: (DST)[2] = (SRC)[2]; \ 286848b8605Smrg case 2: (DST)[1] = (SRC)[1]; \ 287848b8605Smrg case 1: (DST)[0] = (SRC)[0]; \ 288848b8605Smrg } \ 289848b8605Smrg} while(0) 290848b8605Smrg 291848b8605Smrg/** Copy \p SZ elements into a homegeneous (4-element) vector, giving 292848b8605Smrg * default values to the remaining */ 293848b8605Smrg#define COPY_CLEAN_4V(DST, SZ, SRC) \ 294848b8605Smrgdo { \ 295848b8605Smrg ASSIGN_4V( DST, 0, 0, 0, 1 ); \ 296848b8605Smrg COPY_SZ_4V( DST, SZ, SRC ); \ 297848b8605Smrg} while (0) 298848b8605Smrg 299848b8605Smrg/** Subtraction */ 300848b8605Smrg#define SUB_4V( DST, SRCA, SRCB ) \ 301848b8605Smrgdo { \ 302848b8605Smrg (DST)[0] = (SRCA)[0] - (SRCB)[0]; \ 303848b8605Smrg (DST)[1] = (SRCA)[1] - (SRCB)[1]; \ 304848b8605Smrg (DST)[2] = (SRCA)[2] - (SRCB)[2]; \ 305848b8605Smrg (DST)[3] = (SRCA)[3] - (SRCB)[3]; \ 306848b8605Smrg} while (0) 307848b8605Smrg 308848b8605Smrg/** Addition */ 309848b8605Smrg#define ADD_4V( DST, SRCA, SRCB ) \ 310848b8605Smrgdo { \ 311848b8605Smrg (DST)[0] = (SRCA)[0] + (SRCB)[0]; \ 312848b8605Smrg (DST)[1] = (SRCA)[1] + (SRCB)[1]; \ 313848b8605Smrg (DST)[2] = (SRCA)[2] + (SRCB)[2]; \ 314848b8605Smrg (DST)[3] = (SRCA)[3] + (SRCB)[3]; \ 315848b8605Smrg} while (0) 316848b8605Smrg 317848b8605Smrg/** Element-wise multiplication */ 318848b8605Smrg#define SCALE_4V( DST, SRCA, SRCB ) \ 319848b8605Smrgdo { \ 320848b8605Smrg (DST)[0] = (SRCA)[0] * (SRCB)[0]; \ 321848b8605Smrg (DST)[1] = (SRCA)[1] * (SRCB)[1]; \ 322848b8605Smrg (DST)[2] = (SRCA)[2] * (SRCB)[2]; \ 323848b8605Smrg (DST)[3] = (SRCA)[3] * (SRCB)[3]; \ 324848b8605Smrg} while (0) 325848b8605Smrg 326848b8605Smrg/** In-place addition */ 327848b8605Smrg#define ACC_4V( DST, SRC ) \ 328848b8605Smrgdo { \ 329848b8605Smrg (DST)[0] += (SRC)[0]; \ 330848b8605Smrg (DST)[1] += (SRC)[1]; \ 331848b8605Smrg (DST)[2] += (SRC)[2]; \ 332848b8605Smrg (DST)[3] += (SRC)[3]; \ 333848b8605Smrg} while (0) 334848b8605Smrg 335848b8605Smrg/** Element-wise multiplication and addition */ 336848b8605Smrg#define ACC_SCALE_4V( DST, SRCA, SRCB ) \ 337848b8605Smrgdo { \ 338848b8605Smrg (DST)[0] += (SRCA)[0] * (SRCB)[0]; \ 339848b8605Smrg (DST)[1] += (SRCA)[1] * (SRCB)[1]; \ 340848b8605Smrg (DST)[2] += (SRCA)[2] * (SRCB)[2]; \ 341848b8605Smrg (DST)[3] += (SRCA)[3] * (SRCB)[3]; \ 342848b8605Smrg} while (0) 343848b8605Smrg 344848b8605Smrg/** In-place scalar multiplication and addition */ 345848b8605Smrg#define ACC_SCALE_SCALAR_4V( DST, S, SRCB ) \ 346848b8605Smrgdo { \ 347848b8605Smrg (DST)[0] += S * (SRCB)[0]; \ 348848b8605Smrg (DST)[1] += S * (SRCB)[1]; \ 349848b8605Smrg (DST)[2] += S * (SRCB)[2]; \ 350848b8605Smrg (DST)[3] += S * (SRCB)[3]; \ 351848b8605Smrg} while (0) 352848b8605Smrg 353848b8605Smrg/** Scalar multiplication */ 354848b8605Smrg#define SCALE_SCALAR_4V( DST, S, SRCB ) \ 355848b8605Smrgdo { \ 356848b8605Smrg (DST)[0] = S * (SRCB)[0]; \ 357848b8605Smrg (DST)[1] = S * (SRCB)[1]; \ 358848b8605Smrg (DST)[2] = S * (SRCB)[2]; \ 359848b8605Smrg (DST)[3] = S * (SRCB)[3]; \ 360848b8605Smrg} while (0) 361848b8605Smrg 362848b8605Smrg/** In-place scalar multiplication */ 363848b8605Smrg#define SELF_SCALE_SCALAR_4V( DST, S ) \ 364848b8605Smrgdo { \ 365848b8605Smrg (DST)[0] *= S; \ 366848b8605Smrg (DST)[1] *= S; \ 367848b8605Smrg (DST)[2] *= S; \ 368848b8605Smrg (DST)[3] *= S; \ 369848b8605Smrg} while (0) 370848b8605Smrg 371848b8605Smrg/*@}*/ 372848b8605Smrg 373848b8605Smrg 374848b8605Smrg/**********************************************************************/ 375848b8605Smrg/** \name 3-element vector operations*/ 376848b8605Smrg/*@{*/ 377848b8605Smrg 378848b8605Smrg/** Zero */ 379848b8605Smrg#define ZERO_3V( DST ) (DST)[0] = (DST)[1] = (DST)[2] = 0 380848b8605Smrg 381848b8605Smrg/** Test for equality */ 382848b8605Smrg#define TEST_EQ_3V(a,b) \ 383848b8605Smrg ((a)[0] == (b)[0] && \ 384848b8605Smrg (a)[1] == (b)[1] && \ 385848b8605Smrg (a)[2] == (b)[2]) 386848b8605Smrg 387848b8605Smrg/** Copy a 3-element vector */ 388848b8605Smrg#define COPY_3V( DST, SRC ) \ 389848b8605Smrgdo { \ 390848b8605Smrg (DST)[0] = (SRC)[0]; \ 391848b8605Smrg (DST)[1] = (SRC)[1]; \ 392848b8605Smrg (DST)[2] = (SRC)[2]; \ 393848b8605Smrg} while (0) 394848b8605Smrg 395848b8605Smrg/** Copy a 3-element vector with cast */ 396848b8605Smrg#define COPY_3V_CAST( DST, SRC, CAST ) \ 397848b8605Smrgdo { \ 398848b8605Smrg (DST)[0] = (CAST)(SRC)[0]; \ 399848b8605Smrg (DST)[1] = (CAST)(SRC)[1]; \ 400848b8605Smrg (DST)[2] = (CAST)(SRC)[2]; \ 401848b8605Smrg} while (0) 402848b8605Smrg 403848b8605Smrg/** Copy a 3-element float vector */ 404848b8605Smrg#define COPY_3FV( DST, SRC ) \ 405848b8605Smrgdo { \ 406848b8605Smrg const GLfloat *_tmp = (SRC); \ 407848b8605Smrg (DST)[0] = _tmp[0]; \ 408848b8605Smrg (DST)[1] = _tmp[1]; \ 409848b8605Smrg (DST)[2] = _tmp[2]; \ 410848b8605Smrg} while (0) 411848b8605Smrg 412848b8605Smrg/** Subtraction */ 413848b8605Smrg#define SUB_3V( DST, SRCA, SRCB ) \ 414848b8605Smrgdo { \ 415848b8605Smrg (DST)[0] = (SRCA)[0] - (SRCB)[0]; \ 416848b8605Smrg (DST)[1] = (SRCA)[1] - (SRCB)[1]; \ 417848b8605Smrg (DST)[2] = (SRCA)[2] - (SRCB)[2]; \ 418848b8605Smrg} while (0) 419848b8605Smrg 420848b8605Smrg/** Addition */ 421848b8605Smrg#define ADD_3V( DST, SRCA, SRCB ) \ 422848b8605Smrgdo { \ 423848b8605Smrg (DST)[0] = (SRCA)[0] + (SRCB)[0]; \ 424848b8605Smrg (DST)[1] = (SRCA)[1] + (SRCB)[1]; \ 425848b8605Smrg (DST)[2] = (SRCA)[2] + (SRCB)[2]; \ 426848b8605Smrg} while (0) 427848b8605Smrg 428848b8605Smrg/** In-place scalar multiplication */ 429848b8605Smrg#define SCALE_3V( DST, SRCA, SRCB ) \ 430848b8605Smrgdo { \ 431848b8605Smrg (DST)[0] = (SRCA)[0] * (SRCB)[0]; \ 432848b8605Smrg (DST)[1] = (SRCA)[1] * (SRCB)[1]; \ 433848b8605Smrg (DST)[2] = (SRCA)[2] * (SRCB)[2]; \ 434848b8605Smrg} while (0) 435848b8605Smrg 436848b8605Smrg/** In-place element-wise multiplication */ 437848b8605Smrg#define SELF_SCALE_3V( DST, SRC ) \ 438848b8605Smrgdo { \ 439848b8605Smrg (DST)[0] *= (SRC)[0]; \ 440848b8605Smrg (DST)[1] *= (SRC)[1]; \ 441848b8605Smrg (DST)[2] *= (SRC)[2]; \ 442848b8605Smrg} while (0) 443848b8605Smrg 444848b8605Smrg/** In-place addition */ 445848b8605Smrg#define ACC_3V( DST, SRC ) \ 446848b8605Smrgdo { \ 447848b8605Smrg (DST)[0] += (SRC)[0]; \ 448848b8605Smrg (DST)[1] += (SRC)[1]; \ 449848b8605Smrg (DST)[2] += (SRC)[2]; \ 450848b8605Smrg} while (0) 451848b8605Smrg 452848b8605Smrg/** Element-wise multiplication and addition */ 453848b8605Smrg#define ACC_SCALE_3V( DST, SRCA, SRCB ) \ 454848b8605Smrgdo { \ 455848b8605Smrg (DST)[0] += (SRCA)[0] * (SRCB)[0]; \ 456848b8605Smrg (DST)[1] += (SRCA)[1] * (SRCB)[1]; \ 457848b8605Smrg (DST)[2] += (SRCA)[2] * (SRCB)[2]; \ 458848b8605Smrg} while (0) 459848b8605Smrg 460848b8605Smrg/** Scalar multiplication */ 461848b8605Smrg#define SCALE_SCALAR_3V( DST, S, SRCB ) \ 462848b8605Smrgdo { \ 463848b8605Smrg (DST)[0] = S * (SRCB)[0]; \ 464848b8605Smrg (DST)[1] = S * (SRCB)[1]; \ 465848b8605Smrg (DST)[2] = S * (SRCB)[2]; \ 466848b8605Smrg} while (0) 467848b8605Smrg 468848b8605Smrg/** In-place scalar multiplication and addition */ 469848b8605Smrg#define ACC_SCALE_SCALAR_3V( DST, S, SRCB ) \ 470848b8605Smrgdo { \ 471848b8605Smrg (DST)[0] += S * (SRCB)[0]; \ 472848b8605Smrg (DST)[1] += S * (SRCB)[1]; \ 473848b8605Smrg (DST)[2] += S * (SRCB)[2]; \ 474848b8605Smrg} while (0) 475848b8605Smrg 476848b8605Smrg/** In-place scalar multiplication */ 477848b8605Smrg#define SELF_SCALE_SCALAR_3V( DST, S ) \ 478848b8605Smrgdo { \ 479848b8605Smrg (DST)[0] *= S; \ 480848b8605Smrg (DST)[1] *= S; \ 481848b8605Smrg (DST)[2] *= S; \ 482848b8605Smrg} while (0) 483848b8605Smrg 484848b8605Smrg/** In-place scalar addition */ 485848b8605Smrg#define ACC_SCALAR_3V( DST, S ) \ 486848b8605Smrgdo { \ 487848b8605Smrg (DST)[0] += S; \ 488848b8605Smrg (DST)[1] += S; \ 489848b8605Smrg (DST)[2] += S; \ 490848b8605Smrg} while (0) 491848b8605Smrg 492848b8605Smrg/** Assignment */ 493848b8605Smrg#define ASSIGN_3V( V, V0, V1, V2 ) \ 494848b8605Smrgdo { \ 495848b8605Smrg V[0] = V0; \ 496848b8605Smrg V[1] = V1; \ 497848b8605Smrg V[2] = V2; \ 498848b8605Smrg} while(0) 499848b8605Smrg 500848b8605Smrg/*@}*/ 501848b8605Smrg 502848b8605Smrg 503848b8605Smrg/**********************************************************************/ 504848b8605Smrg/** \name 2-element vector operations*/ 505848b8605Smrg/*@{*/ 506848b8605Smrg 507848b8605Smrg/** Zero */ 508848b8605Smrg#define ZERO_2V( DST ) (DST)[0] = (DST)[1] = 0 509848b8605Smrg 510848b8605Smrg/** Copy a 2-element vector */ 511848b8605Smrg#define COPY_2V( DST, SRC ) \ 512848b8605Smrgdo { \ 513848b8605Smrg (DST)[0] = (SRC)[0]; \ 514848b8605Smrg (DST)[1] = (SRC)[1]; \ 515848b8605Smrg} while (0) 516848b8605Smrg 517848b8605Smrg/** Copy a 2-element vector with cast */ 518848b8605Smrg#define COPY_2V_CAST( DST, SRC, CAST ) \ 519848b8605Smrgdo { \ 520848b8605Smrg (DST)[0] = (CAST)(SRC)[0]; \ 521848b8605Smrg (DST)[1] = (CAST)(SRC)[1]; \ 522848b8605Smrg} while (0) 523848b8605Smrg 524848b8605Smrg/** Copy a 2-element float vector */ 525848b8605Smrg#define COPY_2FV( DST, SRC ) \ 526848b8605Smrgdo { \ 527848b8605Smrg const GLfloat *_tmp = (SRC); \ 528848b8605Smrg (DST)[0] = _tmp[0]; \ 529848b8605Smrg (DST)[1] = _tmp[1]; \ 530848b8605Smrg} while (0) 531848b8605Smrg 532848b8605Smrg/** Subtraction */ 533848b8605Smrg#define SUB_2V( DST, SRCA, SRCB ) \ 534848b8605Smrgdo { \ 535848b8605Smrg (DST)[0] = (SRCA)[0] - (SRCB)[0]; \ 536848b8605Smrg (DST)[1] = (SRCA)[1] - (SRCB)[1]; \ 537848b8605Smrg} while (0) 538848b8605Smrg 539848b8605Smrg/** Addition */ 540848b8605Smrg#define ADD_2V( DST, SRCA, SRCB ) \ 541848b8605Smrgdo { \ 542848b8605Smrg (DST)[0] = (SRCA)[0] + (SRCB)[0]; \ 543848b8605Smrg (DST)[1] = (SRCA)[1] + (SRCB)[1]; \ 544848b8605Smrg} while (0) 545848b8605Smrg 546848b8605Smrg/** In-place scalar multiplication */ 547848b8605Smrg#define SCALE_2V( DST, SRCA, SRCB ) \ 548848b8605Smrgdo { \ 549848b8605Smrg (DST)[0] = (SRCA)[0] * (SRCB)[0]; \ 550848b8605Smrg (DST)[1] = (SRCA)[1] * (SRCB)[1]; \ 551848b8605Smrg} while (0) 552848b8605Smrg 553848b8605Smrg/** In-place addition */ 554848b8605Smrg#define ACC_2V( DST, SRC ) \ 555848b8605Smrgdo { \ 556848b8605Smrg (DST)[0] += (SRC)[0]; \ 557848b8605Smrg (DST)[1] += (SRC)[1]; \ 558848b8605Smrg} while (0) 559848b8605Smrg 560848b8605Smrg/** Element-wise multiplication and addition */ 561848b8605Smrg#define ACC_SCALE_2V( DST, SRCA, SRCB ) \ 562848b8605Smrgdo { \ 563848b8605Smrg (DST)[0] += (SRCA)[0] * (SRCB)[0]; \ 564848b8605Smrg (DST)[1] += (SRCA)[1] * (SRCB)[1]; \ 565848b8605Smrg} while (0) 566848b8605Smrg 567848b8605Smrg/** Scalar multiplication */ 568848b8605Smrg#define SCALE_SCALAR_2V( DST, S, SRCB ) \ 569848b8605Smrgdo { \ 570848b8605Smrg (DST)[0] = S * (SRCB)[0]; \ 571848b8605Smrg (DST)[1] = S * (SRCB)[1]; \ 572848b8605Smrg} while (0) 573848b8605Smrg 574848b8605Smrg/** In-place scalar multiplication and addition */ 575848b8605Smrg#define ACC_SCALE_SCALAR_2V( DST, S, SRCB ) \ 576848b8605Smrgdo { \ 577848b8605Smrg (DST)[0] += S * (SRCB)[0]; \ 578848b8605Smrg (DST)[1] += S * (SRCB)[1]; \ 579848b8605Smrg} while (0) 580848b8605Smrg 581848b8605Smrg/** In-place scalar multiplication */ 582848b8605Smrg#define SELF_SCALE_SCALAR_2V( DST, S ) \ 583848b8605Smrgdo { \ 584848b8605Smrg (DST)[0] *= S; \ 585848b8605Smrg (DST)[1] *= S; \ 586848b8605Smrg} while (0) 587848b8605Smrg 588848b8605Smrg/** In-place scalar addition */ 589848b8605Smrg#define ACC_SCALAR_2V( DST, S ) \ 590848b8605Smrgdo { \ 591848b8605Smrg (DST)[0] += S; \ 592848b8605Smrg (DST)[1] += S; \ 593848b8605Smrg} while (0) 594848b8605Smrg 595848b8605Smrg/** Assign scalers to short vectors */ 596848b8605Smrg#define ASSIGN_2V( V, V0, V1 ) \ 597848b8605Smrgdo { \ 598848b8605Smrg V[0] = V0; \ 599848b8605Smrg V[1] = V1; \ 600848b8605Smrg} while(0) 601848b8605Smrg 602848b8605Smrg/*@}*/ 603848b8605Smrg 604848b8605Smrg/** Copy \p sz elements into a homegeneous (4-element) vector, giving 605848b8605Smrg * default values to the remaining components. 606848b8605Smrg * The default values are chosen based on \p type. 607848b8605Smrg */ 608848b8605Smrgstatic inline void 609b8e80941SmrgCOPY_CLEAN_4V_TYPE_AS_UNION(fi_type dst[4], int sz, const fi_type src[4], 610848b8605Smrg GLenum type) 611848b8605Smrg{ 612848b8605Smrg switch (type) { 613848b8605Smrg case GL_FLOAT: 614b8e80941Smrg ASSIGN_4V(dst, FLOAT_AS_UNION(0), FLOAT_AS_UNION(0), 615b8e80941Smrg FLOAT_AS_UNION(0), FLOAT_AS_UNION(1)); 616848b8605Smrg break; 617848b8605Smrg case GL_INT: 618b8e80941Smrg ASSIGN_4V(dst, INT_AS_UNION(0), INT_AS_UNION(0), 619b8e80941Smrg INT_AS_UNION(0), INT_AS_UNION(1)); 620848b8605Smrg break; 621848b8605Smrg case GL_UNSIGNED_INT: 622b8e80941Smrg ASSIGN_4V(dst, UINT_AS_UNION(0), UINT_AS_UNION(0), 623b8e80941Smrg UINT_AS_UNION(0), UINT_AS_UNION(1)); 624848b8605Smrg break; 625848b8605Smrg default: 626b8e80941Smrg ASSIGN_4V(dst, FLOAT_AS_UNION(0), FLOAT_AS_UNION(0), 627b8e80941Smrg FLOAT_AS_UNION(0), FLOAT_AS_UNION(1)); /* silence warnings */ 628b8e80941Smrg assert(!"Unexpected type in COPY_CLEAN_4V_TYPE_AS_UNION macro"); 629848b8605Smrg } 630848b8605Smrg COPY_SZ_4V(dst, sz, src); 631848b8605Smrg} 632848b8605Smrg 633848b8605Smrg/** \name Linear interpolation functions */ 634848b8605Smrg/*@{*/ 635848b8605Smrg 636848b8605Smrgstatic inline GLfloat 637848b8605SmrgLINTERP(GLfloat t, GLfloat out, GLfloat in) 638848b8605Smrg{ 639848b8605Smrg return out + t * (in - out); 640848b8605Smrg} 641848b8605Smrg 642848b8605Smrgstatic inline void 643848b8605SmrgINTERP_3F(GLfloat t, GLfloat dst[3], const GLfloat out[3], const GLfloat in[3]) 644848b8605Smrg{ 645848b8605Smrg dst[0] = LINTERP( t, out[0], in[0] ); 646848b8605Smrg dst[1] = LINTERP( t, out[1], in[1] ); 647848b8605Smrg dst[2] = LINTERP( t, out[2], in[2] ); 648848b8605Smrg} 649848b8605Smrg 650848b8605Smrgstatic inline void 651848b8605SmrgINTERP_4F(GLfloat t, GLfloat dst[4], const GLfloat out[4], const GLfloat in[4]) 652848b8605Smrg{ 653848b8605Smrg dst[0] = LINTERP( t, out[0], in[0] ); 654848b8605Smrg dst[1] = LINTERP( t, out[1], in[1] ); 655848b8605Smrg dst[2] = LINTERP( t, out[2], in[2] ); 656848b8605Smrg dst[3] = LINTERP( t, out[3], in[3] ); 657848b8605Smrg} 658848b8605Smrg 659848b8605Smrg/*@}*/ 660848b8605Smrg 661848b8605Smrg 662848b8605Smrg 663848b8605Smrgstatic inline unsigned 664848b8605Smrgminify(unsigned value, unsigned levels) 665848b8605Smrg{ 666848b8605Smrg return MAX2(1, value >> levels); 667848b8605Smrg} 668848b8605Smrg 669848b8605Smrg/** 670848b8605Smrg * Align a value up to an alignment value 671848b8605Smrg * 672848b8605Smrg * If \c value is not already aligned to the requested alignment value, it 673848b8605Smrg * will be rounded up. 674848b8605Smrg * 675848b8605Smrg * \param value Value to be rounded 676848b8605Smrg * \param alignment Alignment value to be used. This must be a power of two. 677848b8605Smrg * 678848b8605Smrg * \sa ROUND_DOWN_TO() 679848b8605Smrg */ 680b8e80941Smrgstatic inline uintptr_t 681b8e80941SmrgALIGN(uintptr_t value, int32_t alignment) 682b8e80941Smrg{ 683b8e80941Smrg assert((alignment > 0) && _mesa_is_pow_two(alignment)); 684b8e80941Smrg return (((value) + (alignment) - 1) & ~((alignment) - 1)); 685b8e80941Smrg} 686b8e80941Smrg 687b8e80941Smrg/** 688b8e80941Smrg * Like ALIGN(), but works with a non-power-of-two alignment. 689b8e80941Smrg */ 690b8e80941Smrgstatic inline uintptr_t 691b8e80941SmrgALIGN_NPOT(uintptr_t value, int32_t alignment) 692b8e80941Smrg{ 693b8e80941Smrg assert(alignment > 0); 694b8e80941Smrg return (value + alignment - 1) / alignment * alignment; 695b8e80941Smrg} 696848b8605Smrg 697848b8605Smrg/** 698848b8605Smrg * Align a value down to an alignment value 699848b8605Smrg * 700848b8605Smrg * If \c value is not already aligned to the requested alignment value, it 701848b8605Smrg * will be rounded down. 702848b8605Smrg * 703848b8605Smrg * \param value Value to be rounded 704848b8605Smrg * \param alignment Alignment value to be used. This must be a power of two. 705848b8605Smrg * 706848b8605Smrg * \sa ALIGN() 707848b8605Smrg */ 708b8e80941Smrgstatic inline uintptr_t 709b8e80941SmrgROUND_DOWN_TO(uintptr_t value, int32_t alignment) 710b8e80941Smrg{ 711b8e80941Smrg assert((alignment > 0) && _mesa_is_pow_two(alignment)); 712b8e80941Smrg return ((value) & ~(alignment - 1)); 713b8e80941Smrg} 714848b8605Smrg 715848b8605Smrg 716848b8605Smrg/** Cross product of two 3-element vectors */ 717848b8605Smrgstatic inline void 718848b8605SmrgCROSS3(GLfloat n[3], const GLfloat u[3], const GLfloat v[3]) 719848b8605Smrg{ 720848b8605Smrg n[0] = u[1] * v[2] - u[2] * v[1]; 721848b8605Smrg n[1] = u[2] * v[0] - u[0] * v[2]; 722848b8605Smrg n[2] = u[0] * v[1] - u[1] * v[0]; 723848b8605Smrg} 724848b8605Smrg 725848b8605Smrg 726848b8605Smrg/** Dot product of two 2-element vectors */ 727848b8605Smrgstatic inline GLfloat 728848b8605SmrgDOT2(const GLfloat a[2], const GLfloat b[2]) 729848b8605Smrg{ 730848b8605Smrg return a[0] * b[0] + a[1] * b[1]; 731848b8605Smrg} 732848b8605Smrg 733848b8605Smrgstatic inline GLfloat 734848b8605SmrgDOT3(const GLfloat a[3], const GLfloat b[3]) 735848b8605Smrg{ 736848b8605Smrg return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; 737848b8605Smrg} 738848b8605Smrg 739848b8605Smrgstatic inline GLfloat 740848b8605SmrgDOT4(const GLfloat a[4], const GLfloat b[4]) 741848b8605Smrg{ 742848b8605Smrg return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]; 743848b8605Smrg} 744848b8605Smrg 745848b8605Smrg 746848b8605Smrgstatic inline GLfloat 747848b8605SmrgLEN_SQUARED_3FV(const GLfloat v[3]) 748848b8605Smrg{ 749848b8605Smrg return DOT3(v, v); 750848b8605Smrg} 751848b8605Smrg 752848b8605Smrgstatic inline GLfloat 753848b8605SmrgLEN_SQUARED_2FV(const GLfloat v[2]) 754848b8605Smrg{ 755848b8605Smrg return DOT2(v, v); 756848b8605Smrg} 757848b8605Smrg 758848b8605Smrg 759848b8605Smrgstatic inline GLfloat 760848b8605SmrgLEN_3FV(const GLfloat v[3]) 761848b8605Smrg{ 762848b8605Smrg return sqrtf(LEN_SQUARED_3FV(v)); 763848b8605Smrg} 764848b8605Smrg 765848b8605Smrgstatic inline GLfloat 766848b8605SmrgLEN_2FV(const GLfloat v[2]) 767848b8605Smrg{ 768848b8605Smrg return sqrtf(LEN_SQUARED_2FV(v)); 769848b8605Smrg} 770848b8605Smrg 771848b8605Smrg 772848b8605Smrg/* Normalize a 3-element vector to unit length. */ 773848b8605Smrgstatic inline void 774848b8605SmrgNORMALIZE_3FV(GLfloat v[3]) 775848b8605Smrg{ 776848b8605Smrg GLfloat len = (GLfloat) LEN_SQUARED_3FV(v); 777848b8605Smrg if (len) { 778b8e80941Smrg len = 1.0f / sqrtf(len); 779848b8605Smrg v[0] *= len; 780848b8605Smrg v[1] *= len; 781848b8605Smrg v[2] *= len; 782848b8605Smrg } 783848b8605Smrg} 784848b8605Smrg 785848b8605Smrg 786848b8605Smrg/** Test two floats have opposite signs */ 787848b8605Smrgstatic inline GLboolean 788848b8605SmrgDIFFERENT_SIGNS(GLfloat x, GLfloat y) 789848b8605Smrg{ 790b8e80941Smrg#ifdef _MSC_VER 791b8e80941Smrg#pragma warning( push ) 792b8e80941Smrg#pragma warning( disable : 6334 ) /* sizeof operator applied to an expression with an operator may yield unexpected results */ 793b8e80941Smrg#endif 794848b8605Smrg return signbit(x) != signbit(y); 795b8e80941Smrg#ifdef _MSC_VER 796b8e80941Smrg#pragma warning( pop ) 797b8e80941Smrg#endif 798848b8605Smrg} 799848b8605Smrg 800848b8605Smrg 801848b8605Smrg/** casts to silence warnings with some compilers */ 802848b8605Smrg#define ENUM_TO_INT(E) ((GLint)(E)) 803848b8605Smrg#define ENUM_TO_FLOAT(E) ((GLfloat)(GLint)(E)) 804848b8605Smrg#define ENUM_TO_DOUBLE(E) ((GLdouble)(GLint)(E)) 805848b8605Smrg#define ENUM_TO_BOOLEAN(E) ((E) ? GL_TRUE : GL_FALSE) 806848b8605Smrg 807848b8605Smrg 808848b8605Smrg/* Stringify */ 809848b8605Smrg#define STRINGIFY(x) #x 810848b8605Smrg 811848b8605Smrg#endif 812