cc: Use worker context for one-copy tile initialization.
[chromium-blink-merge.git] / cc / surfaces / display.cc
blob586bfad3dc7a0961205c694cd7ae4cda81bf8695
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 scoped_ptr<ResourceProvider> resource_provider = ResourceProvider::Create(
105 output_surface_.get(), bitmap_manager_, gpu_memory_buffer_manager_,
106 nullptr, settings_.highp_threshold_min, settings_.use_rgba_4444_textures,
107 settings_.texture_id_allocation_chunk_size);
108 if (!resource_provider)
109 return;
111 if (output_surface_->context_provider()) {
112 scoped_ptr<GLRenderer> renderer = GLRenderer::Create(
113 this, &settings_, output_surface_.get(), resource_provider.get(),
114 texture_mailbox_deleter_.get(), settings_.highp_threshold_min);
115 if (!renderer)
116 return;
117 renderer_ = renderer.Pass();
118 } else {
119 scoped_ptr<SoftwareRenderer> renderer = SoftwareRenderer::Create(
120 this, &settings_, output_surface_.get(), resource_provider.get());
121 if (!renderer)
122 return;
123 renderer_ = renderer.Pass();
126 resource_provider_ = resource_provider.Pass();
127 // TODO(jbauman): Outputting an incomplete quad list doesn't work when using
128 // overlays.
129 bool output_partial_list = renderer_->Capabilities().using_partial_swap &&
130 !output_surface_->GetOverlayCandidateValidator();
131 aggregator_.reset(new SurfaceAggregator(manager_, resource_provider_.get(),
132 output_partial_list));
135 void Display::DidLoseOutputSurface() {
136 if (scheduler_)
137 scheduler_->OutputSurfaceLost();
138 // WARNING: The client may delete the Display in this method call. Do not
139 // make any additional references to members after this call.
140 client_->OutputSurfaceLost();
143 void Display::UpdateRootSurfaceResourcesLocked() {
144 Surface* surface = manager_->GetSurfaceForId(current_surface_id_);
145 bool root_surface_resources_locked = !surface || !surface->GetEligibleFrame();
146 if (scheduler_)
147 scheduler_->SetRootSurfaceResourcesLocked(root_surface_resources_locked);
150 bool Display::DrawAndSwap() {
151 TRACE_EVENT0("cc", "Display::DrawAndSwap");
153 if (current_surface_id_.is_null()) {
154 TRACE_EVENT_INSTANT0("cc", "No root surface.", TRACE_EVENT_SCOPE_THREAD);
155 return false;
158 InitializeRenderer();
159 if (!output_surface_) {
160 TRACE_EVENT_INSTANT0("cc", "No output surface", TRACE_EVENT_SCOPE_THREAD);
161 return false;
164 if (output_surface_->SurfaceIsSuspendForRecycle())
165 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 (should_draw) {
209 gfx::Rect device_viewport_rect = gfx::Rect(current_surface_size_);
210 gfx::Rect device_clip_rect =
211 external_clip_.IsEmpty() ? device_viewport_rect : external_clip_;
212 bool disable_picture_quad_image_filtering = false;
214 renderer_->DecideRenderPassAllocationsForFrame(
215 frame_data->render_pass_list);
216 renderer_->DrawFrame(&frame_data->render_pass_list, device_scale_factor_,
217 device_viewport_rect, device_clip_rect,
218 disable_picture_quad_image_filtering);
219 } else {
220 TRACE_EVENT_INSTANT0("cc", "Draw skipped.", TRACE_EVENT_SCOPE_THREAD);
223 bool should_swap = should_draw && size_matches;
224 if (should_swap) {
225 swapped_since_resize_ = true;
226 for (auto& latency : frame->metadata.latency_info) {
227 TRACE_EVENT_FLOW_STEP0("input,benchmark", "LatencyInfo.Flow",
228 TRACE_ID_DONT_MANGLE(latency.trace_id()),
229 "Display::DrawAndSwap");
231 benchmark_instrumentation::IssueDisplayRenderingStatsEvent();
232 renderer_->SwapBuffers(frame->metadata);
233 } else {
234 TRACE_EVENT_INSTANT0("cc", "Swap skipped.", TRACE_EVENT_SCOPE_THREAD);
235 stored_latency_info_.insert(stored_latency_info_.end(),
236 frame->metadata.latency_info.begin(),
237 frame->metadata.latency_info.end());
238 DidSwapBuffers();
239 DidSwapBuffersComplete();
242 return true;
245 void Display::DidSwapBuffers() {
246 if (scheduler_)
247 scheduler_->DidSwapBuffers();
250 void Display::DidSwapBuffersComplete() {
251 if (scheduler_)
252 scheduler_->DidSwapBuffersComplete();
255 void Display::CommitVSyncParameters(base::TimeTicks timebase,
256 base::TimeDelta interval) {
257 client_->CommitVSyncParameters(timebase, interval);
260 void Display::SetMemoryPolicy(const ManagedMemoryPolicy& policy) {
261 client_->SetMemoryPolicy(policy);
264 void Display::OnDraw() {
265 NOTREACHED();
268 void Display::SetNeedsRedrawRect(const gfx::Rect& damage_rect) {
269 NOTREACHED();
272 void Display::ReclaimResources(const CompositorFrameAck* ack) {
273 NOTREACHED();
276 void Display::SetExternalDrawConstraints(
277 const gfx::Transform& transform,
278 const gfx::Rect& viewport,
279 const gfx::Rect& clip,
280 const gfx::Rect& viewport_rect_for_tile_priority,
281 const gfx::Transform& transform_for_tile_priority,
282 bool resourceless_software_draw) {
283 NOTREACHED();
286 void Display::SetTreeActivationCallback(const base::Closure& callback) {
287 NOTREACHED();
290 void Display::SetFullRootLayerDamage() {
291 if (aggregator_ && !current_surface_id_.is_null())
292 aggregator_->SetFullDamageForSurface(current_surface_id_);
295 void Display::OnSurfaceDamaged(SurfaceId surface_id, bool* changed) {
296 if (aggregator_ &&
297 aggregator_->previous_contained_surfaces().count(surface_id)) {
298 Surface* surface = manager_->GetSurfaceForId(surface_id);
299 if (surface) {
300 const CompositorFrame* current_frame = surface->GetEligibleFrame();
301 if (!current_frame || !current_frame->delegated_frame_data ||
302 !current_frame->delegated_frame_data->resource_list.size()) {
303 aggregator_->ReleaseResources(surface_id);
306 if (scheduler_)
307 scheduler_->SurfaceDamaged(surface_id);
308 *changed = true;
309 } else if (surface_id == current_surface_id_) {
310 if (scheduler_)
311 scheduler_->SurfaceDamaged(surface_id);
312 *changed = true;
315 if (surface_id == current_surface_id_)
316 UpdateRootSurfaceResourcesLocked();
319 SurfaceId Display::CurrentSurfaceId() {
320 return current_surface_id_;
323 } // namespace cc