Chromium Code Reviews| Index: cc/surfaces/surface.cc |
| diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc |
| index dd41c3de17b9ac999f29effb6fb84459ec1e3fc5..b72cfa8043ff0c3231a5570c80c8832aeca7793e 100644 |
| --- a/cc/surfaces/surface.cc |
| +++ b/cc/surfaces/surface.cc |
| @@ -12,6 +12,7 @@ |
| #include "cc/base/container_util.h" |
| #include "cc/output/compositor_frame.h" |
| #include "cc/output/copy_output_request.h" |
| +#include "cc/surfaces/pending_frame_observer.h" |
| #include "cc/surfaces/surface_factory.h" |
| #include "cc/surfaces/surface_id_allocator.h" |
| #include "cc/surfaces/surface_manager.h" |
| @@ -31,11 +32,18 @@ Surface::Surface(const SurfaceId& id, base::WeakPtr<SurfaceFactory> factory) |
| Surface::~Surface() { |
| ClearCopyRequests(); |
| - if (current_frame_ && factory_) { |
| - UnrefFrameResources(*current_frame_); |
| + if (factory_) { |
| + if (pending_frame_) |
| + UnrefFrameResources(*pending_frame_); |
| + if (active_frame_) |
| + UnrefFrameResources(*active_frame_); |
| } |
| if (!draw_callback_.is_null()) |
| draw_callback_.Run(); |
| + |
| + for (auto& observer : observers_) |
| + observer.OnSurfaceDiscarded(this); |
| + observers_.Clear(); |
| } |
| void Surface::SetPreviousFrameSurface(Surface* surface) { |
| @@ -45,46 +53,80 @@ void Surface::SetPreviousFrameSurface(Surface* surface) { |
| } |
| 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.
|
| - DCHECK(factory_); |
| - ClearCopyRequests(); |
| - |
| - TakeLatencyInfo(&frame.metadata.latency_info); |
| + base::Optional<CompositorFrame> previous_pending_frame = |
| + std::move(pending_frame_); |
| + pending_frame_.reset(); |
| - base::Optional<CompositorFrame> previous_frame = std::move(current_frame_); |
| - current_frame_ = std::move(frame); |
| + std::unordered_set<SurfaceId, SurfaceIdHash> new_blocked_on_surfaces; |
| - if (current_frame_) { |
| - factory_->ReceiveFromChild(current_frame_->resource_list); |
| + for (const SurfaceId& surface_id : frame.metadata.referenced_surfaces) { |
| + Surface* surface = factory_->manager()->GetSurfaceForId(surface_id); |
| + // If a referenced surface does not have a corresponding active frame in the |
| + // display compositor, then it blocks this frame. |
| + if (!surface || !surface->HasActiveFrame()) |
| + new_blocked_on_surfaces.insert(surface_id); |
| } |
| - // Empty frames shouldn't be drawn and shouldn't contribute damage, so don't |
| - // increment frame index for them. |
| - if (current_frame_ && !current_frame_->render_pass_list.empty()) { |
| - ++frame_index_; |
| + // If this Surface has a previous pending frame, then we must determine the |
| + // changes in dependencies so that we can update the |
| + // DisplayCompositorLockManager map. |
| + if (previous_pending_frame.has_value()) { |
| + 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.
|
| + SurfaceDependencies removed_dependencies; |
| + |
| + 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.
|
| + if (!new_blocked_on_surfaces.count(surface_id)) |
| + removed_dependencies.insert(surface_id); |
| + } |
| + |
| + for (const SurfaceId& surface_id : new_blocked_on_surfaces) { |
| + if (!blocked_on_surfaces_.count(surface_id)) |
| + added_dependencies.insert(surface_id); |
| + } |
| + |
| + // If there is a change in the dependency set, then inform observers. |
| + if (!added_dependencies.empty() || !removed_dependencies.empty()) { |
| + for (auto& observer : observers_) { |
| + observer.OnSurfaceChanged(this, added_dependencies, |
| + removed_dependencies); |
| + } |
| + } |
| } |
| - previous_frame_surface_id_ = surface_id(); |
| + blocked_on_surfaces_ = std::move(new_blocked_on_surfaces); |
| - if (previous_frame) |
| - UnrefFrameResources(*previous_frame); |
| + if (!blocked_on_surfaces_.empty()) { |
| + pending_frame_ = std::move(frame); |
| + if (pending_frame_) { |
| + factory_->ReceiveFromChild(pending_frame_->resource_list); |
| + // Ask the surface manager to inform |this| when its dependencies are |
| + // resolved. |
| + factory_->manager()->RequestSurfaceResolution(this); |
| + } |
| + } else { |
| + // If there are no blockers, then immediately activate the frame. |
| + ActivateFrame(std::move(frame)); |
| + } |
| + |
| + // Returns resources for the previous pending frame. |
| + if (previous_pending_frame) |
| + UnrefFrameResources(*previous_pending_frame); |
| if (!draw_callback_.is_null()) |
| draw_callback_.Run(); |
| draw_callback_ = callback; |
| - |
| - referenced_surfaces_ = current_frame_->metadata.referenced_surfaces; |
| } |
| void Surface::EvictFrame() { |
| QueueFrame(CompositorFrame(), DrawCallback()); |
| - current_frame_.reset(); |
| + active_frame_.reset(); |
| } |
| void Surface::RequestCopyOfOutput( |
| std::unique_ptr<CopyOutputRequest> copy_request) { |
| - if (current_frame_ && !current_frame_->render_pass_list.empty()) { |
| + 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.
|
| std::vector<std::unique_ptr<CopyOutputRequest>>& copy_requests = |
| - current_frame_->render_pass_list.back()->copy_requests; |
| + active_frame_->render_pass_list.back()->copy_requests; |
| if (copy_request->has_source()) { |
| const base::UnguessableToken& source = copy_request->source(); |
| @@ -103,11 +145,79 @@ void Surface::RequestCopyOfOutput( |
| } |
| } |
| +void Surface::ReportSurfaceIdAvailable(const SurfaceId& surface_id) { |
| + auto it = blocked_on_surfaces_.find(surface_id); |
| + // This surface may no longer have blockers if the deadline has passed. |
| + if (it == blocked_on_surfaces_.end()) |
| + return; |
| + |
| + blocked_on_surfaces_.erase(it); |
| + |
| + if (!blocked_on_surfaces_.empty()) |
| + return; |
| + |
| + // All blockers have been cleared. The surface can be activated now. |
| + 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
|
| +} |
| + |
| +void Surface::AddObserver(PendingFrameObserver* observer) { |
| + observers_.AddObserver(observer); |
| +} |
| + |
| +void Surface::RemoveObserver(PendingFrameObserver* observer) { |
| + observers_.RemoveObserver(observer); |
| +} |
| + |
| +void Surface::ActivatePendingFrameForDeadline() { |
| + if (!pending_frame_ || !pending_frame_->metadata.respect_deadline) |
| + return; |
| + |
| + // If a frame is being activated because of a deadline, then clear its set |
| + // of blockers. |
| + blocked_on_surfaces_.clear(); |
| + ActivatePendingFrame(); |
| +} |
| + |
| +void Surface::ActivatePendingFrame() { |
| + ActivateFrame(std::move(pending_frame_.value())); |
| + pending_frame_.reset(); |
| + // ActiveFrame resources are now double ref-ed. Unref. |
| + UnrefFrameResources(*active_frame_); |
| +} |
| + |
| +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.
|
| + DCHECK(factory_); |
| + ClearCopyRequests(); |
| + |
| + TakeLatencyInfo(&frame.metadata.latency_info); |
| + |
| + base::Optional<CompositorFrame> previous_frame = std::move(active_frame_); |
| + active_frame_ = std::move(frame); |
| + |
| + 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
|
| + factory_->ReceiveFromChild(active_frame_->resource_list); |
| + |
| + // Empty frames shouldn't be drawn and shouldn't contribute damage, so don't |
| + // increment frame index for them. |
| + if (active_frame_ && !active_frame_->render_pass_list.empty()) |
| + ++frame_index_; |
| + |
| + previous_frame_surface_id_ = surface_id(); |
| + |
| + if (previous_frame) |
| + UnrefFrameResources(*previous_frame); |
| + |
| + referenced_surfaces_ = active_frame_->metadata.referenced_surfaces; |
| + |
| + for (auto& observer : observers_) |
| + observer.OnSurfaceActivated(this); |
| +} |
| + |
| void Surface::TakeCopyOutputRequests( |
| std::multimap<int, std::unique_ptr<CopyOutputRequest>>* copy_requests) { |
| DCHECK(copy_requests->empty()); |
| - if (current_frame_) { |
| - for (const auto& render_pass : current_frame_->render_pass_list) { |
| + if (active_frame_) { |
|
vmpstr
2017/02/07 22:46:19
nit:
if (!active_frame_)
return;
...
Fady Samuel
2017/02/08 00:52:49
Done.
|
| + for (const auto& render_pass : active_frame_->render_pass_list) { |
| for (auto& request : render_pass->copy_requests) { |
| copy_requests->insert( |
| std::make_pair(render_pass->id, std::move(request))); |
| @@ -117,22 +227,27 @@ void Surface::TakeCopyOutputRequests( |
| } |
| } |
| -const CompositorFrame& Surface::GetEligibleFrame() const { |
| - DCHECK(current_frame_); |
| - return current_frame_.value(); |
| +const CompositorFrame& Surface::GetActiveFrame() const { |
| + DCHECK(active_frame_); |
| + return active_frame_.value(); |
| +} |
| + |
| +const CompositorFrame& Surface::GetPendingFrame() { |
| + DCHECK(pending_frame_); |
| + return pending_frame_.value(); |
| } |
| void Surface::TakeLatencyInfo(std::vector<ui::LatencyInfo>* latency_info) { |
| - if (!current_frame_) |
| + if (!active_frame_) |
| return; |
| if (latency_info->empty()) { |
| - current_frame_->metadata.latency_info.swap(*latency_info); |
| + active_frame_->metadata.latency_info.swap(*latency_info); |
| return; |
| } |
| - std::copy(current_frame_->metadata.latency_info.begin(), |
| - current_frame_->metadata.latency_info.end(), |
| + std::copy(active_frame_->metadata.latency_info.begin(), |
| + active_frame_->metadata.latency_info.end(), |
| std::back_inserter(*latency_info)); |
| - current_frame_->metadata.latency_info.clear(); |
| + active_frame_->metadata.latency_info.clear(); |
| } |
| void Surface::RunDrawCallbacks() { |
| @@ -170,8 +285,8 @@ void Surface::UnrefFrameResources(const CompositorFrame& frame) { |
| } |
| void Surface::ClearCopyRequests() { |
| - if (current_frame_) { |
| - for (const auto& render_pass : current_frame_->render_pass_list) { |
| + if (active_frame_) { |
| + for (const auto& render_pass : active_frame_->render_pass_list) { |
| for (const auto& copy_request : render_pass->copy_requests) |
| copy_request->SendEmptyResult(); |
| } |