summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cc/cc.gyp8
-rw-r--r--cc/cc_tests.gyp1
-rw-r--r--cc/surfaces/display.cc83
-rw-r--r--cc/surfaces/display.h24
-rw-r--r--cc/surfaces/surface.cc75
-rw-r--r--cc/surfaces/surface.h40
-rw-r--r--cc/surfaces/surface_aggregator.cc141
-rw-r--r--cc/surfaces/surface_aggregator.h28
-rw-r--r--cc/surfaces/surface_aggregator_test_helpers.cc23
-rw-r--r--cc/surfaces/surface_aggregator_test_helpers.h4
-rw-r--r--cc/surfaces/surface_aggregator_unittest.cc354
-rw-r--r--cc/surfaces/surface_factory.cc59
-rw-r--r--cc/surfaces/surface_factory.h61
-rw-r--r--cc/surfaces/surface_factory_client.h (renamed from cc/surfaces/surface_client.h)10
-rw-r--r--cc/surfaces/surface_factory_unittest.cc360
-rw-r--r--cc/surfaces/surface_id.h22
-rw-r--r--cc/surfaces/surface_manager.cc22
-rw-r--r--cc/surfaces/surface_manager.h6
-rw-r--r--cc/surfaces/surface_resource_holder.cc68
-rw-r--r--cc/surfaces/surface_resource_holder.h51
-rw-r--r--cc/surfaces/surface_unittest.cc391
-rw-r--r--cc/surfaces/surfaces_pixeltest.cc62
-rw-r--r--content/browser/compositor/gpu_process_transport_factory.cc5
-rw-r--r--content/browser/compositor/onscreen_display_client.cc13
-rw-r--r--content/browser/compositor/onscreen_display_client.h7
-rw-r--r--content/browser/compositor/surface_display_output_surface.cc19
-rw-r--r--content/browser/compositor/surface_display_output_surface.h14
27 files changed, 1179 insertions, 772 deletions
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 46f7d48..73bbb2b 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -493,12 +493,16 @@
'surfaces/display_client.h',
'surfaces/surface.cc',
'surfaces/surface.h',
- 'surfaces/surface_id.h',
'surfaces/surface_aggregator.cc',
'surfaces/surface_aggregator.h',
- 'surfaces/surface_client.h',
+ 'surfaces/surface_factory.cc',
+ 'surfaces/surface_factory.h',
+ 'surfaces/surface_factory_client.h',
+ 'surfaces/surface_id.h',
'surfaces/surface_manager.cc',
'surfaces/surface_manager.h',
+ 'surfaces/surface_resource_holder.cc',
+ 'surfaces/surface_resource_holder.h',
'surfaces/surfaces_export.h',
],
},
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index 72aab12..763bda9 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -121,6 +121,7 @@
'surfaces/surface_aggregator_test_helpers.cc',
'surfaces/surface_aggregator_test_helpers.h',
'surfaces/surface_aggregator_unittest.cc',
+ 'surfaces/surface_factory_unittest.cc',
'surfaces/surface_unittest.cc',
'surfaces/surfaces_pixeltest.cc',
],
diff --git a/cc/surfaces/display.cc b/cc/surfaces/display.cc
index a39695f..30e593d 100644
--- a/cc/surfaces/display.cc
+++ b/cc/surfaces/display.cc
@@ -4,48 +4,40 @@
#include "cc/surfaces/display.h"
+#include "base/debug/trace_event.h"
#include "base/message_loop/message_loop.h"
#include "cc/output/compositor_frame.h"
+#include "cc/output/compositor_frame_ack.h"
#include "cc/output/direct_renderer.h"
#include "cc/output/gl_renderer.h"
#include "cc/output/software_renderer.h"
#include "cc/surfaces/display_client.h"
#include "cc/surfaces/surface.h"
+#include "cc/surfaces/surface_aggregator.h"
+#include "cc/surfaces/surface_factory.h"
namespace cc {
-static ResourceProvider::ResourceId ResourceRemapHelper(
- bool* invalid_frame,
- const ResourceProvider::ResourceIdMap& child_to_parent_map,
- ResourceProvider::ResourceIdArray* resources_in_frame,
- ResourceProvider::ResourceId id) {
- ResourceProvider::ResourceIdMap::const_iterator it =
- child_to_parent_map.find(id);
- if (it == child_to_parent_map.end()) {
- *invalid_frame = true;
- return 0;
- }
-
- DCHECK_EQ(it->first, id);
- ResourceProvider::ResourceId remapped_id = it->second;
- resources_in_frame->push_back(id);
- return remapped_id;
-}
-
Display::Display(DisplayClient* client,
SurfaceManager* manager,
+ SurfaceFactory* factory,
SharedBitmapManager* bitmap_manager)
: client_(client),
manager_(manager),
- aggregator_(manager),
- bitmap_manager_(bitmap_manager) {
+ bitmap_manager_(bitmap_manager),
+ factory_(factory) {
}
Display::~Display() {
}
void Display::Resize(const gfx::Size& size) {
- current_surface_.reset(new Surface(manager_, this, size));
+ if (size == current_surface_size_)
+ return;
+ if (!current_surface_id_.is_null())
+ factory_->Destroy(current_surface_id_);
+ current_surface_id_ = factory_->Create(size);
+ current_surface_size_ = size;
}
void Display::InitializeOutputSurface() {
@@ -91,55 +83,27 @@ void Display::InitializeOutputSurface() {
output_surface_ = output_surface.Pass();
resource_provider_ = resource_provider.Pass();
- child_id_ = resource_provider_->CreateChild(
- base::Bind(&Display::ReturnResources, base::Unretained(this)));
+ aggregator_.reset(new SurfaceAggregator(manager_, resource_provider_.get()));
}
bool Display::Draw() {
- if (!current_surface_)
+ if (current_surface_id_.is_null())
return false;
InitializeOutputSurface();
if (!output_surface_)
return false;
- // TODO(jamesr): Use the surface aggregator instead.
- scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
- CompositorFrame* current_frame = current_surface_->GetEligibleFrame();
- frame_data->resource_list =
- current_frame->delegated_frame_data->resource_list;
- RenderPass::CopyAll(current_frame->delegated_frame_data->render_pass_list,
- &frame_data->render_pass_list);
-
- if (frame_data->render_pass_list.empty())
+ scoped_ptr<CompositorFrame> frame =
+ aggregator_->Aggregate(current_surface_id_);
+ if (!frame)
return false;
- const ResourceProvider::ResourceIdMap& resource_map =
- resource_provider_->GetChildToParentMap(child_id_);
- resource_provider_->ReceiveFromChild(child_id_, frame_data->resource_list);
-
- bool invalid_frame = false;
- ResourceProvider::ResourceIdArray resources_in_frame;
- DrawQuad::ResourceIteratorCallback remap_resources_to_parent_callback =
- base::Bind(&ResourceRemapHelper,
- &invalid_frame,
- resource_map,
- &resources_in_frame);
- for (size_t i = 0; i < frame_data->render_pass_list.size(); ++i) {
- RenderPass* pass = frame_data->render_pass_list[i];
- for (size_t j = 0; j < pass->quad_list.size(); ++j) {
- DrawQuad* quad = pass->quad_list[j];
- quad->IterateResources(remap_resources_to_parent_callback);
- }
- }
-
- if (invalid_frame)
- return false;
- resource_provider_->DeclareUsedResourcesFromChild(child_id_,
- resources_in_frame);
+ TRACE_EVENT0("cc", "Display::Draw");
+ DelegatedFrameData* frame_data = frame->delegated_frame_data.get();
float device_scale_factor = 1.0f;
- gfx::Rect device_viewport_rect = gfx::Rect(current_surface_->size());
+ gfx::Rect device_viewport_rect = gfx::Rect(current_surface_size_);
gfx::Rect device_clip_rect = device_viewport_rect;
bool disable_picture_quad_image_filtering = false;
@@ -154,10 +118,7 @@ bool Display::Draw() {
}
SurfaceId Display::CurrentSurfaceId() {
- return current_surface_ ? current_surface_->surface_id() : SurfaceId();
-}
-
-void Display::ReturnResources(const ReturnedResourceArray& resources) {
+ return current_surface_id_;
}
} // namespace cc
diff --git a/cc/surfaces/display.h b/cc/surfaces/display.h
index 191b28d..689045b 100644
--- a/cc/surfaces/display.h
+++ b/cc/surfaces/display.h
@@ -6,11 +6,10 @@
#define CC_SURFACES_DISPLAY_H_
#include "base/memory/scoped_ptr.h"
-
#include "cc/output/output_surface_client.h"
#include "cc/output/renderer.h"
+#include "cc/resources/returned_resource.h"
#include "cc/surfaces/surface_aggregator.h"
-#include "cc/surfaces/surface_client.h"
#include "cc/surfaces/surface_id.h"
#include "cc/surfaces/surfaces_export.h"
@@ -26,14 +25,21 @@ class OutputSurface;
class ResourceProvider;
class SharedBitmapManager;
class Surface;
+class SurfaceAggregator;
+class SurfaceFactory;
class SurfaceManager;
-class CC_SURFACES_EXPORT Display : public SurfaceClient,
- public OutputSurfaceClient,
+// A Display produces a surface that can be used to draw to a physical display
+// (OutputSurface). Since a surface is a fixed size and displays can resize, a
+// Display may create/destroy surfaces over its lifetime. Frames submitted to a
+// display's surface will have their resources returned through the factory's
+// client.
+class CC_SURFACES_EXPORT Display : public OutputSurfaceClient,
public RendererClient {
public:
Display(DisplayClient* client,
SurfaceManager* manager,
+ SurfaceFactory* factory,
SharedBitmapManager* bitmap_manager);
virtual ~Display();
@@ -66,22 +72,20 @@ class CC_SURFACES_EXPORT Display : public SurfaceClient,
virtual void SetFullRootLayerDamage() OVERRIDE {}
virtual void RunOnDemandRasterTask(Task* on_demand_raster_task) OVERRIDE {}
- // SurfaceClient implementation.
- virtual void ReturnResources(const ReturnedResourceArray& resources) OVERRIDE;
-
private:
void InitializeOutputSurface();
DisplayClient* client_;
SurfaceManager* manager_;
- SurfaceAggregator aggregator_;
SharedBitmapManager* bitmap_manager_;
+ SurfaceFactory* factory_;
+ SurfaceId current_surface_id_;
+ gfx::Size current_surface_size_;
LayerTreeSettings settings_;
- scoped_ptr<Surface> current_surface_;
scoped_ptr<OutputSurface> output_surface_;
scoped_ptr<ResourceProvider> resource_provider_;
+ scoped_ptr<SurfaceAggregator> aggregator_;
scoped_ptr<DirectRenderer> renderer_;
- int child_id_;
DISALLOW_COPY_AND_ASSIGN(Display);
};
diff --git a/cc/surfaces/surface.cc b/cc/surfaces/surface.cc
index ed5a0f6..bed727c 100644
--- a/cc/surfaces/surface.cc
+++ b/cc/surfaces/surface.cc
@@ -5,88 +5,39 @@
#include "cc/surfaces/surface.h"
#include "cc/output/compositor_frame.h"
-#include "cc/surfaces/surface_manager.h"
+#include "cc/surfaces/surface_factory.h"
namespace cc {
-Surface::Surface(SurfaceManager* manager,
- SurfaceClient* client,
- const gfx::Size& size)
- : manager_(manager),
- client_(client),
- size_(size) {
- surface_id_ = manager_->RegisterAndAllocateIdForSurface(this);
+Surface::Surface(SurfaceId id, const gfx::Size& size, SurfaceFactory* factory)
+ : surface_id_(id), size_(size), factory_(factory) {
}
Surface::~Surface() {
- manager_->DeregisterSurface(surface_id_);
+ if (current_frame_) {
+ ReturnedResourceArray current_resources;
+ TransferableResource::ReturnResources(
+ current_frame_->delegated_frame_data->resource_list,
+ &current_resources);
+ factory_->UnrefResources(current_resources);
+ }
}
void Surface::QueueFrame(scoped_ptr<CompositorFrame> frame) {
scoped_ptr<CompositorFrame> previous_frame = current_frame_.Pass();
current_frame_ = frame.Pass();
- ReceiveResourcesFromClient(
+ factory_->ReceiveFromChild(
current_frame_->delegated_frame_data->resource_list);
+
if (previous_frame) {
ReturnedResourceArray previous_resources;
TransferableResource::ReturnResources(
previous_frame->delegated_frame_data->resource_list,
&previous_resources);
- UnrefResources(previous_resources);
+ factory_->UnrefResources(previous_resources);
}
}
CompositorFrame* Surface::GetEligibleFrame() { return current_frame_.get(); }
-void Surface::ReturnUnusedResourcesToClient() {
- client_->ReturnResources(resources_available_to_return_);
- resources_available_to_return_.clear();
-}
-
-void Surface::RefCurrentFrameResources() {
- if (!current_frame_)
- return;
- const TransferableResourceArray& current_frame_resources =
- current_frame_->delegated_frame_data->resource_list;
- for (size_t i = 0; i < current_frame_resources.size(); ++i) {
- const TransferableResource& resource = current_frame_resources[i];
- ResourceIdCountMap::iterator it =
- resource_id_use_count_map_.find(resource.id);
- DCHECK(it != resource_id_use_count_map_.end());
- it->second.refs_holding_resource_alive++;
- }
-}
-
-Surface::ResourceRefs::ResourceRefs()
- : refs_received_from_child(0), refs_holding_resource_alive(0) {
-}
-
-void Surface::ReceiveResourcesFromClient(
- const TransferableResourceArray& resources) {
- for (TransferableResourceArray::const_iterator it = resources.begin();
- it != resources.end();
- ++it) {
- ResourceRefs& ref = resource_id_use_count_map_[it->id];
- ref.refs_holding_resource_alive++;
- ref.refs_received_from_child++;
- }
-}
-
-void Surface::UnrefResources(const ReturnedResourceArray& resources) {
- for (ReturnedResourceArray::const_iterator it = resources.begin();
- it != resources.end();
- ++it) {
- ResourceProvider::ResourceId id = it->id;
- ResourceIdCountMap::iterator count_it = resource_id_use_count_map_.find(id);
- DCHECK(count_it != resource_id_use_count_map_.end());
- count_it->second.refs_holding_resource_alive -= it->count;
- if (count_it->second.refs_holding_resource_alive == 0) {
- resources_available_to_return_.push_back(*it);
- resources_available_to_return_.back().count =
- count_it->second.refs_received_from_child;
- resource_id_use_count_map_.erase(count_it);
- }
- }
-}
-
} // namespace cc
diff --git a/cc/surfaces/surface.h b/cc/surfaces/surface.h
index 007f33d..f62a897 100644
--- a/cc/surfaces/surface.h
+++ b/cc/surfaces/surface.h
@@ -8,9 +8,6 @@
#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
-#include "cc/resources/resource_provider.h"
-#include "cc/resources/return_callback.h"
-#include "cc/surfaces/surface_client.h"
#include "cc/surfaces/surface_id.h"
#include "cc/surfaces/surfaces_export.h"
#include "ui/gfx/size.h"
@@ -18,12 +15,12 @@
namespace cc {
class CompositorFrame;
class SurfaceManager;
+class SurfaceFactory;
+class SurfaceResourceHolder;
class CC_SURFACES_EXPORT Surface {
public:
- Surface(SurfaceManager* manager,
- SurfaceClient* client,
- const gfx::Size& size);
+ Surface(SurfaceId id, const gfx::Size& size, SurfaceFactory* factory);
~Surface();
const gfx::Size& size() const { return size_; }
@@ -33,40 +30,15 @@ class CC_SURFACES_EXPORT Surface {
// Returns the most recent frame that is eligible to be rendered.
CompositorFrame* GetEligibleFrame();
- // Takes a reference to all of the current frame's resources for an external
- // consumer (e.g. a ResourceProvider). The caller to this should call
- // UnrefResources() when they are done with the resources.
- void RefCurrentFrameResources();
- void UnrefResources(const ReturnedResourceArray& resources);
-
- // Returns all resources that are currently not in use to the client.
- void ReturnUnusedResourcesToClient();
+ SurfaceFactory* factory() { return factory_; }
private:
- void ReceiveResourcesFromClient(const TransferableResourceArray& resources);
-
- SurfaceManager* manager_;
- SurfaceClient* client_;
- gfx::Size size_;
SurfaceId surface_id_;
+ gfx::Size size_;
+ SurfaceFactory* factory_;
// TODO(jamesr): Support multiple frames in flight.
scoped_ptr<CompositorFrame> current_frame_;
- struct ResourceRefs {
- ResourceRefs();
-
- int refs_received_from_child;
- int refs_holding_resource_alive;
- };
- // Keeps track of the number of users currently in flight for each resource
- // ID we've received from the client. When this counter hits zero for a
- // particular resource, that ID is available to return to the client.
- typedef base::hash_map<ResourceProvider::ResourceId, ResourceRefs>
- ResourceIdCountMap;
- ResourceIdCountMap resource_id_use_count_map_;
-
- ReturnedResourceArray resources_available_to_return_;
-
DISALLOW_COPY_AND_ASSIGN(Surface);
};
diff --git a/cc/surfaces/surface_aggregator.cc b/cc/surfaces/surface_aggregator.cc
index 72300c0..2926140 100644
--- a/cc/surfaces/surface_aggregator.cc
+++ b/cc/surfaces/surface_aggregator.cc
@@ -4,7 +4,9 @@
#include "cc/surfaces/surface_aggregator.h"
+#include "base/bind.h"
#include "base/containers/hash_tables.h"
+#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/delegated_frame_data.h"
@@ -13,31 +15,22 @@
#include "cc/quads/shared_quad_state.h"
#include "cc/quads/surface_draw_quad.h"
#include "cc/surfaces/surface.h"
+#include "cc/surfaces/surface_factory.h"
#include "cc/surfaces/surface_manager.h"
namespace cc {
-SurfaceAggregator::SurfaceAggregator(SurfaceManager* manager)
- : manager_(manager) {
+SurfaceAggregator::SurfaceAggregator(SurfaceManager* manager,
+ ResourceProvider* provider)
+ : manager_(manager), provider_(provider) {
DCHECK(manager_);
}
SurfaceAggregator::~SurfaceAggregator() {}
-DelegatedFrameData* SurfaceAggregator::GetReferencedDataForSurfaceId(
- SurfaceId surface_id) {
- Surface* referenced_surface = manager_->GetSurfaceForId(surface_id);
- if (!referenced_surface)
- return NULL; // Invalid surface id, skip this quad.
- CompositorFrame* referenced_frame = referenced_surface->GetEligibleFrame();
- if (!referenced_frame)
- return NULL;
- return referenced_frame->delegated_frame_data.get();
-}
-
class SurfaceAggregator::RenderPassIdAllocator {
public:
- explicit RenderPassIdAllocator(int surface_id)
+ explicit RenderPassIdAllocator(SurfaceId surface_id)
: surface_id_(surface_id), next_index_(1) {}
~RenderPassIdAllocator() {}
@@ -49,12 +42,12 @@ class SurfaceAggregator::RenderPassIdAllocator {
RenderPass::Id Remap(RenderPass::Id id) {
DCHECK(id_to_index_map_.find(id) != id_to_index_map_.end());
- return RenderPass::Id(surface_id_, id_to_index_map_[id]);
+ return RenderPass::Id(surface_id_.id, id_to_index_map_[id]);
}
private:
base::hash_map<RenderPass::Id, int> id_to_index_map_;
- int surface_id_;
+ SurfaceId surface_id_;
int next_index_;
DISALLOW_COPY_AND_ASSIGN(RenderPassIdAllocator);
@@ -62,7 +55,7 @@ class SurfaceAggregator::RenderPassIdAllocator {
RenderPass::Id SurfaceAggregator::RemapPassId(
RenderPass::Id surface_local_pass_id,
- int surface_id) {
+ SurfaceId surface_id) {
RenderPassIdAllocator* allocator = render_pass_allocator_map_.get(surface_id);
if (!allocator) {
allocator = new RenderPassIdAllocator(surface_id);
@@ -72,26 +65,102 @@ RenderPass::Id SurfaceAggregator::RemapPassId(
return allocator->Remap(surface_local_pass_id);
}
+int SurfaceAggregator::ChildIdForSurface(Surface* surface) {
+ 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(
+ &SurfaceFactory::UnrefResources, surface->factory()->AsWeakPtr()));
+ surface_id_to_resource_child_id_[surface->surface_id()] = child_id;
+ return child_id;
+ } else {
+ return it->second;
+ }
+}
+
+static ResourceProvider::ResourceId ResourceRemapHelper(
+ bool* invalid_frame,
+ const ResourceProvider::ResourceIdMap& child_to_parent_map,
+ ResourceProvider::ResourceIdArray* resources_in_frame,
+ ResourceProvider::ResourceId id) {
+ ResourceProvider::ResourceIdMap::const_iterator it =
+ child_to_parent_map.find(id);
+ if (it == child_to_parent_map.end()) {
+ *invalid_frame = true;
+ return 0;
+ }
+
+ DCHECK_EQ(it->first, id);
+ ResourceProvider::ResourceId remapped_id = it->second;
+ resources_in_frame->push_back(id);
+ return remapped_id;
+}
+
+bool SurfaceAggregator::TakeResources(Surface* surface,
+ DelegatedFrameData* frame_data) {
+ if (!provider_) // TODO(jamesr): hack for unit tests that don't set up rp
+ return false;
+
+ int child_id = ChildIdForSurface(surface);
+ provider_->ReceiveFromChild(child_id, frame_data->resource_list);
+ surface->factory()->RefResources(frame_data->resource_list);
+
+ typedef ResourceProvider::ResourceIdArray IdArray;
+ IdArray referenced_resources;
+
+ bool invalid_frame = false;
+ DrawQuad::ResourceIteratorCallback remap =
+ base::Bind(&ResourceRemapHelper,
+ &invalid_frame,
+ provider_->GetChildToParentMap(child_id),
+ &referenced_resources);
+ const RenderPassList& referenced_passes = frame_data->render_pass_list;
+ for (RenderPassList::const_iterator it = referenced_passes.begin();
+ it != referenced_passes.end();
+ ++it) {
+ const QuadList& quad_list = (*it)->quad_list;
+ for (QuadList::const_iterator quad_it = quad_list.begin();
+ quad_it != quad_list.end();
+ ++quad_it) {
+ (*quad_it)->IterateResources(remap);
+ }
+ }
+ if (!invalid_frame)
+ provider_->DeclareUsedResourcesFromChild(child_id, referenced_resources);
+
+ return invalid_frame;
+}
+
void SurfaceAggregator::HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad,
RenderPass* dest_pass) {
SurfaceId surface_id = surface_quad->surface_id;
// If this surface's id is already in our referenced set then it creates
// a cycle in the graph and should be dropped.
- if (referenced_surfaces_.count(surface_id.id))
+ if (referenced_surfaces_.count(surface_id))
+ return;
+ Surface* surface = manager_->GetSurfaceForId(surface_id);
+ if (!surface)
return;
- DelegatedFrameData* referenced_data =
- GetReferencedDataForSurfaceId(surface_id);
- if (!referenced_data)
+ CompositorFrame* frame = surface->GetEligibleFrame();
+ if (!frame)
return;
- std::set<int>::iterator it = referenced_surfaces_.insert(surface_id.id).first;
+ DelegatedFrameData* frame_data = frame->delegated_frame_data.get();
+ if (!frame_data)
+ return;
+
+ bool invalid_frame = TakeResources(surface, frame_data);
+ if (invalid_frame)
+ return;
+
+ SurfaceSet::iterator it = referenced_surfaces_.insert(surface_id).first;
- const RenderPassList& referenced_passes = referenced_data->render_pass_list;
+ const RenderPassList& referenced_passes = frame_data->render_pass_list;
for (size_t j = 0; j + 1 < referenced_passes.size(); ++j) {
const RenderPass& source = *referenced_passes[j];
scoped_ptr<RenderPass> copy_pass(RenderPass::Create());
- RenderPass::Id remapped_pass_id = RemapPassId(source.id, surface_id.id);
+ RenderPass::Id remapped_pass_id = RemapPassId(source.id, surface_id);
copy_pass->SetAll(remapped_pass_id,
source.output_rect,
@@ -111,13 +180,13 @@ void SurfaceAggregator::HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad,
source.shared_quad_state_list,
gfx::Transform(),
copy_pass.get(),
- surface_id.id);
+ surface_id);
dest_pass_list_->push_back(copy_pass.Pass());
}
// TODO(jamesr): Clean up last pass special casing.
- const RenderPass& last_pass = *referenced_data->render_pass_list.back();
+ const RenderPass& last_pass = *frame_data->render_pass_list.back();
const QuadList& quads = last_pass.quad_list;
// TODO(jamesr): Make sure clipping is enforced.
@@ -125,7 +194,7 @@ void SurfaceAggregator::HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad,
last_pass.shared_quad_state_list,
surface_quad->quadTransform(),
dest_pass,
- surface_id.id);
+ surface_id);
referenced_surfaces_.erase(it);
}
@@ -152,7 +221,7 @@ void SurfaceAggregator::CopyQuadsToPass(
const SharedQuadStateList& source_shared_quad_state_list,
const gfx::Transform& content_to_target_transform,
RenderPass* dest_pass,
- int surface_id) {
+ SurfaceId surface_id) {
const SharedQuadState* last_copied_source_shared_quad_state = NULL;
for (size_t i = 0, sqs_i = 0; i < source_quad_list.size(); ++i) {
@@ -191,7 +260,7 @@ void SurfaceAggregator::CopyQuadsToPass(
}
void SurfaceAggregator::CopyPasses(const RenderPassList& source_pass_list,
- int surface_id) {
+ SurfaceId surface_id) {
for (size_t i = 0; i < source_pass_list.size(); ++i) {
const RenderPass& source = *source_pass_list[i];
@@ -217,11 +286,11 @@ void SurfaceAggregator::CopyPasses(const RenderPassList& source_pass_list,
scoped_ptr<CompositorFrame> SurfaceAggregator::Aggregate(SurfaceId surface_id) {
Surface* surface = manager_->GetSurfaceForId(surface_id);
- if (!surface)
- return scoped_ptr<CompositorFrame>();
+ DCHECK(surface);
CompositorFrame* root_surface_frame = surface->GetEligibleFrame();
if (!root_surface_frame)
return scoped_ptr<CompositorFrame>();
+ TRACE_EVENT0("cc", "SurfaceAggregator::Aggregate");
scoped_ptr<CompositorFrame> frame(new CompositorFrame);
frame->delegated_frame_data = make_scoped_ptr(new DelegatedFrameData);
@@ -231,10 +300,16 @@ scoped_ptr<CompositorFrame> SurfaceAggregator::Aggregate(SurfaceId surface_id) {
const RenderPassList& source_pass_list =
root_surface_frame->delegated_frame_data->render_pass_list;
- std::set<int>::iterator it = referenced_surfaces_.insert(surface_id.id).first;
+ 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;
- CopyPasses(source_pass_list, surface_id.id);
+
+ bool invalid_frame =
+ TakeResources(surface, root_surface_frame->delegated_frame_data.get());
+ DCHECK(!invalid_frame);
+
+ CopyPasses(source_pass_list, surface_id);
referenced_surfaces_.erase(it);
DCHECK(referenced_surfaces_.empty());
diff --git a/cc/surfaces/surface_aggregator.h b/cc/surfaces/surface_aggregator.h
index fe52050..02dc478 100644
--- a/cc/surfaces/surface_aggregator.h
+++ b/cc/surfaces/surface_aggregator.h
@@ -7,9 +7,11 @@
#include <set>
+#include "base/containers/hash_tables.h"
#include "base/containers/scoped_ptr_hash_map.h"
#include "base/memory/scoped_ptr.h"
#include "cc/quads/render_pass.h"
+#include "cc/resources/transferable_resource.h"
#include "cc/surfaces/surface_id.h"
#include "cc/surfaces/surfaces_export.h"
@@ -17,20 +19,21 @@ namespace cc {
class CompositorFrame;
class DelegatedFrameData;
+class ResourceProvider;
+class Surface;
class SurfaceDrawQuad;
class SurfaceManager;
class CC_SURFACES_EXPORT SurfaceAggregator {
public:
- explicit SurfaceAggregator(SurfaceManager* manager);
+ SurfaceAggregator(SurfaceManager* manager, ResourceProvider* provider);
~SurfaceAggregator();
scoped_ptr<CompositorFrame> Aggregate(SurfaceId surface_id);
private:
- DelegatedFrameData* GetReferencedDataForSurfaceId(SurfaceId surface_id);
RenderPass::Id RemapPassId(RenderPass::Id surface_local_pass_id,
- int surface_id);
+ SurfaceId surface_id);
void HandleSurfaceQuad(const SurfaceDrawQuad* surface_quad,
RenderPass* dest_pass);
@@ -41,27 +44,38 @@ class CC_SURFACES_EXPORT SurfaceAggregator {
const SharedQuadStateList& source_shared_quad_state_list,
const gfx::Transform& content_to_target_transform,
RenderPass* dest_pass,
- int surface_id);
- void CopyPasses(const RenderPassList& source_pass_list, int surface_id);
+ SurfaceId surface_id);
+ void CopyPasses(const RenderPassList& source_pass_list, SurfaceId surface_id);
+
+ bool TakeResources(Surface* surface, DelegatedFrameData* frame_data);
+ int ChildIdForSurface(Surface* surface);
SurfaceManager* manager_;
+ ResourceProvider* provider_;
class RenderPassIdAllocator;
- typedef base::ScopedPtrHashMap<int, RenderPassIdAllocator>
+ typedef base::ScopedPtrHashMap<SurfaceId, RenderPassIdAllocator>
RenderPassIdAllocatorMap;
RenderPassIdAllocatorMap render_pass_allocator_map_;
+ typedef base::hash_map<SurfaceId, int> SurfaceToResourceChildIdMap;
+ SurfaceToResourceChildIdMap surface_id_to_resource_child_id_;
+
// The following state is only valid for the duration of one Aggregate call
// and is only stored on the class to avoid having to pass through every
// function call.
// This is the set of surfaces referenced in the aggregation so far, used to
// detect cycles.
- std::set<int> referenced_surfaces_;
+ typedef std::set<SurfaceId> SurfaceSet;
+ SurfaceSet referenced_surfaces_;
// This is the pass list for the aggregated frame.
RenderPassList* dest_pass_list_;
+ // Resource list for the aggregated frame.
+ TransferableResourceArray* dest_resource_list_;
+
DISALLOW_COPY_AND_ASSIGN(SurfaceAggregator);
};
diff --git a/cc/surfaces/surface_aggregator_test_helpers.cc b/cc/surfaces/surface_aggregator_test_helpers.cc
index a653eb1..63a39af 100644
--- a/cc/surfaces/surface_aggregator_test_helpers.cc
+++ b/cc/surfaces/surface_aggregator_test_helpers.cc
@@ -145,28 +145,5 @@ void TestPassesMatchExpectations(Pass* expected_passes,
}
}
-void SubmitFrame(Pass* passes, size_t pass_count, Surface* surface) {
- RenderPassList pass_list;
- AddPasses(&pass_list, gfx::Rect(surface->size()), passes, pass_count);
-
- scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
- pass_list.swap(frame_data->render_pass_list);
-
- scoped_ptr<CompositorFrame> frame(new CompositorFrame);
- frame->delegated_frame_data = frame_data.Pass();
-
- surface->QueueFrame(frame.Pass());
-}
-
-void QueuePassAsFrame(scoped_ptr<RenderPass> pass, Surface* surface) {
- scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
- delegated_frame_data->render_pass_list.push_back(pass.Pass());
-
- scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
- child_frame->delegated_frame_data = delegated_frame_data.Pass();
-
- surface->QueueFrame(child_frame.Pass());
-}
-
} // namespace test
} // namespace cc
diff --git a/cc/surfaces/surface_aggregator_test_helpers.h b/cc/surfaces/surface_aggregator_test_helpers.h
index 10c5659..75bfaeb 100644
--- a/cc/surfaces/surface_aggregator_test_helpers.h
+++ b/cc/surfaces/surface_aggregator_test_helpers.h
@@ -85,10 +85,6 @@ void TestPassesMatchExpectations(Pass* expected_passes,
size_t expected_pass_count,
RenderPassList* passes);
-void SubmitFrame(Pass* passes, size_t pass_count, Surface* surface);
-
-void QueuePassAsFrame(scoped_ptr<RenderPass> pass, Surface* surface);
-
} // namespace test
} // namespace cc
diff --git a/cc/surfaces/surface_aggregator_unittest.cc b/cc/surfaces/surface_aggregator_unittest.cc
index 62ba079..bf49b57 100644
--- a/cc/surfaces/surface_aggregator_unittest.cc
+++ b/cc/surfaces/surface_aggregator_unittest.cc
@@ -8,12 +8,18 @@
#include "cc/quads/render_pass_draw_quad.h"
#include "cc/quads/solid_color_draw_quad.h"
#include "cc/quads/surface_draw_quad.h"
+#include "cc/resources/shared_bitmap_manager.h"
#include "cc/surfaces/surface.h"
#include "cc/surfaces/surface_aggregator.h"
#include "cc/surfaces/surface_aggregator_test_helpers.h"
+#include "cc/surfaces/surface_factory.h"
+#include "cc/surfaces/surface_factory_client.h"
#include "cc/surfaces/surface_manager.h"
+#include "cc/test/fake_output_surface.h"
+#include "cc/test/fake_output_surface_client.h"
#include "cc/test/render_pass_test_common.h"
#include "cc/test/render_pass_test_utils.h"
+#include "cc/test/test_shared_bitmap_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColor.h"
@@ -26,35 +32,54 @@ SurfaceId InvalidSurfaceId() {
return invalid;
}
+gfx::Size SurfaceSize() {
+ static gfx::Size size(5, 5);
+ return size;
+}
+
+class EmptySurfaceFactoryClient : public SurfaceFactoryClient {
+ public:
+ virtual void ReturnResources(
+ const ReturnedResourceArray& resources) OVERRIDE {}
+};
+
class SurfaceAggregatorTest : public testing::Test {
public:
- SurfaceAggregatorTest() : aggregator_(&manager_) {}
+ SurfaceAggregatorTest()
+ : factory_(&manager_, &empty_client_), aggregator_(&manager_, NULL) {}
protected:
SurfaceManager manager_;
+ EmptySurfaceFactoryClient empty_client_;
+ SurfaceFactory factory_;
SurfaceAggregator aggregator_;
};
-TEST_F(SurfaceAggregatorTest, InvalidSurfaceId) {
- scoped_ptr<CompositorFrame> frame = aggregator_.Aggregate(InvalidSurfaceId());
- EXPECT_FALSE(frame);
-}
-
TEST_F(SurfaceAggregatorTest, ValidSurfaceNoFrame) {
- Surface one(&manager_, NULL, gfx::Size(5, 5));
- scoped_ptr<CompositorFrame> frame = aggregator_.Aggregate(one.surface_id());
+ SurfaceId one_id = factory_.Create(SurfaceSize());
+ scoped_ptr<CompositorFrame> frame = aggregator_.Aggregate(one_id);
EXPECT_FALSE(frame);
+ factory_.Destroy(one_id);
}
class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
public:
- SurfaceAggregatorValidSurfaceTest()
- : root_surface_(&manager_, NULL, gfx::Size(5, 5)) {}
+ SurfaceAggregatorValidSurfaceTest() {}
+
+ virtual void SetUp() {
+ SurfaceAggregatorTest::SetUp();
+ root_surface_id_ = factory_.Create(SurfaceSize());
+ }
+
+ virtual void TearDown() {
+ factory_.Destroy(root_surface_id_);
+ SurfaceAggregatorTest::TearDown();
+ }
void AggregateAndVerify(test::Pass* expected_passes,
size_t expected_pass_count) {
scoped_ptr<CompositorFrame> aggregated_frame =
- aggregator_.Aggregate(root_surface_.surface_id());
+ aggregator_.Aggregate(root_surface_id_);
ASSERT_TRUE(aggregated_frame);
ASSERT_TRUE(aggregated_frame->delegated_frame_data);
@@ -66,8 +91,33 @@ class SurfaceAggregatorValidSurfaceTest : public SurfaceAggregatorTest {
expected_passes, expected_pass_count, &frame_data->render_pass_list);
}
+ void SubmitFrame(test::Pass* passes,
+ size_t pass_count,
+ SurfaceId surface_id) {
+ RenderPassList pass_list;
+ AddPasses(&pass_list, gfx::Rect(SurfaceSize()), passes, pass_count);
+
+ scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
+ pass_list.swap(frame_data->render_pass_list);
+
+ scoped_ptr<CompositorFrame> frame(new CompositorFrame);
+ frame->delegated_frame_data = frame_data.Pass();
+
+ factory_.SubmitFrame(surface_id, frame.Pass());
+ }
+
+ void QueuePassAsFrame(scoped_ptr<RenderPass> pass, SurfaceId surface_id) {
+ scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
+ delegated_frame_data->render_pass_list.push_back(pass.Pass());
+
+ scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
+ child_frame->delegated_frame_data = delegated_frame_data.Pass();
+
+ factory_.SubmitFrame(surface_id, child_frame.Pass());
+ }
+
protected:
- Surface root_surface_;
+ SurfaceId root_surface_id_;
};
// Tests that a very simple frame containing only two solid color quads makes it
@@ -77,7 +127,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleFrame) {
test::Quad::SolidColorQuad(SK_ColorBLUE)};
test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
- SubmitFrame(passes, arraysize(passes), &root_surface_);
+ SubmitFrame(passes, arraysize(passes), root_surface_id_);
AggregateAndVerify(passes, arraysize(passes));
}
@@ -90,7 +140,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSimpleFrame) {
test::Pass passes[] = {test::Pass(quads[0], arraysize(quads[0])),
test::Pass(quads[1], arraysize(quads[1]))};
- SubmitFrame(passes, arraysize(passes), &root_surface_);
+ SubmitFrame(passes, arraysize(passes), root_surface_id_);
AggregateAndVerify(passes, arraysize(passes));
}
@@ -100,23 +150,20 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSimpleFrame) {
// embedded_surface has a frame containing only a solid color quad. The solid
// color quad should be aggregated into the final frame.
TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) {
- gfx::Size surface_size(5, 5);
-
- Surface embedded_surface(&manager_, NULL, surface_size);
+ SurfaceId embedded_surface_id = factory_.Create(SurfaceSize());
test::Quad embedded_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN)};
test::Pass embedded_passes[] = {
test::Pass(embedded_quads, arraysize(embedded_quads))};
- SubmitFrame(embedded_passes, arraysize(embedded_passes), &embedded_surface);
+ SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
- test::Quad root_quads[] = {
- test::Quad::SolidColorQuad(SK_ColorWHITE),
- test::Quad::SurfaceQuad(embedded_surface.surface_id()),
- test::Quad::SolidColorQuad(SK_ColorBLACK)};
+ test::Quad root_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
+ test::Quad::SurfaceQuad(embedded_surface_id),
+ test::Quad::SolidColorQuad(SK_ColorBLACK)};
test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
- SubmitFrame(root_passes, arraysize(root_passes), &root_surface_);
+ SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorWHITE),
test::Quad::SolidColorQuad(SK_ColorGREEN),
@@ -124,13 +171,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleSurfaceReference) {
test::Pass expected_passes[] = {
test::Pass(expected_quads, arraysize(expected_quads))};
AggregateAndVerify(expected_passes, arraysize(expected_passes));
+
+ factory_.Destroy(embedded_surface_id);
}
// This tests referencing a surface that has multiple render passes.
TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
- gfx::Size surface_size(5, 5);
-
- Surface embedded_surface(&manager_, NULL, surface_size);
+ SurfaceId embedded_surface_id = factory_.Create(SurfaceSize());
RenderPass::Id pass_ids[] = {RenderPass::Id(1, 1), RenderPass::Id(1, 2),
RenderPass::Id(1, 3)};
@@ -144,11 +191,11 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
test::Pass(embedded_quads[1], arraysize(embedded_quads[1]), pass_ids[1]),
test::Pass(embedded_quads[2], arraysize(embedded_quads[2]), pass_ids[2])};
- SubmitFrame(embedded_passes, arraysize(embedded_passes), &embedded_surface);
+ SubmitFrame(embedded_passes, arraysize(embedded_passes), embedded_surface_id);
test::Quad root_quads[][2] = {
{test::Quad::SolidColorQuad(5), test::Quad::SolidColorQuad(6)},
- {test::Quad::SurfaceQuad(embedded_surface.surface_id()),
+ {test::Quad::SurfaceQuad(embedded_surface_id),
test::Quad::RenderPassQuad(pass_ids[0])},
{test::Quad::SolidColorQuad(7), test::Quad::RenderPassQuad(pass_ids[1])}};
test::Pass root_passes[] = {
@@ -156,10 +203,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
test::Pass(root_quads[1], arraysize(root_quads[1]), pass_ids[1]),
test::Pass(root_quads[2], arraysize(root_quads[2]), pass_ids[2])};
- SubmitFrame(root_passes, arraysize(root_passes), &root_surface_);
+ SubmitFrame(root_passes, arraysize(root_passes), root_surface_id_);
scoped_ptr<CompositorFrame> aggregated_frame =
- aggregator_.Aggregate(root_surface_.surface_id());
+ aggregator_.Aggregate(root_surface_id_);
ASSERT_TRUE(aggregated_frame);
ASSERT_TRUE(aggregated_frame->delegated_frame_data);
@@ -257,6 +304,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, MultiPassSurfaceReference) {
EXPECT_EQ(actual_pass_ids[3],
fifth_pass_render_pass_draw_quad->render_pass_id);
}
+ factory_.Destroy(embedded_surface_id);
}
// Tests an invalid surface reference in a frame. The surface quad should just
@@ -267,7 +315,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, InvalidSurfaceReference) {
test::Quad::SolidColorQuad(SK_ColorBLUE)};
test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
- SubmitFrame(passes, arraysize(passes), &root_surface_);
+ SubmitFrame(passes, arraysize(passes), root_surface_id_);
test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
test::Quad::SolidColorQuad(SK_ColorBLUE)};
@@ -279,30 +327,30 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, InvalidSurfaceReference) {
// Tests a reference to a valid surface with no submitted frame. This quad
// should also just be dropped.
TEST_F(SurfaceAggregatorValidSurfaceTest, ValidSurfaceReferenceWithNoFrame) {
- Surface surface_with_no_frame(&manager_, NULL, gfx::Size(5, 5));
- test::Quad quads[] = {
- test::Quad::SolidColorQuad(SK_ColorGREEN),
- test::Quad::SurfaceQuad(surface_with_no_frame.surface_id()),
- test::Quad::SolidColorQuad(SK_ColorBLUE)};
+ SurfaceId surface_with_no_frame_id = factory_.Create(gfx::Size(5, 5));
+ test::Quad quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
+ test::Quad::SurfaceQuad(surface_with_no_frame_id),
+ test::Quad::SolidColorQuad(SK_ColorBLUE)};
test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
- SubmitFrame(passes, arraysize(passes), &root_surface_);
+ SubmitFrame(passes, arraysize(passes), root_surface_id_);
test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
test::Quad::SolidColorQuad(SK_ColorBLUE)};
test::Pass expected_passes[] = {
test::Pass(expected_quads, arraysize(expected_quads))};
AggregateAndVerify(expected_passes, arraysize(expected_passes));
+ factory_.Destroy(surface_with_no_frame_id);
}
// Tests a surface quad referencing itself, generating a trivial cycle.
// The quad creating the cycle should be dropped from the final frame.
TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleCyclicalReference) {
- test::Quad quads[] = {test::Quad::SurfaceQuad(root_surface_.surface_id()),
+ test::Quad quads[] = {test::Quad::SurfaceQuad(root_surface_id_),
test::Quad::SolidColorQuad(SK_ColorYELLOW)};
test::Pass passes[] = {test::Pass(quads, arraysize(quads))};
- SubmitFrame(passes, arraysize(passes), &root_surface_);
+ SubmitFrame(passes, arraysize(passes), root_surface_id_);
test::Quad expected_quads[] = {test::Quad::SolidColorQuad(SK_ColorYELLOW)};
test::Pass expected_passes[] = {
@@ -312,26 +360,22 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, SimpleCyclicalReference) {
// Tests a more complex cycle with one intermediate surface.
TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) {
- gfx::Size surface_size(5, 5);
-
- Surface child_surface(&manager_, NULL, surface_size);
+ SurfaceId child_surface_id = factory_.Create(SurfaceSize());
- test::Quad parent_quads[] = {
- test::Quad::SolidColorQuad(SK_ColorBLUE),
- test::Quad::SurfaceQuad(child_surface.surface_id()),
- test::Quad::SolidColorQuad(SK_ColorCYAN)};
+ test::Quad parent_quads[] = {test::Quad::SolidColorQuad(SK_ColorBLUE),
+ test::Quad::SurfaceQuad(child_surface_id),
+ test::Quad::SolidColorQuad(SK_ColorCYAN)};
test::Pass parent_passes[] = {
test::Pass(parent_quads, arraysize(parent_quads))};
- SubmitFrame(parent_passes, arraysize(parent_passes), &root_surface_);
+ SubmitFrame(parent_passes, arraysize(parent_passes), root_surface_id_);
- test::Quad child_quads[] = {
- test::Quad::SolidColorQuad(SK_ColorGREEN),
- test::Quad::SurfaceQuad(root_surface_.surface_id()),
- test::Quad::SolidColorQuad(SK_ColorMAGENTA)};
+ test::Quad child_quads[] = {test::Quad::SolidColorQuad(SK_ColorGREEN),
+ test::Quad::SurfaceQuad(root_surface_id_),
+ test::Quad::SolidColorQuad(SK_ColorMAGENTA)};
test::Pass child_passes[] = {test::Pass(child_quads, arraysize(child_quads))};
- SubmitFrame(child_passes, arraysize(child_passes), &child_surface);
+ SubmitFrame(child_passes, arraysize(child_passes), child_surface_id);
// The child surface's reference to the root_surface_ will be dropped, so
// we'll end up with:
@@ -346,14 +390,13 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, TwoSurfaceCyclicalReference) {
test::Pass expected_passes[] = {
test::Pass(expected_quads, arraysize(expected_quads))};
AggregateAndVerify(expected_passes, arraysize(expected_passes));
+ factory_.Destroy(child_surface_id);
}
// Tests that we map render pass IDs from different surfaces into a unified
// namespace and update RenderPassDrawQuad's id references to match.
TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) {
- gfx::Size surface_size(5, 5);
-
- Surface child_surface(&manager_, NULL, surface_size);
+ SurfaceId child_surface_id = factory_.Create(SurfaceSize());
RenderPass::Id child_pass_id[] = {RenderPass::Id(1, 1), RenderPass::Id(1, 2)};
test::Quad child_quad[][1] = {{test::Quad::SolidColorQuad(SK_ColorGREEN)},
@@ -362,21 +405,21 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) {
test::Pass(child_quad[0], arraysize(child_quad[0]), child_pass_id[0]),
test::Pass(child_quad[1], arraysize(child_quad[1]), child_pass_id[1])};
- SubmitFrame(surface_passes, arraysize(surface_passes), &child_surface);
+ SubmitFrame(surface_passes, arraysize(surface_passes), child_surface_id);
// Pass IDs from the parent surface may collide with ones from the child.
RenderPass::Id parent_pass_id[] = {RenderPass::Id(2, 1),
RenderPass::Id(1, 2)};
test::Quad parent_quad[][1] = {
- {test::Quad::SurfaceQuad(child_surface.surface_id())},
+ {test::Quad::SurfaceQuad(child_surface_id)},
{test::Quad::RenderPassQuad(parent_pass_id[0])}};
test::Pass parent_passes[] = {
test::Pass(parent_quad[0], arraysize(parent_quad[0]), parent_pass_id[0]),
test::Pass(parent_quad[1], arraysize(parent_quad[1]), parent_pass_id[1])};
- SubmitFrame(parent_passes, arraysize(parent_passes), &root_surface_);
+ SubmitFrame(parent_passes, arraysize(parent_passes), root_surface_id_);
scoped_ptr<CompositorFrame> aggregated_frame =
- aggregator_.Aggregate(root_surface_.surface_id());
+ aggregator_.Aggregate(root_surface_id_);
ASSERT_TRUE(aggregated_frame);
ASSERT_TRUE(aggregated_frame->delegated_frame_data);
@@ -409,6 +452,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, RenderPassIdMapping) {
EXPECT_EQ(
actual_pass_ids[1],
RenderPassDrawQuad::MaterialCast(render_pass_quads[1])->render_pass_id);
+ factory_.Destroy(child_surface_id);
}
void AddSolidColorQuadWithBlendMode(const gfx::Size& size,
@@ -470,8 +514,6 @@ void AddSolidColorQuadWithBlendMode(const gfx::Size& size,
// quad_child_two_0 - blend_mode kSrcIn_Mode
// quad_root_2 - blend_mode kDstIn_Mode
TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) {
- gfx::Size surface_size(5, 5);
-
const SkXfermode::Mode blend_modes[] = {SkXfermode::kClear_Mode, // 0
SkXfermode::kSrc_Mode, // 1
SkXfermode::kDst_Mode, // 2
@@ -482,71 +524,74 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) {
};
RenderPass::Id pass_id(1, 1);
- Surface grandchild_surface(&manager_, NULL, surface_size);
+ SurfaceId grandchild_surface_id = factory_.Create(SurfaceSize());
scoped_ptr<RenderPass> grandchild_pass = RenderPass::Create();
- gfx::Rect output_rect(surface_size);
- gfx::Rect damage_rect(surface_size);
+ gfx::Rect output_rect(SurfaceSize());
+ gfx::Rect damage_rect(SurfaceSize());
gfx::Transform transform_to_root_target;
grandchild_pass->SetNew(
pass_id, output_rect, damage_rect, transform_to_root_target);
AddSolidColorQuadWithBlendMode(
- surface_size, grandchild_pass.get(), blend_modes[2]);
- test::QueuePassAsFrame(grandchild_pass.Pass(), &grandchild_surface);
+ SurfaceSize(), grandchild_pass.get(), blend_modes[2]);
+ QueuePassAsFrame(grandchild_pass.Pass(), grandchild_surface_id);
- Surface child_one_surface(&manager_, NULL, surface_size);
+ SurfaceId child_one_surface_id = factory_.Create(SurfaceSize());
scoped_ptr<RenderPass> child_one_pass = RenderPass::Create();
child_one_pass->SetNew(
pass_id, output_rect, damage_rect, transform_to_root_target);
AddSolidColorQuadWithBlendMode(
- surface_size, child_one_pass.get(), blend_modes[1]);
+ SurfaceSize(), child_one_pass.get(), blend_modes[1]);
scoped_ptr<SurfaceDrawQuad> grandchild_surface_quad =
SurfaceDrawQuad::Create();
grandchild_surface_quad->SetNew(child_one_pass->shared_quad_state_list.back(),
- gfx::Rect(surface_size),
- gfx::Rect(surface_size),
- grandchild_surface.surface_id());
+ gfx::Rect(SurfaceSize()),
+ gfx::Rect(SurfaceSize()),
+ grandchild_surface_id);
child_one_pass->quad_list.push_back(
grandchild_surface_quad.PassAs<DrawQuad>());
AddSolidColorQuadWithBlendMode(
- surface_size, child_one_pass.get(), blend_modes[3]);
- test::QueuePassAsFrame(child_one_pass.Pass(), &child_one_surface);
+ SurfaceSize(), child_one_pass.get(), blend_modes[3]);
+ QueuePassAsFrame(child_one_pass.Pass(), child_one_surface_id);
- Surface child_two_surface(&manager_, NULL, surface_size);
+ SurfaceId child_two_surface_id = factory_.Create(SurfaceSize());
scoped_ptr<RenderPass> child_two_pass = RenderPass::Create();
child_two_pass->SetNew(
pass_id, output_rect, damage_rect, transform_to_root_target);
AddSolidColorQuadWithBlendMode(
- surface_size, child_two_pass.get(), blend_modes[5]);
- test::QueuePassAsFrame(child_two_pass.Pass(), &child_two_surface);
+ SurfaceSize(), child_two_pass.get(), blend_modes[5]);
+ QueuePassAsFrame(child_two_pass.Pass(), child_two_surface_id);
scoped_ptr<RenderPass> root_pass = RenderPass::Create();
root_pass->SetNew(
pass_id, output_rect, damage_rect, transform_to_root_target);
- AddSolidColorQuadWithBlendMode(surface_size, root_pass.get(), blend_modes[0]);
+ AddSolidColorQuadWithBlendMode(
+ SurfaceSize(), root_pass.get(), blend_modes[0]);
scoped_ptr<SurfaceDrawQuad> child_one_surface_quad =
SurfaceDrawQuad::Create();
child_one_surface_quad->SetNew(root_pass->shared_quad_state_list.back(),
- gfx::Rect(surface_size),
- gfx::Rect(surface_size),
- child_one_surface.surface_id());
+ gfx::Rect(SurfaceSize()),
+ gfx::Rect(SurfaceSize()),
+ child_one_surface_id);
root_pass->quad_list.push_back(child_one_surface_quad.PassAs<DrawQuad>());
- AddSolidColorQuadWithBlendMode(surface_size, root_pass.get(), blend_modes[4]);
+ AddSolidColorQuadWithBlendMode(
+ SurfaceSize(), root_pass.get(), blend_modes[4]);
scoped_ptr<SurfaceDrawQuad> child_two_surface_quad =
SurfaceDrawQuad::Create();
child_two_surface_quad->SetNew(root_pass->shared_quad_state_list.back(),
- gfx::Rect(surface_size),
- gfx::Rect(surface_size),
- child_two_surface.surface_id());
+ gfx::Rect(SurfaceSize()),
+ gfx::Rect(SurfaceSize()),
+ child_two_surface_id);
root_pass->quad_list.push_back(child_two_surface_quad.PassAs<DrawQuad>());
- AddSolidColorQuadWithBlendMode(surface_size, root_pass.get(), blend_modes[6]);
+ AddSolidColorQuadWithBlendMode(
+ SurfaceSize(), root_pass.get(), blend_modes[6]);
- test::QueuePassAsFrame(root_pass.Pass(), &root_surface_);
+ QueuePassAsFrame(root_pass.Pass(), root_surface_id_);
scoped_ptr<CompositorFrame> aggregated_frame =
- aggregator_.Aggregate(root_surface_.surface_id());
+ aggregator_.Aggregate(root_surface_id_);
ASSERT_TRUE(aggregated_frame);
ASSERT_TRUE(aggregated_frame->delegated_frame_data);
@@ -565,6 +610,9 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) {
DrawQuad* quad = aggregated_quad_list[i];
EXPECT_EQ(blend_modes[i], quad->shared_quad_state->blend_mode) << i;
}
+ factory_.Destroy(child_one_surface_id);
+ factory_.Destroy(child_two_surface_id);
+ factory_.Destroy(grandchild_surface_id);
}
// This tests that when aggregating a frame with multiple render passes that we
@@ -583,9 +631,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateSharedQuadStateProperties) {
// contributing render pass' transform in the aggregate frame should not be
// affected.
TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
- gfx::Size surface_size(5, 5);
-
- Surface child_surface(&manager_, NULL, surface_size);
+ SurfaceId child_surface_id = factory_.Create(SurfaceSize());
RenderPass::Id child_pass_id[] = {RenderPass::Id(1, 1), RenderPass::Id(1, 2)};
test::Quad child_quads[][1] = {
{test::Quad::SolidColorQuad(SK_ColorGREEN)},
@@ -596,7 +642,7 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
RenderPassList child_pass_list;
AddPasses(&child_pass_list,
- gfx::Rect(surface_size),
+ gfx::Rect(SurfaceSize()),
child_passes,
arraysize(child_passes));
@@ -617,16 +663,15 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
child_frame->delegated_frame_data = child_frame_data.Pass();
- child_surface.QueueFrame(child_frame.Pass());
+ factory_.SubmitFrame(child_surface_id, child_frame.Pass());
- test::Quad root_quads[] = {
- test::Quad::SolidColorQuad(1),
- test::Quad::SurfaceQuad(child_surface.surface_id())};
+ test::Quad root_quads[] = {test::Quad::SolidColorQuad(1),
+ test::Quad::SurfaceQuad(child_surface_id)};
test::Pass root_passes[] = {test::Pass(root_quads, arraysize(root_quads))};
RenderPassList root_pass_list;
AddPasses(&root_pass_list,
- gfx::Rect(surface_size),
+ gfx::Rect(SurfaceSize()),
root_passes,
arraysize(root_passes));
@@ -643,10 +688,10 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
root_frame->delegated_frame_data = root_frame_data.Pass();
- root_surface_.QueueFrame(root_frame.Pass());
+ factory_.SubmitFrame(root_surface_id_, root_frame.Pass());
scoped_ptr<CompositorFrame> aggregated_frame =
- aggregator_.Aggregate(root_surface_.surface_id());
+ aggregator_.Aggregate(root_surface_id_);
ASSERT_TRUE(aggregated_frame);
ASSERT_TRUE(aggregated_frame->delegated_frame_data);
@@ -701,6 +746,119 @@ TEST_F(SurfaceAggregatorValidSurfaceTest, AggregateMultiplePassWithTransform) {
quad->quadTransform().ToString())
<< i;
}
+ factory_.Destroy(child_surface_id);
+}
+
+class ResourceTestDrawQuad : public DrawQuad {
+ public:
+ explicit ResourceTestDrawQuad(unsigned resource) : resource_(resource) {
+ material = DrawQuad::TEXTURE_CONTENT;
+ }
+ virtual ~ResourceTestDrawQuad() {}
+
+ virtual void IterateResources(
+ const ResourceIteratorCallback& callback) OVERRIDE {
+ callback.Run(resource_);
+ }
+
+ virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE {}
+
+ private:
+ unsigned resource_;
+};
+
+class SurfaceAggregatorWithResourcesTest : public testing::Test {
+ public:
+ virtual void SetUp() {
+ output_surface_ = FakeOutputSurface::CreateSoftware(
+ make_scoped_ptr(new SoftwareOutputDevice));
+ output_surface_->BindToClient(&output_surface_client_);
+ shared_bitmap_manager_.reset(new TestSharedBitmapManager);
+
+ resource_provider_ = ResourceProvider::Create(output_surface_.get(),
+ shared_bitmap_manager_.get(),
+ 0,
+ false,
+ 1,
+ false);
+
+ aggregator_.reset(
+ new SurfaceAggregator(&manager_, resource_provider_.get()));
+ }
+
+ protected:
+ SurfaceManager manager_;
+ FakeOutputSurfaceClient output_surface_client_;
+ scoped_ptr<OutputSurface> output_surface_;
+ scoped_ptr<SharedBitmapManager> shared_bitmap_manager_;
+ scoped_ptr<ResourceProvider> resource_provider_;
+ scoped_ptr<SurfaceAggregator> aggregator_;
+};
+
+class ResourceTrackingSurfaceFactoryClient : public SurfaceFactoryClient {
+ public:
+ ResourceTrackingSurfaceFactoryClient() {}
+ virtual ~ResourceTrackingSurfaceFactoryClient() {}
+
+ virtual void ReturnResources(
+ const ReturnedResourceArray& resources) OVERRIDE {
+ returned_resources_ = resources;
+ }
+
+ ReturnedResourceArray returned_resources() const {
+ return returned_resources_;
+ }
+
+ private:
+ ReturnedResourceArray returned_resources_;
+
+ DISALLOW_COPY_AND_ASSIGN(ResourceTrackingSurfaceFactoryClient);
+};
+
+void SubmitFrameWithResources(ResourceProvider::ResourceId* resource_ids,
+ size_t num_resource_ids,
+ SurfaceFactory* factory,
+ SurfaceId surface_id) {
+ scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
+ scoped_ptr<RenderPass> pass = RenderPass::Create();
+ SharedQuadState* sqs = pass->CreateAndAppendSharedQuadState();
+ for (size_t i = 0u; i < num_resource_ids; ++i) {
+ TransferableResource resource;
+ resource.id = resource_ids[i];
+ resource.is_software = true;
+ frame_data->resource_list.push_back(resource);
+ scoped_ptr<DrawQuad> quad(new ResourceTestDrawQuad(resource_ids[i]));
+ quad->shared_quad_state = sqs;
+ pass->quad_list.push_back(quad.Pass());
+ }
+ frame_data->render_pass_list.push_back(pass.Pass());
+ scoped_ptr<CompositorFrame> frame(new CompositorFrame);
+ frame->delegated_frame_data = frame_data.Pass();
+ factory->SubmitFrame(surface_id, frame.Pass());
+}
+
+TEST_F(SurfaceAggregatorWithResourcesTest, TakeResourcesOneSurface) {
+ ResourceTrackingSurfaceFactoryClient client;
+ SurfaceFactory factory(&manager_, &client);
+ SurfaceId surface_id = factory.Create(SurfaceSize());
+
+ ResourceProvider::ResourceId ids[] = {11, 12, 13};
+ SubmitFrameWithResources(ids, arraysize(ids), &factory, surface_id);
+
+ scoped_ptr<CompositorFrame> frame = aggregator_->Aggregate(surface_id);
+
+ // Nothing should be available to be returned yet.
+ EXPECT_TRUE(client.returned_resources().empty());
+
+ SubmitFrameWithResources(NULL, 0u, &factory, surface_id);
+
+ frame = aggregator_->Aggregate(surface_id);
+
+ ASSERT_EQ(3u, client.returned_resources().size());
+ for (size_t i = 0; i < 3; ++i) {
+ EXPECT_EQ(ids[i], client.returned_resources()[i].id);
+ }
+ factory.Destroy(surface_id);
}
} // namespace
diff --git a/cc/surfaces/surface_factory.cc b/cc/surfaces/surface_factory.cc
new file mode 100644
index 0000000..09c9f45
--- /dev/null
+++ b/cc/surfaces/surface_factory.cc
@@ -0,0 +1,59 @@
+// 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_factory.h"
+
+#include "cc/output/compositor_frame.h"
+#include "cc/surfaces/surface.h"
+#include "cc/surfaces/surface_manager.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace cc {
+SurfaceFactory::SurfaceFactory(SurfaceManager* manager,
+ SurfaceFactoryClient* client)
+ : manager_(manager), client_(client), holder_(client) {
+}
+
+SurfaceFactory::~SurfaceFactory() {
+ DCHECK_EQ(0u, surface_map_.size());
+}
+
+SurfaceId SurfaceFactory::Create(const gfx::Size& size) {
+ SurfaceId id = manager_->AllocateId();
+ scoped_ptr<Surface> surface(new Surface(id, size, this));
+ manager_->RegisterSurface(surface.get());
+ surface_map_.add(id, surface.Pass());
+ return id;
+}
+
+void SurfaceFactory::Destroy(SurfaceId surface_id) {
+ OwningSurfaceMap::iterator it = surface_map_.find(surface_id);
+ DCHECK(it != surface_map_.end());
+ DCHECK(it->second->factory() == this);
+ manager_->DeregisterSurface(surface_id);
+ surface_map_.erase(it);
+}
+
+void SurfaceFactory::SubmitFrame(SurfaceId surface_id,
+ scoped_ptr<CompositorFrame> frame) {
+ OwningSurfaceMap::iterator it = surface_map_.find(surface_id);
+ DCHECK(it != surface_map_.end());
+ DCHECK(it->second->factory() == this);
+ it->second->QueueFrame(frame.Pass());
+}
+
+void SurfaceFactory::ReceiveFromChild(
+ const TransferableResourceArray& resources) {
+ holder_.ReceiveFromChild(resources);
+}
+
+void SurfaceFactory::RefResources(const TransferableResourceArray& resources) {
+ holder_.RefResources(resources);
+}
+
+void SurfaceFactory::UnrefResources(const ReturnedResourceArray& resources) {
+ holder_.UnrefResources(resources);
+}
+
+} // namespace cc
diff --git a/cc/surfaces/surface_factory.h b/cc/surfaces/surface_factory.h
new file mode 100644
index 0000000..5ea85d4
--- /dev/null
+++ b/cc/surfaces/surface_factory.h
@@ -0,0 +1,61 @@
+// 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.
+
+#ifndef CC_SURFACES_SURFACE_FACTORY_H_
+#define CC_SURFACES_SURFACE_FACTORY_H_
+
+#include "base/containers/scoped_ptr_hash_map.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "cc/surfaces/surface_id.h"
+#include "cc/surfaces/surface_resource_holder.h"
+#include "cc/surfaces/surfaces_export.h"
+
+namespace gfx {
+class Size;
+}
+
+namespace cc {
+class CompositorFrame;
+class Surface;
+class SurfaceFactoryClient;
+class SurfaceManager;
+
+// A SurfaceFactory is used to create surfaces that may share resources and
+// receive returned resources for frames submitted to those surfaces. Resources
+// submitted to frames created by a particular factory will be returned to that
+// factory's client when they are no longer being used. This is the only class
+// most users of surfaces will need to directly interact with.
+class CC_SURFACES_EXPORT SurfaceFactory
+ : public base::SupportsWeakPtr<SurfaceFactory> {
+ public:
+ SurfaceFactory(SurfaceManager* manager, SurfaceFactoryClient* client);
+ ~SurfaceFactory();
+
+ SurfaceId Create(const gfx::Size& size);
+ void Destroy(SurfaceId surface_id);
+ // A frame can only be submitted to a surface created by this factory,
+ // although the frame may reference surfaces created by other factories.
+ void SubmitFrame(SurfaceId surface_id, scoped_ptr<CompositorFrame> frame);
+
+ SurfaceFactoryClient* client() { return client_; }
+
+ void ReceiveFromChild(const TransferableResourceArray& resources);
+ void RefResources(const TransferableResourceArray& resources);
+ void UnrefResources(const ReturnedResourceArray& resources);
+
+ private:
+ SurfaceManager* manager_;
+ SurfaceFactoryClient* client_;
+ typedef base::ScopedPtrHashMap<SurfaceId, Surface> OwningSurfaceMap;
+ base::ScopedPtrHashMap<SurfaceId, Surface> surface_map_;
+
+ SurfaceResourceHolder holder_;
+
+ DISALLOW_COPY_AND_ASSIGN(SurfaceFactory);
+};
+
+} // namespace cc
+
+#endif // CC_SURFACES_SURFACE_FACTORY_H_
diff --git a/cc/surfaces/surface_client.h b/cc/surfaces/surface_factory_client.h
index 8875872..9866b27 100644
--- a/cc/surfaces/surface_client.h
+++ b/cc/surfaces/surface_factory_client.h
@@ -2,21 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CC_SURFACES_SURFACE_CLIENT_H_
-#define CC_SURFACES_SURFACE_CLIENT_H_
+#ifndef CC_SURFACES_SURFACE_FACTORY_CLIENT_H_
+#define CC_SURFACES_SURFACE_FACTORY_CLIENT_H_
#include "cc/resources/returned_resource.h"
#include "cc/surfaces/surfaces_export.h"
namespace cc {
-class CC_SURFACES_EXPORT SurfaceClient {
+class CC_SURFACES_EXPORT SurfaceFactoryClient {
public:
- virtual ~SurfaceClient() {}
+ virtual ~SurfaceFactoryClient() {}
virtual void ReturnResources(const ReturnedResourceArray& resources) = 0;
};
} // namespace cc
-#endif // CC_SURFACES_SURFACE_CLIENT_H_
+#endif // CC_SURFACES_SURFACE_FACTORY_CLIENT_H_
diff --git a/cc/surfaces/surface_factory_unittest.cc b/cc/surfaces/surface_factory_unittest.cc
new file mode 100644
index 0000000..f6244e8
--- /dev/null
+++ b/cc/surfaces/surface_factory_unittest.cc
@@ -0,0 +1,360 @@
+// 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/output/compositor_frame.h"
+#include "cc/output/delegated_frame_data.h"
+#include "cc/surfaces/surface.h"
+#include "cc/surfaces/surface_factory.h"
+#include "cc/surfaces/surface_factory_client.h"
+#include "cc/surfaces/surface_manager.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/size.h"
+
+namespace cc {
+namespace {
+
+class TestSurfaceFactoryClient : public SurfaceFactoryClient {
+ public:
+ TestSurfaceFactoryClient() {}
+ virtual ~TestSurfaceFactoryClient() {}
+
+ virtual void ReturnResources(
+ const ReturnedResourceArray& resources) OVERRIDE {
+ returned_resources_.insert(
+ returned_resources_.end(), resources.begin(), resources.end());
+ }
+
+ const ReturnedResourceArray& returned_resources() const {
+ return returned_resources_;
+ }
+
+ void clear_returned_resources() { returned_resources_.clear(); }
+
+ private:
+ ReturnedResourceArray returned_resources_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestSurfaceFactoryClient);
+};
+
+class SurfaceFactoryTest : public testing::Test {
+ public:
+ SurfaceFactoryTest()
+ : factory_(&manager_, &client_),
+ surface_id_(factory_.Create(gfx::Size(5, 5))) {}
+
+ virtual ~SurfaceFactoryTest() { factory_.Destroy(surface_id_); }
+
+ void SubmitFrameWithResources(ResourceProvider::ResourceId* resource_ids,
+ size_t num_resource_ids) {
+ scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
+ for (size_t i = 0u; i < num_resource_ids; ++i) {
+ TransferableResource resource;
+ resource.id = resource_ids[i];
+ resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
+ frame_data->resource_list.push_back(resource);
+ }
+ scoped_ptr<CompositorFrame> frame(new CompositorFrame);
+ frame->delegated_frame_data = frame_data.Pass();
+ factory_.SubmitFrame(surface_id_, frame.Pass());
+ }
+
+ void UnrefResources(ResourceProvider::ResourceId* ids_to_unref,
+ int* counts_to_unref,
+ size_t num_ids_to_unref) {
+ ReturnedResourceArray unref_array;
+ for (size_t i = 0; i < num_ids_to_unref; ++i) {
+ ReturnedResource resource;
+ resource.id = ids_to_unref[i];
+ resource.count = counts_to_unref[i];
+ unref_array.push_back(resource);
+ }
+ factory_.UnrefResources(unref_array);
+ }
+
+ void CheckReturnedResourcesMatchExpected(
+ ResourceProvider::ResourceId* expected_returned_ids,
+ int* expected_returned_counts,
+ size_t expected_resources) {
+ const ReturnedResourceArray& actual_resources =
+ client_.returned_resources();
+ ASSERT_EQ(expected_resources, actual_resources.size());
+ for (size_t i = 0; i < expected_resources; ++i) {
+ ReturnedResource resource = actual_resources[i];
+ EXPECT_EQ(expected_returned_ids[i], resource.id);
+ EXPECT_EQ(expected_returned_counts[i], resource.count);
+ }
+ client_.clear_returned_resources();
+ }
+
+ void RefCurrentFrameResources() {
+ Surface* surface = manager_.GetSurfaceForId(surface_id_);
+ factory_.RefResources(
+ surface->GetEligibleFrame()->delegated_frame_data->resource_list);
+ }
+
+ protected:
+ SurfaceManager manager_;
+ TestSurfaceFactoryClient client_;
+ SurfaceFactory factory_;
+ SurfaceId surface_id_;
+};
+
+// Tests submitting a frame with resources followed by one with no resources
+// with no resource provider action in between.
+TEST_F(SurfaceFactoryTest, ResourceLifetimeSimple) {
+ ResourceProvider::ResourceId first_frame_ids[] = {1, 2, 3};
+ SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
+
+ // All of the resources submitted in the first frame are still in use at this
+ // time by virtue of being in the pending frame, so none can be returned to
+ // the client yet.
+ EXPECT_EQ(0u, client_.returned_resources().size());
+ client_.clear_returned_resources();
+
+ // The second frame references no resources and thus should make all resources
+ // available to be returned.
+ SubmitFrameWithResources(NULL, 0);
+
+ ResourceProvider::ResourceId expected_returned_ids[] = {1, 2, 3};
+ int expected_returned_counts[] = {1, 1, 1};
+ CheckReturnedResourcesMatchExpected(expected_returned_ids,
+ expected_returned_counts,
+ arraysize(expected_returned_counts));
+}
+
+// Tests submitting a frame with resources followed by one with no resources
+// with the resource provider holding everything alive.
+TEST_F(SurfaceFactoryTest, ResourceLifetimeSimpleWithProviderHoldingAlive) {
+ ResourceProvider::ResourceId first_frame_ids[] = {1, 2, 3};
+ SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
+
+ // All of the resources submitted in the first frame are still in use at this
+ // time by virtue of being in the pending frame, so none can be returned to
+ // the client yet.
+ EXPECT_EQ(0u, client_.returned_resources().size());
+ client_.clear_returned_resources();
+
+ // Hold on to everything.
+ RefCurrentFrameResources();
+
+ // The second frame references no resources and thus should make all resources
+ // available to be returned as soon as the resource provider releases them.
+ SubmitFrameWithResources(NULL, 0);
+
+ EXPECT_EQ(0u, client_.returned_resources().size());
+ client_.clear_returned_resources();
+
+ int release_counts[] = {1, 1, 1};
+ UnrefResources(first_frame_ids, release_counts, arraysize(first_frame_ids));
+
+ ResourceProvider::ResourceId expected_returned_ids[] = {1, 2, 3};
+ int expected_returned_counts[] = {1, 1, 1};
+ CheckReturnedResourcesMatchExpected(expected_returned_ids,
+ expected_returned_counts,
+ arraysize(expected_returned_counts));
+}
+
+// Tests referencing a resource, unref'ing it to zero, then using it again
+// before returning it to the client.
+TEST_F(SurfaceFactoryTest, ResourceReusedBeforeReturn) {
+ ResourceProvider::ResourceId first_frame_ids[] = {7};
+ SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
+
+ // This removes all references to resource id 7.
+ SubmitFrameWithResources(NULL, 0);
+
+ // This references id 7 again.
+ SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
+
+ // This removes it again.
+ SubmitFrameWithResources(NULL, 0);
+
+ // Now it should be returned.
+ // We don't care how many entries are in the returned array for 7, so long as
+ // the total returned count matches the submitted count.
+ const ReturnedResourceArray& returned = client_.returned_resources();
+ size_t return_count = 0;
+ for (size_t i = 0; i < returned.size(); ++i) {
+ EXPECT_EQ(7u, returned[i].id);
+ return_count += returned[i].count;
+ }
+ EXPECT_EQ(2u, return_count);
+}
+
+// Tests having resources referenced multiple times, as if referenced by
+// multiple providers.
+TEST_F(SurfaceFactoryTest, ResourceRefMultipleTimes) {
+ ResourceProvider::ResourceId first_frame_ids[] = {3, 4};
+ SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
+
+ // Ref resources from the first frame twice.
+ RefCurrentFrameResources();
+ RefCurrentFrameResources();
+
+ ResourceProvider::ResourceId second_frame_ids[] = {4, 5};
+ SubmitFrameWithResources(second_frame_ids, arraysize(second_frame_ids));
+
+ // Ref resources from the second frame 3 times.
+ RefCurrentFrameResources();
+ RefCurrentFrameResources();
+ RefCurrentFrameResources();
+
+ // Submit a frame with no resources to remove all current frame refs from
+ // submitted resources.
+ SubmitFrameWithResources(NULL, 0);
+
+ EXPECT_EQ(0u, client_.returned_resources().size());
+ client_.clear_returned_resources();
+
+ // Expected current refs:
+ // 3 -> 2
+ // 4 -> 2 + 3 = 5
+ // 5 -> 3
+ {
+ SCOPED_TRACE("unref all 3");
+ ResourceProvider::ResourceId ids_to_unref[] = {3, 4, 5};
+ int counts[] = {1, 1, 1};
+ UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
+
+ EXPECT_EQ(0u, client_.returned_resources().size());
+ client_.clear_returned_resources();
+
+ UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
+
+ ResourceProvider::ResourceId expected_returned_ids[] = {3};
+ int expected_returned_counts[] = {1};
+ CheckReturnedResourcesMatchExpected(expected_returned_ids,
+ expected_returned_counts,
+ arraysize(expected_returned_counts));
+ }
+
+ // Expected refs remaining:
+ // 4 -> 3
+ // 5 -> 1
+ {
+ SCOPED_TRACE("unref 4 and 5");
+ ResourceProvider::ResourceId ids_to_unref[] = {4, 5};
+ int counts[] = {1, 1};
+ UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
+
+ ResourceProvider::ResourceId expected_returned_ids[] = {5};
+ int expected_returned_counts[] = {1};
+ CheckReturnedResourcesMatchExpected(expected_returned_ids,
+ expected_returned_counts,
+ arraysize(expected_returned_counts));
+ }
+
+ // Now, just 2 refs remaining on resource 4. Unref both at once and make sure
+ // the returned count is correct.
+ {
+ SCOPED_TRACE("unref only 4");
+ ResourceProvider::ResourceId ids_to_unref[] = {4};
+ int counts[] = {2};
+ UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
+
+ ResourceProvider::ResourceId expected_returned_ids[] = {4};
+ int expected_returned_counts[] = {2};
+ CheckReturnedResourcesMatchExpected(expected_returned_ids,
+ expected_returned_counts,
+ arraysize(expected_returned_counts));
+ }
+}
+
+TEST_F(SurfaceFactoryTest, ResourceLifetime) {
+ ResourceProvider::ResourceId first_frame_ids[] = {1, 2, 3};
+ SubmitFrameWithResources(first_frame_ids, arraysize(first_frame_ids));
+
+ // All of the resources submitted in the first frame are still in use at this
+ // time by virtue of being in the pending frame, so none can be returned to
+ // the client yet.
+ EXPECT_EQ(0u, client_.returned_resources().size());
+ client_.clear_returned_resources();
+
+ // The second frame references some of the same resources, but some different
+ // ones. We expect to receive back resource 1 with a count of 1 since it was
+ // only referenced by the first frame.
+ ResourceProvider::ResourceId second_frame_ids[] = {2, 3, 4};
+ SubmitFrameWithResources(second_frame_ids, arraysize(second_frame_ids));
+
+ {
+ SCOPED_TRACE("second frame");
+ ResourceProvider::ResourceId expected_returned_ids[] = {1};
+ int expected_returned_counts[] = {1};
+ CheckReturnedResourcesMatchExpected(expected_returned_ids,
+ expected_returned_counts,
+ arraysize(expected_returned_counts));
+ }
+
+ // The third frame references a disjoint set of resources, so we expect to
+ // receive back all resources from the first and second frames. Resource IDs 2
+ // and 3 will have counts of 2, since they were used in both frames, and
+ // resource ID 4 will have a count of 1.
+ ResourceProvider::ResourceId third_frame_ids[] = {10, 11, 12, 13};
+ SubmitFrameWithResources(third_frame_ids, arraysize(third_frame_ids));
+
+ {
+ SCOPED_TRACE("third frame");
+ ResourceProvider::ResourceId expected_returned_ids[] = {2, 3, 4};
+ int expected_returned_counts[] = {2, 2, 1};
+ CheckReturnedResourcesMatchExpected(expected_returned_ids,
+ expected_returned_counts,
+ arraysize(expected_returned_counts));
+ }
+
+ // Simulate a ResourceProvider taking a ref on all of the resources.
+ RefCurrentFrameResources();
+
+ ResourceProvider::ResourceId fourth_frame_ids[] = {12, 13};
+ SubmitFrameWithResources(fourth_frame_ids, arraysize(fourth_frame_ids));
+
+ EXPECT_EQ(0u, client_.returned_resources().size());
+
+ RefCurrentFrameResources();
+
+ // All resources are still being used by the external reference, so none can
+ // be returned to the client.
+ EXPECT_EQ(0u, client_.returned_resources().size());
+
+ // Release resources associated with the first RefCurrentFrameResources() call
+ // first.
+ {
+ ResourceProvider::ResourceId ids_to_unref[] = {10, 11, 12, 13};
+ int counts[] = {1, 1, 1, 1};
+ UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
+ }
+
+ {
+ SCOPED_TRACE("fourth frame, first unref");
+ ResourceProvider::ResourceId expected_returned_ids[] = {10, 11};
+ int expected_returned_counts[] = {1, 1};
+ CheckReturnedResourcesMatchExpected(expected_returned_ids,
+ expected_returned_counts,
+ arraysize(expected_returned_counts));
+ }
+
+ {
+ ResourceProvider::ResourceId ids_to_unref[] = {12, 13};
+ int counts[] = {1, 1};
+ UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref));
+ }
+
+ // Resources 12 and 13 are still in use by the current frame, so they
+ // shouldn't be available to be returned.
+ EXPECT_EQ(0u, client_.returned_resources().size());
+
+ // If we submit an empty frame, however, they should become available.
+ SubmitFrameWithResources(NULL, 0u);
+
+ {
+ SCOPED_TRACE("fourth frame, second unref");
+ ResourceProvider::ResourceId expected_returned_ids[] = {12, 13};
+ int expected_returned_counts[] = {2, 2};
+ CheckReturnedResourcesMatchExpected(expected_returned_ids,
+ expected_returned_counts,
+ arraysize(expected_returned_counts));
+ }
+}
+
+} // namespace
+} // namespace cc
diff --git a/cc/surfaces/surface_id.h b/cc/surfaces/surface_id.h
index aa9474d..9b59f64 100644
--- a/cc/surfaces/surface_id.h
+++ b/cc/surfaces/surface_id.h
@@ -5,6 +5,9 @@
#ifndef CC_SURFACES_SURFACE_ID_H_
#define CC_SURFACES_SURFACE_ID_H_
+#include "base/compiler_specific.h"
+#include "base/containers/hash_tables.h"
+
namespace cc {
struct SurfaceId {
@@ -24,6 +27,25 @@ inline bool operator!=(const SurfaceId& a, const SurfaceId& b) {
return !(a == b);
}
+inline bool operator<(const SurfaceId& a, const SurfaceId& b) {
+ return a.id < b.id;
+}
+
} // namespace cc
+namespace BASE_HASH_NAMESPACE {
+#if defined(COMPILER_MSVC)
+inline size_t hash_value(const cc::SurfaceId& key) {
+ return hash_value(key.id);
+}
+#elif defined(COMPILER_GCC)
+template <>
+struct hash<cc::SurfaceId> {
+ size_t operator()(cc::SurfaceId key) const { return hash<int>()(key.id); }
+};
+#else
+#error define a hash function for your compiler
+#endif // COMPILER
+} // namespace BASE_HASH_NAMESPACE
+
#endif // CC_SURFACES_SURFACE_ID_H_
diff --git a/cc/surfaces/surface_manager.cc b/cc/surfaces/surface_manager.cc
index b41aefc..77ad3c1 100644
--- a/cc/surfaces/surface_manager.cc
+++ b/cc/surfaces/surface_manager.cc
@@ -5,30 +5,36 @@
#include "cc/surfaces/surface_manager.h"
#include "base/logging.h"
+#include "cc/surfaces/surface.h"
namespace cc {
-SurfaceManager::SurfaceManager()
- : next_surface_id_(1) {
+SurfaceManager::SurfaceManager() : next_surface_id_(1) {
}
-SurfaceManager::~SurfaceManager() {}
+SurfaceManager::~SurfaceManager() {
+ DCHECK_EQ(0u, surface_map_.size());
+}
-SurfaceId SurfaceManager::RegisterAndAllocateIdForSurface(Surface* surface) {
- DCHECK(surface);
+SurfaceId SurfaceManager::AllocateId() {
int surface_id = next_surface_id_++;
- surface_map_[surface_id] = surface;
return SurfaceId(surface_id);
}
+void SurfaceManager::RegisterSurface(Surface* surface) {
+ DCHECK(surface);
+ DCHECK(!surface_map_.count(surface->surface_id()));
+ surface_map_[surface->surface_id()] = surface;
+}
+
void SurfaceManager::DeregisterSurface(SurfaceId surface_id) {
- SurfaceMap::iterator it = surface_map_.find(surface_id.id);
+ SurfaceMap::iterator it = surface_map_.find(surface_id);
DCHECK(it != surface_map_.end());
surface_map_.erase(it);
}
Surface* SurfaceManager::GetSurfaceForId(SurfaceId surface_id) {
- SurfaceMap::iterator it = surface_map_.find(surface_id.id);
+ SurfaceMap::iterator it = surface_map_.find(surface_id);
if (it == surface_map_.end())
return NULL;
return it->second;
diff --git a/cc/surfaces/surface_manager.h b/cc/surfaces/surface_manager.h
index b14259d..726ed85 100644
--- a/cc/surfaces/surface_manager.h
+++ b/cc/surfaces/surface_manager.h
@@ -13,20 +13,20 @@
namespace cc {
class CompositorFrame;
class Surface;
-class SurfaceClient;
class CC_SURFACES_EXPORT SurfaceManager {
public:
SurfaceManager();
~SurfaceManager();
- SurfaceId RegisterAndAllocateIdForSurface(Surface* surface);
+ SurfaceId AllocateId();
+ void RegisterSurface(Surface* surface);
void DeregisterSurface(SurfaceId surface_id);
Surface* GetSurfaceForId(SurfaceId surface_id);
private:
- typedef base::hash_map<int, Surface*> SurfaceMap;
+ typedef base::hash_map<SurfaceId, Surface*> SurfaceMap;
SurfaceMap surface_map_;
int next_surface_id_;
diff --git a/cc/surfaces/surface_resource_holder.cc b/cc/surfaces/surface_resource_holder.cc
new file mode 100644
index 0000000..d142f7f
--- /dev/null
+++ b/cc/surfaces/surface_resource_holder.cc
@@ -0,0 +1,68 @@
+// 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_resource_holder.h"
+
+#include "cc/surfaces/surface_factory_client.h"
+
+namespace cc {
+
+SurfaceResourceHolder::SurfaceResourceHolder(SurfaceFactoryClient* client)
+ : client_(client) {
+}
+
+SurfaceResourceHolder::~SurfaceResourceHolder() {
+}
+
+SurfaceResourceHolder::ResourceRefs::ResourceRefs()
+ : refs_received_from_child(0), refs_holding_resource_alive(0) {
+}
+
+void SurfaceResourceHolder::ReceiveFromChild(
+ const TransferableResourceArray& resources) {
+ for (TransferableResourceArray::const_iterator it = resources.begin();
+ it != resources.end();
+ ++it) {
+ ResourceRefs& ref = resource_id_use_count_map_[it->id];
+ ref.refs_holding_resource_alive++;
+ ref.refs_received_from_child++;
+ }
+}
+
+void SurfaceResourceHolder::RefResources(
+ const TransferableResourceArray& resources) {
+ for (TransferableResourceArray::const_iterator it = resources.begin();
+ it != resources.end();
+ ++it) {
+ ResourceIdCountMap::iterator count_it =
+ resource_id_use_count_map_.find(it->id);
+ DCHECK(count_it != resource_id_use_count_map_.end());
+ count_it->second.refs_holding_resource_alive++;
+ }
+}
+
+void SurfaceResourceHolder::UnrefResources(
+ const ReturnedResourceArray& resources) {
+ ReturnedResourceArray resources_available_to_return;
+
+ for (ReturnedResourceArray::const_iterator it = resources.begin();
+ it != resources.end();
+ ++it) {
+ ResourceProvider::ResourceId id = it->id;
+ ResourceIdCountMap::iterator count_it = resource_id_use_count_map_.find(id);
+ DCHECK(count_it != resource_id_use_count_map_.end());
+ ResourceRefs& ref = count_it->second;
+ ref.refs_holding_resource_alive -= it->count;
+ if (ref.refs_holding_resource_alive == 0) {
+ ReturnedResource returned = *it;
+ returned.count = ref.refs_received_from_child;
+ resources_available_to_return.push_back(returned);
+ resource_id_use_count_map_.erase(count_it);
+ }
+ }
+
+ client_->ReturnResources(resources_available_to_return);
+}
+
+} // namespace cc
diff --git a/cc/surfaces/surface_resource_holder.h b/cc/surfaces/surface_resource_holder.h
new file mode 100644
index 0000000..20c9f29
--- /dev/null
+++ b/cc/surfaces/surface_resource_holder.h
@@ -0,0 +1,51 @@
+// 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.
+
+#ifndef CC_SURFACES_SURFACE_RESOURCE_HOLDER_H_
+#define CC_SURFACES_SURFACE_RESOURCE_HOLDER_H_
+
+#include "base/containers/hash_tables.h"
+#include "base/macros.h"
+#include "cc/resources/resource_provider.h"
+#include "cc/resources/returned_resource.h"
+#include "cc/surfaces/surfaces_export.h"
+
+namespace cc {
+class SurfaceFactoryClient;
+
+// A SurfaceResourceHolder manages the lifetime of resources submitted by a
+// particular SurfaceFactory. Each resource is held by the service until
+// it is no longer referenced by any pending frames or by any
+// resource providers.
+class CC_SURFACES_EXPORT SurfaceResourceHolder {
+ public:
+ explicit SurfaceResourceHolder(SurfaceFactoryClient* client);
+ ~SurfaceResourceHolder();
+
+ void ReceiveFromChild(const TransferableResourceArray& resources);
+ void RefResources(const TransferableResourceArray& resources);
+ void UnrefResources(const ReturnedResourceArray& resources);
+
+ private:
+ SurfaceFactoryClient* client_;
+
+ struct ResourceRefs {
+ ResourceRefs();
+
+ int refs_received_from_child;
+ int refs_holding_resource_alive;
+ };
+ // Keeps track of the number of users currently in flight for each resource
+ // ID we've received from the client. When this counter hits zero for a
+ // particular resource, that ID is available to return to the client.
+ typedef base::hash_map<ResourceProvider::ResourceId, ResourceRefs>
+ ResourceIdCountMap;
+ ResourceIdCountMap resource_id_use_count_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(SurfaceResourceHolder);
+};
+
+} // namespace cc
+
+#endif // CC_SURFACES_SURFACE_RESOURCE_HOLDER_H_
diff --git a/cc/surfaces/surface_unittest.cc b/cc/surfaces/surface_unittest.cc
index 66890c4..7d91b0a 100644
--- a/cc/surfaces/surface_unittest.cc
+++ b/cc/surfaces/surface_unittest.cc
@@ -2,10 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "cc/output/compositor_frame.h"
-#include "cc/output/delegated_frame_data.h"
#include "cc/surfaces/surface.h"
-#include "cc/surfaces/surface_client.h"
+#include "cc/surfaces/surface_factory.h"
#include "cc/surfaces/surface_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/size.h"
@@ -15,397 +13,18 @@ namespace {
TEST(SurfaceTest, SurfaceLifetime) {
SurfaceManager manager;
+ SurfaceFactory factory(&manager, NULL);
SurfaceId surface_id;
{
- Surface surface(&manager, NULL, gfx::Size(5, 5));
- surface_id = surface.surface_id();
+ surface_id = factory.Create(gfx::Size(5, 5));
EXPECT_TRUE(!surface_id.is_null());
- EXPECT_EQ(&surface, manager.GetSurfaceForId(surface_id));
+ EXPECT_TRUE(!!manager.GetSurfaceForId(surface_id));
+ factory.Destroy(surface_id);
}
EXPECT_EQ(NULL, manager.GetSurfaceForId(surface_id));
}
-class TestSurfaceClient : public SurfaceClient {
- public:
- TestSurfaceClient() {}
- virtual ~TestSurfaceClient() {}
-
- virtual void ReturnResources(
- const ReturnedResourceArray& resources) OVERRIDE {
- returned_resources_ = resources;
- }
-
- const ReturnedResourceArray& returned_resources() const {
- return returned_resources_;
- }
-
- void clear_returned_resources() { returned_resources_.clear(); }
-
- private:
- ReturnedResourceArray returned_resources_;
-
- DISALLOW_COPY_AND_ASSIGN(TestSurfaceClient);
-};
-
-void SubmitFrameWithResources(ResourceProvider::ResourceId* resource_ids,
- size_t num_resource_ids,
- Surface* surface) {
- scoped_ptr<DelegatedFrameData> frame_data(new DelegatedFrameData);
- for (size_t i = 0u; i < num_resource_ids; ++i) {
- TransferableResource resource;
- resource.id = resource_ids[i];
- resource.mailbox_holder.texture_target = GL_TEXTURE_2D;
- frame_data->resource_list.push_back(resource);
- }
- scoped_ptr<CompositorFrame> frame(new CompositorFrame);
- frame->delegated_frame_data = frame_data.Pass();
- surface->QueueFrame(frame.Pass());
-}
-
-void CheckReturnedResourcesMatchExpected(
- ResourceProvider::ResourceId* expected_returned_ids,
- int* expected_returned_counts,
- size_t expected_resources,
- const ReturnedResourceArray& actual_resources) {
- ASSERT_EQ(expected_resources, actual_resources.size());
- for (size_t i = 0; i < expected_resources; ++i) {
- ReturnedResource resource = actual_resources[i];
- EXPECT_EQ(expected_returned_ids[i], resource.id);
- EXPECT_EQ(expected_returned_counts[i], resource.count);
- }
-}
-
-void UnrefResources(ResourceProvider::ResourceId* ids_to_unref,
- int* counts_to_unref,
- size_t num_ids_to_unref,
- Surface* surface) {
- ReturnedResourceArray unref_array;
- for (size_t i = 0; i < num_ids_to_unref; ++i) {
- ReturnedResource resource;
- resource.id = ids_to_unref[i];
- resource.count = counts_to_unref[i];
- unref_array.push_back(resource);
- }
- surface->UnrefResources(unref_array);
-}
-
-// Tests submitting a frame with resources followed by one with no resources
-// with no resource provider action in between.
-TEST(SurfaceTest, ResourceLifetimeSimple) {
- SurfaceManager manager;
- TestSurfaceClient client;
- Surface surface(&manager, &client, gfx::Size(5, 5));
-
- ResourceProvider::ResourceId first_frame_ids[] = {1, 2, 3};
- SubmitFrameWithResources(
- first_frame_ids, arraysize(first_frame_ids), &surface);
-
- // All of the resources submitted in the first frame are still in use at this
- // time by virtue of being in the pending frame, so none can be returned to
- // the client yet.
- surface.ReturnUnusedResourcesToClient();
- EXPECT_EQ(0u, client.returned_resources().size());
- client.clear_returned_resources();
-
- // The second frame references no resources and thus should make all resources
- // available to be returned.
- SubmitFrameWithResources(NULL, 0, &surface);
-
- surface.ReturnUnusedResourcesToClient();
- ResourceProvider::ResourceId expected_returned_ids[] = {1, 2, 3};
- int expected_returned_counts[] = {1, 1, 1};
- CheckReturnedResourcesMatchExpected(expected_returned_ids,
- expected_returned_counts,
- arraysize(expected_returned_counts),
- client.returned_resources());
-}
-
-// Tests submitting a frame with resources followed by one with no resources
-// with the resource provider holding everything alive.
-TEST(SurfaceTest, ResourceLifetimeSimpleWithProviderHoldingAlive) {
- SurfaceManager manager;
- TestSurfaceClient client;
- Surface surface(&manager, &client, gfx::Size(5, 5));
-
- ResourceProvider::ResourceId first_frame_ids[] = {1, 2, 3};
- SubmitFrameWithResources(
- first_frame_ids, arraysize(first_frame_ids), &surface);
-
- // All of the resources submitted in the first frame are still in use at this
- // time by virtue of being in the pending frame, so none can be returned to
- // the client yet.
- surface.ReturnUnusedResourcesToClient();
- EXPECT_EQ(0u, client.returned_resources().size());
- client.clear_returned_resources();
-
- // Hold on to everything.
- surface.RefCurrentFrameResources();
-
- // The second frame references no resources and thus should make all resources
- // available to be returned as soon as the resource provider releases them.
- SubmitFrameWithResources(NULL, 0, &surface);
-
- surface.ReturnUnusedResourcesToClient();
- EXPECT_EQ(0u, client.returned_resources().size());
- client.clear_returned_resources();
-
- int release_counts[] = {1, 1, 1};
- UnrefResources(
- first_frame_ids, release_counts, arraysize(first_frame_ids), &surface);
-
- surface.ReturnUnusedResourcesToClient();
- ResourceProvider::ResourceId expected_returned_ids[] = {1, 2, 3};
- int expected_returned_counts[] = {1, 1, 1};
- CheckReturnedResourcesMatchExpected(expected_returned_ids,
- expected_returned_counts,
- arraysize(expected_returned_counts),
- client.returned_resources());
-}
-
-// Tests referencing a resource, unref'ing it to zero, then using it again
-// before returning it to the client.
-TEST(SurfaceTest, ResourceReusedBeforeReturn) {
- SurfaceManager manager;
- TestSurfaceClient client;
- Surface surface(&manager, &client, gfx::Size(5, 5));
-
- ResourceProvider::ResourceId first_frame_ids[] = {7};
- SubmitFrameWithResources(
- first_frame_ids, arraysize(first_frame_ids), &surface);
-
- // This removes all references to resource id 7.
- SubmitFrameWithResources(NULL, 0, &surface);
-
- // This references id 7 again.
- SubmitFrameWithResources(
- first_frame_ids, arraysize(first_frame_ids), &surface);
-
- // This removes it again.
- SubmitFrameWithResources(NULL, 0, &surface);
-
- // Now it should be returned.
- surface.ReturnUnusedResourcesToClient();
-
- // We don't care how many entries are in the returned array for 7, so long as
- // the total returned count matches the submitted count.
- const ReturnedResourceArray& returned = client.returned_resources();
- size_t return_count = 0;
- for (size_t i = 0; i < returned.size(); ++i) {
- EXPECT_EQ(7u, returned[i].id);
- return_count += returned[i].count;
- }
- EXPECT_EQ(2u, return_count);
-}
-
-// Tests having resources referenced multiple times, as if referenced by
-// multiple providers.
-TEST(SurfaceTest, ResourceRefMultipleTimes) {
- SurfaceManager manager;
- TestSurfaceClient client;
- Surface surface(&manager, &client, gfx::Size(5, 5));
-
- ResourceProvider::ResourceId first_frame_ids[] = {3, 4};
- SubmitFrameWithResources(
- first_frame_ids, arraysize(first_frame_ids), &surface);
-
- // Ref resources from the first frame twice.
- surface.RefCurrentFrameResources();
- surface.RefCurrentFrameResources();
-
- ResourceProvider::ResourceId second_frame_ids[] = {4, 5};
- SubmitFrameWithResources(
- second_frame_ids, arraysize(second_frame_ids), &surface);
-
- // Ref resources from the second frame 3 times.
- surface.RefCurrentFrameResources();
- surface.RefCurrentFrameResources();
- surface.RefCurrentFrameResources();
-
- // Submit a frame with no resources to remove all current frame refs from
- // submitted resources.
- SubmitFrameWithResources(NULL, 0, &surface);
-
- surface.ReturnUnusedResourcesToClient();
- EXPECT_EQ(0u, client.returned_resources().size());
- client.clear_returned_resources();
-
- // Expected current refs:
- // 3 -> 2
- // 4 -> 2 + 3 = 5
- // 5 -> 3
- {
- SCOPED_TRACE("unref all 3");
- ResourceProvider::ResourceId ids_to_unref[] = {3, 4, 5};
- int counts[] = {1, 1, 1};
- UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref), &surface);
-
- surface.ReturnUnusedResourcesToClient();
- EXPECT_EQ(0u, client.returned_resources().size());
- client.clear_returned_resources();
-
- UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref), &surface);
-
- surface.ReturnUnusedResourcesToClient();
- ResourceProvider::ResourceId expected_returned_ids[] = {3};
- int expected_returned_counts[] = {1};
- CheckReturnedResourcesMatchExpected(expected_returned_ids,
- expected_returned_counts,
- arraysize(expected_returned_counts),
- client.returned_resources());
- }
-
- // Expected refs remaining:
- // 4 -> 3
- // 5 -> 1
- {
- SCOPED_TRACE("unref 4 and 5");
- ResourceProvider::ResourceId ids_to_unref[] = {4, 5};
- int counts[] = {1, 1};
- UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref), &surface);
-
- surface.ReturnUnusedResourcesToClient();
- ResourceProvider::ResourceId expected_returned_ids[] = {5};
- int expected_returned_counts[] = {1};
- CheckReturnedResourcesMatchExpected(expected_returned_ids,
- expected_returned_counts,
- arraysize(expected_returned_counts),
- client.returned_resources());
- }
-
- // Now, just 2 refs remaining on resource 4. Unref both at once and make sure
- // the returned count is correct.
- {
- SCOPED_TRACE("unref only 4");
- ResourceProvider::ResourceId ids_to_unref[] = {4};
- int counts[] = {2};
- UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref), &surface);
-
- surface.ReturnUnusedResourcesToClient();
- ResourceProvider::ResourceId expected_returned_ids[] = {4};
- int expected_returned_counts[] = {2};
- CheckReturnedResourcesMatchExpected(expected_returned_ids,
- expected_returned_counts,
- arraysize(expected_returned_counts),
- client.returned_resources());
- }
-}
-
-TEST(SurfaceTest, ResourceLifetime) {
- SurfaceManager manager;
- TestSurfaceClient client;
- Surface surface(&manager, &client, gfx::Size(5, 5));
-
- ResourceProvider::ResourceId first_frame_ids[] = {1, 2, 3};
- SubmitFrameWithResources(
- first_frame_ids, arraysize(first_frame_ids), &surface);
-
- // All of the resources submitted in the first frame are still in use at this
- // time by virtue of being in the pending frame, so none can be returned to
- // the client yet.
- surface.ReturnUnusedResourcesToClient();
- EXPECT_EQ(0u, client.returned_resources().size());
- client.clear_returned_resources();
-
- // The second frame references some of the same resources, but some different
- // ones. We expect to receive back resource 1 with a count of 1 since it was
- // only referenced by the first frame.
- ResourceProvider::ResourceId second_frame_ids[] = {2, 3, 4};
- SubmitFrameWithResources(
- second_frame_ids, arraysize(second_frame_ids), &surface);
-
- surface.ReturnUnusedResourcesToClient();
- {
- SCOPED_TRACE("second frame");
- ResourceProvider::ResourceId expected_returned_ids[] = {1};
- int expected_returned_counts[] = {1};
- CheckReturnedResourcesMatchExpected(expected_returned_ids,
- expected_returned_counts,
- arraysize(expected_returned_counts),
- client.returned_resources());
- }
-
- // The third frame references a disjoint set of resources, so we expect to
- // receive back all resources from the first and second frames. Resource IDs 2
- // and 3 will have counts of 2, since they were used in both frames, and
- // resource ID 4 will have a count of 1.
- ResourceProvider::ResourceId third_frame_ids[] = {10, 11, 12, 13};
- SubmitFrameWithResources(
- third_frame_ids, arraysize(third_frame_ids), &surface);
-
- surface.ReturnUnusedResourcesToClient();
- {
- SCOPED_TRACE("third frame");
- ResourceProvider::ResourceId expected_returned_ids[] = {2, 3, 4};
- int expected_returned_counts[] = {2, 2, 1};
- CheckReturnedResourcesMatchExpected(expected_returned_ids,
- expected_returned_counts,
- arraysize(expected_returned_counts),
- client.returned_resources());
- }
-
- // Simulate a ResourceProvider taking a ref on all of the resources.
- surface.RefCurrentFrameResources();
-
- ResourceProvider::ResourceId fourth_frame_ids[] = {12, 13};
- SubmitFrameWithResources(
- fourth_frame_ids, arraysize(fourth_frame_ids), &surface);
-
- surface.ReturnUnusedResourcesToClient();
- EXPECT_EQ(0u, client.returned_resources().size());
-
- surface.RefCurrentFrameResources();
-
- // All resources are still being used by the external reference, so none can
- // be returned to the client.
- surface.ReturnUnusedResourcesToClient();
- EXPECT_EQ(0u, client.returned_resources().size());
-
- // Release resources associated with the first RefCurrentFrameResources() call
- // first.
- {
- ResourceProvider::ResourceId ids_to_unref[] = {10, 11, 12, 13};
- int counts[] = {1, 1, 1, 1};
- UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref), &surface);
- }
-
- surface.ReturnUnusedResourcesToClient();
- {
- SCOPED_TRACE("fourth frame, first unref");
- ResourceProvider::ResourceId expected_returned_ids[] = {10, 11};
- int expected_returned_counts[] = {1, 1};
- CheckReturnedResourcesMatchExpected(expected_returned_ids,
- expected_returned_counts,
- arraysize(expected_returned_counts),
- client.returned_resources());
- }
-
- {
- ResourceProvider::ResourceId ids_to_unref[] = {12, 13};
- int counts[] = {1, 1};
- UnrefResources(ids_to_unref, counts, arraysize(ids_to_unref), &surface);
- }
-
- // Resources 12 and 13 are still in use by the current frame, so they
- // shouldn't be available to be returned.
- surface.ReturnUnusedResourcesToClient();
- EXPECT_EQ(0u, client.returned_resources().size());
-
- // If we submit an empty frame, however, they should become available.
- SubmitFrameWithResources(NULL, 0u, &surface);
-
- surface.ReturnUnusedResourcesToClient();
- {
- SCOPED_TRACE("fourth frame, second unref");
- ResourceProvider::ResourceId expected_returned_ids[] = {12, 13};
- int expected_returned_counts[] = {2, 2};
- CheckReturnedResourcesMatchExpected(expected_returned_ids,
- expected_returned_counts,
- arraysize(expected_returned_counts),
- client.returned_resources());
- }
-}
-
} // namespace
} // namespace cc
diff --git a/cc/surfaces/surfaces_pixeltest.cc b/cc/surfaces/surfaces_pixeltest.cc
index 9afb4c6..6947abc 100644
--- a/cc/surfaces/surfaces_pixeltest.cc
+++ b/cc/surfaces/surfaces_pixeltest.cc
@@ -8,6 +8,8 @@
#include "cc/quads/surface_draw_quad.h"
#include "cc/surfaces/surface.h"
#include "cc/surfaces/surface_aggregator.h"
+#include "cc/surfaces/surface_factory.h"
+#include "cc/surfaces/surface_factory_client.h"
#include "cc/surfaces/surface_manager.h"
#include "cc/test/pixel_comparator.h"
#include "cc/test/pixel_test.h"
@@ -18,9 +20,20 @@
namespace cc {
namespace {
+class EmptySurfaceFactoryClient : public SurfaceFactoryClient {
+ public:
+ virtual void ReturnResources(
+ const ReturnedResourceArray& resources) OVERRIDE {}
+};
+
class SurfacesPixelTest : public RendererPixelTest<GLRenderer> {
+ public:
+ SurfacesPixelTest() : factory_(&manager_, &client_) {}
+
protected:
SurfaceManager manager_;
+ EmptySurfaceFactoryClient client_;
+ SurfaceFactory factory_;
};
SharedQuadState* CreateAndAppendTestSharedQuadState(
@@ -70,12 +83,13 @@ TEST_F(SurfacesPixelTest, DrawSimpleFrame) {
scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
root_frame->delegated_frame_data = delegated_frame_data.Pass();
- Surface root_surface(&manager_, NULL, device_viewport_size_);
- root_surface.QueueFrame(root_frame.Pass());
+ SurfaceId root_surface_id = factory_.Create(device_viewport_size_);
+ factory_.SubmitFrame(root_surface_id, root_frame.Pass());
- SurfaceAggregator aggregator(&manager_);
+ SurfaceAggregator aggregator(&manager_, resource_provider_.get());
scoped_ptr<CompositorFrame> aggregated_frame =
- aggregator.Aggregate(root_surface.surface_id());
+ aggregator.Aggregate(root_surface_id);
+ factory_.Destroy(root_surface_id);
bool discard_alpha = false;
ExactPixelComparator pixel_comparator(discard_alpha);
@@ -89,8 +103,8 @@ TEST_F(SurfacesPixelTest, DrawSimpleFrame) {
// Draws a frame with simple surface embedding.
TEST_F(SurfacesPixelTest, DrawSimpleAggregatedFrame) {
gfx::Size child_size(200, 100);
- Surface child_surface(&manager_, NULL, child_size);
- Surface root_surface(&manager_, NULL, device_viewport_size_);
+ SurfaceId child_surface_id = factory_.Create(child_size);
+ SurfaceId root_surface_id = factory_.Create(device_viewport_size_);
{
gfx::Rect rect(device_viewport_size_);
@@ -105,7 +119,7 @@ TEST_F(SurfacesPixelTest, DrawSimpleAggregatedFrame) {
surface_quad->SetNew(pass->shared_quad_state_list.back(),
gfx::Rect(child_size),
gfx::Rect(child_size),
- child_surface.surface_id());
+ child_surface_id);
pass->quad_list.push_back(surface_quad.PassAs<DrawQuad>());
scoped_ptr<SolidColorDrawQuad> color_quad = SolidColorDrawQuad::Create();
@@ -123,7 +137,7 @@ TEST_F(SurfacesPixelTest, DrawSimpleAggregatedFrame) {
scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
root_frame->delegated_frame_data = delegated_frame_data.Pass();
- root_surface.QueueFrame(root_frame.Pass());
+ factory_.SubmitFrame(root_surface_id, root_frame.Pass());
}
{
@@ -150,12 +164,12 @@ TEST_F(SurfacesPixelTest, DrawSimpleAggregatedFrame) {
scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
child_frame->delegated_frame_data = delegated_frame_data.Pass();
- child_surface.QueueFrame(child_frame.Pass());
+ factory_.SubmitFrame(child_surface_id, child_frame.Pass());
}
- SurfaceAggregator aggregator(&manager_);
+ SurfaceAggregator aggregator(&manager_, resource_provider_.get());
scoped_ptr<CompositorFrame> aggregated_frame =
- aggregator.Aggregate(root_surface.surface_id());
+ aggregator.Aggregate(root_surface_id);
bool discard_alpha = false;
ExactPixelComparator pixel_comparator(discard_alpha);
@@ -164,6 +178,8 @@ TEST_F(SurfacesPixelTest, DrawSimpleAggregatedFrame) {
EXPECT_TRUE(RunPixelTest(pass_list,
base::FilePath(FILE_PATH_LITERAL("blue_yellow.png")),
pixel_comparator));
+ factory_.Destroy(root_surface_id);
+ factory_.Destroy(child_surface_id);
}
// Tests a surface quad that has a non-identity transform into its pass.
@@ -177,9 +193,9 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
// bottom_blue_quad (100x100 @ 0x100)
// right_child -> top_blue_quad (100x100 @ 0x0),
// bottom_green_quad (100x100 @ 0x100)
- Surface left_child(&manager_, NULL, child_size);
- Surface right_child(&manager_, NULL, child_size);
- Surface root_surface(&manager_, NULL, device_viewport_size_);
+ SurfaceId left_child_id = factory_.Create(child_size);
+ SurfaceId right_child_id = factory_.Create(child_size);
+ SurfaceId root_surface_id = factory_.Create(device_viewport_size_);
{
gfx::Rect rect(device_viewport_size_);
@@ -195,7 +211,7 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
left_surface_quad->SetNew(pass->shared_quad_state_list.back(),
gfx::Rect(child_size),
gfx::Rect(child_size),
- left_child.surface_id());
+ left_child_id);
pass->quad_list.push_back(left_surface_quad.PassAs<DrawQuad>());
surface_transform.Translate(100, 0);
@@ -206,7 +222,7 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
right_surface_quad->SetNew(pass->shared_quad_state_list.back(),
gfx::Rect(child_size),
gfx::Rect(child_size),
- right_child.surface_id());
+ right_child_id);
pass->quad_list.push_back(right_surface_quad.PassAs<DrawQuad>());
scoped_ptr<DelegatedFrameData> delegated_frame_data(new DelegatedFrameData);
@@ -215,7 +231,7 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
scoped_ptr<CompositorFrame> root_frame(new CompositorFrame);
root_frame->delegated_frame_data = delegated_frame_data.Pass();
- root_surface.QueueFrame(root_frame.Pass());
+ factory_.SubmitFrame(root_surface_id, root_frame.Pass());
}
{
@@ -252,7 +268,7 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
child_frame->delegated_frame_data = delegated_frame_data.Pass();
- left_child.QueueFrame(child_frame.Pass());
+ factory_.SubmitFrame(left_child_id, child_frame.Pass());
}
{
@@ -289,12 +305,12 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
scoped_ptr<CompositorFrame> child_frame(new CompositorFrame);
child_frame->delegated_frame_data = delegated_frame_data.Pass();
- right_child.QueueFrame(child_frame.Pass());
+ factory_.SubmitFrame(right_child_id, child_frame.Pass());
}
- SurfaceAggregator aggregator(&manager_);
+ SurfaceAggregator aggregator(&manager_, resource_provider_.get());
scoped_ptr<CompositorFrame> aggregated_frame =
- aggregator.Aggregate(root_surface.surface_id());
+ aggregator.Aggregate(root_surface_id);
bool discard_alpha = false;
ExactPixelComparator pixel_comparator(discard_alpha);
@@ -304,6 +320,10 @@ TEST_F(SurfacesPixelTest, DrawAggregatedFrameWithSurfaceTransforms) {
pass_list,
base::FilePath(FILE_PATH_LITERAL("four_blue_green_checkers.png")),
pixel_comparator));
+
+ factory_.Destroy(root_surface_id);
+ factory_.Destroy(left_child_id);
+ factory_.Destroy(right_child_id);
}
} // namespace
diff --git a/content/browser/compositor/gpu_process_transport_factory.cc b/content/browser/compositor/gpu_process_transport_factory.cc
index bdf7cb4..b583393 100644
--- a/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/content/browser/compositor/gpu_process_transport_factory.cc
@@ -188,8 +188,9 @@ scoped_ptr<cc::OutputSurface> GpuProcessTransportFactory::CreateOutputSurface(
"Offscreen-Compositor");
}
scoped_ptr<SurfaceDisplayOutputSurface> output_surface(
- new SurfaceDisplayOutputSurface(
- display_client->display(), manager, offscreen_context_provider));
+ new SurfaceDisplayOutputSurface(manager, offscreen_context_provider));
+ display_client->CreateDisplay(output_surface->factory());
+ output_surface->set_display(display_client->display());
data->display_client = display_client.Pass();
return output_surface.PassAs<cc::OutputSurface>();
}
diff --git a/content/browser/compositor/onscreen_display_client.cc b/content/browser/compositor/onscreen_display_client.cc
index 814f0fc..3138f9d 100644
--- a/content/browser/compositor/onscreen_display_client.cc
+++ b/content/browser/compositor/onscreen_display_client.cc
@@ -5,6 +5,8 @@
#include "content/browser/compositor/onscreen_display_client.h"
#include "cc/output/output_surface.h"
+#include "cc/surfaces/surface_factory.h"
+#include "cc/surfaces/surface_manager.h"
#include "content/common/host_shared_bitmap_manager.h"
namespace content {
@@ -13,14 +15,19 @@ OnscreenDisplayClient::OnscreenDisplayClient(
const scoped_refptr<cc::ContextProvider>& onscreen_context_provider,
scoped_ptr<cc::OutputSurface> software_surface,
cc::SurfaceManager* manager)
- : onscreen_context_provider_(onscreen_context_provider),
- software_surface_(software_surface.Pass()),
- display_(this, manager, HostSharedBitmapManager::current()) {
+ : manager_(manager),
+ onscreen_context_provider_(onscreen_context_provider),
+ software_surface_(software_surface.Pass()) {
}
OnscreenDisplayClient::~OnscreenDisplayClient() {
}
+void OnscreenDisplayClient::CreateDisplay(cc::SurfaceFactory* factory) {
+ display_.reset(new cc::Display(
+ this, manager_, factory, HostSharedBitmapManager::current()));
+}
+
scoped_ptr<cc::OutputSurface> OnscreenDisplayClient::CreateOutputSurface() {
if (!onscreen_context_provider_)
return software_surface_.Pass();
diff --git a/content/browser/compositor/onscreen_display_client.h b/content/browser/compositor/onscreen_display_client.h
index 7ab6ff7..b518cc9 100644
--- a/content/browser/compositor/onscreen_display_client.h
+++ b/content/browser/compositor/onscreen_display_client.h
@@ -28,15 +28,18 @@ class OnscreenDisplayClient : cc::DisplayClient {
cc::SurfaceManager* manager);
virtual ~OnscreenDisplayClient();
- cc::Display* display() { return &display_; }
+ void CreateDisplay(cc::SurfaceFactory* factory);
+
+ cc::Display* display() { return display_.get(); }
// cc::DisplayClient implementation.
virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface() OVERRIDE;
private:
+ cc::SurfaceManager* manager_;
scoped_refptr<cc::ContextProvider> onscreen_context_provider_;
scoped_ptr<cc::OutputSurface> software_surface_;
- cc::Display display_;
+ scoped_ptr<cc::Display> display_;
DISALLOW_COPY_AND_ASSIGN(OnscreenDisplayClient);
};
diff --git a/content/browser/compositor/surface_display_output_surface.cc b/content/browser/compositor/surface_display_output_surface.cc
index 46c4ad7..91dc0ab4 100644
--- a/content/browser/compositor/surface_display_output_surface.cc
+++ b/content/browser/compositor/surface_display_output_surface.cc
@@ -5,6 +5,7 @@
#include "content/browser/compositor/surface_display_output_surface.h"
#include "cc/output/compositor_frame.h"
+#include "cc/output/compositor_frame_ack.h"
#include "cc/surfaces/display.h"
#include "cc/surfaces/surface.h"
#include "cc/surfaces/surface_manager.h"
@@ -12,13 +13,13 @@
namespace content {
SurfaceDisplayOutputSurface::SurfaceDisplayOutputSurface(
- cc::Display* display,
cc::SurfaceManager* surface_manager,
const scoped_refptr<cc::ContextProvider>& context_provider)
: cc::OutputSurface(context_provider,
scoped_ptr<cc::SoftwareOutputDevice>()),
- display_(display),
- surface_manager_(surface_manager) {
+ display_(NULL),
+ surface_manager_(surface_manager),
+ factory_(surface_manager, this) {
capabilities_.delegated_rendering = true;
capabilities_.max_frames_pending = 1;
}
@@ -31,13 +32,12 @@ void SurfaceDisplayOutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
frame->delegated_frame_data->render_pass_list.back()->output_rect.size();
display_->Resize(frame_size);
cc::SurfaceId surface_id = display_->CurrentSurfaceId();
- cc::Surface* surface = surface_manager_->GetSurfaceForId(surface_id);
- if (!surface)
+ if (surface_id.is_null())
return;
scoped_ptr<cc::CompositorFrame> frame_copy(new cc::CompositorFrame());
frame->AssignTo(frame_copy.get());
- surface->QueueFrame(frame_copy.Pass());
+ factory_.SubmitFrame(surface_id, frame_copy.Pass());
if (!display_->Draw())
return;
@@ -46,4 +46,11 @@ void SurfaceDisplayOutputSurface::SwapBuffers(cc::CompositorFrame* frame) {
client_->DidSwapBuffersComplete();
}
+void SurfaceDisplayOutputSurface::ReturnResources(
+ const cc::ReturnedResourceArray& resources) {
+ cc::CompositorFrameAck ack;
+ ack.resources = resources;
+ client_->ReclaimResources(&ack);
+}
+
} // namespace content
diff --git a/content/browser/compositor/surface_display_output_surface.h b/content/browser/compositor/surface_display_output_surface.h
index 185e0ff..e8b126c 100644
--- a/content/browser/compositor/surface_display_output_surface.h
+++ b/content/browser/compositor/surface_display_output_surface.h
@@ -6,6 +6,8 @@
#define CONTENT_BROWSER_COMPOSITOR_SURFACE_DISPLAY_OUTPUT_SURFACE_H_
#include "cc/output/output_surface.h"
+#include "cc/surfaces/surface_factory.h"
+#include "cc/surfaces/surface_factory_client.h"
namespace cc {
class Display;
@@ -17,21 +19,29 @@ namespace content {
// This class is maps a compositor OutputSurface to the surface system's Display
// concept, allowing a compositor client to submit frames for a native root
// window or physical display.
-class SurfaceDisplayOutputSurface : public cc::OutputSurface {
+class SurfaceDisplayOutputSurface : public cc::OutputSurface,
+ public cc::SurfaceFactoryClient {
public:
// The underlying cc::Display and cc::SurfaceManager must outlive this class.
SurfaceDisplayOutputSurface(
- cc::Display* display,
cc::SurfaceManager* surface_manager,
const scoped_refptr<cc::ContextProvider>& context_provider);
virtual ~SurfaceDisplayOutputSurface();
+ void set_display(cc::Display* display) { display_ = display; }
+ cc::SurfaceFactory* factory() { return &factory_; }
+
// cc::OutputSurface implementation.
virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE;
+ // cc::SurfaceFactoryClient implementation.
+ virtual void ReturnResources(
+ const cc::ReturnedResourceArray& resources) OVERRIDE;
+
private:
cc::Display* display_;
cc::SurfaceManager* surface_manager_;
+ cc::SurfaceFactory factory_;
DISALLOW_COPY_AND_ASSIGN(SurfaceDisplayOutputSurface);
};