xref: /aosp_15_r20/external/skia/src/core/SkRasterPipelineContextUtils.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2023 Google Inc.
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 SkRasterPipelineContextUtils_DEFINED
9 #define SkRasterPipelineContextUtils_DEFINED
10 
11 #include "src/base/SkArenaAlloc.h"
12 #include "src/base/SkUtils.h"
13 
14 #include <cstring>
15 #include <type_traits>
16 
17 namespace SkRPCtxUtils {
18 
19 template <typename T>
20 using UnpackedType = typename std::conditional<sizeof(T) <= sizeof(void*), T, const T&>::type;
21 
22 /**
23  * SkRPCtxUtils::Pack will check if the passed-in struct is small enough to fit directly in the
24  * context field. If so, it will return the data bit-casted into a void pointer. If not, it
25  * allocates a copy of the struct inside the alloc and then returns a pointer to the copy.
26  */
27 template <typename T>
Pack(const T & ctx,SkArenaAlloc * alloc)28 [[maybe_unused]] static void* Pack(const T& ctx, SkArenaAlloc* alloc) {
29     // If the context is small enough to fit in a pointer, bit-cast it; if not, alloc a copy.
30     if constexpr (sizeof(T) <= sizeof(void*)) {
31         return sk_bit_cast<void*>(ctx);
32     } else {
33         return alloc->make<T>(ctx);
34     }
35 }
36 
37 /**
38  * SkRPCtxUtils::Unpack performs the reverse operation: either un-bitcasting the object back to its
39  * original form, or returning the pointer as-is, depending on the size of the type.
40  */
41 template <typename T>
Unpack(const T * ctx)42 [[maybe_unused]] static UnpackedType<T> Unpack(const T* ctx) {
43     // If the context struct fits in a pointer, reinterpret the bits; if it doesn't, return
44     // a reference. This can vary based on the architecture (32-bit pointers vs 64-bit) so we
45     // let the compiler decide which is right, rather than hard-coding it.
46     if constexpr (sizeof(T) <= sizeof(void*)) {
47         return sk_bit_cast<T>(ctx);
48     } else {
49         return *ctx;
50     }
51 }
52 
53 }  // namespace SkRPCtxUtils
54 
55 #endif  // SkRasterPipelineContextUtils_DEFINED
56