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)
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 __attribute__((visibility("default")))
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 # ifndef SK_BUILD_FOR_OHOS
280 # define SK_ABORT(message, ...) \
281 do { \
282 sk_abort_no_print(); \
283 } while (false)
284 # else
285 # define SK_ABORT(message, ...) \
286 do { \
287 SkDebugf(SK_DUMP_LINE_FORMAT ": fatal error: \"" message "\"\n", \
288 __FILE__, __LINE__, ##__VA_ARGS__); \
289 SK_DUMP_GOOGLE3_STACK(); \
290 sk_abort_no_print(); \
291 } while (false)
292 # endif
293 #endif
294
295 // If SK_R32_SHIFT is set, we'll use that to choose RGBA or BGRA.
296 // If not, we'll default to RGBA everywhere except BGRA on Windows.
297 #if defined(SK_R32_SHIFT)
298 static_assert(SK_R32_SHIFT == 0 || SK_R32_SHIFT == 16, "");
299 #elif defined(SK_BUILD_FOR_WIN)
300 #define SK_R32_SHIFT 16
301 #else
302 #define SK_R32_SHIFT 0
303 #endif
304
305 #if defined(SK_B32_SHIFT)
306 static_assert(SK_B32_SHIFT == (16-SK_R32_SHIFT), "");
307 #else
308 #define SK_B32_SHIFT (16-SK_R32_SHIFT)
309 #endif
310
311 #define SK_G32_SHIFT 8
312 #define SK_A32_SHIFT 24
313
314
315 /**
316 * SK_PMCOLOR_BYTE_ORDER can be used to query the byte order of SkPMColor at compile time.
317 */
318 #ifdef SK_CPU_BENDIAN
319 # define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3) \
320 (SK_ ## C3 ## 32_SHIFT == 0 && \
321 SK_ ## C2 ## 32_SHIFT == 8 && \
322 SK_ ## C1 ## 32_SHIFT == 16 && \
323 SK_ ## C0 ## 32_SHIFT == 24)
324 #else
325 # define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3) \
326 (SK_ ## C0 ## 32_SHIFT == 0 && \
327 SK_ ## C1 ## 32_SHIFT == 8 && \
328 SK_ ## C2 ## 32_SHIFT == 16 && \
329 SK_ ## C3 ## 32_SHIFT == 24)
330 #endif
331
332 #if defined SK_DEBUG && defined SK_BUILD_FOR_WIN
333 #ifdef free
334 #undef free
335 #endif
336 #include <crtdbg.h>
337 #undef free
338 #endif
339
340 #if !defined(SK_UNUSED)
341 # if !defined(__clang__) && defined(_MSC_VER)
342 # define SK_UNUSED __pragma(warning(suppress:4189))
343 # else
344 # define SK_UNUSED SK_ATTRIBUTE(unused)
345 # endif
346 #endif
347
348 #if !defined(SK_MAYBE_UNUSED)
349 # if defined(__clang__) || defined(__GNUC__)
350 # define SK_MAYBE_UNUSED [[maybe_unused]]
351 # else
352 # define SK_MAYBE_UNUSED
353 # endif
354 #endif
355
356 /**
357 * If your judgment is better than the compiler's (i.e. you've profiled it),
358 * you can use SK_ALWAYS_INLINE to force inlining. E.g.
359 * inline void someMethod() { ... } // may not be inlined
360 * SK_ALWAYS_INLINE void someMethod() { ... } // should always be inlined
361 */
362 #if !defined(SK_ALWAYS_INLINE)
363 # if defined(SK_BUILD_FOR_WIN)
364 # define SK_ALWAYS_INLINE __forceinline
365 # else
366 # define SK_ALWAYS_INLINE SK_ATTRIBUTE(always_inline) inline
367 # endif
368 #endif
369
370 /**
371 * If your judgment is better than the compiler's (i.e. you've profiled it),
372 * you can use SK_NEVER_INLINE to prevent inlining.
373 */
374 #if !defined(SK_NEVER_INLINE)
375 # if defined(SK_BUILD_FOR_WIN)
376 # define SK_NEVER_INLINE __declspec(noinline)
377 # else
378 # define SK_NEVER_INLINE SK_ATTRIBUTE(noinline)
379 # endif
380 #endif
381
382 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
383 #define SK_PREFETCH(ptr) _mm_prefetch(reinterpret_cast<const char*>(ptr), _MM_HINT_T0)
384 #elif defined(__GNUC__)
385 #define SK_PREFETCH(ptr) __builtin_prefetch(ptr)
386 #else
387 #define SK_PREFETCH(ptr)
388 #endif
389
390 #ifndef SK_PRINTF_LIKE
391 # if defined(__clang__) || defined(__GNUC__)
392 # define SK_PRINTF_LIKE(A, B) __attribute__((format(printf, (A), (B))))
393 # else
394 # define SK_PRINTF_LIKE(A, B)
395 # endif
396 #endif
397
398 #ifndef SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
399 #define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 0
400 #endif
401
402 #if !defined(SK_GAMMA_EXPONENT)
403 #define SK_GAMMA_EXPONENT (0.0f) // SRGB
404 #endif
405
406 #ifndef GR_TEST_UTILS
407 # define GR_TEST_UTILS 0
408 #endif
409
410 #ifndef SK_GPU_V1
411 # define SK_GPU_V1 1
412 #endif
413
414 #if defined(SK_HISTOGRAM_ENUMERATION) || \
415 defined(SK_HISTOGRAM_BOOLEAN) || \
416 defined(SK_HISTOGRAM_EXACT_LINEAR) || \
417 defined(SK_HISTOGRAM_MEMORY_KB)
418 # define SK_HISTOGRAMS_ENABLED 1
419 #else
420 # define SK_HISTOGRAMS_ENABLED 0
421 #endif
422
423 #ifndef SK_HISTOGRAM_BOOLEAN
424 # define SK_HISTOGRAM_BOOLEAN(name, sample)
425 #endif
426
427 #ifndef SK_HISTOGRAM_ENUMERATION
428 # define SK_HISTOGRAM_ENUMERATION(name, sample, enum_size)
429 #endif
430
431 #ifndef SK_HISTOGRAM_EXACT_LINEAR
432 # define SK_HISTOGRAM_EXACT_LINEAR(name, sample, value_max)
433 #endif
434
435 #ifndef SK_HISTOGRAM_MEMORY_KB
436 # define SK_HISTOGRAM_MEMORY_KB(name, sample)
437 #endif
438
439 #define SK_HISTOGRAM_PERCENTAGE(name, percent_as_int) \
440 SK_HISTOGRAM_EXACT_LINEAR(name, percent_as_int, 101)
441
442 #ifndef SK_DISABLE_LEGACY_SHADERCONTEXT
443 #define SK_ENABLE_LEGACY_SHADERCONTEXT
444 #endif
445
446 #ifdef SK_ENABLE_API_AVAILABLE
447 #define SK_API_AVAILABLE API_AVAILABLE
448 #else
449 #define SK_API_AVAILABLE(...)
450 #endif
451
452 #if defined(SK_BUILD_FOR_LIBFUZZER) || defined(SK_BUILD_FOR_AFL_FUZZ)
453 #define SK_BUILD_FOR_FUZZER
454 #endif
455
456 /** Called internally if we hit an unrecoverable error.
457 The platform implementation must not return, but should either throw
458 an exception or otherwise exit.
459 */
460 [[noreturn]] SK_API extern void sk_abort_no_print(void);
461
462 #ifndef SkDebugf
463 extern SK_API void SkDebugf(const char format[], ...) SK_PRINTF_LIKE(1, 2);
464 #endif
465
466 #ifdef SKIA_OHOS_SINGLE_OWNER
467 extern SK_API bool GetEnableSkiaSingleOwner();
468
469 extern SK_API void PrintBackTrace(uint32_t tid);
470
471 extern bool IsRenderService();
472 #endif
473
474 // SkASSERT, SkASSERTF and SkASSERT_RELEASE can be used as stand alone assertion expressions, e.g.
475 // uint32_t foo(int x) {
476 // SkASSERT(x > 4);
477 // return x - 4;
478 // }
479 // and are also written to be compatible with constexpr functions:
480 // constexpr uint32_t foo(int x) {
481 // return SkASSERT(x > 4),
482 // x - 4;
483 // }
484 #define SkASSERT_RELEASE(cond) \
485 static_cast<void>( (cond) ? (void)0 : []{ SK_ABORT("assert(%s)", #cond); }() )
486
487 #ifdef SK_DEBUG
488 #define SkASSERT(cond) SkASSERT_RELEASE(cond)
489 #define SkASSERTF(cond, fmt, ...) static_cast<void>( (cond) ? (void)0 : [&]{ \
490 SkDebugf(fmt"\n", ##__VA_ARGS__); \
491 SK_ABORT("assert(%s)", #cond); \
492 }() )
493 #define SkDEBUGFAIL(message) SK_ABORT("%s", message)
494 #define SkDEBUGFAILF(fmt, ...) SK_ABORT(fmt, ##__VA_ARGS__)
495 #define SkDEBUGCODE(...) __VA_ARGS__
496 #define SkDEBUGF(...) SkDebugf(__VA_ARGS__)
497 #define SkAssertResult(cond) SkASSERT(cond)
498 #else
499 #define SkASSERT(cond) static_cast<void>(0)
500 #define SkASSERTF(cond, fmt, ...) static_cast<void>(0)
501 #define SkDEBUGFAIL(message)
502 #define SkDEBUGFAILF(fmt, ...)
503 #define SkDEBUGCODE(...)
504 #define SkDEBUGF(...)
505 #ifndef SK_BUILD_FOR_OHOS
506 #define SkDebugf(...)
507 #endif
508 // unlike SkASSERT, this macro executes its condition in the non-debug build.
509 // The if is present so that this can be used with functions marked SK_WARN_UNUSED_RESULT.
510 #define SkAssertResult(cond) if (cond) {} do {} while(false)
511 #endif
512
513 #ifdef SKIA_OHOS_SHADER_REDUCE
514 extern SK_API bool SkShaderReduceProperty();
515 #endif
516
517 ////////////////////////////////////////////////////////////////////////////////
518
519 /** Fast type for unsigned 8 bits. Use for parameter passing and local
520 variables, not for storage
521 */
522 typedef unsigned U8CPU;
523
524 /** Fast type for unsigned 16 bits. Use for parameter passing and local
525 variables, not for storage
526 */
527 typedef unsigned U16CPU;
528
529 /** @return false or true based on the condition
530 */
SkToBool(const T & x)531 template <typename T> static constexpr bool SkToBool(const T& x) {
532 return 0 != x; // NOLINT(modernize-use-nullptr)
533 }
534
535 static constexpr int16_t SK_MaxS16 = INT16_MAX;
536 static constexpr int16_t SK_MinS16 = -SK_MaxS16;
537
538 static constexpr int32_t SK_MaxS32 = INT32_MAX;
539 static constexpr int32_t SK_MinS32 = -SK_MaxS32;
540 static constexpr int32_t SK_NaN32 = INT32_MIN;
541
542 static constexpr int64_t SK_MaxS64 = INT64_MAX;
543 static constexpr int64_t SK_MinS64 = -SK_MaxS64;
544
SkLeftShift(int32_t value,int32_t shift)545 static inline constexpr int32_t SkLeftShift(int32_t value, int32_t shift) {
546 return (int32_t) ((uint32_t) value << shift);
547 }
548
SkLeftShift(int64_t value,int32_t shift)549 static inline constexpr int64_t SkLeftShift(int64_t value, int32_t shift) {
550 return (int64_t) ((uint64_t) value << shift);
551 }
552
553 ////////////////////////////////////////////////////////////////////////////////
554
555 /** @return the number of entries in an array (not a pointer)
556 */
557 template <typename T, size_t N> char (&SkArrayCountHelper(T (&array)[N]))[N];
558 #define SK_ARRAY_COUNT(array) (sizeof(SkArrayCountHelper(array)))
559
560 ////////////////////////////////////////////////////////////////////////////////
561
SkAlign2(T x)562 template <typename T> static constexpr T SkAlign2(T x) { return (x + 1) >> 1 << 1; }
SkAlign4(T x)563 template <typename T> static constexpr T SkAlign4(T x) { return (x + 3) >> 2 << 2; }
SkAlign8(T x)564 template <typename T> static constexpr T SkAlign8(T x) { return (x + 7) >> 3 << 3; }
565
SkIsAlign2(T x)566 template <typename T> static constexpr bool SkIsAlign2(T x) { return 0 == (x & 1); }
SkIsAlign4(T x)567 template <typename T> static constexpr bool SkIsAlign4(T x) { return 0 == (x & 3); }
SkIsAlign8(T x)568 template <typename T> static constexpr bool SkIsAlign8(T x) { return 0 == (x & 7); }
569
SkAlignPtr(T x)570 template <typename T> static constexpr T SkAlignPtr(T x) {
571 return sizeof(void*) == 8 ? SkAlign8(x) : SkAlign4(x);
572 }
SkIsAlignPtr(T x)573 template <typename T> static constexpr bool SkIsAlignPtr(T x) {
574 return sizeof(void*) == 8 ? SkIsAlign8(x) : SkIsAlign4(x);
575 }
576
577 /**
578 * align up to a power of 2
579 */
SkAlignTo(size_t x,size_t alignment)580 static inline constexpr size_t SkAlignTo(size_t x, size_t alignment) {
581 // The same as alignment && SkIsPow2(value), w/o a dependency cycle.
582 SkASSERT(alignment && (alignment & (alignment - 1)) == 0);
583 return (x + alignment - 1) & ~(alignment - 1);
584 }
585
586 typedef uint32_t SkFourByteTag;
SkSetFourByteTag(char a,char b,char c,char d)587 static inline constexpr SkFourByteTag SkSetFourByteTag(char a, char b, char c, char d) {
588 return (((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | (uint32_t)d);
589 }
590
591 ////////////////////////////////////////////////////////////////////////////////
592
593 /** 32 bit integer to hold a unicode value
594 */
595 typedef int32_t SkUnichar;
596
597 /** 16 bit unsigned integer to hold a glyph index
598 */
599 typedef uint16_t SkGlyphID;
600
601 /** 32 bit value to hold a millisecond duration
602 Note that SK_MSecMax is about 25 days.
603 */
604 typedef uint32_t SkMSec;
605
606 /** Maximum representable milliseconds; 24d 20h 31m 23.647s.
607 */
608 static constexpr SkMSec SK_MSecMax = INT32_MAX;
609
610 /** The generation IDs in Skia reserve 0 has an invalid marker.
611 */
612 static constexpr uint32_t SK_InvalidGenID = 0;
613
614 /** The unique IDs in Skia reserve 0 has an invalid marker.
615 */
616 static constexpr uint32_t SK_InvalidUniqueID = 0;
617
SkAbs32(int32_t value)618 static inline int32_t SkAbs32(int32_t value) {
619 SkASSERT(value != SK_NaN32); // The most negative int32_t can't be negated.
620 if (value < 0) {
621 value = -value;
622 }
623 return value;
624 }
625
SkTAbs(T value)626 template <typename T> static inline T SkTAbs(T value) {
627 if (value < 0) {
628 value = -value;
629 }
630 return value;
631 }
632
633 ////////////////////////////////////////////////////////////////////////////////
634
635 /** Indicates whether an allocation should count against a cache budget.
636 */
637 enum class SkBudgeted : bool {
638 kNo = false,
639 kYes = true
640 };
641
642 /** Indicates whether a backing store needs to be an exact match or can be
643 larger than is strictly necessary
644 */
645 enum class SkBackingFit {
646 kApprox,
647 kExact
648 };
649
650 #endif
651