1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/renderer/android/synchronous_layer_tree_frame_sink.h"
6
7 #include <vector>
8
9 #include "base/auto_reset.h"
10 #include "base/bind.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/macros.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/threading/thread_task_runner_handle.h"
16 #include "cc/trees/layer_tree_frame_sink_client.h"
17 #include "components/viz/common/display/renderer_settings.h"
18 #include "components/viz/common/features.h"
19 #include "components/viz/common/gpu/context_provider.h"
20 #include "components/viz/common/quads/compositor_frame.h"
21 #include "components/viz/common/quads/render_pass.h"
22 #include "components/viz/common/quads/surface_draw_quad.h"
23 #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
24 #include "components/viz/service/display/display.h"
25 #include "components/viz/service/display/output_surface.h"
26 #include "components/viz/service/display/output_surface_frame.h"
27 #include "components/viz/service/display/overlay_processor_stub.h"
28 #include "components/viz/service/display/software_output_device.h"
29 #include "components/viz/service/display/texture_deleter.h"
30 #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
31 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
32 #include "content/common/view_messages.h"
33 #include "content/renderer/frame_swap_message_queue.h"
34 #include "content/renderer/input/synchronous_compositor_registry.h"
35 #include "content/renderer/render_thread_impl.h"
36 #include "gpu/command_buffer/client/context_support.h"
37 #include "gpu/command_buffer/client/gles2_interface.h"
38 #include "gpu/command_buffer/common/gpu_memory_allocation.h"
39 #include "ipc/ipc_message.h"
40 #include "ipc/ipc_message_macros.h"
41 #include "ipc/ipc_sender.h"
42 #include "third_party/skia/include/core/SkCanvas.h"
43 #include "ui/gfx/geometry/rect_conversions.h"
44 #include "ui/gfx/skia_util.h"
45 #include "ui/gfx/transform.h"
46
47 namespace content {
48
49 namespace {
50
51 const viz::FrameSinkId kRootFrameSinkId(1, 1);
52 const viz::FrameSinkId kChildFrameSinkId(1, 2);
53
54 // Do not limit number of resources, so use an unrealistically high value.
55 const size_t kNumResourcesLimit = 10 * 1000 * 1000;
56
57 class SoftwareDevice : public viz::SoftwareOutputDevice {
58 public:
SoftwareDevice(SkCanvas ** canvas)59 SoftwareDevice(SkCanvas** canvas) : canvas_(canvas) {}
60
Resize(const gfx::Size & pixel_size,float device_scale_factor)61 void Resize(const gfx::Size& pixel_size, float device_scale_factor) override {
62 // Intentional no-op: canvas size is controlled by the embedder.
63 }
BeginPaint(const gfx::Rect & damage_rect)64 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override {
65 DCHECK(*canvas_) << "BeginPaint with no canvas set";
66 return *canvas_;
67 }
EndPaint()68 void EndPaint() override {}
69
70 private:
71 SkCanvas** canvas_;
72
73 DISALLOW_COPY_AND_ASSIGN(SoftwareDevice);
74 };
75
76 // This is used with resourceless software draws.
77 class SoftwareCompositorFrameSinkClient
78 : public viz::mojom::CompositorFrameSinkClient {
79 public:
80 SoftwareCompositorFrameSinkClient() = default;
81 ~SoftwareCompositorFrameSinkClient() override = default;
82
DidReceiveCompositorFrameAck(const std::vector<viz::ReturnedResource> & resources)83 void DidReceiveCompositorFrameAck(
84 const std::vector<viz::ReturnedResource>& resources) override {
85 DCHECK(resources.empty());
86 }
OnBeginFrame(const viz::BeginFrameArgs & args,const viz::FrameTimingDetailsMap & timing_details)87 void OnBeginFrame(const viz::BeginFrameArgs& args,
88 const viz::FrameTimingDetailsMap& timing_details) override {
89 }
ReclaimResources(const std::vector<viz::ReturnedResource> & resources)90 void ReclaimResources(
91 const std::vector<viz::ReturnedResource>& resources) override {
92 DCHECK(resources.empty());
93 }
OnBeginFramePausedChanged(bool paused)94 void OnBeginFramePausedChanged(bool paused) override {}
95
96 private:
97 DISALLOW_COPY_AND_ASSIGN(SoftwareCompositorFrameSinkClient);
98 };
99
100 } // namespace
101
102 class SynchronousLayerTreeFrameSink::SoftwareOutputSurface
103 : public viz::OutputSurface {
104 public:
SoftwareOutputSurface(std::unique_ptr<SoftwareDevice> software_device)105 SoftwareOutputSurface(std::unique_ptr<SoftwareDevice> software_device)
106 : viz::OutputSurface(std::move(software_device)) {}
107
108 // viz::OutputSurface implementation.
BindToClient(viz::OutputSurfaceClient * client)109 void BindToClient(viz::OutputSurfaceClient* client) override {}
EnsureBackbuffer()110 void EnsureBackbuffer() override {}
DiscardBackbuffer()111 void DiscardBackbuffer() override {}
BindFramebuffer()112 void BindFramebuffer() override {}
SetDrawRectangle(const gfx::Rect & rect)113 void SetDrawRectangle(const gfx::Rect& rect) override {}
SwapBuffers(viz::OutputSurfaceFrame frame)114 void SwapBuffers(viz::OutputSurfaceFrame frame) override {}
Reshape(const gfx::Size & size,float scale_factor,const gfx::ColorSpace & color_space,gfx::BufferFormat format,bool use_stencil)115 void Reshape(const gfx::Size& size,
116 float scale_factor,
117 const gfx::ColorSpace& color_space,
118 gfx::BufferFormat format,
119 bool use_stencil) override {}
GetFramebufferCopyTextureFormat()120 uint32_t GetFramebufferCopyTextureFormat() override { return 0; }
IsDisplayedAsOverlayPlane() const121 bool IsDisplayedAsOverlayPlane() const override { return false; }
GetOverlayTextureId() const122 unsigned GetOverlayTextureId() const override { return 0; }
HasExternalStencilTest() const123 bool HasExternalStencilTest() const override { return false; }
ApplyExternalStencil()124 void ApplyExternalStencil() override {}
UpdateGpuFence()125 unsigned UpdateGpuFence() override { return 0; }
SetUpdateVSyncParametersCallback(viz::UpdateVSyncParametersCallback callback)126 void SetUpdateVSyncParametersCallback(
127 viz::UpdateVSyncParametersCallback callback) override {}
SetDisplayTransformHint(gfx::OverlayTransform transform)128 void SetDisplayTransformHint(gfx::OverlayTransform transform) override {}
GetDisplayTransform()129 gfx::OverlayTransform GetDisplayTransform() override {
130 return gfx::OVERLAY_TRANSFORM_NONE;
131 }
GetGpuTaskSchedulerHelper()132 scoped_refptr<gpu::GpuTaskSchedulerHelper> GetGpuTaskSchedulerHelper()
133 override {
134 return nullptr;
135 }
GetMemoryTracker()136 gpu::MemoryTracker* GetMemoryTracker() override { return nullptr; }
137 };
138
139 base::TimeDelta SynchronousLayerTreeFrameSink::StubDisplayClient::
GetPreferredFrameIntervalForFrameSinkId(const viz::FrameSinkId & id)140 GetPreferredFrameIntervalForFrameSinkId(const viz::FrameSinkId& id) {
141 return viz::BeginFrameArgs::MinInterval();
142 }
143
SynchronousLayerTreeFrameSink(scoped_refptr<viz::ContextProvider> context_provider,scoped_refptr<viz::RasterContextProvider> worker_context_provider,scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,gpu::GpuMemoryBufferManager * gpu_memory_buffer_manager,IPC::Sender * sender,int routing_id,uint32_t layer_tree_frame_sink_id,std::unique_ptr<viz::BeginFrameSource> synthetic_begin_frame_source,SynchronousCompositorRegistry * registry,scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue,mojo::PendingRemote<viz::mojom::CompositorFrameSink> compositor_frame_sink_remote,mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient> client_receiver)144 SynchronousLayerTreeFrameSink::SynchronousLayerTreeFrameSink(
145 scoped_refptr<viz::ContextProvider> context_provider,
146 scoped_refptr<viz::RasterContextProvider> worker_context_provider,
147 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
148 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
149 IPC::Sender* sender,
150 int routing_id,
151 uint32_t layer_tree_frame_sink_id,
152 std::unique_ptr<viz::BeginFrameSource> synthetic_begin_frame_source,
153 SynchronousCompositorRegistry* registry,
154 scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue,
155 mojo::PendingRemote<viz::mojom::CompositorFrameSink>
156 compositor_frame_sink_remote,
157 mojo::PendingReceiver<viz::mojom::CompositorFrameSinkClient>
158 client_receiver)
159 : cc::LayerTreeFrameSink(std::move(context_provider),
160 std::move(worker_context_provider),
161 std::move(compositor_task_runner),
162 gpu_memory_buffer_manager),
163 routing_id_(routing_id),
164 layer_tree_frame_sink_id_(layer_tree_frame_sink_id),
165 registry_(registry),
166 sender_(sender),
167 memory_policy_(0u),
168 frame_swap_message_queue_(frame_swap_message_queue),
169 unbound_compositor_frame_sink_(std::move(compositor_frame_sink_remote)),
170 unbound_client_(std::move(client_receiver)),
171 synthetic_begin_frame_source_(std::move(synthetic_begin_frame_source)),
172 viz_frame_submission_enabled_(
173 features::IsUsingVizFrameSubmissionForWebView()) {
174 DCHECK(registry_);
175 DCHECK(sender_);
176 thread_checker_.DetachFromThread();
177 memory_policy_.priority_cutoff_when_visible =
178 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
179 }
180
181 SynchronousLayerTreeFrameSink::~SynchronousLayerTreeFrameSink() = default;
182
SetSyncClient(SynchronousLayerTreeFrameSinkClient * compositor)183 void SynchronousLayerTreeFrameSink::SetSyncClient(
184 SynchronousLayerTreeFrameSinkClient* compositor) {
185 sync_client_ = compositor;
186 }
187
BindToClient(cc::LayerTreeFrameSinkClient * sink_client)188 bool SynchronousLayerTreeFrameSink::BindToClient(
189 cc::LayerTreeFrameSinkClient* sink_client) {
190 DCHECK(CalledOnValidThread());
191 if (!cc::LayerTreeFrameSink::BindToClient(sink_client))
192 return false;
193
194 if (viz_frame_submission_enabled_) {
195 compositor_frame_sink_.Bind(std::move(unbound_compositor_frame_sink_));
196 client_receiver_.Bind(std::move(unbound_client_), compositor_task_runner_);
197 }
198
199 // The SharedBitmapManager is null since software compositing is not supported
200 // or used on Android.
201 frame_sink_manager_ = std::make_unique<viz::FrameSinkManagerImpl>(
202 /*shared_bitmap_manager=*/nullptr);
203
204 if (synthetic_begin_frame_source_) {
205 client_->SetBeginFrameSource(synthetic_begin_frame_source_.get());
206 } else {
207 external_begin_frame_source_ =
208 std::make_unique<viz::ExternalBeginFrameSource>(this);
209 external_begin_frame_source_->OnSetBeginFrameSourcePaused(
210 begin_frames_paused_);
211 client_->SetBeginFrameSource(external_begin_frame_source_.get());
212 }
213
214 client_->SetMemoryPolicy(memory_policy_);
215 client_->SetTreeActivationCallback(base::BindRepeating(
216 &SynchronousLayerTreeFrameSink::DidActivatePendingTree,
217 base::Unretained(this)));
218 registry_->RegisterLayerTreeFrameSink(routing_id_, this);
219
220 software_frame_sink_client_ =
221 std::make_unique<SoftwareCompositorFrameSinkClient>();
222 constexpr bool root_support_is_root = true;
223 constexpr bool child_support_is_root = false;
224 root_support_ = std::make_unique<viz::CompositorFrameSinkSupport>(
225 software_frame_sink_client_.get(), frame_sink_manager_.get(),
226 kRootFrameSinkId, root_support_is_root);
227 child_support_ = std::make_unique<viz::CompositorFrameSinkSupport>(
228 software_frame_sink_client_.get(), frame_sink_manager_.get(),
229 kChildFrameSinkId, child_support_is_root);
230
231 viz::RendererSettings software_renderer_settings;
232
233 auto output_surface = std::make_unique<SoftwareOutputSurface>(
234 std::make_unique<SoftwareDevice>(¤t_sw_canvas_));
235 software_output_surface_ = output_surface.get();
236
237 auto overlay_processor = std::make_unique<viz::OverlayProcessorStub>();
238
239 // The gpu_memory_buffer_manager here is null as the Display is only used for
240 // resourcesless software draws, where no resources are included in the frame
241 // swapped from the compositor. So there is no need for it.
242 // The shared_bitmap_manager_ is provided for the Display to allocate
243 // resources.
244 // TODO(crbug.com/692814): The Display never sends its resources out of
245 // process so there is no reason for it to use a SharedBitmapManager.
246 display_ = std::make_unique<viz::Display>(
247 &shared_bitmap_manager_, software_renderer_settings, kRootFrameSinkId,
248 std::move(output_surface), std::move(overlay_processor),
249 nullptr /* scheduler */, nullptr /* current_task_runner */);
250 display_->Initialize(&display_client_,
251 frame_sink_manager_->surface_manager());
252 display_->SetVisible(true);
253 return true;
254 }
255
DetachFromClient()256 void SynchronousLayerTreeFrameSink::DetachFromClient() {
257 DCHECK(CalledOnValidThread());
258 client_->SetBeginFrameSource(nullptr);
259 // Destroy the begin frame source on the same thread it was bound on.
260 synthetic_begin_frame_source_ = nullptr;
261 external_begin_frame_source_ = nullptr;
262 if (sync_client_)
263 sync_client_->SinkDestroyed();
264 registry_->UnregisterLayerTreeFrameSink(routing_id_, this);
265 client_->SetTreeActivationCallback(base::RepeatingClosure());
266 root_support_.reset();
267 child_support_.reset();
268 software_frame_sink_client_ = nullptr;
269 software_output_surface_ = nullptr;
270 display_ = nullptr;
271 frame_sink_manager_ = nullptr;
272
273 client_receiver_.reset();
274 compositor_frame_sink_.reset();
275
276 cc::LayerTreeFrameSink::DetachFromClient();
277 }
278
SetLocalSurfaceId(const viz::LocalSurfaceId & local_surface_id)279 void SynchronousLayerTreeFrameSink::SetLocalSurfaceId(
280 const viz::LocalSurfaceId& local_surface_id) {
281 DCHECK(CalledOnValidThread());
282 local_surface_id_ = local_surface_id;
283 }
284
SubmitCompositorFrame(viz::CompositorFrame frame,bool hit_test_data_changed,bool show_hit_test_borders)285 void SynchronousLayerTreeFrameSink::SubmitCompositorFrame(
286 viz::CompositorFrame frame,
287 bool hit_test_data_changed,
288 bool show_hit_test_borders) {
289 DCHECK(CalledOnValidThread());
290 DCHECK(sync_client_);
291
292 base::Optional<viz::CompositorFrame> submit_frame;
293 gfx::Size child_size = in_software_draw_
294 ? sw_viewport_for_current_draw_.size()
295 : frame.size_in_pixels();
296 if (!child_local_surface_id_allocation_.IsValid() ||
297 child_size_ != child_size ||
298 device_scale_factor_ != frame.metadata.device_scale_factor) {
299 child_local_surface_id_allocator_.GenerateId();
300 child_local_surface_id_allocation_ =
301 child_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation();
302 child_size_ = child_size;
303 device_scale_factor_ = frame.metadata.device_scale_factor;
304 }
305
306 if (in_software_draw_) {
307 // The frame we send to the client is actually just the metadata. Preserve
308 // the |frame| for the software path below.
309 submit_frame.emplace();
310 submit_frame->metadata = frame.metadata.Clone();
311
312 // The layer compositor should be giving a frame that covers the
313 // |sw_viewport_for_current_draw_| but at 0,0.
314 DCHECK(gfx::Rect(child_size) == frame.render_pass_list.back()->output_rect);
315
316 // Make a size that covers from 0,0 and includes the area coming from the
317 // layer compositor.
318 gfx::Size display_size(sw_viewport_for_current_draw_.right(),
319 sw_viewport_for_current_draw_.bottom());
320 display_->Resize(display_size);
321
322 if (!root_local_surface_id_allocation_.IsValid() ||
323 display_size_ != display_size ||
324 device_scale_factor_ != frame.metadata.device_scale_factor) {
325 root_local_surface_id_allocator_.GenerateId();
326 root_local_surface_id_allocation_ =
327 root_local_surface_id_allocator_.GetCurrentLocalSurfaceIdAllocation();
328 display_size_ = display_size;
329 device_scale_factor_ = frame.metadata.device_scale_factor;
330 }
331
332 display_->SetLocalSurfaceId(
333 root_local_surface_id_allocation_.local_surface_id(),
334 frame.metadata.device_scale_factor);
335
336 // The offset for the child frame relative to the origin of the canvas being
337 // drawn into.
338 gfx::Transform child_transform;
339 child_transform.Translate(
340 gfx::Vector2dF(sw_viewport_for_current_draw_.OffsetFromOrigin()));
341
342 // Make a root frame that embeds the frame coming from the layer compositor
343 // and positions it based on the provided viewport.
344 // TODO(danakj): We could apply the transform here instead of passing it to
345 // the LayerTreeFrameSink client too? (We'd have to do the same for
346 // hardware frames in SurfacesInstance?)
347 viz::CompositorFrame embed_frame;
348 embed_frame.metadata.begin_frame_ack = frame.metadata.begin_frame_ack;
349 embed_frame.metadata.device_scale_factor =
350 frame.metadata.device_scale_factor;
351 embed_frame.render_pass_list.push_back(viz::RenderPass::Create());
352
353 // The embedding RenderPass covers the entire Display's area.
354 const auto& embed_render_pass = embed_frame.render_pass_list.back();
355 embed_render_pass->SetNew(1, gfx::Rect(display_size),
356 gfx::Rect(display_size), gfx::Transform());
357 embed_render_pass->has_transparent_background = false;
358
359 // The RenderPass has a single SurfaceDrawQuad (and SharedQuadState for it).
360 bool are_contents_opaque =
361 !frame.render_pass_list.back()->has_transparent_background;
362 auto* shared_quad_state =
363 embed_render_pass->CreateAndAppendSharedQuadState();
364 auto* surface_quad =
365 embed_render_pass->CreateAndAppendDrawQuad<viz::SurfaceDrawQuad>();
366 shared_quad_state->SetAll(
367 child_transform, gfx::Rect(child_size), gfx::Rect(child_size),
368 gfx::RRectF() /* rounded_corner_bounds */, gfx::Rect() /* clip_rect */,
369 false /* is_clipped */, are_contents_opaque /* are_contents_opaque */,
370 1.f /* opacity */, SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
371 surface_quad->SetNew(
372 shared_quad_state, gfx::Rect(child_size), gfx::Rect(child_size),
373 viz::SurfaceRange(
374 base::nullopt,
375 viz::SurfaceId(
376 kChildFrameSinkId,
377 child_local_surface_id_allocation_.local_surface_id())),
378 SK_ColorWHITE, false /* stretch_content_to_fill_bounds */);
379
380 child_support_->SubmitCompositorFrame(
381 child_local_surface_id_allocation_.local_surface_id(),
382 std::move(frame));
383 root_support_->SubmitCompositorFrame(
384 root_local_surface_id_allocation_.local_surface_id(),
385 std::move(embed_frame));
386 display_->DrawAndSwap(base::TimeTicks::Now());
387
388 // We don't track metrics for frames submitted to |display_| but it still
389 // expects that every frame will receive a swap ack and presentation
390 // feedback so we send null signals here.
391 display_->DidReceiveSwapBuffersAck(gfx::SwapTimings());
392 display_->DidReceivePresentationFeedback(
393 gfx::PresentationFeedback::Failure());
394 } else {
395 frame.metadata.local_surface_id_allocation_time =
396 child_local_surface_id_allocation_.allocation_time();
397
398 if (viz_frame_submission_enabled_) {
399 frame.metadata.begin_frame_ack =
400 viz::BeginFrameAck::CreateManualAckWithDamage();
401
402 // For hardware draws with viz we send frame to compositor_frame_sink_
403 compositor_frame_sink_->SubmitCompositorFrame(
404 local_surface_id_, std::move(frame), client_->BuildHitTestData(), 0);
405 } else {
406 // For hardware draws without viz we send the whole frame to the client so
407 // it can draw the content in it.
408 submit_frame = std::move(frame);
409 }
410 }
411 // NOTE: submit_frame will be empty if viz_frame_submission_enabled_ enabled,
412 // but it won't be used upstream
413 sync_client_->SubmitCompositorFrame(layer_tree_frame_sink_id_,
414 std::move(submit_frame),
415 client_->BuildHitTestData());
416 did_submit_frame_ = true;
417 }
418
DidNotProduceFrame(const viz::BeginFrameAck & ack)419 void SynchronousLayerTreeFrameSink::DidNotProduceFrame(
420 const viz::BeginFrameAck& ack) {
421 // We do not call CompositorFrameSink::DidNotProduceFrame here because
422 // submission of frame depends on DemandDraw calls. DidNotProduceFrame will be
423 // called there or during OnBeginFrame as fallback.
424 }
425
DidAllocateSharedBitmap(base::ReadOnlySharedMemoryRegion region,const viz::SharedBitmapId & id)426 void SynchronousLayerTreeFrameSink::DidAllocateSharedBitmap(
427 base::ReadOnlySharedMemoryRegion region,
428 const viz::SharedBitmapId& id) {
429 // Webview does not use software compositing (other than resourceless draws,
430 // but this is called for software /resources/).
431 NOTREACHED();
432 }
433
DidDeleteSharedBitmap(const viz::SharedBitmapId & id)434 void SynchronousLayerTreeFrameSink::DidDeleteSharedBitmap(
435 const viz::SharedBitmapId& id) {
436 // Webview does not use software compositing (other than resourceless draws,
437 // but this is called for software /resources/).
438 NOTREACHED();
439 }
440
Invalidate(bool needs_draw)441 void SynchronousLayerTreeFrameSink::Invalidate(bool needs_draw) {
442 DCHECK(CalledOnValidThread());
443 if (sync_client_)
444 sync_client_->Invalidate(needs_draw);
445 }
446
DemandDrawHw(const gfx::Size & viewport_size,const gfx::Rect & viewport_rect_for_tile_priority,const gfx::Transform & transform_for_tile_priority)447 void SynchronousLayerTreeFrameSink::DemandDrawHw(
448 const gfx::Size& viewport_size,
449 const gfx::Rect& viewport_rect_for_tile_priority,
450 const gfx::Transform& transform_for_tile_priority) {
451 DCHECK(CalledOnValidThread());
452 DCHECK(HasClient());
453 DCHECK(context_provider_.get());
454
455 client_->SetExternalTilePriorityConstraints(viewport_rect_for_tile_priority,
456 transform_for_tile_priority);
457 InvokeComposite(gfx::Transform(), gfx::Rect(viewport_size));
458 }
459
DemandDrawSw(SkCanvas * canvas)460 void SynchronousLayerTreeFrameSink::DemandDrawSw(SkCanvas* canvas) {
461 DCHECK(CalledOnValidThread());
462 DCHECK(canvas);
463 DCHECK(!current_sw_canvas_);
464
465 base::AutoReset<SkCanvas*> canvas_resetter(¤t_sw_canvas_, canvas);
466
467 SkIRect canvas_clip = canvas->getDeviceClipBounds();
468 gfx::Rect viewport = gfx::SkIRectToRect(canvas_clip);
469
470 gfx::Transform transform(gfx::Transform::kSkipInitialization);
471 transform.matrix() = canvas->getTotalMatrix(); // Converts 3x3 matrix to 4x4.
472
473 // We will resize the Display to ensure it covers the entire |viewport|, so
474 // save it for later.
475 sw_viewport_for_current_draw_ = viewport;
476
477 base::AutoReset<bool> set_in_software_draw(&in_software_draw_, true);
478 InvokeComposite(transform, viewport);
479 }
480
WillSkipDraw()481 void SynchronousLayerTreeFrameSink::WillSkipDraw() {
482 client_->OnDraw(gfx::Transform(), gfx::Rect(), in_software_draw_,
483 true /*skip_draw*/);
484 }
485
InvokeComposite(const gfx::Transform & transform,const gfx::Rect & viewport)486 void SynchronousLayerTreeFrameSink::InvokeComposite(
487 const gfx::Transform& transform,
488 const gfx::Rect& viewport) {
489 did_submit_frame_ = false;
490 // Adjust transform so that the layer compositor draws the |viewport| rect
491 // at its origin. The offset of the |viewport| we pass to the layer compositor
492 // must also be zero, since the rect needs to be in the coordinates of the
493 // layer compositor.
494 gfx::Transform adjusted_transform = transform;
495 adjusted_transform.matrix().postTranslate(-viewport.x(), -viewport.y(), 0);
496 // Don't propagate the viewport origin, as it will affect the clip rect.
497 client_->OnDraw(adjusted_transform, gfx::Rect(viewport.size()),
498 in_software_draw_, false /*skip_draw*/);
499
500 if (did_submit_frame_) {
501 // This must happen after unwinding the stack and leaving the compositor.
502 // Usually it is a separate task but we just defer it until OnDraw
503 // completes instead.
504 client_->DidReceiveCompositorFrameAck();
505 }
506 }
507
ReclaimResources(uint32_t layer_tree_frame_sink_id,const std::vector<viz::ReturnedResource> & resources)508 void SynchronousLayerTreeFrameSink::ReclaimResources(
509 uint32_t layer_tree_frame_sink_id,
510 const std::vector<viz::ReturnedResource>& resources) {
511 // Ignore message if it's a stale one coming from a different output surface
512 // (e.g. after a lost context).
513 if (layer_tree_frame_sink_id != layer_tree_frame_sink_id_)
514 return;
515 client_->ReclaimResources(resources);
516 }
517
SetMemoryPolicy(size_t bytes_limit)518 void SynchronousLayerTreeFrameSink::SetMemoryPolicy(size_t bytes_limit) {
519 DCHECK(CalledOnValidThread());
520 bool became_zero = memory_policy_.bytes_limit_when_visible && !bytes_limit;
521 bool became_non_zero =
522 !memory_policy_.bytes_limit_when_visible && bytes_limit;
523 memory_policy_.bytes_limit_when_visible = bytes_limit;
524 memory_policy_.num_resources_limit = kNumResourcesLimit;
525
526 if (client_)
527 client_->SetMemoryPolicy(memory_policy_);
528
529 if (became_zero) {
530 // This is small hack to drop context resources without destroying it
531 // when this compositor is put into the background.
532 context_provider()->ContextSupport()->SetAggressivelyFreeResources(
533 true /* aggressively_free_resources */);
534 } else if (became_non_zero) {
535 context_provider()->ContextSupport()->SetAggressivelyFreeResources(
536 false /* aggressively_free_resources */);
537 }
538 }
539
DidActivatePendingTree()540 void SynchronousLayerTreeFrameSink::DidActivatePendingTree() {
541 DCHECK(CalledOnValidThread());
542 if (sync_client_)
543 sync_client_->DidActivatePendingTree();
544 DeliverMessages();
545 }
546
DeliverMessages()547 void SynchronousLayerTreeFrameSink::DeliverMessages() {
548 std::vector<std::unique_ptr<IPC::Message>> messages;
549 std::unique_ptr<FrameSwapMessageQueue::SendMessageScope> send_message_scope =
550 frame_swap_message_queue_->AcquireSendMessageScope();
551 frame_swap_message_queue_->DrainMessages(&messages);
552 for (auto& msg : messages) {
553 Send(msg.release());
554 }
555 }
556
Send(IPC::Message * message)557 bool SynchronousLayerTreeFrameSink::Send(IPC::Message* message) {
558 DCHECK(CalledOnValidThread());
559 return sender_->Send(message);
560 }
561
CalledOnValidThread() const562 bool SynchronousLayerTreeFrameSink::CalledOnValidThread() const {
563 return thread_checker_.CalledOnValidThread();
564 }
565
DidReceiveCompositorFrameAck(const std::vector<viz::ReturnedResource> & resources)566 void SynchronousLayerTreeFrameSink::DidReceiveCompositorFrameAck(
567 const std::vector<viz::ReturnedResource>& resources) {
568 DCHECK(CalledOnValidThread());
569 DCHECK(viz_frame_submission_enabled_);
570 client_->ReclaimResources(resources);
571 // client_->DidReceiveCompositorFrameAck() is called just after frame
572 // submission so cc won't be throttled on actual draw which can happen late
573 // (or not happen at all) for WebView.
574 }
575
OnBeginFrame(const viz::BeginFrameArgs & args,const viz::FrameTimingDetailsMap & timing_details)576 void SynchronousLayerTreeFrameSink::OnBeginFrame(
577 const viz::BeginFrameArgs& args,
578 const viz::FrameTimingDetailsMap& timing_details) {
579 DCHECK(viz_frame_submission_enabled_);
580
581 // We do not receive BeginFrames via CompositorFrameSink, so we do not forward
582 // it to cc. We still might get one with FrameTimingDetailsMap, so we report
583 // it here.
584
585 if (client_) {
586 for (const auto& pair : timing_details) {
587 client_->DidPresentCompositorFrame(pair.first, pair.second);
588 }
589 }
590 }
591
ReclaimResources(const std::vector<viz::ReturnedResource> & resources)592 void SynchronousLayerTreeFrameSink::ReclaimResources(
593 const std::vector<viz::ReturnedResource>& resources) {
594 DCHECK(CalledOnValidThread());
595 DCHECK(viz_frame_submission_enabled_);
596 client_->ReclaimResources(resources);
597 }
598
OnBeginFramePausedChanged(bool paused)599 void SynchronousLayerTreeFrameSink::OnBeginFramePausedChanged(bool paused) {
600 DCHECK(viz_frame_submission_enabled_);
601 }
602
OnNeedsBeginFrames(bool needs_begin_frames)603 void SynchronousLayerTreeFrameSink::OnNeedsBeginFrames(
604 bool needs_begin_frames) {
605 needs_begin_frames_ = needs_begin_frames;
606 if (sync_client_) {
607 sync_client_->SetNeedsBeginFrames(needs_begin_frames);
608 }
609 }
610
DidPresentCompositorFrame(const viz::FrameTimingDetailsMap & timing_details)611 void SynchronousLayerTreeFrameSink::DidPresentCompositorFrame(
612 const viz::FrameTimingDetailsMap& timing_details) {
613 DCHECK(!viz_frame_submission_enabled_ || timing_details.empty());
614
615 if (!client_)
616 return;
617 for (const auto& pair : timing_details)
618 client_->DidPresentCompositorFrame(pair.first, pair.second);
619 }
620
BeginFrame(const viz::BeginFrameArgs & args)621 void SynchronousLayerTreeFrameSink::BeginFrame(
622 const viz::BeginFrameArgs& args) {
623 if (external_begin_frame_source_)
624 external_begin_frame_source_->OnBeginFrame(args);
625 }
626
SetBeginFrameSourcePaused(bool paused)627 void SynchronousLayerTreeFrameSink::SetBeginFrameSourcePaused(bool paused) {
628 if (external_begin_frame_source_)
629 external_begin_frame_source_->OnSetBeginFrameSourcePaused(paused);
630 }
631
632 } // namespace content
633