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