OLD | NEW |
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 904 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
915 DeleteResourceInternal(it, Normal); | 915 DeleteResourceInternal(it, Normal); |
916 } else { | 916 } else { |
917 ChildMap::iterator child_it = children_.find(resource->child_id); | 917 ChildMap::iterator child_it = children_.find(resource->child_id); |
918 ResourceIdArray unused; | 918 ResourceIdArray unused; |
919 unused.push_back(id); | 919 unused.push_back(id); |
920 DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused); | 920 DeleteAndReturnUnusedResourcesToChild(child_it, Normal, unused); |
921 } | 921 } |
922 } | 922 } |
923 } | 923 } |
924 | 924 |
925 const ResourceProvider::Resource* ResourceProvider::LockForWrite( | 925 ResourceProvider::Resource* ResourceProvider::LockForWrite(ResourceId id) { |
926 ResourceId id) { | |
927 Resource* resource = GetResource(id); | 926 Resource* resource = GetResource(id); |
928 DCHECK(CanLockForWrite(id)); | 927 DCHECK(CanLockForWrite(id)); |
929 LazyAllocate(resource); | |
930 | 928 |
931 resource->locked_for_write = true; | 929 resource->locked_for_write = true; |
932 return resource; | 930 return resource; |
933 } | 931 } |
934 | 932 |
935 bool ResourceProvider::CanLockForWrite(ResourceId id) { | 933 bool ResourceProvider::CanLockForWrite(ResourceId id) { |
936 Resource* resource = GetResource(id); | 934 Resource* resource = GetResource(id); |
937 return !resource->locked_for_write && !resource->lock_for_read_count && | 935 return !resource->locked_for_write && !resource->lock_for_read_count && |
938 !resource->exported_count && resource->origin == Resource::Internal && | 936 !resource->exported_count && resource->origin == Resource::Internal && |
939 !resource->lost && ReadLockFenceHasPassed(resource); | 937 !resource->lost && ReadLockFenceHasPassed(resource); |
940 } | 938 } |
941 | 939 |
942 void ResourceProvider::UnlockForWrite(ResourceId id) { | 940 void ResourceProvider::UnlockForWrite(ResourceProvider::Resource* resource) { |
943 Resource* resource = GetResource(id); | |
944 DCHECK(resource->locked_for_write); | 941 DCHECK(resource->locked_for_write); |
945 DCHECK_EQ(resource->exported_count, 0); | 942 DCHECK_EQ(resource->exported_count, 0); |
946 DCHECK(resource->origin == Resource::Internal); | 943 DCHECK(resource->origin == Resource::Internal); |
947 resource->locked_for_write = false; | 944 resource->locked_for_write = false; |
948 } | 945 } |
949 | 946 |
950 const ResourceProvider::Resource* | |
951 ResourceProvider::LockForWriteToGpuMemoryBuffer(ResourceId id) { | |
952 Resource* resource = GetResource(id); | |
953 DCHECK_EQ(GLTexture, resource->type); | |
954 DCHECK(CanLockForWrite(id)); | |
955 | |
956 if (!resource->gpu_memory_buffer) { | |
957 scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer = | |
958 gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer( | |
959 resource->size, | |
960 ToGpuMemoryBufferFormat(resource->format), | |
961 gfx::GpuMemoryBuffer::MAP); | |
962 resource->gpu_memory_buffer = gpu_memory_buffer.release(); | |
963 resource->allocated = true; | |
964 } | |
965 | |
966 resource->locked_for_write = true; | |
967 return resource; | |
968 } | |
969 | |
970 void ResourceProvider::UnlockForWriteToGpuMemoryBuffer(ResourceId id) { | |
971 Resource* resource = GetResource(id); | |
972 DCHECK(resource->locked_for_write); | |
973 DCHECK_EQ(resource->exported_count, 0); | |
974 DCHECK(resource->origin == Resource::Internal); | |
975 DCHECK_EQ(GLTexture, resource->type); | |
976 | |
977 if (!resource->image_id) { | |
978 GLES2Interface* gl = ContextGL(); | |
979 DCHECK(gl); | |
980 resource->image_id = | |
981 gl->CreateImageCHROMIUM(resource->gpu_memory_buffer->AsClientBuffer(), | |
982 resource->size.width(), | |
983 resource->size.height(), | |
984 GL_RGBA); | |
985 } | |
986 | |
987 resource->locked_for_write = false; | |
988 resource->dirty_image = true; | |
989 | |
990 // GpuMemoryBuffer provides direct access to the memory used by the GPU. | |
991 // Read lock fences are required to ensure that we're not trying to map a | |
992 // buffer that is currently in-use by the GPU. | |
993 resource->read_lock_fences_enabled = true; | |
994 } | |
995 | |
996 void ResourceProvider::LockForWriteToSkSurface(ResourceId id) { | |
997 Resource* resource = GetResource(id); | |
998 DCHECK_EQ(GLTexture, resource->type); | |
999 DCHECK(CanLockForWrite(id)); | |
1000 | |
1001 resource->locked_for_write = true; | |
1002 } | |
1003 | |
1004 void ResourceProvider::UnlockForWriteToSkSurface(ResourceId id) { | |
1005 Resource* resource = GetResource(id); | |
1006 DCHECK(resource->locked_for_write); | |
1007 DCHECK_EQ(resource->exported_count, 0); | |
1008 DCHECK(resource->origin == Resource::Internal); | |
1009 DCHECK_EQ(GLTexture, resource->type); | |
1010 resource->locked_for_write = false; | |
1011 } | |
1012 | |
1013 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL( | 947 ResourceProvider::ScopedReadLockGL::ScopedReadLockGL( |
1014 ResourceProvider* resource_provider, | 948 ResourceProvider* resource_provider, |
1015 ResourceProvider::ResourceId resource_id) | 949 ResourceProvider::ResourceId resource_id) |
1016 : resource_provider_(resource_provider), | 950 : resource_provider_(resource_provider), |
1017 resource_id_(resource_id), | 951 resource_id_(resource_id), |
1018 texture_id_(resource_provider->LockForRead(resource_id)->gl_id) { | 952 texture_id_(resource_provider->LockForRead(resource_id)->gl_id) { |
1019 DCHECK(texture_id_); | 953 DCHECK(texture_id_); |
1020 } | 954 } |
1021 | 955 |
1022 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() { | 956 ResourceProvider::ScopedReadLockGL::~ScopedReadLockGL() { |
(...skipping 19 matching lines...) Expand all Loading... |
1042 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) { | 976 target_(resource_provider->BindForSampling(resource_id, unit_, filter)) { |
1043 } | 977 } |
1044 | 978 |
1045 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() { | 979 ResourceProvider::ScopedSamplerGL::~ScopedSamplerGL() { |
1046 } | 980 } |
1047 | 981 |
1048 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL( | 982 ResourceProvider::ScopedWriteLockGL::ScopedWriteLockGL( |
1049 ResourceProvider* resource_provider, | 983 ResourceProvider* resource_provider, |
1050 ResourceProvider::ResourceId resource_id) | 984 ResourceProvider::ResourceId resource_id) |
1051 : resource_provider_(resource_provider), | 985 : resource_provider_(resource_provider), |
1052 resource_id_(resource_id), | 986 resource_(resource_provider->LockForWrite(resource_id)) { |
1053 texture_id_(resource_provider->LockForWrite(resource_id)->gl_id) { | 987 resource_provider_->LazyAllocate(resource_); |
| 988 texture_id_ = resource_->gl_id; |
1054 DCHECK(texture_id_); | 989 DCHECK(texture_id_); |
1055 } | 990 } |
1056 | 991 |
1057 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() { | 992 ResourceProvider::ScopedWriteLockGL::~ScopedWriteLockGL() { |
1058 resource_provider_->UnlockForWrite(resource_id_); | 993 resource_provider_->UnlockForWrite(resource_); |
1059 } | 994 } |
1060 | 995 |
1061 void ResourceProvider::PopulateSkBitmapWithResource( | 996 void ResourceProvider::PopulateSkBitmapWithResource( |
1062 SkBitmap* sk_bitmap, const Resource* resource) { | 997 SkBitmap* sk_bitmap, const Resource* resource) { |
1063 DCHECK_EQ(RGBA_8888, resource->format); | 998 DCHECK_EQ(RGBA_8888, resource->format); |
1064 SkImageInfo info = SkImageInfo::MakeN32Premul(resource->size.width(), | 999 SkImageInfo info = SkImageInfo::MakeN32Premul(resource->size.width(), |
1065 resource->size.height()); | 1000 resource->size.height()); |
1066 sk_bitmap->installPixels(info, resource->pixels, info.minRowBytes()); | 1001 sk_bitmap->installPixels(info, resource->pixels, info.minRowBytes()); |
1067 } | 1002 } |
1068 | 1003 |
1069 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware( | 1004 ResourceProvider::ScopedReadLockSoftware::ScopedReadLockSoftware( |
1070 ResourceProvider* resource_provider, | 1005 ResourceProvider* resource_provider, |
1071 ResourceProvider::ResourceId resource_id) | 1006 ResourceProvider::ResourceId resource_id) |
1072 : resource_provider_(resource_provider), | 1007 : resource_provider_(resource_provider), |
1073 resource_id_(resource_id) { | 1008 resource_id_(resource_id) { |
1074 const Resource* resource = resource_provider->LockForRead(resource_id); | 1009 const Resource* resource = resource_provider->LockForRead(resource_id); |
1075 wrap_mode_ = resource->wrap_mode; | 1010 wrap_mode_ = resource->wrap_mode; |
1076 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource); | 1011 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource); |
1077 } | 1012 } |
1078 | 1013 |
1079 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() { | 1014 ResourceProvider::ScopedReadLockSoftware::~ScopedReadLockSoftware() { |
1080 resource_provider_->UnlockForRead(resource_id_); | 1015 resource_provider_->UnlockForRead(resource_id_); |
1081 } | 1016 } |
1082 | 1017 |
1083 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware( | 1018 ResourceProvider::ScopedWriteLockSoftware::ScopedWriteLockSoftware( |
1084 ResourceProvider* resource_provider, | 1019 ResourceProvider* resource_provider, |
1085 ResourceProvider::ResourceId resource_id) | 1020 ResourceProvider::ResourceId resource_id) |
1086 : resource_provider_(resource_provider), | 1021 : resource_provider_(resource_provider), |
1087 resource_id_(resource_id) { | 1022 resource_(resource_provider->LockForWrite(resource_id)) { |
1088 ResourceProvider::PopulateSkBitmapWithResource( | 1023 ResourceProvider::PopulateSkBitmapWithResource(&sk_bitmap_, resource_); |
1089 &sk_bitmap_, resource_provider->LockForWrite(resource_id)); | |
1090 DCHECK(valid()); | 1024 DCHECK(valid()); |
1091 sk_canvas_.reset(new SkCanvas(sk_bitmap_)); | 1025 sk_canvas_.reset(new SkCanvas(sk_bitmap_)); |
1092 } | 1026 } |
1093 | 1027 |
1094 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() { | 1028 ResourceProvider::ScopedWriteLockSoftware::~ScopedWriteLockSoftware() { |
1095 resource_provider_->UnlockForWrite(resource_id_); | 1029 resource_provider_->UnlockForWrite(resource_); |
1096 } | 1030 } |
1097 | 1031 |
1098 ResourceProvider::ScopedWriteLockGpuMemoryBuffer:: | 1032 ResourceProvider::ScopedWriteLockGpuMemoryBuffer:: |
1099 ScopedWriteLockGpuMemoryBuffer(ResourceProvider* resource_provider, | 1033 ScopedWriteLockGpuMemoryBuffer(ResourceProvider* resource_provider, |
1100 ResourceProvider::ResourceId resource_id) | 1034 ResourceProvider::ResourceId resource_id) |
1101 : resource_provider_(resource_provider), | 1035 : resource_provider_(resource_provider), |
1102 resource_id_(resource_id), | 1036 resource_(resource_provider->LockForWrite(resource_id)), |
1103 gpu_memory_buffer_( | 1037 gpu_memory_buffer_manager_(resource_provider->gpu_memory_buffer_manager_), |
1104 resource_provider->LockForWriteToGpuMemoryBuffer(resource_id) | 1038 gpu_memory_buffer_(nullptr), |
1105 ->gpu_memory_buffer) { | 1039 size_(resource_->size), |
| 1040 format_(resource_->format) { |
| 1041 DCHECK_EQ(GLTexture, resource_->type); |
| 1042 std::swap(gpu_memory_buffer_, resource_->gpu_memory_buffer); |
1106 } | 1043 } |
1107 | 1044 |
1108 ResourceProvider::ScopedWriteLockGpuMemoryBuffer:: | 1045 ResourceProvider::ScopedWriteLockGpuMemoryBuffer:: |
1109 ~ScopedWriteLockGpuMemoryBuffer() { | 1046 ~ScopedWriteLockGpuMemoryBuffer() { |
1110 resource_provider_->UnlockForWriteToGpuMemoryBuffer(resource_id_); | 1047 resource_provider_->UnlockForWrite(resource_); |
| 1048 if (!gpu_memory_buffer_) |
| 1049 return; |
| 1050 |
| 1051 if (!resource_->image_id) { |
| 1052 GLES2Interface* gl = resource_provider_->ContextGL(); |
| 1053 DCHECK(gl); |
| 1054 |
| 1055 resource_->image_id = |
| 1056 gl->CreateImageCHROMIUM(gpu_memory_buffer_->AsClientBuffer(), |
| 1057 size_.width(), |
| 1058 size_.height(), |
| 1059 GL_RGBA); |
| 1060 } |
| 1061 |
| 1062 std::swap(resource_->gpu_memory_buffer, gpu_memory_buffer_); |
| 1063 resource_->allocated = true; |
| 1064 resource_->dirty_image = true; |
| 1065 |
| 1066 // GpuMemoryBuffer provides direct access to the memory used by the GPU. |
| 1067 // Read lock fences are required to ensure that we're not trying to map a |
| 1068 // buffer that is currently in-use by the GPU. |
| 1069 resource_->read_lock_fences_enabled = true; |
| 1070 } |
| 1071 |
| 1072 gfx::GpuMemoryBuffer* |
| 1073 ResourceProvider::ScopedWriteLockGpuMemoryBuffer::GetGpuMemoryBuffer() { |
| 1074 if (!gpu_memory_buffer_) { |
| 1075 scoped_ptr<gfx::GpuMemoryBuffer> gpu_memory_buffer = |
| 1076 gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer( |
| 1077 size_, ToGpuMemoryBufferFormat(format_), gfx::GpuMemoryBuffer::MAP); |
| 1078 gpu_memory_buffer_ = gpu_memory_buffer.release(); |
| 1079 } |
| 1080 |
| 1081 return gpu_memory_buffer_; |
1111 } | 1082 } |
1112 | 1083 |
1113 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr( | 1084 ResourceProvider::ScopedWriteLockGr::ScopedWriteLockGr( |
1114 ResourceProvider* resource_provider, | 1085 ResourceProvider* resource_provider, |
1115 ResourceProvider::ResourceId resource_id) | 1086 ResourceProvider::ResourceId resource_id) |
1116 : resource_provider_(resource_provider), resource_id_(resource_id) { | 1087 : resource_provider_(resource_provider), |
1117 resource_provider->LockForWriteToSkSurface(resource_id); | 1088 resource_(resource_provider->LockForWrite(resource_id)) { |
1118 } | 1089 } |
1119 | 1090 |
1120 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() { | 1091 ResourceProvider::ScopedWriteLockGr::~ScopedWriteLockGr() { |
1121 resource_provider_->UnlockForWriteToSkSurface(resource_id_); | 1092 resource_provider_->UnlockForWrite(resource_); |
1122 } | 1093 } |
1123 | 1094 |
1124 SkSurface* ResourceProvider::ScopedWriteLockGr::GetSkSurface( | 1095 SkSurface* ResourceProvider::ScopedWriteLockGr::GetSkSurface( |
1125 bool use_distance_field_text) { | 1096 bool use_distance_field_text) { |
1126 Resource* resource = resource_provider_->GetResource(resource_id_); | 1097 DCHECK(resource_->locked_for_write); |
1127 DCHECK(resource->locked_for_write); | |
1128 | 1098 |
1129 // If the surface doesn't exist, or doesn't have the correct dff setting, | 1099 // If the surface doesn't exist, or doesn't have the correct dff setting, |
1130 // recreate the surface within the resource. | 1100 // recreate the surface within the resource. |
1131 if (!resource->sk_surface || | 1101 if (!resource_->sk_surface || |
1132 use_distance_field_text != | 1102 use_distance_field_text != |
1133 resource->sk_surface->props().isUseDistanceFieldFonts()) { | 1103 resource_->sk_surface->props().isUseDistanceFieldFonts()) { |
1134 class GrContext* gr_context = resource_provider_->GrContext(); | 1104 class GrContext* gr_context = resource_provider_->GrContext(); |
1135 // TODO(alokp): Implement TestContextProvider::GrContext(). | 1105 // TODO(alokp): Implement TestContextProvider::GrContext(). |
1136 if (!gr_context) | 1106 if (!gr_context) |
1137 return nullptr; | 1107 return nullptr; |
1138 | 1108 |
1139 resource_provider_->LazyAllocate(resource); | 1109 resource_provider_->LazyAllocate(resource_); |
1140 | 1110 |
1141 GrBackendTextureDesc desc; | 1111 GrBackendTextureDesc desc; |
1142 desc.fFlags = kRenderTarget_GrBackendTextureFlag; | 1112 desc.fFlags = kRenderTarget_GrBackendTextureFlag; |
1143 desc.fWidth = resource->size.width(); | 1113 desc.fWidth = resource_->size.width(); |
1144 desc.fHeight = resource->size.height(); | 1114 desc.fHeight = resource_->size.height(); |
1145 desc.fConfig = ToGrPixelConfig(resource->format); | 1115 desc.fConfig = ToGrPixelConfig(resource_->format); |
1146 desc.fOrigin = kTopLeft_GrSurfaceOrigin; | 1116 desc.fOrigin = kTopLeft_GrSurfaceOrigin; |
1147 desc.fTextureHandle = resource->gl_id; | 1117 desc.fTextureHandle = resource_->gl_id; |
1148 skia::RefPtr<GrTexture> gr_texture = | 1118 skia::RefPtr<GrTexture> gr_texture = |
1149 skia::AdoptRef(gr_context->wrapBackendTexture(desc)); | 1119 skia::AdoptRef(gr_context->wrapBackendTexture(desc)); |
1150 SkSurface::TextRenderMode text_render_mode = | 1120 SkSurface::TextRenderMode text_render_mode = |
1151 use_distance_field_text ? SkSurface::kDistanceField_TextRenderMode | 1121 use_distance_field_text ? SkSurface::kDistanceField_TextRenderMode |
1152 : SkSurface::kStandard_TextRenderMode; | 1122 : SkSurface::kStandard_TextRenderMode; |
1153 resource->sk_surface = skia::AdoptRef(SkSurface::NewRenderTargetDirect( | 1123 resource_->sk_surface = skia::AdoptRef(SkSurface::NewRenderTargetDirect( |
1154 gr_texture->asRenderTarget(), text_render_mode)); | 1124 gr_texture->asRenderTarget(), text_render_mode)); |
1155 } | 1125 } |
1156 return resource->sk_surface.get(); | 1126 return resource_->sk_surface.get(); |
1157 } | 1127 } |
1158 | 1128 |
1159 ResourceProvider::ResourceProvider( | 1129 ResourceProvider::ResourceProvider( |
1160 OutputSurface* output_surface, | 1130 OutputSurface* output_surface, |
1161 SharedBitmapManager* shared_bitmap_manager, | 1131 SharedBitmapManager* shared_bitmap_manager, |
1162 GpuMemoryBufferManager* gpu_memory_buffer_manager, | 1132 GpuMemoryBufferManager* gpu_memory_buffer_manager, |
1163 BlockingTaskRunner* blocking_main_thread_task_runner, | 1133 BlockingTaskRunner* blocking_main_thread_task_runner, |
1164 int highp_threshold_min, | 1134 int highp_threshold_min, |
1165 bool use_rgba_4444_texture_format, | 1135 bool use_rgba_4444_texture_format, |
1166 size_t id_allocation_chunk_size) | 1136 size_t id_allocation_chunk_size) |
(...skipping 733 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1900 DCHECK(gl); | 1870 DCHECK(gl); |
1901 DCHECK(resource->gl_upload_query_id); | 1871 DCHECK(resource->gl_upload_query_id); |
1902 GLuint complete = 1; | 1872 GLuint complete = 1; |
1903 gl->GetQueryObjectuivEXT( | 1873 gl->GetQueryObjectuivEXT( |
1904 resource->gl_upload_query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete); | 1874 resource->gl_upload_query_id, GL_QUERY_RESULT_AVAILABLE_EXT, &complete); |
1905 if (!complete) | 1875 if (!complete) |
1906 return false; | 1876 return false; |
1907 } | 1877 } |
1908 | 1878 |
1909 resource->pending_set_pixels = false; | 1879 resource->pending_set_pixels = false; |
1910 UnlockForWrite(id); | 1880 UnlockForWrite(resource); |
1911 | 1881 |
1912 // Async set pixels commands are not necessarily processed in-sequence with | 1882 // Async set pixels commands are not necessarily processed in-sequence with |
1913 // drawing commands. Read lock fences are required to ensure that async | 1883 // drawing commands. Read lock fences are required to ensure that async |
1914 // commands don't access the resource while used for drawing. | 1884 // commands don't access the resource while used for drawing. |
1915 resource->read_lock_fences_enabled = true; | 1885 resource->read_lock_fences_enabled = true; |
1916 | 1886 |
1917 return true; | 1887 return true; |
1918 } | 1888 } |
1919 | 1889 |
1920 void ResourceProvider::CreateForTesting(ResourceId id) { | 1890 void ResourceProvider::CreateForTesting(ResourceId id) { |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2094 ContextProvider* context_provider = output_surface_->context_provider(); | 2064 ContextProvider* context_provider = output_surface_->context_provider(); |
2095 return context_provider ? context_provider->ContextGL() : NULL; | 2065 return context_provider ? context_provider->ContextGL() : NULL; |
2096 } | 2066 } |
2097 | 2067 |
2098 class GrContext* ResourceProvider::GrContext() const { | 2068 class GrContext* ResourceProvider::GrContext() const { |
2099 ContextProvider* context_provider = output_surface_->context_provider(); | 2069 ContextProvider* context_provider = output_surface_->context_provider(); |
2100 return context_provider ? context_provider->GrContext() : NULL; | 2070 return context_provider ? context_provider->GrContext() : NULL; |
2101 } | 2071 } |
2102 | 2072 |
2103 } // namespace cc | 2073 } // namespace cc |
OLD | NEW |