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(Instance
, mOwner
)
25 static inline nsDependentCString
ToCString(const std::string_view s
) {
26 return {s
.data(), s
.length()};
29 /* static */ bool Instance::PrefEnabled(JSContext
* aCx
, JSObject
* aObj
) {
30 if (!StaticPrefs::dom_webgpu_enabled()) {
34 if (NS_IsMainThread()) {
38 return StaticPrefs::dom_webgpu_workers_enabled();
42 already_AddRefed
<Instance
> Instance::Create(nsIGlobalObject
* aOwner
) {
43 RefPtr
<Instance
> result
= new Instance(aOwner
);
44 return result
.forget();
47 Instance::Instance(nsIGlobalObject
* aOwner
) : mOwner(aOwner
) {}
49 Instance::~Instance() { Cleanup(); }
51 void Instance::Cleanup() {}
53 JSObject
* Instance::WrapObject(JSContext
* cx
,
54 JS::Handle
<JSObject
*> givenProto
) {
55 return dom::GPU_Binding::Wrap(cx
, this, givenProto
);
58 already_AddRefed
<dom::Promise
> Instance::RequestAdapter(
59 const dom::GPURequestAdapterOptions
& aOptions
, ErrorResult
& aRv
) {
60 RefPtr
<dom::Promise
> promise
= dom::Promise::Create(mOwner
, aRv
);
61 if (NS_WARN_IF(aRv
.Failed())) {
66 // Check if we should allow the request.
68 const auto errStr
= [&]() -> std::optional
<std::string_view
> {
69 #ifdef RELEASE_OR_BETA
71 return "WebGPU is not yet available in Release or Beta builds.";
74 if (!gfx::gfxVars::AllowWebGPU()) {
75 return "WebGPU is disabled by blocklist.";
77 if (!StaticPrefs::dom_webgpu_enabled()) {
78 return "WebGPU is disabled by dom.webgpu.enabled:false.";
83 promise
->MaybeRejectWithNotSupportedError(ToCString(*errStr
));
84 return promise
.forget();
90 auto* const canvasManager
= gfx::CanvasManagerChild::Get();
92 promise
->MaybeRejectWithInvalidStateError(
93 "Failed to create CanavasManagerChild");
94 return promise
.forget();
97 RefPtr
<WebGPUChild
> bridge
= canvasManager
->GetWebGPUChild();
99 promise
->MaybeRejectWithInvalidStateError("Failed to create WebGPUChild");
100 return promise
.forget();
103 RefPtr
<Instance
> instance
= this;
105 bridge
->InstanceRequestAdapter(aOptions
)->Then(
106 GetCurrentSerialEventTarget(), __func__
,
107 [promise
, instance
, bridge
](ipc::ByteBuf aInfoBuf
) {
108 auto info
= std::make_shared
<ffi::WGPUAdapterInformation
>();
109 ffi::wgpu_client_adapter_extract_info(ToFFI(&aInfoBuf
), info
.get());
110 MOZ_ASSERT(info
->id
!= 0);
111 RefPtr
<Adapter
> adapter
= new Adapter(instance
, bridge
, info
);
112 promise
->MaybeResolve(adapter
);
114 [promise
](const Maybe
<ipc::ResponseRejectReason
>& aResponseReason
) {
115 if (aResponseReason
.isSome()) {
116 promise
->MaybeRejectWithAbortError("Internal communication error!");
118 promise
->MaybeResolve(JS::NullHandleValue
);
122 return promise
.forget();
125 } // namespace mozilla::webgpu