Add ICU message format support
[chromium-blink-merge.git] / cc / surfaces / display.cc
blob7e80854a0aaf8c9aef340a746340ce060b14017d
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 TRACE_EVENT0("cc", "Display::SetSurfaceId");
67 current_surface_id_ = id;
68 device_scale_factor_ = device_scale_factor;
70 UpdateRootSurfaceResourcesLocked();
71 if (scheduler_)
72 scheduler_->SetNewRootSurface(id);
75 void Display::Resize(const gfx::Size& size) {
76 if (size == current_surface_size_)
77 return;
79 TRACE_EVENT0("cc", "Display::Resize");
81 // Need to ensure all pending swaps have executed before the window is
82 // resized, or D3D11 will scale the swap output.
83 if (settings_.finish_rendering_on_resize) {
84 if (!swapped_since_resize_ && scheduler_)
85 scheduler_->ForceImmediateSwapIfPossible();
86 if (swapped_since_resize_ && output_surface_ &&
87 output_surface_->context_provider())
88 output_surface_->context_provider()->ContextGL()->ShallowFinishCHROMIUM();
90 swapped_since_resize_ = false;
91 current_surface_size_ = size;
92 if (scheduler_)
93 scheduler_->DisplayResized();
96 void Display::SetExternalClip(const gfx::Rect& clip) {
97 external_clip_ = clip;
100 void Display::InitializeRenderer() {
101 if (resource_provider_)
102 return;
104 // Display does not use GpuMemoryBuffers, so persistent map is not relevant.
105 bool use_persistent_map_for_gpu_memory_buffers = false;
106 scoped_ptr<ResourceProvider> resource_provider = ResourceProvider::Create(
107 output_surface_.get(), bitmap_manager_, gpu_memory_buffer_manager_,
108 nullptr, settings_.highp_threshold_min, settings_.use_rgba_4444_textures,
109 settings_.texture_id_allocation_chunk_size,
110 use_persistent_map_for_gpu_memory_buffers);
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 if (output_surface_->SurfaceIsSuspendForRecycle())
168 return false;
170 scoped_ptr<CompositorFrame> frame =
171 aggregator_->Aggregate(current_surface_id_);
172 if (!frame) {
173 TRACE_EVENT_INSTANT0("cc", "Empty aggregated frame.",
174 TRACE_EVENT_SCOPE_THREAD);
175 return false;
178 // Run callbacks early to allow pipelining.
179 for (const auto& id_entry : aggregator_->previous_contained_surfaces()) {
180 Surface* surface = manager_->GetSurfaceForId(id_entry.first);
181 if (surface)
182 surface->RunDrawCallbacks(SurfaceDrawStatus::DRAWN);
185 DelegatedFrameData* frame_data = frame->delegated_frame_data.get();
187 frame->metadata.latency_info.insert(frame->metadata.latency_info.end(),
188 stored_latency_info_.begin(),
189 stored_latency_info_.end());
190 stored_latency_info_.clear();
191 bool have_copy_requests = false;
192 for (const auto* pass : frame_data->render_pass_list) {
193 have_copy_requests |= !pass->copy_requests.empty();
196 gfx::Size surface_size;
197 bool have_damage = false;
198 if (!frame_data->render_pass_list.empty()) {
199 surface_size = frame_data->render_pass_list.back()->output_rect.size();
200 have_damage =
201 !frame_data->render_pass_list.back()->damage_rect.size().IsEmpty();
204 bool size_matches = surface_size == current_surface_size_;
205 if (!size_matches)
206 TRACE_EVENT_INSTANT0("cc", "Size missmatch.", TRACE_EVENT_SCOPE_THREAD);
208 bool should_draw = !frame->metadata.latency_info.empty() ||
209 have_copy_requests || (have_damage && size_matches);
211 if (should_draw) {
212 gfx::Rect device_viewport_rect = gfx::Rect(current_surface_size_);
213 gfx::Rect device_clip_rect =
214 external_clip_.IsEmpty() ? device_viewport_rect : external_clip_;
215 bool disable_picture_quad_image_filtering = false;
217 renderer_->DecideRenderPassAllocationsForFrame(
218 frame_data->render_pass_list);
219 renderer_->DrawFrame(&frame_data->render_pass_list, device_scale_factor_,
220 device_viewport_rect, device_clip_rect,
221 disable_picture_quad_image_filtering);
222 } else {
223 TRACE_EVENT_INSTANT0("cc", "Draw skipped.", TRACE_EVENT_SCOPE_THREAD);
226 bool should_swap = should_draw && size_matches;
227 if (should_swap) {
228 swapped_since_resize_ = true;
229 for (auto& latency : frame->metadata.latency_info) {
230 TRACE_EVENT_FLOW_STEP0("input,benchmark", "LatencyInfo.Flow",
231 TRACE_ID_DONT_MANGLE(latency.trace_id()),
232 "Display::DrawAndSwap");
234 benchmark_instrumentation::IssueDisplayRenderingStatsEvent();
235 renderer_->SwapBuffers(frame->metadata);
236 } else {
237 TRACE_EVENT_INSTANT0("cc", "Swap skipped.", TRACE_EVENT_SCOPE_THREAD);
238 stored_latency_info_.insert(stored_latency_info_.end(),
239 frame->metadata.latency_info.begin(),
240 frame->metadata.latency_info.end());
241 DidSwapBuffers();
242 DidSwapBuffersComplete();
245 return true;
248 void Display::DidSwapBuffers() {
249 if (scheduler_)
250 scheduler_->DidSwapBuffers();
253 void Display::DidSwapBuffersComplete() {
254 if (scheduler_)
255 scheduler_->DidSwapBuffersComplete();
258 void Display::CommitVSyncParameters(base::TimeTicks timebase,
259 base::TimeDelta interval) {
260 client_->CommitVSyncParameters(timebase, interval);
263 void Display::SetMemoryPolicy(const ManagedMemoryPolicy& policy) {
264 client_->SetMemoryPolicy(policy);
267 void Display::OnDraw() {
268 NOTREACHED();
271 void Display::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
272 NOTREACHED();
275 void Display::ReclaimResources(const CompositorFrameAck* ack) {
276 NOTREACHED();
279 void Display::SetExternalDrawConstraints(
280 const gfx::Transform& transform,
281 const gfx::Rect& viewport,
282 const gfx::Rect& clip,
283 const gfx::Rect& viewport_rect_for_tile_priority,
284 const gfx::Transform& transform_for_tile_priority,
285 bool resourceless_software_draw) {
286 NOTREACHED();
289 void Display::SetTreeActivationCallback(const base::Closure& callback) {
290 NOTREACHED();
293 void Display::SetFullRootLayerDamage() {
294 if (aggregator_ && !current_surface_id_.is_null())
295 aggregator_->SetFullDamageForSurface(current_surface_id_);
298 void Display::OnSurfaceDamaged(SurfaceId surface_id, bool* changed) {
299 if (aggregator_ &&
300 aggregator_->previous_contained_surfaces().count(surface_id)) {
301 Surface* surface = manager_->GetSurfaceForId(surface_id);
302 if (surface) {
303 const CompositorFrame* current_frame = surface->GetEligibleFrame();
304 if (!current_frame || !current_frame->delegated_frame_data ||
305 !current_frame->delegated_frame_data->resource_list.size()) {
306 aggregator_->ReleaseResources(surface_id);
309 if (scheduler_)
310 scheduler_->SurfaceDamaged(surface_id);
311 *changed = true;
312 } else if (surface_id == current_surface_id_) {
313 if (scheduler_)
314 scheduler_->SurfaceDamaged(surface_id);
315 *changed = true;
318 if (surface_id == current_surface_id_)
319 UpdateRootSurfaceResourcesLocked();
322 SurfaceId Display::CurrentSurfaceId() {
323 return current_surface_id_;
326 } // namespace cc