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/message_loop/message_loop.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/resources/texture_mailbox_deleter.h"
17 #include "cc/surfaces/display_client.h"
18 #include "cc/surfaces/surface.h"
19 #include "cc/surfaces/surface_aggregator.h"
20 #include "cc/surfaces/surface_manager.h"
21 #include "cc/trees/blocking_task_runner.h"
25 Display::Display(DisplayClient
* client
,
26 SurfaceManager
* manager
,
27 SharedBitmapManager
* bitmap_manager
,
28 gpu::GpuMemoryBufferManager
* gpu_memory_buffer_manager
,
29 const RendererSettings
& settings
)
32 bitmap_manager_(bitmap_manager
),
33 gpu_memory_buffer_manager_(gpu_memory_buffer_manager
),
35 device_scale_factor_(1.f
),
36 blocking_main_thread_task_runner_(
37 BlockingTaskRunner::Create(base::MessageLoopProxy::current())),
38 texture_mailbox_deleter_(
39 new TextureMailboxDeleter(base::MessageLoopProxy::current())) {
40 manager_
->AddObserver(this);
44 manager_
->RemoveObserver(this);
46 for (const auto& id_entry
: aggregator_
->previous_contained_surfaces()) {
47 Surface
* surface
= manager_
->GetSurfaceForId(id_entry
.first
);
49 surface
->RunDrawCallbacks(SurfaceDrawStatus::DRAW_SKIPPED
);
54 bool Display::Initialize(scoped_ptr
<OutputSurface
> output_surface
) {
55 output_surface_
= output_surface
.Pass();
56 return output_surface_
->BindToClient(this);
59 void Display::SetSurfaceId(SurfaceId id
, float device_scale_factor
) {
60 current_surface_id_
= id
;
61 device_scale_factor_
= device_scale_factor
;
62 client_
->DisplayDamaged();
65 void Display::Resize(const gfx::Size
& size
) {
66 if (size
== current_surface_size_
)
68 // Need to ensure all pending swaps have executed before the window is
69 // resized, or D3D11 will scale the swap output.
70 if (renderer_
&& settings_
.finish_rendering_on_resize
)
72 current_surface_size_
= size
;
73 client_
->DisplayDamaged();
76 void Display::InitializeRenderer() {
77 if (resource_provider_
)
80 scoped_ptr
<ResourceProvider
> resource_provider
= ResourceProvider::Create(
81 output_surface_
.get(), bitmap_manager_
, gpu_memory_buffer_manager_
,
82 blocking_main_thread_task_runner_
.get(), settings_
.highp_threshold_min
,
83 settings_
.use_rgba_4444_textures
,
84 settings_
.texture_id_allocation_chunk_size
);
85 if (!resource_provider
)
88 if (output_surface_
->context_provider()) {
89 scoped_ptr
<GLRenderer
> renderer
= GLRenderer::Create(
90 this, &settings_
, output_surface_
.get(), resource_provider
.get(),
91 texture_mailbox_deleter_
.get(), settings_
.highp_threshold_min
);
94 renderer_
= renderer
.Pass();
96 scoped_ptr
<SoftwareRenderer
> renderer
= SoftwareRenderer::Create(
97 this, &settings_
, output_surface_
.get(), resource_provider
.get());
100 renderer_
= renderer
.Pass();
103 resource_provider_
= resource_provider
.Pass();
104 aggregator_
.reset(new SurfaceAggregator(manager_
, resource_provider_
.get()));
107 void Display::DidLoseOutputSurface() {
108 client_
->OutputSurfaceLost();
111 bool Display::Draw() {
112 if (current_surface_id_
.is_null())
115 InitializeRenderer();
116 if (!output_surface_
)
119 // TODO(skyostil): We should hold a BlockingTaskRunner::CapturePostTasks
120 // while Aggregate is called to immediately run release callbacks afterward.
121 scoped_ptr
<CompositorFrame
> frame
=
122 aggregator_
->Aggregate(current_surface_id_
);
126 TRACE_EVENT0("cc", "Display::Draw");
127 benchmark_instrumentation::IssueDisplayRenderingStatsEvent();
129 // Run callbacks early to allow pipelining.
130 for (const auto& id_entry
: aggregator_
->previous_contained_surfaces()) {
131 Surface
* surface
= manager_
->GetSurfaceForId(id_entry
.first
);
133 surface
->RunDrawCallbacks(SurfaceDrawStatus::DRAWN
);
135 DelegatedFrameData
* frame_data
= frame
->delegated_frame_data
.get();
137 frame
->metadata
.latency_info
.insert(frame
->metadata
.latency_info
.end(),
138 stored_latency_info_
.begin(),
139 stored_latency_info_
.end());
140 stored_latency_info_
.clear();
141 bool have_copy_requests
= false;
142 for (const auto* pass
: frame_data
->render_pass_list
) {
143 have_copy_requests
|= !pass
->copy_requests
.empty();
146 gfx::Size surface_size
;
147 bool have_damage
= false;
148 if (!frame_data
->render_pass_list
.empty()) {
149 surface_size
= frame_data
->render_pass_list
.back()->output_rect
.size();
151 !frame_data
->render_pass_list
.back()->damage_rect
.size().IsEmpty();
153 bool avoid_swap
= surface_size
!= current_surface_size_
;
154 bool should_draw
= !frame
->metadata
.latency_info
.empty() ||
155 have_copy_requests
|| (have_damage
&& !avoid_swap
);
158 gfx::Rect device_viewport_rect
= gfx::Rect(current_surface_size_
);
159 gfx::Rect device_clip_rect
= device_viewport_rect
;
160 bool disable_picture_quad_image_filtering
= false;
162 renderer_
->DecideRenderPassAllocationsForFrame(
163 frame_data
->render_pass_list
);
164 renderer_
->DrawFrame(&frame_data
->render_pass_list
, device_scale_factor_
,
165 device_viewport_rect
, device_clip_rect
,
166 disable_picture_quad_image_filtering
);
169 if (should_draw
&& !avoid_swap
) {
170 renderer_
->SwapBuffers(frame
->metadata
);
172 stored_latency_info_
.insert(stored_latency_info_
.end(),
173 frame
->metadata
.latency_info
.begin(),
174 frame
->metadata
.latency_info
.end());
176 DidSwapBuffersComplete();
182 void Display::DidSwapBuffers() {
183 client_
->DidSwapBuffers();
186 void Display::DidSwapBuffersComplete() {
187 client_
->DidSwapBuffersComplete();
190 void Display::CommitVSyncParameters(base::TimeTicks timebase
,
191 base::TimeDelta interval
) {
192 client_
->CommitVSyncParameters(timebase
, interval
);
195 void Display::SetMemoryPolicy(const ManagedMemoryPolicy
& policy
) {
196 client_
->SetMemoryPolicy(policy
);
199 void Display::OnDraw() {
203 void Display::DeferredInitialize() {
207 void Display::ReleaseGL() {
211 void Display::SetNeedsRedrawRect(const gfx::Rect
& damage_rect
) {
215 void Display::ReclaimResources(const CompositorFrameAck
* ack
) {
219 void Display::SetExternalDrawConstraints(
220 const gfx::Transform
& transform
,
221 const gfx::Rect
& viewport
,
222 const gfx::Rect
& clip
,
223 const gfx::Rect
& viewport_rect_for_tile_priority
,
224 const gfx::Transform
& transform_for_tile_priority
,
225 bool resourceless_software_draw
) {
229 void Display::SetTreeActivationCallback(const base::Closure
& callback
) {
233 void Display::SetFullRootLayerDamage() {
237 void Display::OnSurfaceDamaged(SurfaceId surface_id
, bool* changed
) {
239 aggregator_
->previous_contained_surfaces().count(surface_id
)) {
240 Surface
* surface
= manager_
->GetSurfaceForId(surface_id
);
242 const CompositorFrame
* current_frame
= surface
->GetEligibleFrame();
243 if (!current_frame
|| !current_frame
->delegated_frame_data
||
244 !current_frame
->delegated_frame_data
->resource_list
.size())
245 aggregator_
->ReleaseResources(surface_id
);
247 client_
->DisplayDamaged();
249 } else if (surface_id
== current_surface_id_
) {
250 client_
->DisplayDamaged();
255 SurfaceId
Display::CurrentSurfaceId() {
256 return current_surface_id_
;
259 int Display::GetMaxFramesPending() {
260 int max_frames_pending
=
261 output_surface_
? output_surface_
->capabilities().max_frames_pending
: 0;
262 if (max_frames_pending
<= 0)
263 max_frames_pending
= OutputSurface::DEFAULT_MAX_FRAMES_PENDING
;
264 return max_frames_pending
;