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 #define SK_BUILD_FOR_ANDROID
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 #define SK_BUILD_FOR_UNIX
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// When targetting iOS and using gyp to generate the build files, it is not
103// possible to select files to build depending on the architecture (i.e. it
104// is not possible to use hand optimized assembly implementation). In that
105// configuration SK_BUILD_NO_OPTS is defined. Remove optimisation then.
106#ifdef SK_BUILD_NO_OPTS
107 #define SK_CPU_SSE_LEVEL 0
108#endif
109
110// Are we in GCC/Clang?
111#ifndef SK_CPU_SSE_LEVEL
112 // These checks must be done in descending order to ensure we set the highest
113 // available SSE level.
114 #if defined(__AVX512F__) && defined(__AVX512DQ__) && defined(__AVX512CD__) && \
115 defined(__AVX512BW__) && defined(__AVX512VL__)
116 #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SKX
117 #elif defined(__AVX2__)
118 #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_AVX2
119 #elif defined(__AVX__)
120 #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_AVX
121 #elif defined(__SSE4_2__)
122 #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE42
123 #elif defined(__SSE4_1__)
124 #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE41
125 #elif defined(__SSSE3__)
126 #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSSE3
127 #elif defined(__SSE3__)
128 #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE3
129 #elif defined(__SSE2__)
130 #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE2
131 #endif
132#endif
133
134// Are we in VisualStudio?
135#ifndef SK_CPU_SSE_LEVEL
136 // These checks must be done in descending order to ensure we set the highest
137 // available SSE level. 64-bit intel guarantees at least SSE2 support.
138 #if defined(__AVX512F__) && defined(__AVX512DQ__) && defined(__AVX512CD__) && \
139 defined(__AVX512BW__) && defined(__AVX512VL__)
140 #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SKX
141 #elif defined(__AVX2__)
142 #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_AVX2
143 #elif defined(__AVX__)
144 #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_AVX
145 #elif defined(_M_X64) || defined(_M_AMD64)
146 #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE2
147 #elif defined(_M_IX86_FP)
148 #if _M_IX86_FP >= 2
149 #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE2
150 #elif _M_IX86_FP == 1
151 #define SK_CPU_SSE_LEVEL SK_CPU_SSE_LEVEL_SSE1
152 #endif
153 #endif
154#endif
155
156// ARM defines
157#if defined(__arm__) && (!defined(__APPLE__) || !TARGET_IPHONE_SIMULATOR)
158 #define SK_CPU_ARM32
159#elif defined(__aarch64__) && !defined(SK_BUILD_NO_OPTS)
160 #define SK_CPU_ARM64
161#endif
162
163// All 64-bit ARM chips have NEON. Many 32-bit ARM chips do too.
164#if !defined(SK_ARM_HAS_NEON) && !defined(SK_BUILD_NO_OPTS) && defined(__ARM_NEON)
165 #define SK_ARM_HAS_NEON
166#endif
167
168// Really this __APPLE__ check shouldn't be necessary, but it seems that Apple's Clang defines
169// __ARM_FEATURE_CRC32 for -arch arm64, even though their chips don't support those instructions!
170#if defined(__ARM_FEATURE_CRC32) && !defined(__APPLE__)
171 #define SK_ARM_HAS_CRC32
172#endif
173
174
175// DLL/.so exports.
176#if !defined(SKIA_IMPLEMENTATION)
177 #define SKIA_IMPLEMENTATION 0
178#endif
179#if !defined(SK_API)
180 #if defined(SKIA_DLL)
181 #if defined(_MSC_VER)
182 #if SKIA_IMPLEMENTATION
183 #define SK_API __declspec(dllexport)
184 #else
185 #define SK_API __declspec(dllimport)
186 #endif
187 #else
188 #define SK_API __attribute__((visibility("default")))
189 #endif
190 #else
191 #define SK_API
192 #endif
193#endif
194
195// SK_SPI is functionally identical to SK_API, but used within src to clarify that it's less stable
196#if !defined(SK_SPI)
197 #define SK_SPI SK_API
198#endif
199
200// IWYU pragma: begin_exports
201#if defined (SK_USER_CONFIG_HEADER)
202 #include SK_USER_CONFIG_HEADER
203#else
204 #include "include/config/SkUserConfig.h"
205#endif
206#include <stddef.h>
207#include <stdint.h>
208// IWYU pragma: end_exports
209
210// Post SkUserConfig.h checks and such.
211#if !defined(SK_DEBUG) && !defined(SK_RELEASE)
212 #ifdef NDEBUG
213 #define SK_RELEASE
214 #else
215 #define SK_DEBUG
216 #endif
217#endif
218
219#if defined(SK_DEBUG) && defined(SK_RELEASE)
220# error "cannot define both SK_DEBUG and SK_RELEASE"
221#elif !defined(SK_DEBUG) && !defined(SK_RELEASE)
222# error "must define either SK_DEBUG or SK_RELEASE"
223#endif
224
225#if defined(SK_CPU_LENDIAN) && defined(SK_CPU_BENDIAN)
226# error "cannot define both SK_CPU_LENDIAN and SK_CPU_BENDIAN"
227#elif !defined(SK_CPU_LENDIAN) && !defined(SK_CPU_BENDIAN)
228# error "must define either SK_CPU_LENDIAN or SK_CPU_BENDIAN"
229#endif
230
231#if defined(SK_CPU_BENDIAN) && !defined(I_ACKNOWLEDGE_SKIA_DOES_NOT_SUPPORT_BIG_ENDIAN)
232 #error "The Skia team is not endian-savvy enough to support big-endian CPUs."
233 #error "If you still want to use Skia,"
234 #error "please define I_ACKNOWLEDGE_SKIA_DOES_NOT_SUPPORT_BIG_ENDIAN."
235#endif
236
237#if !defined(SK_ATTRIBUTE)
238# if defined(__clang__) || defined(__GNUC__)
239# define SK_ATTRIBUTE(attr) __attribute__((attr))
240# else
241# define SK_ATTRIBUTE(attr)
242# endif
243#endif
244
245#if !defined(SK_SUPPORT_GPU)
246# define SK_SUPPORT_GPU 1
247#endif
248
249#if !SK_SUPPORT_GPU
250# undef SK_GL
251# undef SK_VULKAN
252# undef SK_METAL
253# undef SK_DAWN
254# undef SK_DIRECT3D
255#endif
256
257#if !defined(SkUNREACHABLE)
258# if defined(_MSC_VER) && !defined(__clang__)
259# include <intrin.h>
260# define FAST_FAIL_INVALID_ARG 5
261// See https://developercommunity.visualstudio.com/content/problem/1128631/code-flow-doesnt-see-noreturn-with-extern-c.html
262// for why this is wrapped. Hopefully removable after msvc++ 19.27 is no longer supported.
263[[noreturn]] static inline void sk_fast_fail() { __fastfail(FAST_FAIL_INVALID_ARG); }
264# define SkUNREACHABLE sk_fast_fail()
265# else
266# define SkUNREACHABLE __builtin_trap()
267# endif
268#endif
269
270#if defined(SK_BUILD_FOR_GOOGLE3)
271 void SkDebugfForDumpStackTrace(const char* data, void* unused);
272 void DumpStackTrace(int skip_count, void w(const char*, void*), void* arg);
273# define SK_DUMP_GOOGLE3_STACK() DumpStackTrace(0, SkDebugfForDumpStackTrace, nullptr)
274#else
275# define SK_DUMP_GOOGLE3_STACK()
276#endif
277
278#ifndef SK_ABORT
279# ifdef SK_BUILD_FOR_WIN
280 // This style lets Visual Studio follow errors back to the source file.
281# define SK_DUMP_LINE_FORMAT "%s(%d)"
282# else
283# define SK_DUMP_LINE_FORMAT "%s:%d"
284# endif
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
294// If SK_R32_SHIFT is set, we'll use that to choose RGBA or BGRA.
295// If not, we'll default to RGBA everywhere except BGRA on Windows.
296#if defined(SK_R32_SHIFT)
297 static_assert(SK_R32_SHIFT == 0 || SK_R32_SHIFT == 16, "");
298#elif defined(SK_BUILD_FOR_WIN)
299 #define SK_R32_SHIFT 16
300#else
301 #define SK_R32_SHIFT 0
302#endif
303
304#if defined(SK_B32_SHIFT)
305 static_assert(SK_B32_SHIFT == (16-SK_R32_SHIFT), "");
306#else
307 #define SK_B32_SHIFT (16-SK_R32_SHIFT)
308#endif
309
310#define SK_G32_SHIFT 8
311#define SK_A32_SHIFT 24
312
313
314/**
315 * SK_PMCOLOR_BYTE_ORDER can be used to query the byte order of SkPMColor at compile time.
316 */
317#ifdef SK_CPU_BENDIAN
318# define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3) \
319 (SK_ ## C3 ## 32_SHIFT == 0 && \
320 SK_ ## C2 ## 32_SHIFT == 8 && \
321 SK_ ## C1 ## 32_SHIFT == 16 && \
322 SK_ ## C0 ## 32_SHIFT == 24)
323#else
324# define SK_PMCOLOR_BYTE_ORDER(C0, C1, C2, C3) \
325 (SK_ ## C0 ## 32_SHIFT == 0 && \
326 SK_ ## C1 ## 32_SHIFT == 8 && \
327 SK_ ## C2 ## 32_SHIFT == 16 && \
328 SK_ ## C3 ## 32_SHIFT == 24)
329#endif
330
331#if defined SK_DEBUG && defined SK_BUILD_FOR_WIN
332 #ifdef free
333 #undef free
334 #endif
335 #include <crtdbg.h>
336 #undef free
337#endif
338
339#if !defined(SK_UNUSED)
340# if !defined(__clang__) && defined(_MSC_VER)
341# define SK_UNUSED __pragma(warning(suppress:4189))
342# else
343# define SK_UNUSED SK_ATTRIBUTE(unused)
344# endif
345#endif
346
347/**
348 * If your judgment is better than the compiler's (i.e. you've profiled it),
349 * you can use SK_ALWAYS_INLINE to force inlining. E.g.
350 * inline void someMethod() { ... } // may not be inlined
351 * SK_ALWAYS_INLINE void someMethod() { ... } // should always be inlined
352 */
353#if !defined(SK_ALWAYS_INLINE)
354# if defined(SK_BUILD_FOR_WIN)
355# define SK_ALWAYS_INLINE __forceinline
356# else
357# define SK_ALWAYS_INLINE SK_ATTRIBUTE(always_inline) inline
358# endif
359#endif
360
361/**
362 * If your judgment is better than the compiler's (i.e. you've profiled it),
363 * you can use SK_NEVER_INLINE to prevent inlining.
364 */
365#if !defined(SK_NEVER_INLINE)
366# if defined(SK_BUILD_FOR_WIN)
367# define SK_NEVER_INLINE __declspec(noinline)
368# else
369# define SK_NEVER_INLINE SK_ATTRIBUTE(noinline)
370# endif
371#endif
372
373#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE1
374 #define SK_PREFETCH(ptr) _mm_prefetch(reinterpret_cast<const char*>(ptr), _MM_HINT_T0)
375#elif defined(__GNUC__)
376 #define SK_PREFETCH(ptr) __builtin_prefetch(ptr)
377#else
378 #define SK_PREFETCH(ptr)
379#endif
380
381#ifndef SK_PRINTF_LIKE
382# if defined(__clang__) || defined(__GNUC__)
383# define SK_PRINTF_LIKE(A, B) __attribute__((format(printf, (A), (B))))
384# else
385# define SK_PRINTF_LIKE(A, B)
386# endif
387#endif
388
389#ifndef SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
390 #define SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 0
391#endif
392
393#if !defined(SK_GAMMA_EXPONENT)
394 #define SK_GAMMA_EXPONENT (0.0f) // SRGB
395#endif
396
397#ifndef GR_TEST_UTILS
398# define GR_TEST_UTILS 0
399#endif
400
401#if defined(SK_HISTOGRAM_ENUMERATION) && defined(SK_HISTOGRAM_BOOLEAN)
402# define SK_HISTOGRAMS_ENABLED 1
403#else
404# define SK_HISTOGRAMS_ENABLED 0
405#endif
406
407#ifndef SK_HISTOGRAM_BOOLEAN
408# define SK_HISTOGRAM_BOOLEAN(name, value)
409#endif
410
411#ifndef SK_HISTOGRAM_ENUMERATION
412# define SK_HISTOGRAM_ENUMERATION(name, value, boundary_value)
413#endif
414
415#ifndef SK_DISABLE_LEGACY_SHADERCONTEXT
416#define SK_ENABLE_LEGACY_SHADERCONTEXT
417#endif
418
419#ifdef SK_ENABLE_API_AVAILABLE
420#define SK_API_AVAILABLE API_AVAILABLE
421#else
422#define SK_API_AVAILABLE(...)
423#endif
424
425/** Called internally if we hit an unrecoverable error.
426 The platform implementation must not return, but should either throw
427 an exception or otherwise exit.
428*/
429[[noreturn]] SK_API extern void sk_abort_no_print(void);
430
431#ifndef SkDebugf
432 SK_API void SkDebugf(const char format[], ...);
433#endif
434
435// SkASSERT, SkASSERTF and SkASSERT_RELEASE can be used as stand alone assertion expressions, e.g.
436// uint32_t foo(int x) {
437// SkASSERT(x > 4);
438// return x - 4;
439// }
440// and are also written to be compatible with constexpr functions:
441// constexpr uint32_t foo(int x) {
442// return SkASSERT(x > 4),
443// x - 4;
444// }
445#define SkASSERT_RELEASE(cond) \
446 static_cast<void>( (cond) ? (void)0 : []{ SK_ABORT("assert(%s)", #cond); }() )
447
448#ifdef SK_DEBUG
449 #define SkASSERT(cond) SkASSERT_RELEASE(cond)
450 #define SkASSERTF(cond, fmt, ...) static_cast<void>( (cond) ? (void)0 : [&]{ \
451 SkDebugf(fmt"\n", __VA_ARGS__); \
452 SK_ABORT("assert(%s)", #cond); \
453 }() )
454 #define SkDEBUGFAIL(message) SK_ABORT("%s", message)
455 #define SkDEBUGFAILF(fmt, ...) SK_ABORT(fmt, ##__VA_ARGS__)
456 #define SkDEBUGCODE(...) __VA_ARGS__
457 #define SkDEBUGF(...) SkDebugf(__VA_ARGS__)
458 #define SkAssertResult(cond) SkASSERT(cond)
459#else
460 #define SkASSERT(cond) static_cast<void>(0)
461 #define SkASSERTF(cond, fmt, ...) static_cast<void>(0)
462 #define SkDEBUGFAIL(message)
463 #define SkDEBUGFAILF(fmt, ...)
464 #define SkDEBUGCODE(...)
465 #define SkDEBUGF(...)
466
467 // unlike SkASSERT, this macro executes its condition in the non-debug build.
468 // The if is present so that this can be used with functions marked SK_WARN_UNUSED_RESULT.
469 #define SkAssertResult(cond) if (cond) {} do {} while(false)
470#endif
471
472////////////////////////////////////////////////////////////////////////////////
473
474/** Fast type for unsigned 8 bits. Use for parameter passing and local
475 variables, not for storage
476*/
477typedef unsigned U8CPU;
478
479/** Fast type for unsigned 16 bits. Use for parameter passing and local
480 variables, not for storage
481*/
482typedef unsigned U16CPU;
483
484/** @return false or true based on the condition
485*/
486template <typename T> static constexpr bool SkToBool(const T& x) {
487 return 0 != x; // NOLINT(modernize-use-nullptr)
488}
489
490static constexpr int16_t SK_MaxS16 = INT16_MAX;
491static constexpr int16_t SK_MinS16 = -SK_MaxS16;
492
493static constexpr int32_t SK_MaxS32 = INT32_MAX;
494static constexpr int32_t SK_MinS32 = -SK_MaxS32;
495static constexpr int32_t SK_NaN32 = INT32_MIN;
496
497static constexpr int64_t SK_MaxS64 = INT64_MAX;
498static constexpr int64_t SK_MinS64 = -SK_MaxS64;
499
500static inline constexpr int32_t SkLeftShift(int32_t value, int32_t shift) {
501 return (int32_t) ((uint32_t) value << shift);
502}
503
504static inline constexpr int64_t SkLeftShift(int64_t value, int32_t shift) {
505 return (int64_t) ((uint64_t) value << shift);
506}
507
508////////////////////////////////////////////////////////////////////////////////
509
510/** @return the number of entries in an array (not a pointer)
511*/
512template <typename T, size_t N> char (&SkArrayCountHelper(T (&array)[N]))[N];
513#define SK_ARRAY_COUNT(array) (sizeof(SkArrayCountHelper(array)))
514
515////////////////////////////////////////////////////////////////////////////////
516
517template <typename T> static constexpr T SkAlign2(T x) { return (x + 1) >> 1 << 1; }
518template <typename T> static constexpr T SkAlign4(T x) { return (x + 3) >> 2 << 2; }
519template <typename T> static constexpr T SkAlign8(T x) { return (x + 7) >> 3 << 3; }
520
521template <typename T> static constexpr bool SkIsAlign2(T x) { return 0 == (x & 1); }
522template <typename T> static constexpr bool SkIsAlign4(T x) { return 0 == (x & 3); }
523template <typename T> static constexpr bool SkIsAlign8(T x) { return 0 == (x & 7); }
524
525template <typename T> static constexpr T SkAlignPtr(T x) {
526 return sizeof(void*) == 8 ? SkAlign8(x) : SkAlign4(x);
527}
528template <typename T> static constexpr bool SkIsAlignPtr(T x) {
529 return sizeof(void*) == 8 ? SkIsAlign8(x) : SkIsAlign4(x);
530}
531
532typedef uint32_t SkFourByteTag;
533static inline constexpr SkFourByteTag SkSetFourByteTag(char a, char b, char c, char d) {
534 return (((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8) | (uint32_t)d);
535}
536
537////////////////////////////////////////////////////////////////////////////////
538
539/** 32 bit integer to hold a unicode value
540*/
541typedef int32_t SkUnichar;
542
543/** 16 bit unsigned integer to hold a glyph index
544*/
545typedef uint16_t SkGlyphID;
546
547/** 32 bit value to hold a millisecond duration
548 Note that SK_MSecMax is about 25 days.
549*/
550typedef uint32_t SkMSec;
551
552/** Maximum representable milliseconds; 24d 20h 31m 23.647s.
553*/
554static constexpr SkMSec SK_MSecMax = INT32_MAX;
555
556/** The generation IDs in Skia reserve 0 has an invalid marker.
557*/
558static constexpr uint32_t SK_InvalidGenID = 0;
559
560/** The unique IDs in Skia reserve 0 has an invalid marker.
561*/
562static constexpr uint32_t SK_InvalidUniqueID = 0;
563
564static inline int32_t SkAbs32(int32_t value) {
565 SkASSERT(value != SK_NaN32); // The most negative int32_t can't be negated.
566 if (value < 0) {
567 value = -value;
568 }
569 return value;
570}
571
572template <typename T> static inline T SkTAbs(T value) {
573 if (value < 0) {
574 value = -value;
575 }
576 return value;
577}
578
579/** @return value pinned (clamped) between min and max, inclusively.
580
581 NOTE: Unlike std::clamp, SkTPin has well-defined behavior if 'value' is a
582 floating point NaN. In that case, 'max' is returned.
583*/
584template <typename T> static constexpr const T& SkTPin(const T& value, const T& min, const T& max) {
585 return value < min ? min : (value < max ? value : max);
586}
587
588////////////////////////////////////////////////////////////////////////////////
589
590/** Indicates whether an allocation should count against a cache budget.
591*/
592enum class SkBudgeted : bool {
593 kNo = false,
594 kYes = true
595};
596
597/** Indicates whether a backing store needs to be an exact match or can be
598 larger than is strictly necessary
599*/
600enum class SkBackingFit {
601 kApprox,
602 kExact
603};
604
605#endif
606