Chromium Code Reviews| OLD | NEW |
|---|---|
| 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_frame_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 (factory_) { |
| 35 UnrefFrameResources(*current_frame_); | 36 if (pending_frame_) |
| 37 UnrefFrameResources(*pending_frame_); | |
| 38 if (active_frame_) | |
| 39 UnrefFrameResources(*active_frame_); | |
| 36 } | 40 } |
| 37 if (!draw_callback_.is_null()) | 41 if (!draw_callback_.is_null()) |
| 38 draw_callback_.Run(); | 42 draw_callback_.Run(); |
| 43 | |
| 44 for (auto& observer : observers_) | |
| 45 observer.OnSurfaceDiscarded(this); | |
| 46 observers_.Clear(); | |
| 39 } | 47 } |
| 40 | 48 |
| 41 void Surface::SetPreviousFrameSurface(Surface* surface) { | 49 void Surface::SetPreviousFrameSurface(Surface* surface) { |
| 42 DCHECK(surface); | 50 DCHECK(surface); |
| 43 frame_index_ = surface->frame_index() + 1; | 51 frame_index_ = surface->frame_index() + 1; |
| 44 previous_frame_surface_id_ = surface->surface_id(); | 52 previous_frame_surface_id_ = surface->surface_id(); |
| 45 } | 53 } |
| 46 | 54 |
| 47 void Surface::QueueFrame(CompositorFrame frame, const DrawCallback& callback) { | 55 void Surface::QueueFrame(CompositorFrame frame, const DrawCallback& callback) { |
|
vmpstr
2017/02/07 22:46:19
Can you extract the code between lines 60 and 96 t
Fady Samuel
2017/02/08 00:52:49
Done.
| |
| 48 DCHECK(factory_); | 56 base::Optional<CompositorFrame> previous_pending_frame = |
| 49 ClearCopyRequests(); | 57 std::move(pending_frame_); |
| 58 pending_frame_.reset(); | |
| 50 | 59 |
| 51 TakeLatencyInfo(&frame.metadata.latency_info); | 60 std::unordered_set<SurfaceId, SurfaceIdHash> new_blocked_on_surfaces; |
| 52 | 61 |
| 53 base::Optional<CompositorFrame> previous_frame = std::move(current_frame_); | 62 for (const SurfaceId& surface_id : frame.metadata.referenced_surfaces) { |
| 54 current_frame_ = std::move(frame); | 63 Surface* surface = factory_->manager()->GetSurfaceForId(surface_id); |
| 55 | 64 // If a referenced surface does not have a corresponding active frame in the |
| 56 if (current_frame_) { | 65 // display compositor, then it blocks this frame. |
| 57 factory_->ReceiveFromChild(current_frame_->resource_list); | 66 if (!surface || !surface->HasActiveFrame()) |
| 67 new_blocked_on_surfaces.insert(surface_id); | |
| 58 } | 68 } |
| 59 | 69 |
| 60 // Empty frames shouldn't be drawn and shouldn't contribute damage, so don't | 70 // If this Surface has a previous pending frame, then we must determine the |
| 61 // increment frame index for them. | 71 // changes in dependencies so that we can update the |
| 62 if (current_frame_ && !current_frame_->render_pass_list.empty()) { | 72 // DisplayCompositorLockManager map. |
| 63 ++frame_index_; | 73 if (previous_pending_frame.has_value()) { |
| 74 SurfaceDependencies added_dependencies; | |
|
vmpstr
2017/02/07 22:46:19
move this to right before the second for loop plea
Fady Samuel
2017/02/08 00:52:49
Done.
| |
| 75 SurfaceDependencies removed_dependencies; | |
| 76 | |
| 77 for (const SurfaceId& surface_id : blocked_on_surfaces_) { | |
|
vmpstr
2017/02/07 22:46:19
If you use flat_sets which are ordered, then I thi
Fady Samuel
2017/02/08 00:52:49
I'll leave it as is for now.
| |
| 78 if (!new_blocked_on_surfaces.count(surface_id)) | |
| 79 removed_dependencies.insert(surface_id); | |
| 80 } | |
| 81 | |
| 82 for (const SurfaceId& surface_id : new_blocked_on_surfaces) { | |
| 83 if (!blocked_on_surfaces_.count(surface_id)) | |
| 84 added_dependencies.insert(surface_id); | |
| 85 } | |
| 86 | |
| 87 // If there is a change in the dependency set, then inform observers. | |
| 88 if (!added_dependencies.empty() || !removed_dependencies.empty()) { | |
| 89 for (auto& observer : observers_) { | |
| 90 observer.OnSurfaceChanged(this, added_dependencies, | |
| 91 removed_dependencies); | |
| 92 } | |
| 93 } | |
| 64 } | 94 } |
| 65 | 95 |
| 66 previous_frame_surface_id_ = surface_id(); | 96 blocked_on_surfaces_ = std::move(new_blocked_on_surfaces); |
| 67 | 97 |
| 68 if (previous_frame) | 98 if (!blocked_on_surfaces_.empty()) { |
| 69 UnrefFrameResources(*previous_frame); | 99 pending_frame_ = std::move(frame); |
| 100 if (pending_frame_) { | |
| 101 factory_->ReceiveFromChild(pending_frame_->resource_list); | |
| 102 // Ask the surface manager to inform |this| when its dependencies are | |
| 103 // resolved. | |
| 104 factory_->manager()->RequestSurfaceResolution(this); | |
| 105 } | |
| 106 } else { | |
| 107 // If there are no blockers, then immediately activate the frame. | |
| 108 ActivateFrame(std::move(frame)); | |
| 109 } | |
| 110 | |
| 111 // Returns resources for the previous pending frame. | |
| 112 if (previous_pending_frame) | |
| 113 UnrefFrameResources(*previous_pending_frame); | |
| 70 | 114 |
| 71 if (!draw_callback_.is_null()) | 115 if (!draw_callback_.is_null()) |
| 72 draw_callback_.Run(); | 116 draw_callback_.Run(); |
| 73 draw_callback_ = callback; | 117 draw_callback_ = callback; |
| 74 | |
| 75 referenced_surfaces_ = current_frame_->metadata.referenced_surfaces; | |
| 76 } | 118 } |
| 77 | 119 |
| 78 void Surface::EvictFrame() { | 120 void Surface::EvictFrame() { |
| 79 QueueFrame(CompositorFrame(), DrawCallback()); | 121 QueueFrame(CompositorFrame(), DrawCallback()); |
| 80 current_frame_.reset(); | 122 active_frame_.reset(); |
| 81 } | 123 } |
| 82 | 124 |
| 83 void Surface::RequestCopyOfOutput( | 125 void Surface::RequestCopyOfOutput( |
| 84 std::unique_ptr<CopyOutputRequest> copy_request) { | 126 std::unique_ptr<CopyOutputRequest> copy_request) { |
| 85 if (current_frame_ && !current_frame_->render_pass_list.empty()) { | 127 if (active_frame_ && !active_frame_->render_pass_list.empty()) { |
|
vmpstr
2017/02/07 22:46:19
minor nit: while here, I think this would read bet
Fady Samuel
2017/02/08 00:52:49
Done.
| |
| 86 std::vector<std::unique_ptr<CopyOutputRequest>>& copy_requests = | 128 std::vector<std::unique_ptr<CopyOutputRequest>>& copy_requests = |
| 87 current_frame_->render_pass_list.back()->copy_requests; | 129 active_frame_->render_pass_list.back()->copy_requests; |
| 88 | 130 |
| 89 if (copy_request->has_source()) { | 131 if (copy_request->has_source()) { |
| 90 const base::UnguessableToken& source = copy_request->source(); | 132 const base::UnguessableToken& source = copy_request->source(); |
| 91 // Remove existing CopyOutputRequests made on the Surface by the same | 133 // Remove existing CopyOutputRequests made on the Surface by the same |
| 92 // source. | 134 // source. |
| 93 auto to_remove = std::remove_if( | 135 auto to_remove = std::remove_if( |
| 94 copy_requests.begin(), copy_requests.end(), | 136 copy_requests.begin(), copy_requests.end(), |
| 95 [&source](const std::unique_ptr<CopyOutputRequest>& x) { | 137 [&source](const std::unique_ptr<CopyOutputRequest>& x) { |
| 96 return x->has_source() && x->source() == source; | 138 return x->has_source() && x->source() == source; |
| 97 }); | 139 }); |
| 98 copy_requests.erase(to_remove, copy_requests.end()); | 140 copy_requests.erase(to_remove, copy_requests.end()); |
| 99 } | 141 } |
| 100 copy_requests.push_back(std::move(copy_request)); | 142 copy_requests.push_back(std::move(copy_request)); |
| 101 } else { | 143 } else { |
| 102 copy_request->SendEmptyResult(); | 144 copy_request->SendEmptyResult(); |
| 103 } | 145 } |
| 104 } | 146 } |
| 105 | 147 |
| 148 void Surface::ReportSurfaceIdAvailable(const SurfaceId& surface_id) { | |
| 149 auto it = blocked_on_surfaces_.find(surface_id); | |
| 150 // This surface may no longer have blockers if the deadline has passed. | |
| 151 if (it == blocked_on_surfaces_.end()) | |
| 152 return; | |
| 153 | |
| 154 blocked_on_surfaces_.erase(it); | |
| 155 | |
| 156 if (!blocked_on_surfaces_.empty()) | |
| 157 return; | |
| 158 | |
| 159 // All blockers have been cleared. The surface can be activated now. | |
| 160 ActivatePendingFrame(); | |
|
vmpstr
2017/02/07 22:46:19
Are we guaranteed to have a pending frame at this
Fady Samuel
2017/02/08 00:52:49
We got this far, which means we had a blocker (and
| |
| 161 } | |
| 162 | |
| 163 void Surface::AddObserver(PendingFrameObserver* observer) { | |
| 164 observers_.AddObserver(observer); | |
| 165 } | |
| 166 | |
| 167 void Surface::RemoveObserver(PendingFrameObserver* observer) { | |
| 168 observers_.RemoveObserver(observer); | |
| 169 } | |
| 170 | |
| 171 void Surface::ActivatePendingFrameForDeadline() { | |
| 172 if (!pending_frame_ || !pending_frame_->metadata.respect_deadline) | |
| 173 return; | |
| 174 | |
| 175 // If a frame is being activated because of a deadline, then clear its set | |
| 176 // of blockers. | |
| 177 blocked_on_surfaces_.clear(); | |
| 178 ActivatePendingFrame(); | |
| 179 } | |
| 180 | |
| 181 void Surface::ActivatePendingFrame() { | |
| 182 ActivateFrame(std::move(pending_frame_.value())); | |
| 183 pending_frame_.reset(); | |
| 184 // ActiveFrame resources are now double ref-ed. Unref. | |
| 185 UnrefFrameResources(*active_frame_); | |
| 186 } | |
| 187 | |
| 188 void Surface::ActivateFrame(CompositorFrame frame) { | |
|
vmpstr
2017/02/07 22:46:19
Can you add a comment at the top of the function t
Fady Samuel
2017/02/08 00:52:49
Done.
| |
| 189 DCHECK(factory_); | |
| 190 ClearCopyRequests(); | |
| 191 | |
| 192 TakeLatencyInfo(&frame.metadata.latency_info); | |
| 193 | |
| 194 base::Optional<CompositorFrame> previous_frame = std::move(active_frame_); | |
| 195 active_frame_ = std::move(frame); | |
| 196 | |
| 197 if (active_frame_) | |
|
vmpstr
2017/02/07 22:46:19
In what situations can we not have an active_frame
Fady Samuel
2017/02/08 00:52:49
Heh, We just set the active_frame_ so we should ha
| |
| 198 factory_->ReceiveFromChild(active_frame_->resource_list); | |
| 199 | |
| 200 // Empty frames shouldn't be drawn and shouldn't contribute damage, so don't | |
| 201 // increment frame index for them. | |
| 202 if (active_frame_ && !active_frame_->render_pass_list.empty()) | |
| 203 ++frame_index_; | |
| 204 | |
| 205 previous_frame_surface_id_ = surface_id(); | |
| 206 | |
| 207 if (previous_frame) | |
| 208 UnrefFrameResources(*previous_frame); | |
| 209 | |
| 210 referenced_surfaces_ = active_frame_->metadata.referenced_surfaces; | |
| 211 | |
| 212 for (auto& observer : observers_) | |
| 213 observer.OnSurfaceActivated(this); | |
| 214 } | |
| 215 | |
| 106 void Surface::TakeCopyOutputRequests( | 216 void Surface::TakeCopyOutputRequests( |
| 107 std::multimap<int, std::unique_ptr<CopyOutputRequest>>* copy_requests) { | 217 std::multimap<int, std::unique_ptr<CopyOutputRequest>>* copy_requests) { |
| 108 DCHECK(copy_requests->empty()); | 218 DCHECK(copy_requests->empty()); |
| 109 if (current_frame_) { | 219 if (active_frame_) { |
|
vmpstr
2017/02/07 22:46:19
nit:
if (!active_frame_)
return;
...
Fady Samuel
2017/02/08 00:52:49
Done.
| |
| 110 for (const auto& render_pass : current_frame_->render_pass_list) { | 220 for (const auto& render_pass : active_frame_->render_pass_list) { |
| 111 for (auto& request : render_pass->copy_requests) { | 221 for (auto& request : render_pass->copy_requests) { |
| 112 copy_requests->insert( | 222 copy_requests->insert( |
| 113 std::make_pair(render_pass->id, std::move(request))); | 223 std::make_pair(render_pass->id, std::move(request))); |
| 114 } | 224 } |
| 115 render_pass->copy_requests.clear(); | 225 render_pass->copy_requests.clear(); |
| 116 } | 226 } |
| 117 } | 227 } |
| 118 } | 228 } |
| 119 | 229 |
| 120 const CompositorFrame& Surface::GetEligibleFrame() const { | 230 const CompositorFrame& Surface::GetActiveFrame() const { |
| 121 DCHECK(current_frame_); | 231 DCHECK(active_frame_); |
| 122 return current_frame_.value(); | 232 return active_frame_.value(); |
| 233 } | |
| 234 | |
| 235 const CompositorFrame& Surface::GetPendingFrame() { | |
| 236 DCHECK(pending_frame_); | |
| 237 return pending_frame_.value(); | |
| 123 } | 238 } |
| 124 | 239 |
| 125 void Surface::TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info) { | 240 void Surface::TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info) { |
| 126 if (!current_frame_) | 241 if (!active_frame_) |
| 127 return; | 242 return; |
| 128 if (latency_info->empty()) { | 243 if (latency_info->empty()) { |
| 129 current_frame_->metadata.latency_info.swap(*latency_info); | 244 active_frame_->metadata.latency_info.swap(*latency_info); |
| 130 return; | 245 return; |
| 131 } | 246 } |
| 132 std::copy(current_frame_->metadata.latency_info.begin(), | 247 std::copy(active_frame_->metadata.latency_info.begin(), |
| 133 current_frame_->metadata.latency_info.end(), | 248 active_frame_->metadata.latency_info.end(), |
| 134 std::back_inserter(*latency_info)); | 249 std::back_inserter(*latency_info)); |
| 135 current_frame_->metadata.latency_info.clear(); | 250 active_frame_->metadata.latency_info.clear(); |
| 136 } | 251 } |
| 137 | 252 |
| 138 void Surface::RunDrawCallbacks() { | 253 void Surface::RunDrawCallbacks() { |
| 139 if (!draw_callback_.is_null()) { | 254 if (!draw_callback_.is_null()) { |
| 140 DrawCallback callback = draw_callback_; | 255 DrawCallback callback = draw_callback_; |
| 141 draw_callback_ = DrawCallback(); | 256 draw_callback_ = DrawCallback(); |
| 142 callback.Run(); | 257 callback.Run(); |
| 143 } | 258 } |
| 144 } | 259 } |
| 145 | 260 |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 163 void Surface::UnrefFrameResources(const CompositorFrame& frame) { | 278 void Surface::UnrefFrameResources(const CompositorFrame& frame) { |
| 164 ReturnedResourceArray resources; | 279 ReturnedResourceArray resources; |
| 165 TransferableResource::ReturnResources(frame.resource_list, &resources); | 280 TransferableResource::ReturnResources(frame.resource_list, &resources); |
| 166 // No point in returning same sync token to sender. | 281 // No point in returning same sync token to sender. |
| 167 for (auto& resource : resources) | 282 for (auto& resource : resources) |
| 168 resource.sync_token.Clear(); | 283 resource.sync_token.Clear(); |
| 169 factory_->UnrefResources(resources); | 284 factory_->UnrefResources(resources); |
| 170 } | 285 } |
| 171 | 286 |
| 172 void Surface::ClearCopyRequests() { | 287 void Surface::ClearCopyRequests() { |
| 173 if (current_frame_) { | 288 if (active_frame_) { |
| 174 for (const auto& render_pass : current_frame_->render_pass_list) { | 289 for (const auto& render_pass : active_frame_->render_pass_list) { |
| 175 for (const auto& copy_request : render_pass->copy_requests) | 290 for (const auto& copy_request : render_pass->copy_requests) |
| 176 copy_request->SendEmptyResult(); | 291 copy_request->SendEmptyResult(); |
| 177 } | 292 } |
| 178 } | 293 } |
| 179 } | 294 } |
| 180 | 295 |
| 181 } // namespace cc | 296 } // namespace cc |
| OLD | NEW |