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

Unified Diff: cc/resources/resource_provider.cc

Issue 24078024: cc: Return resources to child compositor via a Callback. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: deletechild: No AndReceiveAck needed, change STP Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cc/resources/resource_provider.h ('k') | cc/resources/resource_provider_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/resources/resource_provider.cc
diff --git a/cc/resources/resource_provider.cc b/cc/resources/resource_provider.cc
index e1cbba56053bdb6b3ddfd43bad47cbebda23d31e..6ee8be02c9972e0904319f64170c897eee43a22a 100644
--- a/cc/resources/resource_provider.cc
+++ b/cc/resources/resource_provider.cc
@@ -86,7 +86,8 @@ class ScopedSetActiveTexture {
} // namespace
ResourceProvider::Resource::Resource()
- : gl_id(0),
+ : child_id(0),
+ gl_id(0),
gl_pixel_buffer_id(0),
gl_upload_query_id(0),
pixels(NULL),
@@ -115,15 +116,15 @@ ResourceProvider::Resource::Resource()
ResourceProvider::Resource::~Resource() {}
-ResourceProvider::Resource::Resource(
- unsigned texture_id,
- gfx::Size size,
- GLenum filter,
- GLenum texture_pool,
- GLint wrap_mode,
- TextureUsageHint hint,
- ResourceFormat format)
- : gl_id(texture_id),
+ResourceProvider::Resource::Resource(unsigned texture_id,
+ gfx::Size size,
+ GLenum filter,
+ GLenum texture_pool,
+ GLint wrap_mode,
+ TextureUsageHint hint,
+ ResourceFormat format)
+ : child_id(0),
+ gl_id(texture_id),
gl_pixel_buffer_id(0),
gl_upload_query_id(0),
pixels(NULL),
@@ -152,12 +153,12 @@ ResourceProvider::Resource::Resource(
DCHECK(wrap_mode == GL_CLAMP_TO_EDGE || wrap_mode == GL_REPEAT);
}
-ResourceProvider::Resource::Resource(
- uint8_t* pixels,
- gfx::Size size,
- GLenum filter,
- GLint wrap_mode)
- : gl_id(0),
+ResourceProvider::Resource::Resource(uint8_t* pixels,
+ gfx::Size size,
+ GLenum filter,
+ GLint wrap_mode)
+ : child_id(0),
+ gl_id(0),
gl_pixel_buffer_id(0),
gl_upload_query_id(0),
pixels(pixels),
@@ -215,6 +216,8 @@ scoped_ptr<ResourceProvider> ResourceProvider::Create(
}
ResourceProvider::~ResourceProvider() {
+ while (!children_.empty())
+ DestroyChild(children_.begin()->first);
while (!resources_.empty())
DeleteResourceInternal(resources_.begin(), ForShutdown);
@@ -810,9 +813,12 @@ void ResourceProvider::CleanUpGLIfNeeded() {
Finish();
}
-int ResourceProvider::CreateChild() {
+int ResourceProvider::CreateChild(const ReturnCallback& return_callback) {
DCHECK(thread_checker_.CalledOnValidThread());
+
Child child_info;
+ child_info.return_callback = return_callback;
+
int child = next_child_++;
children_[child] = child_info;
return child;
@@ -820,20 +826,26 @@ int ResourceProvider::CreateChild() {
void ResourceProvider::DestroyChild(int child_id) {
DCHECK(thread_checker_.CalledOnValidThread());
+
ChildMap::iterator it = children_.find(child_id);
DCHECK(it != children_.end());
Child& child = it->second;
+
+ ResourceIdArray resources_for_child;
+
for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin();
child_it != child.child_to_parent_map.end();
++child_it) {
ResourceId id = child_it->second;
- // We're abandoning this resource, it will not get recycled.
- // crbug.com/224062
- ResourceMap::iterator resource_it = resources_.find(id);
- CHECK(resource_it != resources_.end());
- resource_it->second.imported_count = 0;
- DeleteResource(id);
+ resources_for_child.push_back(id);
}
+
+ // If the child is going away, don't consider any resources in use.
+ child.in_use_resources.clear();
+
+ DeleteAndReturnUnusedResourcesToChild(
+ &child, ForShutdown, resources_for_child);
+
children_.erase(it);
}
@@ -875,62 +887,6 @@ void ResourceProvider::PrepareSendToParent(const ResourceIdArray& resources,
}
}
-void ResourceProvider::PrepareSendReturnsToChild(
- int child,
- const ResourceIdArray& resources,
- ReturnedResourceArray* list) {
- DCHECK(thread_checker_.CalledOnValidThread());
- WebGraphicsContext3D* context3d = Context3d();
- if (!context3d || !context3d->makeContextCurrent()) {
- // TODO(skaslev): Implement this path for software compositing.
- return;
- }
- Child& child_info = children_.find(child)->second;
- bool need_sync_point = false;
- for (ResourceIdArray::const_iterator it = resources.begin();
- it != resources.end(); ++it) {
- Resource* resource = GetResource(*it);
- DCHECK(!resource->locked_for_write);
- DCHECK(!resource->lock_for_read_count);
- DCHECK(child_info.parent_to_child_map.find(*it) !=
- child_info.parent_to_child_map.end());
-
- if (resource->filter != resource->original_filter) {
- DCHECK(resource->target);
- DCHECK(resource->gl_id);
-
- GLC(context3d, context3d->bindTexture(resource->target, resource->gl_id));
- GLC(context3d, context3d->texParameteri(resource->target,
- GL_TEXTURE_MIN_FILTER,
- resource->original_filter));
- GLC(context3d, context3d->texParameteri(resource->target,
- GL_TEXTURE_MAG_FILTER,
- resource->original_filter));
- }
-
- ReturnedResource returned;
- returned.id = child_info.parent_to_child_map[*it];
- returned.sync_point = resource->mailbox.sync_point();
- if (!returned.sync_point)
- need_sync_point = true;
- returned.count = resource->imported_count;
- list->push_back(returned);
-
- child_info.parent_to_child_map.erase(*it);
- child_info.child_to_parent_map.erase(returned.id);
- resources_[*it].imported_count = 0;
- DeleteResource(*it);
- }
- if (need_sync_point) {
- unsigned int sync_point = context3d->insertSyncPoint();
- for (ReturnedResourceArray::iterator it = list->begin();
- it != list->end(); ++it) {
- if (!it->sync_point)
- it->sync_point = sync_point;
- }
- }
-}
-
void ResourceProvider::ReceiveFromChild(
int child, const TransferableResourceArray& resources) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -962,26 +918,65 @@ void ResourceProvider::ReceiveFromChild(
GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, texture_id));
GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D,
it->mailbox.name));
-
- ResourceId id = next_id_++;
- Resource resource(
- texture_id,
- it->size,
- it->filter,
- 0,
- GL_CLAMP_TO_EDGE,
- TextureUsageAny,
- it->format);
+ ResourceId local_id = next_id_++;
+ Resource resource(texture_id,
+ it->size,
+ it->filter,
+ 0,
+ GL_CLAMP_TO_EDGE,
+ TextureUsageAny,
+ it->format);
resource.mailbox.SetName(it->mailbox);
+ resource.child_id = child;
// Don't allocate a texture for a child.
resource.allocated = true;
resource.imported_count = 1;
- resources_[id] = resource;
- child_info.parent_to_child_map[id] = it->id;
- child_info.child_to_parent_map[it->id] = id;
+ resources_[local_id] = resource;
+ child_info.parent_to_child_map[local_id] = it->id;
+ child_info.child_to_parent_map[it->id] = local_id;
}
}
+void ResourceProvider::DeclareUsedResourcesFromChild(
+ int child,
+ const ResourceIdArray& resources_from_child) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ Child& child_info = children_.find(child)->second;
+ child_info.in_use_resources.clear();
+
+ for (size_t i = 0; i < resources_from_child.size(); ++i) {
+ ResourceIdMap::iterator it =
+ child_info.child_to_parent_map.find(resources_from_child[i]);
+ DCHECK(it != child_info.child_to_parent_map.end());
+
+ ResourceId local_id = it->second;
+ child_info.in_use_resources.insert(local_id);
+ }
+
+ ResourceIdArray unused;
+ for (ResourceIdMap::iterator it = child_info.child_to_parent_map.begin();
+ it != child_info.child_to_parent_map.end();
+ ++it) {
+ ResourceId local_id = it->second;
+ bool resource_is_in_use = child_info.in_use_resources.count(local_id) > 0;
+ if (!resource_is_in_use)
+ unused.push_back(local_id);
+ }
+ DeleteAndReturnUnusedResourcesToChild(&child_info, Normal, unused);
+}
+
+// static
+bool ResourceProvider::CompareResourceMapIteratorsByChildId(
+ const std::pair<ReturnedResource, ResourceMap::iterator>& a,
+ const std::pair<ReturnedResource, ResourceMap::iterator>& b) {
+ const ResourceMap::iterator& a_it = a.second;
+ const ResourceMap::iterator& b_it = b.second;
+ const Resource& a_resource = a_it->second;
+ const Resource& b_resource = b_it->second;
+ return a_resource.child_id < b_resource.child_id;
+}
+
void ResourceProvider::ReceiveReturnsFromParent(
const ReturnedResourceArray& resources) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -990,25 +985,83 @@ void ResourceProvider::ReceiveReturnsFromParent(
// TODO(skaslev): Implement this path for software compositing.
return;
}
+
+ int child_id = 0;
+ Child* child_info = NULL;
+ ResourceIdArray resources_for_child;
+
+ std::vector<std::pair<ReturnedResource, ResourceMap::iterator> >
+ sorted_resources;
+
for (ReturnedResourceArray::const_iterator it = resources.begin();
it != resources.end();
++it) {
- ResourceMap::iterator map_iterator = resources_.find(it->id);
- DCHECK(map_iterator != resources_.end());
+ ResourceId local_id = it->id;
+ ResourceMap::iterator map_iterator = resources_.find(local_id);
+
+ // Resource was already lost (e.g. it belonged to a child that was
+ // destroyed).
+ if (map_iterator == resources_.end())
+ continue;
+
+ sorted_resources.push_back(
+ std::pair<ReturnedResource, ResourceMap::iterator>(*it, map_iterator));
+ }
+
+ std::sort(sorted_resources.begin(),
+ sorted_resources.end(),
+ CompareResourceMapIteratorsByChildId);
+
+ for (size_t i = 0; i < sorted_resources.size(); ++i) {
+ ReturnedResource& returned = sorted_resources[i].first;
+ ResourceMap::iterator& map_iterator = sorted_resources[i].second;
+ ResourceId local_id = map_iterator->first;
Resource* resource = &map_iterator->second;
- CHECK_GE(resource->exported_count, it->count);
- resource->exported_count -= it->count;
+
+ CHECK_GE(resource->exported_count, returned.count);
+ resource->exported_count -= returned.count;
if (resource->exported_count)
continue;
+
if (resource->gl_id) {
- if (it->sync_point)
- GLC(context3d, context3d->waitSyncPoint(it->sync_point));
+ if (returned.sync_point)
+ GLC(context3d, context3d->waitSyncPoint(returned.sync_point));
} else {
resource->mailbox =
- TextureMailbox(resource->mailbox.name(), it->sync_point);
+ TextureMailbox(resource->mailbox.name(), returned.sync_point);
}
- if (resource->marked_for_deletion)
+
+ if (!resource->marked_for_deletion)
+ continue;
+
+ if (!resource->child_id) {
+ // The resource belongs to this ResourceProvider, so it can be destroyed.
DeleteResourceInternal(map_iterator, Normal);
+ continue;
+ }
+
+ // Delete the resource and return it to the child it came from one.
+ if (resource->child_id != child_id) {
+ ChildMap::iterator child_it = children_.find(resource->child_id);
+ DCHECK(child_it != children_.end());
+
+ if (child_id) {
+ DCHECK_NE(resources_for_child.size(), 0u);
+ DeleteAndReturnUnusedResourcesToChild(
+ child_info, Normal, resources_for_child);
+ resources_for_child.clear();
+ }
+
+ child_info = &child_it->second;
+ child_id = resource->child_id;
+ }
+ resources_for_child.push_back(local_id);
+ }
+
+ if (child_id) {
+ DCHECK_NE(resources_for_child.size(), 0u);
+ DeleteAndReturnUnusedResourcesToChild(
+ child_info, Normal, resources_for_child);
}
}
@@ -1046,6 +1099,93 @@ void ResourceProvider::TransferResource(WebGraphicsContext3D* context,
}
}
+void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
+ Child* child_info,
+ DeleteStyle style,
+ const ResourceIdArray& unused) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(child_info);
+
+ if (unused.empty())
+ return;
+
+ WebGraphicsContext3D* context3d = Context3d();
+ if (!context3d || !context3d->makeContextCurrent()) {
+ // TODO(skaslev): Implement this path for software compositing.
+ return;
+ }
+
+ ReturnedResourceArray to_return;
+
+ bool need_sync_point = false;
+ for (size_t i = 0; i < unused.size(); ++i) {
+ ResourceId local_id = unused[i];
+
+ ResourceMap::iterator it = resources_.find(local_id);
+ CHECK(it != resources_.end());
+ Resource& resource = it->second;
+
+ DCHECK(!resource.locked_for_write);
+ DCHECK(!resource.lock_for_read_count);
+ DCHECK_EQ(0u, child_info->in_use_resources.count(local_id));
+ DCHECK(child_info->parent_to_child_map.count(local_id));
+
+ ResourceId child_id = child_info->parent_to_child_map[local_id];
+ DCHECK(child_info->child_to_parent_map.count(child_id));
+
+ // TODO(danakj): bool is_lost = false;
+ if (resource.exported_count > 0) {
+ if (style != ForShutdown) {
+ // Defer this until we receive the resource back from the parent.
+ resource.marked_for_deletion = true;
+ continue;
+ }
+
+ // We still have an exported_count, so we'll have to lose it.
+ // TODO(danakj): is_lost = true;
+ }
+
+ if (resource.filter != resource.original_filter) {
+ DCHECK(resource.target);
+ DCHECK(resource.gl_id);
+
+ GLC(context3d, context3d->bindTexture(resource.target, resource.gl_id));
+ GLC(context3d,
+ context3d->texParameteri(resource.target,
+ GL_TEXTURE_MIN_FILTER,
+ resource.original_filter));
+ GLC(context3d,
+ context3d->texParameteri(resource.target,
+ GL_TEXTURE_MAG_FILTER,
+ resource.original_filter));
+ }
+
+ ReturnedResource returned;
+ returned.id = child_id;
+ returned.sync_point = resource.mailbox.sync_point();
+ if (!returned.sync_point)
+ need_sync_point = true;
+ returned.count = resource.imported_count;
+ // TODO(danakj): Save the |is_lost| bit.
+ to_return.push_back(returned);
+
+ child_info->parent_to_child_map.erase(local_id);
+ child_info->child_to_parent_map.erase(child_id);
+ resource.imported_count = 0;
+ DeleteResourceInternal(it, style);
+ }
+ if (need_sync_point) {
+ unsigned int sync_point = context3d->insertSyncPoint();
+ for (size_t i = 0; i < to_return.size(); ++i) {
+ if (!to_return[i].sync_point)
+ to_return[i].sync_point = sync_point;
+ }
+ }
+
+ if (!to_return.empty())
+ child_info->return_callback.Run(to_return);
+}
+
void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
Resource* resource = GetResource(id);
DCHECK(!resource->external);
« no previous file with comments | « cc/resources/resource_provider.h ('k') | cc/resources/resource_provider_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698