File: widget_compositor.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (148 lines) | stat: -rw-r--r-- 5,785 bytes parent folder | download | duplicates (6)
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright 2020 The Chromium Authors
// 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/widget/compositing/widget_compositor.h"

#include <utility>

#include "base/functional/callback_helpers.h"
#include "base/task/single_thread_task_runner.h"
#include "base/types/pass_key.h"
#include "cc/trees/layer_tree_host.h"
#include "third_party/blink/renderer/platform/widget/compositing/queue_report_time_swap_promise.h"
#include "third_party/blink/renderer/platform/widget/widget_base.h"
#include "third_party/blink/renderer/platform/widget/widget_base_client.h"

namespace blink {

// static
scoped_refptr<WidgetCompositor> WidgetCompositor::Create(
    base::WeakPtr<WidgetBase> widget_base,
    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
    mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver) {
  auto compositor = base::MakeRefCounted<WidgetCompositor>(
      WidgetCompositorPassKeyProvider::GetPassKey(), std::move(widget_base),
      std::move(main_task_runner), std::move(compositor_task_runner));
  compositor->BindOnThread(std::move(receiver));
  return compositor;
}

WidgetCompositor::WidgetCompositor(
    base::PassKey<WidgetCompositorPassKeyProvider>,
    base::WeakPtr<WidgetBase> widget_base,
    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner)
    : widget_base_(std::move(widget_base)),
      main_task_runner_(std::move(main_task_runner)),
      compositor_task_runner_(std::move(compositor_task_runner)),
      swap_queue_(std::make_unique<WidgetSwapQueue>()) {}

void WidgetCompositor::Shutdown() {
  if (!compositor_task_runner_) {
    ResetOnThread();
  } else {
    compositor_task_runner_->PostTask(
        FROM_HERE, base::BindOnce(&WidgetCompositor::ResetOnThread,
                                  scoped_refptr<WidgetCompositor>(this)));
  }
}

void WidgetCompositor::BindOnThread(
    mojo::PendingReceiver<mojom::blink::WidgetCompositor> receiver) {
  if (CalledOnValidCompositorThread()) {
    receiver_.Bind(std::move(receiver), compositor_task_runner_);
  } else {
    compositor_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&WidgetCompositor::BindOnThread, base::RetainedRef(this),
                       std::move(receiver)));
  }
}

void WidgetCompositor::ResetOnThread() {
  DCHECK(CalledOnValidCompositorThread());
  receiver_.reset();
}

void WidgetCompositor::VisualStateRequest(VisualStateRequestCallback callback) {
  DCHECK(CalledOnValidCompositorThread());

  auto drain_callback =
      base::BindOnce(&WidgetCompositor::DrainQueue, base::RetainedRef(this));
  auto swap_callback = base::BindOnce(&WidgetCompositor::VisualStateResponse,
                                      base::RetainedRef(this));
  if (!compositor_task_runner_) {
    CreateQueueSwapPromise(std::move(drain_callback), std::move(swap_callback),
                           std::move(callback));
  } else {
    main_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&WidgetCompositor::CreateQueueSwapPromise,
                       base::RetainedRef(this), std::move(drain_callback),
                       std::move(swap_callback), std::move(callback)));
  }
}

cc::LayerTreeHost* WidgetCompositor::LayerTreeHost() const {
  return widget_base_->LayerTreeHost();
}

void WidgetCompositor::CreateQueueSwapPromise(
    base::OnceCallback<void(int)> drain_callback,
    base::OnceClosure swap_callback,
    VisualStateRequestCallback callback) {
  DCHECK(main_task_runner_->BelongsToCurrentThread());

  bool first_message_for_frame = false;
  int source_frame_number = 0;
  if (widget_base_) {
    source_frame_number = LayerTreeHost()->SourceFrameNumber();
    swap_queue_->Queue(source_frame_number, std::move(callback),
                       &first_message_for_frame);
  }

  if (first_message_for_frame) {
    LayerTreeHost()->QueueSwapPromise(
        std::make_unique<QueueReportTimeSwapPromise>(
            source_frame_number, std::move(drain_callback),
            std::move(swap_callback), compositor_task_runner_));
    // Request a main frame if one is not already in progress. This might either
    // A) request a commit ahead of time or B) request a commit which is not
    // needed because there are not pending updates. If B) then the frame will
    // be aborted early and the swap promises will be broken (see
    // EarlyOut_NoUpdates).
    LayerTreeHost()->SetNeedsAnimateIfNotInsideMainFrame();

    // In web tests the request does not actually cause a commit, because the
    // compositor is scheduled by the test runner to avoid flakiness. So for
    // this case we must request a main frame.
    widget_base_->client()->ScheduleAnimationForWebTests();
  } else if (compositor_task_runner_) {
    // Delete callbacks on the compositor thread.
    compositor_task_runner_->PostTask(
        FROM_HERE, base::DoNothingWithBoundArgs(std::move(drain_callback),
                                                std::move(swap_callback)));
  }
}

void WidgetCompositor::VisualStateResponse() {
  DCHECK(CalledOnValidCompositorThread());
  Vector<VisualStateRequestCallback> callbacks;
  swap_queue_->GetCallbacks(&callbacks);
  for (auto& callback : callbacks)
    std::move(callback).Run();
}

void WidgetCompositor::DrainQueue(int source_frame_number) {
  DCHECK(CalledOnValidCompositorThread());
  swap_queue_->Drain(source_frame_number);
}

bool WidgetCompositor::CalledOnValidCompositorThread() {
  return !compositor_task_runner_ ||
         compositor_task_runner_->BelongsToCurrentThread();
}

}  // namespace blink