| 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_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 Loading... |
| 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 |
| OLD | NEW |