Cycles: Add implementation of clip extension mode
[blender.git] / intern / cycles / util / util_types.h
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #ifndef __UTIL_TYPES_H__
18 #define __UTIL_TYPES_H__
19
20 #ifndef __KERNEL_OPENCL__
21
22 #include <stdlib.h>
23
24 #endif
25
26 /* Bitness */
27
28 #if defined(__ppc64__) || defined(__PPC64__) || defined(__x86_64__) || defined(__ia64__) || defined(_M_X64)
29 #define __KERNEL_64_BIT__
30 #endif
31
32 /* Qualifiers for kernel code shared by CPU and GPU */
33
34 #ifndef __KERNEL_GPU__
35
36 #define ccl_device static inline
37 #define ccl_device_noinline static
38 #define ccl_global
39 #define ccl_constant
40 #define __KERNEL_WITH_SSE_ALIGN__
41
42 #if defined(_WIN32) && !defined(FREE_WINDOWS)
43 #define ccl_device_inline static __forceinline
44 #define ccl_align(...) __declspec(align(__VA_ARGS__))
45 #ifdef __KERNEL_64_BIT__
46 #define ccl_try_align(...) __declspec(align(__VA_ARGS__))
47 #else
48 #undef __KERNEL_WITH_SSE_ALIGN__
49 #define ccl_try_align(...) /* not support for function arguments (error C2719) */
50 #endif
51 #define ccl_may_alias
52 #define ccl_always_inline __forceinline
53 #define ccl_maybe_unused
54
55 #else
56
57 #define ccl_device_inline static inline __attribute__((always_inline))
58 #define ccl_align(...) __attribute__((aligned(__VA_ARGS__)))
59 #ifndef FREE_WINDOWS64
60 #define __forceinline inline __attribute__((always_inline))
61 #endif
62 #define ccl_try_align(...) __attribute__((aligned(__VA_ARGS__)))
63 #define ccl_may_alias __attribute__((__may_alias__))
64 #define ccl_always_inline __attribute__((always_inline))
65 #define ccl_maybe_unused __attribute__((used))
66
67 #endif
68
69 #endif
70
71 /* Standard Integer Types */
72
73 #ifndef __KERNEL_GPU__
74
75 /* int8_t, uint16_t, and friends */
76 #ifndef _WIN32
77 #include <stdint.h>
78 #endif
79
80 /* SIMD Types */
81
82 #include "util_optimization.h"
83
84 #endif
85
86 CCL_NAMESPACE_BEGIN
87
88 /* Types
89  *
90  * Define simpler unsigned type names, and integer with defined number of bits.
91  * Also vector types, named to be compatible with OpenCL builtin types, while
92  * working for CUDA and C++ too. */
93
94 /* Shorter Unsigned Names */
95
96 #ifndef __KERNEL_OPENCL__
97
98 typedef unsigned char uchar;
99 typedef unsigned int uint;
100
101 #endif
102
103 #ifndef __KERNEL_GPU__
104
105 /* Fixed Bits Types */
106
107 #ifdef _WIN32
108
109 typedef signed char int8_t;
110 typedef unsigned char uint8_t;
111
112 typedef signed short int16_t;
113 typedef unsigned short uint16_t;
114
115 typedef signed int int32_t;
116 typedef unsigned int uint32_t;
117
118 typedef long long int64_t;
119 typedef unsigned long long uint64_t;
120
121 #ifdef __KERNEL_64_BIT__
122 typedef int64_t ssize_t;
123 #else
124 typedef int32_t ssize_t;
125 #endif
126
127 #endif
128
129 /* Generic Memory Pointer */
130
131 typedef uint64_t device_ptr;
132
133 /* Vector Types */
134
135 struct uchar2 {
136         uchar x, y;
137
138         __forceinline uchar operator[](int i) const { return *(&x + i); }
139         __forceinline uchar& operator[](int i) { return *(&x + i); }
140 };
141
142 struct uchar3 {
143         uchar x, y, z;
144
145         __forceinline uchar operator[](int i) const { return *(&x + i); }
146         __forceinline uchar& operator[](int i) { return *(&x + i); }
147 };
148
149 struct uchar4 {
150         uchar x, y, z, w;
151
152         __forceinline uchar operator[](int i) const { return *(&x + i); }
153         __forceinline uchar& operator[](int i) { return *(&x + i); }
154 };
155
156 struct int2 {
157         int x, y;
158
159         __forceinline int operator[](int i) const { return *(&x + i); }
160         __forceinline int& operator[](int i) { return *(&x + i); }
161 };
162
163 struct ccl_try_align(16) int3 {
164 #ifdef __KERNEL_SSE__
165         union {
166                 __m128i m128;
167                 struct { int x, y, z, w; };
168         };
169
170         __forceinline int3() {}
171         __forceinline int3(const __m128i a) : m128(a) {}
172         __forceinline operator const __m128i&(void) const { return m128; }
173         __forceinline operator __m128i&(void) { return m128; }
174 #else
175         int x, y, z, w;
176 #endif
177
178         __forceinline int operator[](int i) const { return *(&x + i); }
179         __forceinline int& operator[](int i) { return *(&x + i); }
180 };
181
182 struct ccl_try_align(16) int4 {
183 #ifdef __KERNEL_SSE__
184         union {
185                 __m128i m128;
186                 struct { int x, y, z, w; };
187         };
188
189         __forceinline int4() {}
190         __forceinline int4(const __m128i a) : m128(a) {}
191         __forceinline operator const __m128i&(void) const { return m128; }
192         __forceinline operator __m128i&(void) { return m128; }
193 #else
194         int x, y, z, w;
195 #endif
196
197         __forceinline int operator[](int i) const { return *(&x + i); }
198         __forceinline int& operator[](int i) { return *(&x + i); }
199 };
200
201 struct uint2 {
202         uint x, y;
203
204         __forceinline uint operator[](uint i) const { return *(&x + i); }
205         __forceinline uint& operator[](uint i) { return *(&x + i); }
206 };
207
208 struct uint3 {
209         uint x, y, z;
210
211         __forceinline uint operator[](uint i) const { return *(&x + i); }
212         __forceinline uint& operator[](uint i) { return *(&x + i); }
213 };
214
215 struct uint4 {
216         uint x, y, z, w;
217
218         __forceinline uint operator[](uint i) const { return *(&x + i); }
219         __forceinline uint& operator[](uint i) { return *(&x + i); }
220 };
221
222 struct float2 {
223         float x, y;
224
225         __forceinline float operator[](int i) const { return *(&x + i); }
226         __forceinline float& operator[](int i) { return *(&x + i); }
227 };
228
229 struct ccl_try_align(16) float3 {
230 #ifdef __KERNEL_SSE__
231         union {
232                 __m128 m128;
233                 struct { float x, y, z, w; };
234         };
235
236         __forceinline float3() {}
237         __forceinline float3(const __m128 a) : m128(a) {}
238         __forceinline operator const __m128&(void) const { return m128; }
239         __forceinline operator __m128&(void) { return m128; }
240 #else
241         float x, y, z, w;
242 #endif
243
244         __forceinline float operator[](int i) const { return *(&x + i); }
245         __forceinline float& operator[](int i) { return *(&x + i); }
246 };
247
248 struct ccl_try_align(16) float4 {
249 #ifdef __KERNEL_SSE__
250         union {
251                 __m128 m128;
252                 struct { float x, y, z, w; };
253         };
254
255         __forceinline float4() {}
256         __forceinline float4(const __m128 a) : m128(a) {}
257         __forceinline operator const __m128&(void) const { return m128; }
258         __forceinline operator __m128&(void) { return m128; }
259 #else
260         float x, y, z, w;
261 #endif
262
263         __forceinline float operator[](int i) const { return *(&x + i); }
264         __forceinline float& operator[](int i) { return *(&x + i); }
265 };
266
267 template<typename T>
268 class vector3
269 {
270 public:
271         T x, y, z;
272
273         ccl_always_inline vector3() {}
274         ccl_always_inline vector3(const T& a)
275           : x(a), y(a), z(a) {}
276         ccl_always_inline vector3(const T& x, const T& y, const T& z)
277           : x(x), y(y), z(z) {}
278 };
279
280 #endif
281
282 #ifndef __KERNEL_GPU__
283
284 /* Vector Type Constructors
285  * 
286  * OpenCL does not support C++ class, so we use these instead. */
287
288 ccl_device_inline uchar2 make_uchar2(uchar x, uchar y)
289 {
290         uchar2 a = {x, y};
291         return a;
292 }
293
294 ccl_device_inline uchar3 make_uchar3(uchar x, uchar y, uchar z)
295 {
296         uchar3 a = {x, y, z};
297         return a;
298 }
299
300 ccl_device_inline uchar4 make_uchar4(uchar x, uchar y, uchar z, uchar w)
301 {
302         uchar4 a = {x, y, z, w};
303         return a;
304 }
305
306 ccl_device_inline int2 make_int2(int x, int y)
307 {
308         int2 a = {x, y};
309         return a;
310 }
311
312 ccl_device_inline int3 make_int3(int x, int y, int z)
313 {
314 #ifdef __KERNEL_SSE__
315         int3 a;
316         a.m128 = _mm_set_epi32(0, z, y, x);
317 #else
318         int3 a = {x, y, z, 0};
319 #endif
320
321         return a;
322 }
323
324 ccl_device_inline int4 make_int4(int x, int y, int z, int w)
325 {
326 #ifdef __KERNEL_SSE__
327         int4 a;
328         a.m128 = _mm_set_epi32(w, z, y, x);
329 #else
330         int4 a = {x, y, z, w};
331 #endif
332
333         return a;
334 }
335
336 ccl_device_inline uint2 make_uint2(uint x, uint y)
337 {
338         uint2 a = {x, y};
339         return a;
340 }
341
342 ccl_device_inline uint3 make_uint3(uint x, uint y, uint z)
343 {
344         uint3 a = {x, y, z};
345         return a;
346 }
347
348 ccl_device_inline uint4 make_uint4(uint x, uint y, uint z, uint w)
349 {
350         uint4 a = {x, y, z, w};
351         return a;
352 }
353
354 ccl_device_inline float2 make_float2(float x, float y)
355 {
356         float2 a = {x, y};
357         return a;
358 }
359
360 ccl_device_inline float3 make_float3(float x, float y, float z)
361 {
362 #ifdef __KERNEL_SSE__
363         float3 a;
364         a.m128 = _mm_set_ps(0.0f, z, y, x);
365 #else
366         float3 a = {x, y, z, 0.0f};
367 #endif
368
369         return a;
370 }
371
372 ccl_device_inline float4 make_float4(float x, float y, float z, float w)
373 {
374 #ifdef __KERNEL_SSE__
375         float4 a;
376         a.m128 = _mm_set_ps(w, z, y, x);
377 #else
378         float4 a = {x, y, z, w};
379 #endif
380
381         return a;
382 }
383
384 ccl_device_inline int align_up(int offset, int alignment)
385 {
386         return (offset + alignment - 1) & ~(alignment - 1);
387 }
388
389 ccl_device_inline int3 make_int3(int i)
390 {
391 #ifdef __KERNEL_SSE__
392         int3 a;
393         a.m128 = _mm_set1_epi32(i);
394 #else
395         int3 a = {i, i, i, i};
396 #endif
397
398         return a;
399 }
400
401 ccl_device_inline int4 make_int4(int i)
402 {
403 #ifdef __KERNEL_SSE__
404         int4 a;
405         a.m128 = _mm_set1_epi32(i);
406 #else
407         int4 a = {i, i, i, i};
408 #endif
409
410         return a;
411 }
412
413 ccl_device_inline float3 make_float3(float f)
414 {
415 #ifdef __KERNEL_SSE__
416         float3 a;
417         a.m128 = _mm_set1_ps(f);
418 #else
419         float3 a = {f, f, f, f};
420 #endif
421
422         return a;
423 }
424
425 ccl_device_inline float4 make_float4(float f)
426 {
427 #ifdef __KERNEL_SSE__
428         float4 a;
429         a.m128 = _mm_set1_ps(f);
430 #else
431         float4 a = {f, f, f, f};
432 #endif
433
434         return a;
435 }
436
437 ccl_device_inline float4 make_float4(const int4& i)
438 {
439 #ifdef __KERNEL_SSE__
440         float4 a;
441         a.m128 = _mm_cvtepi32_ps(i.m128);
442 #else
443         float4 a = {(float)i.x, (float)i.y, (float)i.z, (float)i.w};
444 #endif
445
446         return a;
447 }
448
449 ccl_device_inline int4 make_int4(const float3& f)
450 {
451 #ifdef __KERNEL_SSE__
452         int4 a;
453         a.m128 = _mm_cvtps_epi32(f.m128);
454 #else
455         int4 a = {(int)f.x, (int)f.y, (int)f.z, (int)f.w};
456 #endif
457
458         return a;
459 }
460
461 #endif
462
463 /* Interpolation types for textures
464  * cuda also use texture space to store other objects */
465 enum InterpolationType {
466         INTERPOLATION_NONE = -1,
467         INTERPOLATION_LINEAR = 0,
468         INTERPOLATION_CLOSEST = 1,
469         INTERPOLATION_CUBIC = 2,
470         INTERPOLATION_SMART = 3,
471 };
472
473 /* Extension types for textures.
474  *
475  * Defines how the image is extrapolated past its original bounds.
476  */
477 enum ExtensionType {
478         /* Cause the image to repeat horizontally and vertically. */
479         EXTENSION_REPEAT = 0,
480         /* Extend by repeating edge pixels of the image. */
481         EXTENSION_EXTEND = 1,
482         /* Clip to image size and set exterior pixels as transparent. */
483         EXTENSION_CLIP = 2,
484 };
485
486 /* macros */
487
488 /* hints for branch prediction, only use in code that runs a _lot_ */
489 #if defined(__GNUC__) && defined(__KERNEL_CPU__)
490 #  define LIKELY(x)       __builtin_expect(!!(x), 1)
491 #  define UNLIKELY(x)     __builtin_expect(!!(x), 0)
492 #else
493 #  define LIKELY(x)       (x)
494 #  define UNLIKELY(x)     (x)
495 #endif
496
497 #if defined(__cplusplus) && ((__cplusplus >= 201103L) || (defined(_MSC_VER) && _MSC_VER >= 1800))
498 #  define HAS_CPP11_FEATURES
499 #endif
500
501 #if defined(__GNUC__) || defined(__clang__)
502 #  if defined(HAS_CPP11_FEATURES)
503 /* Some magic to be sure we don't have reference in the type. */
504 template<typename T> static inline T decltype_helper(T x) { return x; }
505 #    define TYPEOF(x) decltype(decltype_helper(x))
506 #  else
507 #    define TYPEOF(x) typeof(x)
508 #  endif
509 #endif
510
511 /* Causes warning:
512  * incompatible types when assigning to type 'Foo' from type 'Bar'
513  * ... the compiler optimizes away the temp var */
514 #ifdef __GNUC__
515 #define CHECK_TYPE(var, type)  {  \
516         TYPEOF(var) *__tmp;         \
517         __tmp = (type *)NULL;         \
518         (void)__tmp;                  \
519 } (void)0
520
521 #define CHECK_TYPE_PAIR(var_a, var_b)  {  \
522         TYPEOF(var_a) *__tmp;                 \
523         __tmp = (typeof(var_b) *)NULL;        \
524         (void)__tmp;                          \
525 } (void)0
526 #else
527 #  define CHECK_TYPE(var, type)
528 #  define CHECK_TYPE_PAIR(var_a, var_b)
529 #endif
530
531 /* can be used in simple macros */
532 #define CHECK_TYPE_INLINE(val, type) \
533         ((void)(((type)0) != (val)))
534
535
536 CCL_NAMESPACE_END
537
538 #endif /* __UTIL_TYPES_H__ */
539