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

Unified Diff: cc/surfaces/surface.cc

Issue 2582823002: WIP: Surface Synchronization System
Patch Set: Only create ClientSurfaceEmbedder if window is visible. Trash it otherwise. Created 3 years, 11 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 20d34011a58d5aa0bff6e4236856476a219fe560..e7b809fc9e4448726aa08dce1f126b3c6e69db3c 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_surface_observer.h"
#include "cc/surfaces/surface_factory.h"
#include "cc/surfaces/surface_id_allocator.h"
#include "cc/surfaces/surface_manager.h"
@@ -31,11 +32,15 @@ Surface::Surface(const SurfaceId& id, base::WeakPtr<SurfaceFactory> factory)
Surface::~Surface() {
ClearCopyRequests();
- if (current_frame_ && factory_) {
- UnrefFrameResources(*current_frame_);
+ if (active_frame_ && factory_) {
+ 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 +50,96 @@ void Surface::SetPreviousFrameSurface(Surface* surface) {
}
void Surface::QueueFrame(CompositorFrame frame, const DrawCallback& callback) {
- DCHECK(factory_);
- ClearCopyRequests();
+ base::Optional<CompositorFrame> previous_pending_frame =
+ std::move(pending_frame_);
+ pending_frame_.reset();
- TakeLatencyInfo(&frame.metadata.latency_info);
+ std::set<SurfaceId> new_blocked_on_surfaces;
- base::Optional<CompositorFrame> previous_frame = std::move(current_frame_);
- current_frame_ = std::move(frame);
+ // Referenced surface IDs that aren't currently known to the surface manager
+ // block this frame.
+ for (const SurfaceId& surface_id : frame.metadata.referenced_surfaces) {
+ Surface* surface = factory_->manager()->GetSurfaceForId(surface_id);
+ if (!surface || !surface->HasFrame())
+ new_blocked_on_surfaces.insert(surface_id);
+ }
+
+ uint32_t added = 0;
+ uint32_t removed = 0;
+
+ if (previous_pending_frame.has_value()) {
+ SurfaceDependencies added_dependencies;
+ SurfaceDependencies removed_dependencies;
+
+ for (const SurfaceId& surface_id : blocked_on_surfaces_) {
+ if (!new_blocked_on_surfaces.count(surface_id))
+ removed_dependencies.insert(surface_id);
+ }
- if (current_frame_) {
- factory_->ReceiveFromChild(current_frame_->resource_list);
+ for (const SurfaceId& surface_id : new_blocked_on_surfaces) {
+ if (!blocked_on_surfaces_.count(surface_id)) {
+ added_dependencies.insert(surface_id);
+ fprintf(stderr, ">>>[%s] QueueFrame Blocked On: %s\n",
+ this->surface_id().ToString().c_str(),
+ surface_id.ToString().c_str());
+ }
+ }
+
+ added = added_dependencies.size();
+ removed = removed_dependencies.size();
+
+ if (!added_dependencies.empty() || !removed_dependencies.empty()) {
+ for (auto& observer : observers_) {
+ observer.OnSurfaceChanged(this, added_dependencies,
+ removed_dependencies);
+ }
+ }
}
- // 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_;
+ blocked_on_surfaces_ = std::move(new_blocked_on_surfaces);
+ if (blocked_on_surfaces_.size() > 0) {
+ std::stringstream sstr;
+ sstr << "{" << std::endl;
+ for (const auto& surface_id : blocked_on_surfaces_) {
+ sstr << " " << surface_id.ToString() << "\n";
+ }
+ sstr << "}" << std::endl;
+
+ fprintf(
+ stderr,
+ ">>>[%s] QueueFrame blocked_on_surfaces: %d added: %d removed: %d\n%s",
+ surface_id().ToString().c_str(), (uint32_t)blocked_on_surfaces_.size(),
+ added, removed, sstr.str().c_str());
}
- previous_frame_surface_id_ = surface_id();
+ if (!blocked_on_surfaces_.empty()) {
+ pending_frame_ = std::move(frame);
+ if (pending_frame_)
+ factory_->ReceiveFromChild(pending_frame_->resource_list);
+ } else {
+ fprintf(stderr, ">>>Surface::QueueFrame activating frame: %s\n",
+ surface_id().ToString().c_str());
+ ActivateFrame(std::move(frame));
+ }
- if (previous_frame)
- UnrefFrameResources(*previous_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()) {
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 (void* source = copy_request->source()) {
// Remove existing CopyOutputRequests made on the Surface by the same
@@ -102,11 +157,87 @@ 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);
+ fprintf(stderr, ">>>[%s] %s available, %d remaining\n",
+ this->surface_id().ToString().c_str(), surface_id.ToString().c_str(),
+ (uint32_t)blocked_on_surfaces_.size());
+
+ if (!blocked_on_surfaces_.empty())
+ return;
+
+ // All blockers have been cleared. The surface can be activated now.
+ ActivatePendingFrame();
+}
+
+void Surface::AddObserver(PendingSurfaceObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void Surface::RemoveObserver(PendingSurfaceObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void Surface::ActivatePendingFrameForDeadline() {
+ if (!pending_frame_ || !pending_frame_->metadata.respect_deadline)
+ return;
+ std::stringstream sstr;
+ sstr << "Deadline for blockers: {" << std::endl;
+ for (const auto& surface_id : blocked_on_surfaces_) {
+ sstr << " " << surface_id.ToString() << "\n";
+ }
+ sstr << "}" << std::endl;
+
+ fprintf(stderr, ">>>Surface::ActivatePendingFrameForDeadline: %s\n%s",
+ surface_id().ToString().c_str(), sstr.str().c_str());
+
+ blocked_on_surfaces_.clear();
+ ActivatePendingFrame();
+}
+
+void Surface::ActivatePendingFrame() {
+ ActivateFrame(std::move(pending_frame_.value()));
+ pending_frame_.reset();
+}
+
+void Surface::ActivateFrame(CompositorFrame frame) {
+ 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_)
+ 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_) {
+ 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,21 +248,25 @@ void Surface::TakeCopyOutputRequests(
}
const CompositorFrame& Surface::GetEligibleFrame() const {
- DCHECK(current_frame_);
- return current_frame_.value();
+ DCHECK(active_frame_);
+ return active_frame_.value();
+}
+
+const base::Optional<CompositorFrame>& Surface::GetPendingFrame() {
+ return pending_frame_;
}
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() {
@@ -169,8 +304,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