// Copyright 2014 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.h" #include "cc/output/compositor_frame.h" #include "cc/output/copy_output_request.h" #include "cc/surfaces/surface_factory.h" #include "cc/surfaces/surface_manager.h" namespace cc { // The frame index starts at 2 so that empty frames will be treated as // completely damaged the first time they're drawn from. static const int kFrameIndexStart = 2; Surface::Surface(SurfaceId id, const gfx::Size& size, SurfaceFactory* factory) : surface_id_(id), size_(size), factory_(factory->AsWeakPtr()), frame_index_(kFrameIndexStart) { } Surface::~Surface() { ClearCopyRequests(); if (current_frame_ && factory_) { ReturnedResourceArray current_resources; TransferableResource::ReturnResources( current_frame_->delegated_frame_data->resource_list, ¤t_resources); factory_->UnrefResources(current_resources); } } void Surface::QueueFrame(scoped_ptr frame, const base::Closure& callback) { DCHECK(factory_); ClearCopyRequests(); TakeLatencyInfo(&frame->metadata.latency_info); scoped_ptr previous_frame = current_frame_.Pass(); current_frame_ = frame.Pass(); factory_->ReceiveFromChild( current_frame_->delegated_frame_data->resource_list); ++frame_index_; if (previous_frame) { ReturnedResourceArray previous_resources; TransferableResource::ReturnResources( previous_frame->delegated_frame_data->resource_list, &previous_resources); factory_->UnrefResources(previous_resources); } if (!draw_callback_.is_null()) draw_callback_.Run(); draw_callback_ = callback; factory_->manager()->DidSatisfySequences( surface_id_, ¤t_frame_->metadata.satisfies_sequences); } void Surface::RequestCopyOfOutput(scoped_ptr copy_request) { if (current_frame_ && !current_frame_->delegated_frame_data->render_pass_list.empty()) current_frame_->delegated_frame_data->render_pass_list.back() ->copy_requests.push_back(copy_request.Pass()); else copy_request->SendEmptyResult(); } void Surface::TakeCopyOutputRequests( std::multimap* copy_requests) { DCHECK(copy_requests->empty()); if (current_frame_) { for (auto* render_pass : current_frame_->delegated_frame_data->render_pass_list) { while (!render_pass->copy_requests.empty()) { scoped_ptr request = render_pass->copy_requests.take_back(); render_pass->copy_requests.pop_back(); copy_requests->insert( std::make_pair(render_pass->id, request.release())); } } } } const CompositorFrame* Surface::GetEligibleFrame() { return current_frame_.get(); } void Surface::TakeLatencyInfo(std::vector* latency_info) { if (!current_frame_) return; if (latency_info->empty()) { current_frame_->metadata.latency_info.swap(*latency_info); return; } std::copy(current_frame_->metadata.latency_info.begin(), current_frame_->metadata.latency_info.end(), std::back_inserter(*latency_info)); current_frame_->metadata.latency_info.clear(); } void Surface::RunDrawCallbacks() { if (!draw_callback_.is_null()) { base::Closure callback = draw_callback_; draw_callback_ = base::Closure(); callback.Run(); } } void Surface::ClearCopyRequests() { if (current_frame_) { for (auto* render_pass : current_frame_->delegated_frame_data->render_pass_list) { for (auto* copy_request : render_pass->copy_requests) copy_request->SendEmptyResult(); } } } } // namespace cc