• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 SkTypes_DEFINED
9 #define SkTypes_DEFINED
10 
11 /** \file SkTypes.h
12 */
13 
14 // Pre-SkUserConfig.h setup.
15 
16 // Allows embedders that want to disable macros that take arguments to just
17 // define that symbol to be one of these
18 #define SK_NOTHING_ARG1(arg1)
19 #define SK_NOTHING_ARG2(arg1, arg2)
20 #define SK_NOTHING_ARG3(arg1, arg2, arg3)
21 
22 #if !defined(SK_BUILD_FOR_ANDROID) && !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_WIN) && \
23     !defined(SK_BUILD_FOR_UNIX) && !defined(SK_BUILD_FOR_MAC) && !defined(SK_BUILD_FOR_OHOS)
24 
25     #ifdef __APPLE__
26         #include <TargetConditionals.h>
27     #endif
28 
29     #if defined(_WIN32) || defined(__SYMBIAN32__)
30         #define SK_BUILD_FOR_WIN
31     #elif defined(ANDROID) || defined(__ANDROID__)
32 
33     #elif defined(linux) || defined(__linux) || defined(__FreeBSD__) || \
34           defined(__OpenBSD__) || defined(__sun) || defined(__NetBSD__) || \
35           defined(__DragonFly__) || defined(__Fuchsia__) || \
36           defined(__GLIBC__) || defined(__GNU__) || defined(__unix__)
37 
38     #elif TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
39         #define SK_BUILD_FOR_IOS
40     #else
41         #define SK_BUILD_FOR_MAC
42     #endif
43 
44 #endif
45 
46 #if defined(SK_BUILD_FOR_WIN) && !defined(__clang__)
47     #if !defined(SK_RESTRICT)
48         #define SK_RESTRICT __restrict
49     #endif
50     #if !defined(SK_WARN_UNUSED_RESULT)
51         #define SK_WARN_UNUSED_RESULT
52     #endif
53 #endif
54 
55 #if !defined(SK_RESTRICT)
56     #define SK_RESTRICT __restrict__
57 #endif
58 
59 #if !defined(SK_WARN_UNUSED_RESULT)
60     #define SK_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
61 #endif
62 
63 #if !defined(SK_CPU_BENDIAN) && !defined(SK_CPU_LENDIAN)
64     #if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
65         #define SK_CPU_BENDIAN
66     #elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
67         #define SK_CPU_LENDIAN
68     #elif defined(__sparc) || defined(__sparc__) || \
69       defined(_POWER) || defined(__powerpc__) || \
70       defined(__ppc__) || defined(__hppa) || \
71       defined(__PPC__) || defined(__PPC64__) || \
72       defined(_MIPSEB) || defined(__ARMEB__) || \
73       defined(__s390__) || \
74       (defined(__sh__) && defined(__BIG_ENDIAN__)) || \
75       (defined(__ia64) && defined(__BIG_ENDIAN__))
76          #define SK_CPU_BENDIAN
77     #else
78         #define SK_CPU_LENDIAN
79     #endif
80 #endif
81 
82 #if defined(__i386) || defined(_M_IX86) ||  defined(__x86_64__) || defined(_M_X64)
83   #define SK_CPU_X86 1
84 #endif
85 
86 /**
87  *  SK_CPU_SSE_LEVEL
88  *
89  *  If defined, SK_CPU_SSE_LEVEL should be set to the highest supported level.
90  *  On non-intel CPU this should be undefined.
91  */
92 #define SK_CPU_SSE_LEVEL_SSE1     10
93 #define SK_CPU_SSE_LEVEL_SSE2     20
94 #define SK_CPU_SSE_LEVEL_SSE3     30
95 #define SK_CPU_SSE_LEVEL_SSSE3    31
96 #define SK_CPU_SSE_LEVEL_SSE41    41
97 #define SK_CPU_SSE_LEVEL_SSE42    42
98 #define SK_CPU_SSE_LEVEL_AVX      51
99 #define SK_CPU_SSE_LEVEL_AVX2     52
100 #define SK_CPU_SSE_LEVEL_SKX      60
101 
102 // Are we in GCC/Clang?
103 #ifndef SK_CPU_SSE_LEVEL
104     // These checks must be done in descending order to ensure we set the highest
105     // available SSE level.
106     #if defined(__AVX512F__) && defined(__AVX512DQ__) && defined(__AVX512CD__) && \
107         defined(__AVX512BW__) && defined(__AVX512VL__)
108         #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SKX
109     #elif defined(__AVX2__)
110         #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_AVX2
111     #elif defined(__AVX__)
112         #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_AVX
113     #elif defined(__SSE4_2__)
114         #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE42
115     #elif defined(__SSE4_1__)
116         #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE41
117     #elif defined(__SSSE3__)
118         #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSSE3
119     #elif defined(__SSE3__)
120         #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE3
121     #elif defined(__SSE2__)
122         #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE2
123     #endif
124 #endif
125 
126 // Are we in VisualStudio?
127 #ifndef SK_CPU_SSE_LEVEL
128     // These checks must be done in descending order to ensure we set the highest
129     // available SSE level. 64-bit intel guarantees at least SSE2 support.
130     #if defined(__AVX512F__) && defined(__AVX512DQ__) && defined(__AVX512CD__) && \
131         defined(__AVX512BW__) && defined(__AVX512VL__)
132         #define SK_CPU_SSE_LEVEL        SK_CPU_SSE_LEVEL_SKX
133     #elif defined(__AVX2__)
134         #define SK_CPU_SSE_LEVEL        SK_CPU_SSE_LEVEL_AVX2
135     #elif defined(__AVX__)
136         #define SK_CPU_SSE_LEVEL        SK_CPU_SSE_LEVEL_AVX
137     #elif defined(_M_X64) || defined(_M_AMD64)
138         #define SK_CPU_SSE_LEVEL        SK_CPU_SSE_LEVEL_SSE2
139     #elif defined(_M_IX86_FP)
140         #if _M_IX86_FP >= 2
141             #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE2
142         #elif _M_IX86_FP == 1
143             #define SK_CPU_SSE_LEVEL    SK_CPU_SSE_LEVEL_SSE1
144         #endif
145     #endif
146 #endif
147 
148 // ARM defines
149 #if defined(__arm__) && (!defined(__APPLE__) || !TARGET_IPHONE_SIMULATOR)
150     #define SK_CPU_ARM32
151 #elif defined(__aarch64__)
152     #define SK_CPU_ARM64
153 #endif
154 
155 // All 64-bit ARM chips have NEON.  Many 32-bit ARM chips do too.
156 #if !defined(SK_ARM_HAS_NEON) && defined(__ARM_NEON)
157     #define SK_ARM_HAS_NEON
158 #endif
159 
160 #if defined(__ARM_FEATURE_CRC32)
161     #define SK_ARM_HAS_CRC32
162 #endif
163 
164 
165 // DLL/.so exports.
166 #if !defined(SKIA_IMPLEMENTATION)
167     #define SKIA_IMPLEMENTATION 0
168 #endif
169 #if !defined(SK_API)
170     #if defined(SKIA_DLL)
171         #if defined(_MSC_VER)
172             #if SKIA_IMPLEMENTATION
173                 #define SK_API __declspec(dllexport)
174             #else
175                 #define SK_API __declspec(dllimport)
176             #endif
177         #else
178             #define SK_API __attribute__((visibility("default")))
179         #endif
180     #else
181         #define SK_API
182     #endif
183 #endif
184 
185 // SK_SPI is functionally identical to SK_API, but used within src to clarify that it's less stable
186 #if !defined(SK_SPI)
187     #define SK_SPI SK_API
188 #endif
189 
190 // IWYU pragma: begin_exports
191 #if defined (SK_USER_CONFIG_HEADER)
192     #include SK_USER_CONFIG_HEADER
193 #else
194     #include "include/config/SkUserConfig.h"
195 #endif
196 #include <stddef.h>
197 #include <stdint.h>
198 // IWYU pragma: end_exports
199 
200 // Post SkUserConfig.h checks and such.
201 #if !defined(SK_DEBUG) && !defined(SK_RELEASE)
202     #ifdef NDEBUG
203         #define SK_RELEASE
204     #else
205         #define SK_DEBUG
206     #endif
207 #endif
208 
209 #if defined(SK_DEBUG) && defined(SK_RELEASE)
210 #  error "cannot define both SK_DEBUG and SK_RELEASE"
211 #elif !defined(SK_DEBUG) && !defined(SK_RELEASE)
212 #  error "must define either SK_DEBUG or SK_RELEASE"
213 #endif
214 
215 #if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN)
216 #  error "cannot define both SK_CPU_LENDIAN and SK_CPU_BENDIAN"
217 #elif !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN)
218 #  error "must define either SK_CPU_LENDIAN or SK_CPU_BENDIAN"
219 #endif
220 
221 #if defined(SK_CPU_BENDIAN) && !defined(I_ACKNOWLEDGE_SKIA_DOES_NOT_SUPPORT_BIG_ENDIAN)
222     #error "The Skia team is not endian-savvy enough to support big-endian CPUs."
223     #error "If you still want to use Skia,"
224     #error "please define I_ACKNOWLEDGE_SKIA_DOES_NOT_SUPPORT_BIG_ENDIAN."
225 #endif
226 
227 #if !defined(SK_ATTRIBUTE)
228 #  if defined(__clang__) || defined(__GNUC__)
229 #    define SK_ATTRIBUTE(attr) __attribute__((attr))
230 #  else
231 #    define SK_ATTRIBUTE(attr)
232 #  endif
233 #endif
234 
235 #if !defined(SK_SUPPORT_GPU)
236 #  define SK_SUPPORT_GPU true
237 #endif
238 
239 #if SK_SUPPORT_GPU || SK_GRAPHITE_ENABLED
240 #  if !defined(SK_ENABLE_SKSL)
241 #    define SK_ENABLE_SKSL
242 #  endif
243 #else
244 #  undef SK_GL
245 #  undef SK_VULKAN
246 #  undef SK_METAL
247 #  undef SK_DAWN
248 #  undef SK_DIRECT3D
249 #endif
250 
251 #if !defined(SkUNREACHABLE)
252 #  if defined(_MSC_VER) && !defined(__clang__)
253 #    include <intrin.h>
254 #    define FAST_FAIL_INVALID_ARG                 5
255 // See https://developercommunity.visualstudio.com/content/problem/1128631/code-flow-doesnt-see-noreturn-with-extern-c.html
256 // for why this is wrapped. Hopefully removable after msvc++ 19.27 is no longer supported.
sk_fast_fail()257 [[noreturn]] static inline void sk_fast_fail() { __fastfail(FAST_FAIL_INVALID_ARG); }
258 #    define SkUNREACHABLE sk_fast_fail()
259 #  else
260 #    define SkUNREACHABLE __builtin_trap()
261 #  endif
262 #endif
263 
264 #if defined(SK_BUILD_FOR_GOOGLE3)
265     void SkDebugfForDumpStackTrace(const char* data, void* unused);
266     void DumpStackTrace(int skip_count, void w(const char*, void*), void* arg);
267 #  define SK_DUMP_GOOGLE3_STACK() DumpStackTrace(0, SkDebugfForDumpStackTrace, nullptr)
268 #else
269 #  define SK_DUMP_GOOGLE3_STACK()
270 #endif
271 
272 #ifndef SK_ABORT
273 #  ifdef SK_BUILD_FOR_WIN
274      // This style lets Visual Studio follow errors back to the source file.
275 #    define SK_DUMP_LINE_FORMAT "%s(%d)"
276 #  else
277 #    define SK_DUMP_LINE_FORMAT "%s:%d"
278 #  endif
279 #  ifdef SK_BUILD_FOR_OHOS
280 #    define SK_ABORT(message, ...)
281 #  else
282 #    define SK_ABORT(message, ...) \
283         do { \
284             SkDebugf(SK_DUMP_LINE_FORMAT ": fatal error: \"" message "\"\n", \
285                  __FILE__, __LINE__, ##__VA_ARGS__); \
286             SK_DUMP_GOOGLE3_STACK(); \
287             sk_abort_no_print(); \
288         } while (false)
289 #  endif
290 #endif
291 
292 // If SK_R32_SHIFT is set, we'll use that to choose RGBA or BGRA.
293 // If not, we'll default to RGBA everywhere except BGRA on Windows.
294 #if defined(SK_R32_SHIFT)
295     static_assert(SK_R32_SHIFT == 0 || SK_R32_SHIFT == 16, "");
296 #elif defined(SK_BUILD_FOR_WIN)
297     #define SK_R32_SHIFT 16
298 #else
299     #define SK_R32_SHIFT 0
300 #endif
301 
302 #if defined(SK_B32_SHIFT)
303     static_assert(SK_B32_SHIFT == (16-SK_R32_SHIFT), "");
304 #else
305     #define SK_B32_SHIFT (16-SK_R32_SHIFT)
306 #endif
307 
308 #define SK_G32_SHIFT 8
309 #define SK_A32_SHIFT 24
310 
311 
312 /**
313  * SK_PMCOLOR_BYTE_ORDER can be used to query the byte order of SkPMColor at compile time.
314  */
315 #ifdef SK_CPU_BENDIAN
316 #  define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3)     \
317         (SK_ ## C3 ## 32_SHIFT == 0  &&             \
318          SK_ ## C2 ## 32_SHIFT == 8  &&             \
319          SK_ ## C1 ## 32_SHIFT == 16 &&             \
320          SK_ ## C0 ## 32_SHIFT == 24)
321 #else
322 #  define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3)     \
323         (SK_ ## C0 ## 32_SHIFT == 0  &&             \
324          SK_ ## C1 ## 32_SHIFT == 8  &&             \
325          SK_ ## C2 ## 32_SHIFT == 16 &&             \
326          SK_ ## C3 ## 32_SHIFT == 24)
327 #endif
328 
329 #if defined SK_DEBUG && defined SK_BUILD_FOR_WIN
330     #ifdef free
331         #undef free
332     #endif
333     #include <crtdbg.h>
334     #undef free
335 #endif
336 
337 #if !defined(SK_UNUSED)
338 #  if !defined(__clang__) && defined(_MSC_VER)
339 #    define SK_UNUSED __pragma(warning(suppress:4189))
340 #  else
341 #    define SK_UNUSED SK_ATTRIBUTE(unused)
342 #  endif
343 #endif
344 
345 #if !defined(SK_MAYBE_UNUSED)
346 #  if defined(__clang__) || defined(__GNUC__)
347 #    define SK_MAYBE_UNUSED [[maybe_unused]]
348 #  else
349 #    define SK_MAYBE_UNUSED
350 #  endif
351 #endif
352 
353 /**
354  * If your judgment is better than the compiler's (i.e. you've profiled it),
355  * you can use SK_ALWAYS_INLINE to force inlining. E.g.
356  *     inline void someMethod() { ... }             // may not be inlined
357  *     SK_ALWAYS_INLINE void someMethod() { ... }   // should always be inlined
358  */
359 #if !defined(SK_ALWAYS_INLINE)
360 #  if defined(SK_BUILD_FOR_WIN)
361 #    define SK_ALWAYS_INLINE __forceinline
362 #  else
363 #    define SK_ALWAYS_INLINE SK_ATTRIBUTE(always_inline) inline
364 #  endif
365 #endif
366 
367 /**
368  * If your judgment is better than the compiler's (i.e. you've profiled it),
369  * you can use SK_NEVER_INLINE to prevent inlining.
370  */
371 #if !defined(SK_NEVER_INLINE)
372 #  if defined(SK_BUILD_FOR_WIN)
373 #    define SK_NEVER_INLINE __declspec(noinline)
374 #  else
375 #    define SK_NEVER_INLINE SK_ATTRIBUTE(noinline)
376 #  endif
377 #endif
378 
379 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
380     #define SK_PREFETCH(ptr) _mm_prefetch(reinterpret_cast<const char*>(ptr), _MM_HINT_T0)
381 #elif defined(__GNUC__)
382     #define SK_PREFETCH(ptr) __builtin_prefetch(ptr)
383 #else
384     #define SK_PREFETCH(ptr)
385 #endif
386 
387 #ifndef SK_PRINTF_LIKE
388 #  if defined(__clang__) || defined(__GNUC__)
389 #    define SK_PRINTF_LIKE(A, B) __attribute__((format(printf, (A), (B))))
390 #  else
391 #    define SK_PRINTF_LIKE(A, B)
392 #  endif
393 #endif
394 
395 #ifndef SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
396     #define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 0
397 #endif
398 
399 #if !defined(SK_GAMMA_EXPONENT)
400     #define SK_GAMMA_EXPONENT (0.0f)  // SRGB
401 #endif
402 
403 #ifndef GR_TEST_UTILS
404 #  define GR_TEST_UTILS 0
405 #endif
406 
407 #ifndef SK_GPU_V1
408 #  define SK_GPU_V1 1
409 #endif
410 
411 #if defined(SK_HISTOGRAM_ENUMERATION)  || \
412     defined(SK_HISTOGRAM_BOOLEAN)      || \
413     defined(SK_HISTOGRAM_EXACT_LINEAR) || \
414     defined(SK_HISTOGRAM_MEMORY_KB)
415 #  define SK_HISTOGRAMS_ENABLED 1
416 #else
417 #  define SK_HISTOGRAMS_ENABLED 0
418 #endif
419 
420 #ifndef SK_HISTOGRAM_BOOLEAN
421 #  define SK_HISTOGRAM_BOOLEAN(name, sample)
422 #endif
423 
424 #ifndef SK_HISTOGRAM_ENUMERATION
425 #  define SK_HISTOGRAM_ENUMERATION(name, sample, enum_size)
426 #endif
427 
428 #ifndef SK_HISTOGRAM_EXACT_LINEAR
429 #  define SK_HISTOGRAM_EXACT_LINEAR(name, sample, value_max)
430 #endif
431 
432 #ifndef SK_HISTOGRAM_MEMORY_KB
433 #  define SK_HISTOGRAM_MEMORY_KB(name, sample)
434 #endif
435 
436 #define SK_HISTOGRAM_PERCENTAGE(name, percent_as_int) \
437     SK_HISTOGRAM_EXACT_LINEAR(name, percent_as_int, 101)
438 
439 #ifndef SK_DISABLE_LEGACY_SHADERCONTEXT
440 #define SK_ENABLE_LEGACY_SHADERCONTEXT
441 #endif
442 
443 #ifdef SK_ENABLE_API_AVAILABLE
444 #define SK_API_AVAILABLE API_AVAILABLE
445 #else
446 #define SK_API_AVAILABLE(...)
447 #endif
448 
449 #if defined(SK_BUILD_FOR_LIBFUZZER) || defined(SK_BUILD_FOR_AFL_FUZZ)
450     #define SK_BUILD_FOR_FUZZER
451 #endif
452 
453 /** Called internally if we hit an unrecoverable error.
454     The platform implementation must not return, but should either throw
455     an exception or otherwise exit.
456 */
457 [[noreturn]] SK_API extern void sk_abort_no_print(void);
458 
459 #ifndef SkDebugf
460     SK_API void SkDebugf(const char format[], ...) SK_PRINTF_LIKE(1, 2);
461 #endif
462 
463 // SkASSERT, SkASSERTF and SkASSERT_RELEASE can be used as stand alone assertion expressions, e.g.
464 //    uint32_t foo(int x) {
465 //        SkASSERT(x > 4);
466 //        return x - 4;
467 //    }
468 // and are also written to be compatible with constexpr functions:
469 //    constexpr uint32_t foo(int x) {
470 //        return SkASSERT(x > 4),
471 //               x - 4;
472 //    }
473 #define SkASSERT_RELEASE(cond) \
474         static_cast<void>( (cond) ? (void)0 : []{ SK_ABORT("assert(%s)", #cond); }() )
475 
476 #ifdef SK_DEBUG
477     #define SkASSERT(cond) SkASSERT_RELEASE(cond)
478     #define SkASSERTF(cond, fmt, ...) static_cast<void>( (cond) ? (void)0 : [&]{ \
479                                           SkDebugf(fmt"\n", ##__VA_ARGS__);      \
480                                           SK_ABORT("assert(%s)", #cond);         \
481                                       }() )
482     #define SkDEBUGFAIL(message)        SK_ABORT("%s", message)
483     #define SkDEBUGFAILF(fmt, ...)      SK_ABORT(fmt, ##__VA_ARGS__)
484     #define SkDEBUGCODE(...)            __VA_ARGS__
485     #define SkDEBUGF(...)               SkDebugf(__VA_ARGS__)
486     #define SkAssertResult(cond)        SkASSERT(cond)
487 #else
488     #define SkASSERT(cond)            static_cast<void>(0)
489     #define SkASSERTF(cond, fmt, ...) static_cast<void>(0)
490     #define SkDEBUGFAIL(message)
491     #define SkDEBUGFAILF(fmt, ...)
492     #define SkDEBUGCODE(...)
493     #define SkDEBUGF(...)
494     #ifdef SK_BUILD_FOR_OHOS
495         #define SkDebugf(...)
496     #endif
497 
498     // unlike SkASSERT, this macro executes its condition in the non-debug build.
499     // The if is present so that this can be used with functions marked SK_WARN_UNUSED_RESULT.
500     #define SkAssertResult(cond)         if (cond) {} do {} while(false)
501 #endif
502 
503 ////////////////////////////////////////////////////////////////////////////////
504 
505 /** Fast type for unsigned 8 bits. Use for parameter passing and local
506     variables, not for storage
507 */
508 typedef unsigned U8CPU;
509 
510 /** Fast type for unsigned 16 bits. Use for parameter passing and local
511     variables, not for storage
512 */
513 typedef unsigned U16CPU;
514 
515 /** @return false or true based on the condition
516 */
SkToBool(const T & x)517 template <typename T> static constexpr bool SkToBool(const T& x) {
518     return 0 != x;  // NOLINT(modernize-use-nullptr)
519 }
520 
521 static constexpr int16_t SK_MaxS16 = INT16_MAX;
522 static constexpr int16_t SK_MinS16 = -SK_MaxS16;
523 
524 static constexpr int32_t SK_MaxS32 = INT32_MAX;
525 static constexpr int32_t SK_MinS32 = -SK_MaxS32;
526 static constexpr int32_t SK_NaN32  = INT32_MIN;
527 
528 static constexpr int64_t SK_MaxS64 = INT64_MAX;
529 static constexpr int64_t SK_MinS64 = -SK_MaxS64;
530 
SkLeftShift(int32_t value,int32_t shift)531 static inline constexpr int32_t SkLeftShift(int32_t value, int32_t shift) {
532     return (int32_t) ((uint32_t) value << shift);
533 }
534 
SkLeftShift(int64_t value,int32_t shift)535 static inline constexpr int64_t SkLeftShift(int64_t value, int32_t shift) {
536     return (int64_t) ((uint64_t) value << shift);
537 }
538 
539 ////////////////////////////////////////////////////////////////////////////////
540 
541 /** @return the number of entries in an array (not a pointer)
542 */
543 template <typename T, size_t N> char (&SkArrayCountHelper(T (&array)[N]))[N];
544 #define SK_ARRAY_COUNT(array) (sizeof(SkArrayCountHelper(array)))
545 
546 ////////////////////////////////////////////////////////////////////////////////
547 
SkAlign2(T x)548 template <typename T> static constexpr T SkAlign2(T x) { return (x + 1) >> 1 << 1; }
SkAlign4(T x)549 template <typename T> static constexpr T SkAlign4(T x) { return (x + 3) >> 2 << 2; }
SkAlign8(T x)550 template <typename T> static constexpr T SkAlign8(T x) { return (x + 7) >> 3 << 3; }
551 
SkIsAlign2(T x)552 template <typename T> static constexpr bool SkIsAlign2(T x) { return 0 == (x & 1); }
SkIsAlign4(T x)553 template <typename T> static constexpr bool SkIsAlign4(T x) { return 0 == (x & 3); }
SkIsAlign8(T x)554 template <typename T> static constexpr bool SkIsAlign8(T x) { return 0 == (x & 7); }
555 
SkAlignPtr(T x)556 template <typename T> static constexpr T SkAlignPtr(T x) {
557     return sizeof(void*) == 8 ? SkAlign8(x) : SkAlign4(x);
558 }
SkIsAlignPtr(T x)559 template <typename T> static constexpr bool SkIsAlignPtr(T x) {
560     return sizeof(void*) == 8 ? SkIsAlign8(x) : SkIsAlign4(x);
561 }
562 
563 /**
564  *  align up to a power of 2
565  */
SkAlignTo(size_t x,size_t alignment)566 static inline constexpr size_t SkAlignTo(size_t x, size_t alignment) {
567     // The same as alignment && SkIsPow2(value), w/o a dependency cycle.
568     SkASSERT(alignment && (alignment & (alignment - 1)) == 0);
569     return (x + alignment - 1) & ~(alignment - 1);
570 }
571 
572 typedef uint32_t SkFourByteTag;
SkSetFourByteTag(char a,char b,char c,char d)573 static inline constexpr SkFourByteTag SkSetFourByteTag(char a, char b, char c, char d) {
574     return (((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | (uint32_t)d);
575 }
576 
577 ////////////////////////////////////////////////////////////////////////////////
578 
579 /** 32 bit integer to hold a unicode value
580 */
581 typedef int32_t SkUnichar;
582 
583 /** 16 bit unsigned integer to hold a glyph index
584 */
585 typedef uint16_t SkGlyphID;
586 
587 /** 32 bit value to hold a millisecond duration
588     Note that SK_MSecMax is about 25 days.
589 */
590 typedef uint32_t SkMSec;
591 
592 /** Maximum representable milliseconds; 24d 20h 31m 23.647s.
593 */
594 static constexpr SkMSec SK_MSecMax = INT32_MAX;
595 
596 /** The generation IDs in Skia reserve 0 has an invalid marker.
597 */
598 static constexpr uint32_t SK_InvalidGenID = 0;
599 
600 /** The unique IDs in Skia reserve 0 has an invalid marker.
601 */
602 static constexpr uint32_t SK_InvalidUniqueID = 0;
603 
SkAbs32(int32_t value)604 static inline int32_t SkAbs32(int32_t value) {
605     SkASSERT(value != SK_NaN32);  // The most negative int32_t can't be negated.
606     if (value < 0) {
607         value = -value;
608     }
609     return value;
610 }
611 
SkTAbs(T value)612 template <typename T> static inline T SkTAbs(T value) {
613     if (value < 0) {
614         value = -value;
615     }
616     return value;
617 }
618 
619 ////////////////////////////////////////////////////////////////////////////////
620 
621 /** Indicates whether an allocation should count against a cache budget.
622 */
623 enum class SkBudgeted : bool {
624     kNo  = false,
625     kYes = true
626 };
627 
628 /** Indicates whether a backing store needs to be an exact match or can be
629     larger than is strictly necessary
630 */
631 enum class SkBackingFit {
632     kApprox,
633     kExact
634 };
635 
636 #endif
637