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

Unified Diff: cc/surfaces/surface_dependency_tracker.cc

Issue 2676373004: Implement service-side surface synchronization (Closed)
Patch Set: Better unit test name 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..934586bbb53757c654ba28c6d660b1359ff06ced
--- /dev/null
+++ b/cc/surfaces/surface_dependency_tracker.cc
@@ -0,0 +1,180 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
kylechar 2017/02/09 15:50:31 2017
+// 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"
kylechar 2017/02/09 15:50:32 Duplicate include.
+#include "cc/surfaces/surface_info.h"
+#include "cc/surfaces/surface_manager.h"
+
+namespace cc {
+
+namespace {
+constexpr uint32_t kMaxBeginFrameCount = 4;
+}
kylechar 2017/02/09 15:50:31 } // namespace
+
+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_before_dependencies;
+
+ // 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_dependency = surface_manager_->GetSurfaceForId(surface_id);
+ if (!surface_dependency || !surface_dependency->HasActiveFrame())
+ blocked_surfaces_[surface_id].insert(surface);
+ }
+
+ if (!pending_surfaces_.count(surface)) {
+ surface->AddObserver(this);
+ pending_surfaces_.insert(surface);
+ }
+
+ if (needs_begin_frame && !frames_since_deadline_set_)
+ frames_since_deadline_set_ = 0;
+}
+
+void SurfaceDependencyTracker::OnBeginFrame(const BeginFrameArgs& args) {
+ // If no deadline is set then we have nothing to do.
+ if (!frames_since_deadline_set_)
+ 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 (++(*frames_since_deadline_set_) != kMaxBeginFrameCount)
+ return;
+
+ // Activate all surfaces that respect the deadline.
+ PendingSurfaceSet pending_surfaces(pending_surfaces_);
+ for (Surface* pending_surface : pending_surfaces)
+ pending_surface->ActivatePendingFrameForDeadline();
+
+ frames_since_deadline_set_.reset();
+}
+
+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 = blocked_surfaces_.find(surface_id);
+ if (it == blocked_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())
+ blocked_surfaces_.erase(surface_id);
+ }
+ }
+
+ if (blocked_surfaces_.empty())
+ frames_since_deadline_set_.reset();
+
+ 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 |blocked_surfaces_| map with the changes in dependencies.
+ for (const SurfaceId& surface_id : added_dependencies)
+ blocked_surfaces_[surface_id].insert(surface);
+
+ for (const SurfaceId& surface_id : removed_dependencies) {
+ auto it = blocked_surfaces_.find(surface_id);
+ it->second.erase(surface);
+ if (it->second.empty())
+ blocked_surfaces_.erase(it);
+ }
+
+ // If there are no more dependencies to resolve then we don't need to have a
+ // deadline.
+ if (blocked_surfaces_.empty())
+ frames_since_deadline_set_.reset();
+}
+
+// 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 = blocked_surfaces_.find(surface_id);
+ if (it == blocked_surfaces_.end())
+ return;
+
+ // Unblock surfaces that depend on this |surface_id|.
+ PendingSurfaceSet blocked_pending_surface_set(it->second);
+ blocked_surfaces_.erase(it);
+ // If there are no more blockers in the system, then we no longer need to
+ // have a deadline.
+ if (blocked_surfaces_.empty())
+ frames_since_deadline_set_.reset();
+
+ // 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