Bug 1857841 - pt 3. Add a new page kind named "fresh" r=glandium
[gecko.git] / dom / webgpu / Instance.cpp
blob4bf58b7fa860d74683747237bcfdaadaa921c0a8
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/. */
6 #include "Instance.h"
8 #include "Adapter.h"
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"
18 #include <optional>
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()) {
31 return false;
34 if (NS_IsMainThread()) {
35 return true;
38 return StaticPrefs::dom_webgpu_workers_enabled();
41 /*static*/
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())) {
62 return nullptr;
65 // -
66 // Check if we should allow the request.
68 const auto errStr = [&]() -> std::optional<std::string_view> {
69 #ifdef RELEASE_OR_BETA
70 if (true) {
71 return "WebGPU is not yet available in Release or Beta builds.";
73 #endif
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.";
80 return {};
81 }();
82 if (errStr) {
83 promise->MaybeRejectWithNotSupportedError(ToCString(*errStr));
84 return promise.forget();
87 // -
88 // Make the request.
90 auto* const canvasManager = gfx::CanvasManagerChild::Get();
91 if (!canvasManager) {
92 promise->MaybeRejectWithInvalidStateError(
93 "Failed to create CanavasManagerChild");
94 return promise.forget();
97 RefPtr<WebGPUChild> bridge = canvasManager->GetWebGPUChild();
98 if (!bridge) {
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!");
117 } else {
118 promise->MaybeResolve(JS::NullHandleValue);
122 return promise.forget();
125 } // namespace mozilla::webgpu