1 /*
2 * Copyright (C) 2023 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 #include <dlfcn.h>
18 
19 #include "OMXAL/OpenMAXAL.h"
20 #include "OMXAL/OpenMAXAL_Android.h"
21 
22 #include "berberis/base/struct_check.h"
23 #include "berberis/guest_abi/function_wrappers.h"
24 #include "berberis/guest_abi/guest_params.h"
25 #include "berberis/guest_state/guest_addr.h"
26 #include "berberis/proxy_loader/proxy_library_builder.h"
27 
28 namespace berberis {
29 
30 namespace {
31 
32 // TODO(b/312279687): Maybe share this with SLES translation.
33 #define REGISTER_TRAMPOLINE(itf_name, func_name) \
34   WrapHostFunction((*itf)->func_name, #itf_name "::" #func_name)
35 
36 #define REGISTER_CUSTOM_TRAMPOLINE(itf_name, func_name)             \
37   WrapHostFunctionImpl(reinterpret_cast<void*>((*itf)->func_name),  \
38                        DoCustomTrampoline_##itf_name##_##func_name, \
39                        #itf_name "::" #func_name)
40 
41 // Interfaces are just structures listing function pointers, thus are layout-compatible.
42 typedef XAObjectItf Guest_XAObjectItf;
43 typedef XAEngineItf Guest_XAEngineItf;
44 typedef XAPlayItf Guest_XAPlayItf;
45 typedef XAAndroidBufferQueueItf Guest_XAAndroidBufferQueueItf;
46 typedef XAStreamInformationItf Guest_XAStreamInformationItf;
47 typedef XAVolumeItf Guest_XAVolumeItf;
48 
49 CHECK_STRUCT_LAYOUT(XAEngineOption, 64, 32);
50 CHECK_FIELD_LAYOUT(XAEngineOption, feature, 0, 32);
51 CHECK_FIELD_LAYOUT(XAEngineOption, data, 32, 32);
52 typedef XAEngineOption Guest_XAEngineOption;
53 
54 // Note, that this is not an integer, but is a pointer to structure!
55 typedef std::remove_reference_t<decltype(*std::declval<XAInterfaceID>())> XAInterfaceID_deref;
56 CHECK_STRUCT_LAYOUT(XAInterfaceID_deref, 128, 32);
57 CHECK_FIELD_LAYOUT(XAInterfaceID_deref, time_low, 0, 32);
58 CHECK_FIELD_LAYOUT(XAInterfaceID_deref, time_mid, 32, 16);
59 CHECK_FIELD_LAYOUT(XAInterfaceID_deref, time_hi_and_version, 48, 16);
60 CHECK_FIELD_LAYOUT(XAInterfaceID_deref, clock_seq, 64, 16);
61 CHECK_FIELD_LAYOUT(XAInterfaceID_deref, node, 80, 48);
62 typedef XAInterfaceID Guest_XAInterfaceID;
63 
64 #if defined(NATIVE_BRIDGE_GUEST_ARCH_ARM)
65 
66 CHECK_STRUCT_LAYOUT(XADataSource, 64, 32);
67 CHECK_FIELD_LAYOUT(XADataSource, pLocator, 0, 32);
68 CHECK_FIELD_LAYOUT(XADataSource, pFormat, 32, 32);
69 
70 CHECK_STRUCT_LAYOUT(XADataSink, 64, 32);
71 CHECK_FIELD_LAYOUT(XADataSink, pLocator, 0, 32);
72 CHECK_FIELD_LAYOUT(XADataSink, pFormat, 32, 32);
73 
74 #elif defined(NATIVE_BRIDGE_GUEST_ARCH_ARM64)
75 
76 CHECK_STRUCT_LAYOUT(XADataSource, 128, 64);
77 CHECK_FIELD_LAYOUT(XADataSource, pLocator, 0, 64);
78 CHECK_FIELD_LAYOUT(XADataSource, pFormat, 64, 64);
79 
80 CHECK_STRUCT_LAYOUT(XADataSink, 128, 64);
81 CHECK_FIELD_LAYOUT(XADataSink, pLocator, 0, 64);
82 CHECK_FIELD_LAYOUT(XADataSink, pFormat, 64, 64);
83 
84 #elif defined(NATIVE_BRIDGE_GUEST_ARCH_RISCV64)
85 
86 CHECK_STRUCT_LAYOUT(XADataSource, 128, 64);
87 CHECK_FIELD_LAYOUT(XADataSource, pLocator, 0, 64);
88 CHECK_FIELD_LAYOUT(XADataSource, pFormat, 64, 64);
89 
90 CHECK_STRUCT_LAYOUT(XADataSink, 128, 64);
91 CHECK_FIELD_LAYOUT(XADataSink, pLocator, 0, 64);
92 CHECK_FIELD_LAYOUT(XADataSink, pFormat, 64, 64);
93 
94 #else
95 
96 #error "Unknown guest arch"
97 
98 #endif
99 
100 CHECK_STRUCT_LAYOUT(XALEDDescriptor, 64, 32);
101 CHECK_FIELD_LAYOUT(XALEDDescriptor, ledCount, 0, 8);
102 CHECK_FIELD_LAYOUT(XALEDDescriptor, primaryLED, 8, 8);
103 CHECK_FIELD_LAYOUT(XALEDDescriptor, colorMask, 32, 32);
104 
105 CHECK_STRUCT_LAYOUT(XAVibraDescriptor, 128, 32);
106 CHECK_FIELD_LAYOUT(XAVibraDescriptor, supportsFrequency, 0, 32);
107 CHECK_FIELD_LAYOUT(XAVibraDescriptor, supportsIntensity, 32, 32);
108 CHECK_FIELD_LAYOUT(XAVibraDescriptor, minFrequency, 64, 32);
109 CHECK_FIELD_LAYOUT(XAVibraDescriptor, maxFrequency, 96, 32);
110 
RegisterXAEngineItfMethods(Guest_XAEngineItf itf)111 void RegisterXAEngineItfMethods(Guest_XAEngineItf itf) {
112   REGISTER_TRAMPOLINE(XAEngine, CreateOutputMix);
113   REGISTER_TRAMPOLINE(XAEngine, CreateMediaPlayer);
114   REGISTER_TRAMPOLINE(XAEngine, CreateMediaRecorder);
115   REGISTER_TRAMPOLINE(XAEngine, CreateCameraDevice);
116   REGISTER_TRAMPOLINE(XAEngine, CreateRadioDevice);
117   REGISTER_TRAMPOLINE(XAEngine, CreateLEDDevice);
118   REGISTER_TRAMPOLINE(XAEngine, CreateVibraDevice);
119   REGISTER_TRAMPOLINE(XAEngine, CreateMetadataExtractor);
120   REGISTER_TRAMPOLINE(XAEngine, CreateExtensionObject);
121   REGISTER_TRAMPOLINE(XAEngine, GetImplementationInfo);
122   REGISTER_TRAMPOLINE(XAEngine, QuerySupportedProfiles);
123   REGISTER_TRAMPOLINE(XAEngine, QueryNumSupportedInterfaces);
124   REGISTER_TRAMPOLINE(XAEngine, QuerySupportedInterfaces);
125   REGISTER_TRAMPOLINE(XAEngine, QueryNumSupportedExtensions);
126   REGISTER_TRAMPOLINE(XAEngine, QuerySupportedExtension);
127   REGISTER_TRAMPOLINE(XAEngine, IsExtensionSupported);
128   REGISTER_TRAMPOLINE(XAEngine, QueryLEDCapabilities);
129   REGISTER_TRAMPOLINE(XAEngine, QueryVibraCapabilities);
130 }
131 
132 // XAresult (*RegisterCallback) (XAPlayItf self, xaPlayCallback callback, void * pContext);
DoCustomTrampoline_XAPlay_RegisterCallback(HostCode,ProcessState * state)133 void DoCustomTrampoline_XAPlay_RegisterCallback(HostCode /*callee*/, ProcessState* state) {
134   using PFN_callee = decltype(std::declval<XAPlayItf_>().RegisterCallback);
135   auto [self, guest_callback, callback_context] = GuestParamsValues<PFN_callee>(state);
136 
137   // typedef void (XAAPIENTRY * xaPlayCallback) (XAPlayItf caller, void * pContext, XAuint32 event);
138   auto host_callback = WrapGuestFunction(guest_callback, "XAPlay_RegisterCallback-callback");
139 
140   auto&& [ret] = GuestReturnReference<PFN_callee>(state);
141   ret = (*self)->RegisterCallback(self, host_callback, callback_context);
142 }
143 
RegisterXAPlayItfMethods(Guest_XAPlayItf itf)144 void RegisterXAPlayItfMethods(Guest_XAPlayItf itf) {
145   REGISTER_TRAMPOLINE(XAPlay, SetPlayState);
146   REGISTER_TRAMPOLINE(XAPlay, GetPlayState);
147   REGISTER_TRAMPOLINE(XAPlay, GetDuration);
148   REGISTER_TRAMPOLINE(XAPlay, GetPosition);
149   REGISTER_TRAMPOLINE(XAPlay, SetMarkerPosition);
150   REGISTER_TRAMPOLINE(XAPlay, ClearMarkerPosition);
151   REGISTER_TRAMPOLINE(XAPlay, GetMarkerPosition);
152   REGISTER_TRAMPOLINE(XAPlay, SetPositionUpdatePeriod);
153   REGISTER_TRAMPOLINE(XAPlay, GetPositionUpdatePeriod);
154   REGISTER_TRAMPOLINE(XAPlay, SetCallbackEventsMask);
155   REGISTER_TRAMPOLINE(XAPlay, GetCallbackEventsMask);
156   REGISTER_CUSTOM_TRAMPOLINE(XAPlay, RegisterCallback);
157 }
158 
159 // XAresult (*RegisterCallback) (XAAndroidBufferQueueItf self);
160 //                               xaAndroidBufferQueueCallback callback,
161 //                               void* pCallbackContext);
DoCustomTrampoline_XABufferQueue_RegisterCallback(HostCode,ProcessState * state)162 void DoCustomTrampoline_XABufferQueue_RegisterCallback(HostCode /*callee*/, ProcessState* state) {
163   using PFN_callee = decltype(std::declval<XAAndroidBufferQueueItf_>().RegisterCallback);
164   auto [self, guest_callback, callback_context] = GuestParamsValues<PFN_callee>(state);
165 
166   // typedef XAresult (XAAPIENTRY *xaAndroidBufferQueueCallback)(
167   //   XAAndroidBufferQueueItf caller,/* input */
168   //   void *pCallbackContext,        /* input */
169   //   void *pBufferContext,          /* input */
170   //   void *pBufferData,             /* input */
171   //   XAuint32 dataSize,             /* input */
172   //   XAuint32 dataUsed,             /* input */
173   //   const XAAndroidBufferItem *pItems,/* input */
174   //   XAuint32 itemsLength           /* input */
175   // );
176   auto host_callback = WrapGuestFunction(guest_callback, "XABufferQueue_RegisterCallback-callback");
177 
178   auto&& [ret] = GuestReturnReference<PFN_callee>(state);
179   ret = (*self)->RegisterCallback(self, host_callback, callback_context);
180 }
181 
182 CHECK_STRUCT_LAYOUT(XAAndroidBufferQueueState, 64, 32);
183 CHECK_FIELD_LAYOUT(XAAndroidBufferQueueState, count, 0, 32);
184 CHECK_FIELD_LAYOUT(XAAndroidBufferQueueState, index, 32, 32);
185 
RegisterXAAndroidBufferQueueItfMethods(Guest_XAAndroidBufferQueueItf itf)186 void RegisterXAAndroidBufferQueueItfMethods(Guest_XAAndroidBufferQueueItf itf) {
187   REGISTER_CUSTOM_TRAMPOLINE(XABufferQueue, RegisterCallback);
188   REGISTER_TRAMPOLINE(XABufferQueue, SetCallbackEventsMask);
189   REGISTER_TRAMPOLINE(XABufferQueue, Enqueue);
190   REGISTER_TRAMPOLINE(XABufferQueue, Clear);
191   REGISTER_TRAMPOLINE(XABufferQueue, GetState);
192   REGISTER_TRAMPOLINE(XABufferQueue, GetCallbackEventsMask);
193 }
194 
195 // XAresult (*RegisterStreamChangeCallback) (XAStreamInformationItf self,
196 //                                           xaStreamEventChangeCallback callback,
197 //                                           void * pContext);
DoCustomTrampoline_XAStreamInformation_RegisterStreamChangeCallback(HostCode,ProcessState * state)198 void DoCustomTrampoline_XAStreamInformation_RegisterStreamChangeCallback(HostCode /*callee*/,
199                                                                          ProcessState* state) {
200   using PFN_callee = decltype(std::declval<XAStreamInformationItf_>().RegisterStreamChangeCallback);
201   auto [self, guest_callback, callback_context] = GuestParamsValues<PFN_callee>(state);
202 
203   // typedef void (XAAPIENTRY * xaStreamEventChangeCallback) (
204   //     XAStreamInformationItf caller, XAuint32 eventId,
205   //     XAuint32 streamIndex, void * pEventData, void * pContext);
206   auto host_callback = WrapGuestFunction(
207       guest_callback, "XAStreamInformation_RegisterStreamChangeCallback-callback");
208 
209   auto&& [ret] = GuestReturnReference<PFN_callee>(state);
210   ret = (*self)->RegisterStreamChangeCallback(self, host_callback, callback_context);
211 }
212 
213 CHECK_STRUCT_LAYOUT(XAMediaContainerInformation, 96, 32);
214 CHECK_FIELD_LAYOUT(XAMediaContainerInformation, containerType, 0, 32);
215 CHECK_FIELD_LAYOUT(XAMediaContainerInformation, mediaDuration, 32, 32);
216 CHECK_FIELD_LAYOUT(XAMediaContainerInformation, numStreams, 64, 32);
217 
RegisterXAStreamInformationItfMethods(Guest_XAStreamInformationItf itf)218 void RegisterXAStreamInformationItfMethods(Guest_XAStreamInformationItf itf) {
219   REGISTER_CUSTOM_TRAMPOLINE(XAStreamInformation, RegisterStreamChangeCallback);
220   REGISTER_TRAMPOLINE(XAStreamInformation, QueryMediaContainerInformation);
221   REGISTER_TRAMPOLINE(XAStreamInformation, QueryStreamType);
222   REGISTER_TRAMPOLINE(XAStreamInformation, QueryStreamInformation);
223   REGISTER_TRAMPOLINE(XAStreamInformation, QueryStreamName);
224   REGISTER_TRAMPOLINE(XAStreamInformation, QueryActiveStreams);
225   REGISTER_TRAMPOLINE(XAStreamInformation, SetActiveStream);
226 }
227 
RegisterXAVideoDecoderCapabilitiesItfMethods(XAVideoDecoderCapabilitiesItf itf)228 void RegisterXAVideoDecoderCapabilitiesItfMethods(XAVideoDecoderCapabilitiesItf itf) {
229   REGISTER_TRAMPOLINE(XAVideoDecoderCapabilities, GetVideoDecoders);
230   REGISTER_TRAMPOLINE(XAVideoDecoderCapabilities, GetVideoDecoderCapabilities);
231 }
232 
RegisterXAVolumeItfMethods(Guest_XAVolumeItf itf)233 void RegisterXAVolumeItfMethods(Guest_XAVolumeItf itf) {
234   REGISTER_TRAMPOLINE(XAVolume, SetVolumeLevel);
235   REGISTER_TRAMPOLINE(XAVolume, GetVolumeLevel);
236   REGISTER_TRAMPOLINE(XAVolume, GetMaxVolumeLevel);
237   REGISTER_TRAMPOLINE(XAVolume, SetMute);
238   REGISTER_TRAMPOLINE(XAVolume, GetMute);
239   REGISTER_TRAMPOLINE(XAVolume, EnableStereoPosition);
240   REGISTER_TRAMPOLINE(XAVolume, IsEnabledStereoPosition);
241   REGISTER_TRAMPOLINE(XAVolume, SetStereoPosition);
242   REGISTER_TRAMPOLINE(XAVolume, GetStereoPosition);
243 }
244 
245 //  XAresult (*GetInterface) (XAObjectItf self, const XAInterfaceID iid, void * pInterface);
DoCustomTrampoline_XAObject_GetInterface(HostCode,ProcessState * state)246 void DoCustomTrampoline_XAObject_GetInterface(HostCode /*callee*/, ProcessState* state) {
247   using PFN_callee = decltype(std::declval<XAObjectItf_>().GetInterface);
248   auto [self, iid, interface] = GuestParamsValues<PFN_callee>(state);
249 
250   auto&& [ret] = GuestReturnReference<PFN_callee>(state);
251   ret = (*self)->GetInterface(self, iid, interface);
252 
253   if (ret != XA_RESULT_SUCCESS) {
254     return;
255   }
256 
257   // Note, that iid is not an integer (see comment to Guest_XAInterfaceID).
258   if (iid == XA_IID_ANDROIDBUFFERQUEUESOURCE) {
259     RegisterXAAndroidBufferQueueItfMethods(*static_cast<Guest_XAAndroidBufferQueueItf*>(interface));
260   } else if (iid == XA_IID_AUDIODECODERCAPABILITIES) {
261     LOG_ALWAYS_FATAL("Unknown XA_IID_AUDIODECODERCAPABILITIES");
262   } else if (iid == XA_IID_AUDIOENCODER) {
263     LOG_ALWAYS_FATAL("Unknown XA_IID_AUDIOENCODER");
264   } else if (iid == XA_IID_AUDIOENCODERCAPABILITIES) {
265     LOG_ALWAYS_FATAL("Unknown XA_IID_AUDIOENCODERCAPABILITIES");
266   } else if (iid == XA_IID_AUDIOIODEVICECAPABILITIES) {
267     LOG_ALWAYS_FATAL("Unknown XA_IID_AUDIOIODEVICECAPABILITIES");
268   } else if (iid == XA_IID_CAMERA) {
269     LOG_ALWAYS_FATAL("Unknown XA_IID_CAMERA");
270   } else if (iid == XA_IID_CAMERACAPABILITIES) {
271     LOG_ALWAYS_FATAL("Unknown XA_IID_CAMERACAPABILITIES");
272   } else if (iid == XA_IID_CONFIGEXTENSION) {
273     LOG_ALWAYS_FATAL("Unknown XA_IID_CONFIGEXTENSION");
274   } else if (iid == XA_IID_DEVICEVOLUME) {
275     LOG_ALWAYS_FATAL("Unknown XA_IID_DEVICEVOLUME");
276   } else if (iid == XA_IID_DYNAMICINTERFACEMANAGEMENT) {
277     LOG_ALWAYS_FATAL("Unknown XA_IID_DYNAMICINTERFACEMANAGEMENT");
278   } else if (iid == XA_IID_DYNAMICSOURCE) {
279     LOG_ALWAYS_FATAL("Unknown XA_IID_DYNAMICSOURCE");
280   } else if (iid == XA_IID_ENGINE) {
281     RegisterXAEngineItfMethods(*static_cast<Guest_XAEngineItf*>(interface));
282   } else if (iid == XA_IID_EQUALIZER) {
283     LOG_ALWAYS_FATAL("Unknown XA_IID_EQUALIZER");
284   } else if (iid == XA_IID_IMAGECONTROLS) {
285     LOG_ALWAYS_FATAL("Unknown XA_IID_IMAGECONTROLS");
286   } else if (iid == XA_IID_IMAGEDECODERCAPABILITIES) {
287     LOG_ALWAYS_FATAL("Unknown XA_IID_IMAGEDECODERCAPABILITIES");
288   } else if (iid == XA_IID_IMAGEEFFECTS) {
289     LOG_ALWAYS_FATAL("Unknown XA_IID_IMAGEEFFECTS");
290   } else if (iid == XA_IID_IMAGEENCODER) {
291     LOG_ALWAYS_FATAL("Unknown XA_IID_IMAGEENCODER");
292   } else if (iid == XA_IID_IMAGEENCODERCAPABILITIES) {
293     LOG_ALWAYS_FATAL("Unknown XA_IID_IMAGEENCODERCAPABILITIES");
294   } else if (iid == XA_IID_LED) {
295     LOG_ALWAYS_FATAL("Unknown XA_IID_LED");
296   } else if (iid == XA_IID_METADATAEXTRACTION) {
297     LOG_ALWAYS_FATAL("Unknown XA_IID_METADATAEXTRACTION");
298   } else if (iid == XA_IID_METADATAINSERTION) {
299     LOG_ALWAYS_FATAL("Unknown XA_IID_METADATAINSERTION");
300   } else if (iid == XA_IID_METADATATRAVERSAL) {
301     LOG_ALWAYS_FATAL("Unknown XA_IID_METADATATRAVERSAL");
302   } else if (iid == XA_IID_NULL) {
303     LOG_ALWAYS_FATAL("Unknown XA_IID_NULL");
304   } else if (iid == XA_IID_OBJECT) {
305     LOG_ALWAYS_FATAL("Unknown XA_IID_OBJECT");
306   } else if (iid == XA_IID_OUTPUTMIX) {
307     LOG_ALWAYS_FATAL("Unknown XA_IID_OUTPUTMIX");
308   } else if (iid == XA_IID_PLAY) {
309     RegisterXAPlayItfMethods(*static_cast<Guest_XAPlayItf*>(interface));
310   } else if (iid == XA_IID_PLAYBACKRATE) {
311     LOG_ALWAYS_FATAL("Unknown XA_IID_PLAYBACKRATE");
312   } else if (iid == XA_IID_PREFETCHSTATUS) {
313     LOG_ALWAYS_FATAL("Unknown XA_IID_PREFETCHSTATUS");
314   } else if (iid == XA_IID_RADIO) {
315     LOG_ALWAYS_FATAL("Unknown XA_IID_RADIO");
316   } else if (iid == XA_IID_RDS) {
317     LOG_ALWAYS_FATAL("Unknown XA_IID_RDS");
318   } else if (iid == XA_IID_RECORD) {
319     LOG_ALWAYS_FATAL("Unknown XA_IID_RECORD");
320   } else if (iid == XA_IID_SEEK) {
321     LOG_ALWAYS_FATAL("Unknown XA_IID_SEEK");
322   } else if (iid == XA_IID_SNAPSHOT) {
323     LOG_ALWAYS_FATAL("Unknown XA_IID_SNAPSHOT");
324   } else if (iid == XA_IID_STREAMINFORMATION) {
325     RegisterXAStreamInformationItfMethods(*static_cast<Guest_XAStreamInformationItf*>(interface));
326   } else if (iid == XA_IID_THREADSYNC) {
327     LOG_ALWAYS_FATAL("Unknown XA_IID_THREADSYNC");
328   } else if (iid == XA_IID_VIBRA) {
329     LOG_ALWAYS_FATAL("Unknown XA_IID_VIBRA");
330   } else if (iid == XA_IID_VIDEODECODERCAPABILITIES) {
331     RegisterXAVideoDecoderCapabilitiesItfMethods(
332         *static_cast<XAVideoDecoderCapabilitiesItf*>(interface));
333   } else if (iid == XA_IID_VIDEOENCODER) {
334     LOG_ALWAYS_FATAL("Unknown XA_IID_VIDEOENCODER");
335   } else if (iid == XA_IID_VIDEOENCODERCAPABILITIES) {
336     LOG_ALWAYS_FATAL("Unknown XA_IID_VIDEOENCODERCAPABILITIES");
337   } else if (iid == XA_IID_VIDEOPOSTPROCESSING) {
338     LOG_ALWAYS_FATAL("Unknown XA_IID_VIDEOPOSTPROCESSING");
339   } else if (iid == XA_IID_VOLUME) {
340     RegisterXAVolumeItfMethods(*static_cast<Guest_XAVolumeItf*>(interface));
341   } else {
342     LOG_ALWAYS_FATAL("Unknown XAInterfaceID");
343   }
344 }
345 
346 // XAresult (*RegisterCallback) (XAObjectItf self, xaObjectCallback callback, void * pContext);
DoCustomTrampoline_XAObject_RegisterCallback(HostCode,ProcessState * state)347 void DoCustomTrampoline_XAObject_RegisterCallback(HostCode /*callee*/, ProcessState* state) {
348   using PFN_callee = decltype(std::declval<XAObjectItf_>().RegisterCallback);
349   auto [self, guest_callback, callback_context] = GuestParamsValues<PFN_callee>(state);
350 
351   // typedef void (XAAPIENTRY * xaObjectCallback) (
352   //    XAObjectItf caller,
353   //    const void * pContext,
354   //    XAuint32 event,
355   //    XAresult result,
356   //    XAuint32 param,
357   //    void * pInterface);
358   auto host_callback = WrapGuestFunction(guest_callback, "XAObject_RegisterCallback-callback");
359 
360   auto&& [ret] = GuestReturnReference<PFN_callee>(state);
361   ret = (*self)->RegisterCallback(self, host_callback, callback_context);
362 }
363 
RegisterXAObjectItfMethods(Guest_XAObjectItf itf)364 void RegisterXAObjectItfMethods(Guest_XAObjectItf itf) {
365   REGISTER_TRAMPOLINE(XAObject, Realize);
366   REGISTER_CUSTOM_TRAMPOLINE(XAObject, GetInterface);
367   REGISTER_TRAMPOLINE(XAObject, Destroy);
368   REGISTER_TRAMPOLINE(XAObject, Resume);
369   REGISTER_TRAMPOLINE(XAObject, GetState);
370   REGISTER_TRAMPOLINE(XAObject, AbortAsyncOperation);
371   REGISTER_TRAMPOLINE(XAObject, SetPriority);
372   REGISTER_TRAMPOLINE(XAObject, GetPriority);
373   REGISTER_TRAMPOLINE(XAObject, SetLossOfControlInterfaces);
374   REGISTER_CUSTOM_TRAMPOLINE(XAObject, RegisterCallback);
375 };
376 
DoThunk_xaCreateEngine(Guest_XAObjectItf * engine,uint32_t num_options,const Guest_XAEngineOption * engine_options,uint32_t num_interfaces,const Guest_XAInterfaceID * interface_ids,uint32_t * interface_required)377 uint32_t DoThunk_xaCreateEngine(Guest_XAObjectItf* engine,
378                                 uint32_t num_options,
379                                 const Guest_XAEngineOption* engine_options,
380                                 uint32_t num_interfaces,
381                                 const Guest_XAInterfaceID* interface_ids,
382                                 uint32_t* interface_required) {
383   auto res = xaCreateEngine(
384       engine, num_options, engine_options, num_interfaces, interface_ids, interface_required);
385   RegisterXAObjectItfMethods(*engine);
386   return res;
387 }
388 
389 #if defined(NATIVE_BRIDGE_GUEST_ARCH_ARM) && defined(__i386__)
390 
391 #include "trampolines_arm_to_x86-inl.h"  // generated file NOLINT [build/include]
392 
393 #elif defined(NATIVE_BRIDGE_GUEST_ARCH_ARM64) && defined(__x86_64__)
394 
395 #include "trampolines_arm64_to_x86_64-inl.h"  // generated file NOLINT [build/include]
396 
397 #elif defined(NATIVE_BRIDGE_GUEST_ARCH_RISCV64) && defined(__x86_64__)
398 
399 #include "trampolines_riscv64_to_x86_64-inl.h"  // generated file NOLINT [build/include]
400 
401 #else
402 
403 #error "Unknown guest/host arch combination"
404 
405 #endif
406 
407 DEFINE_INIT_PROXY_LIBRARY("libOpenMAXAL.so")
408 
409 }  // namespace
410 
411 }  // namespace berberis
412