1// [Blend2D]
2// 2D Vector Graphics Powered by a JIT Compiler.
3//
4// [License]
5// Zlib - See LICENSE.md file in the package.
6
7#ifndef BLEND2D_BLRUNTIME_P_H
8#define BLEND2D_BLRUNTIME_P_H
9
10#include "./blapi-internal_p.h"
11#include "./blruntime.h"
12
13//! \cond INTERNAL
14//! \addtogroup blend2d_internal
15//! \{
16
17// ============================================================================
18// [BLRuntime - FixedFuncArray]
19// ============================================================================
20
21//! Fixed array used by handlers, initial content should be zero initialized
22//! by the linker as it's used only in a statically allocated `BLRuntimeContext`.
23template<typename Func, size_t N>
24struct BLFixedFuncArray {
25 size_t size;
26 Func data[N];
27
28 BL_INLINE void reset() noexcept { size = 0; }
29
30 BL_INLINE void add(Func func) noexcept {
31 BL_ASSERT(size < N);
32 data[size++] = func;
33 }
34
35 template<typename... Args>
36 BL_INLINE void call(Args&&... args) noexcept {
37 for (size_t i = 0; i < size; i++)
38 data[i](std::forward<Args>(args)...);
39 }
40
41 template<typename... Args>
42 BL_INLINE void callInReverseOrder(Args&&... args) noexcept {
43 size_t i = size;
44 while (i)
45 data[--i](std::forward<Args>(args)...);
46 }
47};
48
49// ============================================================================
50// [BLRuntime - Context]
51// ============================================================================
52
53//! Blend2D runtime context.
54//!
55//! A singleton that is created at Blend2D startup and that can be used to query
56//! various information about the library and its runtime.
57struct BLRuntimeContext {
58 //! Shutdown handler.
59 typedef void (BL_CDECL* ShutdownFunc)(BLRuntimeContext* rt) BL_NOEXCEPT;
60 //! Cleanup handler.
61 typedef void (BL_CDECL* CleanupFunc)(BLRuntimeContext* rt, uint32_t cleanupFlags) BL_NOEXCEPT;
62 //! MemoryInfo handler.
63 typedef void (BL_CDECL* MemoryInfoFunc)(BLRuntimeContext* rt, BLRuntimeMemoryInfo* memoryInfo) BL_NOEXCEPT;
64
65 //! Counts how many times `blRuntimeInit()` has been called.
66 //!
67 //! Returns the current initialization count, which is incremented every
68 //! time a `blRuntimeInit()` is called and decremented every time a
69 //! `blRuntimeShutdown()` is called.
70 //!
71 //! When this counter is incremented from 0 to 1 the library is initialized,
72 //! when it's decremented to zero it will free all resources and it will no
73 //! longer be safe to use.
74 volatile size_t refCount;
75
76 //! System information.
77 BLRuntimeSystemInfo systemInfo;
78
79 // NOTE: There is only a limited number of handlers that can be added to the
80 // context. The reason we do it this way is that for builds of Blend2D that
81 // have conditionally disabled some features it's easier to have only `RtInit()`
82 // handlers and let them register cleanup/shutdown handlers when needed.
83
84 //! Shutdown handlers (always traversed from last to first).
85 BLFixedFuncArray<ShutdownFunc, 8> shutdownHandlers;
86 //! Cleanup handlers (always executed from first to last).
87 BLFixedFuncArray<CleanupFunc, 8> cleanupHandlers;
88 //! MemoryInfo handlers (always traversed from first to last).
89 BLFixedFuncArray<MemoryInfoFunc, 8> memoryInfoHandlers;
90};
91
92//! Instance of a global runtime context.
93BL_HIDDEN extern BLRuntimeContext blRuntimeContext;
94
95// ============================================================================
96// [BLRuntime - Cpu Features]
97// ============================================================================
98
99// NOTE: Must be in anonymous namespace. When the compilation unit uses certain
100// optimizations we constexpr the check and return `true` without checking CPU
101// features as the compilation unit uses them anyway [at that point].
102BL_DIAGNOSTIC_PUSH(BL_DIAGNOSTIC_NO_UNUSED_PARAMETERS)
103
104namespace {
105
106#ifdef BL_TARGET_OPT_SSE2
107constexpr bool blRuntimeHasSSE2(BLRuntimeContext* rt) noexcept { return true; }
108#else
109inline bool blRuntimeHasSSE2(BLRuntimeContext* rt) noexcept { return (rt->systemInfo.cpuFeatures & BL_RUNTIME_CPU_FEATURE_X86_SSE2) != 0; }
110#endif
111
112#ifdef BL_TARGET_OPT_SSE3
113constexpr bool blRuntimeHasSSE3(BLRuntimeContext* rt) noexcept { return true; }
114#else
115inline bool blRuntimeHasSSE3(BLRuntimeContext* rt) noexcept { return (rt->systemInfo.cpuFeatures & BL_RUNTIME_CPU_FEATURE_X86_SSE3) != 0; }
116#endif
117
118#ifdef BL_TARGET_OPT_SSSE3
119constexpr bool blRuntimeHasSSSE3(BLRuntimeContext* rt) noexcept { return true; }
120#else
121inline bool blRuntimeHasSSSE3(BLRuntimeContext* rt) noexcept { return (rt->systemInfo.cpuFeatures & BL_RUNTIME_CPU_FEATURE_X86_SSSE3) != 0; }
122#endif
123
124#ifdef BL_TARGET_OPT_SSE4_1
125constexpr bool blRuntimeHasSSE4_1(BLRuntimeContext* rt) noexcept { return true; }
126#else
127inline bool blRuntimeHasSSE4_1(BLRuntimeContext* rt) noexcept { return (rt->systemInfo.cpuFeatures & BL_RUNTIME_CPU_FEATURE_X86_SSE4_1) != 0; }
128#endif
129
130#ifdef BL_TARGET_OPT_SSE4_2
131constexpr bool blRuntimeHasSSE4_2(BLRuntimeContext* rt) noexcept { return true; }
132#else
133inline bool blRuntimeHasSSE4_2(BLRuntimeContext* rt) noexcept { return (rt->systemInfo.cpuFeatures & BL_RUNTIME_CPU_FEATURE_X86_SSE4_2) != 0; }
134#endif
135
136#ifdef BL_TARGET_OPT_AVX
137constexpr bool blRuntimeHasAVX(BLRuntimeContext* rt) noexcept { return true; }
138#else
139inline bool blRuntimeHasAVX(BLRuntimeContext* rt) noexcept { return (rt->systemInfo.cpuFeatures & BL_RUNTIME_CPU_FEATURE_X86_AVX) != 0; }
140#endif
141
142#ifdef BL_TARGET_OPT_AVX2
143constexpr bool blRuntimeHasAVX2(BLRuntimeContext* rt) noexcept { return true; }
144#else
145inline bool blRuntimeHasAVX2(BLRuntimeContext* rt) noexcept { return (rt->systemInfo.cpuFeatures & BL_RUNTIME_CPU_FEATURE_X86_AVX2) != 0; }
146#endif
147
148} // {anonymous}
149
150BL_DIAGNOSTIC_POP
151
152// ============================================================================
153// [BLRuntime - Impl]
154// ============================================================================
155
156BL_HIDDEN void BL_CDECL blRuntimeDummyDestroyImplFunc(void* impl, void* destroyData) noexcept;
157
158// ============================================================================
159// [BLRuntime - Utilities]
160// ============================================================================
161
162BL_HIDDEN BL_NORETURN void blRuntimeFailure(const char* fmt, ...) noexcept;
163
164// ============================================================================
165// [BLRuntime - Runtime Init]
166// ============================================================================
167
168BL_HIDDEN void blThreadingRtInit(BLRuntimeContext* rt) noexcept;
169BL_HIDDEN void blThreadPoolRtInit(BLRuntimeContext* rt) noexcept;
170BL_HIDDEN void blZeroAllocatorRtInit(BLRuntimeContext* rt) noexcept;
171BL_HIDDEN void blMatrix2DRtInit(BLRuntimeContext* rt) noexcept;
172BL_HIDDEN void blArrayRtInit(BLRuntimeContext* rt) noexcept;
173BL_HIDDEN void blStringRtInit(BLRuntimeContext* rt) noexcept;
174BL_HIDDEN void blPathRtInit(BLRuntimeContext* rt) noexcept;
175BL_HIDDEN void blRegionRtInit(BLRuntimeContext* rt) noexcept;
176BL_HIDDEN void blImageRtInit(BLRuntimeContext* rt) noexcept;
177BL_HIDDEN void blImageScalerRtInit(BLRuntimeContext* rt) noexcept;
178BL_HIDDEN void blPatternRtInit(BLRuntimeContext* rt) noexcept;
179BL_HIDDEN void blGradientRtInit(BLRuntimeContext* rt) noexcept;
180BL_HIDDEN void blFontRtInit(BLRuntimeContext* rt) noexcept;
181BL_HIDDEN void blContextRtInit(BLRuntimeContext* rt) noexcept;
182
183#if !defined(BL_BUILD_NO_FIXED_PIPE)
184BL_HIDDEN void blFixedPipeRtInit(BLRuntimeContext* rt) noexcept;
185#endif
186
187#if !defined(BL_BUILD_NO_JIT)
188BL_HIDDEN void blPipeGenRtInit(BLRuntimeContext* rt) noexcept;
189#endif
190
191//! \}
192//! \endcond
193
194#endif // BLEND2D_BLRUNTIME_P_H
195