// This file is part of Blend2D project // // See blend2d.h or LICENSE.md for license and copyright information // SPDX-License-Identifier: Zlib #ifndef BLEND2D_RUNTIMESCOPE_H_INCLUDED #define BLEND2D_RUNTIMESCOPE_H_INCLUDED #include "api.h" //! \addtogroup blend2d_api_runtime //! \{ //! \name BLRuntimeScope - C API //! \{ //! Blend2D runtime scope [C API]. struct BLRuntimeScopeCore { uint32_t data[2]; }; BL_BEGIN_C_DECLS BL_API BLResult BL_CDECL blRuntimeScopeBegin(BLRuntimeScopeCore* self) BL_NOEXCEPT_C; BL_API BLResult BL_CDECL blRuntimeScopeEnd(BLRuntimeScopeCore* self) BL_NOEXCEPT_C; BL_API bool BL_CDECL blRuntimeScopeIsActive(const BLRuntimeScopeCore* self) BL_NOEXCEPT_C; BL_END_C_DECLS //! \} #if defined(__cplusplus) //! \name BLRuntimeScope - C++ API //! \{ //! Blend2D runtime scope [C++ API]. //! //! Runtime scope is a totally optional feature that can be used by Blend2D to setup the current thread's control //! word in a way to make the behavior of some floating point computations consistent between platforms. Blend2D //! doesn't rely on any specific behavior, however, for testing purposes and possibly consistency of rendering //! across different architectures some setup may be necessary. //! //! The runtime scope current only changes FPU control word in 32-bit x86 case to 64-bit precision. This means //! that if the FPU control word was set to 80-bits the precision of floating computations would be basically //! lowered, but this is necessary to make sure that intermediate computations match other platforms that don't //! have extended precision. Blend2D doesn't rely on extended precision in any way and this all is needed only //! if 100% consistency is required across different platforms. //! //! At the moment BLRuntimeScope is only used by tests to ensure that we can compare reference implementation //! written in C++ with SIMD optimized implementation written either in C++ or generated at runtime (JIT). //! //! As the name of the class suggests, `BLRuntimeScope` establishes a scope, so the FPU control word would only //! be changed temporarily within the life-time of the scope. //! //! Example: //! //! ``` //! void do_something(BLImage& image) noexcept { //! // Establishes a new scope by possibly changing the environment (FPU control word). //! BLRuntimeScope scope; //! //! BLContext ctx(image); //! // ... do something ... //! //! // The scope ends here - the environment is restored. //! } //! ``` class BLRuntimeScope final : public BLRuntimeScopeCore { BLRuntimeScope(BLRuntimeScope& other) noexcept = delete; BLRuntimeScope& operator=(BLRuntimeScope& other) noexcept = delete; public: //! \name Construction & Destruction //! \{ //! Establishes a new runtime scope by possibly changing the state of FPU control word. BL_INLINE_NODEBUG BLRuntimeScope() noexcept { blRuntimeScopeBegin(this); } //! Restores the scope to the previous state. BL_INLINE_NODEBUG ~BLRuntimeScope() noexcept { blRuntimeScopeEnd(this); } //! \} //! \name Accessors //! \{ BL_INLINE_NODEBUG bool isActive() const noexcept { return blRuntimeScopeIsActive(this); } //! \} }; //! \} #endif //! \} #endif // BLEND2D_RUNTIMESCOPE_H_INCLUDED