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