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

Unified Diff: cc/surfaces/surface.cc

Issue 2676373004: Implement service-side surface synchronization (Closed)
Patch Set: DisplayCompositorLockManager => SurfaceDependencyTracker. Added More Comments 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 side-by-side diff with in-line comments
Download patch
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();
}

Powered by Google App Engine
This is Rietveld 408576698