summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.cc
blob: 3ab5796e9c2abe88020c74cb1d3230fac8acf5d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Copyright 2019 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 "third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h"

#include "base/check.h"
#include "third_party/blink/renderer/platform/graphics/gpu/webgpu_resource_provider_cache.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"

namespace blink {

// static
scoped_refptr<DawnControlClientHolder> DawnControlClientHolder::Create(
    std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
    scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
  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::MarkContextLost,
          dawn_control_client_holder->weak_ptr_factory_.GetWeakPtr()));
  return dawn_control_client_holder;
}

DawnControlClientHolder::DawnControlClientHolder(
    std::unique_ptr<WebGraphicsContext3DProvider> context_provider,
    scoped_refptr<base::SingleThreadTaskRunner> task_runner)
    : context_provider_(std::make_unique<WebGraphicsContext3DProviderWrapper>(
          std::move(context_provider))),
      task_runner_(task_runner),
      api_channel_(context_provider_->ContextProvider()
                       ->WebGPUInterface()
                       ->GetAPIChannel()),
      procs_(api_channel_->GetProcs()),
      recyclable_resource_cache_(GetContextProviderWeakPtr(), task_runner) {}

DawnControlClientHolder::~DawnControlClientHolder() = default;

void DawnControlClientHolder::Destroy() {
  MarkContextLost();

  // Destroy the WebGPU context.
  // This ensures that GPU resources are eagerly reclaimed.
  // Because we have disconnected the wire client, any JavaScript which uses
  // WebGPU will do nothing.
  if (context_provider_) {
    // If the context provider is destroyed during a real lost context event, it
    // causes the CommandBufferProxy that the context provider owns, which is
    // what issued the lost context event in the first place, to be destroyed
    // before the event is done being handled. This causes a crash when an
    // outstanding AutoLock goes out of scope. To avoid this, we create a no-op
    // task to hold a reference to the context provider until this function is
    // done executing, and drop it after.
    task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce([](std::unique_ptr<WebGraphicsContext3DProviderWrapper>
                              context_provider) {},
                       std::move(context_provider_)));
  }
}

base::WeakPtr<WebGraphicsContext3DProviderWrapper>
DawnControlClientHolder::GetContextProviderWeakPtr() const {
  if (!context_provider_) {
    return nullptr;
  }
  return context_provider_->GetWeakPtr();
}

void DawnControlClientHolder::MarkContextLost() {
  if (context_lost_) {
    return;
  }
  api_channel_->Disconnect();
  context_lost_ = true;
}

bool DawnControlClientHolder::IsContextLost() const {
  return context_lost_;
}

std::unique_ptr<RecyclableCanvasResource>
DawnControlClientHolder::GetOrCreateCanvasResource(
    const IntSize& size,
    const CanvasResourceParams& params,
    bool is_origin_top_left) {
  return recyclable_resource_cache_.GetOrCreateCanvasResource(
      size, params, is_origin_top_left);
}

}  // namespace blink