File: demo_client.cc

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,122,156 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (194 lines) | stat: -rw-r--r-- 8,037 bytes parent folder | download | duplicates (5)
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/viz/demo/client/demo_client.h"

#include <array>
#include <memory>
#include <utility>
#include <vector>

#include "components/viz/common/quads/compositor_frame.h"
#include "components/viz/common/quads/solid_color_draw_quad.h"
#include "components/viz/common/quads/surface_draw_quad.h"

namespace demo {

DemoClient::DemoClient(const viz::FrameSinkId& frame_sink_id,
                       const viz::LocalSurfaceId& local_surface_id,
                       const gfx::Rect& bounds)
    : thread_(frame_sink_id.ToString()),
      frame_sink_id_(frame_sink_id),
      local_surface_id_(local_surface_id),
      bounds_(bounds) {
  CHECK(thread_.Start());
}

DemoClient::~DemoClient() = default;

void DemoClient::Initialize(
    mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient> receiver,
    mojo::PendingAssociatedRemote<viz::mojom::CompositorFrameSink>
        sink_remote) {
  thread_.task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&DemoClient::InitializeOnThread,
                                base::Unretained(this), std::move(receiver),
                                std::move(sink_remote), mojo::NullRemote()));
}

void DemoClient::Initialize(
    mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient> receiver,
    mojo::PendingRemote<viz::mojom::CompositorFrameSink> sink_remote) {
  thread_.task_runner()->PostTask(
      FROM_HERE,
      base::BindOnce(&DemoClient::InitializeOnThread, base::Unretained(this),
                     std::move(receiver), mojo::NullAssociatedRemote(),
                     std::move(sink_remote)));
}

viz::LocalSurfaceId DemoClient::Embed(const viz::FrameSinkId& frame_sink_id,
                                      const gfx::Rect& bounds) {
  // |embeds_| is used on the client-thread in CreateFrame(). So this needs to
  // be mutated under a lock.
  base::AutoLock lock(lock_);
  allocator_.GenerateId();
  embeds_[frame_sink_id] = {allocator_.GetCurrentLocalSurfaceId(), bounds};
  return embeds_[frame_sink_id].lsid;
}

void DemoClient::Resize(const gfx::Size& size,
                        const viz::LocalSurfaceId& local_surface_id) {
  // |bounds_| and |local_surface_id_| are used on the client-thread in
  // CreateFrame(). So these need to be mutated under a lock.
  base::AutoLock lock(lock_);
  bounds_.set_size(size);
  local_surface_id_ = local_surface_id;
}

