1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 // IWYU pragma: private, include "SkTypes.h"
9 
10 #ifndef SkPostConfig_DEFINED
11 #define SkPostConfig_DEFINED
12 
13 #if defined(SK_BUILD_FOR_WIN32)
14 #  define SK_BUILD_FOR_WIN
15 #endif
16 
17 #if !defined(SK_DEBUG) && !defined(SK_RELEASE)
18     #ifdef NDEBUG
19         #define SK_RELEASE
20     #else
21         #define SK_DEBUG
22     #endif
23 #endif
24 
25 #if defined(SK_DEBUG) && defined(SK_RELEASE)
26 #  error "cannot define both SK_DEBUG and SK_RELEASE"
27 #elif !defined(SK_DEBUG) && !defined(SK_RELEASE)
28 #  error "must define either SK_DEBUG or SK_RELEASE"
29 #endif
30 
31 #if defined(SK_SUPPORT_UNITTEST) && !defined(SK_DEBUG)
32 #  error "can't have unittests without debug"
33 #endif
34 
35 /**
36  * Matrix calculations may be float or double.
37  * The default is float, as that's what Chromium's using.
38  */
39 #if defined(SK_MSCALAR_IS_DOUBLE) && defined(SK_MSCALAR_IS_FLOAT)
40 #  error "cannot define both SK_MSCALAR_IS_DOUBLE and SK_MSCALAR_IS_FLOAT"
41 #elif !defined(SK_MSCALAR_IS_DOUBLE) && !defined(SK_MSCALAR_IS_FLOAT)
42 #  define SK_MSCALAR_IS_FLOAT
43 #endif
44 
45 #if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN)
46 #  error "cannot define both SK_CPU_LENDIAN and SK_CPU_BENDIAN"
47 #elif !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN)
48 #  error "must define either SK_CPU_LENDIAN or SK_CPU_BENDIAN"
49 #endif
50 
51 /**
52  * Ensure the port has defined all of SK_X32_SHIFT, or none of them.
53  */
54 #ifdef SK_A32_SHIFT
55 #  if !defined(SK_R32_SHIFT) || !defined(SK_G32_SHIFT) || !defined(SK_B32_SHIFT)
56 #    error "all or none of the 32bit SHIFT amounts must be defined"
57 #  endif
58 #else
59 #  if defined(SK_R32_SHIFT) || defined(SK_G32_SHIFT) || defined(SK_B32_SHIFT)
60 #    error "all or none of the 32bit SHIFT amounts must be defined"
61 #  endif
62 #endif
63 
64 #if !defined(SK_HAS_COMPILER_FEATURE)
65 #  if defined(__has_feature)
66 #    define SK_HAS_COMPILER_FEATURE(x) __has_feature(x)
67 #  else
68 #    define SK_HAS_COMPILER_FEATURE(x) 0
69 #  endif
70 #endif
71 
72 #if !defined(SK_ATTRIBUTE)
73 #  if defined(__clang__) || defined(__GNUC__)
74 #    define SK_ATTRIBUTE(attr) __attribute__((attr))
75 #  else
76 #    define SK_ATTRIBUTE(attr)
77 #  endif
78 #endif
79 
80 #if defined(_MSC_VER) && SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
81     #define SK_VECTORCALL __vectorcall
82 #elif defined(SK_CPU_ARM32) && defined(SK_ARM_HAS_NEON)
83     #define SK_VECTORCALL __attribute__((pcs("aapcs-vfp")))
84 #else
85     #define SK_VECTORCALL
86 #endif
87 
88 #if !defined(SK_SUPPORT_GPU)
89 #  define SK_SUPPORT_GPU 1
90 #endif
91 
92 /**
93  * The clang static analyzer likes to know that when the program is not
94  * expected to continue (crash, assertion failure, etc). It will notice that
95  * some combination of parameters lead to a function call that does not return.
96  * It can then make appropriate assumptions about the parameters in code
97  * executed only if the non-returning function was *not* called.
98  */
99 #if !defined(SkNO_RETURN_HINT)
100 #  if SK_HAS_COMPILER_FEATURE(attribute_analyzer_noreturn)
101      static inline void SkNO_RETURN_HINT() __attribute__((analyzer_noreturn));
SkNO_RETURN_HINT()102      static inline void SkNO_RETURN_HINT() {}
103 #  else
104 #    define SkNO_RETURN_HINT() do {} while (false)
105 #  endif
106 #endif
107 
108 ///////////////////////////////////////////////////////////////////////////////
109 
110 // TODO(mdempsky): Move elsewhere as appropriate.
111 #include <new>
112 
113 
114 ///////////////////////////////////////////////////////////////////////////////
115 
116 #ifdef SK_BUILD_FOR_WIN
117 #  ifndef SK_A32_SHIFT
118 #    define SK_A32_SHIFT 24
119 #    define SK_R32_SHIFT 16
120 #    define SK_G32_SHIFT 8
121 #    define SK_B32_SHIFT 0
122 #  endif
123 #
124 #endif
125 
126 #if defined(GOOGLE3)
127     void SkDebugfForDumpStackTrace(const char* data, void* unused);
128     void DumpStackTrace(int skip_count, void w(const char*, void*), void* arg);
129 #  define SK_DUMP_GOOGLE3_STACK() DumpStackTrace(0, SkDebugfForDumpStackTrace, nullptr)
130 #else
131 #  define SK_DUMP_GOOGLE3_STACK()
132 #endif
133 
134 #ifndef SK_ABORT
135 #  define SK_ABORT(message) \
136     do { \
137        SkNO_RETURN_HINT(); \
138        SkDebugf("%s:%d: fatal error: \"%s\"\n", __FILE__, __LINE__, message); \
139        SK_DUMP_GOOGLE3_STACK(); \
140        sk_abort_no_print(); \
141     } while (false)
142 #endif
143 
144 /**
145  *  We check to see if the SHIFT value has already been defined.
146  *  if not, we define it ourself to some default values. We default to OpenGL
147  *  order (in memory: r,g,b,a)
148  */
149 #ifndef SK_A32_SHIFT
150 #  ifdef SK_CPU_BENDIAN
151 #    define SK_R32_SHIFT    24
152 #    define SK_G32_SHIFT    16
153 #    define SK_B32_SHIFT    8
154 #    define SK_A32_SHIFT    0
155 #  else
156 #    define SK_R32_SHIFT    0
157 #    define SK_G32_SHIFT    8
158 #    define SK_B32_SHIFT    16
159 #    define SK_A32_SHIFT    24
160 #  endif
161 #endif
162 
163 /**
164  * SkColor has well defined shift values, but SkPMColor is configurable. This
165  * macro is a convenience that returns true if the shift values are equal while
166  * ignoring the machine's endianness.
167  */
168 #define SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER \
169     (SK_A32_SHIFT == 24 && SK_R32_SHIFT == 16 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 0)
170 
171 /**
172  * SK_PMCOLOR_BYTE_ORDER can be used to query the byte order of SkPMColor at compile time. The
173  * relationship between the byte order and shift values depends on machine endianness. If the shift
174  * order is R=0, G=8, B=16, A=24 then ((char*)&pmcolor)[0] will produce the R channel on a little
175  * endian machine and the A channel on a big endian machine. Thus, given those shifts values,
176  * SK_PMCOLOR_BYTE_ORDER(R,G,B,A) will be true on a little endian machine and
177  * SK_PMCOLOR_BYTE_ORDER(A,B,G,R) will be true on a big endian machine.
178  */
179 #ifdef SK_CPU_BENDIAN
180 #  define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3)     \
181         (SK_ ## C3 ## 32_SHIFT == 0  &&             \
182          SK_ ## C2 ## 32_SHIFT == 8  &&             \
183          SK_ ## C1 ## 32_SHIFT == 16 &&             \
184          SK_ ## C0 ## 32_SHIFT == 24)
185 #else
186 #  define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3)     \
187         (SK_ ## C0 ## 32_SHIFT == 0  &&             \
188          SK_ ## C1 ## 32_SHIFT == 8  &&             \
189          SK_ ## C2 ## 32_SHIFT == 16 &&             \
190          SK_ ## C3 ## 32_SHIFT == 24)
191 #endif
192 
193 //////////////////////////////////////////////////////////////////////////////////////////////
194 
195 #if defined SK_DEBUG && defined SK_BUILD_FOR_WIN32
196 #  ifdef free
197 #    undef free
198 #  endif
199 #  include <crtdbg.h>
200 #  undef free
201 #
202 #  ifdef SK_DEBUGx
203 #    if defined(SK_SIMULATE_FAILED_MALLOC) && defined(__cplusplus)
204        void * operator new(
205            size_t cb,
206            int nBlockUse,
207            const char * szFileName,
208            int nLine,
209            int foo
210            );
211        void * operator new[](
212            size_t cb,
213            int nBlockUse,
214            const char * szFileName,
215            int nLine,
216            int foo
217            );
218        void operator delete(
219            void *pUserData,
220            int, const char*, int, int
221            );
222        void operator delete(
223            void *pUserData
224            );
225        void operator delete[]( void * p );
226 #      define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__, 0)
227 #    else
228 #      define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)
229 #    endif
230 #    define new DEBUG_CLIENTBLOCK
231 #  else
232 #    define DEBUG_CLIENTBLOCK
233 #  endif
234 #endif
235 
236 //////////////////////////////////////////////////////////////////////
237 
238 #if !defined(SK_UNUSED)
239 #  if defined(_MSC_VER)
240 #    define SK_UNUSED __pragma(warning(suppress:4189))
241 #  else
242 #    define SK_UNUSED SK_ATTRIBUTE(unused)
243 #  endif
244 #endif
245 
246 #if !defined(SK_ATTR_DEPRECATED)
247    // FIXME: we ignore msg for now...
248 #  define SK_ATTR_DEPRECATED(msg) SK_ATTRIBUTE(deprecated)
249 #endif
250 
251 #if !defined(SK_ATTR_EXTERNALLY_DEPRECATED)
252 #  if !defined(SK_INTERNAL)
253 #    define SK_ATTR_EXTERNALLY_DEPRECATED(msg) SK_ATTR_DEPRECATED(msg)
254 #  else
255 #    define SK_ATTR_EXTERNALLY_DEPRECATED(msg)
256 #  endif
257 #endif
258 
259 /**
260  * If your judgment is better than the compiler's (i.e. you've profiled it),
261  * you can use SK_ALWAYS_INLINE to force inlining. E.g.
262  *     inline void someMethod() { ... }             // may not be inlined
263  *     SK_ALWAYS_INLINE void someMethod() { ... }   // should always be inlined
264  */
265 #if !defined(SK_ALWAYS_INLINE)
266 #  if defined(SK_BUILD_FOR_WIN)
267 #    define SK_ALWAYS_INLINE __forceinline
268 #  else
269 #    define SK_ALWAYS_INLINE SK_ATTRIBUTE(always_inline) inline
270 #  endif
271 #endif
272 
273 /**
274  * If your judgment is better than the compiler's (i.e. you've profiled it),
275  * you can use SK_NEVER_INLINE to prevent inlining.
276  */
277 #if !defined(SK_NEVER_INLINE)
278 #  if defined(SK_BUILD_FOR_WIN)
279 #    define SK_NEVER_INLINE __declspec(noinline)
280 #  else
281 #    define SK_NEVER_INLINE SK_ATTRIBUTE(noinline)
282 #  endif
283 #endif
284 
285 //////////////////////////////////////////////////////////////////////
286 
287 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
288     #define SK_PREFETCH(ptr)       _mm_prefetch(reinterpret_cast<const char*>(ptr), _MM_HINT_T0)
289     #define SK_WRITE_PREFETCH(ptr) _mm_prefetch(reinterpret_cast<const char*>(ptr), _MM_HINT_T0)
290 #elif defined(__GNUC__)
291     #define SK_PREFETCH(ptr)       __builtin_prefetch(ptr)
292     #define SK_WRITE_PREFETCH(ptr) __builtin_prefetch(ptr, 1)
293 #else
294     #define SK_PREFETCH(ptr)
295     #define SK_WRITE_PREFETCH(ptr)
296 #endif
297 
298 //////////////////////////////////////////////////////////////////////
299 
300 #ifndef SK_PRINTF_LIKE
301 #  if defined(__clang__) || defined(__GNUC__)
302 #    define SK_PRINTF_LIKE(A, B) __attribute__((format(printf, (A), (B))))
303 #  else
304 #    define SK_PRINTF_LIKE(A, B)
305 #  endif
306 #endif
307 
308 //////////////////////////////////////////////////////////////////////
309 
310 #ifndef SK_SIZE_T_SPECIFIER
311 #  if defined(_MSC_VER)
312 #    define SK_SIZE_T_SPECIFIER "%Iu"
313 #  else
314 #    define SK_SIZE_T_SPECIFIER "%zu"
315 #  endif
316 #endif
317 
318 //////////////////////////////////////////////////////////////////////
319 
320 #ifndef SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
321 #  define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 1
322 #endif
323 
324 //////////////////////////////////////////////////////////////////////
325 
326 #ifndef SK_EGL
327 #  if defined(SK_BUILD_FOR_ANDROID)
328 #    define SK_EGL 1
329 #  else
330 #    define SK_EGL 0
331 #  endif
332 #endif
333 
334 //////////////////////////////////////////////////////////////////////
335 
336 #if !defined(SK_GAMMA_EXPONENT)
337     #define SK_GAMMA_EXPONENT (0.0f)  // SRGB
338 #endif
339 
340 //////////////////////////////////////////////////////////////////////
341 
342 #ifndef GR_TEST_UTILS
343 #  define GR_TEST_UTILS 1
344 #endif
345 
346 //////////////////////////////////////////////////////////////////////
347 
348 #if defined(SK_HISTOGRAM_ENUMERATION) && defined(SK_HISTOGRAM_BOOLEAN)
349 #  define SK_HISTOGRAMS_ENABLED 1
350 #else
351 #  define SK_HISTOGRAMS_ENABLED 0
352 #endif
353 
354 #ifndef SK_HISTOGRAM_BOOLEAN
355 #  define SK_HISTOGRAM_BOOLEAN(name, value)
356 #endif
357 
358 #ifndef SK_HISTOGRAM_ENUMERATION
359 #  define SK_HISTOGRAM_ENUMERATION(name, value, boundary_value)
360 #endif
361 
362 #endif // SkPostConfig_DEFINED
363