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

Side by Side 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: 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/resources/resource_provider.h" 5 #include "cc/resources/resource_provider.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 9
10 #include "base/containers/hash_tables.h" 10 #include "base/containers/hash_tables.h"
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 } 198 }
199 199
200 if (!success) 200 if (!success)
201 return scoped_ptr<ResourceProvider>(); 201 return scoped_ptr<ResourceProvider>();
202 202
203 DCHECK_NE(InvalidType, resource_provider->default_resource_type()); 203 DCHECK_NE(InvalidType, resource_provider->default_resource_type());
204 return resource_provider.Pass(); 204 return resource_provider.Pass();
205 } 205 }
206 206
207 ResourceProvider::~ResourceProvider() { 207 ResourceProvider::~ResourceProvider() {
208 while (!children_.empty())
209 DestroyChild(children_.begin()->first);
208 while (!resources_.empty()) 210 while (!resources_.empty())
209 DeleteResourceInternal(resources_.begin(), ForShutdown); 211 DeleteResourceInternal(resources_.begin(), ForShutdown);
210 212
211 CleanUpGLIfNeeded(); 213 CleanUpGLIfNeeded();
212 } 214 }
213 215
214 bool ResourceProvider::InUseByConsumer(ResourceId id) { 216 bool ResourceProvider::InUseByConsumer(ResourceId id) {
215 Resource* resource = GetResource(id); 217 Resource* resource = GetResource(id);
216 return resource->lock_for_read_count > 0 || resource->exported_count > 0; 218 return resource->lock_for_read_count > 0 || resource->exported_count > 0;
217 } 219 }
(...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after
772 DCHECK(!texture_uploader_); 774 DCHECK(!texture_uploader_);
773 return; 775 return;
774 } 776 }
775 777
776 DCHECK(context3d); 778 DCHECK(context3d);
777 context3d->makeContextCurrent(); 779 context3d->makeContextCurrent();
778 texture_uploader_.reset(); 780 texture_uploader_.reset();
779 Finish(); 781 Finish();
780 } 782 }
781 783
782 int ResourceProvider::CreateChild() { 784 int ResourceProvider::CreateChild(const ReturnCallback& return_callback) {
783 DCHECK(thread_checker_.CalledOnValidThread()); 785 DCHECK(thread_checker_.CalledOnValidThread());
786
784 Child child_info; 787 Child child_info;
788 child_info.return_callback = return_callback;
789
785 int child = next_child_++; 790 int child = next_child_++;
786 children_[child] = child_info; 791 children_[child] = child_info;
787 return child; 792 return child;
788 } 793 }
789 794
790 void ResourceProvider::DestroyChild(int child_id) { 795 void ResourceProvider::DestroyChild(int child_id) {
791 DCHECK(thread_checker_.CalledOnValidThread()); 796 DCHECK(thread_checker_.CalledOnValidThread());
797
792 ChildMap::iterator it = children_.find(child_id); 798 ChildMap::iterator it = children_.find(child_id);
793 DCHECK(it != children_.end()); 799 DCHECK(it != children_.end());
794 Child& child = it->second; 800 Child& child = it->second;
801
802 ResourceIdArray resources_for_child;
803
795 for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin(); 804 for (ResourceIdMap::iterator child_it = child.child_to_parent_map.begin();
796 child_it != child.child_to_parent_map.end(); 805 child_it != child.child_to_parent_map.end();
797 ++child_it) { 806 ++child_it) {
798 ResourceId id = child_it->second; 807 ResourceId id = child_it->second;
799 // We're abandoning this resource, it will not get recycled. 808 resources_for_child.push_back(id);
800 // crbug.com/224062
801 ResourceMap::iterator resource_it = resources_.find(id);
802 CHECK(resource_it != resources_.end());
803 resource_it->second.imported_count = 0;
804 DeleteResource(id);
805 } 809 }
810
811 // If the child is going away, don't consider any resources in use.
812 child.in_use_resources.clear();
813
814 DeleteAndReturnUnusedResourcesToChild(
815 &child, ForShutdown, resources_for_child);
816
806 children_.erase(it); 817 children_.erase(it);
807 } 818 }
808 819
809 const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap( 820 const ResourceProvider::ResourceIdMap& ResourceProvider::GetChildToParentMap(
810 int child) const { 821 int child) const {
811 DCHECK(thread_checker_.CalledOnValidThread()); 822 DCHECK(thread_checker_.CalledOnValidThread());
812 ChildMap::const_iterator it = children_.find(child); 823 ChildMap::const_iterator it = children_.find(child);
813 DCHECK(it != children_.end()); 824 DCHECK(it != children_.end());
814 return it->second.child_to_parent_map; 825 return it->second.child_to_parent_map;
815 } 826 }
(...skipping 21 matching lines...) Expand all
837 unsigned int sync_point = context3d->insertSyncPoint(); 848 unsigned int sync_point = context3d->insertSyncPoint();
838 for (TransferableResourceArray::iterator it = list->begin(); 849 for (TransferableResourceArray::iterator it = list->begin();
839 it != list->end(); 850 it != list->end();
840 ++it) { 851 ++it) {
841 if (!it->sync_point) 852 if (!it->sync_point)
842 it->sync_point = sync_point; 853 it->sync_point = sync_point;
843 } 854 }
844 } 855 }
845 } 856 }
846 857
847 void ResourceProvider::PrepareSendReturnsToChild(
848 int child,
849 const ResourceIdArray& resources,
850 ReturnedResourceArray* list) {
851 DCHECK(thread_checker_.CalledOnValidThread());
852 WebGraphicsContext3D* context3d = Context3d();
853 if (!context3d || !context3d->makeContextCurrent()) {
854 // TODO(skaslev): Implement this path for software compositing.
855 return;
856 }
857 Child& child_info = children_.find(child)->second;
858 bool need_sync_point = false;
859 for (ResourceIdArray::const_iterator it = resources.begin();
860 it != resources.end(); ++it) {
861 Resource* resource = GetResource(*it);
862 DCHECK(!resource->locked_for_write);
863 DCHECK(!resource->lock_for_read_count);
864 DCHECK(child_info.parent_to_child_map.find(*it) !=
865 child_info.parent_to_child_map.end());
866
867 if (resource->filter != resource->original_filter) {
868 DCHECK(resource->target);
869 DCHECK(resource->gl_id);
870
871 GLC(context3d, context3d->bindTexture(resource->target, resource->gl_id));
872 GLC(context3d, context3d->texParameteri(resource->target,
873 GL_TEXTURE_MIN_FILTER,
874 resource->original_filter));
875 GLC(context3d, context3d->texParameteri(resource->target,
876 GL_TEXTURE_MAG_FILTER,
877 resource->original_filter));
878 }
879
880 ReturnedResource returned;
881 returned.id = child_info.parent_to_child_map[*it];
882 returned.sync_point = resource->mailbox.sync_point();
883 if (!returned.sync_point)
884 need_sync_point = true;
885 returned.count = resource->imported_count;
886 list->push_back(returned);
887
888 child_info.parent_to_child_map.erase(*it);
889 child_info.child_to_parent_map.erase(returned.id);
890 resources_[*it].imported_count = 0;
891 DeleteResource(*it);
892 }
893 if (need_sync_point) {
894 unsigned int sync_point = context3d->insertSyncPoint();
895 for (ReturnedResourceArray::iterator it = list->begin();
896 it != list->end(); ++it) {
897 if (!it->sync_point)
898 it->sync_point = sync_point;
899 }
900 }
901 }
902
903 void ResourceProvider::ReceiveFromChild( 858 void ResourceProvider::ReceiveFromChild(
904 int child, const TransferableResourceArray& resources) { 859 int child, const TransferableResourceArray& resources) {
905 DCHECK(thread_checker_.CalledOnValidThread()); 860 DCHECK(thread_checker_.CalledOnValidThread());
906 WebGraphicsContext3D* context3d = Context3d(); 861 WebGraphicsContext3D* context3d = Context3d();
907 if (!context3d || !context3d->makeContextCurrent()) { 862 if (!context3d || !context3d->makeContextCurrent()) {
908 // TODO(skaslev): Implement this path for software compositing. 863 // TODO(skaslev): Implement this path for software compositing.
909 return; 864 return;
910 } 865 }
911 Child& child_info = children_.find(child)->second; 866 Child& child_info = children_.find(child)->second;
912 for (TransferableResourceArray::const_iterator it = resources.begin(); 867 for (TransferableResourceArray::const_iterator it = resources.begin();
(...skipping 11 matching lines...) Expand all
924 // deadlocks and/or security issues. The caller is responsible for 879 // deadlocks and/or security issues. The caller is responsible for
925 // waiting asynchronously, and resetting sync_point before calling this. 880 // waiting asynchronously, and resetting sync_point before calling this.
926 // However if the parent is a renderer (e.g. browser tag), it may be ok 881 // However if the parent is a renderer (e.g. browser tag), it may be ok
927 // (and is simpler) to wait. 882 // (and is simpler) to wait.
928 if (it->sync_point) 883 if (it->sync_point)
929 GLC(context3d, context3d->waitSyncPoint(it->sync_point)); 884 GLC(context3d, context3d->waitSyncPoint(it->sync_point));
930 GLC(context3d, texture_id = context3d->createTexture()); 885 GLC(context3d, texture_id = context3d->createTexture());
931 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, texture_id)); 886 GLC(context3d, context3d->bindTexture(GL_TEXTURE_2D, texture_id));
932 GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D, 887 GLC(context3d, context3d->consumeTextureCHROMIUM(GL_TEXTURE_2D,
933 it->mailbox.name)); 888 it->mailbox.name));
934 ResourceId id = next_id_++; 889 ResourceId local_id = next_id_++;
935 Resource resource( 890 Resource resource(texture_id,
936 texture_id, it->size, it->format, it->filter, 0, GL_CLAMP_TO_EDGE, 891 it->size,
937 TextureUsageAny); 892 it->format,
893 it->filter,
894 0,
895 GL_CLAMP_TO_EDGE,
896 TextureUsageAny);
938 resource.mailbox.SetName(it->mailbox); 897 resource.mailbox.SetName(it->mailbox);
898 resource.child_id = child;
939 // Don't allocate a texture for a child. 899 // Don't allocate a texture for a child.
940 resource.allocated = true; 900 resource.allocated = true;
941 resource.imported_count = 1; 901 resource.imported_count = 1;
942 resources_[id] = resource; 902 resources_[local_id] = resource;
943 child_info.parent_to_child_map[id] = it->id; 903 child_info.parent_to_child_map[local_id] = it->id;
944 child_info.child_to_parent_map[it->id] = id; 904 child_info.child_to_parent_map[it->id] = local_id;
945 } 905 }
946 } 906 }
947 907
908 void ResourceProvider::DeclareUsedResourcesFromChild(
909 int child,
910 const ResourceIdArray& resources_from_child) {
911 DCHECK(thread_checker_.CalledOnValidThread());
912
913 Child& child_info = children_.find(child)->second;
914 child_info.in_use_resources.clear();
915
916 for (size_t i = 0; i < resources_from_child.size(); ++i) {
917 ResourceIdMap::iterator it =
918 child_info.child_to_parent_map.find(resources_from_child[i]);
919 DCHECK(it != child_info.child_to_parent_map.end());
920
921 ResourceId local_id = it->second;
922 child_info.in_use_resources.insert(local_id);
923 }
924
925 ResourceIdArray unused;
926 for (ResourceIdMap::iterator it = child_info.child_to_parent_map.begin();
927 it != child_info.child_to_parent_map.end();
928 ++it) {
929 ResourceId local_id = it->second;
930 bool resource_is_in_use = child_info.in_use_resources.count(local_id);
931 if (!resource_is_in_use)
932 unused.push_back(local_id);
933 }
934 DeleteAndReturnUnusedResourcesToChild(&child_info, Normal, unused);
935 }
936
948 void ResourceProvider::ReceiveReturnsFromParent( 937 void ResourceProvider::ReceiveReturnsFromParent(
949 const ReturnedResourceArray& resources) { 938 const ReturnedResourceArray& resources) {
950 DCHECK(thread_checker_.CalledOnValidThread()); 939 DCHECK(thread_checker_.CalledOnValidThread());
951 WebGraphicsContext3D* context3d = Context3d(); 940 WebGraphicsContext3D* context3d = Context3d();
952 if (!context3d || !context3d->makeContextCurrent()) { 941 if (!context3d || !context3d->makeContextCurrent()) {
953 // TODO(skaslev): Implement this path for software compositing. 942 // TODO(skaslev): Implement this path for software compositing.
954 return; 943 return;
955 } 944 }
945
946 int child_id = 0;
947 Child* child_info = NULL;
948 ResourceIdArray resources_for_child;
949
956 for (ReturnedResourceArray::const_iterator it = resources.begin(); 950 for (ReturnedResourceArray::const_iterator it = resources.begin();
957 it != resources.end(); 951 it != resources.end();
958 ++it) { 952 ++it) {
959 ResourceMap::iterator map_iterator = resources_.find(it->id); 953 ResourceId local_id = it->id;
960 DCHECK(map_iterator != resources_.end()); 954 ResourceMap::iterator map_iterator = resources_.find(local_id);
955
956 // Resource was already lost (e.g. it belonged to a child that was
957 // destroyed).
958 if (map_iterator == resources_.end())
959 continue;
960
961 Resource* resource = &map_iterator->second; 961 Resource* resource = &map_iterator->second;
962
962 CHECK_GE(resource->exported_count, it->count); 963 CHECK_GE(resource->exported_count, it->count);
963 resource->exported_count -= it->count; 964 resource->exported_count -= it->count;
964 if (resource->exported_count) 965 if (resource->exported_count)
965 continue; 966 continue;
967
966 if (resource->gl_id) { 968 if (resource->gl_id) {
967 if (it->sync_point) 969 if (it->sync_point)
968 GLC(context3d, context3d->waitSyncPoint(it->sync_point)); 970 GLC(context3d, context3d->waitSyncPoint(it->sync_point));
969 } else { 971 } else {
970 resource->mailbox = 972 resource->mailbox =
971 TextureMailbox(resource->mailbox.name(), it->sync_point); 973 TextureMailbox(resource->mailbox.name(), it->sync_point);
972 } 974 }
973 if (resource->marked_for_deletion) 975
974 DeleteResourceInternal(map_iterator, Normal); 976 if (!resource->marked_for_deletion)
977 continue;
978 if (!resource->child_id)
979 continue;
980
981 // Delete the resource and return it to a child if it came from one.
982 if (resource->child_id != child_id) {
983 ChildMap::iterator child_it = children_.find(resource->child_id);
984 if (child_it == children_.end()) {
985 // The child is gone and has abandoned the resource.
piman 2013/09/20 01:55:01 How can this happen? If the child is gone, we remo
danakj 2013/09/20 14:54:52 Hm.. let me double check.. maybe this condition is
danakj 2013/09/20 17:35:12 DCHECKing here pointed out that Resource::child_id
986 DeleteResourceInternal(map_iterator, Normal);
987 continue;
988 }
989
990 if (child_id) {
991 DCHECK_NE(resources_for_child.size(), 0u);
992 DeleteAndReturnUnusedResourcesToChild(
993 child_info, Normal, resources_for_child);
994 resources_for_child.clear();
piman 2013/09/20 01:55:01 Not sure how "coherent" the child ids will be in p
danakj 2013/09/20 14:54:52 I thought about a per-child id map but I thought i
danakj 2013/09/20 17:35:12 Implementing sorting required some fun with pairs,
995 }
996
997 child_info = &child_it->second;
998 child_id = resource->child_id;
999 }
1000 resources_for_child.push_back(local_id);
1001 }
1002
1003 if (child_id) {
1004 DCHECK_NE(resources_for_child.size(), 0u);
1005 DeleteAndReturnUnusedResourcesToChild(
1006 child_info, Normal, resources_for_child);
975 } 1007 }
976 } 1008 }
977 1009
978 void ResourceProvider::TransferResource(WebGraphicsContext3D* context, 1010 void ResourceProvider::TransferResource(WebGraphicsContext3D* context,
979 ResourceId id, 1011 ResourceId id,
980 TransferableResource* resource) { 1012 TransferableResource* resource) {
981 Resource* source = GetResource(id); 1013 Resource* source = GetResource(id);
982 DCHECK(!source->locked_for_write); 1014 DCHECK(!source->locked_for_write);
983 DCHECK(!source->lock_for_read_count); 1015 DCHECK(!source->lock_for_read_count);
984 DCHECK(!source->external || (source->external && source->mailbox.IsValid())); 1016 DCHECK(!source->external || (source->external && source->mailbox.IsValid()));
(...skipping 17 matching lines...) Expand all
1002 source->mailbox.SetName(resource->mailbox); 1034 source->mailbox.SetName(resource->mailbox);
1003 } else { 1035 } else {
1004 // This is either an external resource, or a compositor resource that we 1036 // This is either an external resource, or a compositor resource that we
1005 // already exported. Make sure to forward the sync point that we were given. 1037 // already exported. Make sure to forward the sync point that we were given.
1006 resource->mailbox = source->mailbox.name(); 1038 resource->mailbox = source->mailbox.name();
1007 resource->sync_point = source->mailbox.sync_point(); 1039 resource->sync_point = source->mailbox.sync_point();
1008 source->mailbox.ResetSyncPoint(); 1040 source->mailbox.ResetSyncPoint();
1009 } 1041 }
1010 } 1042 }
1011 1043
1044 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild(
1045 Child* child_info,
1046 DeleteStyle style,
1047 const ResourceIdArray& unused) {
1048 DCHECK(thread_checker_.CalledOnValidThread());
1049 DCHECK(child_info);
1050
1051 if (unused.empty())
1052 return;
1053
1054 WebGraphicsContext3D* context3d = Context3d();
1055 if (!context3d || !context3d->makeContextCurrent()) {
1056 // TODO(skaslev): Implement this path for software compositing.
1057 return;
1058 }
1059
1060 ReturnedResourceArray to_return;
1061
1062 bool need_sync_point = false;
1063 for (size_t i = 0; i < unused.size(); ++i) {
1064 ResourceId local_id = unused[i];
1065
1066 ResourceMap::iterator it = resources_.find(local_id);
1067 CHECK(it != resources_.end());
1068 Resource& resource = it->second;
1069
1070 DCHECK(!resource.locked_for_write);
1071 DCHECK(!resource.lock_for_read_count);
1072 DCHECK_EQ(0u, child_info->in_use_resources.count(local_id));
1073 DCHECK(child_info->parent_to_child_map.count(local_id));
1074
1075 ResourceId child_id = child_info->parent_to_child_map[local_id];
1076 DCHECK(child_info->child_to_parent_map.count(child_id));
1077
1078 bool is_lost = false;
1079 if (resource.exported_count > 0) {
1080 if (style != ForShutdown) {
1081 // Defer this until we receive the resource back from the parent.
1082 resource.marked_for_deletion = true;
1083 continue;
1084 }
1085
1086 // We still have an exported_count, so we'll have to lose it.
1087 is_lost = true;
1088 }
1089
1090 if (resource.filter != resource.original_filter) {
1091 DCHECK(resource.target);
1092 DCHECK(resource.gl_id);
1093
1094 GLC(context3d, context3d->bindTexture(resource.target, resource.gl_id));
1095 GLC(context3d,
1096 context3d->texParameteri(resource.target,
1097 GL_TEXTURE_MIN_FILTER,
1098 resource.original_filter));
1099 GLC(context3d,
1100 context3d->texParameteri(resource.target,
1101 GL_TEXTURE_MAG_FILTER,
1102 resource.original_filter));
1103 }
1104
1105 ReturnedResource returned;
1106 returned.id = child_id;
1107 returned.sync_point = resource.mailbox.sync_point();
1108 if (!returned.sync_point)
1109 need_sync_point = true;
1110 returned.count = resource.imported_count;
1111 // TODO(danakj): Save the |is_lost| bit.
1112 to_return.push_back(returned);
1113
1114 child_info->parent_to_child_map.erase(local_id);
1115 child_info->child_to_parent_map.erase(child_id);
1116 resource.imported_count = 0;
1117 DeleteResourceInternal(it, style);
1118 }
1119 if (need_sync_point) {
1120 unsigned int sync_point = context3d->insertSyncPoint();
1121 for (size_t i = 0; i < to_return.size(); ++i) {
1122 if (!to_return[i].sync_point)
1123 to_return[i].sync_point = sync_point;
1124 }
1125 }
1126
1127 if (!to_return.empty())
1128 child_info->return_callback.Run(to_return);
1129 }
1130
1012 void ResourceProvider::AcquirePixelBuffer(ResourceId id) { 1131 void ResourceProvider::AcquirePixelBuffer(ResourceId id) {
1013 Resource* resource = GetResource(id); 1132 Resource* resource = GetResource(id);
1014 DCHECK(!resource->external); 1133 DCHECK(!resource->external);
1015 DCHECK_EQ(resource->exported_count, 0); 1134 DCHECK_EQ(resource->exported_count, 0);
1016 DCHECK(!resource->image_id); 1135 DCHECK(!resource->image_id);
1017 1136
1018 if (resource->type == GLTexture) { 1137 if (resource->type == GLTexture) {
1019 WebGraphicsContext3D* context3d = Context3d(); 1138 WebGraphicsContext3D* context3d = Context3d();
1020 DCHECK(context3d); 1139 DCHECK(context3d);
1021 if (!resource->gl_pixel_buffer_id) 1140 if (!resource->gl_pixel_buffer_id)
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after
1450 context->getIntegerv(GL_ACTIVE_TEXTURE, &active_unit); 1569 context->getIntegerv(GL_ACTIVE_TEXTURE, &active_unit);
1451 return active_unit; 1570 return active_unit;
1452 } 1571 }
1453 1572
1454 WebKit::WebGraphicsContext3D* ResourceProvider::Context3d() const { 1573 WebKit::WebGraphicsContext3D* ResourceProvider::Context3d() const {
1455 ContextProvider* context_provider = output_surface_->context_provider(); 1574 ContextProvider* context_provider = output_surface_->context_provider();
1456 return context_provider ? context_provider->Context3d() : NULL; 1575 return context_provider ? context_provider->Context3d() : NULL;
1457 } 1576 }
1458 1577
1459 } // namespace cc 1578 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698