Merge "Deprecated Layer::TREE_DEPTH_MULTIPLIER and fixed mis-usage." into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / render / gl-resources / texture-cache.cpp
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // CLASS HEADER
19 #include <dali/internal/render/gl-resources/texture-cache.h>
20
21 // INTERNAL HEADERS
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>
35
36 using Dali::Internal::Texture;
37 using Dali::Internal::FrameBufferTexture;
38 using Dali::Integration::Bitmap;
39
40 namespace
41 {
42 #if defined(DEBUG_ENABLED)
43 Debug::Filter* gTextureCacheFilter = Debug::Filter::New(Debug::Concise, false, "LOG_TEXTURE_CACHE");
44 #endif
45 }
46
47
48 namespace Dali
49 {
50 namespace Internal
51 {
52
53
54 namespace SceneGraph
55 {
56
57 namespace
58 {
59
60 /**
61  * @brief Forward to all textures in container the news that the GL Context is down.
62  */
63 void GlContextDestroyed( TextureContainer& textures )
64 {
65   TextureIter end = textures.end();
66   TextureIter iter = textures.begin();
67   for( ; iter != end; ++iter )
68   {
69     (*iter->second).GlContextDestroyed();
70   }
71 }
72
73 }
74
75 TextureCache::TextureCache( RenderQueue& renderQueue,
76                             TextureUploadedDispatcher& postProcessResourceDispatcher,
77                             Context& context)
78 : mTextureUploadedDispatcher(postProcessResourceDispatcher),
79   mContext(context),
80   mDiscardBitmapsPolicy(ResourcePolicy::OWNED_DISCARD)
81 {
82 }
83
84 TextureCache::~TextureCache()
85 {
86 }
87
88 void TextureCache::CreateTexture( ResourceId        id,
89                                   unsigned int      width,
90                                   unsigned int      height,
91                                   Pixel::Format     pixelFormat,
92                                   bool              clearPixels )
93 {
94   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::CreateTexture(id=%i width:%u height:%u)\n", id, width, height);
95
96   Texture* texture = TextureFactory::NewBitmapTexture(width, height, pixelFormat, clearPixels, mContext, GetDiscardBitmapsPolicy() );
97   mTextures.insert(TexturePair(id, texture));
98 }
99
100 void TextureCache::AddBitmap(ResourceId id, Integration::BitmapPtr bitmap)
101 {
102   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddBitmap(id=%i Bitmap:%p)\n", id, bitmap.Get());
103
104   Texture* texture = TextureFactory::NewBitmapTexture(bitmap.Get(), mContext, GetDiscardBitmapsPolicy());
105   mTextures.insert(TexturePair(id, texture));
106 }
107
108 void TextureCache::AddNativeImage(ResourceId id, NativeImageInterfacePtr nativeImage)
109 {
110   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddNativeImage(id=%i NativeImg:%p)\n", id, nativeImage.Get());
111
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));
115 }
116
117 void TextureCache::AddFrameBuffer( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat )
118 {
119   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddFrameBuffer(id=%i width:%u height:%u)\n", id, width, height);
120
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));
125 }
126
127 void TextureCache::AddFrameBuffer( ResourceId id, NativeImageInterfacePtr nativeImage )
128 {
129   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddFrameBuffer(id=%i width:%u height:%u)\n", id, nativeImage->GetWidth(), nativeImage->GetHeight());
130
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));
135 }
136
137 void TextureCache::CreateGlTexture( ResourceId id )
138 {
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() )
143   {
144     TexturePointer texturePtr = textureIter->second;
145     if( texturePtr )
146     {
147       texturePtr->CreateGlTexture();
148     }
149   }
150 }
151
152 void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap )
153 {
154   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i bitmap:%p )\n", id, bitmap.Get());
155
156   TextureIter textureIter = mTextures.find(id);
157   if( textureIter != mTextures.end() )
158   {
159     // we have reloaded the image from file, update texture
160     TexturePointer texturePtr = textureIter->second;
161     if( texturePtr )
162     {
163       texturePtr->Update( bitmap.Get() );
164
165       ResourceId ppRequest( id );
166       mTextureUploadedDispatcher.DispatchTextureUploaded(ppRequest);
167     }
168   }
169 }
170
171 void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset )
172 {
173   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i bitmap:%p )\n", id, bitmap.Get());
174
175   TextureIter textureIter = mTextures.find(id);
176   if( textureIter != mTextures.end() )
177   {
178     TexturePointer texturePtr = textureIter->second;
179     if( texturePtr )
180     {
181       texturePtr->Update( bitmap.Get(), xOffset, yOffset );
182
183       ResourceId ppRequest( id  );
184       mTextureUploadedDispatcher.DispatchTextureUploaded(ppRequest);
185     }
186   }
187 }
188
189 void TextureCache::UpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
190 {
191   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(destId=%i srcId=%i )\n", destId, srcId );
192
193   BitmapTexture* srcTexture = TextureCache::GetBitmapTexture( srcId );
194   Integration::BitmapPtr srcBitmap = ( srcTexture != NULL ) ? srcTexture->GetBitmap() : NULL;
195
196   if( srcBitmap )
197   {
198     UpdateTexture( destId, srcBitmap, xOffset, yOffset );
199   }
200 }
201
202 void TextureCache::UpdateTexture( ResourceId id, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset )
203 {
204   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i pixel data:%p )\n", id, pixelData.Get());
205
206   TextureIter textureIter = mTextures.find(id);
207   if( textureIter != mTextures.end() )
208   {
209     TexturePointer texturePtr = textureIter->second;
210     if( texturePtr )
211     {
212       texturePtr->Update( pixelData.Get(), xOffset, yOffset );
213
214       ResourceId ppRequest( id );
215       mTextureUploadedDispatcher.DispatchTextureUploaded(ppRequest);
216     }
217   }
218 }
219
220 void TextureCache::UpdateTextureArea( ResourceId id, const RectArea& area )
221 {
222   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTextureArea(id=%i)\n", id );
223
224   TextureIter textureIter = mTextures.find(id);
225   if( textureIter != mTextures.end() )
226   {
227     TexturePointer texturePtr = textureIter->second;
228     if( texturePtr )
229     {
230       texturePtr->UpdateArea( area );
231
232       ResourceId ppRequest( id );
233       mTextureUploadedDispatcher.DispatchTextureUploaded(ppRequest);
234     }
235   }
236 }
237
238 void TextureCache::DiscardTexture( ResourceId id )
239 {
240   bool deleted = false;
241
242   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::DiscardTexture(id:%u)\n", id);
243
244   if( mTextures.size() > 0)
245   {
246     TextureIter iter = mTextures.find(id);
247     if( iter != mTextures.end() )
248     {
249       TexturePointer texturePtr = iter->second;
250       if( texturePtr )
251       {
252         // if valid texture pointer, cleanup GL resources
253         texturePtr->GlCleanup();
254       }
255       mTextures.erase(iter);
256       deleted = true;
257     }
258   }
259
260   if( mFramebufferTextures.size() > 0)
261   {
262     TextureIter iter = mFramebufferTextures.find(id);
263     if( iter != mFramebufferTextures.end() )
264     {
265       TexturePointer texturePtr = iter->second;
266       if( texturePtr )
267       {
268         // if valid texture pointer, cleanup GL resources
269         texturePtr->GlCleanup();
270       }
271       mFramebufferTextures.erase(iter);
272       deleted = true;
273     }
274   }
275
276   if(deleted)
277   {
278     if( mObservers.size() > 0 )
279     {
280       TextureResourceObserversIter observersIter = mObservers.find(id);
281       if( observersIter != mObservers.end() )
282       {
283         TextureObservers observers = observersIter->second;
284         for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
285         {
286           TextureObserver* observer = *iter;
287           observer->TextureDiscarded( id );
288         }
289
290         mObservers.erase( observersIter );
291       }
292     }
293   }
294 }
295
296 bool TextureCache::BindTexture( Texture *texture, ResourceId id, GLenum target, TextureUnit textureunit )
297 {
298   unsigned int glTextureId = texture->GetTextureId();
299
300   bool success = texture->Bind(target, textureunit);
301   bool created = ( glTextureId == 0 ) && ( texture->GetTextureId() != 0 );
302
303   if( created && texture->UpdateOnCreate() ) // i.e. the pixel data was sent to GL
304   {
305     ResourceId ppRequest( id );
306     mTextureUploadedDispatcher.DispatchTextureUploaded(ppRequest);
307   }
308   return success;
309 }
310
311 Texture* TextureCache::GetTexture(ResourceId id)
312 {
313   Texture* texture = NULL;
314   TextureIter iter = mTextures.find(id);
315
316   if( iter != mTextures.end() )
317   {
318     TexturePointer texturePtr = iter->second;
319     if( texturePtr )
320     {
321       texture = texturePtr.Get();
322     }
323   }
324
325   if( texture == NULL )
326   {
327     TextureIter iter = mFramebufferTextures.find(id);
328     if( iter != mFramebufferTextures.end() )
329     {
330       TexturePointer texturePtr = iter->second;
331       if( texturePtr )
332       {
333         texture = texturePtr.Get();
334       }
335     }
336   }
337
338   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::GetTexture(id:%u) : %p\n", id, texture);
339
340   return texture;
341 }
342
343 BitmapTexture* TextureCache::GetBitmapTexture(ResourceId id)
344 {
345   BitmapTexture* texture = NULL;
346   TextureIter iter = mTextures.find( id );
347
348   if( iter != mTextures.end() )
349   {
350     TexturePointer texturePtr = iter->second;
351     if( texturePtr )
352     {
353       texture = dynamic_cast< BitmapTexture* >( texturePtr.Get() );
354     }
355   }
356
357   return texture;
358 }
359
360 FrameBufferTexture* TextureCache::GetFramebuffer(ResourceId id)
361 {
362   FrameBufferTexture* offscreen = NULL;
363   TextureIter iter = mFramebufferTextures.find(id);
364
365   DALI_ASSERT_DEBUG( iter != mFramebufferTextures.end() );
366
367   if( iter != mFramebufferTextures.end() )
368   {
369     TexturePointer texturePtr = iter->second;
370     if( texturePtr )
371     {
372       offscreen = dynamic_cast< FrameBufferTexture* >( texturePtr.Get() );
373     }
374   }
375   DALI_ASSERT_DEBUG( offscreen );
376
377   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::GetFramebuffer(id:%u) : %p\n", id, offscreen);
378
379   return offscreen;
380 }
381
382 void TextureCache::AddObserver( ResourceId id, TextureObserver* observer )
383 {
384   TextureResourceObserversIter observersIter = mObservers.find(id);
385   if( observersIter != mObservers.end() )
386   {
387     TextureObservers& observers = observersIter->second;
388     bool foundObserver = false;
389     for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
390     {
391       if( *iter == observer )
392       {
393         foundObserver = true;
394         break;
395       }
396     }
397     if( ! foundObserver )
398     {
399       observers.push_back(observer);
400     }
401   }
402   else
403   {
404     TextureObservers observers;
405     observers.push_back(observer);
406     mObservers.insert(std::pair<ResourceId, TextureObservers>(id, observers));
407   }
408 }
409
410 void TextureCache::RemoveObserver( ResourceId id, TextureObserver* observer )
411 {
412   TextureResourceObserversIter observersIter = mObservers.find(id);
413   if( observersIter != mObservers.end() )
414   {
415     TextureObservers& observers = observersIter->second;
416     for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
417     {
418       if(*iter == observer)
419       {
420         observers.erase(iter);
421         break;
422       }
423     }
424   }
425 }
426
427 void TextureCache::GlContextDestroyed()
428 {
429   SceneGraph::GlContextDestroyed( mTextures );
430   SceneGraph::GlContextDestroyed( mFramebufferTextures );
431 }
432
433 void TextureCache::SetDiscardBitmapsPolicy( ResourcePolicy::Discardable policy )
434 {
435   DALI_LOG_INFO( gTextureCacheFilter, Debug::General, "TextureCache::SetDiscardBitmapsPolicy(%s)\n",
436                  policy==ResourcePolicy::OWNED_DISCARD?"DISCARD":"RETAIN" );
437   mDiscardBitmapsPolicy = policy;
438 }
439
440 ResourcePolicy::Discardable TextureCache::GetDiscardBitmapsPolicy()
441 {
442   return mDiscardBitmapsPolicy;
443 }
444
445 } // SceneGraph
446
447 } // Internal
448
449 } // Dali