summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer')
-rw-r--r--chromium/third_party/blink/renderer/core/display_lock/display_lock_context.cc3
-rw-r--r--chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc3
-rw-r--r--chromium/third_party/blink/renderer/modules/BUILD.gn1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn14
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/DEPS1
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu.cc5
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu.h10
-rw-r--r--chromium/third_party/blink/renderer/modules/webgpu/gpu_context_lost_test.cc229
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc22
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h4
10 files changed, 286 insertions, 6 deletions
diff --git a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.cc
index 918c6b7350d..4114d83a195 100644
--- a/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.cc
+++ b/chromium/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -998,6 +998,9 @@ bool DisplayLockContext::ForceUnlockIfNeeded() {
layout_invalidation_reason::kDisplayLock);
}
}
+ // If we forced unlock, then we need to prevent subsequent calls to
+ // Lock() until the next frame.
+ SetRequestedState(EContentVisibility::kVisible);
}
return true;
}
diff --git a/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc b/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
index 69f6da14d17..d15636e1ea2 100644
--- a/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
+++ b/chromium/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
@@ -549,6 +549,9 @@ FontSelector* OffscreenCanvas::GetFontSelector() {
if (auto* window = DynamicTo<LocalDOMWindow>(GetExecutionContext())) {
return window->document()->GetStyleEngine().GetFontSelector();
}
+ // TODO(crbug.com/1334864): Temporary mitigation. Remove the following
+ // CHECK once a more comprehensive solution has been implemented.
+ CHECK(GetExecutionContext()->IsWorkerGlobalScope());
return To<WorkerGlobalScope>(GetExecutionContext())->GetFontSelector();
}
diff --git a/chromium/third_party/blink/renderer/modules/BUILD.gn b/chromium/third_party/blink/renderer/modules/BUILD.gn
index 818e3e38fe4..f9428f65f47 100644
--- a/chromium/third_party/blink/renderer/modules/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/BUILD.gn
@@ -663,6 +663,7 @@ source_set("unit_tests") {
"//third_party/blink/renderer/modules/peerconnection:test_support",
"//third_party/blink/renderer/modules/storage:unit_tests",
"//third_party/blink/renderer/modules/webcodecs:unit_tests",
+ "//third_party/blink/renderer/modules/webgpu:unit_tests",
"//third_party/blink/renderer/modules/webtransport:unit_tests",
"//third_party/blink/renderer/platform",
"//third_party/blink/renderer/platform:test_support",
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn b/chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn
index e7d4345b4a2..87ffc91763d 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn
+++ b/chromium/third_party/blink/renderer/modules/webgpu/BUILD.gn
@@ -93,3 +93,17 @@ blink_modules_sources("webgpu") {
"//third_party/dawn/include/dawn:headers",
]
}
+
+source_set("unit_tests") {
+ testonly = true
+ sources = [ "gpu_context_lost_test.cc" ]
+
+ deps = [
+ "//base/test:test_support",
+ "//third_party/blink/renderer/controller:blink_bindings_test_sources",
+ "//third_party/blink/renderer/core",
+ "//third_party/blink/renderer/core:testing",
+ "//third_party/blink/renderer/modules",
+ "//third_party/blink/renderer/platform:test_support",
+ ]
+}
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/DEPS b/chromium/third_party/blink/renderer/modules/webgpu/DEPS
index c7774f8346b..1238fddbe36 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/DEPS
+++ b/chromium/third_party/blink/renderer/modules/webgpu/DEPS
@@ -9,6 +9,7 @@ include_rules = [
"+gpu/command_buffer/client/raster_interface.h",
"+gpu/command_buffer/client/shared_image_interface.h",
"+gpu/command_buffer/client/webgpu_interface.h",
+ "+gpu/command_buffer/client/webgpu_interface_stub.h",
"+media/base/video_frame.h",
"+media/base/wait_and_replace_sync_token_client.h",
"+media/renderers/paint_canvas_video_renderer.h",
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu.cc
index faa292a7723..c7516603b90 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu.cc
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu.cc
@@ -288,4 +288,9 @@ void BoxedMappableWGPUBufferHandles::ClearAndDestroyAll(
contents_.clear();
}
+void GPU::SetDawnControlClientHolderForTesting(
+ scoped_refptr<DawnControlClientHolder> dawn_control_client) {
+ dawn_control_client_ = std::move(dawn_control_client);
+}
+
} // namespace blink
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu.h b/chromium/third_party/blink/renderer/modules/webgpu/gpu.h
index 4477129d951..606a331ad18 100644
--- a/chromium/third_party/blink/renderer/modules/webgpu/gpu.h
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu.h
@@ -9,6 +9,7 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
+#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
#include "third_party/blink/renderer/platform/supplementable.h"
@@ -48,9 +49,9 @@ struct BoxedMappableWGPUBufferHandles
HashSet<void*> contents_;
};
-class GPU final : public ScriptWrappable,
- public Supplement<NavigatorBase>,
- public ExecutionContextLifecycleObserver {
+class MODULES_EXPORT GPU final : public ScriptWrappable,
+ public Supplement<NavigatorBase>,
+ public ExecutionContextLifecycleObserver {
DEFINE_WRAPPERTYPEINFO();
public:
@@ -87,6 +88,9 @@ class GPU final : public ScriptWrappable,
return mappable_buffer_handles_.get();
}
+ void SetDawnControlClientHolderForTesting(
+ scoped_refptr<DawnControlClientHolder> dawn_control_client);
+
private:
void OnRequestAdapterCallback(ScriptState* script_state,
const GPURequestAdapterOptions* options,
diff --git a/chromium/third_party/blink/renderer/modules/webgpu/gpu_context_lost_test.cc b/chromium/third_party/blink/renderer/modules/webgpu/gpu_context_lost_test.cc
new file mode 100644
index 00000000000..1063295a543
--- /dev/null
+++ b/chromium/third_party/blink/renderer/modules/webgpu/gpu_context_lost_test.cc
@@ -0,0 +1,229 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/callback.h"
+#include "base/run_loop.h"
+#include "base/test/mock_callback.h"
+#include "gpu/command_buffer/client/webgpu_interface_stub.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/navigator.h"
+#include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
+#include "third_party/blink/renderer/modules/webgpu/gpu.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/drawing_buffer_test_helpers.h"
+
+namespace blink {
+
+namespace {
+
+class WebGPUContextProviderForTest
+ : public WebGraphicsContext3DProviderForTests {
+ public:
+ explicit WebGPUContextProviderForTest(
+ base::MockCallback<base::OnceClosure>* destruction_callback)
+ : WebGraphicsContext3DProviderForTests(
+ std::make_unique<gpu::webgpu::WebGPUInterfaceStub>()),
+ destruction_callback_(destruction_callback) {}
+ ~WebGPUContextProviderForTest() override {
+ if (destruction_callback_) {
+ destruction_callback_->Run();
+ }
+ }
+
+ static WebGPUContextProviderForTest* From(
+ scoped_refptr<DawnControlClientHolder>& dawn_control_client) {
+ return static_cast<WebGPUContextProviderForTest*>(
+ dawn_control_client->GetContextProviderWeakPtr()->ContextProvider());
+ }
+
+ void ClearDestructionCallback() { destruction_callback_ = nullptr; }
+
+ void SetLostContextCallback(
+ base::RepeatingClosure lost_context_callback) override {
+ lost_context_callback_ = std::move(lost_context_callback);
+ }
+
+ void CallLostContextCallback() { lost_context_callback_.Run(); }
+
+ private:
+ base::MockCallback<base::OnceClosure>* destruction_callback_;
+ base::RepeatingClosure lost_context_callback_;
+};
+
+class WebGPUContextLostTest : public testing::Test {
+ protected:
+ void SetUp() override { page_ = std::make_unique<DummyPageHolder>(); }
+
+ std::tuple<ExecutionContext*, GPU*> SetUpGPU(V8TestingScope* v8_test_scope) {
+ ExecutionContext* execution_context =
+ ExecutionContext::From(v8_test_scope->GetScriptState());
+
+ Navigator* navigator = page_->GetFrame().DomWindow()->navigator();
+ GPU* gpu = MakeGarbageCollected<GPU>(*navigator);
+ return std::make_tuple(execution_context, gpu);
+ }
+
+ std::unique_ptr<DummyPageHolder> page_;
+};
+
+// Test that the context provider is destructed after the last reference to
+// its owning DawnControlClientHolder is dropped.
+TEST_F(WebGPUContextLostTest, DestructedAfterLastRefDropped) {
+ V8TestingScope v8_test_scope;
+ ExecutionContext* execution_context =
+ ExecutionContext::From(v8_test_scope.GetScriptState());
+
+ base::MockCallback<base::OnceClosure> destruction_callback;
+ auto context_provider =
+ std::make_unique<WebGPUContextProviderForTest>(&destruction_callback);
+
+ auto dawn_control_client = DawnControlClientHolder::Create(
+ std::move(context_provider),
+ execution_context->GetTaskRunner(TaskType::kWebGPU));
+
+ // Drop the last reference to the DawnControlClientHolder which will
+ // now destroy the context provider.
+ EXPECT_CALL(destruction_callback, Run()).Times(1);
+ dawn_control_client = nullptr;
+}
+
+// Test that the GPU lost context callback marks the context lost, but does not
+// destruct it.
+TEST_F(WebGPUContextLostTest, GPULostContext) {
+ V8TestingScope v8_test_scope;
+ auto [execution_context, gpu] = SetUpGPU(&v8_test_scope);
+
+ base::MockCallback<base::OnceClosure> destruction_callback;
+ auto context_provider =
+ std::make_unique<WebGPUContextProviderForTest>(&destruction_callback);
+
+ auto dawn_control_client = DawnControlClientHolder::Create(
+ std::move(context_provider),
+ execution_context->GetTaskRunner(TaskType::kWebGPU));
+
+ gpu->SetDawnControlClientHolderForTesting(dawn_control_client);
+
+ // Trigger the lost context callback, but the context should not be destroyed.
+ EXPECT_CALL(destruction_callback, Run()).Times(0);
+ WebGPUContextProviderForTest::From(dawn_control_client)
+ ->CallLostContextCallback();
+ testing::Mock::VerifyAndClear(&destruction_callback);
+
+ // The context should be marked lost.
+ EXPECT_TRUE(dawn_control_client->IsContextLost());
+
+ // The context provider should still be live.
+ auto context_provider_weak_ptr =
+ dawn_control_client->GetContextProviderWeakPtr();
+ EXPECT_NE(context_provider_weak_ptr, nullptr);
+
+ // Clear the destruction callback since it is stack-allocated in this frame.
+ static_cast<WebGPUContextProviderForTest*>(
+ context_provider_weak_ptr->ContextProvider())
+ ->ClearDestructionCallback();
+}
+
+// Test that the GPU lost context callback marks the context lost, and then when
+// the context is recreated, the context still lives until the previous
+// DawnControlClientHolder is destroyed.
+TEST_F(WebGPUContextLostTest, RecreatedAfterGPULostContext) {
+ V8TestingScope v8_test_scope;
+ auto [execution_context, gpu] = SetUpGPU(&v8_test_scope);
+
+ base::MockCallback<base::OnceClosure> destruction_callback;
+ auto context_provider =
+ std::make_unique<WebGPUContextProviderForTest>(&destruction_callback);
+
+ auto dawn_control_client = DawnControlClientHolder::Create(
+ std::move(context_provider),
+ execution_context->GetTaskRunner(TaskType::kWebGPU));
+
+ gpu->SetDawnControlClientHolderForTesting(dawn_control_client);
+
+ // Trigger the lost context callback, but the context should not be destroyed.
+ EXPECT_CALL(destruction_callback, Run()).Times(0);
+ WebGPUContextProviderForTest::From(dawn_control_client)
+ ->CallLostContextCallback();
+ testing::Mock::VerifyAndClear(&destruction_callback);
+
+ // The context should be marked lost.
+ EXPECT_TRUE(dawn_control_client->IsContextLost());
+
+ // The context provider should still be live.
+ auto context_provider_weak_ptr =
+ dawn_control_client->GetContextProviderWeakPtr();
+ EXPECT_NE(context_provider_weak_ptr, nullptr);
+
+ // Make a new context provider and DawnControlClientHolder
+ base::MockCallback<base::OnceClosure> destruction_callback2;
+ auto context_provider2 =
+ std::make_unique<WebGPUContextProviderForTest>(&destruction_callback2);
+
+ auto dawn_control_client2 = DawnControlClientHolder::Create(
+ std::move(context_provider2),
+ execution_context->GetTaskRunner(TaskType::kWebGPU));
+
+ // Set the new context, but the previous context should still not be
+ // destroyed.
+ EXPECT_CALL(destruction_callback, Run()).Times(0);
+ gpu->SetDawnControlClientHolderForTesting(dawn_control_client2);
+ testing::Mock::VerifyAndClear(&destruction_callback);
+
+ // Drop the last reference to the previous DawnControlClientHolder which will
+ // now destroy the previous context provider.
+ EXPECT_CALL(destruction_callback, Run()).Times(1);
+ dawn_control_client = nullptr;
+ testing::Mock::VerifyAndClear(&destruction_callback);
+
+ // Clear the destruction callback since it is stack-allocated in this frame.
+ static_cast<WebGPUContextProviderForTest*>(
+ dawn_control_client2->GetContextProviderWeakPtr()->ContextProvider())
+ ->ClearDestructionCallback();
+}
+
+// Test that ContextDestroyed lifecycle event destructs the context.
+TEST_F(WebGPUContextLostTest, ContextDestroyed) {
+ V8TestingScope v8_test_scope;
+ auto [execution_context, gpu] = SetUpGPU(&v8_test_scope);
+
+ base::MockCallback<base::OnceClosure> destruction_callback;
+ auto context_provider =
+ std::make_unique<WebGPUContextProviderForTest>(&destruction_callback);
+
+ auto dawn_control_client = DawnControlClientHolder::Create(
+ std::move(context_provider),
+ execution_context->GetTaskRunner(TaskType::kWebGPU));
+
+ gpu->SetDawnControlClientHolderForTesting(dawn_control_client);
+
+ // Trigger the context destroyed lifecycle event. The context should not be
+ // destroyed yet.
+ EXPECT_CALL(destruction_callback, Run()).Times(0);
+ gpu->ContextDestroyed();
+ testing::Mock::VerifyAndClear(&destruction_callback);
+
+ // The context should be marked lost.
+ EXPECT_TRUE(dawn_control_client->IsContextLost());
+
+ // Getting the context provider should return null.
+ EXPECT_EQ(dawn_control_client->GetContextProviderWeakPtr(), nullptr);
+
+ // The context is destructed in a posted task with a fresh callstack to avoid
+ // re-entrancy issues. Expectations should resolve by the end of the next
+ // task.
+ EXPECT_CALL(destruction_callback, Run()).Times(1);
+ base::RunLoop loop;
+ execution_context->GetTaskRunner(TaskType::kWebGPU)
+ ->PostTask(FROM_HERE, loop.QuitClosure());
+ loop.Run();
+ testing::Mock::VerifyAndClear(&destruction_callback);
+}
+
+} // namespace
+
+} // namespace blink
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc b/chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc
index be5b392fa83..6a6283972e7 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc
@@ -17,9 +17,17 @@ scoped_refptr<DawnControlClientHolder> DawnControlClientHolder::Create(
auto dawn_control_client_holder =
base::MakeRefCounted<DawnControlClientHolder>(std::move(context_provider),
std::move(task_runner));
+ // The context lost callback occurs when the client receives
+ // OnGpuControlLostContext. This can happen on fatal errors when the GPU
+ // channel is disconnected: the GPU process crashes, the GPU process fails to
+ // deserialize a message, etc. We mark the context lost, but NOT destroy the
+ // entire WebGraphicsContext3DProvider as that would free services for mapping
+ // shared memory. There may still be outstanding mapped GPUBuffers pointing to
+ // this memory.
dawn_control_client_holder->context_provider_->ContextProvider()
->SetLostContextCallback(WTF::BindRepeating(
- &DawnControlClientHolder::Destroy, dawn_control_client_holder));
+ &DawnControlClientHolder::MarkContextLost,
+ dawn_control_client_holder->weak_ptr_factory_.GetWeakPtr()));
return dawn_control_client_holder;
}
@@ -38,7 +46,7 @@ DawnControlClientHolder::DawnControlClientHolder(
DawnControlClientHolder::~DawnControlClientHolder() = default;
void DawnControlClientHolder::Destroy() {
- api_channel_->Disconnect();
+ MarkContextLost();
// Destroy the WebGPU context.
// This ensures that GPU resources are eagerly reclaimed.
@@ -68,8 +76,16 @@ DawnControlClientHolder::GetContextProviderWeakPtr() const {
return context_provider_->GetWeakPtr();
}
+void DawnControlClientHolder::MarkContextLost() {
+ if (context_lost_) {
+ return;
+ }
+ api_channel_->Disconnect();
+ context_lost_ = true;
+}
+
bool DawnControlClientHolder::IsContextLost() const {
- return !context_provider_;
+ return context_lost_;
}
std::unique_ptr<RecyclableCanvasResource>
diff --git a/chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h b/chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h
index 550038892c9..9e3c086225a 100644
--- a/chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h
+++ b/chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h
@@ -47,6 +47,7 @@ class PLATFORM_EXPORT DawnControlClientHolder
base::WeakPtr<WebGraphicsContext3DProviderWrapper> GetContextProviderWeakPtr()
const;
const DawnProcTable& GetProcs() const { return procs_; }
+ void MarkContextLost();
bool IsContextLost() const;
std::unique_ptr<RecyclableCanvasResource> GetOrCreateCanvasResource(
const SkImageInfo& info,
@@ -56,11 +57,14 @@ class PLATFORM_EXPORT DawnControlClientHolder
friend class RefCounted<DawnControlClientHolder>;
~DawnControlClientHolder();
+ bool context_lost_ = false;
std::unique_ptr<WebGraphicsContext3DProviderWrapper> context_provider_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
scoped_refptr<gpu::webgpu::APIChannel> api_channel_;
DawnProcTable procs_;
WebGPURecyclableResourceCache recyclable_resource_cache_;
+
+ base::WeakPtrFactory<DawnControlClientHolder> weak_ptr_factory_{this};
};
} // namespace blink