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.
4
5 #include "cc/surfaces/display.h"
6
7 #include "base/debug/trace_event.h"
8 #include "base/message_loop/message_loop.h"
9 #include "cc/output/compositor_frame.h"
10 #include "cc/output/compositor_frame_ack.h"
11 #include "cc/output/direct_renderer.h"
12 #include "cc/output/gl_renderer.h"
13 #include "cc/output/software_renderer.h"
14 #include "cc/surfaces/display_client.h"
15 #include "cc/surfaces/surface.h"
16 #include "cc/surfaces/surface_aggregator.h"
17 #include "cc/surfaces/surface_manager.h"
18 #include "cc/trees/blocking_task_runner.h"
19
20 namespace cc {
21
Display(DisplayClient * client,SurfaceManager * manager,SharedBitmapManager * bitmap_manager)22 Display::Display(DisplayClient* client,
23 SurfaceManager* manager,
24 SharedBitmapManager* bitmap_manager)
25 : client_(client),
26 manager_(manager),
27 bitmap_manager_(bitmap_manager),
28 blocking_main_thread_task_runner_(
29 BlockingTaskRunner::Create(base::MessageLoopProxy::current())) {
30 manager_->AddObserver(this);
31 }
32
~Display()33 Display::~Display() {
34 manager_->RemoveObserver(this);
35 }
36
Resize(SurfaceId id,const gfx::Size & size)37 void Display::Resize(SurfaceId id, const gfx::Size& size) {
38 current_surface_id_ = id;
39 current_surface_size_ = size;
40 client_->DisplayDamaged();
41 }
42
InitializeOutputSurface()43 void Display::InitializeOutputSurface() {
44 if (output_surface_)
45 return;
46 scoped_ptr<OutputSurface> output_surface = client_->CreateOutputSurface();
47 if (!output_surface->BindToClient(this))
48 return;
49
50 int highp_threshold_min = 0;
51 bool use_rgba_4444_texture_format = false;
52 size_t id_allocation_chunk_size = 1;
53 bool use_distance_field_text = false;
54 scoped_ptr<ResourceProvider> resource_provider =
55 ResourceProvider::Create(output_surface.get(),
56 bitmap_manager_,
57 blocking_main_thread_task_runner_.get(),
58 highp_threshold_min,
59 use_rgba_4444_texture_format,
60 id_allocation_chunk_size,
61 use_distance_field_text);
62 if (!resource_provider)
63 return;
64
65 if (output_surface->context_provider()) {
66 TextureMailboxDeleter* texture_mailbox_deleter = NULL;
67 scoped_ptr<GLRenderer> renderer =
68 GLRenderer::Create(this,
69 &settings_,
70 output_surface.get(),
71 resource_provider.get(),
72 texture_mailbox_deleter,
73 highp_threshold_min);
74 if (!renderer)
75 return;
76 renderer_ = renderer.Pass();
77 } else {
78 scoped_ptr<SoftwareRenderer> renderer = SoftwareRenderer::Create(
79 this, &settings_, output_surface.get(), resource_provider.get());
80 if (!renderer)
81 return;
82 renderer_ = renderer.Pass();
83 }
84
85 output_surface_ = output_surface.Pass();
86 resource_provider_ = resource_provider.Pass();
87 aggregator_.reset(new SurfaceAggregator(manager_, resource_provider_.get()));
88 }
89
Draw()90 bool Display::Draw() {
91 if (current_surface_id_.is_null())
92 return false;
93
94 InitializeOutputSurface();
95 if (!output_surface_)
96 return false;
97
98 // TODO(skyostil): We should hold a BlockingTaskRunner::CapturePostTasks
99 // while Aggregate is called to immediately run release callbacks afterward.
100 scoped_ptr<CompositorFrame> frame =
101 aggregator_->Aggregate(current_surface_id_);
102 if (!frame)
103 return false;
104
105 TRACE_EVENT0("cc", "Display::Draw");
106 DelegatedFrameData* frame_data = frame->delegated_frame_data.get();
107
108 // Only reshape when we know we are going to draw. Otherwise, the reshape
109 // can leave the window at the wrong size if we never draw and the proper
110 // viewport size is never set.
111 output_surface_->Reshape(current_surface_size_, 1.f);
112 float device_scale_factor = 1.0f;
113 gfx::Rect device_viewport_rect = gfx::Rect(current_surface_size_);
114 gfx::Rect device_clip_rect = device_viewport_rect;
115 bool disable_picture_quad_image_filtering = false;
116
117 renderer_->DecideRenderPassAllocationsForFrame(frame_data->render_pass_list);
118 renderer_->DrawFrame(&frame_data->render_pass_list,
119 device_scale_factor,
120 device_viewport_rect,
121 device_clip_rect,
122 disable_picture_quad_image_filtering);
123 renderer_->SwapBuffers(frame->metadata);
124 for (SurfaceAggregator::SurfaceIndexMap::iterator it =
125 aggregator_->previous_contained_surfaces().begin();
126 it != aggregator_->previous_contained_surfaces().end();
127 ++it) {
128 Surface* surface = manager_->GetSurfaceForId(it->first);
129 if (surface)
130 surface->RunDrawCallbacks();
131 }
132 return true;
133 }
134
DidSwapBuffers()135 void Display::DidSwapBuffers() {
136 client_->DidSwapBuffers();
137 }
138
DidSwapBuffersComplete()139 void Display::DidSwapBuffersComplete() {
140 client_->DidSwapBuffersComplete();
141 }
142
CommitVSyncParameters(base::TimeTicks timebase,base::TimeDelta interval)143 void Display::CommitVSyncParameters(base::TimeTicks timebase,
144 base::TimeDelta interval) {
145 client_->CommitVSyncParameters(timebase, interval);
146 }
147
OnSurfaceDamaged(SurfaceId surface)148 void Display::OnSurfaceDamaged(SurfaceId surface) {
149 if (aggregator_ && aggregator_->previous_contained_surfaces().count(surface))
150 client_->DisplayDamaged();
151 }
152
CurrentSurfaceId()153 SurfaceId Display::CurrentSurfaceId() {
154 return current_surface_id_;
155 }
156
GetMaxFramesPending()157 int Display::GetMaxFramesPending() {
158 if (!output_surface_)
159 return OutputSurface::DEFAULT_MAX_FRAMES_PENDING;
160 return output_surface_->capabilities().max_frames_pending;
161 }
162
163 } // namespace cc
164