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

Unified Diff: cc/surfaces/surface_dependency_tracker.cc

Issue 2676373004: Implement service-side surface synchronization (Closed)
Patch Set: Use base::flat_set 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_dependency_tracker.cc
diff --git a/cc/surfaces/surface_dependency_tracker.cc b/cc/surfaces/surface_dependency_tracker.cc
new file mode 100644
index 0000000000000000000000000000000000000000..2f7b3580f2121067a3f8f92e5b06ff0b46c115a5
--- /dev/null
+++ b/cc/surfaces/surface_dependency_tracker.cc
@@ -0,0 +1,189 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "cc/surfaces/surface_dependency_tracker.h"
+
+#include "cc/surfaces/surface.h"
+#include "cc/surfaces/surface_info.h"
+#include "cc/surfaces/surface_manager.h"
+
+namespace cc {
+
+namespace {
+constexpr uint32_t kMaxBeginFrameCount = 4;
+}
+
+SurfaceDependencyTracker::SurfaceDependencyTracker(
+ SurfaceManager* surface_manager,
+ BeginFrameSource* begin_frame_source)
+ : surface_manager_(surface_manager),
+ begin_frame_source_(begin_frame_source) {
+ surface_manager_->AddObserver(this);
+ begin_frame_source_->AddObserver(this);
+}
+
+SurfaceDependencyTracker::~SurfaceDependencyTracker() {
+ surface_manager_->RemoveObserver(this);
+ begin_frame_source_->RemoveObserver(this);
+}
+
+void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) {
+ DCHECK(surface->HasPendingFrame());
+
+ const CompositorFrame& pending_frame = surface->GetPendingFrame();
+ bool needs_begin_frame =
+ pending_frame.metadata.can_activate_without_dependencies;
vmpstr 2017/02/08 19:25:40 oh, maybe "can_activate_before_dependencies" :D
Fady Samuel 2017/02/08 23:39:58 Done.
+
+ // Referenced surface IDs that aren't currently known to the surface manager
+ // or do not have an active CompsotiorFrame block this frame.
+ for (const SurfaceId& surface_id :
+ pending_frame.metadata.referenced_surfaces) {
+ Surface* surface_dep = surface_manager_->GetSurfaceForId(surface_id);
vmpstr 2017/02/08 19:25:39 s/surface_dep/dependency/
Fady Samuel 2017/02/08 23:39:58 Done.
+ if (!surface_dep || !surface_dep->HasActiveFrame())
+ blocking_surfaces_[surface_id].insert(surface);
vmpstr 2017/02/08 19:25:40 this to me says if the dependency isn't satisfied,
Fady Samuel 2017/02/08 23:39:58 If the dependency isn't satisfied, then it blocks
+ }
+
+ if (!pending_surfaces_.count(surface)) {
+ surface->AddObserver(this);
+ pending_surfaces_.insert(surface);
+ }
+
+ if (needs_begin_frame) {
vmpstr 2017/02/08 19:25:40 When can RequestSurfaceResolution be called? My wo
Fady Samuel 2017/02/08 23:39:58 Done.
+ has_deadline_ = true;
+ begin_frame_count_ = 0;
+ }
+}
+
+void SurfaceDependencyTracker::OnBeginFrame(const BeginFrameArgs& args) {
+ // If no deadline is set then we have nothing to do.
+ if (!has_deadline_)
+ return;
+
+ // TODO(fsamuel, kylechar): We have a single global deadline here. We should
+ // scope deadlines to surface subtrees. We cannot do that until
+ // SurfaceReferences have been fully implemented
+ // (see https://crbug.com/689719).
+ last_begin_frame_args_ = args;
+ // Nothing to do if we haven't hit a deadline yet.
+ if (++begin_frame_count_ != kMaxBeginFrameCount)
+ return;
+
+ // Activate all surfaces that respect the deadline.
+ PendingSurfaceSet pending_surfaces(pending_surfaces_);
+ for (Surface* pending_surface : pending_surfaces)
+ pending_surface->ActivatePendingFrameForDeadline();
+
+ has_deadline_ = false;
+ begin_frame_count_ = 0;
vmpstr 2017/02/08 19:25:39 You might hate the idea, but having a bool and an
Fady Samuel 2017/02/08 23:39:58 added base::Optional<uint32_t> frames_since_deadli
+}
+
+const BeginFrameArgs& SurfaceDependencyTracker::LastUsedBeginFrameArgs() const {
+ return last_begin_frame_args_;
+}
+
+void SurfaceDependencyTracker::OnBeginFrameSourcePausedChanged(bool paused) {}
+
+void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) {
+ // If the surface being destroyed doesn't have a pending frame then we have
+ // nothing to do here.
+ if (!surface->HasPendingFrame())
+ return;
+
+ const CompositorFrame& pending_frame = surface->GetPendingFrame();
+
+ DCHECK(!pending_frame.metadata.referenced_surfaces.empty());
+
+ for (const SurfaceId& surface_id :
+ pending_frame.metadata.referenced_surfaces) {
+ auto it = blocking_surfaces_.find(surface_id);
+ if (it == blocking_surfaces_.end())
+ continue;
+
+ auto& pending_surface_set = it->second;
+ auto pending_surface_it = pending_surface_set.find(surface);
+ if (pending_surface_it != pending_surface_set.end()) {
+ pending_surface_set.erase(surface);
+ if (pending_surface_set.empty())
+ blocking_surfaces_.erase(surface_id);
+ }
+ }
+
+ if (blocking_surfaces_.empty()) {
+ has_deadline_ = false;
+ begin_frame_count_ = 0;
+ }
+
+ pending_surfaces_.erase(surface);
+ surface->RemoveObserver(this);
+
+ // TODO(fsamuel): We should consider removing this surface as a dependency on
+ // other surfaces. This dependency will be removed when the deadline hits
+ // anyway but maybe we should try to actiate these frames early (see
+ // https://crbug.com/689725).
+}
+
+void SurfaceDependencyTracker::OnSurfaceActivated(Surface* surface) {
+ surface->RemoveObserver(this);
+ pending_surfaces_.erase(surface);
+ NotifySurfaceIdAvailable(surface->surface_id());
+}
+
+void SurfaceDependencyTracker::OnSurfaceDependenciesChanged(
+ Surface* surface,
+ const SurfaceDependencies& added_dependencies,
+ const SurfaceDependencies& removed_dependencies) {
+ // Update the |blocking_surfaces_| map with the changes in dependencies.
+ for (const SurfaceId& surface_id : added_dependencies)
+ blocking_surfaces_[surface_id].insert(surface);
+
+ for (const SurfaceId& surface_id : removed_dependencies) {
+ auto it = blocking_surfaces_.find(surface_id);
+ it->second.erase(surface);
+ if (it->second.empty())
+ blocking_surfaces_.erase(it);
+ }
+
+ // If there are no more dependencies to resolve then we don't need to have a
+ // deadline.
+ if (blocking_surfaces_.empty()) {
+ has_deadline_ = false;
+ begin_frame_count_ = 0;
+ }
+}
+
+// SurfaceObserver implementation:
+void SurfaceDependencyTracker::OnSurfaceCreated(
+ const SurfaceInfo& surface_info) {
+ // This is called when a Surface has an activated frame for the first time.
+ // SurfaceDependencyTracker only observes Surfaces that contain pending
+ // frames. SurfaceDependencyTracker becomes aware of CompositorFrames that
+ // activate immediately go through here.
+ NotifySurfaceIdAvailable(surface_info.id());
+}
+
+void SurfaceDependencyTracker::OnSurfaceDamaged(const SurfaceId& surface_id,
+ bool* changed) {}
+
+void SurfaceDependencyTracker::NotifySurfaceIdAvailable(
+ const SurfaceId& surface_id) {
+ auto it = blocking_surfaces_.find(surface_id);
+ if (it == blocking_surfaces_.end())
+ return;
+
+ // Unblock surfaces that depend on this pending surface.
+ PendingSurfaceSet blocked_pending_surface_set(it->second);
+ blocking_surfaces_.erase(it);
+ // If there are no more blockers in the system, then we no longer need to
+ // have a deadline.
+ if (blocking_surfaces_.empty()) {
+ has_deadline_ = false;
+ begin_frame_count_ = 0;
+ }
+
+ // Tell each surface about the availability of its blocker.
+ for (Surface* blocked_pending_surface : blocked_pending_surface_set)
+ blocked_pending_surface->NotifySurfaceIdAvailable(surface_id);
+}
+
+} // namespace cc

Powered by Google App Engine
This is Rietveld 408576698