viz::CompositorFrame DemoClient::CreateFrame(const viz::BeginFrameArgs& args) {
  constexpr auto colors = std::to_array<SkColor4f>({
      SkColors::kRed,
      SkColors::kGreen,
      SkColors::kYellow,
  });
  viz::CompositorFrame frame;

  frame.metadata.begin_frame_ack = viz::BeginFrameAck(args, true);
  frame.metadata.device_scale_factor = 1.f;
  frame.metadata.frame_token = ++next_frame_token_;

  const viz::CompositorRenderPassId kRenderPassId{1};
  const gfx::Rect& output_rect = bounds_;
  const gfx::Rect& damage_rect = output_rect;
  auto render_pass = viz::CompositorRenderPass::Create();
  render_pass->SetNew(kRenderPassId, output_rect, damage_rect,
                      gfx::Transform());

  // The content of the client is one big solid-color rectangle, which includes
  // the other clients above it (in z-order). The embedded clients are first
  // added to the CompositorFrame using their SurfaceId (i.e. the FrameSinkId
  // and LocalSurfaceId), and then the big rectangle is added afterwards.
  for (auto& iter : embeds_) {
    const gfx::Rect& child_bounds = iter.second.bounds;
    const gfx::Vector2dF center(child_bounds.width() / 2,
                                child_bounds.height() / 2);

    // Apply a rotation so there's visual-update every frame in the demo.
    gfx::Transform transform;
    transform.Translate(center + child_bounds.OffsetFromOrigin());
    transform.Rotate(iter.second.degrees);
    iter.second.degrees += 0.3;
    transform.Translate(-center);

    viz::SharedQuadState* quad_state =
        render_pass->CreateAndAppendSharedQuadState();
    quad_state->SetAll(transform,
                       /*layer_rect=*/child_bounds,
                       /*visible_layer_rect=*/child_bounds,
                       /*filter_info=*/gfx::MaskFilterInfo(),
                       /*clip=*/std::nullopt,
                       /*contents_opaque=*/false, /*opacity_f=*/1.f,
                       /*blend=*/SkBlendMode::kSrcOver,
                       /*sorting_context=*/0,
                       /*layer_id=*/0u, /*fast_rounded_corner=*/false);

    viz::SurfaceDrawQuad* embed =
        render_pass->CreateAndAppendDrawQuad<viz::SurfaceDrawQuad>();
    viz::SurfaceId surface_id(iter.first, iter.second.lsid);
    // |rect| and |visible_rect| needs to be in the quad's coord-space, so to
    // draw the whole quad, it needs to use origin (0, 0).
    embed->SetNew(quad_state,
                  /*rect=*/gfx::Rect(child_bounds.size()),
                  /*visible_rect=*/gfx::Rect(child_bounds.size()),
                  viz::SurfaceRange(surface_id), SkColors::kGray,
                  /*stretch_content_to_fill_bounds=*/false);
  }

  // Add a solid-color draw-quad for the big rectangle covering the entire
  // content-area of the client.
  viz::SharedQuadState* quad_state =
      render_pass->CreateAndAppendSharedQuadState();
  quad_state->SetAll(gfx::Transform(),
                     /*quad_layer_rect=*/output_rect,
                     /*visible_layer_rect=*/output_rect,
                     /*mask_filter_info=*/gfx::MaskFilterInfo(),
                     /*clip_rect=*/std::nullopt, /*are_contents_opaque=*/false,
                     /*opacity=*/1.f,
                     /*blend_mode=*/SkBlendMode::kSrcOver,
                     /*sorting_context=*/0,
                     /*layer_id=*/0u,
                     /*fast_rounded_corner=*/false);

  viz::SolidColorDrawQuad* color_quad =
      render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
  color_quad->SetNew(quad_state, output_rect, output_rect,
                     colors[(++frame_count_ / 60) % std::size(colors)], false);

  frame.render_pass_list.push_back(std::move(render_pass));

  return frame;
}

viz::mojom::CompositorFrameSink* DemoClient::GetPtr() {
  if (associated_sink_.is_bound())
    return associated_sink_.get();
  return sink_.get();
}

void DemoClient::InitializeOnThread(
    mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient> receiver,
    mojo::PendingAssociatedRemote<viz::mojom::CompositorFrameSink>
        associated_sink_remote,
    mojo::PendingRemote<viz::mojom::CompositorFrameSink> sink_remote) {
  receiver_.Bind(std::move(receiver));
  if (associated_sink_remote)
    associated_sink_.Bind(std::move(associated_sink_remote));
  else
    sink_.Bind(std::move(sink_remote));
  // Request for begin-frames.
  GetPtr()->SetNeedsBeginFrame(true);
}

void DemoClient::DidReceiveCompositorFrameAck(
    std::vector<viz::ReturnedResource> resources) {
  // See documentation in mojom for how this can be used.
}

void DemoClient::OnBeginFrame(const viz::BeginFrameArgs& args,
                              const viz::FrameTimingDetailsMap& timing_details,
                              std::vector<viz::ReturnedResource> resources) {
  // Generate a new compositor-frame for each begin-frame. This demo client
  // generates and submits the compositor-frame immediately. But it is possible
  // for the client to delay sending the compositor-frame. |args| includes the
  // deadline for the client before it needs to submit the compositor-frame.
  base::AutoLock lock(lock_);
  GetPtr()->SubmitCompositorFrame(local_surface_id_, CreateFrame(args),
                                  /*hit_test_region_list=*/std::nullopt,
                                  /*submit_time=*/0);
}
void DemoClient::OnBeginFramePausedChanged(bool paused) {}
void DemoClient::ReclaimResources(
    std::vector<viz::ReturnedResource> resources) {}

}  // namespace demo