Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(560)

Side by Side Diff: cc/surfaces/surface.cc

Issue 2582823002: WIP: Surface Synchronization System
Patch Set: Only create ClientSurfaceEmbedder if window is visible. Trash it otherwise. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/surfaces/surface.h" 5 #include "cc/surfaces/surface.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <stdint.h> 8 #include <stdint.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
11 11
12 #include "cc/base/container_util.h" 12 #include "cc/base/container_util.h"
13 #include "cc/output/compositor_frame.h" 13 #include "cc/output/compositor_frame.h"
14 #include "cc/output/copy_output_request.h" 14 #include "cc/output/copy_output_request.h"
15 #include "cc/surfaces/pending_surface_observer.h"
15 #include "cc/surfaces/surface_factory.h" 16 #include "cc/surfaces/surface_factory.h"
16 #include "cc/surfaces/surface_id_allocator.h" 17 #include "cc/surfaces/surface_id_allocator.h"
17 #include "cc/surfaces/surface_manager.h" 18 #include "cc/surfaces/surface_manager.h"
18 19
19 namespace cc { 20 namespace cc {
20 21
21 // The frame index starts at 2 so that empty frames will be treated as 22 // The frame index starts at 2 so that empty frames will be treated as
22 // completely damaged the first time they're drawn from. 23 // completely damaged the first time they're drawn from.
23 static const int kFrameIndexStart = 2; 24 static const int kFrameIndexStart = 2;
24 25
25 Surface::Surface(const SurfaceId& id, base::WeakPtr<SurfaceFactory> factory) 26 Surface::Surface(const SurfaceId& id, base::WeakPtr<SurfaceFactory> factory)
26 : surface_id_(id), 27 : surface_id_(id),
27 previous_frame_surface_id_(id), 28 previous_frame_surface_id_(id),
28 factory_(factory), 29 factory_(factory),
29 frame_index_(kFrameIndexStart), 30 frame_index_(kFrameIndexStart),
30 destroyed_(false) {} 31 destroyed_(false) {}
31 32
32 Surface::~Surface() { 33 Surface::~Surface() {
33 ClearCopyRequests(); 34 ClearCopyRequests();
34 if (current_frame_ && factory_) { 35 if (active_frame_ && factory_) {
35 UnrefFrameResources(*current_frame_); 36 UnrefFrameResources(*active_frame_);
36 } 37 }
37 if (!draw_callback_.is_null()) 38 if (!draw_callback_.is_null())
38 draw_callback_.Run(); 39 draw_callback_.Run();
40
41 for (auto& observer : observers_)
42 observer.OnSurfaceDiscarded(this);
43 observers_.Clear();
39 } 44 }
40 45
41 void Surface::SetPreviousFrameSurface(Surface* surface) { 46 void Surface::SetPreviousFrameSurface(Surface* surface) {
42 DCHECK(surface); 47 DCHECK(surface);
43 frame_index_ = surface->frame_index() + 1; 48 frame_index_ = surface->frame_index() + 1;
44 previous_frame_surface_id_ = surface->surface_id(); 49 previous_frame_surface_id_ = surface->surface_id();
45 } 50 }
46 51
47 void Surface::QueueFrame(CompositorFrame frame, const DrawCallback& callback) { 52 void Surface::QueueFrame(CompositorFrame frame, const DrawCallback& callback) {
48 DCHECK(factory_); 53 base::Optional<CompositorFrame> previous_pending_frame =
49 ClearCopyRequests(); 54 std::move(pending_frame_);
55 pending_frame_.reset();
50 56
51 TakeLatencyInfo(&frame.metadata.latency_info); 57 std::set<SurfaceId> new_blocked_on_surfaces;
52 58
53 base::Optional<CompositorFrame> previous_frame = std::move(current_frame_); 59 // Referenced surface IDs that aren't currently known to the surface manager
54 current_frame_ = std::move(frame); 60 // block this frame.
55 61 for (const SurfaceId& surface_id : frame.metadata.referenced_surfaces) {
56 if (current_frame_) { 62 Surface* surface = factory_->manager()->GetSurfaceForId(surface_id);
57 factory_->ReceiveFromChild(current_frame_->resource_list); 63 if (!surface || !surface->HasFrame())
64 new_blocked_on_surfaces.insert(surface_id);
58 } 65 }
59 66
60 // Empty frames shouldn't be drawn and shouldn't contribute damage, so don't 67 uint32_t added = 0;
61 // increment frame index for them. 68 uint32_t removed = 0;
62 if (current_frame_ && !current_frame_->render_pass_list.empty()) { 69
63 ++frame_index_; 70 if (previous_pending_frame.has_value()) {
71 SurfaceDependencies added_dependencies;
72 SurfaceDependencies removed_dependencies;
73
74 for (const SurfaceId& surface_id : blocked_on_surfaces_) {
75 if (!new_blocked_on_surfaces.count(surface_id))
76 removed_dependencies.insert(surface_id);
77 }
78
79 for (const SurfaceId& surface_id : new_blocked_on_surfaces) {
80 if (!blocked_on_surfaces_.count(surface_id)) {
81 added_dependencies.insert(surface_id);
82 fprintf(stderr, ">>>[%s] QueueFrame Blocked On: %s\n",
83 this->surface_id().ToString().c_str(),
84 surface_id.ToString().c_str());
85 }
86 }
87
88 added = added_dependencies.size();
89 removed = removed_dependencies.size();
90
91 if (!added_dependencies.empty() || !removed_dependencies.empty()) {
92 for (auto& observer : observers_) {
93 observer.OnSurfaceChanged(this, added_dependencies,
94 removed_dependencies);
95 }
96 }
64 } 97 }
65 98
66 previous_frame_surface_id_ = surface_id(); 99 blocked_on_surfaces_ = std::move(new_blocked_on_surfaces);
100 if (blocked_on_surfaces_.size() > 0) {
101 std::stringstream sstr;
102 sstr << "{" << std::endl;
103 for (const auto& surface_id : blocked_on_surfaces_) {
104 sstr << " " << surface_id.ToString() << "\n";
105 }
106 sstr << "}" << std::endl;
67 107
68 if (previous_frame) 108 fprintf(
69 UnrefFrameResources(*previous_frame); 109 stderr,
110 ">>>[%s] QueueFrame blocked_on_surfaces: %d added: %d removed: %d\n%s",
111 surface_id().ToString().c_str(), (uint32_t)blocked_on_surfaces_.size(),
112 added, removed, sstr.str().c_str());
113 }
114
115 if (!blocked_on_surfaces_.empty()) {
116 pending_frame_ = std::move(frame);
117 if (pending_frame_)
118 factory_->ReceiveFromChild(pending_frame_->resource_list);
119 } else {
120 fprintf(stderr, ">>>Surface::QueueFrame activating frame: %s\n",
121 surface_id().ToString().c_str());
122 ActivateFrame(std::move(frame));
123 }
124
125 if (previous_pending_frame)
126 UnrefFrameResources(*previous_pending_frame);
70 127
71 if (!draw_callback_.is_null()) 128 if (!draw_callback_.is_null())
72 draw_callback_.Run(); 129 draw_callback_.Run();
73 draw_callback_ = callback; 130 draw_callback_ = callback;
74
75 referenced_surfaces_ = current_frame_->metadata.referenced_surfaces;
76 } 131 }
77 132
78 void Surface::EvictFrame() { 133 void Surface::EvictFrame() {
79 QueueFrame(CompositorFrame(), DrawCallback()); 134 QueueFrame(CompositorFrame(), DrawCallback());
80 current_frame_.reset(); 135 active_frame_.reset();
81 } 136 }
82 137
83 void Surface::RequestCopyOfOutput( 138 void Surface::RequestCopyOfOutput(
84 std::unique_ptr<CopyOutputRequest> copy_request) { 139 std::unique_ptr<CopyOutputRequest> copy_request) {
85 if (current_frame_ && !current_frame_->render_pass_list.empty()) { 140 if (active_frame_ && !active_frame_->render_pass_list.empty()) {
86 std::vector<std::unique_ptr<CopyOutputRequest>>& copy_requests = 141 std::vector<std::unique_ptr<CopyOutputRequest>>& copy_requests =
87 current_frame_->render_pass_list.back()->copy_requests; 142 active_frame_->render_pass_list.back()->copy_requests;
88 143
89 if (void* source = copy_request->source()) { 144 if (void* source = copy_request->source()) {
90 // Remove existing CopyOutputRequests made on the Surface by the same 145 // Remove existing CopyOutputRequests made on the Surface by the same
91 // source. 146 // source.
92 auto to_remove = 147 auto to_remove =
93 std::remove_if(copy_requests.begin(), copy_requests.end(), 148 std::remove_if(copy_requests.begin(), copy_requests.end(),
94 [source](const std::unique_ptr<CopyOutputRequest>& x) { 149 [source](const std::unique_ptr<CopyOutputRequest>& x) {
95 return x->source() == source; 150 return x->source() == source;
96 }); 151 });
97 copy_requests.erase(to_remove, copy_requests.end()); 152 copy_requests.erase(to_remove, copy_requests.end());
98 } 153 }
99 copy_requests.push_back(std::move(copy_request)); 154 copy_requests.push_back(std::move(copy_request));
100 } else { 155 } else {
101 copy_request->SendEmptyResult(); 156 copy_request->SendEmptyResult();
102 } 157 }
103 } 158 }
104 159
160 void Surface::ReportSurfaceIdAvailable(const SurfaceId& surface_id) {
161 auto it = blocked_on_surfaces_.find(surface_id);
162 // This surface may no longer have blockers if the deadline has passed.
163 if (it == blocked_on_surfaces_.end())
164 return;
165
166 blocked_on_surfaces_.erase(it);
167 fprintf(stderr, ">>>[%s] %s available, %d remaining\n",
168 this->surface_id().ToString().c_str(), surface_id.ToString().c_str(),
169 (uint32_t)blocked_on_surfaces_.size());
170
171 if (!blocked_on_surfaces_.empty())
172 return;
173
174 // All blockers have been cleared. The surface can be activated now.
175 ActivatePendingFrame();
176 }
177
178 void Surface::AddObserver(PendingSurfaceObserver* observer) {
179 observers_.AddObserver(observer);
180 }
181
182 void Surface::RemoveObserver(PendingSurfaceObserver* observer) {
183 observers_.RemoveObserver(observer);
184 }
185
186 void Surface::ActivatePendingFrameForDeadline() {
187 if (!pending_frame_ || !pending_frame_->metadata.respect_deadline)
188 return;
189 std::stringstream sstr;
190 sstr << "Deadline for blockers: {" << std::endl;
191 for (const auto& surface_id : blocked_on_surfaces_) {
192 sstr << " " << surface_id.ToString() << "\n";
193 }
194 sstr << "}" << std::endl;
195
196 fprintf(stderr, ">>>Surface::ActivatePendingFrameForDeadline: %s\n%s",
197 surface_id().ToString().c_str(), sstr.str().c_str());
198
199 blocked_on_surfaces_.clear();
200 ActivatePendingFrame();
201 }
202
203 void Surface::ActivatePendingFrame() {
204 ActivateFrame(std::move(pending_frame_.value()));
205 pending_frame_.reset();
206 }
207
208 void Surface::ActivateFrame(CompositorFrame frame) {
209 DCHECK(factory_);
210 ClearCopyRequests();
211
212 TakeLatencyInfo(&frame.metadata.latency_info);
213
214 base::Optional<CompositorFrame> previous_frame = std::move(active_frame_);
215 active_frame_ = std::move(frame);
216
217 if (active_frame_)
218 factory_->ReceiveFromChild(active_frame_->resource_list);
219
220 // Empty frames shouldn't be drawn and shouldn't contribute damage, so don't
221 // increment frame index for them.
222 if (active_frame_ && !active_frame_->render_pass_list.empty())
223 ++frame_index_;
224
225 previous_frame_surface_id_ = surface_id();
226
227 if (previous_frame)
228 UnrefFrameResources(*previous_frame);
229
230 referenced_surfaces_ = active_frame_->metadata.referenced_surfaces;
231
232 for (auto& observer : observers_)
233 observer.OnSurfaceActivated(this);
234 }
235
105 void Surface::TakeCopyOutputRequests( 236 void Surface::TakeCopyOutputRequests(
106 std::multimap<int, std::unique_ptr<CopyOutputRequest>>* copy_requests) { 237 std::multimap<int, std::unique_ptr<CopyOutputRequest>>* copy_requests) {
107 DCHECK(copy_requests->empty()); 238 DCHECK(copy_requests->empty());
108 if (current_frame_) { 239 if (active_frame_) {
109 for (const auto& render_pass : current_frame_->render_pass_list) { 240 for (const auto& render_pass : active_frame_->render_pass_list) {
110 for (auto& request : render_pass->copy_requests) { 241 for (auto& request : render_pass->copy_requests) {
111 copy_requests->insert( 242 copy_requests->insert(
112 std::make_pair(render_pass->id, std::move(request))); 243 std::make_pair(render_pass->id, std::move(request)));
113 } 244 }
114 render_pass->copy_requests.clear(); 245 render_pass->copy_requests.clear();
115 } 246 }
116 } 247 }
117 } 248 }
118 249
119 const CompositorFrame& Surface::GetEligibleFrame() const { 250 const CompositorFrame& Surface::GetEligibleFrame() const {
120 DCHECK(current_frame_); 251 DCHECK(active_frame_);
121 return current_frame_.value(); 252 return active_frame_.value();
253 }
254
255 const base::Optional<CompositorFrame>& Surface::GetPendingFrame() {
256 return pending_frame_;
122 } 257 }
123 258
124 void Surface::TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info) { 259 void Surface::TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info) {
125 if (!current_frame_) 260 if (!active_frame_)
126 return; 261 return;
127 if (latency_info->empty()) { 262 if (latency_info->empty()) {
128 current_frame_->metadata.latency_info.swap(*latency_info); 263 active_frame_->metadata.latency_info.swap(*latency_info);
129 return; 264 return;
130 } 265 }
131 std::copy(current_frame_->metadata.latency_info.begin(), 266 std::copy(active_frame_->metadata.latency_info.begin(),
132 current_frame_->metadata.latency_info.end(), 267 active_frame_->metadata.latency_info.end(),
133 std::back_inserter(*latency_info)); 268 std::back_inserter(*latency_info));
134 current_frame_->metadata.latency_info.clear(); 269 active_frame_->metadata.latency_info.clear();
135 } 270 }
136 271
137 void Surface::RunDrawCallbacks() { 272 void Surface::RunDrawCallbacks() {
138 if (!draw_callback_.is_null()) { 273 if (!draw_callback_.is_null()) {
139 DrawCallback callback = draw_callback_; 274 DrawCallback callback = draw_callback_;
140 draw_callback_ = DrawCallback(); 275 draw_callback_ = DrawCallback();
141 callback.Run(); 276 callback.Run();
142 } 277 }
143 } 278 }
144 279
(...skipping 17 matching lines...) Expand all
162 void Surface::UnrefFrameResources(const CompositorFrame& frame) { 297 void Surface::UnrefFrameResources(const CompositorFrame& frame) {
163 ReturnedResourceArray resources; 298 ReturnedResourceArray resources;
164 TransferableResource::ReturnResources(frame.resource_list, &resources); 299 TransferableResource::ReturnResources(frame.resource_list, &resources);
165 // No point in returning same sync token to sender. 300 // No point in returning same sync token to sender.
166 for (auto& resource : resources) 301 for (auto& resource : resources)
167 resource.sync_token.Clear(); 302 resource.sync_token.Clear();
168 factory_->UnrefResources(resources); 303 factory_->UnrefResources(resources);
169 } 304 }
170 305
171 void Surface::ClearCopyRequests() { 306 void Surface::ClearCopyRequests() {
172 if (current_frame_) { 307 if (active_frame_) {
173 for (const auto& render_pass : current_frame_->render_pass_list) { 308 for (const auto& render_pass : active_frame_->render_pass_list) {
174 for (const auto& copy_request : render_pass->copy_requests) 309 for (const auto& copy_request : render_pass->copy_requests)
175 copy_request->SendEmptyResult(); 310 copy_request->SendEmptyResult();
176 } 311 }
177 } 312 }
178 } 313 }
179 314
180 } // namespace cc 315 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698