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#ifndef SkPostConfig_DEFINED
9#define SkPostConfig_DEFINED
10
11#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_WINCE)
12#  define SK_BUILD_FOR_WIN
13#endif
14
15#if defined(SK_DEBUG) && defined(SK_RELEASE)
16#  error "cannot define both SK_DEBUG and SK_RELEASE"
17#elif !defined(SK_DEBUG) && !defined(SK_RELEASE)
18#  error "must define either SK_DEBUG or SK_RELEASE"
19#endif
20
21#if defined(SK_SUPPORT_UNITTEST) && !defined(SK_DEBUG)
22#  error "can't have unittests without debug"
23#endif
24
25/**
26 * Matrix calculations may be float or double.
27 * The default is double, as that is faster given our impl uses doubles
28 * for intermediate calculations.
29 */
30#if defined(SK_MSCALAR_IS_DOUBLE) && defined(SK_MSCALAR_IS_FLOAT)
31#  error "cannot define both SK_MSCALAR_IS_DOUBLE and SK_MSCALAR_IS_FLOAT"
32#elif !defined(SK_MSCALAR_IS_DOUBLE) && !defined(SK_MSCALAR_IS_FLOAT)
33#  define SK_MSCALAR_IS_DOUBLE
34#endif
35
36#if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN)
37#  error "cannot define both SK_CPU_LENDIAN and SK_CPU_BENDIAN"
38#elif !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN)
39#  error "must define either SK_CPU_LENDIAN or SK_CPU_BENDIAN"
40#endif
41
42/**
43 * Ensure the port has defined all of SK_X32_SHIFT, or none of them.
44 */
45#ifdef SK_A32_SHIFT
46#  if !defined(SK_R32_SHIFT) || !defined(SK_G32_SHIFT) || !defined(SK_B32_SHIFT)
47#    error "all or none of the 32bit SHIFT amounts must be defined"
48#  endif
49#else
50#  if defined(SK_R32_SHIFT) || defined(SK_G32_SHIFT) || defined(SK_B32_SHIFT)
51#    error "all or none of the 32bit SHIFT amounts must be defined"
52#  endif
53#endif
54
55#if !defined(SK_HAS_COMPILER_FEATURE)
56#  if defined(__has_feature)
57#    define SK_HAS_COMPILER_FEATURE(x) __has_feature(x)
58#  else
59#    define SK_HAS_COMPILER_FEATURE(x) 0
60#  endif
61#endif
62
63#if !defined(SK_ATTRIBUTE)
64#  if defined(__clang__) || defined(__GNUC__)
65#    define SK_ATTRIBUTE(attr) __attribute__((attr))
66#  else
67#    define SK_ATTRIBUTE(attr)
68#  endif
69#endif
70
71#if !defined(SK_SUPPORT_GPU)
72#  define SK_SUPPORT_GPU 1
73#endif
74
75/**
76 * The clang static analyzer likes to know that when the program is not
77 * expected to continue (crash, assertion failure, etc). It will notice that
78 * some combination of parameters lead to a function call that does not return.
79 * It can then make appropriate assumptions about the parameters in code
80 * executed only if the non-returning function was *not* called.
81 */
82#if !defined(SkNO_RETURN_HINT)
83#  if SK_HAS_COMPILER_FEATURE(attribute_analyzer_noreturn)
84     static inline void SkNO_RETURN_HINT() __attribute__((analyzer_noreturn));
85     static inline void SkNO_RETURN_HINT() {}
86#  else
87#    define SkNO_RETURN_HINT() do {} while (false)
88#  endif
89#endif
90
91#if defined(SK_ZLIB_INCLUDE) && defined(SK_SYSTEM_ZLIB)
92#  error "cannot define both SK_ZLIB_INCLUDE and SK_SYSTEM_ZLIB"
93#elif defined(SK_ZLIB_INCLUDE) || defined(SK_SYSTEM_ZLIB)
94#  define SK_HAS_ZLIB
95#endif
96
97///////////////////////////////////////////////////////////////////////////////
98
99#ifndef SkNEW
100#  define SkNEW(type_name)                           (new type_name)
101#  define SkNEW_ARGS(type_name, args)                (new type_name args)
102#  define SkNEW_ARRAY(type_name, count)              (new type_name[(count)])
103#  define SkNEW_PLACEMENT(buf, type_name)            (new (buf) type_name)
104#  define SkNEW_PLACEMENT_ARGS(buf, type_name, args) (new (buf) type_name args)
105#  define SkDELETE(obj)                              (delete (obj))
106#  define SkDELETE_ARRAY(array)                      (delete[] (array))
107#endif
108
109#ifndef SK_CRASH
110#  ifdef SK_BUILD_FOR_WIN
111#    define SK_CRASH() __debugbreak()
112#  else
113#    if 1   // set to 0 for infinite loop, which can help connecting gdb
114#      define SK_CRASH() do { SkNO_RETURN_HINT(); *(int *)(uintptr_t)0xbbadbeef = 0; } while (false)
115#    else
116#      define SK_CRASH() do { SkNO_RETURN_HINT(); } while (true)
117#    endif
118#  endif
119#endif
120
121///////////////////////////////////////////////////////////////////////////////
122
123/**
124 * SK_ENABLE_INST_COUNT controlls printing how many reference counted objects
125 * are still held on exit.
126 * Defaults to 1 in DEBUG and 0 in RELEASE.
127 */
128#ifndef SK_ENABLE_INST_COUNT
129#  ifdef SK_DEBUG
130// Only enabled for static builds, because instance counting relies on static
131// variables in functions defined in header files.
132#    define SK_ENABLE_INST_COUNT !defined(SKIA_DLL)
133#  else
134#    define SK_ENABLE_INST_COUNT 0
135#  endif
136#endif
137
138///////////////////////////////////////////////////////////////////////////////
139
140#ifdef SK_BUILD_FOR_WIN
141#  ifndef WIN32_LEAN_AND_MEAN
142#    define WIN32_LEAN_AND_MEAN
143#    define WIN32_IS_MEAN_WAS_LOCALLY_DEFINED
144#  endif
145#  ifndef NOMINMAX
146#    define NOMINMAX
147#    define NOMINMAX_WAS_LOCALLY_DEFINED
148#  endif
149#
150#  include <windows.h>
151#
152#  ifdef WIN32_IS_MEAN_WAS_LOCALLY_DEFINED
153#    undef WIN32_IS_MEAN_WAS_LOCALLY_DEFINED
154#    undef WIN32_LEAN_AND_MEAN
155#  endif
156#  ifdef NOMINMAX_WAS_LOCALLY_DEFINED
157#    undef NOMINMAX_WAS_LOCALLY_DEFINED
158#    undef NOMINMAX
159#  endif
160#
161#  ifndef SK_A32_SHIFT
162#    define SK_A32_SHIFT 24
163#    define SK_R32_SHIFT 16
164#    define SK_G32_SHIFT 8
165#    define SK_B32_SHIFT 0
166#  endif
167#
168#endif
169
170#ifndef SK_ALWAYSBREAK
171#  ifdef SK_DEBUG
172#    define SK_ALWAYSBREAK(cond) do { \
173              if (cond) break; \
174              SkNO_RETURN_HINT(); \
175              SkDebugf("%s:%d: failed assertion \"%s\"\n", __FILE__, __LINE__, #cond); \
176              SK_CRASH(); \
177        } while (false)
178#  else
179#    define SK_ALWAYSBREAK(cond) do { if (cond) break; SK_CRASH(); } while (false)
180#  endif
181#endif
182
183/**
184 *  We check to see if the SHIFT value has already been defined.
185 *  if not, we define it ourself to some default values. We default to OpenGL
186 *  order (in memory: r,g,b,a)
187 */
188#ifndef SK_A32_SHIFT
189#  ifdef SK_CPU_BENDIAN
190#    define SK_R32_SHIFT    24
191#    define SK_G32_SHIFT    16
192#    define SK_B32_SHIFT    8
193#    define SK_A32_SHIFT    0
194#  else
195#    define SK_R32_SHIFT    0
196#    define SK_G32_SHIFT    8
197#    define SK_B32_SHIFT    16
198#    define SK_A32_SHIFT    24
199#  endif
200#endif
201
202/**
203 * SkColor has well defined shift values, but SkPMColor is configurable. This
204 * macro is a convenience that returns true if the shift values are equal while
205 * ignoring the machine's endianness.
206 */
207#define SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER \
208    (SK_A32_SHIFT == 24 && SK_R32_SHIFT == 16 && SK_G32_SHIFT == 8 && SK_B32_SHIFT == 0)
209
210/**
211 * SK_PMCOLOR_BYTE_ORDER can be used to query the byte order of SkPMColor at compile time. The
212 * relationship between the byte order and shift values depends on machine endianness. If the shift
213 * order is R=0, G=8, B=16, A=24 then ((char*)&pmcolor)[0] will produce the R channel on a little
214 * endian machine and the A channel on a big endian machine. Thus, given those shifts values,
215 * SK_PMCOLOR_BYTE_ORDER(R,G,B,A) will be true on a little endian machine and
216 * SK_PMCOLOR_BYTE_ORDER(A,B,G,R) will be true on a big endian machine.
217 */
218#ifdef SK_CPU_BENDIAN
219#  define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3)     \
220        (SK_ ## C3 ## 32_SHIFT == 0  &&             \
221         SK_ ## C2 ## 32_SHIFT == 8  &&             \
222         SK_ ## C1 ## 32_SHIFT == 16 &&             \
223         SK_ ## C0 ## 32_SHIFT == 24)
224#else
225#  define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3)     \
226        (SK_ ## C0 ## 32_SHIFT == 0  &&             \
227         SK_ ## C1 ## 32_SHIFT == 8  &&             \
228         SK_ ## C2 ## 32_SHIFT == 16 &&             \
229         SK_ ## C3 ## 32_SHIFT == 24)
230#endif
231
232//////////////////////////////////////////////////////////////////////
233
234// TODO: rebaseline as needed so we can remove this flag entirely.
235//  - all platforms have int64_t now
236//  - we have slightly different fixed math results because of this check
237//    since we don't define this for linux/android
238#if defined(SK_BUILD_FOR_WIN32) || defined(SK_BUILD_FOR_MAC)
239#  ifndef SkLONGLONG
240#    define SkLONGLONG int64_t
241#  endif
242#endif
243
244//////////////////////////////////////////////////////////////////////////////////////////////
245#ifndef SK_BUILD_FOR_WINCE
246#  include <string.h>
247#  include <stdlib.h>
248#else
249#  define _CMNINTRIN_DECLARE_ONLY
250#  include "cmnintrin.h"
251#endif
252
253#if defined SK_DEBUG && defined SK_BUILD_FOR_WIN32
254#  ifdef free
255#    undef free
256#  endif
257#  include <crtdbg.h>
258#  undef free
259#
260#  ifdef SK_DEBUGx
261#    if defined(SK_SIMULATE_FAILED_MALLOC) && defined(__cplusplus)
262       void * operator new(
263           size_t cb,
264           int nBlockUse,
265           const char * szFileName,
266           int nLine,
267           int foo
268           );
269       void * operator new[](
270           size_t cb,
271           int nBlockUse,
272           const char * szFileName,
273           int nLine,
274           int foo
275           );
276       void operator delete(
277           void *pUserData,
278           int, const char*, int, int
279           );
280       void operator delete(
281           void *pUserData
282           );
283       void operator delete[]( void * p );
284#      define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__, 0)
285#    else
286#      define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)
287#    endif
288#    define new DEBUG_CLIENTBLOCK
289#  else
290#    define DEBUG_CLIENTBLOCK
291#  endif
292#endif
293
294//////////////////////////////////////////////////////////////////////
295
296#ifndef SK_OVERRIDE
297#  if defined(_MSC_VER)
298#    define SK_OVERRIDE override
299#  elif defined(__clang__)
300     // Using __attribute__((override)) on clang does not appear to always work.
301     // Clang defaults to C++03 and warns about using override. Squelch that. Intentionally no
302     // push/pop here so all users of SK_OVERRIDE ignore the warning too. This is like passing
303     // -Wno-c++11-extensions, except that GCC won't die (because it won't see this pragma).
304#    pragma clang diagnostic ignored "-Wc++11-extensions"
305#
306#    if __has_feature(cxx_override_control)
307#      define SK_OVERRIDE override
308#    elif defined(__has_extension) && __has_extension(cxx_override_control)
309#      define SK_OVERRIDE override
310#    endif
311#  endif
312#  ifndef SK_OVERRIDE
313#    define SK_OVERRIDE
314#  endif
315#endif
316
317//////////////////////////////////////////////////////////////////////
318
319#if !defined(SK_UNUSED)
320#  define SK_UNUSED SK_ATTRIBUTE(unused)
321#endif
322
323#if !defined(SK_ATTR_DEPRECATED)
324   // FIXME: we ignore msg for now...
325#  define SK_ATTR_DEPRECATED(msg) SK_ATTRIBUTE(deprecated)
326#endif
327
328#if !defined(SK_ATTR_EXTERNALLY_DEPRECATED)
329#  if !defined(SK_INTERNAL)
330#    define SK_ATTR_EXTERNALLY_DEPRECATED(msg) SK_ATTR_DEPRECATED(msg)
331#  else
332#    define SK_ATTR_EXTERNALLY_DEPRECATED(msg)
333#  endif
334#endif
335
336/**
337 * If your judgment is better than the compiler's (i.e. you've profiled it),
338 * you can use SK_ALWAYS_INLINE to force inlining. E.g.
339 *     inline void someMethod() { ... }             // may not be inlined
340 *     SK_ALWAYS_INLINE void someMethod() { ... }   // should always be inlined
341 */
342#if !defined(SK_ALWAYS_INLINE)
343#  if defined(SK_BUILD_FOR_WIN)
344#    define SK_ALWAYS_INLINE __forceinline
345#  else
346#    define SK_ALWAYS_INLINE SK_ATTRIBUTE(always_inline) inline
347#  endif
348#endif
349
350//////////////////////////////////////////////////////////////////////
351
352#if defined(__clang__) || defined(__GNUC__)
353#  define SK_PREFETCH(ptr) __builtin_prefetch(ptr)
354#  define SK_WRITE_PREFETCH(ptr) __builtin_prefetch(ptr, 1)
355#else
356#  define SK_PREFETCH(ptr)
357#  define SK_WRITE_PREFETCH(ptr)
358#endif
359
360//////////////////////////////////////////////////////////////////////
361
362#ifndef SK_PRINTF_LIKE
363#  if defined(__clang__) || defined(__GNUC__)
364#    define SK_PRINTF_LIKE(A, B) __attribute__((format(printf, (A), (B))))
365#  else
366#    define SK_PRINTF_LIKE(A, B)
367#  endif
368#endif
369
370//////////////////////////////////////////////////////////////////////
371
372#ifndef SK_SIZE_T_SPECIFIER
373#  if defined(_MSC_VER)
374#    define SK_SIZE_T_SPECIFIER "%Iu"
375#  else
376#    define SK_SIZE_T_SPECIFIER "%zu"
377#  endif
378#endif
379
380//////////////////////////////////////////////////////////////////////
381
382#ifndef SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
383#  define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 1
384#endif
385
386//////////////////////////////////////////////////////////////////////
387
388#ifndef SK_ATOMICS_PLATFORM_H
389#  if defined(_MSC_VER)
390#    define SK_ATOMICS_PLATFORM_H "../../src/ports/SkAtomics_win.h"
391#  else
392#    define SK_ATOMICS_PLATFORM_H "../../src/ports/SkAtomics_sync.h"
393#  endif
394#endif
395
396#ifndef SK_MUTEX_PLATFORM_H
397#  if defined(SK_BUILD_FOR_WIN)
398#    define SK_MUTEX_PLATFORM_H "../../src/ports/SkMutex_win.h"
399#  else
400#    define SK_MUTEX_PLATFORM_H "../../src/ports/SkMutex_pthread.h"
401#  endif
402#endif
403
404#ifndef SK_BARRIERS_PLATFORM_H
405#  if SK_HAS_COMPILER_FEATURE(thread_sanitizer)
406#    define SK_BARRIERS_PLATFORM_H "../../src/ports/SkBarriers_tsan.h"
407#  elif defined(SK_CPU_ARM32) || defined(SK_CPU_ARM64)
408#    define SK_BARRIERS_PLATFORM_H "../../src/ports/SkBarriers_arm.h"
409#  else
410#    define SK_BARRIERS_PLATFORM_H "../../src/ports/SkBarriers_x86.h"
411#  endif
412#endif
413
414
415//////////////////////////////////////////////////////////////////////
416
417#if defined(SK_GAMMA_EXPONENT) && defined(SK_GAMMA_SRGB)
418#  error "cannot define both SK_GAMMA_EXPONENT and SK_GAMMA_SRGB"
419#elif defined(SK_GAMMA_SRGB)
420#  define SK_GAMMA_EXPONENT (0.0f)
421#elif !defined(SK_GAMMA_EXPONENT)
422#  define SK_GAMMA_EXPONENT (2.2f)
423#endif
424
425#endif // SkPostConfig_DEFINED
426