1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
9 #include "nsIGlobalObject.h"
10 #include "ipc/WebGPUChild.h"
11 #include "ipc/WebGPUTypes.h"
12 #include "mozilla/webgpu/ffi/wgpu.h"
13 #include "mozilla/dom/Promise.h"
14 #include "mozilla/gfx/CanvasManagerChild.h"
15 #include "mozilla/gfx/gfxVars.h"
16 #include "mozilla/StaticPrefs_dom.h"
19 #include <string_view>
21 namespace mozilla::webgpu
{
23 GPU_IMPL_CYCLE_COLLECTION(WGSLLanguageFeatures
, mParent
)
25 GPU_IMPL_CYCLE_COLLECTION(Instance
, mOwner
, mWgslLanguageFeatures
)
27 static inline nsDependentCString
ToCString(const std::string_view s
) {
28 return {s
.data(), s
.length()};
31 /* static */ bool Instance::PrefEnabled(JSContext
* aCx
, JSObject
* aObj
) {
32 if (!StaticPrefs::dom_webgpu_enabled()) {
36 if (NS_IsMainThread()) {
40 return StaticPrefs::dom_webgpu_workers_enabled();
44 already_AddRefed
<Instance
> Instance::Create(nsIGlobalObject
* aOwner
) {
45 RefPtr
<Instance
> result
= new Instance(aOwner
);
46 return result
.forget();
49 Instance::Instance(nsIGlobalObject
* aOwner
)
50 : mOwner(aOwner
), mWgslLanguageFeatures(new WGSLLanguageFeatures(this)) {}
52 Instance::~Instance() { Cleanup(); }
54 void Instance::Cleanup() {}
56 JSObject
* Instance::WrapObject(JSContext
* cx
,
57 JS::Handle
<JSObject
*> givenProto
) {
58 return dom::GPU_Binding::Wrap(cx
, this, givenProto
);
61 already_AddRefed
<dom::Promise
> Instance::RequestAdapter(
62 const dom::GPURequestAdapterOptions
& aOptions
, ErrorResult
& aRv
) {
63 RefPtr
<dom::Promise
> promise
= dom::Promise::Create(mOwner
, aRv
);
64 if (NS_WARN_IF(aRv
.Failed())) {
69 // Check if we should allow the request.
71 const auto errStr
= [&]() -> std::optional
<std::string_view
> {
72 #ifdef RELEASE_OR_BETA
74 return "WebGPU is not yet available in Release or Beta builds.";
77 if (!gfx::gfxVars::AllowWebGPU()) {
78 return "WebGPU is disabled by blocklist.";
80 if (!StaticPrefs::dom_webgpu_enabled()) {
81 return "WebGPU is disabled by dom.webgpu.enabled:false.";
86 promise
->MaybeRejectWithNotSupportedError(ToCString(*errStr
));
87 return promise
.forget();
93 auto* const canvasManager
= gfx::CanvasManagerChild::Get();
95 promise
->MaybeRejectWithInvalidStateError(
96 "Failed to create CanvasManagerChild");
97 return promise
.forget();
100 RefPtr
<WebGPUChild
> bridge
= canvasManager
->GetWebGPUChild();
102 promise
->MaybeRejectWithInvalidStateError("Failed to create WebGPUChild");
103 return promise
.forget();
106 RefPtr
<Instance
> instance
= this;
108 bridge
->InstanceRequestAdapter(aOptions
)->Then(
109 GetCurrentSerialEventTarget(), __func__
,
110 [promise
, instance
, bridge
](ipc::ByteBuf aInfoBuf
) {
111 auto info
= std::make_shared
<ffi::WGPUAdapterInformation
>();
112 ffi::wgpu_client_adapter_extract_info(ToFFI(&aInfoBuf
), info
.get());
113 MOZ_ASSERT(info
->id
!= 0);
114 RefPtr
<Adapter
> adapter
= new Adapter(instance
, bridge
, info
);
115 promise
->MaybeResolve(adapter
);
117 [promise
](const Maybe
<ipc::ResponseRejectReason
>& aResponseReason
) {
118 if (aResponseReason
.isSome()) {
119 promise
->MaybeRejectWithAbortError("Internal communication error!");
121 promise
->MaybeResolve(JS::NullHandleValue
);
125 return promise
.forget();
128 } // namespace mozilla::webgpu