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.
18 #include <dali/internal/render/gl-resources/texture-cache.h>
20 #include <dali/integration-api/bitmap.h>
22 #include <dali/internal/update/resources/resource-manager-declarations.h>
23 #include <dali/internal/render/common/post-process-resource-dispatcher.h>
24 #include <dali/internal/render/queue/render-queue.h>
25 #include <dali/internal/render/gl-resources/context.h>
26 #include <dali/internal/render/gl-resources/texture-factory.h>
27 #include <dali/internal/render/gl-resources/texture.h>
28 #include <dali/internal/render/gl-resources/texture-observer.h>
29 #include <dali/internal/render/gl-resources/bitmap-texture.h>
30 #include <dali/internal/render/gl-resources/native-texture.h>
31 #include <dali/internal/render/gl-resources/frame-buffer-texture.h>
33 #include <dali/integration-api/debug.h>
35 using Dali::Internal::Texture;
36 using Dali::Internal::FrameBufferTexture;
37 using Dali::Integration::Bitmap;
44 // value types used by messages
45 template <> struct ParameterType< Pixel::Format > : public BasicType< Pixel::Format > {};
50 TextureCache::TextureCache( RenderQueue& renderQueue,
51 PostProcessResourceDispatcher& postProcessResourceDispatcher,
53 : TextureCacheDispatcher(renderQueue),
54 mPostProcessResourceDispatcher(postProcessResourceDispatcher),
59 TextureCache::~TextureCache()
63 void TextureCache::CreateTexture( ResourceId id,
66 Pixel::Format pixelFormat,
69 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::CreateTexture(id=%i width:%u height:%u)\n", id, width, height);
71 Texture* texture = TextureFactory::NewBitmapTexture(width, height, pixelFormat, clearPixels, mContext);
72 mTextures.insert(TexturePair(id, texture));
75 void TextureCache::AddBitmap(ResourceId id, Integration::BitmapPtr bitmap)
77 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddBitmap(id=%i Bitmap:%p)\n", id, bitmap.Get());
79 Texture* texture = TextureFactory::NewBitmapTexture(bitmap.Get(), mContext);
80 mTextures.insert(TexturePair(id, texture));
83 void TextureCache::AddNativeImage(ResourceId id, NativeImagePtr nativeImage)
85 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddNativeImage(id=%i NativeImg:%p)\n", id, nativeImage.Get());
87 /// TODO - currently a new Texture is created even if we reuse the same NativeImage
88 Texture* texture = TextureFactory::NewNativeImageTexture(*nativeImage, mContext);
89 mTextures.insert(TexturePair(id, texture));
92 void TextureCache::AddFrameBuffer( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat )
94 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddFrameBuffer(id=%i width:%u height:%u)\n", id, width, height);
96 // Note: Do not throttle framebuffer generation - a request for a framebuffer should always be honoured
97 // as soon as possible.
98 Texture* texture = TextureFactory::NewFrameBufferTexture( width, height, pixelFormat, mContext );
99 mFramebufferTextures.insert(TexturePair(id, texture));
102 void TextureCache::AddFrameBuffer( ResourceId id, NativeImagePtr nativeImage )
104 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddFrameBuffer(id=%i width:%u height:%u)\n", id, nativeImage->GetWidth(), nativeImage->GetHeight());
106 // Note: Do not throttle framebuffer generation - a request for a framebuffer should always be honoured
107 // as soon as possible.
108 Texture* texture = TextureFactory::NewFrameBufferTexture( nativeImage, mContext );
109 mFramebufferTextures.insert(TexturePair(id, texture));
112 void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap )
114 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i bitmap:%p )\n", id, bitmap.Get());
116 TextureIter textureIter = mTextures.find(id);
117 if( textureIter != mTextures.end() )
119 // we have reloaded the image from file, update texture
120 TexturePointer texturePtr = textureIter->second;
123 texturePtr->Update(bitmap.Get());
125 ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
126 mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
131 void TextureCache::UpdateTextureArea( ResourceId id, const Dali::RectArea& area )
133 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTextureArea(id=%i)\n", id );
135 TextureIter textureIter = mTextures.find(id);
136 if( textureIter != mTextures.end() )
138 TexturePointer texturePtr = textureIter->second;
141 texturePtr->UpdateArea( area );
143 ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
144 mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
149 void TextureCache::AddBitmapUploadArray( ResourceId id, const BitmapUploadArray& uploadArray )
151 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddBitmapUploadArray(id=%i )\n", id);
153 TextureIter textureIter = mTextures.find(id);
155 DALI_ASSERT_DEBUG( textureIter != mTextures.end() );
156 if( textureIter != mTextures.end() )
158 TexturePointer texturePtr = textureIter->second;
161 BitmapTexture* texture = static_cast< BitmapTexture* >( texturePtr.Get() );
162 texture->UploadBitmapArray( uploadArray );
167 void TextureCache::ClearAreas( ResourceId id,
168 const BitmapClearArray& areaArray,
169 std::size_t blockSize,
172 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::ClearAreas(id: %d)\n", id);
173 TextureIter textureIter = mTextures.find(id);
174 DALI_ASSERT_DEBUG( textureIter != mTextures.end() );
175 if( textureIter != mTextures.end() )
177 TexturePointer texturePtr = textureIter->second;
180 BitmapTexture* texture = static_cast< BitmapTexture* >( texturePtr.Get() );
181 texture->ClearAreas( areaArray, blockSize, color );
186 void TextureCache::DiscardTexture( ResourceId id )
188 bool deleted = false;
190 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::DiscardTexture(id:%u)\n", id);
192 if( mTextures.size() > 0)
194 TextureIter iter = mTextures.find(id);
195 if( iter != mTextures.end() )
197 TexturePointer texturePtr = iter->second;
200 // if valid texture pointer, cleanup GL resources
201 texturePtr->GlCleanup();
203 mTextures.erase(iter);
208 if( mFramebufferTextures.size() > 0)
210 TextureIter iter = mFramebufferTextures.find(id);
211 if( iter != mFramebufferTextures.end() )
213 TexturePointer texturePtr = iter->second;
216 // if valid texture pointer, cleanup GL resources
217 texturePtr->GlCleanup();
219 mFramebufferTextures.erase(iter);
226 if( mObservers.size() > 0 )
228 TextureResourceObserversIter observersIter = mObservers.find(id);
229 if( observersIter != mObservers.end() )
231 TextureObservers observers = observersIter->second;
232 for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
234 TextureObserver* observer = *iter;
235 observer->TextureDiscarded( id );
238 mObservers.erase( observersIter );
242 // Tell resource manager
243 ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::DELETED );
244 mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
248 void TextureCache::BindTexture( Texture *texture, ResourceId id, GLenum target, GLenum textureunit )
250 bool created = texture->Bind(target, textureunit);
251 if( created && texture->UpdateOnCreate() ) // i.e. the pixel data was sent to GL
253 ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
254 mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
259 Texture* TextureCache::GetTexture(ResourceId id)
261 Texture* texture = NULL;
262 TextureIter iter = mTextures.find(id);
264 if( iter != mTextures.end() )
266 TexturePointer texturePtr = iter->second;
269 texture = texturePtr.Get();
273 if( texture == NULL )
275 TextureIter iter = mFramebufferTextures.find(id);
276 if( iter != mFramebufferTextures.end() )
278 TexturePointer texturePtr = iter->second;
281 texture = texturePtr.Get();
286 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::GetTexture(id:%u) : %p\n", id, texture);
291 FrameBufferTexture* TextureCache::GetFramebuffer(ResourceId id)
293 FrameBufferTexture* offscreen = NULL;
294 TextureIter iter = mFramebufferTextures.find(id);
296 DALI_ASSERT_DEBUG( iter != mFramebufferTextures.end() );
298 if( iter != mFramebufferTextures.end() )
300 TexturePointer texturePtr = iter->second;
303 offscreen = dynamic_cast< FrameBufferTexture* >( texturePtr.Get() );
306 DALI_ASSERT_DEBUG( offscreen );
308 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::GetFramebuffer(id:%u) : %p\n", id, offscreen);
313 void TextureCache::AddObserver( ResourceId id, TextureObserver* observer )
315 TextureResourceObserversIter observersIter = mObservers.find(id);
316 if( observersIter != mObservers.end() )
318 TextureObservers& observers = observersIter->second;
319 bool foundObserver = false;
320 for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
322 if( *iter == observer )
324 foundObserver = true;
328 if( ! foundObserver )
330 observers.push_back(observer);
335 TextureObservers observers;
336 observers.push_back(observer);
337 mObservers.insert(std::pair<ResourceId, TextureObservers>(id, observers));
341 void TextureCache::RemoveObserver( ResourceId id, TextureObserver* observer )
343 TextureResourceObserversIter observersIter = mObservers.find(id);
344 if( observersIter != mObservers.end() )
346 TextureObservers& observers = observersIter->second;
347 for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
349 if(*iter == observer)
351 observers.erase(iter);
358 void TextureCache::GlContextDestroyed()
360 TextureIter end = mTextures.end();
361 TextureIter iter = mTextures.begin();
362 for( ; iter != end; ++iter )
364 (*iter->second).GlContextDestroyed(); // map holds intrusive pointers
368 /********************************************************************************
369 ********************** Implements TextureCacheDispatcher *********************
370 ********************************************************************************/
372 void TextureCache::DispatchCreateTexture( ResourceId id,
375 Pixel::Format pixelFormat,
378 // NULL, means being shutdown, so ignore msgs
379 if( mSceneGraphBuffers != NULL )
381 typedef MessageValue5< TextureCache, ResourceId, unsigned int, unsigned int, Pixel::Format, bool > DerivedType;
383 // Reserve some memory inside the render queue
384 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
386 // Construct message in the render queue memory; note that delete should not be called on the return value
387 new (slot) DerivedType( this, &TextureCache::CreateTexture, id, width, height, pixelFormat, clearPixels );
391 void TextureCache::DispatchCreateTextureForBitmap( ResourceId id, Bitmap* bitmap )
393 // NULL, means being shutdown, so ignore msgs
394 if( mSceneGraphBuffers != NULL )
396 typedef MessageValue2< TextureCache, ResourceId, Integration::BitmapPtr > DerivedType;
398 // Reserve some memory inside the render queue
399 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
401 // Construct message in the render queue memory; note that delete should not be called on the return value
402 new (slot) DerivedType( this, &TextureCache::AddBitmap, id, bitmap );
406 void TextureCache::DispatchCreateTextureForNativeImage( ResourceId id, NativeImagePtr nativeImage )
408 // NULL, means being shutdown, so ignore msgs
409 if( mSceneGraphBuffers != NULL )
411 typedef MessageValue2< TextureCache, ResourceId, NativeImagePtr > DerivedType;
413 // Reserve some memory inside the render queue
414 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
416 // Construct message in the render queue memory; note that delete should not be called on the return value
417 new (slot) DerivedType( this, &TextureCache::AddNativeImage, id, nativeImage );
421 void TextureCache::DispatchCreateTextureForFrameBuffer( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat )
423 // NULL, means being shutdown, so ignore msgs
424 if( mSceneGraphBuffers != NULL )
426 typedef MessageValue4< TextureCache, ResourceId, unsigned int, unsigned int, Pixel::Format > DerivedType;
428 // Reserve some memory inside the render queue
429 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
431 // Construct message in the render queue memory; note that delete should not be called on the return value
432 new (slot) DerivedType( this, &TextureCache::AddFrameBuffer, id, width, height, pixelFormat );
436 void TextureCache::DispatchCreateTextureForFrameBuffer( ResourceId id, NativeImagePtr nativeImage )
438 // NULL, means being shutdown, so ignore msgs
439 if( mSceneGraphBuffers != NULL )
441 typedef MessageValue2< TextureCache, ResourceId, NativeImagePtr > DerivedType;
443 // Reserve some memory inside the render queue
444 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
446 // Construct message in the render queue memory; note that delete should not be called on the return value
447 new (slot) DerivedType( this, &TextureCache::AddFrameBuffer, id, nativeImage );
451 void TextureCache::DispatchUpdateTexture( ResourceId id, Bitmap* bitmap )
453 // NULL, means being shutdown, so ignore msgs
454 if( mSceneGraphBuffers != NULL )
456 typedef MessageValue2< TextureCache, ResourceId, Integration::BitmapPtr > DerivedType;
458 // Reserve some memory inside the render queue
459 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
461 // Construct message in the render queue memory; note that delete should not be called on the return value
462 new (slot) DerivedType( this, &TextureCache::UpdateTexture, id, bitmap );
466 void TextureCache::DispatchUpdateTextureArea( ResourceId id, const Dali::RectArea& area )
468 // NULL, means being shutdown, so ignore msgs
469 if( mSceneGraphBuffers != NULL )
471 typedef MessageValue2< TextureCache, ResourceId, Dali::RectArea > DerivedType;
473 // Reserve some memory inside the render queue
474 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
476 // Construct message in the render queue memory; note that delete should not be called on the return value
477 new (slot) DerivedType( this, &TextureCache::UpdateTextureArea, id, area );
481 void TextureCache::DispatchUploadBitmapArrayToTexture( ResourceId id, const BitmapUploadArray& uploadArray )
483 // NULL, means being shutdown, so ignore msgs
484 if( mSceneGraphBuffers != NULL )
486 typedef MessageValue2< TextureCache, ResourceId, BitmapUploadArray > DerivedType;
488 // Reserve some memory inside the render queue
489 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
491 // Construct message in the render queue memory; note that delete should not be called on the return value
492 new (slot) DerivedType( this, &TextureCache::AddBitmapUploadArray, id, uploadArray );
496 void TextureCache::DispatchClearAreas( ResourceId id, const BitmapClearArray& areaArray, std::size_t blockSize, uint32_t color )
498 // NULL, means being shutdown, so ignore msgs
499 if( mSceneGraphBuffers != NULL )
501 typedef MessageValue4< TextureCache, ResourceId, BitmapClearArray, std::size_t, uint32_t > DerivedType;
503 // Reserve some memory inside the render queue
504 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
506 // Construct message in the render queue memory; note that delete should not be called on the return value
507 new (slot) DerivedType( this, &TextureCache::ClearAreas, id, areaArray, blockSize, color );
511 void TextureCache::DispatchDiscardTexture( ResourceId id )
513 // NULL, means being shutdown, so ignore msgs
514 if( mSceneGraphBuffers != NULL )
516 typedef MessageValue1< TextureCache, ResourceId > DerivedType;
518 // Reserve some memory inside the render queue
519 unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
521 // Construct message in the render queue memory; note that delete should not be called on the return value
522 new (slot) DerivedType( this, &TextureCache::DiscardTexture, id );