2 // Copyright (c) 2014 Samsung Electronics Co., Ltd.
4 // Licensed under the Flora License, Version 1.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://floralicense.org/license/
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.
17 #include <dali/internal/render/gl-resources/texture-cache.h>
19 #include <dali/integration-api/bitmap.h>
21 #include <dali/internal/update/resources/resource-manager-declarations.h>
22 #include <dali/internal/render/common/post-process-resource-dispatcher.h>
23 #include <dali/internal/render/queue/render-queue.h>
24 #include <dali/internal/render/gl-resources/context.h>
25 #include <dali/internal/render/gl-resources/texture-factory.h>
26 #include <dali/internal/render/gl-resources/texture.h>
27 #include <dali/internal/render/gl-resources/texture-observer.h>
28 #include <dali/internal/render/gl-resources/bitmap-texture.h>
29 #include <dali/internal/render/gl-resources/native-texture.h>
30 #include <dali/internal/render/gl-resources/frame-buffer-texture.h>
32 #include <dali/integration-api/debug.h>
34 using Dali::Internal::Texture;
35 using Dali::Internal::FrameBufferTexture;
36 using Dali::Integration::Bitmap;
43 // value types used by messages
44 template <> struct ParameterType< Pixel::Format > : public BasicType< Pixel::Format > {};
49 TextureCache::TextureCache( RenderQueue& renderQueue,
50 PostProcessResourceDispatcher& postProcessResourceDispatcher,
52 : TextureCacheDispatcher(renderQueue),
53 mPostProcessResourceDispatcher(postProcessResourceDispatcher),
58 TextureCache::~TextureCache()
62 void TextureCache::CreateTexture( ResourceId id,
65 Pixel::Format pixelFormat,
68 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::CreateTexture(id=%i width:%u height:%u)\n", id, width, height);
70 Texture* texture = TextureFactory::NewBitmapTexture(width, height, pixelFormat, clearPixels, mContext);
71 mTextures.insert(TexturePair(id, texture));
74 void TextureCache::AddBitmap(ResourceId id, Integration::BitmapPtr bitmap)
76 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddBitmap(id=%i Bitmap:%p)\n", id, bitmap.Get());
78 Texture* texture = TextureFactory::NewBitmapTexture(bitmap.Get(), mContext);
79 mTextures.insert(TexturePair(id, texture));
82 void TextureCache::AddNativeImage(ResourceId id, NativeImagePtr nativeImage)
84 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddNativeImage(id=%i NativeImg:%p)\n", id, nativeImage.Get());
86 /// TODO - currently a new Texture is created even if we reuse the same NativeImage
87 Texture* texture = TextureFactory::NewNativeImageTexture(*nativeImage, mContext);
88 mTextures.insert(TexturePair(id, texture));
91 void TextureCache::AddFrameBuffer( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat )
93 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddFrameBuffer(id=%i width:%u height:%u)\n", id, width, height);
95 // Note: Do not throttle framebuffer generation - a request for a framebuffer should always be honoured
96 // as soon as possible.
97 Texture* texture = TextureFactory::NewFrameBufferTexture( width, height, pixelFormat, mContext );
98 mFramebufferTextures.insert(TexturePair(id, texture));
101 void TextureCache::AddFrameBuffer( ResourceId id, NativeImagePtr nativeImage )
103 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddFrameBuffer(id=%i width:%u height:%u)\n", id, nativeImage->GetWidth(), nativeImage->GetHeight());
105 // Note: Do not throttle framebuffer generation - a request for a framebuffer should always be honoured
106 // as soon as possible.
107 Texture* texture = TextureFactory::NewFrameBufferTexture( nativeImage, mContext );
108 mFramebufferTextures.insert(TexturePair(id, texture));
111 void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap )
113 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i bitmap:%p )\n", id, bitmap.Get());
115 TextureIter textureIter = mTextures.find(id);
116 if( textureIter != mTextures.end() )
118 // we have reloaded the image from file, update texture
119 TexturePointer texturePtr = textureIter->second;
122 texturePtr->Update(bitmap.Get());
124 ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
125 mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
130 void TextureCache::UpdateTextureArea( ResourceId id, const Dali::RectArea& area )
132 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTextureArea(id=%i)\n", id );
134 TextureIter textureIter = mTextures.find(id);
135 if( textureIter != mTextures.end() )
137 TexturePointer texturePtr = textureIter->second;
140 texturePtr->UpdateArea( area );
142 ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
143 mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
148 void TextureCache::AddBitmapUploadArray( ResourceId id, const BitmapUploadArray& uploadArray )
150 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddBitmapUploadArray(id=%i )\n", id);
152 TextureIter textureIter = mTextures.find(id);
154 DALI_ASSERT_DEBUG( textureIter != mTextures.end() );
155 if( textureIter != mTextures.end() )
157 TexturePointer texturePtr = textureIter->second;
160 BitmapTexture* texture = static_cast< BitmapTexture* >( texturePtr.Get() );
161 texture->UploadBitmapArray( uploadArray );
166 void TextureCache::ClearAreas( ResourceId id,
167 const BitmapClearArray& areaArray,
168 std::size_t blockSize,
171 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::ClearAreas(id: %d)\n", id);
172 TextureIter textureIter = mTextures.find(id);
173 DALI_ASSERT_DEBUG( textureIter != mTextures.end() );
174 if( textureIter != mTextures.end() )
176 TexturePointer texturePtr = textureIter->second;
179 BitmapTexture* texture = static_cast< BitmapTexture* >( texturePtr.Get() );
180 texture->ClearAreas( areaArray, blockSize, color );
185 void TextureCache::DiscardTexture( ResourceId id )
187 bool deleted = false;
189 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::DiscardTexture(id:%u)\n", id);
191 if( mTextures.size() > 0)
193 TextureIter iter = mTextures.find(id);
194 if( iter != mTextures.end() )
196 TexturePointer texturePtr = iter->second;
199 // if valid texture pointer, cleanup GL resources
200 texturePtr->GlCleanup();
202 mTextures.erase(iter);
207 if( mFramebufferTextures.size() > 0)
209 TextureIter iter = mFramebufferTextures.find(id);
210 if( iter != mFramebufferTextures.end() )
212 TexturePointer texturePtr = iter->second;
215 // if valid texture pointer, cleanup GL resources
216 texturePtr->GlCleanup();
218 mFramebufferTextures.erase(iter);
225 if( mObservers.size() > 0 )
227 TextureResourceObserversIter observersIter = mObservers.find(id);
228 if( observersIter != mObservers.end() )
230 TextureObservers observers = observersIter->second;
231 for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
233 TextureObserver* observer = *iter;
234 observer->TextureDiscarded( id );
237 mObservers.erase( observersIter );
241 // Tell resource manager
242 ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::DELETED );
243 mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
247 void TextureCache::BindTexture( Texture *texture, ResourceId id, GLenum target, GLenum textureunit )
249 bool created = texture->Bind(target, textureunit);
250 if( created && texture->UpdateOnCreate() ) // i.e. the pixel data was sent to GL
252 ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
253 mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
258 Texture* TextureCache::GetTexture(ResourceId id)
260 Texture* texture = NULL;
261 TextureIter iter = mTextures.find(id);
263 if( iter != mTextures.end() )
265 TexturePointer texturePtr = iter->second;
268 texture = texturePtr.Get();
272 if( texture == NULL )
274 TextureIter iter = mFramebufferTextures.find(id);
275 if( iter != mFramebufferTextures.end() )
277 TexturePointer texturePtr = iter->second;
280 texture = texturePtr.Get();
285 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::GetTexture(id:%u) : %p\n", id, texture);
290 FrameBufferTexture* TextureCache::GetFramebuffer(ResourceId id)
292 FrameBufferTexture* offscreen = NULL;
293 TextureIter iter = mFramebufferTextures.find(id);
295 DALI_ASSERT_DEBUG( iter != mFramebufferTextures.end() );
297 if( iter != mFramebufferTextures.end() )
299 TexturePointer texturePtr = iter->second;
302 offscreen = dynamic_cast< FrameBufferTexture* >( texturePtr.Get() );
305 DALI_ASSERT_DEBUG( offscreen );
307 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::GetFramebuffer(id:%u) : %p\n", id, offscreen);
312 void TextureCache::AddObserver( ResourceId id, TextureObserver* observer )
314 TextureResourceObserversIter observersIter = mObservers.find(id);
315 if( observersIter != mObservers.end() )
317 TextureObservers& observers = observersIter->second;
318 bool foundObserver = false;
319 for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
321 if( *iter == observer )
323 foundObserver = true;
327 if( ! foundObserver )
329 observers.push_back(observer);
334 TextureObservers observers;
335 observers.push_back(observer);
336 mObservers.insert(std::pair<ResourceId, TextureObservers>(id, observers));
340 void TextureCache::RemoveObserver( ResourceId id, TextureObserver* observer )
342 TextureResourceObserversIter observersIter = mObservers.find(id);
343 if( observersIter != mObservers.end() )
345 TextureObservers& observers = observersIter->second;
346 for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
348 if(*iter == observer)
350 observers.erase(iter);
357 void TextureCache::GlContextDestroyed()
359 TextureIter end = mTextures.end();
360 TextureIter iter = mTextures.begin();
361 for( ; iter != end; ++iter )
363 (*iter->second).GlContextDestroyed(); // map holds intrusive pointers
367 /********************************************************************************
368 ********************** Implements TextureCacheDispatcher *********************
369 ********************************************************************************/
371 void TextureCache::DispatchCreateTexture( ResourceId id,
374 Pixel::Format pixelFormat,
377 // NULL, means being shutdown, so ignore msgs
378 if( mSceneGraphBuffers != NULL )
380 typedef MessageValue5< TextureCache, ResourceId, unsigned int, unsigned int, Pixel::Format, bool > DerivedType;
382 // Reserve some memory inside the render queue
383 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
385 // Construct message in the render queue memory; note that delete should not be called on the return value
386 new (slot) DerivedType( this, &TextureCache::CreateTexture, id, width, height, pixelFormat, clearPixels );
390 void TextureCache::DispatchCreateTextureForBitmap( ResourceId id, Bitmap* bitmap )
392 // NULL, means being shutdown, so ignore msgs
393 if( mSceneGraphBuffers != NULL )
395 typedef MessageValue2< TextureCache, ResourceId, Integration::BitmapPtr > DerivedType;
397 // Reserve some memory inside the render queue
398 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
400 // Construct message in the render queue memory; note that delete should not be called on the return value
401 new (slot) DerivedType( this, &TextureCache::AddBitmap, id, bitmap );
405 void TextureCache::DispatchCreateTextureForNativeImage( ResourceId id, NativeImagePtr nativeImage )
407 // NULL, means being shutdown, so ignore msgs
408 if( mSceneGraphBuffers != NULL )
410 typedef MessageValue2< TextureCache, ResourceId, NativeImagePtr > DerivedType;
412 // Reserve some memory inside the render queue
413 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
415 // Construct message in the render queue memory; note that delete should not be called on the return value
416 new (slot) DerivedType( this, &TextureCache::AddNativeImage, id, nativeImage );
420 void TextureCache::DispatchCreateTextureForFrameBuffer( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat )
422 // NULL, means being shutdown, so ignore msgs
423 if( mSceneGraphBuffers != NULL )
425 typedef MessageValue4< TextureCache, ResourceId, unsigned int, unsigned int, Pixel::Format > DerivedType;
427 // Reserve some memory inside the render queue
428 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
430 // Construct message in the render queue memory; note that delete should not be called on the return value
431 new (slot) DerivedType( this, &TextureCache::AddFrameBuffer, id, width, height, pixelFormat );
435 void TextureCache::DispatchCreateTextureForFrameBuffer( ResourceId id, NativeImagePtr nativeImage )
437 // NULL, means being shutdown, so ignore msgs
438 if( mSceneGraphBuffers != NULL )
440 typedef MessageValue2< TextureCache, ResourceId, NativeImagePtr > DerivedType;
442 // Reserve some memory inside the render queue
443 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
445 // Construct message in the render queue memory; note that delete should not be called on the return value
446 new (slot) DerivedType( this, &TextureCache::AddFrameBuffer, id, nativeImage );
450 void TextureCache::DispatchUpdateTexture( ResourceId id, Bitmap* bitmap )
452 // NULL, means being shutdown, so ignore msgs
453 if( mSceneGraphBuffers != NULL )
455 typedef MessageValue2< TextureCache, ResourceId, Integration::BitmapPtr > DerivedType;
457 // Reserve some memory inside the render queue
458 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
460 // Construct message in the render queue memory; note that delete should not be called on the return value
461 new (slot) DerivedType( this, &TextureCache::UpdateTexture, id, bitmap );
465 void TextureCache::DispatchUpdateTextureArea( ResourceId id, const Dali::RectArea& area )
467 // NULL, means being shutdown, so ignore msgs
468 if( mSceneGraphBuffers != NULL )
470 typedef MessageValue2< TextureCache, ResourceId, Dali::RectArea > DerivedType;
472 // Reserve some memory inside the render queue
473 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
475 // Construct message in the render queue memory; note that delete should not be called on the return value
476 new (slot) DerivedType( this, &TextureCache::UpdateTextureArea, id, area );
480 void TextureCache::DispatchUploadBitmapArrayToTexture( ResourceId id, const BitmapUploadArray& uploadArray )
482 // NULL, means being shutdown, so ignore msgs
483 if( mSceneGraphBuffers != NULL )
485 typedef MessageValue2< TextureCache, ResourceId, BitmapUploadArray > DerivedType;
487 // Reserve some memory inside the render queue
488 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
490 // Construct message in the render queue memory; note that delete should not be called on the return value
491 new (slot) DerivedType( this, &TextureCache::AddBitmapUploadArray, id, uploadArray );
495 void TextureCache::DispatchClearAreas( ResourceId id, const BitmapClearArray& areaArray, std::size_t blockSize, uint32_t color )
497 // NULL, means being shutdown, so ignore msgs
498 if( mSceneGraphBuffers != NULL )
500 typedef MessageValue4< TextureCache, ResourceId, BitmapClearArray, std::size_t, uint32_t > DerivedType;
502 // Reserve some memory inside the render queue
503 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
505 // Construct message in the render queue memory; note that delete should not be called on the return value
506 new (slot) DerivedType( this, &TextureCache::ClearAreas, id, areaArray, blockSize, color );
510 void TextureCache::DispatchDiscardTexture( ResourceId id )
512 // NULL, means being shutdown, so ignore msgs
513 if( mSceneGraphBuffers != NULL )
515 typedef MessageValue1< TextureCache, ResourceId > DerivedType;
517 // Reserve some memory inside the render queue
518 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
520 // Construct message in the render queue memory; note that delete should not be called on the return value
521 new (slot) DerivedType( this, &TextureCache::DiscardTexture, id );