Fix typo in //ui/base/BUILD.gn.
[chromium-blink-merge.git] / cc / surfaces / display.cc
blob54a76efc3d76175fbb2b244f1ee73be4cd6fbe82
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"
24 namespace cc {
26 Display::Display(DisplayClient* client,
27 SurfaceManager* manager,
28 SharedBitmapManager* bitmap_manager,
29 gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
30 const RendererSettings& settings)
31 : client_(client),
32 manager_(manager),
33 bitmap_manager_(bitmap_manager),
34 gpu_memory_buffer_manager_(gpu_memory_buffer_manager),
35 settings_(settings),
36 device_scale_factor_(1.f),
37 swapped_since_resize_(false),
38 scheduler_(nullptr),
39 texture_mailbox_deleter_(new TextureMailboxDeleter(nullptr)) {
40 manager_->AddObserver(this);
43 Display::~Display() {
44 manager_->RemoveObserver(this);
45 if (aggregator_) {
46 for (const auto& id_entry : aggregator_->previous_contained_surfaces()) {
47 Surface* surface = manager_->GetSurfaceForId(id_entry.first);
48 if (surface)
49 surface->RunDrawCallbacks(SurfaceDrawStatus::DRAW_SKIPPED);
54 bool Display::Initialize(scoped_ptr<OutputSurface> output_surface,
55 DisplayScheduler* scheduler) {
56 output_surface_ = output_surface.Pass();
57 scheduler_ = scheduler;
58 return output_surface_->BindToClient(this);
61 void Display::SetSurfaceId(SurfaceId id, float device_scale_factor) {
62 if (current_surface_id_ == id && device_scale_factor_ == device_scale_factor)
63 return;
65 current_surface_id_ = id;
66 device_scale_factor_ = device_scale_factor;
68 UpdateRootSurfaceResourcesLocked();
69 if (scheduler_)
70 scheduler_->EntireDisplayDamaged(id);
73 void Display::Resize(const gfx::Size& size) {
74 if (size == current_surface_size_)
75 return;
76 // Need to ensure all pending swaps have executed before the window is
77 // resized, or D3D11 will scale the swap output.
78 if (settings_.finish_rendering_on_resize) {
79 if (!swapped_since_resize_ && scheduler_)
80 scheduler_->ForceImmediateSwapIfPossible();
81 if (swapped_since_resize_ && output_surface_ &&
82 output_surface_->context_provider())
83 output_surface_->context_provider()->ContextGL()->ShallowFinishCHROMIUM();
85 swapped_since_resize_ = false;
86 current_surface_size_ = size;
87 if (scheduler_)
88 scheduler_->EntireDisplayDamaged(current_surface_id_);
91 void Display::SetExternalClip(const gfx::Rect& clip) {
92 external_clip_ = clip;
95 void Display::InitializeRenderer() {
96 if (resource_provider_)
97 return;
99 // Display does not use GpuMemoryBuffers, so persistent map is not relevant.
100 bool use_persistent_map_for_gpu_memory_buffers = false;
101 scoped_ptr<ResourceProvider> resource_provider = ResourceProvider::Create(
102 output_surface_.get(), bitmap_manager_, gpu_memory_buffer_manager_,
103 nullptr, settings_.highp_threshold_min, settings_.use_rgba_4444_textures,
104 settings_.texture_id_allocation_chunk_size,
105 use_persistent_map_for_gpu_memory_buffers);
106 if (!resource_provider)
107 return;
109 if (output_surface_->context_provider()) {
110 scoped_ptr<GLRenderer> renderer = GLRenderer::Create(
111 this, &settings_, output_surface_.get(), resource_provider.get(),
112 texture_mailbox_deleter_.get(), settings_.highp_threshold_min);
113 if (!renderer)
114 return;
115 renderer_ = renderer.Pass();
116 } else {
117 scoped_ptr<SoftwareRenderer> renderer = SoftwareRenderer::Create(
118 this, &settings_, output_surface_.get(), resource_provider.get());
119 if (!renderer)
120 return;
121 renderer_ = renderer.Pass();
124 resource_provider_ = resource_provider.Pass();
125 // TODO(jbauman): Outputting an incomplete quad list doesn't work when using
126 // overlays.
127 bool output_partial_list = renderer_->Capabilities().using_partial_swap &&
128 !output_surface_->GetOverlayCandidateValidator();
129 aggregator_.reset(new SurfaceAggregator(manager_, resource_provider_.get(),
130 output_partial_list));
133 void Display::DidLoseOutputSurface() {
134 if (scheduler_)
135 scheduler_->OutputSurfaceLost();
136 // WARNING: The client may delete the Display in this method call. Do not
137 // make any additional references to members after this call.
138 client_->OutputSurfaceLost();
141 void Display::UpdateRootSurfaceResourcesLocked() {
142 Surface* surface = manager_->GetSurfaceForId(current_surface_id_);
143 bool root_surface_resources_locked = !surface || !surface->GetEligibleFrame();
144 if (scheduler_)
145 scheduler_->SetRootSurfaceResourcesLocked(root_surface_resources_locked);
148 bool Display::DrawAndSwap() {
149 if (current_surface_id_.is_null())
150 return false;
152 InitializeRenderer();
153 if (!output_surface_)
154 return false;
156 if (output_surface_->SurfaceIsSuspendForRecycle())
157 return false;
159 scoped_ptr<CompositorFrame> frame =
160 aggregator_->Aggregate(current_surface_id_);
161 if (!frame)
162 return false;
164 TRACE_EVENT0("cc", "Display::DrawAndSwap");
166 // Run callbacks early to allow pipelining.
167 for (const auto& id_entry : aggregator_->previous_contained_surfaces()) {
168 Surface* surface = manager_->GetSurfaceForId(id_entry.first);
169 if (surface)
170 surface->RunDrawCallbacks(SurfaceDrawStatus::DRAWN);
172 DelegatedFrameData* frame_data = frame->delegated_frame_data.get();
174 frame->metadata.latency_info.insert(frame->metadata.latency_info.end(),
175 stored_latency_info_.begin(),
176 stored_latency_info_.end());
177 stored_latency_info_.clear();
178 bool have_copy_requests = false;
179 for (const auto* pass : frame_data->render_pass_list) {
180 have_copy_requests |= !pass->copy_requests.empty();
183 gfx::Size surface_size;
184 bool have_damage = false;
185 if (!frame_data->render_pass_list.empty()) {
186 surface_size = frame_data->render_pass_list.back()->output_rect.size();
187 have_damage =
188 !frame_data->render_pass_list.back()->damage_rect.size().IsEmpty();
190 bool avoid_swap = surface_size != current_surface_size_;
191 bool should_draw = !frame->metadata.latency_info.empty() ||
192 have_copy_requests || (have_damage && !avoid_swap);
194 if (should_draw) {
195 gfx::Rect device_viewport_rect = gfx::Rect(current_surface_size_);
196 gfx::Rect device_clip_rect =
197 external_clip_.IsEmpty() ? device_viewport_rect : external_clip_;
198 bool disable_picture_quad_image_filtering = false;
200 renderer_->DecideRenderPassAllocationsForFrame(
201 frame_data->render_pass_list);
202 renderer_->DrawFrame(&frame_data->render_pass_list, device_scale_factor_,
203 device_viewport_rect, device_clip_rect,
204 disable_picture_quad_image_filtering);
207 if (should_draw && !avoid_swap) {
208 swapped_since_resize_ = true;
209 for (auto& latency : frame->metadata.latency_info) {
210 TRACE_EVENT_FLOW_STEP0(
211 "input,benchmark",
212 "LatencyInfo.Flow",
213 TRACE_ID_DONT_MANGLE(latency.trace_id),
214 "Display::DrawAndSwap");
216 benchmark_instrumentation::IssueDisplayRenderingStatsEvent();
217 renderer_->SwapBuffers(frame->metadata);
218 } else {
219 stored_latency_info_.insert(stored_latency_info_.end(),
220 frame->metadata.latency_info.begin(),
221 frame->metadata.latency_info.end());
222 DidSwapBuffers();
223 DidSwapBuffersComplete();
226 return true;
229 void Display::DidSwapBuffers() {
230 if (scheduler_)
231 scheduler_->DidSwapBuffers();
234 void Display::DidSwapBuffersComplete() {
235 if (scheduler_)
236 scheduler_->DidSwapBuffersComplete();
239 void Display::CommitVSyncParameters(base::TimeTicks timebase,
240 base::TimeDelta interval) {
241 client_->CommitVSyncParameters(timebase, interval);
244 void Display::SetMemoryPolicy(const ManagedMemoryPolicy& policy) {
245 client_->SetMemoryPolicy(policy);
248 void Display::OnDraw() {
249 NOTREACHED();
252 void Display::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
253 NOTREACHED();
256 void Display::ReclaimResources(const CompositorFrameAck* ack) {
257 NOTREACHED();
260 void Display::SetExternalDrawConstraints(
261 const gfx::Transform& transform,
262 const gfx::Rect& viewport,
263 const gfx::Rect& clip,
264 const gfx::Rect& viewport_rect_for_tile_priority,
265 const gfx::Transform& transform_for_tile_priority,
266 bool resourceless_software_draw) {
267 NOTREACHED();
270 void Display::SetTreeActivationCallback(const base::Closure& callback) {
271 NOTREACHED();
274 void Display::SetFullRootLayerDamage() {
275 if (aggregator_ && !current_surface_id_.is_null())
276 aggregator_->SetFullDamageForSurface(current_surface_id_);
279 void Display::OnSurfaceDamaged(SurfaceId surface_id, bool* changed) {
280 if (aggregator_ &&
281 aggregator_->previous_contained_surfaces().count(surface_id)) {
282 Surface* surface = manager_->GetSurfaceForId(surface_id);
283 if (surface) {
284 const CompositorFrame* current_frame = surface->GetEligibleFrame();
285 if (!current_frame || !current_frame->delegated_frame_data ||
286 !current_frame->delegated_frame_data->resource_list.size()) {
287 aggregator_->ReleaseResources(surface_id);
290 if (scheduler_)
291 scheduler_->SurfaceDamaged(surface_id);
292 *changed = true;
293 } else if (surface_id == current_surface_id_) {
294 if (scheduler_)
295 scheduler_->SurfaceDamaged(surface_id);
296 *changed = true;
299 if (surface_id == current_surface_id_)
300 UpdateRootSurfaceResourcesLocked();
303 SurfaceId Display::CurrentSurfaceId() {
304 return current_surface_id_;
307 } // namespace cc