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.h>
27 #include <dali/public-api/images/bitmap-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/event-to-update.h>
36 #include <dali/internal/common/message.h>
37 #include <dali/internal/event/common/thread-local-storage.h>
38 #include <dali/internal/event/modeling/model-data-impl.h>
39 #include <dali/internal/event/resources/resource-client-declarations.h>
40 #include <dali/internal/event/effects/shader-factory.h>
41 #include <dali/internal/update/modeling/internal-mesh-data.h>
42 #include <dali/internal/update/modeling/scene-graph-mesh-declarations.h>
43 #include <dali/internal/update/resources/resource-manager-declarations.h>
44 #include <dali/internal/update/resources/bitmap-metadata.h>
59 // value types used by messages
60 template <> struct ParameterType< Integration::LoadResourcePriority >
61 : public BasicType< Integration::LoadResourcePriority > {};
62 template <> struct ParameterType< Pixel::Format >
63 : public BasicType< Pixel::Format > {};
64 template <> struct ParameterType< Integration::ResourceTypeId >
65 : public BasicType< Integration::ResourceTypeId > {};
71 class TextureCacheDispatcher;
72 class PostProcessResourceDispatcher;
75 class NotificationManager;
77 /** Raw bytes of a resource laid out exactly as it wouldbe in a file, but in memory. */
78 typedef Dali::RefCountedVector<uint8_t> RequestBuffer;
79 /** Counting smart pointer for managing a buffer of raw bytes. */
80 typedef IntrusivePtr<RequestBuffer> RequestBufferPtr;
83 * ResourceManager keeps track of resource loading requests, and caches resources that are loaded.
84 * It uses ResourceTicket objects, to keep track of the lifetime of each request.
85 * If the same resource is required by two client objects, they will share the same ResourceTicket
86 * i.e. only one load will occur using the native filesystem.
88 * Multi-threading notes:
89 * Resources are received from the PlatformAbstraction API during the Core::Render() method, which
90 * may be called from a dedicated rendering thread.
91 * Loading requests must be made from the application's main thread e.g. when Dali::Image is created.
93 class ResourceManager : public Integration::ResourceCache
98 * Create a resource manager.
99 * There should exactly one of these objects per Dali Core.
100 * @param[in] platformAbstraction Used to request resources from the native filesystem.
101 * @param[in] notificationManager Used to send NotifyTickets message.
102 * @param[in] postProcessResourcesQueue Used for performing post processing on resources
103 * @param[in] discardQueue Used to cleanup nodes & resources when no longer in use.
104 * @param[in] renderQueue Used to queue resource updates until the next Render.
106 ResourceManager( Integration::PlatformAbstraction& platformAbstraction,
107 NotificationManager& notificationManager,
108 SceneGraph::TextureCacheDispatcher& textureCacheDispatcher,
109 ResourcePostProcessList& postProcessResourcesQueue,
110 SceneGraph::PostProcessResourceDispatcher& postProcessResourceDispatcher,
111 SceneGraph::DiscardQueue& discardQueue,
112 SceneGraph::RenderQueue& renderQueue );
115 * Virtual destructor.
117 virtual ~ResourceManager();
119 public: // Used by ResourceClient
121 /********************************************************************************
122 ************************ ResourceClient direct interface **********************
123 ********************************************************************************/
126 * Resource client passes itself for secondary intialisation.
127 * (The resource client requires the ResourceManager to be instantiated first).
128 * @param[in] resourceClient The ResourceClient.
130 void SetClient( ResourceClient& resourceClient );
132 /********************************************************************************
133 ************************ UpdateManager direct interface ***********************
134 ********************************************************************************/
137 * Called to update the resource cache before rendering.
138 * New resources will be added to the cache using PlatformAbstraction::FillResourceCache().
139 * Unwanted resources will be added to the DiscardQueue.
140 * @param[in] updateBufferIndex The current update buffer index.
141 * @return true, if a resource load was completed or failed
143 bool UpdateCache( BufferIndex updateBufferIndex );
146 * Iterate through the post process queue, performing requested updates.
147 * @param[in] updateBufferIndex The current update buffer index.
149 void PostProcessResources( BufferIndex updateBufferIndex );
151 /********************************************************************************
152 *************************** CoreImpl direct interface *************************
153 ********************************************************************************/
156 * Returns whether the Resource Manager is still processing any resource requests.
157 * @return true if still processing, false otherwise.
159 bool ResourcesToProcess();
161 /********************************************************************************
162 ********************************* Message handlers *****************************
163 ********************************************************************************/
166 * Request a resource from the native filesystem.
167 * @param[in] id The Id of the requested resource
168 * @param[in] typePath The type & path of requested resource.
169 * @param[in] priority The priority of the request. This is ignored if the resource is already being loaded.
171 void HandleLoadResourceRequest( ResourceId id,
172 const ResourceTypePath& typePath,
173 Integration::LoadResourcePriority priority );
176 * Decode a resource from a memory buffer with the semantics of loading.
177 * Notifications of partial completion, success, and failure will happen via
178 * the same loading notification path used for loading from files: Update()
179 * will retrieve loading events in its main loop and notify listeners to its
180 * own loading events, and forward them, still as loading events, to the event
181 * thread via its update queue.
182 * Resource manager and lower levels make no attempt to detect resource
183 * aliases as is done for multiple requests to load the same resource
184 * file, so the caller is responsible for ensuring that it only requests
185 * the decoding of an in-memory resource once and for doing the sharing of the
186 * resulting object itself. Ultimately this responsibility resides with the
188 * @note ! Only Bitmap resources are supported for decoding from memory !
189 * @param[in] id The Id of the requested resource.
190 * @param[in] typePath The type of the requested resource and a path that is ignored.
191 * @param[in] buffer The raw encoded bytes of the resource as they would appear in a file.
192 * @param[in] priority The priority of the request. This is ignored if the resource is already being loaded.
194 void HandleDecodeResourceRequest( ResourceId id,
195 const ResourceTypePath& typePath,
196 RequestBufferPtr buffer,
197 Integration::LoadResourcePriority priority );
200 * Injects a bitmap resource (does not require loading).
201 * @pre bitmap has to be initialized
202 * @param[in] id The resource id
203 * @param[in] bitmap an initialized bitmap
205 void HandleAddBitmapImageRequest(ResourceId id, Integration::BitmapPtr bitmap);
208 * Add an existing resource to the resource manager.
209 * @param[in] id The resource id
210 * @param [in] resourceData the NativeImage object
211 * @return A ref-counted request object. Keep a copy until the resource is no longer required.
213 void HandleAddNativeImageRequest( ResourceId id, NativeImagePtr resourceData );
216 * Add an existing resource to the resource manager.
217 * @param[in] id The resource id
218 * @param[in] width width in pixels
219 * @param[in] height height in pixels
220 * @param[in] pixelFormat Pixel format
222 void HandleAddFrameBufferImageRequest( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat );
225 * Add an existing resource to the resource manager.
226 * @param[in] id The resource id
227 * @param[in] nativeImage The NativeImage
229 void HandleAddFrameBufferImageRequest( ResourceId id, NativeImagePtr nativeImage );
232 * Allocate a new empty texture.
233 * @param[in] id The resource id
234 * @param[in] width width in pixels
235 * @param[in] height height in pixels
236 * @param[in] pixelFormat Pixel format
238 void HandleAllocateTextureRequest( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat );
241 * Requests allocation of a mesh resource
242 * @param[in] id The resource id
243 * @param[in] meshData The mesh data
245 void HandleAllocateMeshRequest (ResourceId id, MeshData* meshData);
248 * Load a shader program from a file
249 * @param[in] id The resource id
250 * @param[in] typePath The type & path of the resource
252 void HandleLoadShaderRequest(ResourceId id, const ResourceTypePath& typePath );
255 * Update bitmap area request
256 * @param[in] textureId The resource ID of a bitmap-texture to remove.
257 * @param[in] area The updated area. Zero width/height indicates the whole bitmap has been updated
259 void HandleUpdateBitmapAreaRequest( ResourceId textureId, const Dali::RectArea& area );
262 * Upload a bitmap to a position within a specified texture
263 * @param[in] destId The destination texture ID
264 * @param[in] srcId The resource ID of the bitmap to upload
265 * @param [in] xOffset Specifies an offset in the x direction within the texture
266 * @param [in] yOffset Specifies an offset in the y direction within the texture
268 void HandleUploadBitmapRequest( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
271 * Upload mesh buffer changes.
272 * @param[in] updateBufferIndex The current update buffer index.
273 * @param[in] id The ID of a Mesh resource.
274 * @param[in] meshData Newly allocated mesh data; ownership is taken.
276 void HandleUpdateMeshRequest( BufferIndex updateBufferIndex, ResourceId id, MeshData* meshData );
279 * Request reloading a resource from the native filesystem.
280 * @param[in] id The resource id
281 * @param[in] typePath The type & path of the resource
282 * @param[in] priority The priority of the request. This is ignored if the resource is already being refreshed.
283 * @param[in] resetFinishedStatus True if the finished status of the resource id should be reset
285 void HandleReloadResourceRequest( ResourceId id, const ResourceTypePath& typePath, Integration::LoadResourcePriority priority, bool resetFinishedStatus );
288 * Save a resource to the given url
289 * @param[in] id The resource id
290 * @param[in] typePath The type & path of the resource
292 void HandleSaveResourceRequest( ResourceId id, const ResourceTypePath& typePath );
295 * Resource ticket has been discarded, throw away the actual resource
297 void HandleDiscardResourceRequest( ResourceId id, Integration::ResourceTypeId typeId );
299 /********************************************************************************
300 ******************** Event thread object direct interface *********************
301 ********************************************************************************/
304 * Called by model implementations which require access to the model
306 * @note Only called from event thread objects - ModelData is not used
308 * @param[in] id - the id of a ModelData resource.
309 * @return the model data or NULL if it has not been loaded.
311 Internal::ModelDataPtr GetModelData(ResourceId id);
313 /********************************************************************************
314 ******************** Update thread object direct interface ********************
315 ********************************************************************************/
318 * Check if a resource has completed loading.
319 * @param[in] id The ID of a bitmap/texture resource.
320 * @return true if the bitmap or texture has finished loading
322 bool IsResourceLoaded(ResourceId id);
325 * Check if a resource has failed to load, e.g. file not found, etc.
326 * @param[in] id The ID of a bitmap/texture resource.
327 * @return true if the bitmap or texture has failed to load
329 bool IsResourceLoadFailed(ResourceId id);
332 * Get bitmap metadata. This stores meta data about the resource, but
333 * doesn't keep track of the resource
335 BitmapMetadata GetBitmapMetadata(ResourceId id);
339 * @note Used by update thread objects (SceneGraph::Mesh) only
340 * @param[in] id - the id of a MeshData resource.
341 * @return the mesh data or NULL if this resource isn't valid
343 Internal::SceneGraph::Mesh* GetMesh(ResourceId id);
346 * Returns the shader resource corresponding to the Id
347 * @param[in] id - the id of a shader binary resource.
348 * @return the shader binary resource data or NULL if it has not been loaded.
350 Integration::ShaderDataPtr GetShaderData(ResourceId id);
352 /********************************************************************************
353 ************************* ResourceCache Implementation ************************
354 ********************************************************************************/
358 * @copydoc Integration::ResourceCache::LoadResponse
360 virtual void LoadResponse(ResourceId id, Integration::ResourceTypeId type, Integration::ResourcePointer resource, Integration::LoadStatus loadStatus);
363 * @copydoc Integration::ResourceCache::SaveComplete
365 virtual void SaveComplete(ResourceId id, Integration::ResourceTypeId type);
368 * @copydoc Integration::ResourceCache::LoadFailed
370 virtual void LoadFailed(ResourceId id, Integration::ResourceFailure failure);
373 * @copydoc Integration::ResourceCache::SaveFailed
375 virtual void SaveFailed(ResourceId id, Integration::ResourceFailure failure);
377 /********************************************************************************
378 ********************************* Private Methods *****************************
379 ********************************************************************************/
383 * Sends notification messages for load sucess & failure,
384 * pushes from newComplete / newFailed into oldComplete / oldFailed respectively
386 void NotifyTickets();
389 * Triggers message to Event thread to update the ticket's image attributes
390 * @pre An Image resource with the given id should exist in the cache.
391 * @param id ID of the image resource
392 * @param attributes Resource image attributes
394 void UpdateImageTicket( ResourceId id, ImageAttributes& attributes );
397 * Send message to ResourceClient in event thread
398 * @param[in] message The message to send
400 void SendToClient( MessageBase* message );
403 * Discard all dead resources.
404 * @param[in] updateBufferIndex The current update buffer index.
406 void DiscardDeadResources( BufferIndex updateBufferIndex );
409 struct ResourceManagerImpl;
410 ResourceManagerImpl* mImpl;
413 // Messages sent to resource manager from other threads:
414 // These functions are run on other threads and insert messages to be
415 // picked-up by the update thread in its main loop and executed on that in
418 inline void RequestLoadResourceMessage( EventToUpdate& eventToUpdate,
419 ResourceManager& manager,
421 const ResourceTypePath& typePath,
422 Integration::LoadResourcePriority priority )
424 typedef MessageValue3< ResourceManager, ResourceId, ResourceTypePath, Integration::LoadResourcePriority > LocalType;
426 // Reserve some memory inside the message queue
427 unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ), false );
429 // Construct message in the message queue memory; note that delete should not be called on the return value
430 new (slot) LocalType( &manager, &ResourceManager::HandleLoadResourceRequest, id, typePath, priority );
433 inline void RequestDecodeResourceMessage( EventToUpdate& eventToUpdate,
434 ResourceManager& manager,
436 /// We use typePath instead of the raw type for ownership and to enable copying of a concrete type.
437 const ResourceTypePath& typePath,
438 RequestBufferPtr buffer,
439 Integration::LoadResourcePriority priority )
441 typedef MessageValue4< ResourceManager, ResourceId, ResourceTypePath, RequestBufferPtr, Integration::LoadResourcePriority > LocalType;
443 // Reserve some memory inside the message queue
444 unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ), false );
446 // Construct message in the message queue memory; note that delete should not be called on the return value
447 new (slot) LocalType( &manager, &ResourceManager::HandleDecodeResourceRequest, id, typePath, buffer, priority );
450 inline void RequestAddBitmapImageMessage( EventToUpdate& eventToUpdate,
451 ResourceManager& manager,
453 Integration::Bitmap* resourceData )
455 typedef MessageValue2< ResourceManager, ResourceId, Integration::BitmapPtr > LocalType;
457 // Reserve some memory inside the message queue
458 unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ) );
460 // Construct message in the message queue memory; note that delete should not be called on the return value
461 new (slot) LocalType( &manager, &ResourceManager::HandleAddBitmapImageRequest, id, resourceData );
464 inline void RequestAddNativeImageMessage( EventToUpdate& eventToUpdate,
465 ResourceManager& manager,
467 NativeImagePtr resourceData )
469 typedef MessageValue2< ResourceManager, ResourceId, NativeImagePtr > LocalType;
471 // Reserve some memory inside the message queue
472 unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ) );
474 // Construct message in the message queue memory; note that delete should not be called on the return value
475 new (slot) LocalType( &manager, &ResourceManager::HandleAddNativeImageRequest, id, resourceData );
478 inline void RequestAddFrameBufferImageMessage( EventToUpdate& eventToUpdate,
479 ResourceManager& manager,
483 Pixel::Format pixelFormat )
485 typedef MessageValue4< ResourceManager, ResourceId, unsigned int, unsigned int, Pixel::Format > LocalType;
487 // Reserve some memory inside the message queue
488 unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ) );
490 // Construct message in the message queue memory; note that delete should not be called on the return value
491 new (slot) LocalType( &manager, &ResourceManager::HandleAddFrameBufferImageRequest, id, width, height, pixelFormat );
494 inline void RequestAddFrameBufferImageMessage( EventToUpdate& eventToUpdate,
495 ResourceManager& manager,
497 NativeImagePtr resourceData )
499 typedef MessageValue2< ResourceManager, ResourceId, NativeImagePtr > LocalType;
501 // Reserve some memory inside the message queue
502 unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ) );
504 // Construct message in the message queue memory; note that delete should not be called on the return value
505 new (slot) LocalType( &manager, &ResourceManager::HandleAddFrameBufferImageRequest, id, resourceData );
508 inline void RequestAllocateTextureMessage(EventToUpdate& eventToUpdate,
509 ResourceManager& manager,
513 Pixel::Format pixelFormat)
515 typedef MessageValue4< ResourceManager, ResourceId, unsigned int, unsigned int, Pixel::Format > LocalType;
517 // Reserve some memory inside the message queue
518 unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ) );
520 // Construct message in the message queue memory; note that delete should not be called on the return value
521 new (slot) LocalType( &manager, &ResourceManager::HandleAllocateTextureRequest, id, width, height, pixelFormat );
524 inline void RequestAllocateMeshMessage( EventToUpdate& eventToUpdate,
525 ResourceManager& manager,
527 OwnerPointer<MeshData>& meshData )
529 typedef MessageValue2< ResourceManager, ResourceId, OwnerPointer<MeshData> > LocalType;
531 // Reserve some memory inside the message queue
532 unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ) );
534 // Construct message in the message queue memory; note that delete should not be called on the return value
535 new (slot) LocalType( &manager, &ResourceManager::HandleAllocateMeshRequest, id, meshData.Release() );
538 inline void RequestLoadShaderMessage( EventToUpdate& eventToUpdate,
539 ResourceManager& manager,
541 const ResourceTypePath& typePath )
543 typedef MessageValue2< ResourceManager, ResourceId, ResourceTypePath > LocalType;
545 // Reserve some memory inside the message queue
546 unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ) );
548 // Construct message in the message queue memory; note that delete should not be called on the return value
549 new (slot) LocalType( &manager, &ResourceManager::HandleLoadShaderRequest, id, typePath );
552 inline void RequestUpdateBitmapAreaMessage( EventToUpdate& eventToUpdate,
553 ResourceManager& manager,
555 const Dali::RectArea& area )
557 typedef MessageValue2< ResourceManager, ResourceId, Dali::RectArea > LocalType;
559 // Reserve some memory inside the message queue
560 unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ), false );
562 // Construct message in the message queue memory; note that delete should not be called on the return value
563 new (slot) LocalType( &manager, &ResourceManager::HandleUpdateBitmapAreaRequest, id, area );
566 inline void RequestUploadBitmapMessage( EventToUpdate& eventToUpdate,
567 ResourceManager& manager,
571 std::size_t yOffset )
573 typedef MessageValue4< ResourceManager, ResourceId, ResourceId, std::size_t, std::size_t > LocalType;
575 // Reserve some memory inside the message queue
576 unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ), false );
578 // Construct message in the message queue memory; note that delete should not be called on the return value
579 new (slot) LocalType( &manager, &ResourceManager::HandleUploadBitmapRequest, destId, srcId, xOffset, yOffset );
582 inline void RequestUpdateMeshMessage( EventToUpdate& eventToUpdate,
583 ResourceManager& manager,
585 const Dali::MeshData& meshData,
586 ResourcePolicy::Discardable discardable )
588 typedef MessageDoubleBuffered2< ResourceManager, ResourceId, OwnerPointer< MeshData > > LocalType;
589 // Reserve some memory inside the message queue
590 unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ) );
592 MeshData* internalMeshData = new MeshData( meshData, discardable, false );
594 // Construct message in the message queue memory; note that delete should not be called on the return value
595 new (slot) LocalType( &manager, &ResourceManager::HandleUpdateMeshRequest, id, internalMeshData );
598 inline void RequestReloadResourceMessage( EventToUpdate& eventToUpdate,
599 ResourceManager& manager,
601 const ResourceTypePath& typePath,
602 Integration::LoadResourcePriority priority,
603 bool resetFinishedStatus )
605 typedef MessageValue4< ResourceManager, ResourceId, ResourceTypePath, Integration::LoadResourcePriority, bool > LocalType;
607 // Reserve some memory inside the message queue
608 unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ), false );
610 // Construct message in the message queue memory; note that delete should not be called on the return value
611 new (slot) LocalType( &manager, &ResourceManager::HandleReloadResourceRequest, id, typePath, priority, resetFinishedStatus );
614 inline void RequestSaveResourceMessage( EventToUpdate& eventToUpdate,
615 ResourceManager& manager,
617 const ResourceTypePath& typePath )
619 typedef MessageValue2< ResourceManager, ResourceId, ResourceTypePath > LocalType;
621 // Reserve some memory inside the message queue
622 unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ) );
624 // Construct message in the message queue memory; note that delete should not be called on the return value
625 new (slot) LocalType( &manager, &ResourceManager::HandleSaveResourceRequest, id, typePath );
628 inline void RequestDiscardResourceMessage( EventToUpdate& eventToUpdate,
629 ResourceManager& manager,
631 Integration::ResourceTypeId typeId )
633 typedef MessageValue2< ResourceManager, ResourceId, Integration::ResourceTypeId > LocalType;
635 // Reserve some memory inside the message queue
636 unsigned int* slot = eventToUpdate.ReserveMessageSlot( sizeof( LocalType ) );
638 // Construct message in the message queue memory; note that delete should not be called on the return value
639 new (slot) LocalType( &manager, &ResourceManager::HandleDiscardResourceRequest, id, typeId );
642 } // namespace Internal
646 #endif // __DALI_INTERNAL_RESOURCE_MANAGER_H__