Merge "DALi Version 1.1.37" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / update / rendering / scene-graph-texture-set.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 // CLASS HEADER
18 #include "scene-graph-texture-set.h"
19
20 // INTERNAL HEADERS
21 #include <dali/devel-api/rendering/texture-set.h>
22 #include <dali/integration-api/resource-declarations.h>
23 #include <dali/internal/common/internal-constants.h>
24 #include <dali/internal/update/resources/texture-metadata.h>
25 #include <dali/internal/update/resources/resource-manager.h>
26 #include <dali/internal/common/memory-pool-object-allocator.h>
27 #include <dali/internal/update/rendering/scene-graph-renderer.h>
28
29 namespace //Unnamed namespace
30 {
31 //Memory pool used to allocate new texture sets. Memory used by this pool will be released when shutting down DALi
32 Dali::Internal::MemoryPoolObjectAllocator<Dali::Internal::SceneGraph::TextureSet> gTextureSetMemoryPool;
33 }
34
35 namespace Dali
36 {
37
38 namespace Internal
39 {
40
41 namespace SceneGraph
42 {
43
44 TextureSet* TextureSet::New()
45 {
46   return new ( gTextureSetMemoryPool.AllocateRawThreadSafe() ) TextureSet();
47 }
48
49 TextureSet::TextureSet()
50 : mSamplers(),
51   mTextureId(),
52   mRenderers(),
53   mResourcesReady( false ),
54   mFinishedResourceAcquisition( false ),
55   mChanged( true ),
56   mHasAlpha( false )
57 {
58 }
59
60 TextureSet::~TextureSet()
61 {
62 }
63
64 void TextureSet::operator delete( void* ptr )
65 {
66   gTextureSetMemoryPool.FreeThreadSafe( static_cast<TextureSet*>( ptr ) );
67 }
68
69 void TextureSet::Prepare( const ResourceManager& resourceManager )
70 {
71   if( mChanged )
72   {
73     unsigned int opaqueCount = 0;
74     unsigned int completeCount = 0;
75     unsigned int failedCount = 0;
76     unsigned int frameBufferCount = 0;
77     const std::size_t textureCount( mTextureId.Count() );
78     if( textureCount > 0 )
79     {
80       for( unsigned int i(0); i<textureCount; ++i )
81       {
82         const ResourceId textureId = mTextureId[ i ];
83         TextureMetadata* metadata = NULL;
84         if( textureId != Integration::InvalidResourceId )
85         {
86           // if there is metadata, resource is loaded
87           if( resourceManager.GetTextureMetadata( textureId, metadata ) )
88           {
89             DALI_ASSERT_DEBUG( metadata );
90             // metadata is valid pointer from now on
91             if( metadata->IsFullyOpaque() )
92             {
93               ++opaqueCount;
94             }
95
96             if( metadata->IsFramebuffer() )
97             {
98               if( metadata->HasFrameBufferBeenRenderedTo() )
99               {
100                 ++completeCount;
101               }
102               else
103               {
104                 frameBufferCount++;
105               }
106             }
107             else
108             {
109               // loaded so will complete this frame
110               ++completeCount;
111             }
112             // no point checking failure as there is no metadata for failed loads
113           }
114           // if no metadata, loading can be failed
115           else if( resourceManager.HasResourceLoadFailed( textureId ) )
116           {
117             ++failedCount;
118           }
119         }
120         else
121         {
122           //If the texture is not valid it is considerer opaque and complete
123           ++opaqueCount;
124           ++completeCount;
125         }
126       }
127     }
128
129     mHasAlpha = ( opaqueCount != textureCount );
130
131     // ready for rendering when all textures are either successfully loaded or they are FBOs
132     mResourcesReady = (completeCount + frameBufferCount >= textureCount);
133
134     // Texture set is complete if all resources are either loaded or failed or, if they are FBOs have been rendererd to
135     mFinishedResourceAcquisition = ( completeCount + failedCount == textureCount );
136
137     if( mFinishedResourceAcquisition )
138     {
139       // Texture set is now considered not changed
140       mChanged = false;
141     }
142   }
143 }
144
145 void TextureSet::SetImage( size_t index,  ResourceId imageId )
146 {
147   size_t textureCount( mTextureId.Size() );
148   if( textureCount < index + 1 )
149   {
150     mTextureId.Resize( index + 1 );
151     mSamplers.Resize( index + 1 );
152     for( size_t i(textureCount); i<=index; ++i )
153     {
154       mTextureId[i] = Integration::InvalidResourceId;
155       mSamplers[i] = NULL;
156     }
157   }
158
159   mTextureId[index] = imageId;
160   mChanged = true;
161   NotifyChangeToRenderers();
162 }
163
164 void TextureSet::SetSampler( size_t index, Render::Sampler* sampler )
165 {
166   size_t samplerCount( mSamplers.Size() );
167   if( samplerCount < index + 1 )
168   {
169     mSamplers.Resize( index + 1 );
170     mTextureId.Resize( index + 1 );
171     for( size_t i(samplerCount); i<=index; ++i )
172     {
173       mTextureId[i] = Integration::InvalidResourceId;
174       mSamplers[i] = NULL;
175     }
176   }
177
178   mSamplers[index] = sampler;
179
180   mChanged = true;
181   NotifyChangeToRenderers();
182 }
183
184 void TextureSet::SetTexture( size_t index, Render::NewTexture* texture )
185 {
186   const size_t textureCount( mTextures.Size() );
187   if( textureCount < index + 1 )
188   {
189     mTextures.Resize( index + 1 );
190     mSamplers.Resize( index + 1 );
191
192     for( size_t i(textureCount); i<=index; ++i )
193     {
194       mTextures[i] = 0;
195       mSamplers[i] = 0;
196     }
197   }
198
199   mTextures[index] = texture;
200   mHasAlpha |= texture->HasAlphaChannel();
201
202   mChanged = true;
203   NotifyChangeToRenderers();
204 }
205
206 bool TextureSet::HasAlpha() const
207 {
208   return mHasAlpha;
209 }
210
211 void TextureSet::GetResourcesStatus( bool& resourcesReady, bool& finishedResourceAcquisition )
212 {
213   resourcesReady = mResourcesReady;
214   finishedResourceAcquisition = mFinishedResourceAcquisition;
215 }
216
217 void TextureSet::AddObserver( Renderer* renderer )
218 {
219   size_t rendererCount( mRenderers.Size() );
220   for( size_t i(0); i<rendererCount; ++i )
221   {
222     if( mRenderers[i] == renderer )
223     {
224       //Renderer already in the list
225       return;
226     }
227   }
228
229   mRenderers.PushBack( renderer );
230 }
231
232 void TextureSet::RemoveObserver( Renderer* renderer )
233 {
234   size_t rendererCount( mRenderers.Size() );
235   for( size_t i(0); i<rendererCount; ++i )
236   {
237     if( mRenderers[i] == renderer )
238     {
239       mRenderers.Remove( mRenderers.Begin() + i );
240       return;
241     }
242   }
243 }
244
245 void TextureSet::NotifyChangeToRenderers()
246 {
247   size_t rendererCount = mRenderers.Size();
248   for( size_t i(0); i<rendererCount; ++i )
249   {
250     mRenderers[i]->TextureSetChanged();
251   }
252 }
253
254 } // namespace SceneGraph
255
256 } // namespace Internal
257
258 } // namespace Dali