Reland "Non-SFI mode: Switch to newlib. (patchset #4 id:60001 of https://codereview...
[chromium-blink-merge.git] / cc / surfaces / display.cc
blob294dc5b4ff57d404f580f0efc6d155d539b1eaa1
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 aggregator_.reset(new SurfaceAggregator(manager_, resource_provider_.get()));
128 void Display::DidLoseOutputSurface() {
129 client_->OutputSurfaceLost();
130 if (scheduler_)
131 scheduler_->OutputSurfaceLost();
134 void Display::UpdateRootSurfaceResourcesLocked() {
135 Surface* surface = manager_->GetSurfaceForId(current_surface_id_);
136 bool root_surface_resources_locked = !surface || !surface->GetEligibleFrame();
137 if (scheduler_)
138 scheduler_->SetRootSurfaceResourcesLocked(root_surface_resources_locked);
141 bool Display::DrawAndSwap() {
142 if (current_surface_id_.is_null())
143 return false;
145 InitializeRenderer();
146 if (!output_surface_)
147 return false;
149 scoped_ptr<CompositorFrame> frame =
150 aggregator_->Aggregate(current_surface_id_);
151 if (!frame)
152 return false;
154 TRACE_EVENT0("cc", "Display::DrawAndSwap");
155 benchmark_instrumentation::IssueDisplayRenderingStatsEvent();
157 // Run callbacks early to allow pipelining.
158 for (const auto& id_entry : aggregator_->previous_contained_surfaces()) {
159 Surface* surface = manager_->GetSurfaceForId(id_entry.first);
160 if (surface)
161 surface->RunDrawCallbacks(SurfaceDrawStatus::DRAWN);
163 DelegatedFrameData* frame_data = frame->delegated_frame_data.get();
165 frame->metadata.latency_info.insert(frame->metadata.latency_info.end(),
166 stored_latency_info_.begin(),
167 stored_latency_info_.end());
168 stored_latency_info_.clear();
169 bool have_copy_requests = false;
170 for (const auto* pass : frame_data->render_pass_list) {
171 have_copy_requests |= !pass->copy_requests.empty();
174 gfx::Size surface_size;
175 bool have_damage = false;
176 if (!frame_data->render_pass_list.empty()) {
177 surface_size = frame_data->render_pass_list.back()->output_rect.size();
178 have_damage =
179 !frame_data->render_pass_list.back()->damage_rect.size().IsEmpty();
181 bool avoid_swap = surface_size != current_surface_size_;
182 bool should_draw = !frame->metadata.latency_info.empty() ||
183 have_copy_requests || (have_damage && !avoid_swap);
185 if (should_draw) {
186 gfx::Rect device_viewport_rect = gfx::Rect(current_surface_size_);
187 gfx::Rect device_clip_rect =
188 external_clip_.IsEmpty() ? device_viewport_rect : external_clip_;
189 bool disable_picture_quad_image_filtering = false;
191 renderer_->DecideRenderPassAllocationsForFrame(
192 frame_data->render_pass_list);
193 renderer_->DrawFrame(&frame_data->render_pass_list, device_scale_factor_,
194 device_viewport_rect, device_clip_rect,
195 disable_picture_quad_image_filtering);
198 if (should_draw && !avoid_swap) {
199 swapped_since_resize_ = true;
200 renderer_->SwapBuffers(frame->metadata);
201 } else {
202 stored_latency_info_.insert(stored_latency_info_.end(),
203 frame->metadata.latency_info.begin(),
204 frame->metadata.latency_info.end());
205 DidSwapBuffers();
206 DidSwapBuffersComplete();
209 return true;
212 void Display::DidSwapBuffers() {
213 if (scheduler_)
214 scheduler_->DidSwapBuffers();
217 void Display::DidSwapBuffersComplete() {
218 if (scheduler_)
219 scheduler_->DidSwapBuffersComplete();
222 void Display::CommitVSyncParameters(base::TimeTicks timebase,
223 base::TimeDelta interval) {
224 client_->CommitVSyncParameters(timebase, interval);
227 void Display::SetMemoryPolicy(const ManagedMemoryPolicy& policy) {
228 client_->SetMemoryPolicy(policy);
231 void Display::OnDraw() {
232 NOTREACHED();
235 void Display::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
236 NOTREACHED();
239 void Display::ReclaimResources(const CompositorFrameAck* ack) {
240 NOTREACHED();
243 void Display::SetExternalDrawConstraints(
244 const gfx::Transform& transform,
245 const gfx::Rect& viewport,
246 const gfx::Rect& clip,
247 const gfx::Rect& viewport_rect_for_tile_priority,
248 const gfx::Transform& transform_for_tile_priority,
249 bool resourceless_software_draw) {
250 NOTREACHED();
253 void Display::SetTreeActivationCallback(const base::Closure& callback) {
254 NOTREACHED();
257 void Display::SetFullRootLayerDamage() {
258 if (aggregator_ && !current_surface_id_.is_null())
259 aggregator_->SetFullDamageForSurface(current_surface_id_);
262 void Display::OnSurfaceDamaged(SurfaceId surface_id, bool* changed) {
263 if (aggregator_ &&
264 aggregator_->previous_contained_surfaces().count(surface_id)) {
265 Surface* surface = manager_->GetSurfaceForId(surface_id);
266 if (surface) {
267 const CompositorFrame* current_frame = surface->GetEligibleFrame();
268 if (!current_frame || !current_frame->delegated_frame_data ||
269 !current_frame->delegated_frame_data->resource_list.size()) {
270 aggregator_->ReleaseResources(surface_id);
273 if (scheduler_)
274 scheduler_->SurfaceDamaged(surface_id);
275 *changed = true;
276 } else if (surface_id == current_surface_id_) {
277 if (scheduler_)
278 scheduler_->SurfaceDamaged(surface_id);
279 *changed = true;
282 if (surface_id == current_surface_id_)
283 UpdateRootSurfaceResourcesLocked();
286 SurfaceId Display::CurrentSurfaceId() {
287 return current_surface_id_;
290 } // namespace cc