| 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 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 WebGraphicsContext3D* context3d = Context3d(); | 542 WebGraphicsContext3D* context3d = Context3d(); |
| 543 DCHECK(context3d); | 543 DCHECK(context3d); |
| 544 GLC(context3d, context3d->deleteQueryEXT(resource->gl_upload_query_id)); | 544 GLC(context3d, context3d->deleteQueryEXT(resource->gl_upload_query_id)); |
| 545 } | 545 } |
| 546 if (resource->gl_pixel_buffer_id) { | 546 if (resource->gl_pixel_buffer_id) { |
| 547 WebGraphicsContext3D* context3d = Context3d(); | 547 WebGraphicsContext3D* context3d = Context3d(); |
| 548 DCHECK(context3d); | 548 DCHECK(context3d); |
| 549 GLC(context3d, context3d->deleteBuffer(resource->gl_pixel_buffer_id)); | 549 GLC(context3d, context3d->deleteBuffer(resource->gl_pixel_buffer_id)); |
| 550 } | 550 } |
| 551 if (resource->mailbox.IsValid() && resource->external) { | 551 if (resource->mailbox.IsValid() && resource->external) { |
| 552 unsigned sync_point = resource->mailbox.sync_point(); | 552 uint32 sync_point = resource->mailbox.sync_point(); |
| 553 if (resource->mailbox.IsTexture()) { | 553 if (resource->mailbox.IsTexture()) { |
| 554 lost_resource |= lost_output_surface_; | 554 lost_resource |= lost_output_surface_; |
| 555 WebGraphicsContext3D* context3d = Context3d(); | 555 WebGraphicsContext3D* context3d = Context3d(); |
| 556 DCHECK(context3d); | 556 DCHECK(context3d); |
| 557 if (resource->gl_id) | 557 if (resource->gl_id) |
| 558 GLC(context3d, context3d->deleteTexture(resource->gl_id)); | 558 GLC(context3d, context3d->deleteTexture(resource->gl_id)); |
| 559 if (!lost_resource && resource->gl_id) | 559 if (!lost_resource && resource->gl_id) |
| 560 sync_point = context3d->insertSyncPoint(); | 560 sync_point = context3d->insertSyncPoint(); |
| 561 } else { | 561 } else { |
| 562 DCHECK(resource->mailbox.IsSharedMemory()); | 562 DCHECK(resource->mailbox.IsSharedMemory()); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 738 | 738 |
| 739 LazyCreate(resource); | 739 LazyCreate(resource); |
| 740 | 740 |
| 741 if (resource->external) { | 741 if (resource->external) { |
| 742 if (!resource->gl_id && resource->mailbox.IsTexture()) { | 742 if (!resource->gl_id && resource->mailbox.IsTexture()) { |
| 743 WebGraphicsContext3D* context3d = Context3d(); | 743 WebGraphicsContext3D* context3d = Context3d(); |
| 744 DCHECK(context3d); | 744 DCHECK(context3d); |
| 745 if (resource->mailbox.sync_point()) { | 745 if (resource->mailbox.sync_point()) { |
| 746 GLC(context3d, | 746 GLC(context3d, |
| 747 context3d->waitSyncPoint(resource->mailbox.sync_point())); | 747 context3d->waitSyncPoint(resource->mailbox.sync_point())); |
| 748 resource->mailbox.ResetSyncPoint(); | 748 resource->mailbox.set_sync_point(0); |
| 749 } | 749 } |
| 750 resource->gl_id = texture_id_allocator_->NextId(); | 750 resource->gl_id = texture_id_allocator_->NextId(); |
| 751 GLC(context3d, context3d->bindTexture(resource->target, resource->gl_id)); | 751 GLC(context3d, context3d->bindTexture(resource->target, resource->gl_id)); |
| 752 GLC(context3d, | 752 GLC(context3d, |
| 753 context3d->consumeTextureCHROMIUM(resource->target, | 753 context3d->consumeTextureCHROMIUM(resource->target, |
| 754 resource->mailbox.data())); | 754 resource->mailbox.mailbox().name)); |
| 755 } | 755 } |
| 756 } | 756 } |
| 757 | 757 |
| 758 resource->lock_for_read_count++; | 758 resource->lock_for_read_count++; |
| 759 if (resource->enable_read_lock_fences) | 759 if (resource->enable_read_lock_fences) |
| 760 resource->read_lock_fence = current_read_lock_fence_; | 760 resource->read_lock_fence = current_read_lock_fence_; |
| 761 | 761 |
| 762 return resource; | 762 return resource; |
| 763 } | 763 } |
| 764 | 764 |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1031 DCHECK(thread_checker_.CalledOnValidThread()); | 1031 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1032 WebGraphicsContext3D* context3d = Context3d(); | 1032 WebGraphicsContext3D* context3d = Context3d(); |
| 1033 if (context3d) | 1033 if (context3d) |
| 1034 context3d->makeContextCurrent(); | 1034 context3d->makeContextCurrent(); |
| 1035 bool need_sync_point = false; | 1035 bool need_sync_point = false; |
| 1036 for (ResourceIdArray::const_iterator it = resources.begin(); | 1036 for (ResourceIdArray::const_iterator it = resources.begin(); |
| 1037 it != resources.end(); | 1037 it != resources.end(); |
| 1038 ++it) { | 1038 ++it) { |
| 1039 TransferableResource resource; | 1039 TransferableResource resource; |
| 1040 TransferResource(context3d, *it, &resource); | 1040 TransferResource(context3d, *it, &resource); |
| 1041 if (!resource.sync_point && !resource.is_software) | 1041 if (!resource.mailbox_holder.sync_point && !resource.is_software) |
| 1042 need_sync_point = true; | 1042 need_sync_point = true; |
| 1043 ++resources_.find(*it)->second.exported_count; | 1043 ++resources_.find(*it)->second.exported_count; |
| 1044 list->push_back(resource); | 1044 list->push_back(resource); |
| 1045 } | 1045 } |
| 1046 if (need_sync_point) { | 1046 if (need_sync_point) { |
| 1047 unsigned int sync_point = context3d->insertSyncPoint(); | 1047 uint32 sync_point = context3d->insertSyncPoint(); |
| 1048 for (TransferableResourceArray::iterator it = list->begin(); | 1048 for (TransferableResourceArray::iterator it = list->begin(); |
| 1049 it != list->end(); | 1049 it != list->end(); |
| 1050 ++it) { | 1050 ++it) { |
| 1051 if (!it->sync_point) | 1051 if (!it->mailbox_holder.sync_point) |
| 1052 it->sync_point = sync_point; | 1052 it->mailbox_holder.sync_point = sync_point; |
| 1053 } | 1053 } |
| 1054 } | 1054 } |
| 1055 } | 1055 } |
| 1056 | 1056 |
| 1057 void ResourceProvider::ReceiveFromChild( | 1057 void ResourceProvider::ReceiveFromChild( |
| 1058 int child, const TransferableResourceArray& resources) { | 1058 int child, const TransferableResourceArray& resources) { |
| 1059 DCHECK(thread_checker_.CalledOnValidThread()); | 1059 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1060 WebGraphicsContext3D* context3d = Context3d(); | 1060 WebGraphicsContext3D* context3d = Context3d(); |
| 1061 if (context3d) | 1061 if (context3d) |
| 1062 context3d->makeContextCurrent(); | 1062 context3d->makeContextCurrent(); |
| 1063 Child& child_info = children_.find(child)->second; | 1063 Child& child_info = children_.find(child)->second; |
| 1064 DCHECK(!child_info.marked_for_deletion); | 1064 DCHECK(!child_info.marked_for_deletion); |
| 1065 for (TransferableResourceArray::const_iterator it = resources.begin(); | 1065 for (TransferableResourceArray::const_iterator it = resources.begin(); |
| 1066 it != resources.end(); | 1066 it != resources.end(); |
| 1067 ++it) { | 1067 ++it) { |
| 1068 ResourceIdMap::iterator resource_in_map_it = | 1068 ResourceIdMap::iterator resource_in_map_it = |
| 1069 child_info.child_to_parent_map.find(it->id); | 1069 child_info.child_to_parent_map.find(it->id); |
| 1070 if (resource_in_map_it != child_info.child_to_parent_map.end()) { | 1070 if (resource_in_map_it != child_info.child_to_parent_map.end()) { |
| 1071 resources_[resource_in_map_it->second].imported_count++; | 1071 resources_[resource_in_map_it->second].imported_count++; |
| 1072 continue; | 1072 continue; |
| 1073 } | 1073 } |
| 1074 | 1074 |
| 1075 scoped_ptr<SharedBitmap> bitmap; | 1075 scoped_ptr<SharedBitmap> bitmap; |
| 1076 uint8_t* pixels = NULL; | 1076 uint8_t* pixels = NULL; |
| 1077 if (it->is_software) { | 1077 if (it->is_software) { |
| 1078 if (shared_bitmap_manager_) | 1078 if (shared_bitmap_manager_) { |
| 1079 bitmap = shared_bitmap_manager_->GetSharedBitmapFromId(it->size, | 1079 bitmap = shared_bitmap_manager_->GetSharedBitmapFromId( |
| 1080 it->mailbox); | 1080 it->size, it->mailbox_holder.mailbox); |
| 1081 } |
| 1081 if (bitmap) | 1082 if (bitmap) |
| 1082 pixels = bitmap->pixels(); | 1083 pixels = bitmap->pixels(); |
| 1083 } | 1084 } |
| 1084 | 1085 |
| 1085 if ((!it->is_software && !context3d) || (it->is_software && !pixels)) { | 1086 if ((!it->is_software && !context3d) || (it->is_software && !pixels)) { |
| 1086 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid"); | 1087 TRACE_EVENT0("cc", "ResourceProvider::ReceiveFromChild dropping invalid"); |
| 1087 ReturnedResourceArray to_return; | 1088 ReturnedResourceArray to_return; |
| 1088 to_return.push_back(it->ToReturnedResource()); | 1089 to_return.push_back(it->ToReturnedResource()); |
| 1089 child_info.return_callback.Run(to_return); | 1090 child_info.return_callback.Run(to_return); |
| 1090 continue; | 1091 continue; |
| 1091 } | 1092 } |
| 1092 | 1093 |
| 1093 ResourceId local_id = next_id_++; | 1094 ResourceId local_id = next_id_++; |
| 1094 Resource& resource = resources_[local_id]; | 1095 Resource& resource = resources_[local_id]; |
| 1095 if (it->is_software) { | 1096 if (it->is_software) { |
| 1096 resource = Resource( | 1097 resource = Resource( |
| 1097 pixels, bitmap.release(), it->size, GL_LINEAR, GL_CLAMP_TO_EDGE); | 1098 pixels, bitmap.release(), it->size, GL_LINEAR, GL_CLAMP_TO_EDGE); |
| 1098 } else { | 1099 } else { |
| 1099 unsigned texture_id; | 1100 unsigned texture_id; |
| 1100 // NOTE: If the parent is a browser and the child a renderer, the parent | 1101 // NOTE: If the parent is a browser and the child a renderer, the parent |
| 1101 // is not supposed to have its context wait, because that could induce | 1102 // is not supposed to have its context wait, because that could induce |
| 1102 // deadlocks and/or security issues. The caller is responsible for | 1103 // deadlocks and/or security issues. The caller is responsible for |
| 1103 // waiting asynchronously, and resetting sync_point before calling this. | 1104 // waiting asynchronously, and resetting sync_point before calling this. |
| 1104 // However if the parent is a renderer (e.g. browser tag), it may be ok | 1105 // However if the parent is a renderer (e.g. browser tag), it may be ok |
| 1105 // (and is simpler) to wait. | 1106 // (and is simpler) to wait. |
| 1106 if (it->sync_point) | 1107 if (it->mailbox_holder.sync_point) |
| 1107 GLC(context3d, context3d->waitSyncPoint(it->sync_point)); | 1108 GLC(context3d, context3d->waitSyncPoint(it->mailbox_holder.sync_point)); |
| 1108 texture_id = texture_id_allocator_->NextId(); | 1109 texture_id = texture_id_allocator_->NextId(); |
| 1109 GLC(context3d, context3d->bindTexture(it->target, texture_id)); | |
| 1110 GLC(context3d, | 1110 GLC(context3d, |
| 1111 context3d->consumeTextureCHROMIUM(it->target, it->mailbox.name)); | 1111 context3d->bindTexture(it->mailbox_holder.texture_target, |
| 1112 texture_id)); |
| 1113 GLC(context3d, |
| 1114 context3d->consumeTextureCHROMIUM(it->mailbox_holder.texture_target, |
| 1115 it->mailbox_holder.mailbox.name)); |
| 1112 resource = Resource(texture_id, | 1116 resource = Resource(texture_id, |
| 1113 it->size, | 1117 it->size, |
| 1114 it->target, | 1118 it->mailbox_holder.texture_target, |
| 1115 it->filter, | 1119 it->filter, |
| 1116 0, | 1120 0, |
| 1117 GL_CLAMP_TO_EDGE, | 1121 GL_CLAMP_TO_EDGE, |
| 1118 TextureUsageAny, | 1122 TextureUsageAny, |
| 1119 it->format); | 1123 it->format); |
| 1120 resource.mailbox.SetName(it->mailbox); | 1124 resource.mailbox = cc::TextureMailbox( |
| 1125 it->mailbox_holder.mailbox, it->mailbox_holder.texture_target, 0); |
| 1121 } | 1126 } |
| 1122 resource.child_id = child; | 1127 resource.child_id = child; |
| 1123 // Don't allocate a texture for a child. | 1128 // Don't allocate a texture for a child. |
| 1124 resource.allocated = true; | 1129 resource.allocated = true; |
| 1125 resource.imported_count = 1; | 1130 resource.imported_count = 1; |
| 1126 child_info.parent_to_child_map[local_id] = it->id; | 1131 child_info.parent_to_child_map[local_id] = it->id; |
| 1127 child_info.child_to_parent_map[it->id] = local_id; | 1132 child_info.child_to_parent_map[it->id] = local_id; |
| 1128 } | 1133 } |
| 1129 } | 1134 } |
| 1130 | 1135 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1213 CHECK_GE(resource->exported_count, returned.count); | 1218 CHECK_GE(resource->exported_count, returned.count); |
| 1214 resource->exported_count -= returned.count; | 1219 resource->exported_count -= returned.count; |
| 1215 resource->lost |= returned.lost; | 1220 resource->lost |= returned.lost; |
| 1216 if (resource->exported_count) | 1221 if (resource->exported_count) |
| 1217 continue; | 1222 continue; |
| 1218 | 1223 |
| 1219 if (resource->gl_id) { | 1224 if (resource->gl_id) { |
| 1220 if (returned.sync_point) | 1225 if (returned.sync_point) |
| 1221 GLC(context3d, context3d->waitSyncPoint(returned.sync_point)); | 1226 GLC(context3d, context3d->waitSyncPoint(returned.sync_point)); |
| 1222 } else if (!resource->shared_bitmap) { | 1227 } else if (!resource->shared_bitmap) { |
| 1223 resource->mailbox = | 1228 resource->mailbox.set_sync_point(returned.sync_point); |
| 1224 TextureMailbox(resource->mailbox.name(), returned.sync_point); | |
| 1225 } | 1229 } |
| 1226 | 1230 |
| 1227 if (!resource->marked_for_deletion) | 1231 if (!resource->marked_for_deletion) |
| 1228 continue; | 1232 continue; |
| 1229 | 1233 |
| 1230 if (!resource->child_id) { | 1234 if (!resource->child_id) { |
| 1231 // The resource belongs to this ResourceProvider, so it can be destroyed. | 1235 // The resource belongs to this ResourceProvider, so it can be destroyed. |
| 1232 DeleteResourceInternal(map_iterator, Normal); | 1236 DeleteResourceInternal(map_iterator, Normal); |
| 1233 continue; | 1237 continue; |
| 1234 } | 1238 } |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1262 ResourceId id, | 1266 ResourceId id, |
| 1263 TransferableResource* resource) { | 1267 TransferableResource* resource) { |
| 1264 Resource* source = GetResource(id); | 1268 Resource* source = GetResource(id); |
| 1265 DCHECK(!source->locked_for_write); | 1269 DCHECK(!source->locked_for_write); |
| 1266 DCHECK(!source->lock_for_read_count); | 1270 DCHECK(!source->lock_for_read_count); |
| 1267 DCHECK(!source->external || (source->external && source->mailbox.IsValid())); | 1271 DCHECK(!source->external || (source->external && source->mailbox.IsValid())); |
| 1268 DCHECK(source->allocated); | 1272 DCHECK(source->allocated); |
| 1269 DCHECK_EQ(source->wrap_mode, GL_CLAMP_TO_EDGE); | 1273 DCHECK_EQ(source->wrap_mode, GL_CLAMP_TO_EDGE); |
| 1270 resource->id = id; | 1274 resource->id = id; |
| 1271 resource->format = source->format; | 1275 resource->format = source->format; |
| 1272 resource->target = source->target; | 1276 resource->mailbox_holder.texture_target = source->target; |
| 1273 resource->filter = source->filter; | 1277 resource->filter = source->filter; |
| 1274 resource->size = source->size; | 1278 resource->size = source->size; |
| 1275 | 1279 |
| 1276 if (source->shared_bitmap) { | 1280 if (source->shared_bitmap) { |
| 1277 resource->mailbox = source->shared_bitmap->id(); | 1281 resource->mailbox_holder.mailbox = source->shared_bitmap->id(); |
| 1278 resource->is_software = true; | 1282 resource->is_software = true; |
| 1279 } else if (!source->mailbox.IsValid()) { | 1283 } else if (!source->mailbox.IsValid()) { |
| 1280 // This is a resource allocated by the compositor, we need to produce it. | 1284 // This is a resource allocated by the compositor, we need to produce it. |
| 1281 // Don't set a sync point, the caller will do it. | 1285 // Don't set a sync point, the caller will do it. |
| 1282 DCHECK(source->gl_id); | 1286 DCHECK(source->gl_id); |
| 1283 GLC(context, context->bindTexture(resource->target, source->gl_id)); | |
| 1284 GLC(context, context->genMailboxCHROMIUM(resource->mailbox.name)); | |
| 1285 GLC(context, | 1287 GLC(context, |
| 1286 context->produceTextureCHROMIUM(resource->target, | 1288 context->bindTexture(resource->mailbox_holder.texture_target, |
| 1287 resource->mailbox.name)); | 1289 source->gl_id)); |
| 1288 source->mailbox.SetName(resource->mailbox); | 1290 GLC(context, |
| 1291 context->genMailboxCHROMIUM(resource->mailbox_holder.mailbox.name)); |
| 1292 GLC(context, |
| 1293 context->produceTextureCHROMIUM(resource->mailbox_holder.texture_target, |
| 1294 resource->mailbox_holder.mailbox.name)); |
| 1295 source->mailbox = cc::TextureMailbox(resource->mailbox_holder); |
| 1289 } else { | 1296 } else { |
| 1290 DCHECK(source->mailbox.IsTexture()); | 1297 DCHECK(source->mailbox.IsTexture()); |
| 1291 // This is either an external resource, or a compositor resource that we | 1298 // This is either an external resource, or a compositor resource that we |
| 1292 // already exported. Make sure to forward the sync point that we were given. | 1299 // already exported. Make sure to forward the sync point that we were given. |
| 1293 resource->mailbox = source->mailbox.name(); | 1300 resource->mailbox_holder.mailbox = source->mailbox.mailbox(); |
| 1294 resource->sync_point = source->mailbox.sync_point(); | 1301 resource->mailbox_holder.texture_target = source->mailbox.target(); |
| 1295 source->mailbox.ResetSyncPoint(); | 1302 resource->mailbox_holder.sync_point = source->mailbox.sync_point(); |
| 1303 source->mailbox.set_sync_point(0); |
| 1296 } | 1304 } |
| 1297 } | 1305 } |
| 1298 | 1306 |
| 1299 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild( | 1307 void ResourceProvider::DeleteAndReturnUnusedResourcesToChild( |
| 1300 ChildMap::iterator child_it, | 1308 ChildMap::iterator child_it, |
| 1301 DeleteStyle style, | 1309 DeleteStyle style, |
| 1302 const ResourceIdArray& unused) { | 1310 const ResourceIdArray& unused) { |
| 1303 DCHECK(thread_checker_.CalledOnValidThread()); | 1311 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1304 DCHECK(child_it != children_.end()); | 1312 DCHECK(child_it != children_.end()); |
| 1305 Child* child_info = &child_it->second; | 1313 Child* child_info = &child_it->second; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1366 returned.lost = is_lost; | 1374 returned.lost = is_lost; |
| 1367 to_return.push_back(returned); | 1375 to_return.push_back(returned); |
| 1368 | 1376 |
| 1369 child_info->parent_to_child_map.erase(local_id); | 1377 child_info->parent_to_child_map.erase(local_id); |
| 1370 child_info->child_to_parent_map.erase(child_id); | 1378 child_info->child_to_parent_map.erase(child_id); |
| 1371 resource.imported_count = 0; | 1379 resource.imported_count = 0; |
| 1372 DeleteResourceInternal(it, style); | 1380 DeleteResourceInternal(it, style); |
| 1373 } | 1381 } |
| 1374 if (need_sync_point) { | 1382 if (need_sync_point) { |
| 1375 DCHECK(context3d); | 1383 DCHECK(context3d); |
| 1376 unsigned int sync_point = context3d->insertSyncPoint(); | 1384 uint32 sync_point = context3d->insertSyncPoint(); |
| 1377 for (size_t i = 0; i < to_return.size(); ++i) { | 1385 for (size_t i = 0; i < to_return.size(); ++i) { |
| 1378 if (!to_return[i].sync_point) | 1386 if (!to_return[i].sync_point) |
| 1379 to_return[i].sync_point = sync_point; | 1387 to_return[i].sync_point = sync_point; |
| 1380 } | 1388 } |
| 1381 } | 1389 } |
| 1382 | 1390 |
| 1383 if (!to_return.empty()) | 1391 if (!to_return.empty()) |
| 1384 child_info->return_callback.Run(to_return); | 1392 child_info->return_callback.Run(to_return); |
| 1385 | 1393 |
| 1386 if (child_info->marked_for_deletion && | 1394 if (child_info->marked_for_deletion && |
| (...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1851 context->getIntegerv(GL_ACTIVE_TEXTURE, &active_unit); | 1859 context->getIntegerv(GL_ACTIVE_TEXTURE, &active_unit); |
| 1852 return active_unit; | 1860 return active_unit; |
| 1853 } | 1861 } |
| 1854 | 1862 |
| 1855 blink::WebGraphicsContext3D* ResourceProvider::Context3d() const { | 1863 blink::WebGraphicsContext3D* ResourceProvider::Context3d() const { |
| 1856 ContextProvider* context_provider = output_surface_->context_provider(); | 1864 ContextProvider* context_provider = output_surface_->context_provider(); |
| 1857 return context_provider ? context_provider->Context3d() : NULL; | 1865 return context_provider ? context_provider->Context3d() : NULL; |
| 1858 } | 1866 } |
| 1859 | 1867 |
| 1860 } // namespace cc | 1868 } // namespace cc |
| OLD | NEW |