#include "cc/surfaces/surface_aggregator.h"
+#include <map>
+
#include "base/bind.h"
#include "base/containers/hash_tables.h"
#include "base/debug/trace_event.h"
#include "cc/trees/blocking_task_runner.h"
namespace cc {
+namespace {
+
+void MoveMatchingRequests(
+ RenderPassId id,
+ std::multimap<RenderPassId, CopyOutputRequest*>* copy_requests,
+ ScopedPtrVector<CopyOutputRequest>* output_requests) {
+ auto request_range = copy_requests->equal_range(id);
+ for (auto it = request_range.first; it != request_range.second; ++it) {
+ DCHECK(it->second);
+ output_requests->push_back(scoped_ptr<CopyOutputRequest>(it->second));
+ it->second = nullptr;
+ }
+ copy_requests->erase(request_range.first, request_range.second);
+}
+
+} // namespace
SurfaceAggregator::SurfaceAggregator(SurfaceManager* manager,
ResourceProvider* provider)
- : manager_(manager), provider_(provider) {
+ : manager_(manager), provider_(provider), next_render_pass_id_(1) {
DCHECK(manager_);
}
class SurfaceAggregator::RenderPassIdAllocator {
public:
- explicit RenderPassIdAllocator(SurfaceId surface_id)
- : surface_id_(surface_id), next_index_(1) {}
+ explicit RenderPassIdAllocator(int* next_index) : next_index_(next_index) {}
~RenderPassIdAllocator() {}
void AddKnownPass(RenderPassId id) {
if (id_to_index_map_.find(id) != id_to_index_map_.end())
return;
- id_to_index_map_[id] = next_index_++;
+ id_to_index_map_[id] = (*next_index_)++;
}
RenderPassId Remap(RenderPassId id) {
DCHECK(id_to_index_map_.find(id) != id_to_index_map_.end());
- return RenderPassId(surface_id_.id, id_to_index_map_[id]);
+ return RenderPassId(1, id_to_index_map_[id]);
}
private:
base::hash_map<RenderPassId, int> id_to_index_map_;
- SurfaceId surface_id_;
- int next_index_;
+ int* next_index_;
DISALLOW_COPY_AND_ASSIGN(RenderPassIdAllocator);
};
SurfaceId surface_id) {
RenderPassIdAllocator* allocator = render_pass_allocator_map_.get(surface_id);
if (!allocator) {
- allocator = new RenderPassIdAllocator(surface_id);
+ allocator = new RenderPassIdAllocator(&next_render_pass_id_);
render_pass_allocator_map_.set(surface_id, make_scoped_ptr(allocator));
}
allocator->AddKnownPass(surface_local_pass_id);
SurfaceToResourceChildIdMap::iterator it =
surface_id_to_resource_child_id_.find(surface->surface_id());
if (it == surface_id_to_resource_child_id_.end()) {
- int child_id = provider_->CreateChild(
- base::Bind(&UnrefHelper, surface->factory()->AsWeakPtr()));
+ int child_id =
+ provider_->CreateChild(base::Bind(&UnrefHelper, surface->factory()));
surface_id_to_resource_child_id_[surface->surface_id()] = child_id;
return child_id;
} else {
int child_id = ChildIdForSurface(surface);
provider_->ReceiveFromChild(child_id, frame_data->resource_list);
- surface->factory()->RefResources(frame_data->resource_list);
+ if (surface->factory())
+ surface->factory()->RefResources(frame_data->resource_list);
typedef ResourceProvider::ResourceIdArray IdArray;
IdArray referenced_resources;
&invalid_frame,
provider_->GetChildToParentMap(child_id),
&referenced_resources);
- for (RenderPassList::iterator it = render_pass_list->begin();
- it != render_pass_list->end();
- ++it) {
- QuadList& quad_list = (*it)->quad_list;
- for (QuadList::Iterator quad_it = quad_list.begin();
- quad_it != quad_list.end();
- ++quad_it) {
- quad_it->IterateResources(remap);
- }
+ for (const auto& render_pass : *render_pass_list) {
+ for (const auto& quad : render_pass->quad_list)
+ quad->IterateResources(remap);
}
+
if (!invalid_frame)
provider_->DeclareUsedResourcesFromChild(child_id, referenced_resources);
if (!frame_data)
return;
+ std::multimap<RenderPassId, CopyOutputRequest*> copy_requests;
+ surface->TakeCopyOutputRequests(©_requests);
+
RenderPassList render_pass_list;
bool invalid_frame = TakeResources(surface, frame_data, &render_pass_list);
- if (invalid_frame)
+ if (invalid_frame) {
+ for (auto& request : copy_requests) {
+ request.second->SendEmptyResult();
+ delete request.second;
+ }
return;
+ }
SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first;
- ScopedPtrVector<CopyOutputRequest> copy_requests;
- surface->TakeCopyOutputRequests(©_requests);
-
bool merge_pass = copy_requests.empty();
const RenderPassList& referenced_passes = render_pass_list;
for (size_t j = 0; j < passes_to_copy; ++j) {
const RenderPass& source = *referenced_passes[j];
- scoped_ptr<RenderPass> copy_pass(RenderPass::Create());
+ size_t sqs_size = source.shared_quad_state_list.size();
+ size_t dq_size = source.quad_list.size();
+ scoped_ptr<RenderPass> copy_pass(RenderPass::Create(sqs_size, dq_size));
RenderPassId remapped_pass_id = RemapPassId(source.id, surface_id);
source.transform_to_root_target,
source.has_transparent_background);
+ MoveMatchingRequests(source.id, ©_requests, ©_pass->copy_requests);
+
// Contributing passes aggregated in to the pass list need to take the
// transform of the surface quad into account to update their transform to
// the root surface.
} else {
RenderPassId remapped_pass_id = RemapPassId(last_pass.id, surface_id);
- dest_pass_list_->back()->copy_requests.swap(copy_requests);
-
SharedQuadState* shared_quad_state =
dest_pass->CreateAndAppendSharedQuadState();
shared_quad_state->CopyFrom(surface_quad->shared_quad_state);
surface_quad->visible_rect,
remapped_pass_id,
0,
- gfx::RectF(),
+ gfx::Vector2dF(),
+ gfx::Size(),
FilterOperations(),
gfx::Vector2dF(),
FilterOperations());
SurfaceId surface_id) {
const SharedQuadState* last_copied_source_shared_quad_state = NULL;
- size_t sqs_i = 0;
- for (QuadList::ConstIterator iter = source_quad_list.begin();
- iter != source_quad_list.end();
- ++iter) {
- const DrawQuad* quad = &*iter;
- while (quad->shared_quad_state != source_shared_quad_state_list[sqs_i]) {
- ++sqs_i;
- DCHECK_LT(sqs_i, source_shared_quad_state_list.size());
+ SharedQuadStateList::ConstIterator sqs_iter =
+ source_shared_quad_state_list.begin();
+ for (const auto& quad : source_quad_list) {
+ while (quad->shared_quad_state != *sqs_iter) {
+ ++sqs_iter;
+ DCHECK(sqs_iter != source_shared_quad_state_list.end());
}
- DCHECK_EQ(quad->shared_quad_state, source_shared_quad_state_list[sqs_i]);
+ DCHECK_EQ(quad->shared_quad_state, *sqs_iter);
if (quad->material == DrawQuad::SURFACE_CONTENT) {
const SurfaceDrawQuad* surface_quad = SurfaceDrawQuad::MaterialCast(quad);
}
}
-void SurfaceAggregator::CopyPasses(const RenderPassList& source_pass_list,
- const Surface* surface) {
+void SurfaceAggregator::CopyPasses(const DelegatedFrameData* frame_data,
+ Surface* surface) {
+ RenderPassList source_pass_list;
+
+ // The root surface is allowed to have copy output requests, so grab them
+ // off its render passes.
+ std::multimap<RenderPassId, CopyOutputRequest*> copy_requests;
+ surface->TakeCopyOutputRequests(©_requests);
+
+ bool invalid_frame = TakeResources(surface, frame_data, &source_pass_list);
+ DCHECK(!invalid_frame);
+
for (size_t i = 0; i < source_pass_list.size(); ++i) {
const RenderPass& source = *source_pass_list[i];
- scoped_ptr<RenderPass> copy_pass(RenderPass::Create());
+ size_t sqs_size = source.shared_quad_state_list.size();
+ size_t dq_size = source.quad_list.size();
+ scoped_ptr<RenderPass> copy_pass(RenderPass::Create(sqs_size, dq_size));
+
+ MoveMatchingRequests(source.id, ©_requests, ©_pass->copy_requests);
RenderPassId remapped_pass_id =
RemapPassId(source.id, surface->surface_id());
contained_surfaces_[surface_id] = surface->frame_index();
const CompositorFrame* root_surface_frame = surface->GetEligibleFrame();
if (!root_surface_frame)
- return scoped_ptr<CompositorFrame>();
+ return nullptr;
TRACE_EVENT0("cc", "SurfaceAggregator::Aggregate");
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
DCHECK(root_surface_frame->delegated_frame_data);
- RenderPassList source_pass_list;
-
SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first;
dest_resource_list_ = &frame->delegated_frame_data->resource_list;
dest_pass_list_ = &frame->delegated_frame_data->render_pass_list;
- bool invalid_frame =
- TakeResources(surface,
- root_surface_frame->delegated_frame_data.get(),
- &source_pass_list);
- DCHECK(!invalid_frame);
-
- CopyPasses(source_pass_list, surface);
+ CopyPasses(root_surface_frame->delegated_frame_data.get(), surface);
referenced_surfaces_.erase(it);
DCHECK(referenced_surfaces_.empty());