Geometry Batching
[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     mSamplers.Resize( index + 1 );
151     for( size_t i(textureCount); i<=index; ++i )
152     {
153       mTextureId[i] = Integration::InvalidResourceId;
154       mSamplers[i] = NULL;
155     }
156   }
157
158   mTextureId[index] = imageId;
159   mChanged = true;
160   NotifyChangeToRenderers();
161 }
162
163 void TextureSet::SetSampler( size_t index, Render::Sampler* sampler )
164 {
165   size_t samplerCount( mSamplers.Size() );
166   if( samplerCount < index + 1 )
167   {
168     mSamplers.Resize( index + 1 );
169     mTextureId.Resize( index + 1 );
170     for( size_t i(samplerCount); i<=index; ++i )
171     {
172       mTextureId[i] = Integration::InvalidResourceId;
173       mSamplers[i] = NULL;
174     }
175   }
176
177   mSamplers[index] = sampler;
178   NotifyChangeToRenderers();
179 }
180
181 void TextureSet::SetTexture( size_t index, Render::NewTexture* texture )
182 {
183   const size_t textureCount( mTextures.Size() );
184   if( textureCount < index + 1 )
185   {
186     mTextures.Resize( index + 1 );
187     mSamplers.Resize( index + 1 );
188
189     for( size_t i(textureCount); i<=index; ++i )
190     {
191       mTextures[i] = 0;
192       mSamplers[i] = 0;
193     }
194   }
195
196   mTextures[index] = texture;
197   mHasAlpha |= texture->HasAlphaChannel();
198   NotifyChangeToRenderers();
199 }
200
201 bool TextureSet::HasAlpha() const
202 {
203   return mHasAlpha;
204 }
205
206 void TextureSet::GetResourcesStatus( bool& resourcesReady, bool& finishedResourceAcquisition )
207 {
208   resourcesReady = mResourcesReady;
209   finishedResourceAcquisition = mFinishedResourceAcquisition;
210 }
211
212 void TextureSet::AddObserver( Renderer* renderer )
213 {
214   size_t rendererCount( mRenderers.Size() );
215   for( size_t i(0); i<rendererCount; ++i )
216   {
217     if( mRenderers[i] == renderer )
218     {
219       //Renderer already in the list
220       return;
221     }
222   }
223
224   mRenderers.PushBack( renderer );
225 }
226
227 void TextureSet::RemoveObserver( Renderer* renderer )
228 {
229   size_t rendererCount( mRenderers.Size() );
230   for( size_t i(0); i<rendererCount; ++i )
231   {
232     if( mRenderers[i] == renderer )
233     {
234       mRenderers.Remove( mRenderers.Begin() + i );
235       return;
236     }
237   }
238 }
239
240 void TextureSet::NotifyChangeToRenderers()
241 {
242   size_t rendererCount = mRenderers.Size();
243   for( size_t i(0); i<rendererCount; ++i )
244   {
245     mRenderers[i]->TextureSetChanged();
246   }
247 }
248
249 } // namespace SceneGraph
250
251 } // namespace Internal
252
253 } // namespace Dali