add BLI_strcpy_rlen, replace strcat, which was used in misleading way.
[blender.git] / intern / cycles / util / util_types.h
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #ifndef __UTIL_TYPES_H__
20 #define __UTIL_TYPES_H__
21
22 #ifndef __KERNEL_OPENCL__
23
24 #include <stdlib.h>
25
26 #endif
27
28 /* Qualifiers for kernel code shared by CPU and GPU */
29
30 #ifndef __KERNEL_GPU__
31
32 #define __device static inline
33 #define __device_noinline static
34 #define __global
35 #define __local
36 #define __shared
37 #define __constant
38
39 #if defined(_WIN32) && !defined(FREE_WINDOWS)
40 #define __device_inline static __forceinline
41 #define __align(...) __declspec(align(__VA_ARGS__))
42 #define __may_alias
43 #else
44 #define __device_inline static inline __attribute__((always_inline))
45 #ifndef FREE_WINDOWS64
46 #define __forceinline inline __attribute__((always_inline))
47 #endif
48 #define __align(...) __attribute__((aligned(__VA_ARGS__)))
49 #define __may_alias __attribute__((__may_alias__))
50 #endif
51
52 #endif
53
54 /* Bitness */
55
56 #if defined(__ppc64__) || defined(__PPC64__) || defined(__x86_64__) || defined(__ia64__) || defined(_M_X64)
57 #define __KERNEL_64_BIT__
58 #endif
59
60 /* SIMD Types */
61
62 #ifndef __KERNEL_GPU__
63
64 /* not enabled, globally applying it just gives slowdown,
65  * but useful for testing. */
66 //#define __KERNEL_SSE__
67 #ifdef __KERNEL_SSE__
68
69 #include <xmmintrin.h> /* SSE 1 */
70 #include <emmintrin.h> /* SSE 2 */
71 #include <pmmintrin.h> /* SSE 3 */
72 #include <tmmintrin.h> /* SSE 3 */
73 #include <smmintrin.h> /* SSE 4 */
74
75 #define __KERNEL_SSE2__
76 #define __KERNEL_SSE3__
77 #define __KERNEL_SSE4__
78
79 #else
80
81 #ifdef __x86_64__
82
83 /* MinGW64 has conflicting declarations for these SSE headers in <windows.h>.
84  * Since we can't avoid including <windows.h>, better only include that */
85 #ifdef FREE_WINDOWS64
86 #include <windows.h>
87 #else
88 #include <xmmintrin.h> /* SSE 1 */
89 #include <emmintrin.h> /* SSE 2 */
90 #endif
91
92 #define __KERNEL_SSE2__
93
94 #endif
95
96 #endif
97
98 #ifndef _WIN32
99
100 #include <stdint.h>
101
102 #endif
103
104 #endif
105
106 CCL_NAMESPACE_BEGIN
107
108 /* Types
109  *
110  * Define simpler unsigned type names, and integer with defined number of bits.
111  * Also vector types, named to be compatible with OpenCL builtin types, while
112  * working for CUDA and C++ too. */
113
114 /* Shorter Unsigned Names */
115
116 #ifndef __KERNEL_OPENCL__
117
118 typedef unsigned char uchar;
119 typedef unsigned int uint;
120
121 #endif
122
123 #ifndef __KERNEL_GPU__
124
125 /* Fixed Bits Types */
126
127 #ifdef _WIN32
128
129 typedef signed char int8_t;
130 typedef unsigned char uint8_t;
131
132 typedef signed short int16_t;
133 typedef unsigned short uint16_t;
134
135 typedef signed int int32_t;
136 typedef unsigned int uint32_t;
137
138 typedef long long int64_t;
139 typedef unsigned long long uint64_t;
140
141 #ifdef __KERNEL_64_BIT__
142 typedef int64_t ssize_t;
143 #else
144 typedef int32_t ssize_t;
145 #endif
146
147 #endif
148
149 /* Generic Memory Pointer */
150
151 typedef uint64_t device_ptr;
152
153 /* Vector Types */
154
155 struct uchar2 {
156         uchar x, y;
157
158         __forceinline uchar operator[](int i) const { return *(&x + i); }
159         __forceinline uchar& operator[](int i) { return *(&x + i); }
160 };
161
162 struct uchar3 {
163         uchar x, y, z;
164
165         __forceinline uchar operator[](int i) const { return *(&x + i); }
166         __forceinline uchar& operator[](int i) { return *(&x + i); }
167 };
168
169 struct uchar4 {
170         uchar x, y, z, w;
171
172         __forceinline uchar operator[](int i) const { return *(&x + i); }
173         __forceinline uchar& operator[](int i) { return *(&x + i); }
174 };
175
176 struct int2 {
177         int x, y;
178
179         __forceinline int operator[](int i) const { return *(&x + i); }
180         __forceinline int& operator[](int i) { return *(&x + i); }
181 };
182
183 #ifdef __KERNEL_SSE__
184 struct __align(16) int3 {
185         union {
186                 __m128i m128;
187                 struct { int x, y, z, w; };
188         };
189
190         __forceinline int3() {}
191         __forceinline int3(const __m128i a) : m128(a) {}
192         __forceinline operator const __m128i&(void) const { return m128; }
193         __forceinline operator __m128i&(void) { return m128; }
194 #else
195 struct int3 {
196         int x, y, z, w;
197 #endif
198
199         __forceinline int operator[](int i) const { return *(&x + i); }
200         __forceinline int& operator[](int i) { return *(&x + i); }
201 };
202
203 #ifdef __KERNEL_SSE__
204 struct __align(16) int4 {
205         union {
206                 __m128i m128;
207                 struct { int x, y, z, w; };
208         };
209
210         __forceinline int4() {}
211         __forceinline int4(const __m128i a) : m128(a) {}
212         __forceinline operator const __m128i&(void) const { return m128; }
213         __forceinline operator __m128i&(void) { return m128; }
214 #else
215 struct int4 {
216         int x, y, z, w;
217 #endif
218
219         __forceinline int operator[](int i) const { return *(&x + i); }
220         __forceinline int& operator[](int i) { return *(&x + i); }
221 };
222
223 struct uint2 {
224         uint x, y;
225
226         __forceinline uint operator[](uint i) const { return *(&x + i); }
227         __forceinline uint& operator[](uint i) { return *(&x + i); }
228 };
229
230 struct uint3 {
231         uint x, y, z;
232
233         __forceinline uint operator[](uint i) const { return *(&x + i); }
234         __forceinline uint& operator[](uint i) { return *(&x + i); }
235 };
236
237 struct uint4 {
238         uint x, y, z, w;
239
240         __forceinline uint operator[](uint i) const { return *(&x + i); }
241         __forceinline uint& operator[](uint i) { return *(&x + i); }
242 };
243
244 struct float2 {
245         float x, y;
246
247         __forceinline float operator[](int i) const { return *(&x + i); }
248         __forceinline float& operator[](int i) { return *(&x + i); }
249 };
250
251 #ifdef __KERNEL_SSE__
252 struct __align(16) float3 {
253         union {
254                 __m128 m128;
255                 struct { float x, y, z, w; };
256         };
257
258         __forceinline float3() {}
259         __forceinline float3(const __m128 a) : m128(a) {}
260         __forceinline operator const __m128&(void) const { return m128; }
261         __forceinline operator __m128&(void) { return m128; }
262 #else
263 struct float3 {
264         float x, y, z, w;
265 #endif
266
267         __forceinline float operator[](int i) const { return *(&x + i); }
268         __forceinline float& operator[](int i) { return *(&x + i); }
269 };
270
271 #ifdef __KERNEL_SSE__
272 struct __align(16) float4 {
273         union {
274                 __m128 m128;
275                 struct { float x, y, z, w; };
276         };
277
278         __forceinline float4() {}
279         __forceinline float4(const __m128 a) : m128(a) {}
280         __forceinline operator const __m128&(void) const { return m128; }
281         __forceinline operator __m128&(void) { return m128; }
282 #else
283 struct float4 {
284         float x, y, z, w;
285 #endif
286
287         __forceinline float operator[](int i) const { return *(&x + i); }
288         __forceinline float& operator[](int i) { return *(&x + i); }
289 };
290
291 #endif
292
293 #ifndef __KERNEL_GPU__
294
295 /* Vector Type Constructors
296  * 
297  * OpenCL does not support C++ class, so we use these instead. */
298
299 __device_inline uchar2 make_uchar2(uchar x, uchar y)
300 {
301         uchar2 a = {x, y};
302         return a;
303 }
304
305 __device_inline uchar3 make_uchar3(uchar x, uchar y, uchar z)
306 {
307         uchar3 a = {x, y, z};
308         return a;
309 }
310
311 __device_inline uchar4 make_uchar4(uchar x, uchar y, uchar z, uchar w)
312 {
313         uchar4 a = {x, y, z, w};
314         return a;
315 }
316
317 __device_inline int2 make_int2(int x, int y)
318 {
319         int2 a = {x, y};
320         return a;
321 }
322
323 __device_inline int3 make_int3(int x, int y, int z)
324 {
325 #ifdef __KERNEL_SSE__
326         int3 a;
327         a.m128 = _mm_set_epi32(0, z, y, x);
328 #else
329         int3 a = {x, y, z, 0};
330 #endif
331
332         return a;
333 }
334
335 __device_inline int4 make_int4(int x, int y, int z, int w)
336 {
337 #ifdef __KERNEL_SSE__
338         int4 a;
339         a.m128 = _mm_set_epi32(w, z, y, x);
340 #else
341         int4 a = {x, y, z, w};
342 #endif
343
344         return a;
345 }
346
347 __device_inline uint2 make_uint2(uint x, uint y)
348 {
349         uint2 a = {x, y};
350         return a;
351 }
352
353 __device_inline uint3 make_uint3(uint x, uint y, uint z)
354 {
355         uint3 a = {x, y, z};
356         return a;
357 }
358
359 __device_inline uint4 make_uint4(uint x, uint y, uint z, uint w)
360 {
361         uint4 a = {x, y, z, w};
362         return a;
363 }
364
365 __device_inline float2 make_float2(float x, float y)
366 {
367         float2 a = {x, y};
368         return a;
369 }
370
371 __device_inline float3 make_float3(float x, float y, float z)
372 {
373 #ifdef __KERNEL_SSE__
374         float3 a;
375         a.m128 = _mm_set_ps(0.0f, z, y, x);
376 #else
377         float3 a = {x, y, z, 0.0f};
378 #endif
379
380         return a;
381 }
382
383 __device_inline float4 make_float4(float x, float y, float z, float w)
384 {
385 #ifdef __KERNEL_SSE__
386         float4 a;
387         a.m128 = _mm_set_ps(w, z, y, x);
388 #else
389         float4 a = {x, y, z, w};
390 #endif
391
392         return a;
393 }
394
395 __device_inline int align_up(int offset, int alignment)
396 {
397         return (offset + alignment - 1) & ~(alignment - 1);
398 }
399
400 __device_inline int3 make_int3(int i)
401 {
402 #ifdef __KERNEL_SSE__
403         int3 a;
404         a.m128 = _mm_set1_epi32(i);
405 #else
406         int3 a = {i, i, i, i};
407 #endif
408
409         return a;
410 }
411
412 __device_inline int4 make_int4(int i)
413 {
414 #ifdef __KERNEL_SSE__
415         int4 a;
416         a.m128 = _mm_set1_epi32(i);
417 #else
418         int4 a = {i, i, i, i};
419 #endif
420
421         return a;
422 }
423
424 __device_inline float3 make_float3(float f)
425 {
426 #ifdef __KERNEL_SSE__
427         float3 a;
428         a.m128 = _mm_set1_ps(f);
429 #else
430         float3 a = {f, f, f, f};
431 #endif
432
433         return a;
434 }
435
436 __device_inline float4 make_float4(float f)
437 {
438 #ifdef __KERNEL_SSE__
439         float4 a;
440         a.m128 = _mm_set1_ps(f);
441 #else
442         float4 a = {f, f, f, f};
443 #endif
444
445         return a;
446 }
447
448 __device_inline float4 make_float4(const int4& i)
449 {
450 #ifdef __KERNEL_SSE__
451         float4 a;
452         a.m128 = _mm_cvtepi32_ps(i.m128);
453 #else
454         float4 a = {(float)i.x, (float)i.y, (float)i.z, (float)i.w};
455 #endif
456
457         return a;
458 }
459
460 __device_inline int4 make_int4(const float3& f)
461 {
462 #ifdef __KERNEL_SSE__
463         int4 a;
464         a.m128 = _mm_cvtps_epi32(f.m128);
465 #else
466         int4 a = {(int)f.x, (int)f.y, (int)f.z, (int)f.w};
467 #endif
468
469         return a;
470 }
471
472 #endif
473
474 CCL_NAMESPACE_END
475
476 #endif /* __UTIL_TYPES_H__ */
477