Merge branch 'devel/master' into tizen
[platform/core/uifw/dali-core.git] / dali / internal / update / resources / resource-manager.cpp
1 /*
2  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/update/resources/resource-manager.h>
20
21 // EXTERNAL INCLUDES
22 #include <stdio.h>
23
24 // INTERNAL INCLUDES
25 #include <dali/devel-api/common/map-wrapper.h>
26 #include <dali/devel-api/common/set-wrapper.h>
27
28 #include <dali/public-api/math/vector2.h>
29 #include <dali/public-api/common/dali-vector.h>
30
31 #include <dali/integration-api/debug.h>
32
33 #include <dali/internal/common/message.h>
34 #include <dali/internal/common/image-attributes.h>
35
36 #include <dali/internal/event/common/notification-manager.h>
37 #include <dali/internal/event/resources/resource-type-path.h>
38
39 #include <dali/internal/update/common/discard-queue.h>
40 #include <dali/internal/update/common/texture-cache-dispatcher.h>
41 #include <dali/internal/update/resources/texture-metadata.h>
42
43 #include <dali/internal/render/queue/render-queue.h>
44
45 using namespace Dali::Integration;
46
47 using Dali::Internal::SceneGraph::DiscardQueue;
48 using Dali::Internal::SceneGraph::RenderQueue;
49 using Dali::Internal::SceneGraph::TextureCacheDispatcher;
50
51
52 namespace Dali
53 {
54
55 namespace Internal
56 {
57
58 typedef std::set<ResourceId>                    LiveRequestContainer;
59 typedef LiveRequestContainer::iterator          LiveRequestIter;
60 typedef LiveRequestContainer::size_type         LiveRequestSize;
61
62 typedef std::map<ResourceId, ResourceTypeId>    DeadRequestContainer;
63 typedef DeadRequestContainer::iterator          DeadRequestIter;
64 typedef std::pair<ResourceId, ResourceTypeId>   DeadRequestPair;
65
66 typedef std::vector<ResourceId>                 NotifyQueue;
67 typedef NotifyQueue::iterator                   NotifyQueueIter;
68
69 typedef Dali::Vector<TextureMetadata>           TextureMetadataCache;
70 typedef TextureMetadataCache::Iterator          TextureMetadataIter;
71
72 static inline bool RemoveId( LiveRequestContainer& container, ResourceId id )
73 {
74   return container.erase(id) != 0;
75 }
76
77 struct ResourceManager::ResourceManagerImpl
78 {
79   ResourceManagerImpl( PlatformAbstraction& platformAbstraction,
80                        NotificationManager& notificationManager,
81                        SceneGraph::TextureCacheDispatcher& textureCacheDispatcher,
82                        LockedResourceQueue& textureUploadedQueue,
83                        DiscardQueue& discardQueue,
84                        RenderQueue& renderQueue )
85   : mPlatformAbstraction(platformAbstraction),
86     mNotificationManager(notificationManager),
87     mTextureCacheDispatcher(textureCacheDispatcher),
88     mTextureUploadedQueue(textureUploadedQueue),
89     mTextureUploadedProcessingQueue(),
90     mDiscardQueue(discardQueue),
91     mRenderQueue(renderQueue),
92     mNotificationCount(0),
93     cacheUpdated(false)
94   {
95     mTextureMetadata.Reserve( 256 ); // reserve size for metadata to avoid early re-allocs in application startup
96   }
97
98   ~ResourceManagerImpl()
99   {
100   }
101
102   PlatformAbstraction&        mPlatformAbstraction;
103   NotificationManager&        mNotificationManager;
104   TextureCacheDispatcher&     mTextureCacheDispatcher;
105   LockedResourceQueue&        mTextureUploadedQueue;
106   TextureUploadedQueue        mTextureUploadedProcessingQueue;
107   DiscardQueue&               mDiscardQueue; ///< Unwanted resources are added here during UpdateCache()
108   RenderQueue&                mRenderQueue;
109   unsigned int                mNotificationCount;
110   bool                        cacheUpdated; ///< returned by UpdateCache(). Set true in NotifyTickets to indicate a change in a resource
111
112   /**
113    * These containers are used to processs requests, and ResourceCache callbacks.
114    * The live request containers are simply sets of integer resource ids.
115    * The ID of a new request will be placed in the loading container.
116    * If the Ticket is destroyed during the load, the ID will be removed.
117    * If the load fails, the ID will be moved to the failed container.
118    * When the Ticket is notified of the failure, the ID will be removed.
119    * If the load succeeds, the ID will be moved to the new-completed container.
120    * When the Ticket is notified of the completion, the ID will be moved to the old-completed container.
121    * If a Ticket is destroyed after a successful load, the ID will be moved to the dead container.
122    * When the resources are eventually deleted, the ID will be removed from the dead container.
123    */
124   LiveRequestContainer loadingRequests;
125   LiveRequestContainer newCompleteRequests;
126   LiveRequestContainer oldCompleteRequests;
127   LiveRequestContainer newFailedRequests;
128   LiveRequestContainer oldFailedRequests;
129   DeadRequestContainer deadRequests;
130
131   /**
132    * This is the resource cache; metadata of the textures
133    */
134   TextureMetadataCache mTextureMetadata;
135 };
136
137 ResourceManager::ResourceManager( PlatformAbstraction& platformAbstraction,
138                                   NotificationManager& notificationManager,
139                                   TextureCacheDispatcher& textureCacheDispatcher,
140                                   LockedResourceQueue& resourcePostProcessQueue,
141                                   DiscardQueue& discardQueue,
142                                   RenderQueue& renderQueue )
143 {
144   mImpl = new ResourceManagerImpl( platformAbstraction,
145                                    notificationManager,
146                                    textureCacheDispatcher,
147                                    resourcePostProcessQueue,
148                                    discardQueue,
149                                    renderQueue );
150 }
151
152 ResourceManager::~ResourceManager()
153 {
154   delete mImpl;
155 }
156
157 /********************************************************************************
158  ************************ UpdateManager direct interface  ***********************
159  ********************************************************************************/
160
161 bool ResourceManager::UpdateCache( BufferIndex updateBufferIndex )
162 {
163   DALI_LOG_INFO(Debug::Filter::gResource, Debug::Verbose, "ResourceManager: UpdateCache(bufferIndex:%u)\n", updateBufferIndex);
164
165   // 1) Move unwanted resources to the DiscardQueue
166
167   DiscardDeadResources( updateBufferIndex );
168
169   // 2) Fill the resource cache
170   mImpl->cacheUpdated = false;
171
172   mImpl->mPlatformAbstraction.GetResources(*this);
173
174   return mImpl->cacheUpdated;
175 }
176
177 /********************************************************************************
178  *************************** CoreImpl direct interface  *************************
179  ********************************************************************************/
180
181 bool ResourceManager::ResourcesToProcess()
182 {
183   bool workTodo = false;
184
185   // need to make sure we have passed all the notifications to the event handling side
186   workTodo |= !mImpl->newCompleteRequests.empty();
187   workTodo |= !mImpl->newFailedRequests.empty();
188   // check if there's something still loading
189   workTodo |= !mImpl->loadingRequests.empty();
190
191   return workTodo;
192 }
193
194
195 /********************************************************************************
196  ********************************* Message handlers *****************************
197  ********************************************************************************/
198
199 void ResourceManager::HandleLoadResourceRequest( ResourceId id, const ResourceTypePath& typePath, LoadResourcePriority priority )
200 {
201   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleLoadResourceRequest(id:%u, path:%s, type.id:%d)\n", id, typePath.path.c_str(), typePath.type->id);
202
203   // Add ID to the loading set
204   mImpl->loadingRequests.insert(id);
205
206   // Make the load request last
207   mImpl->mPlatformAbstraction.LoadResource(ResourceRequest(id, *typePath.type, typePath.path, priority));
208 }
209
210 void ResourceManager::HandleDecodeResourceRequest(
211   ResourceId id,
212   const ResourceTypePath& typePath,
213   RequestBufferPtr buffer,
214   Integration::LoadResourcePriority priority )
215 {
216   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleDecodeResourceRequest(id:%u, buffer.size:%u, type.id:%u)\n", id, buffer->GetVector().Size(), typePath.type->id);
217
218   // Add ID to the loading set
219   mImpl->loadingRequests.insert(id);
220
221   // Make the load request, stuffing the buffer of encoded bytes into the same field used when saving resources:
222   mImpl->mPlatformAbstraction.LoadResource(ResourceRequest(id, *typePath.type, "", buffer, priority));
223 }
224
225 void ResourceManager::HandleAddBitmapImageRequest( ResourceId id, BitmapPtr bitmap )
226 {
227   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleAddBitmapImageRequest(id:%u)\n", id);
228
229   mImpl->oldCompleteRequests.insert(id);
230   mImpl->mTextureMetadata.PushBack( TextureMetadata::New( id, bitmap.Get() ) );
231   mImpl->mTextureCacheDispatcher.DispatchCreateTextureForBitmap( id, bitmap.Get() );
232 }
233
234 void ResourceManager::HandleAddNativeImageRequest(ResourceId id, NativeImageInterfacePtr nativeImage)
235 {
236   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleAddNativeImageRequest(id:%u)\n", id);
237
238   mImpl->oldCompleteRequests.insert(id);
239
240   mImpl->mTextureMetadata.PushBack( TextureMetadata::New( id, nativeImage ) );
241   mImpl->mTextureCacheDispatcher.DispatchCreateTextureForNativeImage( id, nativeImage );
242 }
243
244 void ResourceManager::HandleAddFrameBufferImageRequest( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat )
245 {
246   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleAddFrameBufferImageRequest(id:%u)\n", id);
247
248   mImpl->oldCompleteRequests.insert(id);
249
250   TextureMetadata bitmapMetadata = TextureMetadata::New( id, width, height, Pixel::HasAlpha(pixelFormat) );
251   bitmapMetadata.SetIsFramebuffer(true);
252   mImpl->mTextureMetadata.PushBack( bitmapMetadata );
253
254   mImpl->mTextureCacheDispatcher.DispatchCreateTextureForFrameBuffer( id, width, height, pixelFormat, bufferFormat );
255 }
256
257 void ResourceManager::HandleAddFrameBufferImageRequest( ResourceId id, NativeImageInterfacePtr nativeImage )
258 {
259   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleAddFrameBufferImageRequest(id:%u)\n", id);
260
261   mImpl->oldCompleteRequests.insert(id);
262
263   TextureMetadata bitmapMetadata = TextureMetadata::New(id, nativeImage);
264   bitmapMetadata.SetIsNativeImage(true);
265   bitmapMetadata.SetIsFramebuffer(true);
266   mImpl->mTextureMetadata.PushBack( bitmapMetadata );
267
268   mImpl->mTextureCacheDispatcher.DispatchCreateTextureForFrameBuffer( id, nativeImage );
269 }
270
271 void ResourceManager::HandleAllocateTextureRequest( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat )
272 {
273   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleAllocateTextureRequest(id:%u)\n", id);
274
275   mImpl->oldCompleteRequests.insert(id);
276   // atlas needs metadata as well
277   TextureMetadata bitmapMetadata = TextureMetadata::New( id, width, height, Pixel::HasAlpha(pixelFormat) );
278   mImpl->mTextureMetadata.PushBack( bitmapMetadata );
279
280   mImpl->mTextureCacheDispatcher.DispatchCreateTexture( id, width, height, pixelFormat, true /* true = clear the texture */ );
281 }
282
283 void ResourceManager::HandleUpdateBitmapAreaRequest( ResourceId textureId, const RectArea& area )
284 {
285   if( textureId )
286   {
287     mImpl->mTextureCacheDispatcher.DispatchUpdateTextureArea( textureId, area );
288   }
289 }
290
291 void ResourceManager::HandleUploadBitmapRequest( ResourceId destId, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset )
292 {
293   if( destId && bitmap )
294   {
295     mImpl->mTextureCacheDispatcher.DispatchUpdateTexture( destId, bitmap, xOffset, yOffset );
296   }
297 }
298
299 void ResourceManager::HandleUploadBitmapRequest( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
300 {
301   if( destId && srcId )
302   {
303     mImpl->mTextureCacheDispatcher.DispatchUpdateTexture( destId, srcId, xOffset, yOffset );
304   }
305 }
306
307 void ResourceManager::HandleUploadBitmapRequest( ResourceId destId, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset )
308 {
309   if( destId && pixelData )
310   {
311     mImpl->mTextureCacheDispatcher.DispatchUpdateTexture( destId, pixelData, xOffset, yOffset );
312   }
313 }
314
315 void ResourceManager::HandleReloadResourceRequest( ResourceId id, const ResourceTypePath& typePath, LoadResourcePriority priority, bool resetFinishedStatus )
316 {
317   DALI_LOG_INFO( Debug::Filter::gResource, Debug::General, "ResourceManager: HandleReloadRequest(id:%u, path:%s)\n", id, typePath.path.c_str() );
318
319   if( resetFinishedStatus )
320   {
321     if( ! RemoveId( mImpl->newCompleteRequests, id ) )
322     {
323       RemoveId( mImpl->oldCompleteRequests, id );
324     }
325   }
326
327   // ID might be in the loading set
328   LiveRequestIter iter = mImpl->loadingRequests.find( id );
329   if ( iter == mImpl->loadingRequests.end() )
330   {
331     // Add ID to the loading set
332     mImpl->loadingRequests.insert(id);
333   }
334 }
335
336 void ResourceManager::HandleDiscardResourceRequest( ResourceId deadId, ResourceTypeId typeId )
337 {
338   bool wasComplete = false;
339   bool wasLoading = false;
340
341   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleDiscardResourceRequest(id:%u)\n", deadId);
342
343   // Search for the ID in one of the live containers
344   // IDs are only briefly held in the new-completed or failed containers; check those last
345   // Try removing from the old-completed requests
346   bool foundLiveRequest = wasComplete = RemoveId(mImpl->oldCompleteRequests, deadId);
347
348   // Try removing from the loading requests
349   if (!foundLiveRequest)
350   {
351     foundLiveRequest = wasLoading = RemoveId(mImpl->loadingRequests, deadId);
352   }
353
354   // Try removing from the new completed requests
355   if (!foundLiveRequest)
356   {
357     foundLiveRequest = wasComplete = RemoveId(mImpl->newCompleteRequests, deadId);
358   }
359
360   // Try removing from the new failed requests
361   if (!foundLiveRequest)
362   {
363     foundLiveRequest = RemoveId(mImpl->newFailedRequests, deadId);
364   }
365
366   // Try removing from the old failed requests
367   if (!foundLiveRequest)
368   {
369     foundLiveRequest = RemoveId(mImpl->oldFailedRequests, deadId);
370   }
371
372   // ID should be in one of the live sets
373   if (!foundLiveRequest)
374   {
375     DALI_LOG_WARNING("HandleDiscardResourceRequest: ID should be in one of the live sets!\n");
376   }
377   DALI_ASSERT_DEBUG(foundLiveRequest);
378
379   if (wasComplete)
380   {
381     if(typeId == ResourceBitmap ||
382        typeId == ResourceNativeImage ||
383        typeId == ResourceTargetImage )
384     {
385       // remove the meta data
386
387       TextureMetadataCache::Iterator iter = mImpl->mTextureMetadata.Begin();
388       const TextureMetadataCache::Iterator end = mImpl->mTextureMetadata.End();
389       for( ; iter != end; ++iter )
390       {
391         if( (*iter).GetId() == deadId )
392         {
393           break;
394         }
395       }
396       if( iter != end )
397       {
398         mImpl->mTextureMetadata.Erase( iter );
399       }
400
401       // destroy the texture
402       mImpl->mTextureCacheDispatcher.DispatchDiscardTexture( deadId );
403     }
404     else
405     {
406       // Move ID from completed to dead set
407       mImpl->deadRequests.insert(DeadRequestPair(deadId, typeId));
408     }
409   }
410
411   if (wasLoading)
412   {
413     mImpl->mPlatformAbstraction.CancelLoad(deadId, typeId);
414   }
415 }
416
417 void ResourceManager::HandleCreateGlTextureRequest(ResourceId id)
418 {
419   mImpl->mTextureCacheDispatcher.DispatchCreateGlTexture( id );
420 }
421
422 /********************************************************************************
423  ******************** Update thread object direct interface  ********************
424  ********************************************************************************/
425
426 bool ResourceManager::IsResourceLoaded( ResourceId id ) const
427 {
428   bool loaded = false;
429
430   if( id > 0 )
431   {
432     LiveRequestIter iter = mImpl->newCompleteRequests.find(id);
433     if( iter != mImpl->newCompleteRequests.end() )
434     {
435       loaded = true;
436     }
437     else
438     {
439       iter = mImpl->oldCompleteRequests.find(id);
440       if( iter != mImpl->oldCompleteRequests.end() )
441       {
442         loaded = true;
443       }
444     }
445   }
446
447   return loaded;
448 }
449
450 bool ResourceManager::HasResourceLoadFailed( ResourceId id ) const
451 {
452   bool loadFailed = false;
453
454   if( id > 0 )
455   {
456     LiveRequestIter iter = mImpl->newFailedRequests.find(id);
457     if( iter != mImpl->newFailedRequests.end() )
458     {
459       loadFailed = true;
460     }
461     else
462     {
463       iter = mImpl->oldFailedRequests.find(id);
464       if( iter != mImpl->oldFailedRequests.end() )
465       {
466         loadFailed = true;
467       }
468     }
469   }
470
471   return loadFailed;
472 }
473
474 void ResourceManager::SetFrameBufferBeenRenderedTo( ResourceId id, bool value )
475 {
476   TextureMetadata* metadata = NULL;
477   if( GetTextureMetadata( id, metadata ) )
478   {
479     metadata->SetFrameBufferBeenRenderedTo( value );
480   }
481 }
482
483 bool ResourceManager::HasFrameBufferBeenRenderedTo( ResourceId id ) const
484 {
485   bool retval( false );
486   TextureMetadata* metadata = NULL;
487   if( GetTextureMetadata( id, metadata ) )
488   {
489     retval = metadata->HasFrameBufferBeenRenderedTo();
490   }
491   return retval;
492 }
493
494 bool ResourceManager::GetTextureMetadata( ResourceId id, TextureMetadata*& metadata ) const
495 {
496   if( id > 0 )
497   {
498     const size_t count = mImpl->mTextureMetadata.Count();
499     for( size_t index = 0; index < count; ++index )
500     {
501       if( id == mImpl->mTextureMetadata[ index ].GetId() )
502       {
503         metadata = &mImpl->mTextureMetadata[ index ];
504         return true;
505       }
506     }
507   }
508
509   return false;
510 }
511
512 /********************************************************************************
513  ************************* ResourceCache Implementation  ************************
514  ********************************************************************************/
515
516 void ResourceManager::LoadResponse( ResourceId id, ResourceTypeId type, ResourcePointer resource, LoadStatus loadStatus )
517 {
518   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: LoadResponse(id:%u, status=%s)\n", id, loadStatus==RESOURCE_LOADING?"LOADING":loadStatus==RESOURCE_PARTIALLY_LOADED?"PARTIAL":"COMPLETE");
519
520   // ID might be in the loading set
521   LiveRequestIter iter = mImpl->loadingRequests.find(id);
522
523   if ( iter != mImpl->loadingRequests.end() )
524   {
525     if( loadStatus == RESOURCE_COMPLETELY_LOADED )
526     {
527       // Remove from the loading set
528       mImpl->loadingRequests.erase(iter);
529
530       // Add the ID to the new-completed set, and store the resource
531       mImpl->newCompleteRequests.insert(id);
532     }
533
534     switch ( type )
535     {
536       case ResourceBitmap:
537       {
538         DALI_ASSERT_DEBUG( loadStatus == RESOURCE_COMPLETELY_LOADED && "Partial results not handled for image loading.\n" );
539         Bitmap* const bitmap = static_cast<Bitmap*>( resource.Get() );
540         if( !bitmap )
541         {
542           DALI_LOG_ERROR( "Missing bitmap in loaded resource with id %u.\n", id );
543           break;
544         }
545         unsigned int bitmapWidth  = bitmap->GetImageWidth();
546         unsigned int bitmapHeight = bitmap->GetImageHeight();
547
548         if( Bitmap::PackedPixelsProfile * packedBitmap = bitmap->GetPackedPixelsProfile() )
549         {
550           bitmapWidth  = packedBitmap->GetBufferWidth();
551           bitmapHeight = packedBitmap->GetBufferHeight();
552         }
553         ImageAttributes attrs = ImageAttributes::New( bitmapWidth, bitmapHeight ); ///!< Issue #AHC01
554
555         // Check for reloaded bitmap
556         TextureMetadataCache::Iterator iter = mImpl->mTextureMetadata.Begin();
557         const TextureMetadataCache::Iterator end = mImpl->mTextureMetadata.End();
558         for( ; iter != end; ++iter )
559         {
560           if( (*iter).GetId() == id )
561           {
562             break;
563           }
564         }
565         if( iter != end )
566         {
567           iter->Update( bitmap );
568           mImpl->mTextureCacheDispatcher.DispatchUpdateTexture( id, bitmap );
569         }
570         else
571         {
572           mImpl->mTextureCacheDispatcher.DispatchCreateTextureForBitmap( id, bitmap );
573           mImpl->mTextureMetadata.PushBack( TextureMetadata::New( id, bitmap ) );
574         }
575
576         break;
577       }
578
579       case ResourceNativeImage:
580       {
581         NativeImageInterfacePtr nativeImg( static_cast<NativeImageInterface*>(resource.Get()) );
582
583         ImageAttributes attrs = ImageAttributes::New(nativeImg->GetWidth(), nativeImg->GetHeight());
584
585         mImpl->mTextureMetadata.PushBack( TextureMetadata::New( id, nativeImg ) );
586         mImpl->mTextureCacheDispatcher.DispatchCreateTextureForNativeImage( id, nativeImg );
587
588         break;
589       }
590
591       case ResourceTargetImage:
592       {
593         break;
594       }
595     }
596
597     // flag that a load has completed and the cache updated
598     mImpl->cacheUpdated = true;
599   }
600   else
601   {
602     // This warning can fire if a cancelled load is forgotten here while already complete on a resource thread:
603     DALI_LOG_WARNING( "Received a notification for an untracked resource: (id:%u, status=%s)\n", id, loadStatus==RESOURCE_LOADING?"LOADING":loadStatus==RESOURCE_PARTIALLY_LOADED?"PARTIAL":"COMPLETE");
604   }
605 }
606
607 void ResourceManager::LoadFailed(ResourceId id, ResourceFailure failure)
608 {
609   DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: LoadFailed(id:%u)\n", id);
610
611   // ID might be in the loading set
612   LiveRequestIter iter = mImpl->loadingRequests.find(id);
613
614   if (iter != mImpl->loadingRequests.end())
615   {
616     // Remove from the loading set
617     mImpl->loadingRequests.erase(iter);
618
619     // Add the ID to the failed set, this will trigger a notification during UpdateTickets
620     mImpl->newFailedRequests.insert(id);
621
622     mImpl->cacheUpdated = true;
623   }
624 }
625
626 /********************************************************************************
627  ********************************* Private Methods  *****************************
628  ********************************************************************************/
629
630 void ResourceManager::DiscardDeadResources( BufferIndex updateBufferIndex )
631 {
632   for (DeadRequestIter iter = mImpl->deadRequests.begin(); iter != mImpl->deadRequests.end(); )
633   {
634     // Erase the item and increment the iterator
635     mImpl->deadRequests.erase(iter++);
636   }
637 }
638
639 } // namespace Internal
640
641 } // namespace Dali