| 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();
|
| }
|
|
|