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/event/resources/resource-client.h>
20 #include <dali/devel-api/common/map-wrapper.h>
22 #include <dali/integration-api/resource-request.h>
23 #include <dali/integration-api/debug.h>
25 #include <dali/internal/event/common/event-thread-services.h>
26 #include <dali/internal/event/common/stage-impl.h>
27 #include <dali/internal/event/images/image-impl.h>
28 #include <dali/internal/update/resources/resource-manager.h>
35 using namespace Dali::Integration;
37 typedef std::map<ResourceId, ResourceTicket*> TicketContainer;
38 typedef TicketContainer::iterator TicketContainerIter;
39 typedef TicketContainer::size_type TicketContainerSize;
40 typedef std::pair<ResourceId, ResourceTicket*> TicketPair;
42 struct ResourceClient::Impl
50 TicketContainer mTickets;
53 ResourceClient::ResourceClient( ResourceManager& resourceManager,
54 EventThreadServices& eventThreadServices)
55 : mResourceManager(resourceManager),
56 mEventThreadServices(eventThreadServices)
58 mImpl = new ResourceClient::Impl();
59 mResourceManager.SetClient(*this);
62 ResourceClient::~ResourceClient()
64 // Guard to allow handle destruction after Core has been destroyed
65 if ( Stage::IsInstalled() )
67 for (TicketContainerIter iter = mImpl->mTickets.begin(); iter != mImpl->mTickets.end(); ++iter)
69 (*iter).second->StopLifetimeObservation();
75 ResourceTicketPtr ResourceClient::RequestResource(
76 const ResourceType& type,
77 const std::string& path,
78 LoadResourcePriority priority )
80 ResourceTicketPtr newTicket;
81 ResourceTypePath typePath(type, path);
84 // Create the ticket first
85 // NOTE: pre-increment, otherwise we get 0 for first one.
86 newId = ++(mImpl->mNextId);
92 const BitmapResourceType& bitmapResource = static_cast <const BitmapResourceType&> (type);
93 // image tickets will cache the requested parameters, which are updated on successful loading
94 ImageTicket* imageTicket = new ImageTicket(*this, newId, typePath);
95 imageTicket->mAttributes.Reset( bitmapResource.size, bitmapResource.scalingMode, bitmapResource.samplingMode, bitmapResource.orientationCorrection );
96 newTicket = imageTicket;
100 case ResourceNativeImage:
102 const NativeImageResourceType& nativeResource = static_cast <const NativeImageResourceType&> (type);
103 // image tickets will cache the requested parameters, which are updated on successful loading
104 ImageTicket* imageTicket = new ImageTicket(*this, newId, typePath);
105 imageTicket->mAttributes.SetSize( nativeResource.imageDimensions.GetWidth(), nativeResource.imageDimensions.GetHeight() );
106 newTicket = imageTicket;
109 case ResourceTargetImage:
111 newTicket = new ResourceTicket(*this, newId, typePath);
116 mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
118 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: RequestResource(path:%s type.id:%d) newId:%u\n", path.c_str(), type.id, newId);
120 RequestLoadResourceMessage( mEventThreadServices, mResourceManager, newId, typePath, priority );
124 ResourceTicketPtr ResourceClient::DecodeResource(
125 const ResourceType& type,
126 RequestBufferPtr buffer,
127 LoadResourcePriority priority )
129 DALI_ASSERT_DEBUG( type.id == ResourceBitmap && "Only bitmap resources are currently decoded from memory buffers. It should be easy to expand to other resource types though. The public API function at the front and the resource thread at the back end are all that should need to be changed. The code in the middle should be agnostic to the the resource type it is conveying.\n" );
130 DALI_ASSERT_DEBUG( buffer.Get() && "Null resource buffer passed for decoding." );
131 ResourceTicketPtr newTicket;
132 if( buffer.Get() ) //< Check to avoid SEGV on a null pointer.
134 ResourceTypePath typePath( type, "" );
135 ResourceId newId = 0;
137 // Create the correct ticket type for the resource:
142 // NOTE: pre-increment, otherwise we get 0 for first one.
143 newId = ++(mImpl->mNextId);
144 const BitmapResourceType& bitmapResource = static_cast <const BitmapResourceType&> ( type );
145 // Image tickets will cache the requested parameters, which are updated on successful loading
146 ImageTicket* imageTicket = new ImageTicket( *this, newId, typePath );
147 imageTicket->mAttributes.Reset( bitmapResource.size, bitmapResource.scalingMode, bitmapResource.samplingMode, bitmapResource.orientationCorrection );
148 newTicket = imageTicket;
153 case ResourceNativeImage:
154 case ResourceTargetImage:
156 DALI_LOG_ERROR( "Unsupported resource type passed for decoding from a memory buffer." );
162 mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
163 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: DecodeResource( type.id:%d ) newId:%u\n", type.id, newId);
165 RequestDecodeResourceMessage( mEventThreadServices, mResourceManager, newId, typePath, buffer, priority );
171 bool ResourceClient::ReloadResource( ResourceId id, bool resetFinishedStatus, LoadResourcePriority priority )
173 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: ReloadResource(Id: %u)\n", id);
175 bool resourceExists = false;
176 TicketContainerIter ticketIter;
177 ticketIter = mImpl->mTickets.find(id);
179 if(ticketIter != mImpl->mTickets.end())
181 resourceExists = true;
182 // The ticket is already being observed
183 ResourceTicket* ticket = ticketIter->second;
184 DALI_ASSERT_DEBUG(ticket && "Null ticket for tracked resource request." );
185 const ResourceTypePath * const typePathPtr = &ticket->GetTypePath();
186 DALI_ASSERT_DEBUG( typePathPtr );
187 RequestReloadResourceMessage( mEventThreadServices, mResourceManager, id, *typePathPtr, priority, resetFinishedStatus );
191 DALI_LOG_ERROR ("Resource %d does not exist\n", id);
193 return resourceExists;
196 ResourceTicketPtr ResourceClient::RequestResourceTicket( ResourceId id )
198 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: RequestResourceTicket(Id: %u)\n", id);
200 ResourceTicketPtr ticket;
202 TicketContainerIter ticketIter = mImpl->mTickets.find( id );
204 if ( mImpl->mTickets.end() != ticketIter )
206 ticket = ticketIter->second;
212 ImageTicketPtr ResourceClient::AddBitmapImage(Bitmap* bitmap)
214 DALI_ASSERT_DEBUG( bitmap != NULL );
216 ImageTicketPtr newTicket;
218 const ResourceId newId = ++(mImpl->mNextId);
220 ImageAttributes imageAttributes = ImageAttributes::New(bitmap->GetImageWidth(), bitmap->GetImageHeight());
221 BitmapResourceType bitmapResourceType( ImageDimensions::FromFloatVec2( imageAttributes.GetSize() ) ); // construct first as no copy ctor (needed to bind ref to object)
222 ResourceTypePath typePath(bitmapResourceType, "");
223 newTicket = new ImageTicket(*this, newId, typePath);
224 newTicket->mAttributes = imageAttributes;
225 newTicket->LoadingSucceeded();
227 mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
229 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: AddBitmapImage() New id = %u\n", newId);
230 RequestAddBitmapImageMessage( mEventThreadServices, mResourceManager, newId, bitmap );
235 ResourceTicketPtr ResourceClient::AddNativeImage ( NativeImageInterface& resourceData )
237 ImageTicketPtr newTicket;
239 const ResourceId newId = ++(mImpl->mNextId);
240 NativeImageResourceType nativeImageResourceType; // construct first as no copy ctor (needed to bind ref to object)
241 ResourceTypePath typePath(nativeImageResourceType, "");
242 newTicket = new ImageTicket(*this, newId, typePath);
243 newTicket->mAttributes = ImageAttributes::New(resourceData.GetWidth(),
244 resourceData.GetHeight());
245 newTicket->LoadingSucceeded();
247 mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
249 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: AddNativeImage() New id = %u\n", newId);
251 RequestAddNativeImageMessage( mEventThreadServices, mResourceManager, newId, &resourceData );
256 ImageTicketPtr ResourceClient::AddFrameBufferImage ( unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat )
258 ImageTicketPtr newTicket;
260 const ResourceId newId = ++(mImpl->mNextId);
262 ImageAttributes imageAttributes = ImageAttributes::New(width, height);
263 RenderTargetResourceType renderTargetResourceType( ImageDimensions( width, height ) ); // construct first as no copy ctor (needed to bind ref to object)
264 ResourceTypePath typePath(renderTargetResourceType, "");
265 newTicket = new ImageTicket(*this, newId, typePath);
266 newTicket->mAttributes = imageAttributes;
267 newTicket->LoadingSucceeded();
269 mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
271 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: AddFrameBufferImage() New id = %u\n", newId);
272 RequestAddFrameBufferImageMessage( mEventThreadServices, mResourceManager, newId, width, height, pixelFormat, bufferFormat );
277 ImageTicketPtr ResourceClient::AddFrameBufferImage ( NativeImageInterface& nativeImage )
279 ImageTicketPtr newTicket;
281 const ResourceId newId = ++(mImpl->mNextId);
283 ImageAttributes imageAttributes = ImageAttributes::New( nativeImage.GetWidth(), nativeImage.GetHeight() );
284 RenderTargetResourceType renderTargetResourceType( ImageDimensions( nativeImage.GetWidth(), nativeImage.GetHeight() ) ); // construct first as no copy ctor (needed to bind ref to object)
285 ResourceTypePath typePath(renderTargetResourceType, "");
286 newTicket = new ImageTicket(*this, newId, typePath);
287 newTicket->mAttributes = imageAttributes;
288 newTicket->LoadingSucceeded();
290 mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
292 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: AddFrameBufferImage() New id = %u\n", newId);
293 RequestAddFrameBufferImageMessage( mEventThreadServices, mResourceManager, newId, &nativeImage );
299 ResourceTicketPtr ResourceClient::AllocateTexture( unsigned int width,
301 Pixel::Format pixelformat )
303 ImageTicketPtr newTicket;
304 const ResourceId newId = ++(mImpl->mNextId);
306 ImageAttributes imageAttributes = ImageAttributes::New( width, height);
307 BitmapResourceType bitmapResourceType( ImageDimensions( width, height ) ); // construct first as no copy ctor (needed to bind ref to object)
308 ResourceTypePath typePath(bitmapResourceType, "");
309 newTicket = new ImageTicket(*this, newId, typePath);
311 mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
312 newTicket->mAttributes = imageAttributes;
313 newTicket->LoadingSucceeded();
315 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: AllocateTexture() New id = %u\n", newId);
317 RequestAllocateTextureMessage( mEventThreadServices, mResourceManager, newId, width, height, pixelformat );
322 void ResourceClient::UpdateBitmapArea( ResourceTicketPtr ticket, RectArea& updateArea )
324 DALI_ASSERT_DEBUG( ticket );
326 RequestUpdateBitmapAreaMessage( mEventThreadServices, mResourceManager, ticket->GetId(), updateArea );
329 void ResourceClient::UploadBitmap( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
331 RequestUploadBitmapMessage( mEventThreadServices,
340 void ResourceClient::UploadBitmap( ResourceId destId,Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset)
342 RequestUploadBitmapMessage( mEventThreadServices,
350 void ResourceClient::UploadBitmap( ResourceId destId, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset)
352 RequestUploadBitmapMessage( mEventThreadServices,
360 void ResourceClient::CreateGlTexture( ResourceId id )
362 RequestCreateGlTextureMessage( mEventThreadServices, mResourceManager, id );
366 /********************************************************************************
367 ******************** ResourceTicketLifetimeObserver methods ****************
368 ********************************************************************************/
370 void ResourceClient::ResourceTicketDiscarded(const ResourceTicket& ticket)
372 const ResourceId deadId = ticket.GetId();
373 const ResourceTypePath& typePath = ticket.GetTypePath();
375 // The ticket object is dead, remove from tickets container
376 TicketContainerSize erased = mImpl->mTickets.erase(deadId);
377 DALI_ASSERT_DEBUG(erased != 0);
378 (void)erased; // Avoid "unused variable erased" in release builds
380 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: ResourceTicketDiscarded() deadId = %u\n", deadId);
381 RequestDiscardResourceMessage( mEventThreadServices, mResourceManager, deadId, typePath.type->id );
384 /********************************************************************************
385 *********************** Notifications from ResourceManager ******************
386 ********************************************************************************/
388 void ResourceClient::NotifyUploaded( ResourceId id )
390 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: NotifyUpdated(id:%u)\n", id);
392 TicketContainerIter ticketIter = mImpl->mTickets.find(id);
393 if(ticketIter != mImpl->mTickets.end())
395 ResourceTicket* ticket = ticketIter->second;
400 void ResourceClient::NotifyLoading( ResourceId id )
402 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: NotifyLoading(id:%u)\n", id);
404 TicketContainerIter ticketIter = mImpl->mTickets.find(id);
405 if(ticketIter != mImpl->mTickets.end())
407 ResourceTicket* ticket = ticketIter->second;
412 void ResourceClient::NotifyLoadingSucceeded( ResourceId id )
414 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: NotifyLoadingSucceeded(id:%u)\n", id);
416 TicketContainerIter ticketIter = mImpl->mTickets.find(id);
417 if(ticketIter != mImpl->mTickets.end())
419 ResourceTicket* ticket = ticketIter->second;
420 ticket->LoadingSucceeded();
424 void ResourceClient::NotifyLoadingFailed( ResourceId id )
426 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: NotifyLoadingFailed(id:%u)\n", id);
428 TicketContainerIter ticketIter = mImpl->mTickets.find(id);
429 if(ticketIter != mImpl->mTickets.end())
431 ResourceTicket* ticket = ticketIter->second;
432 ticket->LoadingFailed();
436 void ResourceClient::UpdateImageTicket( ResourceId id, const ImageAttributes& imageAttributes ) ///!< Issue #AHC01
438 DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: UpdateImageTicket(id:%u)\n", id);
440 TicketContainerIter ticketIter = mImpl->mTickets.find(id);
441 if(ticketIter != mImpl->mTickets.end())
443 ResourceTicket* ticket = ticketIter->second;
444 ImageTicketPtr imageTicket = dynamic_cast<ImageTicket*>(ticket);
447 imageTicket->mAttributes = imageAttributes;