1 #ifndef __DALI_INTERNAL_RESOURCE_MANAGER_H__
2 #define __DALI_INTERNAL_RESOURCE_MANAGER_H__
5 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
25 #include <dali/public-api/images/image.h>
26 #include <dali/public-api/images/native-image-interface.h>
27 #include <dali/public-api/images/buffer-image.h>
28 #include <dali/public-api/common/ref-counted-dali-vector.h>
30 #include <dali/integration-api/bitmap.h>
31 #include <dali/integration-api/platform-abstraction.h>
32 #include <dali/integration-api/resource-cache.h>
33 #include <dali/integration-api/shader-data.h>
35 #include <dali/internal/common/message.h>
36 #include <dali/internal/event/common/event-thread-services.h>
37 #include <dali/internal/event/common/thread-local-storage.h>
38 #include <dali/internal/event/resources/resource-client-declarations.h>
39 #include <dali/internal/event/effects/shader-factory.h>
40 #include <dali/internal/update/modeling/internal-mesh-data.h>
41 #include <dali/internal/update/modeling/scene-graph-mesh-declarations.h>
42 #include <dali/internal/update/resources/resource-manager-declarations.h>
43 #include <dali/internal/update/resources/bitmap-metadata.h>
48 class NativeImageInterface;
58 // value types used by messages
59 template <> struct ParameterType< Integration::LoadResourcePriority >
60 : public BasicType< Integration::LoadResourcePriority > {};
61 template <> struct ParameterType< Pixel::Format >
62 : public BasicType< Pixel::Format > {};
63 template <> struct ParameterType< Integration::ResourceTypeId >
64 : public BasicType< Integration::ResourceTypeId > {};
70 class TextureCacheDispatcher;
71 class PostProcessResourceDispatcher;
74 class NotificationManager;
76 /** Raw bytes of a resource laid out exactly as it wouldbe in a file, but in memory. */
77 typedef Dali::RefCountedVector<uint8_t> RequestBuffer;
78 /** Counting smart pointer for managing a buffer of raw bytes. */
79 typedef IntrusivePtr<RequestBuffer> RequestBufferPtr;
82 * ResourceManager keeps track of resource loading requests, and caches resources that are loaded.
83 * It uses ResourceTicket objects, to keep track of the lifetime of each request.
84 * If the same resource is required by two client objects, they will share the same ResourceTicket
85 * i.e. only one load will occur using the native filesystem.
87 * Multi-threading notes:
88 * Resources are received from the PlatformAbstraction API during the Core::Render() method, which
89 * may be called from a dedicated rendering thread.
90 * Loading requests must be made from the application's main thread e.g. when Dali::Image is created.
92 class ResourceManager : public Integration::ResourceCache
97 * Create a resource manager.
98 * There should exactly one of these objects per Dali Core.
99 * @param[in] platformAbstraction Used to request resources from the native filesystem.
100 * @param[in] notificationManager Used to send NotifyTickets message.
101 * @param[in] postProcessResourcesQueue Used for performing post processing on resources
102 * @param[in] discardQueue Used to cleanup nodes & resources when no longer in use.
103 * @param[in] renderQueue Used to queue resource updates until the next Render.
105 ResourceManager( Integration::PlatformAbstraction& platformAbstraction,
106 NotificationManager& notificationManager,
107 SceneGraph::TextureCacheDispatcher& textureCacheDispatcher,
108 ResourcePostProcessList& postProcessResourcesQueue,
109 SceneGraph::PostProcessResourceDispatcher& postProcessResourceDispatcher,
110 SceneGraph::DiscardQueue& discardQueue,
111 SceneGraph::RenderQueue& renderQueue );
114 * Virtual destructor.
116 virtual ~ResourceManager();
118 public: // Used by ResourceClient
120 /********************************************************************************
121 ************************ ResourceClient direct interface **********************
122 ********************************************************************************/
125 * Resource client passes itself for secondary intialisation.
126 * (The resource client requires the ResourceManager to be instantiated first).
127 * @param[in] resourceClient The ResourceClient.
129 void SetClient( ResourceClient& resourceClient );
131 /********************************************************************************
132 ************************ UpdateManager direct interface ***********************
133 ********************************************************************************/
136 * Called to update the resource cache before rendering.
137 * New resources will be added to the cache using PlatformAbstraction::FillResourceCache().
138 * Unwanted resources will be added to the DiscardQueue.
139 * @param[in] updateBufferIndex The current update buffer index.
140 * @return true, if a resource load was completed or failed
142 bool UpdateCache( BufferIndex updateBufferIndex );
145 * Iterate through the post process queue, performing requested updates.
146 * @param[in] updateBufferIndex The current update buffer index.
148 void PostProcessResources( BufferIndex updateBufferIndex );
150 /********************************************************************************
151 *************************** CoreImpl direct interface *************************
152 ********************************************************************************/
155 * Returns whether the Resource Manager is still processing any resource requests.
156 * @return true if still processing, false otherwise.
158 bool ResourcesToProcess();
160 /********************************************************************************
161 ********************************* Message handlers *****************************
162 ********************************************************************************/
165 * Request a resource from the native filesystem.
166 * @param[in] id The Id of the requested resource
167 * @param[in] typePath The type & path of requested resource.
168 * @param[in] priority The priority of the request. This is ignored if the resource is already being loaded.
170 void HandleLoadResourceRequest( ResourceId id,
171 const ResourceTypePath& typePath,
172 Integration::LoadResourcePriority priority );
175 * Decode a resource from a memory buffer with the semantics of loading.
176 * Notifications of partial completion, success, and failure will happen via
177 * the same loading notification path used for loading from files: Update()
178 * will retrieve loading events in its main loop and notify listeners to its
179 * own loading events, and forward them, still as loading events, to the event
180 * thread via its update queue.
181 * Resource manager and lower levels make no attempt to detect resource
182 * aliases as is done for multiple requests to load the same resource
183 * file, so the caller is responsible for ensuring that it only requests
184 * the decoding of an in-memory resource once and for doing the sharing of the
185 * resulting object itself. Ultimately this responsibility resides with the
187 * @note ! Only Bitmap resources are supported for decoding from memory !
188 * @param[in] id The Id of the requested resource.
189 * @param[in] typePath The type of the requested resource and a path that is ignored.
190 * @param[in] buffer The raw encoded bytes of the resource as they would appear in a file.
191 * @param[in] priority The priority of the request. This is ignored if the resource is already being loaded.
193 void HandleDecodeResourceRequest( ResourceId id,
194 const ResourceTypePath& typePath,
195 RequestBufferPtr buffer,
196 Integration::LoadResourcePriority priority );
199 * Injects a bitmap resource (does not require loading).
200 * @pre bitmap has to be initialized
201 * @param[in] id The resource id
202 * @param[in] bitmap an initialized bitmap
204 void HandleAddBitmapImageRequest(ResourceId id, Integration::BitmapPtr bitmap);
207 * Add an existing resource to the resource manager.
208 * @param[in] id The resource id
209 * @param [in] resourceData the NativeImageInterface object
210 * @return A ref-counted request object. Keep a copy until the resource is no longer required.
212 void HandleAddNativeImageRequest( ResourceId id, NativeImageInterfacePtr resourceData );
215 * Add an existing resource to the resource manager.
216 * @param[in] id The resource id
217 * @param[in] width width in pixels
218 * @param[in] height height in pixels
219 * @param[in] pixelFormat Pixel format
221 void HandleAddFrameBufferImageRequest( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat );
224 * Add an existing resource to the resource manager.
225 * @param[in] id The resource id
226 * @param[in] nativeImage The NativeImage
228 void HandleAddFrameBufferImageRequest( ResourceId id, NativeImageInterfacePtr nativeImage );
231 * Allocate a new empty texture.
232 * @param[in] id The resource id
233 * @param[in] width width in pixels
234 * @param[in] height height in pixels
235 * @param[in] pixelFormat Pixel format
237 void HandleAllocateTextureRequest( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat );
240 * Requests allocation of a mesh resource
241 * @param[in] id The resource id
242 * @param[in] meshData The mesh data
244 void HandleAllocateMeshRequest (ResourceId id, MeshData* meshData);
247 * Load a shader program from a file
248 * @param[in] id The resource id
249 * @param[in] typePath The type & path of the resource
251 void HandleLoadShaderRequest(ResourceId id, const ResourceTypePath& typePath );
254 * Update bitmap area request
255 * @param[in] textureId The resource ID of a bitmap-texture to remove.
256 * @param[in] area The updated area. Zero width/height indicates the whole bitmap has been updated
258 void HandleUpdateBitmapAreaRequest( ResourceId textureId, const Dali::RectArea& area );
261 * Upload a bitmap to a position within a specified texture
262 * @param[in] destId The destination texture ID
263 * @param[in] bitmap The pointer pointing to the bitmap data to upload
264 * @param [in] xOffset Specifies an offset in the x direction within the texture
265 * @param [in] yOffset Specifies an offset in the y direction within the texture
267 void HandleUploadBitmapRequest( ResourceId destId, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset );
270 * Upload a bitmap to a position within a specified texture
271 * @param[in] destId The destination texture ID
272 * @param[in] srcId The resource ID of the bitmap to upload
273 * @param [in] xOffset Specifies an offset in the x direction within the texture
274 * @param [in] yOffset Specifies an offset in the y direction within the texture
276 void HandleUploadBitmapRequest( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
279 * Upload mesh buffer changes.
280 * @param[in] updateBufferIndex The current update buffer index.
281 * @param[in] id The ID of a Mesh resource.
282 * @param[in] meshData Newly allocated mesh data; ownership is taken.
284 void HandleUpdateMeshRequest( BufferIndex updateBufferIndex, ResourceId id, MeshData* meshData );
287 * Request reloading a resource from the native filesystem.
288 * @param[in] id The resource id
289 * @param[in] typePath The type & path of the resource
290 * @param[in] priority The priority of the request. This is ignored if the resource is already being refreshed.
291 * @param[in] resetFinishedStatus True if the finished status of the resource id should be reset
293 void HandleReloadResourceRequest( ResourceId id, const ResourceTypePath& typePath, Integration::LoadResourcePriority priority, bool resetFinishedStatus );
296 * Save a resource to the given url
297 * @param[in] id The resource id
298 * @param[in] typePath The type & path of the resource
300 void HandleSaveResourceRequest( ResourceId id, const ResourceTypePath& typePath );
303 * Resource ticket has been discarded, throw away the actual resource
305 void HandleDiscardResourceRequest( ResourceId id, Integration::ResourceTypeId typeId );
307 /********************************************************************************
308 ******************** Update thread object direct interface ********************
309 ********************************************************************************/
312 * Check if a resource has completed loading.
313 * @param[in] id The ID of a bitmap/texture resource.
314 * @return true if the bitmap or texture has finished loading
316 bool IsResourceLoaded(ResourceId id);
319 * Check if a resource has failed to load, e.g. file not found, etc.
320 * @param[in] id The ID of a bitmap/texture resource.
321 * @return true if the bitmap or texture has failed to load
323 bool IsResourceLoadFailed(ResourceId id);
326 * Get bitmap metadata. This stores meta data about the resource, but
327 * doesn't keep track of the resource
329 BitmapMetadata GetBitmapMetadata(ResourceId id);
333 * @note Used by update thread objects (SceneGraph::Mesh) only
334 * @param[in] id - the id of a MeshData resource.
335 * @return the mesh data or NULL if this resource isn't valid
337 Internal::SceneGraph::Mesh* GetMesh(ResourceId id);
340 * Returns the shader resource corresponding to the Id
341 * @param[in] id - the id of a shader binary resource.
342 * @return the shader binary resource data or NULL if it has not been loaded.
344 Integration::ShaderDataPtr GetShaderData(ResourceId id);
346 /********************************************************************************
347 ************************* ResourceCache Implementation ************************
348 ********************************************************************************/
352 * @copydoc Integration::ResourceCache::LoadResponse
354 virtual void LoadResponse(ResourceId id, Integration::ResourceTypeId type, Integration::ResourcePointer resource, Integration::LoadStatus loadStatus);
357 * @copydoc Integration::ResourceCache::SaveComplete
359 virtual void SaveComplete(ResourceId id, Integration::ResourceTypeId type);
362 * @copydoc Integration::ResourceCache::LoadFailed
364 virtual void LoadFailed(ResourceId id, Integration::ResourceFailure failure);
367 * @copydoc Integration::ResourceCache::SaveFailed
369 virtual void SaveFailed(ResourceId id, Integration::ResourceFailure failure);
371 /********************************************************************************
372 ********************************* Private Methods *****************************
373 ********************************************************************************/
376 * Sends notification messages for load sucess & failure,
377 * pushes from newComplete / newFailed into oldComplete / oldFailed respectively
379 void NotifyTickets();
382 * Triggers message to Event thread to update the ticket's image attributes
383 * @pre An Image resource with the given id should exist in the cache.
384 * @param id ID of the image resource
385 * @param attributes Resource image attributes
387 void UpdateImageTicket( ResourceId id, ImageAttributes& attributes );
390 * Send message to ResourceClient in event thread
391 * @param[in] message The message to send
393 void SendToClient( MessageBase* message );
396 * Discard all dead resources.
397 * @param[in] updateBufferIndex The current update buffer index.
399 void DiscardDeadResources( BufferIndex updateBufferIndex );
402 struct ResourceManagerImpl;
403 ResourceManagerImpl* mImpl;
406 // Messages sent to resource manager from other threads:
407 // These functions are run on other threads and insert messages to be
408 // picked-up by the update thread in its main loop and executed on that in
411 inline void RequestLoadResourceMessage( EventThreadServices& eventThreadServices,
412 ResourceManager& manager,
414 const ResourceTypePath& typePath,
415 Integration::LoadResourcePriority priority )
417 typedef MessageValue3< ResourceManager, ResourceId, ResourceTypePath, Integration::LoadResourcePriority > LocalType;
419 // Reserve some memory inside the message queue
420 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ), false );
422 // Construct message in the message queue memory; note that delete should not be called on the return value
423 new (slot) LocalType( &manager, &ResourceManager::HandleLoadResourceRequest, id, typePath, priority );
426 inline void RequestDecodeResourceMessage( EventThreadServices& eventThreadServices,
427 ResourceManager& manager,
429 /// We use typePath instead of the raw type for ownership and to enable copying of a concrete type.
430 const ResourceTypePath& typePath,
431 RequestBufferPtr buffer,
432 Integration::LoadResourcePriority priority )
434 typedef MessageValue4< ResourceManager, ResourceId, ResourceTypePath, RequestBufferPtr, Integration::LoadResourcePriority > LocalType;
436 // Reserve some memory inside the message queue
437 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ), false );
439 // Construct message in the message queue memory; note that delete should not be called on the return value
440 new (slot) LocalType( &manager, &ResourceManager::HandleDecodeResourceRequest, id, typePath, buffer, priority );
443 inline void RequestAddBitmapImageMessage( EventThreadServices& eventThreadServices,
444 ResourceManager& manager,
446 Integration::Bitmap* resourceData )
448 typedef MessageValue2< ResourceManager, ResourceId, Integration::BitmapPtr > LocalType;
450 // Reserve some memory inside the message queue
451 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
453 // Construct message in the message queue memory; note that delete should not be called on the return value
454 new (slot) LocalType( &manager, &ResourceManager::HandleAddBitmapImageRequest, id, resourceData );
457 inline void RequestAddNativeImageMessage( EventThreadServices& eventThreadServices,
458 ResourceManager& manager,
460 NativeImageInterfacePtr resourceData )
462 typedef MessageValue2< ResourceManager, ResourceId, NativeImageInterfacePtr > LocalType;
464 // Reserve some memory inside the message queue
465 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
467 // Construct message in the message queue memory; note that delete should not be called on the return value
468 new (slot) LocalType( &manager, &ResourceManager::HandleAddNativeImageRequest, id, resourceData );
471 inline void RequestAddFrameBufferImageMessage( EventThreadServices& eventThreadServices,
472 ResourceManager& manager,
476 Pixel::Format pixelFormat )
478 typedef MessageValue4< ResourceManager, ResourceId, unsigned int, unsigned int, Pixel::Format > LocalType;
480 // Reserve some memory inside the message queue
481 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
483 // Construct message in the message queue memory; note that delete should not be called on the return value
484 new (slot) LocalType( &manager, &ResourceManager::HandleAddFrameBufferImageRequest, id, width, height, pixelFormat );
487 inline void RequestAddFrameBufferImageMessage( EventThreadServices& eventThreadServices,
488 ResourceManager& manager,
490 NativeImageInterfacePtr resourceData )
492 typedef MessageValue2< ResourceManager, ResourceId, NativeImageInterfacePtr > LocalType;
494 // Reserve some memory inside the message queue
495 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
497 // Construct message in the message queue memory; note that delete should not be called on the return value
498 new (slot) LocalType( &manager, &ResourceManager::HandleAddFrameBufferImageRequest, id, resourceData );
501 inline void RequestAllocateTextureMessage( EventThreadServices& eventThreadServices,
502 ResourceManager& manager,
506 Pixel::Format pixelFormat)
508 typedef MessageValue4< ResourceManager, ResourceId, unsigned int, unsigned int, Pixel::Format > LocalType;
510 // Reserve some memory inside the message queue
511 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
513 // Construct message in the message queue memory; note that delete should not be called on the return value
514 new (slot) LocalType( &manager, &ResourceManager::HandleAllocateTextureRequest, id, width, height, pixelFormat );
517 inline void RequestAllocateMeshMessage( EventThreadServices& eventThreadServices,
518 ResourceManager& manager,
520 OwnerPointer<MeshData>& meshData )
522 typedef MessageValue2< ResourceManager, ResourceId, OwnerPointer<MeshData> > LocalType;
524 // Reserve some memory inside the message queue
525 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
527 // Construct message in the message queue memory; note that delete should not be called on the return value
528 new (slot) LocalType( &manager, &ResourceManager::HandleAllocateMeshRequest, id, meshData.Release() );
531 inline void RequestLoadShaderMessage( EventThreadServices& eventThreadServices,
532 ResourceManager& manager,
534 const ResourceTypePath& typePath )
536 typedef MessageValue2< ResourceManager, ResourceId, ResourceTypePath > LocalType;
538 // Reserve some memory inside the message queue
539 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
541 // Construct message in the message queue memory; note that delete should not be called on the return value
542 new (slot) LocalType( &manager, &ResourceManager::HandleLoadShaderRequest, id, typePath );
545 inline void RequestUpdateBitmapAreaMessage( EventThreadServices& eventThreadServices,
546 ResourceManager& manager,
548 const Dali::RectArea& area )
550 typedef MessageValue2< ResourceManager, ResourceId, Dali::RectArea > LocalType;
552 // Reserve some memory inside the message queue
553 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ), false );
555 // Construct message in the message queue memory; note that delete should not be called on the return value
556 new (slot) LocalType( &manager, &ResourceManager::HandleUpdateBitmapAreaRequest, id, area );
559 inline void RequestUploadBitmapMessage( EventThreadServices& eventThreadServices,
560 ResourceManager& manager,
562 Integration::BitmapPtr bitmap,
564 std::size_t yOffset )
566 typedef MessageValue4< ResourceManager, ResourceId, Integration::BitmapPtr , std::size_t, std::size_t > LocalType;
568 // Reserve some memory inside the message queue
569 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ), false );
571 // Construct message in the message queue memory; note that delete should not be called on the return value
572 new (slot) LocalType( &manager, &ResourceManager::HandleUploadBitmapRequest, destId, bitmap, xOffset, yOffset );
575 inline void RequestUploadBitmapMessage( EventThreadServices& eventThreadServices,
576 ResourceManager& manager,
580 std::size_t yOffset )
582 typedef MessageValue4< ResourceManager, ResourceId, ResourceId, std::size_t, std::size_t > LocalType;
584 // Reserve some memory inside the message queue
585 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ), false );
587 // Construct message in the message queue memory; note that delete should not be called on the return value
588 new (slot) LocalType( &manager, &ResourceManager::HandleUploadBitmapRequest, destId, srcId, xOffset, yOffset );
591 inline void RequestUpdateMeshMessage( EventThreadServices& eventThreadServices,
592 ResourceManager& manager,
594 const Dali::MeshData& meshData,
595 ResourcePolicy::Discardable discardable )
597 typedef MessageDoubleBuffered2< ResourceManager, ResourceId, OwnerPointer< MeshData > > LocalType;
598 // Reserve some memory inside the message queue
599 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
601 MeshData* internalMeshData = new MeshData( meshData, discardable, false );
603 // Construct message in the message queue memory; note that delete should not be called on the return value
604 new (slot) LocalType( &manager, &ResourceManager::HandleUpdateMeshRequest, id, internalMeshData );
607 inline void RequestReloadResourceMessage( EventThreadServices& eventThreadServices,
608 ResourceManager& manager,
610 const ResourceTypePath& typePath,
611 Integration::LoadResourcePriority priority,
612 bool resetFinishedStatus )
614 typedef MessageValue4< ResourceManager, ResourceId, ResourceTypePath, Integration::LoadResourcePriority, bool > LocalType;
616 // Reserve some memory inside the message queue
617 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ), false );
619 // Construct message in the message queue memory; note that delete should not be called on the return value
620 new (slot) LocalType( &manager, &ResourceManager::HandleReloadResourceRequest, id, typePath, priority, resetFinishedStatus );
623 inline void RequestSaveResourceMessage( EventThreadServices& eventThreadServices,
624 ResourceManager& manager,
626 const ResourceTypePath& typePath )
628 typedef MessageValue2< ResourceManager, ResourceId, ResourceTypePath > LocalType;
630 // Reserve some memory inside the message queue
631 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
633 // Construct message in the message queue memory; note that delete should not be called on the return value
634 new (slot) LocalType( &manager, &ResourceManager::HandleSaveResourceRequest, id, typePath );
637 inline void RequestDiscardResourceMessage( EventThreadServices& eventThreadServices,
638 ResourceManager& manager,
640 Integration::ResourceTypeId typeId )
642 typedef MessageValue2< ResourceManager, ResourceId, Integration::ResourceTypeId > LocalType;
644 // Reserve some memory inside the message queue
645 unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
647 // Construct message in the message queue memory; note that delete should not be called on the return value
648 new (slot) LocalType( &manager, &ResourceManager::HandleDiscardResourceRequest, id, typeId );
651 } // namespace Internal
655 #endif // __DALI_INTERNAL_RESOURCE_MANAGER_H__