Ensure favicon images are correctly used and downloaded when syncing bookmark apps.
[chromium-blink-merge.git] / cc / surfaces / display.cc
blobfe278fc08fa7e4a1fbfe3099196cbc2f918ef048
1 // Copyright 2014 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.
5 #include "cc/surfaces/display.h"
7 #include "base/thread_task_runner_handle.h"
8 #include "base/trace_event/trace_event.h"
9 #include "cc/debug/benchmark_instrumentation.h"
10 #include "cc/output/compositor_frame.h"
11 #include "cc/output/compositor_frame_ack.h"
12 #include "cc/output/direct_renderer.h"
13 #include "cc/output/gl_renderer.h"
14 #include "cc/output/renderer_settings.h"
15 #include "cc/output/software_renderer.h"
16 #include "cc/output/texture_mailbox_deleter.h"
17 #include "cc/surfaces/display_client.h"
18 #include "cc/surfaces/display_scheduler.h"
19 #include "cc/surfaces/surface.h"
20 #include "cc/surfaces/surface_aggregator.h"
21 #include "cc/surfaces/surface_manager.h"
22 #include "gpu/command_buffer/client/gles2_interface.h"
23 #include "ui/gfx/buffer_types.h"
25 namespace cc {
27 Display::Display(DisplayClient* client,
28 SurfaceManager* manager,
29 SharedBitmapManager* bitmap_manager,
30 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
31 const RendererSettings& settings)
32 : client_(client),
33 manager_(manager),
34 bitmap_manager_(bitmap_manager),
35 gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
36 settings_(settings),
37 device_scale_factor_(1.f),
38 swapped_since_resize_(false),
39 scheduler_(nullptr),
40 texture_mailbox_deleter_(new TextureMailboxDeleter(nullptr)) {
41 manager_->AddObserver(this);
44 Display::~Display() {
45 manager_->RemoveObserver(this);
46 if (aggregator_) {
47 for (const auto& id_entry : aggregator_->previous_contained_surfaces()) {
48 Surface* surface = manager_->GetSurfaceForId(id_entry.first);
49 if (surface)
50 surface->RunDrawCallbacks(SurfaceDrawStatus::DRAW_SKIPPED);
55 bool Display::Initialize(scoped_ptr<OutputSurface> output_surface,
56 DisplayScheduler* scheduler) {
57 output_surface_ = output_surface.Pass();
58 scheduler_ = scheduler;
59 return output_surface_->BindToClient(this);
62 void Display::SetSurfaceId(SurfaceId id, float device_scale_factor) {
63 if (current_surface_id_ == id && device_scale_factor_ == device_scale_factor)
64 return;
66 TRACE_EVENT0("cc", "Display::SetSurfaceId");
68 current_surface_id_ = id;
69 device_scale_factor_ = device_scale_factor;
71 UpdateRootSurfaceResourcesLocked();
72 if (scheduler_)
73 scheduler_->SetNewRootSurface(id);
76 void Display::Resize(const gfx::Size& size) {
77 if (size == current_surface_size_)
78 return;
80 TRACE_EVENT0("cc", "Display::Resize");
82 // Need to ensure all pending swaps have executed before the window is
83 // resized, or D3D11 will scale the swap output.
84 if (settings_.finish_rendering_on_resize) {
85 if (!swapped_since_resize_ && scheduler_)
86 scheduler_->ForceImmediateSwapIfPossible();
87 if (swapped_since_resize_ && output_surface_ &&
88 output_surface_->context_provider())
89 output_surface_->context_provider()->ContextGL()->ShallowFinishCHROMIUM();
91 swapped_since_resize_ = false;
92 current_surface_size_ = size;
93 if (scheduler_)
94 scheduler_->DisplayResized();
97 void Display::SetExternalClip(const gfx::Rect& clip) {
98 external_clip_ = clip;
101 void Display::InitializeRenderer() {
102 if (resource_provider_)
103 return;
105 scoped_ptr<ResourceProvider> resource_provider = ResourceProvider::Create(
106 output_surface_.get(), bitmap_manager_, gpu_memory_buffer_manager_,
107 nullptr, settings_.highp_threshold_min, settings_.use_rgba_4444_textures,
108 settings_.texture_id_allocation_chunk_size,
109 std::vector<unsigned>(static_cast<size_t>(gfx::BufferFormat::LAST) + 1,
110 GL_TEXTURE_2D));
111 if (!resource_provider)
112 return;
114 if (output_surface_->context_provider()) {
115 scoped_ptr<GLRenderer> renderer = GLRenderer::Create(
116 this, &settings_, output_surface_.get(), resource_provider.get(),
117 texture_mailbox_deleter_.get(), settings_.highp_threshold_min);
118 if (!renderer)
119 return;
120 renderer_ = renderer.Pass();
121 } else {
122 scoped_ptr<SoftwareRenderer> renderer = SoftwareRenderer::Create(
123 this, &settings_, output_surface_.get(), resource_provider.get());
124 if (!renderer)
125 return;
126 renderer_ = renderer.Pass();
129 resource_provider_ = resource_provider.Pass();
130 // TODO(jbauman): Outputting an incomplete quad list doesn't work when using
131 // overlays.
132 bool output_partial_list = renderer_->Capabilities().using_partial_swap &&
133 !output_surface_->GetOverlayCandidateValidator();
134 aggregator_.reset(new SurfaceAggregator(manager_, resource_provider_.get(),
135 output_partial_list));
138 void Display::DidLoseOutputSurface() {
139 if (scheduler_)
140 scheduler_->OutputSurfaceLost();
141 // WARNING: The client may delete the Display in this method call. Do not
142 // make any additional references to members after this call.
143 client_->OutputSurfaceLost();
146 void Display::UpdateRootSurfaceResourcesLocked() {
147 Surface* surface = manager_->GetSurfaceForId(current_surface_id_);
148 bool root_surface_resources_locked = !surface || !surface->GetEligibleFrame();
149 if (scheduler_)
150 scheduler_->SetRootSurfaceResourcesLocked(root_surface_resources_locked);
153 bool Display::DrawAndSwap() {
154 TRACE_EVENT0("cc", "Display::DrawAndSwap");
156 if (current_surface_id_.is_null()) {
157 TRACE_EVENT_INSTANT0("cc", "No root surface.", TRACE_EVENT_SCOPE_THREAD);
158 return false;
161 InitializeRenderer();
162 if (!output_surface_) {
163 TRACE_EVENT_INSTANT0("cc", "No output surface", TRACE_EVENT_SCOPE_THREAD);
164 return false;
167 scoped_ptr<CompositorFrame> frame =
168 aggregator_->Aggregate(current_surface_id_);
169 if (!frame) {
170 TRACE_EVENT_INSTANT0("cc", "Empty aggregated frame.",
171 TRACE_EVENT_SCOPE_THREAD);
172 return false;
175 // Run callbacks early to allow pipelining.
176 for (const auto& id_entry : aggregator_->previous_contained_surfaces()) {
177 Surface* surface = manager_->GetSurfaceForId(id_entry.first);
178 if (surface)
179 surface->RunDrawCallbacks(SurfaceDrawStatus::DRAWN);
182 DelegatedFrameData* frame_data = frame->delegated_frame_data.get();
184 frame->metadata.latency_info.insert(frame->metadata.latency_info.end(),
185 stored_latency_info_.begin(),
186 stored_latency_info_.end());
187 stored_latency_info_.clear();
188 bool have_copy_requests = false;
189 for (const auto* pass : frame_data->render_pass_list) {
190 have_copy_requests |= !pass->copy_requests.empty();
193 gfx::Size surface_size;
194 bool have_damage = false;
195 if (!frame_data->render_pass_list.empty()) {
196 surface_size = frame_data->render_pass_list.back()->output_rect.size();
197 have_damage =
198 !frame_data->render_pass_list.back()->damage_rect.size().IsEmpty();
201 bool size_matches = surface_size == current_surface_size_;
202 if (!size_matches)
203 TRACE_EVENT_INSTANT0("cc", "Size missmatch.", TRACE_EVENT_SCOPE_THREAD);
205 bool should_draw = !frame->metadata.latency_info.empty() ||
206 have_copy_requests || (have_damage && size_matches);
208 // If the surface is suspended then the resources to be used by the draw are
209 // likely destroyed.
210 if (output_surface_->SurfaceIsSuspendForRecycle()) {
211 TRACE_EVENT_INSTANT0("cc", "Surface is suspended for recycle.",
212 TRACE_EVENT_SCOPE_THREAD);
213 should_draw = false;
216 if (should_draw) {
217 gfx::Rect device_viewport_rect = gfx::Rect(current_surface_size_);
218 gfx::Rect device_clip_rect =
219 external_clip_.IsEmpty() ? device_viewport_rect : external_clip_;
220 bool disable_picture_quad_image_filtering = false;
222 renderer_->DecideRenderPassAllocationsForFrame(
223 frame_data->render_pass_list);
224 renderer_->DrawFrame(&frame_data->render_pass_list, device_scale_factor_,
225 device_viewport_rect, device_clip_rect,
226 disable_picture_quad_image_filtering);
227 } else {
228 TRACE_EVENT_INSTANT0("cc", "Draw skipped.", TRACE_EVENT_SCOPE_THREAD);
231 bool should_swap = should_draw && size_matches;
232 if (should_swap) {
233 swapped_since_resize_ = true;
234 for (auto& latency : frame->metadata.latency_info) {
235 TRACE_EVENT_WITH_FLOW1("input,benchmark", "LatencyInfo.Flow",
236 TRACE_ID_DONT_MANGLE(latency.trace_id()),
237 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
238 "step", "Display::DrawAndSwap");
240 benchmark_instrumentation::IssueDisplayRenderingStatsEvent();
241 renderer_->SwapBuffers(frame->metadata);
242 } else {
243 if (have_damage && !size_matches)
244 aggregator_->SetFullDamageForSurface(current_surface_id_);
245 TRACE_EVENT_INSTANT0("cc", "Swap skipped.", TRACE_EVENT_SCOPE_THREAD);
246 stored_latency_info_.insert(stored_latency_info_.end(),
247 frame->metadata.latency_info.begin(),
248 frame->metadata.latency_info.end());
249 DidSwapBuffers();
250 DidSwapBuffersComplete();
253 return true;
256 void Display::DidSwapBuffers() {
257 if (scheduler_)
258 scheduler_->DidSwapBuffers();
261 void Display::DidSwapBuffersComplete() {
262 if (scheduler_)
263 scheduler_->DidSwapBuffersComplete();
266 void Display::CommitVSyncParameters(base::TimeTicks timebase,
267 base::TimeDelta interval) {
268 client_->CommitVSyncParameters(timebase, interval);
271 void Display::SetMemoryPolicy(const ManagedMemoryPolicy& policy) {
272 client_->SetMemoryPolicy(policy);
275 void Display::OnDraw() {
276 NOTREACHED();
279 void Display::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
280 NOTREACHED();
283 void Display::ReclaimResources(const CompositorFrameAck* ack) {
284 NOTREACHED();
287 void Display::SetExternalDrawConstraints(
288 const gfx::Transform& transform,
289 const gfx::Rect& viewport,
290 const gfx::Rect& clip,
291 const gfx::Rect& viewport_rect_for_tile_priority,
292 const gfx::Transform& transform_for_tile_priority,
293 bool resourceless_software_draw) {
294 NOTREACHED();
297 void Display::SetTreeActivationCallback(const base::Closure& callback) {
298 NOTREACHED();
301 void Display::SetFullRootLayerDamage() {
302 if (aggregator_ && !current_surface_id_.is_null())
303 aggregator_->SetFullDamageForSurface(current_surface_id_);
306 void Display::OnSurfaceDamaged(SurfaceId surface_id, bool* changed) {
307 if (aggregator_ &&
308 aggregator_->previous_contained_surfaces().count(surface_id)) {
309 Surface* surface = manager_->GetSurfaceForId(surface_id);
310 if (surface) {
311 const CompositorFrame* current_frame = surface->GetEligibleFrame();
312 if (!current_frame || !current_frame->delegated_frame_data ||
313 !current_frame->delegated_frame_data->resource_list.size()) {
314 aggregator_->ReleaseResources(surface_id);
317 if (scheduler_)
318 scheduler_->SurfaceDamaged(surface_id);
319 *changed = true;
320 } else if (surface_id == current_surface_id_) {
321 if (scheduler_)
322 scheduler_->SurfaceDamaged(surface_id);
323 *changed = true;
326 if (surface_id == current_surface_id_)
327 UpdateRootSurfaceResourcesLocked();
330 SurfaceId Display::CurrentSurfaceId() {
331 return current_surface_id_;
334 } // namespace cc