[go: nahoru, domu]

blob: 2237321bbecd78789b5ba388b00bd6ab8cd69452 [file] [log] [blame]
joth@chromium.org913d99a2013-05-31 07:16:071// Copyright 2013 The Chromium Authors. All rights reserved.
joth@chromium.orgeeb93112013-05-01 19:41:102// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
danakjc7afae52017-06-20 21:12:415#include "content/renderer/android/synchronous_layer_tree_frame_sink.h"
joth@chromium.orgeeb93112013-05-01 19:41:106
boliu5965c8d12016-05-13 23:58:197#include <vector>
8
joth@chromium.org3611c4b42013-06-22 07:06:149#include "base/auto_reset.h"
fdoray7a8954a42016-06-07 04:28:3810#include "base/location.h"
joth@chromium.orgeeb93112013-05-01 19:41:1011#include "base/logging.h"
avi1023d012015-12-25 02:39:1412#include "base/macros.h"
hajimehoshiea85b9dc2016-05-25 09:52:3113#include "base/memory/ptr_util.h"
fdoray7a8954a42016-06-07 04:28:3814#include "base/single_thread_task_runner.h"
15#include "base/threading/thread_task_runner_handle.h"
joth@chromium.org1d0a6b82013-05-16 09:03:1116#include "cc/output/compositor_frame.h"
boliu@chromium.org19e43c52013-06-08 16:46:0217#include "cc/output/context_provider.h"
danakjc7afae52017-06-20 21:12:4118#include "cc/output/layer_tree_frame_sink_client.h"
danakj1120f4c2016-09-15 02:05:3219#include "cc/output/output_surface.h"
kylechar5344b39e2016-10-06 23:51:1920#include "cc/output/output_surface_frame.h"
danakj554c98a2016-07-08 00:25:0721#include "cc/output/renderer_settings.h"
joth@chromium.org1d0a6b82013-05-16 09:03:1122#include "cc/output/software_output_device.h"
danakj554c98a2016-07-08 00:25:0723#include "cc/output/texture_mailbox_deleter.h"
danakje9e89612016-10-04 22:16:2624#include "cc/quads/render_pass.h"
25#include "cc/quads/surface_draw_quad.h"
samans923a54c2017-02-13 22:19:2226#include "cc/surfaces/compositor_frame_sink_support.h"
danakj554c98a2016-07-08 00:25:0727#include "cc/surfaces/display.h"
xing.xu1a9aa94c2017-02-23 21:04:3228#include "cc/surfaces/local_surface_id_allocator.h"
danakj554c98a2016-07-08 00:25:0729#include "cc/surfaces/surface_manager.h"
boliuec72a2ed2016-05-10 00:51:5630#include "content/common/android/sync_compositor_messages.h"
eseckler9404a232017-05-22 14:49:4331#include "content/common/view_messages.h"
boliu42e01312016-05-12 21:47:5232#include "content/renderer/android/synchronous_compositor_filter.h"
boliudff26352015-10-12 23:47:0733#include "content/renderer/android/synchronous_compositor_registry.h"
mkosiba@chromium.org586871b2014-07-22 17:05:1134#include "content/renderer/gpu/frame_swap_message_queue.h"
boliu42e01312016-05-12 21:47:5235#include "content/renderer/render_thread_impl.h"
boliub032a082015-06-05 20:03:1536#include "gpu/command_buffer/client/context_support.h"
jamesr@chromium.orga770f2a2014-01-07 22:29:2337#include "gpu/command_buffer/client/gles2_interface.h"
jamesr@chromium.orgf44d5552013-10-29 04:56:2938#include "gpu/command_buffer/common/gpu_memory_allocation.h"
boliuec72a2ed2016-05-10 00:51:5639#include "ipc/ipc_message.h"
40#include "ipc/ipc_message_macros.h"
boliu42e01312016-05-12 21:47:5241#include "ipc/ipc_sender.h"
joth@chromium.orgeeb93112013-05-01 19:41:1042#include "third_party/skia/include/core/SkCanvas.h"
tfarina3b0452d2014-12-31 15:20:0943#include "ui/gfx/geometry/rect_conversions.h"
joth@chromium.org1d0a6b82013-05-16 09:03:1144#include "ui/gfx/skia_util.h"
boliu@chromium.orga1811b8912013-05-09 15:35:1945#include "ui/gfx/transform.h"
boliu@chromium.orga1811b8912013-05-09 15:35:1946
joth@chromium.orgeeb93112013-05-01 19:41:1047namespace content {
joth@chromium.org1d0a6b82013-05-16 09:03:1148
boliu@chromium.orga1811b8912013-05-09 15:35:1949namespace {
50
tobiasjs3fd0c952016-03-17 10:51:4051const int64_t kFallbackTickTimeoutInMilliseconds = 100;
samans46b4f4072016-11-28 21:47:1352const cc::FrameSinkId kRootFrameSinkId(1, 1);
53const cc::FrameSinkId kChildFrameSinkId(1, 2);
tobiasjs3fd0c952016-03-17 10:51:4054
boliu77de0212014-10-28 04:06:3355// Do not limit number of resources, so use an unrealistically high value.
56const size_t kNumResourcesLimit = 10 * 1000 * 1000;
57
danakj554c98a2016-07-08 00:25:0758class SoftwareDevice : public cc::SoftwareOutputDevice {
joth@chromium.org1d0a6b82013-05-16 09:03:1159 public:
danakj554c98a2016-07-08 00:25:0760 SoftwareDevice(SkCanvas** canvas) : canvas_(canvas) {}
61
danakj70ffc43c2016-10-10 21:47:3062 void Resize(const gfx::Size& pixel_size, float device_scale_factor) override {
joth@chromium.org1d0a6b82013-05-16 09:03:1163 // Intentional no-op: canvas size is controlled by the embedder.
64 }
dchengf0217ba2015-02-05 19:26:3365 SkCanvas* BeginPaint(const gfx::Rect& damage_rect) override {
danakj554c98a2016-07-08 00:25:0766 DCHECK(*canvas_) << "BeginPaint with no canvas set";
67 return *canvas_;
joth@chromium.org1d0a6b82013-05-16 09:03:1168 }
jbauman95f741352015-08-07 02:10:3469 void EndPaint() override {}
joth@chromium.org1d0a6b82013-05-16 09:03:1170
71 private:
danakj554c98a2016-07-08 00:25:0772 SkCanvas** canvas_;
joth@chromium.org1d0a6b82013-05-16 09:03:1173
74 DISALLOW_COPY_AND_ASSIGN(SoftwareDevice);
75};
76
boliu4dae5222016-07-28 00:09:4577} // namespace
78
danakjc7afae52017-06-20 21:12:4179class SynchronousLayerTreeFrameSink::SoftwareOutputSurface
boliu4dae5222016-07-28 00:09:4580 : public cc::OutputSurface {
danakj554c98a2016-07-08 00:25:0781 public:
82 SoftwareOutputSurface(std::unique_ptr<SoftwareDevice> software_device)
danakje41d978a2016-09-19 21:09:2883 : cc::OutputSurface(std::move(software_device)) {}
danakj554c98a2016-07-08 00:25:0784
85 // cc::OutputSurface implementation.
danakj94486a42016-10-25 22:31:1286 void BindToClient(cc::OutputSurfaceClient* client) override {}
danakj1c77b832016-09-26 21:26:0987 void EnsureBackbuffer() override {}
88 void DiscardBackbuffer() override {}
89 void BindFramebuffer() override {}
jbauman2a2ad222017-03-02 00:35:1390 void SetDrawRectangle(const gfx::Rect& rect) override {}
kylechar5344b39e2016-10-06 23:51:1991 void SwapBuffers(cc::OutputSurfaceFrame frame) override {}
boliu4dae5222016-07-28 00:09:4592 void Reshape(const gfx::Size& size,
93 float scale_factor,
94 const gfx::ColorSpace& color_space,
reveman9413cff2017-01-18 03:05:4895 bool has_alpha,
96 bool use_stencil) override {}
danakj1c77b832016-09-26 21:26:0997 uint32_t GetFramebufferCopyTextureFormat() override { return 0; }
98 cc::OverlayCandidateValidator* GetOverlayCandidateValidator() const override {
99 return nullptr;
100 }
101 bool IsDisplayedAsOverlayPlane() const override { return false; }
102 unsigned GetOverlayTextureId() const override { return 0; }
103 bool SurfaceIsSuspendForRecycle() const override { return false; }
104 bool HasExternalStencilTest() const override { return false; }
105 void ApplyExternalStencil() override {}
danakj554c98a2016-07-08 00:25:07106};
107
danakjc7afae52017-06-20 21:12:41108SynchronousLayerTreeFrameSink::SynchronousLayerTreeFrameSink(
hajimehoshiea85b9dc2016-05-25 09:52:31109 scoped_refptr<cc::ContextProvider> context_provider,
110 scoped_refptr<cc::ContextProvider> worker_context_provider,
pimanc44437a22016-10-29 00:09:22111 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
danakje9cf5812017-02-16 22:22:55112 cc::SharedBitmapManager* shared_bitmap_manager,
mkosiba@chromium.org586871b2014-07-22 17:05:11113 int routing_id,
danakjc7afae52017-06-20 21:12:41114 uint32_t layer_tree_frame_sink_id,
enne077ba4862016-09-12 20:59:53115 std::unique_ptr<cc::BeginFrameSource> begin_frame_source,
boliudff26352015-10-12 23:47:07116 SynchronousCompositorRegistry* registry,
mkosiba@chromium.org586871b2014-07-22 17:05:11117 scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue)
danakjc7afae52017-06-20 21:12:41118 : cc::LayerTreeFrameSink(std::move(context_provider),
119 std::move(worker_context_provider),
120 gpu_memory_buffer_manager,
121 nullptr),
joth@chromium.org913d99a2013-05-31 07:16:07122 routing_id_(routing_id),
danakjc7afae52017-06-20 21:12:41123 layer_tree_frame_sink_id_(layer_tree_frame_sink_id),
boliudff26352015-10-12 23:47:07124 registry_(registry),
danakje9cf5812017-02-16 22:22:55125 shared_bitmap_manager_(shared_bitmap_manager),
boliu42e01312016-05-12 21:47:52126 sender_(RenderThreadImpl::current()->sync_compositor_message_filter()),
boliudff26352015-10-12 23:47:07127 memory_policy_(0u),
tobiasjs3fd0c952016-03-17 10:51:40128 frame_swap_message_queue_(frame_swap_message_queue),
danakj554c98a2016-07-08 00:25:07129 surface_manager_(new cc::SurfaceManager),
xing.xu1a9aa94c2017-02-23 21:04:32130 local_surface_id_allocator_(new cc::LocalSurfaceIdAllocator()),
enne077ba4862016-09-12 20:59:53131 begin_frame_source_(std::move(begin_frame_source)) {
boliudff26352015-10-12 23:47:07132 DCHECK(registry_);
boliu42e01312016-05-12 21:47:52133 DCHECK(sender_);
enne077ba4862016-09-12 20:59:53134 DCHECK(begin_frame_source_);
boliu42e01312016-05-12 21:47:52135 thread_checker_.DetachFromThread();
boliu@chromium.org18a862a2013-10-02 10:10:55136 memory_policy_.priority_cutoff_when_visible =
jamesr@chromium.orgf44d5552013-10-29 04:56:29137 gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
joth@chromium.orgeeb93112013-05-01 19:41:10138}
139
danakjc7afae52017-06-20 21:12:41140SynchronousLayerTreeFrameSink::~SynchronousLayerTreeFrameSink() = default;
boliudff26352015-10-12 23:47:07141
danakjc7afae52017-06-20 21:12:41142void SynchronousLayerTreeFrameSink::SetSyncClient(
143 SynchronousLayerTreeFrameSinkClient* compositor) {
boliudff26352015-10-12 23:47:07144 DCHECK(CalledOnValidThread());
145 sync_client_ = compositor;
hush90144532016-06-08 02:09:48146 if (sync_client_)
danakjc7afae52017-06-20 21:12:41147 Send(new SyncCompositorHostMsg_LayerTreeFrameSinkCreated(routing_id_));
joth@chromium.orgeeb93112013-05-01 19:41:10148}
149
danakjc7afae52017-06-20 21:12:41150bool SynchronousLayerTreeFrameSink::OnMessageReceived(
boliuec72a2ed2016-05-10 00:51:56151 const IPC::Message& message) {
152 bool handled = true;
danakjc7afae52017-06-20 21:12:41153 IPC_BEGIN_MESSAGE_MAP(SynchronousLayerTreeFrameSink, message)
boliu42e01312016-05-12 21:47:52154 IPC_MESSAGE_HANDLER(SyncCompositorMsg_SetMemoryPolicy, SetMemoryPolicy)
boliuec72a2ed2016-05-10 00:51:56155 IPC_MESSAGE_HANDLER(SyncCompositorMsg_ReclaimResources, OnReclaimResources)
156 IPC_MESSAGE_UNHANDLED(handled = false)
157 IPC_END_MESSAGE_MAP()
158 return handled;
159}
160
danakjc7afae52017-06-20 21:12:41161bool SynchronousLayerTreeFrameSink::BindToClient(
162 cc::LayerTreeFrameSinkClient* sink_client) {
joth@chromium.orgeeb93112013-05-01 19:41:10163 DCHECK(CalledOnValidThread());
danakjc7afae52017-06-20 21:12:41164 if (!cc::LayerTreeFrameSink::BindToClient(sink_client))
joth@chromium.orgeeb93112013-05-01 19:41:10165 return false;
boliu@chromium.org0552c8e2013-09-10 22:44:43166
enne077ba4862016-09-12 20:59:53167 DCHECK(begin_frame_source_);
168 client_->SetBeginFrameSource(begin_frame_source_.get());
sunnypseab5ac92015-04-02 20:26:13169 client_->SetMemoryPolicy(memory_policy_);
boliu5965c8d12016-05-13 23:58:19170 client_->SetTreeActivationCallback(
danakjc7afae52017-06-20 21:12:41171 base::Bind(&SynchronousLayerTreeFrameSink::DidActivatePendingTree,
boliu5965c8d12016-05-13 23:58:19172 base::Unretained(this)));
danakjc7afae52017-06-20 21:12:41173 registry_->RegisterLayerTreeFrameSink(routing_id_, this);
danakj554c98a2016-07-08 00:25:07174
starazf4a164c2017-02-14 21:10:33175 constexpr bool root_support_is_root = true;
176 constexpr bool child_support_is_root = false;
177 constexpr bool handles_frame_sink_id_invalidation = true;
178 constexpr bool needs_sync_points = true;
staraz962f61092017-04-12 00:13:53179 root_support_ = cc::CompositorFrameSinkSupport::Create(
starazf4a164c2017-02-14 21:10:33180 this, surface_manager_.get(), kRootFrameSinkId, root_support_is_root,
staraz962f61092017-04-12 00:13:53181 handles_frame_sink_id_invalidation, needs_sync_points);
182 child_support_ = cc::CompositorFrameSinkSupport::Create(
starazf4a164c2017-02-14 21:10:33183 this, surface_manager_.get(), kChildFrameSinkId, child_support_is_root,
staraz962f61092017-04-12 00:13:53184 handles_frame_sink_id_invalidation, needs_sync_points);
danakj554c98a2016-07-08 00:25:07185
186 cc::RendererSettings software_renderer_settings;
187
danakje9e89612016-10-04 22:16:26188 auto output_surface = base::MakeUnique<SoftwareOutputSurface>(
189 base::MakeUnique<SoftwareDevice>(&current_sw_canvas_));
190 software_output_surface_ = output_surface.get();
boliu4dae5222016-07-28 00:09:45191
danakje9cf5812017-02-16 22:22:55192 // The gpu_memory_buffer_manager here is null as the Display is only used for
193 // resourcesless software draws, where no resources are included in the frame
194 // swapped from the compositor. So there is no need for it.
195 // The shared_bitmap_manager_ is provided for the Display to allocate
196 // resources.
197 // TODO(crbug.com/692814): The Display never sends its resources out of
198 // process so there is no reason for it to use a SharedBitmapManager.
danakj554c98a2016-07-08 00:25:07199 display_.reset(new cc::Display(
danakje9cf5812017-02-16 22:22:55200 shared_bitmap_manager_, nullptr /* gpu_memory_buffer_manager */,
Alex Zhangd3b9d652017-06-09 18:48:55201 software_renderer_settings, kRootFrameSinkId, std::move(output_surface),
danakje9cf5812017-02-16 22:22:55202 nullptr /* scheduler */, nullptr /* texture_mailbox_deleter */));
starazc9bab212016-11-10 19:27:39203 display_->Initialize(&display_client_, surface_manager_.get());
danakj6f2861b2016-08-17 02:10:17204 display_->SetVisible(true);
joth@chromium.orgeeb93112013-05-01 19:41:10205 return true;
206}
207
danakjc7afae52017-06-20 21:12:41208void SynchronousLayerTreeFrameSink::DetachFromClient() {
revemand180dfc32015-09-24 00:19:43209 DCHECK(CalledOnValidThread());
enne077ba4862016-09-12 20:59:53210 client_->SetBeginFrameSource(nullptr);
211 // Destroy the begin frame source on the same thread it was bound on.
212 begin_frame_source_ = nullptr;
danakjc7afae52017-06-20 21:12:41213 registry_->UnregisterLayerTreeFrameSink(routing_id_, this);
boliu5965c8d12016-05-13 23:58:19214 client_->SetTreeActivationCallback(base::Closure());
samans923a54c2017-02-13 22:19:22215 root_support_.reset();
216 child_support_.reset();
danakje9e89612016-10-04 22:16:26217 software_output_surface_ = nullptr;
danakj554c98a2016-07-08 00:25:07218 display_ = nullptr;
xing.xu1a9aa94c2017-02-23 21:04:32219 local_surface_id_allocator_ = nullptr;
danakj554c98a2016-07-08 00:25:07220 surface_manager_ = nullptr;
danakjc7afae52017-06-20 21:12:41221 cc::LayerTreeFrameSink::DetachFromClient();
tobiasjs3fd0c952016-03-17 10:51:40222 CancelFallbackTick();
revemand180dfc32015-09-24 00:19:43223}
224
danakjc7afae52017-06-20 21:12:41225void SynchronousLayerTreeFrameSink::SubmitCompositorFrame(
danakj9d124422016-10-14 03:15:08226 cc::CompositorFrame frame) {
boliu@chromium.org0552c8e2013-09-10 22:44:43227 DCHECK(CalledOnValidThread());
boliu6c0ed632015-12-29 22:45:59228 DCHECK(sync_client_);
danakj554c98a2016-07-08 00:25:07229
danakjff780202016-07-08 01:07:26230 if (fallback_tick_running_) {
samansce5c3c32016-11-18 13:47:34231 DCHECK(frame.resource_list.empty());
danakjff780202016-07-08 01:07:26232 cc::ReturnedResourceArray return_resources;
samans923a54c2017-02-13 22:19:22233 ReclaimResources(return_resources);
danakj9d124422016-10-14 03:15:08234 did_submit_frame_ = true;
danakjff780202016-07-08 01:07:26235 return;
236 }
237
danakj9d124422016-10-14 03:15:08238 cc::CompositorFrame submit_frame;
danakj554c98a2016-07-08 00:25:07239
240 if (in_software_draw_) {
241 // The frame we send to the client is actually just the metadata. Preserve
242 // the |frame| for the software path below.
danakj9d124422016-10-14 03:15:08243 submit_frame.metadata = frame.metadata.Clone();
danakj554c98a2016-07-08 00:25:07244
danakje9e89612016-10-04 22:16:26245 // The layer compositor should be giving a frame that covers the
246 // |sw_viewport_for_current_draw_| but at 0,0.
247 gfx::Size child_size = sw_viewport_for_current_draw_.size();
samansce5c3c32016-11-18 13:47:34248 DCHECK(gfx::Rect(child_size) == frame.render_pass_list.back()->output_rect);
danakj554c98a2016-07-08 00:25:07249
danakje9e89612016-10-04 22:16:26250 // Make a size that covers from 0,0 and includes the area coming from the
251 // layer compositor.
252 gfx::Size display_size(sw_viewport_for_current_draw_.right(),
253 sw_viewport_for_current_draw_.bottom());
254 display_->Resize(display_size);
255
samanscf887b6f2017-05-24 18:14:29256 if (!root_local_surface_id_.is_valid() || display_size_ != display_size ||
257 device_scale_factor_ != frame.metadata.device_scale_factor) {
258 root_local_surface_id_ = local_surface_id_allocator_->GenerateId();
259 display_size_ = display_size;
260 device_scale_factor_ = frame.metadata.device_scale_factor;
261 }
262
263 if (!child_local_surface_id_.is_valid() || child_size_ != child_size ||
264 device_scale_factor_ != frame.metadata.device_scale_factor) {
265 child_local_surface_id_ = local_surface_id_allocator_->GenerateId();
266 child_size_ = child_size;
267 device_scale_factor_ = frame.metadata.device_scale_factor;
268 }
269
270 display_->SetLocalSurfaceId(root_local_surface_id_,
271 frame.metadata.device_scale_factor);
272
danakje9e89612016-10-04 22:16:26273 // The offset for the child frame relative to the origin of the canvas being
274 // drawn into.
275 gfx::Transform child_transform;
276 child_transform.Translate(
277 gfx::Vector2dF(sw_viewport_for_current_draw_.OffsetFromOrigin()));
278
279 // Make a root frame that embeds the frame coming from the layer compositor
280 // and positions it based on the provided viewport.
281 // TODO(danakj): We could apply the transform here instead of passing it to
danakjc7afae52017-06-20 21:12:41282 // the LayerTreeFrameSink client too? (We'd have to do the same for
danakje9e89612016-10-04 22:16:26283 // hardware frames in SurfacesInstance?)
284 cc::CompositorFrame embed_frame;
eseckler6a9efe9b2017-03-24 16:29:56285 embed_frame.metadata.begin_frame_ack = frame.metadata.begin_frame_ack;
samanscf887b6f2017-05-24 18:14:29286 embed_frame.metadata.device_scale_factor =
287 frame.metadata.device_scale_factor;
samansce5c3c32016-11-18 13:47:34288 embed_frame.render_pass_list.push_back(cc::RenderPass::Create());
danakje9e89612016-10-04 22:16:26289
290 // The embedding RenderPass covers the entire Display's area.
samansce5c3c32016-11-18 13:47:34291 const auto& embed_render_pass = embed_frame.render_pass_list.back();
ajumaa26e58452016-12-15 22:35:01292 embed_render_pass->SetNew(1, gfx::Rect(display_size),
293 gfx::Rect(display_size), gfx::Transform());
294 embed_render_pass->has_transparent_background = false;
danakje9e89612016-10-04 22:16:26295
296 // The RenderPass has a single SurfaceDrawQuad (and SharedQuadState for it).
297 auto* shared_quad_state =
298 embed_render_pass->CreateAndAppendSharedQuadState();
299 auto* surface_quad =
300 embed_render_pass->CreateAndAppendDrawQuad<cc::SurfaceDrawQuad>();
301 shared_quad_state->SetAll(
sunxdf0866592017-04-21 17:01:57302 child_transform, gfx::Rect(child_size), gfx::Rect(child_size),
danakje9e89612016-10-04 22:16:26303 gfx::Rect() /* clip_rect */, false /* is_clipped */, 1.f /* opacity */,
reedcc9c70f2016-11-22 04:26:01304 SkBlendMode::kSrcOver, 0 /* sorting_context_id */);
samans46b4f4072016-11-28 21:47:13305 surface_quad->SetNew(
306 shared_quad_state, gfx::Rect(child_size), gfx::Rect(child_size),
fsamuel1d3252c2017-02-15 20:56:37307 cc::SurfaceId(kChildFrameSinkId, child_local_surface_id_),
308 cc::SurfaceDrawQuadType::PRIMARY, nullptr);
danakje9e89612016-10-04 22:16:26309
samanscf887b6f2017-05-24 18:14:29310 bool result = child_support_->SubmitCompositorFrame(child_local_surface_id_,
311 std::move(frame));
312 DCHECK(result);
313 result = root_support_->SubmitCompositorFrame(root_local_surface_id_,
314 std::move(embed_frame));
315 DCHECK(result);
danakj554c98a2016-07-08 00:25:07316 display_->DrawAndSwap();
317 } else {
danakjff780202016-07-08 01:07:26318 // For hardware draws we send the whole frame to the client so it can draw
319 // the content in it.
danakj9d124422016-10-14 03:15:08320 submit_frame = std::move(frame);
danakj554c98a2016-07-08 00:25:07321 }
322
danakjc7afae52017-06-20 21:12:41323 sync_client_->SubmitCompositorFrame(layer_tree_frame_sink_id_,
danakj9d124422016-10-14 03:15:08324 std::move(submit_frame));
danakj9d124422016-10-14 03:15:08325 did_submit_frame_ = true;
boliu@chromium.orga1811b8912013-05-09 15:35:19326}
327
danakjc7afae52017-06-20 21:12:41328void SynchronousLayerTreeFrameSink::DidNotProduceFrame(
eseckler9404a232017-05-22 14:49:43329 const cc::BeginFrameAck& ack) {
330 DCHECK(!ack.has_damage);
331 DCHECK_LE(cc::BeginFrameArgs::kStartingFrameNumber, ack.sequence_number);
332 Send(new ViewHostMsg_DidNotProduceFrame(routing_id_, ack));
333}
334
danakjc7afae52017-06-20 21:12:41335void SynchronousLayerTreeFrameSink::CancelFallbackTick() {
tobiasjs3fd0c952016-03-17 10:51:40336 fallback_tick_.Cancel();
337 fallback_tick_pending_ = false;
338}
339
danakjc7afae52017-06-20 21:12:41340void SynchronousLayerTreeFrameSink::FallbackTickFired() {
tobiasjs3fd0c952016-03-17 10:51:40341 DCHECK(CalledOnValidThread());
danakjc7afae52017-06-20 21:12:41342 TRACE_EVENT0("renderer", "SynchronousLayerTreeFrameSink::FallbackTickFired");
tobiasjs3fd0c952016-03-17 10:51:40343 base::AutoReset<bool> in_fallback_tick(&fallback_tick_running_, true);
samans26510e442017-06-01 22:29:12344 frame_swap_message_queue_->NotifyFramesAreDiscarded(true);
tobiasjs3fd0c952016-03-17 10:51:40345 SkBitmap bitmap;
346 bitmap.allocN32Pixels(1, 1);
347 bitmap.eraseColor(0);
348 SkCanvas canvas(bitmap);
349 fallback_tick_pending_ = false;
350 DemandDrawSw(&canvas);
samans26510e442017-06-01 22:29:12351 frame_swap_message_queue_->NotifyFramesAreDiscarded(false);
tobiasjs3fd0c952016-03-17 10:51:40352}
353
danakjc7afae52017-06-20 21:12:41354void SynchronousLayerTreeFrameSink::Invalidate() {
sunnypseab5ac92015-04-02 20:26:13355 DCHECK(CalledOnValidThread());
boliudff26352015-10-12 23:47:07356 if (sync_client_)
357 sync_client_->Invalidate();
tobiasjs3fd0c952016-03-17 10:51:40358
359 if (!fallback_tick_pending_) {
360 fallback_tick_.Reset(
danakjc7afae52017-06-20 21:12:41361 base::Bind(&SynchronousLayerTreeFrameSink::FallbackTickFired,
tobiasjs3fd0c952016-03-17 10:51:40362 base::Unretained(this)));
fdoray7a8954a42016-06-07 04:28:38363 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
tobiasjs3fd0c952016-03-17 10:51:40364 FROM_HERE, fallback_tick_.callback(),
365 base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds));
366 fallback_tick_pending_ = true;
367 }
boliu94f592a2014-11-21 21:18:40368}
369
danakjc7afae52017-06-20 21:12:41370void SynchronousLayerTreeFrameSink::DemandDrawHw(
boliu31c233ed2016-07-29 05:38:59371 const gfx::Size& viewport_size,
boliu6d9425ec72015-10-28 21:38:34372 const gfx::Rect& viewport_rect_for_tile_priority,
hush@chromium.orgbd5324592014-07-31 09:09:33373 const gfx::Transform& transform_for_tile_priority) {
boliu@chromium.org19e43c52013-06-08 16:46:02374 DCHECK(CalledOnValidThread());
brianderson@chromium.org049fc7a2013-06-18 12:32:35375 DCHECK(HasClient());
dcheng165763c2014-10-07 04:14:54376 DCHECK(context_provider_.get());
tobiasjs3fd0c952016-03-17 10:51:40377 CancelFallbackTick();
boliu@chromium.org19e43c52013-06-08 16:46:02378
boliu7097ee5b2015-12-17 03:16:09379 client_->SetExternalTilePriorityConstraints(viewport_rect_for_tile_priority,
380 transform_for_tile_priority);
boliu31c233ed2016-07-29 05:38:59381 InvokeComposite(gfx::Transform(), gfx::Rect(viewport_size));
boliu@chromium.org19e43c52013-06-08 16:46:02382}
383
danakjc7afae52017-06-20 21:12:41384void SynchronousLayerTreeFrameSink::DemandDrawSw(SkCanvas* canvas) {
joth@chromium.orgeeb93112013-05-01 19:41:10385 DCHECK(CalledOnValidThread());
joth@chromium.org1d0a6b82013-05-16 09:03:11386 DCHECK(canvas);
387 DCHECK(!current_sw_canvas_);
tobiasjs3fd0c952016-03-17 10:51:40388 CancelFallbackTick();
sunnypseab5ac92015-04-02 20:26:13389
joth@chromium.org3611c4b42013-06-22 07:06:14390 base::AutoReset<SkCanvas*> canvas_resetter(&current_sw_canvas_, canvas);
joth@chromium.org1d0a6b82013-05-16 09:03:11391
reed45325142017-01-27 13:00:07392 SkIRect canvas_clip = canvas->getDeviceClipBounds();
boliu31c233ed2016-07-29 05:38:59393 gfx::Rect viewport = gfx::SkIRectToRect(canvas_clip);
joth@chromium.org1d0a6b82013-05-16 09:03:11394
aelias@chromium.orgf224cc92013-06-06 23:23:32395 gfx::Transform transform(gfx::Transform::kSkipInitialization);
joth@chromium.org1d0a6b82013-05-16 09:03:11396 transform.matrix() = canvas->getTotalMatrix(); // Converts 3x3 matrix to 4x4.
397
danakje9e89612016-10-04 22:16:26398 // We will resize the Display to ensure it covers the entire |viewport|, so
399 // save it for later.
400 sw_viewport_for_current_draw_ = viewport;
401
danakj554c98a2016-07-08 00:25:07402 base::AutoReset<bool> set_in_software_draw(&in_software_draw_, true);
boliu31c233ed2016-07-29 05:38:59403 InvokeComposite(transform, viewport);
joth@chromium.orgeeb93112013-05-01 19:41:10404}
405
danakjc7afae52017-06-20 21:12:41406void SynchronousLayerTreeFrameSink::InvokeComposite(
aelias@chromium.org54af03522013-09-05 00:43:28407 const gfx::Transform& transform,
boliu31c233ed2016-07-29 05:38:59408 const gfx::Rect& viewport) {
danakj9d124422016-10-14 03:15:08409 did_submit_frame_ = false;
danakje9e89612016-10-04 22:16:26410 // Adjust transform so that the layer compositor draws the |viewport| rect
411 // at its origin. The offset of the |viewport| we pass to the layer compositor
412 // is ignored for drawing, so its okay to not match the transform.
413 // TODO(danakj): Why do we pass a viewport origin and then not really use it
414 // (only for comparing to the viewport passed in
415 // SetExternalTilePriorityConstraints), surely this could be more clear?
aelias@chromium.org54af03522013-09-05 00:43:28416 gfx::Transform adjusted_transform = transform;
boliudff26352015-10-12 23:47:07417 adjusted_transform.matrix().postTranslate(-viewport.x(), -viewport.y(), 0);
boliu31c233ed2016-07-29 05:38:59418 client_->OnDraw(adjusted_transform, viewport, in_software_draw_);
aelias@chromium.org54af03522013-09-05 00:43:28419
danakj9d124422016-10-14 03:15:08420 if (did_submit_frame_) {
danakj4600da12016-07-13 21:40:10421 // This must happen after unwinding the stack and leaving the compositor.
422 // Usually it is a separate task but we just defer it until OnDraw completes
423 // instead.
danakj9d124422016-10-14 03:15:08424 client_->DidReceiveCompositorFrameAck();
danakj4600da12016-07-13 21:40:10425 }
boliu@chromium.orga1811b8912013-05-09 15:35:19426}
427
danakjc7afae52017-06-20 21:12:41428void SynchronousLayerTreeFrameSink::OnReclaimResources(
429 uint32_t layer_tree_frame_sink_id,
fsamuelb62b78222016-07-15 01:14:14430 const cc::ReturnedResourceArray& resources) {
boliuec72a2ed2016-05-10 00:51:56431 // Ignore message if it's a stale one coming from a different output surface
432 // (e.g. after a lost context).
danakjc7afae52017-06-20 21:12:41433 if (layer_tree_frame_sink_id != layer_tree_frame_sink_id_)
boliuec72a2ed2016-05-10 00:51:56434 return;
danakjc54146a2016-09-12 21:46:18435 client_->ReclaimResources(resources);
boliu@chromium.org8705654b2014-05-24 01:16:19436}
437
danakjc7afae52017-06-20 21:12:41438void SynchronousLayerTreeFrameSink::SetMemoryPolicy(size_t bytes_limit) {
boliu@chromium.org0552c8e2013-09-10 22:44:43439 DCHECK(CalledOnValidThread());
boliub032a082015-06-05 20:03:15440 bool became_zero = memory_policy_.bytes_limit_when_visible && !bytes_limit;
441 bool became_non_zero =
442 !memory_policy_.bytes_limit_when_visible && bytes_limit;
boliu77de0212014-10-28 04:06:33443 memory_policy_.bytes_limit_when_visible = bytes_limit;
444 memory_policy_.num_resources_limit = kNumResourcesLimit;
boliu@chromium.org0552c8e2013-09-10 22:44:43445
sunnypseab5ac92015-04-02 20:26:13446 if (client_)
447 client_->SetMemoryPolicy(memory_policy_);
boliub032a082015-06-05 20:03:15448
449 if (became_zero) {
450 // This is small hack to drop context resources without destroying it
451 // when this compositor is put into the background.
ericrk58049242015-06-22 20:32:15452 context_provider()->ContextSupport()->SetAggressivelyFreeResources(
453 true /* aggressively_free_resources */);
boliub032a082015-06-05 20:03:15454 } else if (became_non_zero) {
ericrk58049242015-06-22 20:32:15455 context_provider()->ContextSupport()->SetAggressivelyFreeResources(
456 false /* aggressively_free_resources */);
boliub032a082015-06-05 20:03:15457 }
boliu@chromium.org0552c8e2013-09-10 22:44:43458}
459
danakjc7afae52017-06-20 21:12:41460void SynchronousLayerTreeFrameSink::DidActivatePendingTree() {
boliu5965c8d12016-05-13 23:58:19461 DCHECK(CalledOnValidThread());
462 if (sync_client_)
463 sync_client_->DidActivatePendingTree();
464 DeliverMessages();
boliu94f592a2014-11-21 21:18:40465}
466
danakjc7afae52017-06-20 21:12:41467void SynchronousLayerTreeFrameSink::DeliverMessages() {
boliu5965c8d12016-05-13 23:58:19468 std::vector<std::unique_ptr<IPC::Message>> messages;
dchengcedca5612016-04-09 01:40:15469 std::unique_ptr<FrameSwapMessageQueue::SendMessageScope> send_message_scope =
mkosiba@chromium.org586871b2014-07-22 17:05:11470 frame_swap_message_queue_->AcquireSendMessageScope();
boliu5965c8d12016-05-13 23:58:19471 frame_swap_message_queue_->DrainMessages(&messages);
472 for (auto& msg : messages) {
473 Send(msg.release());
474 }
mkosiba@chromium.org586871b2014-07-22 17:05:11475}
476
danakjc7afae52017-06-20 21:12:41477bool SynchronousLayerTreeFrameSink::Send(IPC::Message* message) {
boliu42e01312016-05-12 21:47:52478 DCHECK(CalledOnValidThread());
479 return sender_->Send(message);
480}
481
danakjc7afae52017-06-20 21:12:41482bool SynchronousLayerTreeFrameSink::CalledOnValidThread() const {
boliudff26352015-10-12 23:47:07483 return thread_checker_.CalledOnValidThread();
joth@chromium.org913d99a2013-05-31 07:16:07484}
485
danakjc7afae52017-06-20 21:12:41486void SynchronousLayerTreeFrameSink::DidReceiveCompositorFrameAck(
samans8d3604f2017-04-11 22:15:30487 const cc::ReturnedResourceArray& resources) {
488 ReclaimResources(resources);
489}
samans923a54c2017-02-13 22:19:22490
danakjc7afae52017-06-20 21:12:41491void SynchronousLayerTreeFrameSink::OnBeginFrame(
samans923a54c2017-02-13 22:19:22492 const cc::BeginFrameArgs& args) {}
493
danakjc7afae52017-06-20 21:12:41494void SynchronousLayerTreeFrameSink::ReclaimResources(
danakj554c98a2016-07-08 00:25:07495 const cc::ReturnedResourceArray& resources) {
496 DCHECK(resources.empty());
fsamuelb62b78222016-07-15 01:14:14497 client_->ReclaimResources(resources);
danakj554c98a2016-07-08 00:25:07498}
499
danakjc7afae52017-06-20 21:12:41500void SynchronousLayerTreeFrameSink::WillDrawSurface(
samans6ede8b882017-02-17 04:22:45501 const cc::LocalSurfaceId& local_surface_id,
502 const gfx::Rect& damage_rect) {}
danakj554c98a2016-07-08 00:25:07503
joth@chromium.orgeeb93112013-05-01 19:41:10504} // namespace content