|  | // Copyright 2019 The Chromium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #ifndef GPU_WEBGPU_CALLBACK_H_ | 
|  | #define GPU_WEBGPU_CALLBACK_H_ | 
|  |  | 
|  | #include <memory> | 
|  |  | 
|  | #include "base/functional/callback.h" | 
|  | #include "base/functional/callback_helpers.h" | 
|  | #include "base/types/is_instantiation.h" | 
|  |  | 
|  | namespace gpu::webgpu { | 
|  |  | 
|  | // WGPUCallback<Callback> is a heap-allocated version of | 
|  | // base::OnceCallback or base::RepeatingCallback. | 
|  | // It is allocated on the heap so that it can be reinterpret_cast to/from | 
|  | // void* and passed to WGPU C callbacks. | 
|  | // | 
|  | // Example: | 
|  | //   WGPUOnceCallback<F>* callback = | 
|  | //     BindWGPUOnceCallback(func, arg1); | 
|  | // | 
|  | //   // |someWGPUFunction| expects callback function with arguments: | 
|  | //   //    Args... args, void* userdata. | 
|  | //   // When it is called, it will forward to func(arg1, args...). | 
|  | //   GetProcs().someWGPUFunction( | 
|  | //     callback->UnboundCallback(), callback->AsUserdata()); | 
|  | template <typename Callback> | 
|  | class WGPUCallbackBase; | 
|  |  | 
|  | template <typename Callback> | 
|  | class WGPUOnceCallback; | 
|  |  | 
|  | template <typename Callback> | 
|  | class WGPURepeatingCallback; | 
|  |  | 
|  | template <template <typename> class BaseCallbackTemplate, | 
|  | typename R, | 
|  | typename... Args> | 
|  | requires base::IsBaseCallback<BaseCallbackTemplate<R(Args...)>> | 
|  | class WGPUCallbackBase<BaseCallbackTemplate<R(Args...)>> { | 
|  | using BaseCallback = BaseCallbackTemplate<R(Args...)>; | 
|  |  | 
|  | public: | 
|  | explicit WGPUCallbackBase(BaseCallback callback) | 
|  | : callback_(std::move(callback)) {} | 
|  |  | 
|  | void* AsUserdata() { return static_cast<void*>(this); } | 
|  |  | 
|  | protected: | 
|  | using UnboundCallbackFunction = R (*)(Args..., void*); | 
|  |  | 
|  | static WGPUCallbackBase* FromUserdata(void* userdata) { | 
|  | return static_cast<WGPUCallbackBase*>(userdata); | 
|  | } | 
|  |  | 
|  | R Run(Args... args) && | 
|  | requires base::is_instantiation<BaseCallback, base::OnceCallback> | 
|  | { | 
|  | return std::move(callback_).Run(std::forward<Args>(args)...); | 
|  | } | 
|  |  | 
|  | R Run(Args... args) const& | 
|  | requires base::is_instantiation<BaseCallback, base::RepeatingCallback> | 
|  | { | 
|  | return callback_.Run(std::forward<Args>(args)...); | 
|  | } | 
|  |  | 
|  | private: | 
|  | BaseCallback callback_; | 
|  | }; | 
|  |  | 
|  | template <typename R, typename... Args> | 
|  | class WGPUOnceCallback<R(Args...)> | 
|  | : public WGPUCallbackBase<base::OnceCallback<R(Args...)>> { | 
|  | using BaseCallback = base::OnceCallback<R(Args...)>; | 
|  |  | 
|  | public: | 
|  | using WGPUCallbackBase<BaseCallback>::WGPUCallbackBase; | 
|  |  | 
|  | typename WGPUCallbackBase<BaseCallback>::UnboundCallbackFunction | 
|  | UnboundCallback() { | 
|  | return CallUnboundOnceCallback; | 
|  | } | 
|  |  | 
|  | private: | 
|  | static R CallUnboundOnceCallback(Args... args, void* handle) { | 
|  | // After this non-repeating callback is run, it should delete itself. | 
|  | auto callback = | 
|  | std::unique_ptr<WGPUOnceCallback>(static_cast<WGPUOnceCallback*>( | 
|  | WGPUCallbackBase<BaseCallback>::FromUserdata(handle))); | 
|  | return std::move(*callback).Run(std::forward<Args>(args)...); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <typename R, typename... Args> | 
|  | class WGPURepeatingCallback<R(Args...)> | 
|  | : public WGPUCallbackBase<base::RepeatingCallback<R(Args...)>> { | 
|  | using BaseCallback = base::RepeatingCallback<R(Args...)>; | 
|  |  | 
|  | public: | 
|  | using WGPUCallbackBase<BaseCallback>::WGPUCallbackBase; | 
|  |  | 
|  | typename WGPUCallbackBase<BaseCallback>::UnboundCallbackFunction | 
|  | UnboundCallback() { | 
|  | return CallUnboundRepeatingCallback; | 
|  | } | 
|  |  | 
|  | private: | 
|  | static R CallUnboundRepeatingCallback(Args... args, void* handle) { | 
|  | return static_cast<WGPURepeatingCallback*>( | 
|  | WGPUCallbackBase<BaseCallback>::FromUserdata(handle)) | 
|  | ->Run(std::forward<Args>(args)...); | 
|  | } | 
|  | }; | 
|  |  | 
|  | template <typename CallbackType> | 
|  | requires base::is_instantiation<CallbackType, base::OnceCallback> | 
|  | auto MakeWGPUOnceCallback(CallbackType&& cb) { | 
|  | return new gpu::webgpu::WGPUOnceCallback<typename CallbackType::RunType>( | 
|  | std::move(cb)); | 
|  | } | 
|  |  | 
|  | template <typename FunctionType, typename... BoundParameters> | 
|  | requires(!base::internal::kIsWeakMethod< | 
|  | base::internal::FunctorTraits<FunctionType, | 
|  | BoundParameters...>::is_method, | 
|  | BoundParameters...>) | 
|  | auto BindWGPUOnceCallback(FunctionType&& function, | 
|  | BoundParameters&&... bound_parameters) { | 
|  | return MakeWGPUOnceCallback( | 
|  | base::BindOnce(std::forward<FunctionType>(function), | 
|  | std::forward<BoundParameters>(bound_parameters)...)); | 
|  | } | 
|  |  | 
|  | template <typename CallbackType> | 
|  | requires base::is_instantiation<CallbackType, base::RepeatingCallback> | 
|  | auto MakeWGPURepeatingCallback(CallbackType&& cb) { | 
|  | return new gpu::webgpu::WGPURepeatingCallback<typename CallbackType::RunType>( | 
|  | std::move(cb)); | 
|  | } | 
|  |  | 
|  | template <typename FunctionType, typename... BoundParameters> | 
|  | auto BindWGPURepeatingCallback(FunctionType&& function, | 
|  | BoundParameters&&... bound_parameters) { | 
|  | return MakeWGPURepeatingCallback( | 
|  | base::BindRepeating(std::forward<FunctionType>(function), | 
|  | std::forward<BoundParameters>(bound_parameters)...)); | 
|  | } | 
|  |  | 
|  | }  // namespace gpu::webgpu | 
|  |  | 
|  | #endif  // GPU_WEBGPU_CALLBACK_H_ |