(Atlas) Upload pixel data & Allow the difference in pixel format
[platform/core/uifw/dali-core.git] / dali / internal / render / gl-resources / texture-cache.cpp
1 /*
2  * Copyright (c) 2014 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 #include <dali/internal/render/gl-resources/texture-cache.h>
19
20 #include <dali/integration-api/bitmap.h>
21
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>
32
33 #include <dali/integration-api/debug.h>
34
35 using Dali::Internal::Texture;
36 using Dali::Internal::FrameBufferTexture;
37 using Dali::Integration::Bitmap;
38
39 namespace
40 {
41 #if defined(DEBUG_ENABLED)
42 Debug::Filter* gTextureCacheFilter = Debug::Filter::New(Debug::Concise, false, "LOG_TEXTURE_CACHE");
43 #endif
44 }
45
46
47 namespace Dali
48 {
49 namespace Internal
50 {
51
52 // value types used by messages
53 template <> struct ParameterType< Pixel::Format > : public BasicType< Pixel::Format > {};
54 template <> struct ParameterType< RenderBuffer::Format > : public BasicType< RenderBuffer::Format > {};
55
56 namespace SceneGraph
57 {
58
59 namespace
60 {
61
62 /**
63  * @brief Forward to all textures in container the news that the GL Context is down.
64  */
65 void GlContextDestroyed( TextureContainer& textures )
66 {
67   TextureIter end = textures.end();
68   TextureIter iter = textures.begin();
69   for( ; iter != end; ++iter )
70   {
71     (*iter->second).GlContextDestroyed();
72   }
73 }
74
75 }
76
77 TextureCache::TextureCache( RenderQueue& renderQueue,
78                             PostProcessResourceDispatcher& postProcessResourceDispatcher,
79                             Context& context)
80 : TextureCacheDispatcher(renderQueue),
81   mPostProcessResourceDispatcher(postProcessResourceDispatcher),
82   mContext(context),
83   mDiscardBitmapsPolicy(ResourcePolicy::OWNED_DISCARD)
84 {
85 }
86
87 TextureCache::~TextureCache()
88 {
89 }
90
91 void TextureCache::CreateTexture( ResourceId        id,
92                                   unsigned int      width,
93                                   unsigned int      height,
94                                   Pixel::Format     pixelFormat,
95                                   bool              clearPixels )
96 {
97   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::CreateTexture(id=%i width:%u height:%u)\n", id, width, height);
98
99   Texture* texture = TextureFactory::NewBitmapTexture(width, height, pixelFormat, clearPixels, mContext, GetDiscardBitmapsPolicy() );
100   mTextures.insert(TexturePair(id, texture));
101 }
102
103 void TextureCache::AddBitmap(ResourceId id, Integration::BitmapPtr bitmap)
104 {
105   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddBitmap(id=%i Bitmap:%p)\n", id, bitmap.Get());
106
107   Texture* texture = TextureFactory::NewBitmapTexture(bitmap.Get(), mContext, GetDiscardBitmapsPolicy());
108   mTextures.insert(TexturePair(id, texture));
109 }
110
111 void TextureCache::AddNativeImage(ResourceId id, NativeImageInterfacePtr nativeImage)
112 {
113   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddNativeImage(id=%i NativeImg:%p)\n", id, nativeImage.Get());
114
115   /// TODO - currently a new Texture is created even if we reuse the same NativeImage
116   Texture* texture = TextureFactory::NewNativeImageTexture(*nativeImage, mContext);
117   mTextures.insert(TexturePair(id, texture));
118 }
119
120 void TextureCache::AddFrameBuffer( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat )
121 {
122   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddFrameBuffer(id=%i width:%u height:%u)\n", id, width, height);
123
124   // Note: Do not throttle framebuffer generation - a request for a framebuffer should always be honoured
125   // as soon as possible.
126   Texture* texture = TextureFactory::NewFrameBufferTexture( width, height, pixelFormat, bufferFormat, mContext );
127   mFramebufferTextures.insert(TexturePair(id, texture));
128 }
129
130 void TextureCache::AddFrameBuffer( ResourceId id, NativeImageInterfacePtr nativeImage )
131 {
132   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddFrameBuffer(id=%i width:%u height:%u)\n", id, nativeImage->GetWidth(), nativeImage->GetHeight());
133
134   // Note: Do not throttle framebuffer generation - a request for a framebuffer should always be honoured
135   // as soon as possible.
136   Texture* texture = TextureFactory::NewFrameBufferTexture( nativeImage, mContext );
137   mFramebufferTextures.insert(TexturePair(id, texture));
138 }
139
140 void TextureCache::CreateGlTexture( ResourceId id )
141 {
142   TextureIter textureIter = mTextures.find(id);
143   // If we found a non-null texture object pointer for the resource id, force it
144   // to eagerly allocate a backing GL texture:
145   if( textureIter != mTextures.end() )
146   {
147     TexturePointer texturePtr = textureIter->second;
148     if( texturePtr )
149     {
150       texturePtr->CreateGlTexture();
151     }
152   }
153 }
154
155 void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap )
156 {
157   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i bitmap:%p )\n", id, bitmap.Get());
158
159   TextureIter textureIter = mTextures.find(id);
160   if( textureIter != mTextures.end() )
161   {
162     // we have reloaded the image from file, update texture
163     TexturePointer texturePtr = textureIter->second;
164     if( texturePtr )
165     {
166       texturePtr->Update( bitmap.Get() );
167
168       ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
169       mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
170     }
171   }
172 }
173
174 void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset )
175 {
176   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i bitmap:%p )\n", id, bitmap.Get());
177
178   TextureIter textureIter = mTextures.find(id);
179   if( textureIter != mTextures.end() )
180   {
181     TexturePointer texturePtr = textureIter->second;
182     if( texturePtr )
183     {
184       texturePtr->Update( bitmap.Get(), xOffset, yOffset );
185
186       ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
187       mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
188     }
189   }
190 }
191
192 void TextureCache::UpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
193 {
194   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(destId=%i srcId=%i )\n", destId, srcId );
195
196   BitmapTexture* srcTexture = TextureCache::GetBitmapTexture( srcId );
197   Integration::BitmapPtr srcBitmap = ( srcTexture != NULL ) ? srcTexture->GetBitmap() : NULL;
198
199   if( srcBitmap )
200   {
201     UpdateTexture( destId, srcBitmap, xOffset, yOffset );
202   }
203 }
204
205 void TextureCache::UpdateTexture( ResourceId id, PixelDataPtr pixelData, std::size_t xOffset, std::size_t yOffset )
206 {
207   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i pixel data:%p )\n", id, pixelData.Get());
208
209   TextureIter textureIter = mTextures.find(id);
210   if( textureIter != mTextures.end() )
211   {
212     TexturePointer texturePtr = textureIter->second;
213     if( texturePtr )
214     {
215       texturePtr->Update( pixelData.Get(), xOffset, yOffset );
216
217       ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
218       mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
219     }
220   }
221 }
222
223 void TextureCache::UpdateTextureArea( ResourceId id, const Dali::RectArea& area )
224 {
225   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTextureArea(id=%i)\n", id );
226
227   TextureIter textureIter = mTextures.find(id);
228   if( textureIter != mTextures.end() )
229   {
230     TexturePointer texturePtr = textureIter->second;
231     if( texturePtr )
232     {
233       texturePtr->UpdateArea( area );
234
235       ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
236       mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
237     }
238   }
239 }
240
241 void TextureCache::DiscardTexture( ResourceId id )
242 {
243   bool deleted = false;
244
245   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::DiscardTexture(id:%u)\n", id);
246
247   if( mTextures.size() > 0)
248   {
249     TextureIter iter = mTextures.find(id);
250     if( iter != mTextures.end() )
251     {
252       TexturePointer texturePtr = iter->second;
253       if( texturePtr )
254       {
255         // if valid texture pointer, cleanup GL resources
256         texturePtr->GlCleanup();
257       }
258       mTextures.erase(iter);
259       deleted = true;
260     }
261   }
262
263   if( mFramebufferTextures.size() > 0)
264   {
265     TextureIter iter = mFramebufferTextures.find(id);
266     if( iter != mFramebufferTextures.end() )
267     {
268       TexturePointer texturePtr = iter->second;
269       if( texturePtr )
270       {
271         // if valid texture pointer, cleanup GL resources
272         texturePtr->GlCleanup();
273       }
274       mFramebufferTextures.erase(iter);
275       deleted = true;
276     }
277   }
278
279   if(deleted)
280   {
281     if( mObservers.size() > 0 )
282     {
283       TextureResourceObserversIter observersIter = mObservers.find(id);
284       if( observersIter != mObservers.end() )
285       {
286         TextureObservers observers = observersIter->second;
287         for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
288         {
289           TextureObserver* observer = *iter;
290           observer->TextureDiscarded( id );
291         }
292
293         mObservers.erase( observersIter );
294       }
295     }
296
297     // Tell resource manager
298     ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::DELETED );
299     mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
300   }
301 }
302
303 void TextureCache::BindTexture( Texture *texture, ResourceId id, GLenum target, TextureUnit textureunit )
304 {
305   bool created = texture->Bind(target, textureunit);
306   if( created && texture->UpdateOnCreate() ) // i.e. the pixel data was sent to GL
307   {
308     ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
309     mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
310   }
311 }
312
313 Texture* TextureCache::GetTexture(ResourceId id)
314 {
315   Texture* texture = NULL;
316   TextureIter iter = mTextures.find(id);
317
318   if( iter != mTextures.end() )
319   {
320     TexturePointer texturePtr = iter->second;
321     if( texturePtr )
322     {
323       texture = texturePtr.Get();
324     }
325   }
326
327   if( texture == NULL )
328   {
329     TextureIter iter = mFramebufferTextures.find(id);
330     if( iter != mFramebufferTextures.end() )
331     {
332       TexturePointer texturePtr = iter->second;
333       if( texturePtr )
334       {
335         texture = texturePtr.Get();
336       }
337     }
338   }
339
340   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::GetTexture(id:%u) : %p\n", id, texture);
341
342   return texture;
343 }
344
345 BitmapTexture* TextureCache::GetBitmapTexture(ResourceId id)
346 {
347   BitmapTexture* texture = NULL;
348   TextureIter iter = mTextures.find( id );
349
350   if( iter != mTextures.end() )
351   {
352     TexturePointer texturePtr = iter->second;
353     if( texturePtr )
354     {
355       texture = dynamic_cast< BitmapTexture* >( texturePtr.Get() );
356     }
357   }
358
359   return texture;
360 }
361
362 FrameBufferTexture* TextureCache::GetFramebuffer(ResourceId id)
363 {
364   FrameBufferTexture* offscreen = NULL;
365   TextureIter iter = mFramebufferTextures.find(id);
366
367   DALI_ASSERT_DEBUG( iter != mFramebufferTextures.end() );
368
369   if( iter != mFramebufferTextures.end() )
370   {
371     TexturePointer texturePtr = iter->second;
372     if( texturePtr )
373     {
374       offscreen = dynamic_cast< FrameBufferTexture* >( texturePtr.Get() );
375     }
376   }
377   DALI_ASSERT_DEBUG( offscreen );
378
379   DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::GetFramebuffer(id:%u) : %p\n", id, offscreen);
380
381   return offscreen;
382 }
383
384 void TextureCache::AddObserver( ResourceId id, TextureObserver* observer )
385 {
386   TextureResourceObserversIter observersIter = mObservers.find(id);
387   if( observersIter != mObservers.end() )
388   {
389     TextureObservers& observers = observersIter->second;
390     bool foundObserver = false;
391     for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
392     {
393       if( *iter == observer )
394       {
395         foundObserver = true;
396         break;
397       }
398     }
399     if( ! foundObserver )
400     {
401       observers.push_back(observer);
402     }
403   }
404   else
405   {
406     TextureObservers observers;
407     observers.push_back(observer);
408     mObservers.insert(std::pair<ResourceId, TextureObservers>(id, observers));
409   }
410 }
411
412 void TextureCache::RemoveObserver( ResourceId id, TextureObserver* observer )
413 {
414   TextureResourceObserversIter observersIter = mObservers.find(id);
415   if( observersIter != mObservers.end() )
416   {
417     TextureObservers& observers = observersIter->second;
418     for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
419     {
420       if(*iter == observer)
421       {
422         observers.erase(iter);
423         break;
424       }
425     }
426   }
427 }
428
429 void TextureCache::GlContextDestroyed()
430 {
431   SceneGraph::GlContextDestroyed( mTextures );
432   SceneGraph::GlContextDestroyed( mFramebufferTextures );
433 }
434
435 void TextureCache::SetDiscardBitmapsPolicy( ResourcePolicy::Discardable policy )
436 {
437   DALI_LOG_INFO( gTextureCacheFilter, Debug::General, "TextureCache::SetDiscardBitmapsPolicy(%s)\n",
438                  policy==ResourcePolicy::OWNED_DISCARD?"DISCARD":"RETAIN" );
439   mDiscardBitmapsPolicy = policy;
440 }
441
442 ResourcePolicy::Discardable TextureCache::GetDiscardBitmapsPolicy()
443 {
444   return mDiscardBitmapsPolicy;
445 }
446
447
448 /********************************************************************************
449  **********************  Implements TextureCacheDispatcher  *********************
450  ********************************************************************************/
451
452 void TextureCache::DispatchCreateTexture( ResourceId        id,
453                                           unsigned int      width,
454                                           unsigned int      height,
455                                           Pixel::Format     pixelFormat,
456                                           bool              clearPixels )
457 {
458   // NULL, means being shutdown, so ignore msgs
459   if( mSceneGraphBuffers != NULL )
460   {
461     typedef MessageValue5< TextureCache, ResourceId, unsigned int, unsigned int, Pixel::Format, bool > DerivedType;
462
463     // Reserve some memory inside the render queue
464     unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
465
466     // Construct message in the render queue memory; note that delete should not be called on the return value
467     new (slot) DerivedType( this, &TextureCache::CreateTexture, id, width, height, pixelFormat, clearPixels );
468   }
469 }
470
471 void TextureCache::DispatchCreateTextureForBitmap( ResourceId id, Bitmap* bitmap )
472 {
473   // NULL, means being shutdown, so ignore msgs
474   if( mSceneGraphBuffers != NULL )
475   {
476     typedef MessageValue2< TextureCache, ResourceId, Integration::BitmapPtr > DerivedType;
477
478     // Reserve some memory inside the render queue
479     unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
480
481     // Construct message in the render queue memory; note that delete should not be called on the return value
482     new (slot) DerivedType( this, &TextureCache::AddBitmap, id, bitmap );
483   }
484 }
485
486 void TextureCache::DispatchCreateTextureForNativeImage( ResourceId id, NativeImageInterfacePtr nativeImage )
487 {
488   // NULL, means being shutdown, so ignore msgs
489   if( mSceneGraphBuffers != NULL )
490   {
491     typedef MessageValue2< TextureCache, ResourceId, NativeImageInterfacePtr > DerivedType;
492
493     // Reserve some memory inside the render queue
494     unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
495
496     // Construct message in the render queue memory; note that delete should not be called on the return value
497     new (slot) DerivedType( this, &TextureCache::AddNativeImage, id, nativeImage );
498   }
499 }
500
501 void TextureCache::DispatchCreateGlTexture( ResourceId id )
502 {
503   // NULL, means being shutdown, so ignore msgs
504   if( mSceneGraphBuffers != NULL )
505   {
506     typedef MessageValue1< TextureCache, ResourceId > DerivedType;
507
508     // Reserve some memory inside the render queue
509     unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
510
511     // Construct message in the render queue memory; note that delete should not be called on the return value
512     new (slot) DerivedType( this, &TextureCache::CreateGlTexture, id );
513   }
514 }
515
516 void TextureCache::DispatchCreateTextureForFrameBuffer( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat )
517 {
518   // NULL, means being shutdown, so ignore msgs
519   if( mSceneGraphBuffers != NULL )
520   {
521     typedef MessageValue5< TextureCache, ResourceId, unsigned int, unsigned int, Pixel::Format, RenderBuffer::Format > DerivedType;
522
523     // Reserve some memory inside the render queue
524     unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
525
526     // Construct message in the render queue memory; note that delete should not be called on the return value
527     new (slot) DerivedType( this, &TextureCache::AddFrameBuffer, id, width, height, pixelFormat, bufferFormat );
528   }
529 }
530
531 void TextureCache::DispatchCreateTextureForFrameBuffer( ResourceId id, NativeImageInterfacePtr nativeImage )
532 {
533   // NULL, means being shutdown, so ignore msgs
534   if( mSceneGraphBuffers != NULL )
535   {
536     typedef MessageValue2< TextureCache, ResourceId, NativeImageInterfacePtr > DerivedType;
537
538     // Reserve some memory inside the render queue
539     unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
540
541     // Construct message in the render queue memory; note that delete should not be called on the return value
542     new (slot) DerivedType( this, &TextureCache::AddFrameBuffer, id, nativeImage );
543   }
544 }
545
546 void TextureCache::DispatchUpdateTexture( ResourceId id, Bitmap* bitmap )
547 {
548   // NULL, means being shutdown, so ignore msgs
549   if( mSceneGraphBuffers != NULL )
550   {
551     typedef MessageValue2< TextureCache, ResourceId, Integration::BitmapPtr > DerivedType;
552
553     // Reserve some memory inside the render queue
554     unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
555
556     // Construct message in the render queue memory; note that delete should not be called on the return value
557     new (slot) DerivedType( this, &TextureCache::UpdateTexture, id, bitmap );
558   }
559 }
560
561 void TextureCache::DispatchUpdateTexture( ResourceId id, Integration::BitmapPtr bitmap , std::size_t xOffset, std::size_t yOffset)
562 {
563   // NULL, means being shutdown, so ignore msgs
564   if( mSceneGraphBuffers != NULL )
565   {
566     typedef MessageValue4< TextureCache, ResourceId, Integration::BitmapPtr, std::size_t, std::size_t > DerivedType;
567
568     // Reserve some memory inside the render queue
569     unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
570
571     // Construct message in the render queue memory; note that delete should not be called on the return value
572     new (slot) DerivedType( this, &TextureCache::UpdateTexture, id, bitmap, xOffset, yOffset );
573   }
574 }
575
576 void TextureCache::DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
577 {
578   // NULL, means being shutdown, so ignore msgs
579   if( mSceneGraphBuffers != NULL )
580   {
581     typedef MessageValue4< TextureCache, ResourceId, ResourceId, std::size_t, std::size_t > DerivedType;
582
583     // Reserve some memory inside the render queue
584     unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
585
586     // Construct message in the render queue memory; note that delete should not be called on the return value
587     new (slot) DerivedType( this, &TextureCache::UpdateTexture, destId, srcId, xOffset, yOffset );
588   }
589 }
590
591 void TextureCache::DispatchUpdateTexture( ResourceId id, PixelDataPtr pixelData , std::size_t xOffset, std::size_t yOffset)
592 {
593   // NULL, means being shutdown, so ignore msgs
594   if( mSceneGraphBuffers != NULL )
595   {
596     typedef MessageValue4< TextureCache, ResourceId, PixelDataPtr, std::size_t, std::size_t > DerivedType;
597
598     // Reserve some memory inside the render queue
599     unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
600
601     // Construct message in the render queue memory; note that delete should not be called on the return value
602     new (slot) DerivedType( this, &TextureCache::UpdateTexture, id, pixelData, xOffset, yOffset );
603   }
604 }
605
606 void TextureCache::DispatchUpdateTextureArea( ResourceId id, const Dali::RectArea& area )
607 {
608   // NULL, means being shutdown, so ignore msgs
609   if( mSceneGraphBuffers != NULL )
610   {
611     typedef MessageValue2< TextureCache, ResourceId, Dali::RectArea > DerivedType;
612
613     // Reserve some memory inside the render queue
614     unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
615
616     // Construct message in the render queue memory; note that delete should not be called on the return value
617     new (slot) DerivedType( this, &TextureCache::UpdateTextureArea, id, area );
618   }
619 }
620
621 void TextureCache::DispatchDiscardTexture( ResourceId id )
622 {
623   // NULL, means being shutdown, so ignore msgs
624   if( mSceneGraphBuffers != NULL )
625   {
626     typedef MessageValue1< TextureCache, ResourceId > DerivedType;
627
628     // Reserve some memory inside the render queue
629     unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
630
631     // Construct message in the render queue memory; note that delete should not be called on the return value
632     new (slot) DerivedType( this, &TextureCache::DiscardTexture, id );
633   }
634 }
635
636 } // SceneGraph
637
638 } // Internal
639
640 } // Dali