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>(&current_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(&current_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