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/event/resources/resource-client.h> // For RectArea
25 #include <dali/internal/render/common/texture-uploaded-dispatcher.h>
26 #include <dali/internal/render/queue/render-queue.h>
27 #include <dali/internal/render/gl-resources/context.h>
28 #include <dali/internal/render/gl-resources/texture-factory.h>
29 #include <dali/internal/render/gl-resources/texture-cache.h>
30 #include <dali/internal/render/gl-resources/texture-observer.h>
31 #include <dali/internal/render/gl-resources/bitmap-texture.h>
32 #include <dali/internal/render/gl-resources/native-texture.h>
33 #include <dali/internal/render/gl-resources/frame-buffer-texture.h>
34 #include <dali/internal/update/resources/resource-manager-declarations.h>
35 #include <dali/internal/render/gl-resources/gl-texture.h>
37 using Dali::Internal::Texture;
38 using Dali::Internal::FrameBufferTexture;
39 using Dali::Integration::Bitmap;
43 #if defined(DEBUG_ENABLED)
44 Debug::Filter* gTextureCacheFilter = Debug::Filter::New(Debug::Concise, false, "LOG_TEXTURE_CACHE");
62 * @brief Forward to all textures in container the news that the GL Context is down.
64 void GlContextDestroyed( TextureContainer& textures )
66 TextureIter end = textures.end();
67 TextureIter iter = textures.begin();
68 for( ; iter != end; ++iter )
70 (*iter->second).GlContextDestroyed();
76 TextureCache::TextureCache( RenderQueue& renderQueue,
77 TextureUploadedDispatcher& postProcessResourceDispatcher,
79 : mTextureUploadedDispatcher(postProcessResourceDispatcher),
81 mDiscardBitmapsPolicy(ResourcePolicy::OWNED_DISCARD)
85 TextureCache::~TextureCache()
89 void TextureCache::CreateTexture( ResourceId id,
92 Pixel::Format pixelFormat,
95 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::CreateTexture(id=%i width:%u height:%u)\n", id, width, height);
97 Texture* texture = TextureFactory::NewBitmapTexture(width, height, pixelFormat, clearPixels, mContext, GetDiscardBitmapsPolicy() );
98 mTextures.insert(TexturePair(id, texture));
101 void TextureCache::AddBitmap(ResourceId id, Integration::BitmapPtr bitmap)
103 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddBitmap(id=%i Bitmap:%p)\n", id, bitmap.Get());
105 Texture* texture = TextureFactory::NewBitmapTexture(bitmap.Get(), mContext, GetDiscardBitmapsPolicy());
106 mTextures.insert(TexturePair(id, texture));
109 void TextureCache::AddNativeImage(ResourceId id, NativeImageInterfacePtr nativeImage)
111 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddNativeImage(id=%i NativeImg:%p)\n", id, nativeImage.Get());
113 /// WARNING - currently a new Texture is created even if we reuse the same NativeImage
114 Texture* texture = TextureFactory::NewNativeImageTexture(*nativeImage, mContext);
115 mTextures.insert(TexturePair(id, texture));
118 void TextureCache::AddFrameBuffer( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat )
120 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddFrameBuffer(id=%i width:%u height:%u)\n", id, width, height);
122 // Note: Do not throttle framebuffer generation - a request for a framebuffer should always be honoured
123 // as soon as possible.
124 Texture* texture = TextureFactory::NewFrameBufferTexture( width, height, pixelFormat, bufferFormat, mContext );
125 mFramebufferTextures.insert(TexturePair(id, texture));
128 void TextureCache::AddFrameBuffer( ResourceId id, NativeImageInterfacePtr nativeImage )
130 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddFrameBuffer(id=%i width:%u height:%u)\n", id, nativeImage->GetWidth(), nativeImage->GetHeight());
132 // Note: Do not throttle framebuffer generation - a request for a framebuffer should always be honoured
133 // as soon as possible.
134 Texture* texture = TextureFactory::NewFrameBufferTexture( nativeImage, mContext );
135 mFramebufferTextures.insert(TexturePair(id, texture));
138 void TextureCache::CreateGlTexture( ResourceId id )
140 TextureIter textureIter = mTextures.find(id);
141 // If we found a non-null texture object pointer for the resource id, force it
142 // to eagerly allocate a backing GL texture:
143 if( textureIter != mTextures.end() )
145 TexturePointer texturePtr = textureIter->second;
148 texturePtr->CreateGlTexture();
153 void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap )
155 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i bitmap:%p )\n", id, bitmap.Get());
157 TextureIter textureIter = mTextures.find(id);
158 if( textureIter != mTextures.end() )
160 // we have reloaded the image from file, update texture
161 TexturePointer texturePtr = textureIter->second;
164 texturePtr->Update( bitmap.Get() );
166 ResourceId ppRequest( id );
167 mTextureUploadedDispatcher.DispatchTextureUploaded(ppRequest);
172 void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset )
174 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i bitmap:%p )\n", id, bitmap.Get());
176 TextureIter textureIter = mTextures.find(id);
177 if( textureIter != mTextures.end() )
179 TexturePointer texturePtr = textureIter->second;
182 texturePtr->Update( bitmap.Get(), xOffset, yOffset );
184 ResourceId ppRequest( id );
185 mTextureUploadedDispatcher.DispatchTextureUploaded(ppRequest);
190 void TextureCache::UpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
192 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(destId=%i srcId=%i )\n", destId, srcId );
194 BitmapTexture* srcTexture = TextureCache::GetBitmapTexture( srcId );
195 Integration::BitmapPtr srcBitmap = ( srcTexture != NULL ) ? srcTexture->GetBitmap() : NULL;
199 UpdateTexture( destId, srcBitmap, xOffset, yOffset );
203 void TextureCache::UpdateTexture( ResourceId id, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset )
205 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i pixel data:%p )\n", id, pixelData.Get());
207 TextureIter textureIter = mTextures.find(id);
208 if( textureIter != mTextures.end() )
210 TexturePointer texturePtr = textureIter->second;
213 texturePtr->Update( pixelData.Get(), xOffset, yOffset );
215 ResourceId ppRequest( id );
216 mTextureUploadedDispatcher.DispatchTextureUploaded(ppRequest);
221 void TextureCache::UpdateTextureArea( ResourceId id, const RectArea& area )
223 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTextureArea(id=%i)\n", id );
225 TextureIter textureIter = mTextures.find(id);
226 if( textureIter != mTextures.end() )
228 TexturePointer texturePtr = textureIter->second;
231 texturePtr->UpdateArea( area );
233 ResourceId ppRequest( id );
234 mTextureUploadedDispatcher.DispatchTextureUploaded(ppRequest);
239 void TextureCache::DiscardTexture( ResourceId id )
241 bool deleted = false;
243 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::DiscardTexture(id:%u)\n", id);
245 if( mTextures.size() > 0)
247 TextureIter iter = mTextures.find(id);
248 if( iter != mTextures.end() )
250 TexturePointer texturePtr = iter->second;
253 // if valid texture pointer, cleanup GL resources
254 texturePtr->GlCleanup();
256 mTextures.erase(iter);
261 if( mFramebufferTextures.size() > 0)
263 TextureIter iter = mFramebufferTextures.find(id);
264 if( iter != mFramebufferTextures.end() )
266 TexturePointer texturePtr = iter->second;
269 // if valid texture pointer, cleanup GL resources
270 texturePtr->GlCleanup();
272 mFramebufferTextures.erase(iter);
279 if( mObservers.size() > 0 )
281 TextureResourceObserversIter observersIter = mObservers.find(id);
282 if( observersIter != mObservers.end() )
284 TextureObservers observers = observersIter->second;
285 for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
287 TextureObserver* observer = *iter;
288 observer->TextureDiscarded( id );
291 mObservers.erase( observersIter );
297 bool TextureCache::BindTexture( Texture *texture, ResourceId id, GLenum target, TextureUnit textureunit )
299 unsigned int glTextureId = texture->GetTextureId();
301 bool success = texture->Bind(target, textureunit);
302 bool created = ( glTextureId == 0 ) && ( texture->GetTextureId() != 0 );
304 if( created && texture->UpdateOnCreate() ) // i.e. the pixel data was sent to GL
306 ResourceId ppRequest( id );
307 mTextureUploadedDispatcher.DispatchTextureUploaded(ppRequest);
312 Texture* TextureCache::GetTexture(ResourceId id)
314 Texture* texture = NULL;
315 TextureIter iter = mTextures.find(id);
317 if( iter != mTextures.end() )
319 TexturePointer texturePtr = iter->second;
322 texture = texturePtr.Get();
326 if( texture == NULL )
328 TextureIter iter = mFramebufferTextures.find(id);
329 if( iter != mFramebufferTextures.end() )
331 TexturePointer texturePtr = iter->second;
334 texture = texturePtr.Get();
339 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::GetTexture(id:%u) : %p\n", id, texture);
344 BitmapTexture* TextureCache::GetBitmapTexture(ResourceId id)
346 BitmapTexture* texture = NULL;
347 TextureIter iter = mTextures.find( id );
349 if( iter != mTextures.end() )
351 TexturePointer texturePtr = iter->second;
354 texture = dynamic_cast< BitmapTexture* >( texturePtr.Get() );
361 FrameBufferTexture* TextureCache::GetFramebuffer(ResourceId id)
363 FrameBufferTexture* offscreen = NULL;
364 TextureIter iter = mFramebufferTextures.find(id);
366 DALI_ASSERT_DEBUG( iter != mFramebufferTextures.end() );
368 if( iter != mFramebufferTextures.end() )
370 TexturePointer texturePtr = iter->second;
373 offscreen = dynamic_cast< FrameBufferTexture* >( texturePtr.Get() );
376 DALI_ASSERT_DEBUG( offscreen );
378 DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::GetFramebuffer(id:%u) : %p\n", id, offscreen);
383 void TextureCache::AddObserver( ResourceId id, TextureObserver* observer )
385 TextureResourceObserversIter observersIter = mObservers.find(id);
386 if( observersIter != mObservers.end() )
388 TextureObservers& observers = observersIter->second;
389 bool foundObserver = false;
390 for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
392 if( *iter == observer )
394 foundObserver = true;
398 if( ! foundObserver )
400 observers.push_back(observer);
405 TextureObservers observers;
406 observers.push_back(observer);
407 mObservers.insert(std::pair<ResourceId, TextureObservers>(id, observers));
411 void TextureCache::RemoveObserver( ResourceId id, TextureObserver* observer )
413 TextureResourceObserversIter observersIter = mObservers.find(id);
414 if( observersIter != mObservers.end() )
416 TextureObservers& observers = observersIter->second;
417 for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
419 if(*iter == observer)
421 observers.erase(iter);
428 void TextureCache::GlContextDestroyed()
430 SceneGraph::GlContextDestroyed( mTextures );
431 SceneGraph::GlContextDestroyed( mFramebufferTextures );
434 void TextureCache::SetDiscardBitmapsPolicy( ResourcePolicy::Discardable policy )
436 DALI_LOG_INFO( gTextureCacheFilter, Debug::General, "TextureCache::SetDiscardBitmapsPolicy(%s)\n",
437 policy==ResourcePolicy::OWNED_DISCARD?"DISCARD":"RETAIN" );
438 mDiscardBitmapsPolicy = policy;
441 ResourcePolicy::Discardable TextureCache::GetDiscardBitmapsPolicy()
443 return mDiscardBitmapsPolicy;