2 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <dali/internal/update/resources/resource-manager.h>
26 #include <dali/devel-api/common/map-wrapper.h>
27 #include <dali/devel-api/common/set-wrapper.h>
28 #include <dali/public-api/math/vector2.h>
30 #include <dali/integration-api/debug.h>
32 #include <dali/internal/common/message.h>
33 #include <dali/internal/common/image-attributes.h>
35 #include <dali/internal/event/common/notification-manager.h>
36 #include <dali/internal/event/resources/resource-type-path.h>
37 #include <dali/internal/event/resources/resource-client.h>
39 #include <dali/internal/update/modeling/scene-graph-mesh.h>
40 #include <dali/internal/update/common/discard-queue.h>
41 #include <dali/internal/update/resources/bitmap-metadata.h>
42 #include <dali/internal/render/queue/render-queue.h>
44 #include <dali/internal/render/common/texture-cache-dispatcher.h>
45 #include <dali/internal/render/common/post-process-resource-dispatcher.h>
47 using namespace Dali::Integration;
49 using Dali::Internal::SceneGraph::DiscardQueue;
50 using Dali::Internal::SceneGraph::RenderQueue;
51 using Dali::Internal::SceneGraph::TextureCacheDispatcher;
58 typedef std::set<ResourceId> LiveRequestContainer;
59 typedef LiveRequestContainer::iterator LiveRequestIter;
60 typedef LiveRequestContainer::size_type LiveRequestSize;
62 typedef std::map<ResourceId, ResourceTypeId> DeadRequestContainer;
63 typedef DeadRequestContainer::iterator DeadRequestIter;
64 typedef std::pair<ResourceId, ResourceTypeId> DeadRequestPair;
66 typedef std::vector<ResourceId> NotifyQueue;
67 typedef NotifyQueue::iterator NotifyQueueIter;
69 typedef std::map<ResourceId, BitmapMetadata> BitmapMetadataCache;
70 typedef BitmapMetadataCache::iterator BitmapMetadataIter;
71 typedef std::pair<ResourceId, BitmapMetadata> BitmapMetadataPair;
73 typedef std::map<ResourceId, SceneGraph::Mesh*> MeshCache;
74 typedef MeshCache::iterator MeshCacheIter;
75 typedef std::pair<ResourceId, SceneGraph::Mesh*> MeshDataPair;
77 typedef std::map<ResourceId, ShaderDataPtr> ShaderCache;
78 typedef ShaderCache::iterator ShaderCacheIter;
79 typedef ShaderCache::size_type ShaderCacheSize;
80 typedef std::pair<ResourceId, ShaderDataPtr> ShaderDataPair;
82 static inline bool RemoveId( LiveRequestContainer& container, ResourceId id )
84 return container.erase(id) != 0;
87 struct ResourceManager::ResourceManagerImpl
89 ResourceManagerImpl( PlatformAbstraction& platformAbstraction,
90 NotificationManager& notificationManager,
91 SceneGraph::TextureCacheDispatcher& textureCacheDispatcher,
92 ResourcePostProcessList& resourcePostProcessQueue,
93 SceneGraph::PostProcessResourceDispatcher& postProcessResourceDispatcher,
94 DiscardQueue& discardQueue,
95 RenderQueue& renderQueue )
96 : mPlatformAbstraction(platformAbstraction),
97 mNotificationManager(notificationManager),
98 mResourceClient(NULL),
99 mTextureCacheDispatcher(textureCacheDispatcher),
100 mResourcePostProcessQueue(resourcePostProcessQueue),
101 mPostProcessResourceDispatcher(postProcessResourceDispatcher),
102 mDiscardQueue(discardQueue),
103 mRenderQueue(renderQueue),
104 mNotificationCount(0),
109 ~ResourceManagerImpl()
111 // Cleanup existing meshes
112 for( MeshCacheIter it = mMeshes.begin();
120 PlatformAbstraction& mPlatformAbstraction;
121 NotificationManager& mNotificationManager;
122 ResourceClient* mResourceClient; // (needs to be a ptr - it's not instantiated yet)
123 TextureCacheDispatcher& mTextureCacheDispatcher;
124 ResourcePostProcessList& mResourcePostProcessQueue;
125 SceneGraph::PostProcessResourceDispatcher& mPostProcessResourceDispatcher;
126 DiscardQueue& mDiscardQueue; ///< Unwanted resources are added here during UpdateCache()
127 RenderQueue& mRenderQueue;
128 unsigned int mNotificationCount;
129 bool cacheUpdated; ///< returned by UpdateCache(). Set true in NotifyTickets to indicate a change in a resource
132 * These containers are used to processs requests, and ResourceCache callbacks.
133 * The live request containers are simply sets of integer resource ids.
134 * The ID of a new request will be placed in the loading container.
135 * If the Ticket is destroyed during the load, the ID will be removed.
136 * If the load fails, the ID will be moved to the failed container.
137 * When the Ticket is notified of the failure, the ID will be removed.
138 * If the load succeeds, the ID will be moved to the new-completed container.
139 * When the Ticket is notified of the completion, the ID will be moved to the old-completed container.
140 * If a Ticket is destroyed after a successful load, the ID will be moved to the dead container.
141 * When the resources are eventually deleted, the ID will be removed from the dead container.
143 LiveRequestContainer loadingRequests;
144 LiveRequestContainer newCompleteRequests;
145 LiveRequestContainer oldCompleteRequests;
146 LiveRequestContainer newFailedRequests;
147 LiveRequestContainer oldFailedRequests;
148 DeadRequestContainer deadRequests;
149 LiveRequestContainer saveRequests; ///< copy of id's being saved (must also be in newCompleteRequests or oldCompleteRequests)
150 LiveRequestContainer completeSaveRequests; ///< successful save ids are moved from saveRequests to here
153 * This is the resource cache. It's filled/emptied from within Core::Update()
155 BitmapMetadataCache mBitmapMetadata;
157 ShaderCache mShaders;
160 ResourceManager::ResourceManager( PlatformAbstraction& platformAbstraction,
161 NotificationManager& notificationManager,
162 TextureCacheDispatcher& textureCacheDispatcher,
163 ResourcePostProcessList& resourcePostProcessQueue,
164 SceneGraph::PostProcessResourceDispatcher& postProcessResourceDispatcher,
165 DiscardQueue& discardQueue,
166 RenderQueue& renderQueue )
168 mImpl = new ResourceManagerImpl( platformAbstraction,
170 textureCacheDispatcher,
171 resourcePostProcessQueue,
172 postProcessResourceDispatcher,
177 ResourceManager::~ResourceManager()
182 /********************************************************************************
183 ************************ ResourceClient direct interface **********************
184 ********************************************************************************/
186 void ResourceManager::SetClient( ResourceClient& client )
188 mImpl->mResourceClient = &client;
191 /********************************************************************************
192 ************************ UpdateManager direct interface ***********************
193 ********************************************************************************/
195 bool ResourceManager::UpdateCache( BufferIndex updateBufferIndex )
197 DALI_LOG_INFO(Debug::Filter::gResource, Debug::Verbose, "ResourceManager: UpdateCache(bufferIndex:%u)\n", updateBufferIndex);
199 // 1) Move unwanted resources to the DiscardQueue
201 DiscardDeadResources( updateBufferIndex );
203 // 2) Fill the resource cache
204 mImpl->cacheUpdated = false;
206 mImpl->mPlatformAbstraction.GetResources(*this);
208 return mImpl->cacheUpdated;
211 void ResourceManager::PostProcessResources( BufferIndex updateBufferIndex )
213 DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
214 DALI_LOG_INFO(Debug::Filter::gResource, Debug::Verbose, "ResourceManager: PostProcessResources()\n");
216 unsigned int numIds = mImpl->mResourcePostProcessQueue[ updateBufferIndex ].size();
219 // process the list where RenderManager put post process requests
220 for (i = 0; i < numIds; ++i)
222 ResourcePostProcessRequest ppRequest = mImpl->mResourcePostProcessQueue[ updateBufferIndex ][i];
223 switch(ppRequest.postProcess)
225 case ResourcePostProcessRequest::UPLOADED:
227 SendToClient( UploadedMessage( *mImpl->mResourceClient, ppRequest.id ) );
230 case ResourcePostProcessRequest::SAVE:
232 SendToClient( SaveResourceMessage( *mImpl->mResourceClient, ppRequest.id ) );
236 case ResourcePostProcessRequest::DELETED:
238 // TextureObservers handled in TextureCache
244 mImpl->mResourcePostProcessQueue[ updateBufferIndex ].clear();
248 /********************************************************************************
249 *************************** CoreImpl direct interface *************************
250 ********************************************************************************/
252 bool ResourceManager::ResourcesToProcess()
254 bool workTodo = false;
256 // need to make sure we have passed all the notifications to the event handling side
257 workTodo |= !mImpl->newCompleteRequests.empty();
258 workTodo |= !mImpl->newFailedRequests.empty();
259 // check if there's something still loading
260 workTodo |= !mImpl->loadingRequests.empty();
261 workTodo |= !mImpl->saveRequests.empty();
267 /********************************************************************************
268 ********************************* Message handlers *****************************
269 ********************************************************************************/
271 void ResourceManager::HandleLoadResourceRequest( ResourceId id, const ResourceTypePath& typePath, LoadResourcePriority priority )
273 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);
275 // Add ID to the loading set
276 mImpl->loadingRequests.insert(id);
278 // Make the load request last
279 mImpl->mPlatformAbstraction.LoadResource(ResourceRequest(id, *typePath.type, typePath.path, priority));
282 void ResourceManager::HandleDecodeResourceRequest(
284 const ResourceTypePath& typePath,
285 RequestBufferPtr buffer,
286 Integration::LoadResourcePriority priority )
288 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);
290 // Add ID to the loading set
291 mImpl->loadingRequests.insert(id);
293 // Make the load request, stuffing the buffer of encoded bytes into the same field used when saving resources:
294 mImpl->mPlatformAbstraction.LoadResource(ResourceRequest(id, *typePath.type, "", buffer, priority));
297 void ResourceManager::HandleAddBitmapImageRequest( ResourceId id, BitmapPtr bitmap )
299 DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
300 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleAddBitmapImageRequest(id:%u)\n", id);
302 mImpl->oldCompleteRequests.insert(id);
303 mImpl->mBitmapMetadata.insert(BitmapMetadataPair(id, BitmapMetadata::New( bitmap.Get() )));
304 mImpl->mTextureCacheDispatcher.DispatchCreateTextureForBitmap( id, bitmap.Get() );
307 void ResourceManager::HandleAddNativeImageRequest(ResourceId id, NativeImageInterfacePtr nativeImage)
309 DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
310 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleAddNativeImageRequest(id:%u)\n", id);
312 mImpl->oldCompleteRequests.insert(id);
314 mImpl->mBitmapMetadata.insert(BitmapMetadataPair(id, BitmapMetadata::New(nativeImage)));
315 mImpl->mTextureCacheDispatcher.DispatchCreateTextureForNativeImage( id, nativeImage );
318 void ResourceManager::HandleAddFrameBufferImageRequest( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat )
320 DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
321 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleAddFrameBufferImageRequest(id:%u)\n", id);
323 mImpl->oldCompleteRequests.insert(id);
325 BitmapMetadata bitmapMetadata = BitmapMetadata::New(width, height, Pixel::HasAlpha(pixelFormat));
326 bitmapMetadata.SetIsFramebuffer(true);
327 mImpl->mBitmapMetadata.insert(BitmapMetadataPair(id, bitmapMetadata));
329 mImpl->mTextureCacheDispatcher.DispatchCreateTextureForFrameBuffer( id, width, height, pixelFormat );
332 void ResourceManager::HandleAddFrameBufferImageRequest( ResourceId id, NativeImageInterfacePtr nativeImage )
334 DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
335 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleAddFrameBufferImageRequest(id:%u)\n", id);
337 mImpl->oldCompleteRequests.insert(id);
339 BitmapMetadata bitmapMetadata = BitmapMetadata::New(nativeImage);
340 bitmapMetadata.SetIsNativeImage(true);
341 bitmapMetadata.SetIsFramebuffer(true);
342 mImpl->mBitmapMetadata.insert(BitmapMetadataPair(id, bitmapMetadata));
344 mImpl->mTextureCacheDispatcher.DispatchCreateTextureForFrameBuffer( id, nativeImage );
347 void ResourceManager::HandleAllocateTextureRequest( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat )
349 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleAllocateTextureRequest(id:%u)\n", id);
351 mImpl->oldCompleteRequests.insert(id);
352 mImpl->mTextureCacheDispatcher.DispatchCreateTexture( id, width, height, pixelFormat, true /* true = clear the texture */ );
355 void ResourceManager::HandleAllocateMeshRequest( ResourceId id, MeshData* meshData )
357 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleAllocateMeshRequest(id:%u)\n", id);
359 SceneGraph::Mesh* renderableMesh(SceneGraph::Mesh::New(id, mImpl->mPostProcessResourceDispatcher, mImpl->mRenderQueue, meshData));
361 DALI_ASSERT_ALWAYS(renderableMesh && "renderableMesh not created");
363 // Add the ID to the completed set, and store the resource
364 mImpl->newCompleteRequests.insert(id);
365 mImpl->mMeshes.insert(MeshDataPair(id, renderableMesh));
367 // Let NotificationManager know that the resource manager needs to do some processing
371 void ResourceManager::HandleLoadShaderRequest( ResourceId id, const ResourceTypePath& typePath )
373 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleLoadShaderRequest(id:%u, path:%s)\n", id, typePath.path.c_str());
375 const ShaderResourceType* shaderType = dynamic_cast<const ShaderResourceType*>(typePath.type);
376 DALI_ASSERT_DEBUG(shaderType);
380 ShaderDataPtr shaderData(new ShaderData(shaderType->vertexShader, shaderType->fragmentShader));
382 mImpl->mPlatformAbstraction.LoadShaderBinFile(typePath.path, shaderData->GetBuffer());
384 // Add the ID to the completed set
385 mImpl->newCompleteRequests.insert(id);
387 // Cache the resource
388 mImpl->mShaders.insert(ShaderDataPair(id, shaderData));
390 // Let NotificationManager know that the resource manager needs to do some processing
395 void ResourceManager::HandleUpdateBitmapAreaRequest( ResourceId textureId, const RectArea& area )
399 mImpl->mTextureCacheDispatcher.DispatchUpdateTextureArea( textureId, area );
403 void ResourceManager::HandleUploadBitmapRequest( ResourceId destId, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset )
405 if( destId && bitmap )
407 mImpl->mTextureCacheDispatcher.DispatchUpdateTexture( destId, bitmap, xOffset, yOffset );
411 void ResourceManager::HandleUploadBitmapRequest( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
413 if( destId && srcId )
415 mImpl->mTextureCacheDispatcher.DispatchUpdateTexture( destId, srcId, xOffset, yOffset );
419 void ResourceManager::HandleUpdateMeshRequest( BufferIndex updateBufferIndex, ResourceId id, MeshData* meshData )
421 DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
422 SceneGraph::Mesh* mesh = GetMesh( id );
423 DALI_ASSERT_DEBUG(mesh);
425 // Update the mesh data
426 mesh->SetMeshData( meshData );
428 // Update the GL buffers in the next Render
429 typedef MessageDoubleBuffered2< SceneGraph::Mesh, SceneGraph::Mesh::ThreadBuffer, OwnerPointer<MeshData> > DerivedType;
431 // Reserve some memory inside the render queue
432 unsigned int* slot = mImpl->mRenderQueue.ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
434 // Construct message in the mRenderer queue memory; note that delete should not be called on the return value
435 new (slot) DerivedType( mesh, &SceneGraph::Mesh::MeshDataUpdated, SceneGraph::Mesh::RENDER_THREAD, meshData );
438 void ResourceManager::HandleReloadResourceRequest( ResourceId id, const ResourceTypePath& typePath, LoadResourcePriority priority, bool resetFinishedStatus )
440 DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
441 DALI_LOG_INFO( Debug::Filter::gResource, Debug::General, "ResourceManager: HandleReloadRequest(id:%u, path:%s)\n", id, typePath.path.c_str() );
443 bool resourceIsAlreadyLoading = true;
445 if( resetFinishedStatus )
447 if( ! RemoveId( mImpl->newCompleteRequests, id ) )
449 RemoveId( mImpl->oldCompleteRequests, id );
453 // ID might be in the loading set
454 LiveRequestIter iter = mImpl->loadingRequests.find( id );
455 if ( iter == mImpl->loadingRequests.end() )
457 // Add ID to the loading set
458 mImpl->loadingRequests.insert(id);
459 resourceIsAlreadyLoading = false;
462 if ( !resourceIsAlreadyLoading )
464 // load resource again
465 mImpl->mPlatformAbstraction.LoadResource(ResourceRequest(id, *typePath.type, typePath.path, priority));
466 SendToClient( LoadingMessage( *mImpl->mResourceClient, id ) );
470 void ResourceManager::HandleSaveResourceRequest( ResourceId id, const ResourceTypePath& typePath )
472 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleSaveResourceRequest(id:%u, path:%s)\n", id, typePath.path.c_str());
474 bool resourceFound = false;
476 // ID must be in the complete sets
477 LiveRequestIter iter = mImpl->newCompleteRequests.find(id);
478 if (iter != mImpl->newCompleteRequests.end())
480 resourceFound = true;
484 LiveRequestIter iter = mImpl->oldCompleteRequests.find(id);
485 if (iter != mImpl->oldCompleteRequests.end())
487 resourceFound = true;
493 ResourcePointer resource;
494 DALI_ASSERT_DEBUG( typePath.type != NULL );
496 switch( typePath.type->id )
502 case ResourceNativeImage:
506 case ResourceTargetImage:
512 resource = GetShaderData(id);
521 if( resource ) // i.e. if it's a saveable resource
523 mImpl->saveRequests.insert(id);
525 ResourceRequest request(id, *typePath.type, typePath.path, resource);
526 mImpl->mPlatformAbstraction.SaveResource(request);
531 void ResourceManager::HandleDiscardResourceRequest( ResourceId deadId, ResourceTypeId typeId )
533 bool wasComplete = false;
534 bool wasLoading = false;
536 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleDiscardResourceRequest(id:%u)\n", deadId);
538 // remove copies of the deadId from completed/failed saving sets
539 RemoveId(mImpl->completeSaveRequests, deadId);
541 // Search for the ID in one of the live containers
542 // IDs are only briefly held in the new-completed or failed containers; check those last
543 // Try removing from the old-completed requests
544 bool foundLiveRequest = wasComplete = RemoveId(mImpl->oldCompleteRequests, deadId);
546 // Try removing from the loading requests
547 if (!foundLiveRequest)
549 foundLiveRequest = wasLoading = RemoveId(mImpl->loadingRequests, deadId);
552 // Try removing from the new completed requests
553 if (!foundLiveRequest)
555 foundLiveRequest = wasComplete = RemoveId(mImpl->newCompleteRequests, deadId);
558 // Try removing from the new failed requests
559 if (!foundLiveRequest)
561 foundLiveRequest = RemoveId(mImpl->newFailedRequests, deadId);
564 // Try removing from the old failed requests
565 if (!foundLiveRequest)
567 foundLiveRequest = RemoveId(mImpl->oldFailedRequests, deadId);
570 // ID should be in one of the live sets
571 if (!foundLiveRequest)
573 DALI_LOG_WARNING("HandleDiscardResourceRequest: ID should be in one of the live sets!\n");
575 DALI_ASSERT_DEBUG(foundLiveRequest);
579 if(typeId == ResourceBitmap ||
580 typeId == ResourceNativeImage ||
581 typeId == ResourceTargetImage )
583 // remove the meta data
584 mImpl->mBitmapMetadata.erase( deadId );
586 // destroy the texture
587 mImpl->mTextureCacheDispatcher.DispatchDiscardTexture( deadId );
591 // Move ID from completed to dead set
592 mImpl->deadRequests.insert(DeadRequestPair(deadId, typeId));
598 mImpl->mPlatformAbstraction.CancelLoad(deadId, typeId);
602 void ResourceManager::HandleCreateGlTextureRequest(ResourceId id)
604 mImpl->mTextureCacheDispatcher.DispatchCreateGlTexture( id );
607 /********************************************************************************
608 ******************** Update thread object direct interface ********************
609 ********************************************************************************/
611 bool ResourceManager::IsResourceLoaded(ResourceId id)
617 LiveRequestIter iter = mImpl->newCompleteRequests.find(id);
618 if( iter != mImpl->newCompleteRequests.end() )
624 iter = mImpl->oldCompleteRequests.find(id);
625 if( iter != mImpl->oldCompleteRequests.end() )
635 bool ResourceManager::IsResourceLoadFailed(ResourceId id)
637 bool loadFailed = false;
641 LiveRequestIter iter = mImpl->newFailedRequests.find(id);
642 if( iter != mImpl->newFailedRequests.end() )
648 iter = mImpl->oldFailedRequests.find(id);
649 if( iter != mImpl->oldFailedRequests.end() )
659 BitmapMetadata ResourceManager::GetBitmapMetadata(ResourceId id)
661 BitmapMetadata metadata;
665 BitmapMetadataIter iter = mImpl->mBitmapMetadata.find(id);
666 if( iter != mImpl->mBitmapMetadata.end() )
668 metadata = iter->second;
675 Internal::SceneGraph::Mesh* ResourceManager::GetMesh(ResourceId id)
677 SceneGraph::Mesh* mesh = NULL;
678 MeshCacheIter iter = mImpl->mMeshes.find(id);
680 if (iter != mImpl->mMeshes.end())
688 ShaderDataPtr ResourceManager::GetShaderData(ResourceId id)
690 ShaderDataPtr shaderData;
691 ShaderCacheIter iter = mImpl->mShaders.find(id);
692 if(iter != mImpl->mShaders.end())
694 shaderData = iter->second;
699 /********************************************************************************
700 ************************* ResourceCache Implementation ************************
701 ********************************************************************************/
703 void ResourceManager::LoadResponse( ResourceId id, ResourceTypeId type, ResourcePointer resource, LoadStatus loadStatus )
705 DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
706 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");
708 // ID might be in the loading set
709 LiveRequestIter iter = mImpl->loadingRequests.find(id);
711 if ( iter != mImpl->loadingRequests.end() )
713 if( loadStatus == RESOURCE_COMPLETELY_LOADED )
715 // Remove from the loading set
716 mImpl->loadingRequests.erase(iter);
718 // Add the ID to the new-completed set, and store the resource
719 mImpl->newCompleteRequests.insert(id);
726 DALI_ASSERT_DEBUG( loadStatus == RESOURCE_COMPLETELY_LOADED && "Partial results not handled for image loading.\n" );
727 Bitmap* const bitmap = static_cast<Bitmap*>( resource.Get() );
730 DALI_LOG_ERROR( "Missing bitmap in loaded resource with id %u.\n", id );
733 unsigned int bitmapWidth = bitmap->GetImageWidth();
734 unsigned int bitmapHeight = bitmap->GetImageHeight();
736 if( Bitmap::PackedPixelsProfile * packedBitmap = bitmap->GetPackedPixelsProfile() )
738 bitmapWidth = packedBitmap->GetBufferWidth();
739 bitmapHeight = packedBitmap->GetBufferHeight();
741 ImageAttributes attrs = ImageAttributes::New( bitmapWidth, bitmapHeight ); ///!< Issue #AHC01
742 UpdateImageTicket (id, attrs);
744 // Check for reloaded bitmap
745 BitmapMetadataIter iter = mImpl->mBitmapMetadata.find(id);
746 if (iter != mImpl->mBitmapMetadata.end())
748 iter->second.Update(bitmap);
749 mImpl->mTextureCacheDispatcher.DispatchUpdateTexture( id, bitmap );
753 mImpl->mTextureCacheDispatcher.DispatchCreateTextureForBitmap( id, bitmap );
754 mImpl->mBitmapMetadata.insert(BitmapMetadataPair(id, BitmapMetadata::New(bitmap)));
760 case ResourceNativeImage:
762 NativeImageInterfacePtr nativeImg( static_cast<NativeImageInterface*>(resource.Get()) );
764 ImageAttributes attrs = ImageAttributes::New(nativeImg->GetWidth(), nativeImg->GetHeight());
766 mImpl->mBitmapMetadata.insert(BitmapMetadataPair(id, BitmapMetadata::New(nativeImg)));
767 mImpl->mTextureCacheDispatcher.DispatchCreateTextureForNativeImage( id, nativeImg );
769 UpdateImageTicket (id, attrs);
773 case ResourceTargetImage:
780 mImpl->mShaders.insert(ShaderDataPair(id, static_cast<ShaderData*>(resource.Get())));
790 // Let ResourceClient know that the resource manager has loaded something that its clients might want to hear about:
793 // flag that a load has completed and the cache updated
794 mImpl->cacheUpdated = true;
798 // This warning can fire if a cancelled load is forgotten here while already complete on a resource thread:
799 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");
803 void ResourceManager::SaveComplete(ResourceId id, ResourceTypeId type)
805 DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
806 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: SaveComplete(id:%u)\n", id);
808 // ID must be in the saving set
809 LiveRequestIter iter = mImpl->saveRequests.find(id);
811 if (iter != mImpl->saveRequests.end())
813 // Remove from the saving set
814 mImpl->saveRequests.erase(iter);
816 // If resource has not been discarded..
817 if( mImpl->deadRequests.find(id) == mImpl->deadRequests.end() )
819 SendToClient( SavingSucceededMessage( *mImpl->mResourceClient, id ) );
822 mImpl->cacheUpdated = true;
826 void ResourceManager::LoadFailed(ResourceId id, ResourceFailure failure)
828 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: LoadFailed(id:%u)\n", id);
830 // ID might be in the loading set
831 LiveRequestIter iter = mImpl->loadingRequests.find(id);
833 if (iter != mImpl->loadingRequests.end())
835 // Remove from the loading set
836 mImpl->loadingRequests.erase(iter);
838 // Add the ID to the failed set, this will trigger a notification during UpdateTickets
839 mImpl->newFailedRequests.insert(id);
841 // Let NotificationManager know that the resource manager needs to do some processing
844 mImpl->cacheUpdated = true;
848 void ResourceManager::SaveFailed(ResourceId id, ResourceFailure failure)
850 DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
851 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: SaveFailed(id:%u)\n", id);
853 // ID must be in the saving set
854 LiveRequestIter iter = mImpl->saveRequests.find(id);
856 if (iter != mImpl->saveRequests.end())
858 // Remove from the saving set
859 mImpl->saveRequests.erase(iter);
861 // If resource has not been discarded..
863 if( mImpl->deadRequests.find(id) == mImpl->deadRequests.end() )
865 SendToClient( SavingFailedMessage( *mImpl->mResourceClient, id ) );
868 mImpl->cacheUpdated = true;
872 /********************************************************************************
873 ********************************* Private Methods *****************************
874 ********************************************************************************/
876 void ResourceManager::NotifyTickets()
878 DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
879 // Success notifications
880 for (LiveRequestIter iter = mImpl->newCompleteRequests.begin(); iter != mImpl->newCompleteRequests.end(); ++iter)
882 // Move to oldCompleteRequests
883 mImpl->oldCompleteRequests.insert(*iter);
885 SendToClient( LoadingSucceededMessage( *mImpl->mResourceClient, *iter ) );
887 mImpl->newCompleteRequests.clear();
889 // Failure notifications
890 for (LiveRequestIter iter = mImpl->newFailedRequests.begin(); iter != mImpl->newFailedRequests.end(); ++iter)
892 // Move to oldFailedRequests
893 mImpl->oldFailedRequests.insert(*iter);
895 // We should have a matching request ticket
896 SendToClient( LoadingFailedMessage( *mImpl->mResourceClient, *iter ) );
898 mImpl->newFailedRequests.clear();
901 void ResourceManager::UpdateImageTicket( ResourceId id, ImageAttributes& attributes ) ///!< Issue #AHC01
903 DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
904 // ResourceLoader should load images considering the requested size
905 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: UpdateImageTicket(id:%u)\n", id);
907 // Let NotificationManager know that the resource manager needs to do some processing
908 SendToClient( UpdateImageTicketMessage( *mImpl->mResourceClient, id, attributes) );
911 void ResourceManager::SendToClient( MessageBase* message )
913 mImpl->mNotificationManager.QueueMessage( message );
916 void ResourceManager::DiscardDeadResources( BufferIndex updateBufferIndex )
918 for (DeadRequestIter iter = mImpl->deadRequests.begin(); iter != mImpl->deadRequests.end(); )
920 // Delay destroying ids in saveRequests
921 if( mImpl->saveRequests.find(iter->first) != mImpl->saveRequests.end())
928 * We should find a resource of the correct type, and move it to the DiscardQueue.
930 switch (iter->second)
933 case ResourceNativeImage:
934 case ResourceTargetImage:
939 MeshCacheIter mesh = mImpl->mMeshes.find(iter->first);
940 DALI_ASSERT_DEBUG( mImpl->mMeshes.end() != mesh );
941 if( mImpl->mMeshes.end() != mesh )
943 mImpl->mDiscardQueue.Add( updateBufferIndex, mesh->second );
944 mImpl->mMeshes.erase( mesh );
951 ShaderCacheIter shaderIter = mImpl->mShaders.find(iter->first);
952 DALI_ASSERT_DEBUG( mImpl->mShaders.end() != shaderIter );
953 // shader data is owned through intrusive pointers so no need for discard queue
954 mImpl->mShaders.erase( shaderIter );
959 // Erase the item and increment the iterator
960 mImpl->deadRequests.erase(iter++);
964 } // namespace Internal