1 //
2 // Copyright (C) 2024 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #ifndef VULKAN_XML_H_
18 #define VULKAN_XML_H_
19 
20 #include <unistd.h>
21 
22 #include <cstdint>
23 
24 #include "berberis/base/bit_util.h"
25 #include "berberis/base/struct_check.h"
26 #include "berberis/guest_abi/function_wrappers.h"
27 #include "berberis/guest_abi/guest_arguments.h"
28 #include "berberis/guest_abi/guest_function_wrapper_signature.h"
29 #include "berberis/guest_abi/guest_params.h"
30 #include "berberis/guest_abi/guest_type.h"
31 #include "berberis/guest_state/guest_addr.h"
32 #include "berberis/guest_state/guest_state.h"
33 #include "berberis/runtime_primitives/guest_function_wrapper_impl.h"
34 #include "berberis/runtime_primitives/host_code.h"
35 #include "berberis/runtime_primitives/host_function_wrapper_impl.h"
36 #include "berberis/runtime_primitives/runtime_library.h"
37 
38 #include "binary_search.h"
39 // Note: we only need these defines at the end of xvulkan_xml-inl.h and would like to not include it
40 // prematurely but vulkan_xml_define.h couldn't be included from vulkan_xml-inl.h when these two
41 // files are in different filegroups.
42 #include "vulkan_xml_define.h"
43 
44 // These are explicitly written here as a workaround.  These are platform types that are missing
45 // from vulkan_types.  They are implicitly declared in the berberis namespace because the Vulkan
46 // structures that include them use the "struct X* y;" field syntax.  However, they belong in the
47 // global namespace to avoid conflicts in files that include the host headers for these types,
48 // which are included via vulkan/vulkan.h.
49 struct AHardwareBuffer;
50 struct ANativeWindow;
51 struct Display;
52 struct wl_display;
53 struct xcb_connection_t;
54 
55 namespace berberis {
56 
57 template <typename ResultType, typename... ArgumentType>
WrapGuestFunctionIfNeeded(GuestType<ResultType (*)(ArgumentType...)> func,const char * name)58 inline ResultType (*WrapGuestFunctionIfNeeded(GuestType<ResultType (*)(ArgumentType...)> func,
59                                               const char* name))(ArgumentType...) {
60   auto host_func =
61       reinterpret_cast<ResultType (*)(ArgumentType...)>(UnwrapHostFunction(ToGuestAddr(func)));
62   if (host_func) {
63     return host_func;
64   }
65   return WrapGuestFunction(func, name);
66 }
67 
68 template <GuestAbi::CallingConventionsVariant kCallingConventionsVariant = GuestAbi::kDefaultAbi,
69           typename Func>
WrapHostFunctionIfNeeded(Func func,const char * name)70 inline GuestType<Func> WrapHostFunctionIfNeeded(Func func, const char* name) {
71   auto host_func = UnwrapHostFunction(ToGuestAddr(func));
72   if (!host_func) {
73     WrapHostFunction(func, name);
74   }
75   return func;
76 }
77 
78 class GuestHolderBase {
79  public:
80   GuestHolderBase() = default;
81   virtual ~GuestHolderBase() = default;
82 };
83 
84 class HostHolderBase {
85  public:
86   HostHolderBase() = default;
87   virtual ~HostHolderBase() = default;
88 };
89 
90 // Note: anonymous namespace is subtly different from static: each anonymous namespace has internal
91 // unique name, but is imported into encompassing namespace.
92 //
93 // It's unclear whether it's valid to declare function in one such namespace and then define in the
94 // other one: MSVC says it's impossible, other compilers allow that.
95 //
96 // But even compilers which support such use are confused when friend delaration is used.
97 //
98 // Use of “static” works without any surprises: https://godbolt.org/z/sczb7r5Gn
99 static const void* ConvertOptionalStructures(GuestType<const void*> head,
100                                              std::unique_ptr<HostHolderBase>& holder,
101                                              bool& out_of_memory);
102 static void* ConvertOptionalStructures(GuestType<void*> head,
103                                        std::unique_ptr<HostHolderBase>& holder,
104                                        bool& out_of_memory);
105 static GuestType<const void*> ConvertOptionalStructures(const void* head,
106                                                         std::unique_ptr<GuestHolderBase>& holder,
107                                                         bool& out_of_memory);
108 static GuestType<void*> ConvertOptionalStructures(void* head,
109                                                   std::unique_ptr<GuestHolderBase>& holder,
110                                                   bool& out_of_memory);
111 
112 namespace {
113 
114 #define BERBERIS_VK_DEFINE_HANDLE(name) using name = struct name##_T*
115 
116 #if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__)) || \
117     defined(_M_X64) || defined(__ia64) || defined(_M_IA64) || defined(__aarch64__) ||       \
118     defined(__powerpc64__)
119 #define BERBERIS_VK_DEFINE_NON_DISPATCHABLE_HANDLE(name) \
120   BERBERIS_VK_DEFINE_HANDLE(name)
121 #else
122 #define BERBERIS_VK_DEFINE_NON_DISPATCHABLE_HANDLE(name) using name = std::uint64_t
123 #endif
124 
125 #if defined(_WIN32)
126     // On Windows, Vulkan commands use the stdcall convention
127     #define BERBERIS_VKAPI_PTR  __stdcall
128 #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH < 7
129     // 32bit Android ARMv6 or earlier don't support Vulkan by design.
130     #error "Vulkan isn't supported for the 'armeabi' NDK ABI"
131 #elif defined(__ANDROID__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7 && defined(__ARM_32BIT_STATE)
132     // 32bit Android ARMv7+ are using aapcs-vfp.
133     #define BERBERIS_VKAPI_PTR  __attribute__((pcs("aapcs-vfp")))
134 #else
135     // On other platforms, use the default calling convention
136     #define BERBERIS_VKAPI_PTR
137 #endif
138 
139 // API Constants.
140 // TODO(232598137): Parse them from XML instead.
141 constexpr uint32_t BERBERIS_VK_TRUE = 1;
142 constexpr uint32_t BERBERIS_VK_FALSE = 0;
143 
144 #include "vulkan_xml-inl.h"  // generated file NOLINT [build/include]
145 
146 #endif  // VULKAN_XML_H_
147