2 * Copyright (c) 2016 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/render/gl-resources/texture-cache.h>
22 #include <dali/integration-api/debug.h>
23 #include <dali/integration-api/bitmap.h>
24 #include <dali/internal/render/common/texture-uploaded-dispatcher.h>
25 #include <dali/internal/render/queue/render-queue.h>
26 #include <dali/internal/render/gl-resources/context.h>
27 #include <dali/internal/render/gl-resources/texture-factory.h>
28 #include <dali/internal/render/gl-resources/texture-cache.h>
29 #include <dali/internal/render/gl-resources/texture-observer.h>
30 #include <dali/internal/render/gl-resources/bitmap-texture.h>
31 #include <dali/internal/render/gl-resources/native-texture.h>
32 #include <dali/internal/render/gl-resources/frame-buffer-texture.h>
33 #include <dali/internal/update/resources/resource-manager-declarations.h>
34 #include <dali/internal/render/gl-resources/gl-texture.h>
36 using Dali::Internal::Texture;
37 using Dali::Internal::FrameBufferTexture;
38 using Dali::Integration::Bitmap;
42 #if defined(DEBUG_ENABLED)
43 Debug::Filter* gTextureCacheFilter = Debug::Filter::New(Debug::Concise, false, "LOG_TEXTURE_CACHE");
61 * @brief Forward to all textures in container the news that the GL Context is down.
63 void GlContextDestroyed( TextureContainer& textures )
65 TextureIter end = textures.end();
66 TextureIter iter = textures.begin();
67 for( ; iter != end; ++iter )
69 (*iter->second).GlContextDestroyed();
75 TextureCache::TextureCache( RenderQueue& renderQueue,
76 TextureUploadedDispatcher& postProcessResourceDispatcher,
78 : mTextureUploadedDispatcher(postProcessResourceDispatcher),
80 mDiscardBitmapsPolicy(ResourcePolicy::OWNED_DISCARD)
84 TextureCache::~TextureCache()
88 void TextureCache::CreateTexture( ResourceId id,
91 Pixel::Format pixelFormat,
94 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::CreateTexture(id=%i width:%u height:%u)\n", id, width, height);
96 Texture* texture = TextureFactory::NewBitmapTexture(width, height, pixelFormat, clearPixels, mContext, GetDiscardBitmapsPolicy() );
97 mTextures.insert(TexturePair(id, texture));
100 void TextureCache::AddBitmap(ResourceId id, Integration::BitmapPtr bitmap)
102 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddBitmap(id=%i Bitmap:%p)\n", id, bitmap.Get());
104 Texture* texture = TextureFactory::NewBitmapTexture(bitmap.Get(), mContext, GetDiscardBitmapsPolicy());
105 mTextures.insert(TexturePair(id, texture));
108 void TextureCache::AddNativeImage(ResourceId id, NativeImageInterfacePtr nativeImage)
110 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddNativeImage(id=%i NativeImg:%p)\n", id, nativeImage.Get());
112 /// WARNING - currently a new Texture is created even if we reuse the same NativeImage
113 Texture* texture = TextureFactory::NewNativeImageTexture(*nativeImage, mContext);
114 mTextures.insert(TexturePair(id, texture));
117 void TextureCache::AddFrameBuffer( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat )
119 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddFrameBuffer(id=%i width:%u height:%u)\n", id, width, height);
121 // Note: Do not throttle framebuffer generation - a request for a framebuffer should always be honoured
122 // as soon as possible.
123 Texture* texture = TextureFactory::NewFrameBufferTexture( width, height, pixelFormat, bufferFormat, mContext );
124 mFramebufferTextures.insert(TexturePair(id, texture));
127 void TextureCache::AddFrameBuffer( ResourceId id, NativeImageInterfacePtr nativeImage )
129 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddFrameBuffer(id=%i width:%u height:%u)\n", id, nativeImage->GetWidth(), nativeImage->GetHeight());
131 // Note: Do not throttle framebuffer generation - a request for a framebuffer should always be honoured
132 // as soon as possible.
133 Texture* texture = TextureFactory::NewFrameBufferTexture( nativeImage, mContext );
134 mFramebufferTextures.insert(TexturePair(id, texture));
137 void TextureCache::CreateGlTexture( ResourceId id )
139 TextureIter textureIter = mTextures.find(id);
140 // If we found a non-null texture object pointer for the resource id, force it
141 // to eagerly allocate a backing GL texture:
142 if( textureIter != mTextures.end() )
144 TexturePointer texturePtr = textureIter->second;
147 texturePtr->CreateGlTexture();
152 void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap )
154 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i bitmap:%p )\n", id, bitmap.Get());
156 TextureIter textureIter = mTextures.find(id);
157 if( textureIter != mTextures.end() )
159 // we have reloaded the image from file, update texture
160 TexturePointer texturePtr = textureIter->second;
163 texturePtr->Update( bitmap.Get() );
165 ResourceId ppRequest( id );
166 mTextureUploadedDispatcher.DispatchTextureUploaded(ppRequest);
171 void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset )
173 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i bitmap:%p )\n", id, bitmap.Get());
175 TextureIter textureIter = mTextures.find(id);
176 if( textureIter != mTextures.end() )
178 TexturePointer texturePtr = textureIter->second;
181 texturePtr->Update( bitmap.Get(), xOffset, yOffset );
183 ResourceId ppRequest( id );
184 mTextureUploadedDispatcher.DispatchTextureUploaded(ppRequest);
189 void TextureCache::UpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
191 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(destId=%i srcId=%i )\n", destId, srcId );
193 BitmapTexture* srcTexture = TextureCache::GetBitmapTexture( srcId );
194 Integration::BitmapPtr srcBitmap = ( srcTexture != NULL ) ? srcTexture->GetBitmap() : NULL;
198 UpdateTexture( destId, srcBitmap, xOffset, yOffset );
202 void TextureCache::UpdateTexture( ResourceId id, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset )
204 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i pixel data:%p )\n", id, pixelData.Get());
206 TextureIter textureIter = mTextures.find(id);
207 if( textureIter != mTextures.end() )
209 TexturePointer texturePtr = textureIter->second;
212 texturePtr->Update( pixelData.Get(), xOffset, yOffset );
214 ResourceId ppRequest( id );
215 mTextureUploadedDispatcher.DispatchTextureUploaded(ppRequest);
220 void TextureCache::UpdateTextureArea( ResourceId id, const RectArea& area )
222 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTextureArea(id=%i)\n", id );
224 TextureIter textureIter = mTextures.find(id);
225 if( textureIter != mTextures.end() )
227 TexturePointer texturePtr = textureIter->second;
230 texturePtr->UpdateArea( area );
232 ResourceId ppRequest( id );
233 mTextureUploadedDispatcher.DispatchTextureUploaded(ppRequest);
238 void TextureCache::DiscardTexture( ResourceId id )
240 bool deleted = false;
242 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::DiscardTexture(id:%u)\n", id);
244 if( mTextures.size() > 0)
246 TextureIter iter = mTextures.find(id);
247 if( iter != mTextures.end() )
249 TexturePointer texturePtr = iter->second;
252 // if valid texture pointer, cleanup GL resources
253 texturePtr->GlCleanup();
255 mTextures.erase(iter);
260 if( mFramebufferTextures.size() > 0)
262 TextureIter iter = mFramebufferTextures.find(id);
263 if( iter != mFramebufferTextures.end() )
265 TexturePointer texturePtr = iter->second;
268 // if valid texture pointer, cleanup GL resources
269 texturePtr->GlCleanup();
271 mFramebufferTextures.erase(iter);
278 if( mObservers.size() > 0 )
280 TextureResourceObserversIter observersIter = mObservers.find(id);
281 if( observersIter != mObservers.end() )
283 TextureObservers observers = observersIter->second;
284 for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
286 TextureObserver* observer = *iter;
287 observer->TextureDiscarded( id );
290 mObservers.erase( observersIter );
296 bool TextureCache::BindTexture( Texture *texture, ResourceId id, GLenum target, TextureUnit textureunit )
298 unsigned int glTextureId = texture->GetTextureId();
300 bool success = texture->Bind(target, textureunit);
301 bool created = ( glTextureId == 0 ) && ( texture->GetTextureId() != 0 );
303 if( created && texture->UpdateOnCreate() ) // i.e. the pixel data was sent to GL
305 ResourceId ppRequest( id );
306 mTextureUploadedDispatcher.DispatchTextureUploaded(ppRequest);
311 Texture* TextureCache::GetTexture(ResourceId id)
313 Texture* texture = NULL;
314 TextureIter iter = mTextures.find(id);
316 if( iter != mTextures.end() )
318 TexturePointer texturePtr = iter->second;
321 texture = texturePtr.Get();
325 if( texture == NULL )
327 TextureIter iter = mFramebufferTextures.find(id);
328 if( iter != mFramebufferTextures.end() )
330 TexturePointer texturePtr = iter->second;
333 texture = texturePtr.Get();
338 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::GetTexture(id:%u) : %p\n", id, texture);
343 BitmapTexture* TextureCache::GetBitmapTexture(ResourceId id)
345 BitmapTexture* texture = NULL;
346 TextureIter iter = mTextures.find( id );
348 if( iter != mTextures.end() )
350 TexturePointer texturePtr = iter->second;
353 texture = dynamic_cast< BitmapTexture* >( texturePtr.Get() );
360 FrameBufferTexture* TextureCache::GetFramebuffer(ResourceId id)
362 FrameBufferTexture* offscreen = NULL;
363 TextureIter iter = mFramebufferTextures.find(id);
365 DALI_ASSERT_DEBUG( iter != mFramebufferTextures.end() );
367 if( iter != mFramebufferTextures.end() )
369 TexturePointer texturePtr = iter->second;
372 offscreen = dynamic_cast< FrameBufferTexture* >( texturePtr.Get() );
375 DALI_ASSERT_DEBUG( offscreen );
377 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::GetFramebuffer(id:%u) : %p\n", id, offscreen);
382 void TextureCache::AddObserver( ResourceId id, TextureObserver* observer )
384 TextureResourceObserversIter observersIter = mObservers.find(id);
385 if( observersIter != mObservers.end() )
387 TextureObservers& observers = observersIter->second;
388 bool foundObserver = false;
389 for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
391 if( *iter == observer )
393 foundObserver = true;
397 if( ! foundObserver )
399 observers.push_back(observer);
404 TextureObservers observers;
405 observers.push_back(observer);
406 mObservers.insert(std::pair<ResourceId, TextureObservers>(id, observers));
410 void TextureCache::RemoveObserver( ResourceId id, TextureObserver* observer )
412 TextureResourceObserversIter observersIter = mObservers.find(id);
413 if( observersIter != mObservers.end() )
415 TextureObservers& observers = observersIter->second;
416 for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
418 if(*iter == observer)
420 observers.erase(iter);
427 void TextureCache::GlContextDestroyed()
429 SceneGraph::GlContextDestroyed( mTextures );
430 SceneGraph::GlContextDestroyed( mFramebufferTextures );
433 void TextureCache::SetDiscardBitmapsPolicy( ResourcePolicy::Discardable policy )
435 DALI_LOG_INFO( gTextureCacheFilter, Debug::General, "TextureCache::SetDiscardBitmapsPolicy(%s)\n",
436 policy==ResourcePolicy::OWNED_DISCARD?"DISCARD":"RETAIN" );
437 mDiscardBitmapsPolicy = policy;
440 ResourcePolicy::Discardable TextureCache::GetDiscardBitmapsPolicy()
442 return mDiscardBitmapsPolicy;