Merge "Removed unused CullFace features for ImageActor" into devel/master
[platform/core/uifw/dali-core.git] / dali / internal / update / rendering / scene-graph-material.cpp
1 /*
2  * Copyright (c) 2015 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-material.h"
19
20 // INTERNAL HEADERS
21 #include <dali/public-api/actors/blending.h>
22 #include <dali/public-api/shader-effects/shader-effect.h>
23 #include <dali/devel-api/rendering/material.h>
24 #include <dali/internal/common/internal-constants.h>
25 #include <dali/internal/update/resources/texture-metadata.h>
26 #include <dali/internal/update/resources/resource-manager.h>
27 #include <dali/internal/render/shaders/scene-graph-shader.h>
28 #include <dali/internal/common/memory-pool-object-allocator.h>
29
30 namespace //Unnamed namespace
31 {
32 //Memory pool used to allocate new materials. Memory used by this pool will be released when shutting down DALi
33 Dali::Internal::MemoryPoolObjectAllocator<Dali::Internal::SceneGraph::Material> gMaterialMemoryPool;
34 }
35
36 namespace Dali
37 {
38
39 namespace Internal
40 {
41
42 namespace SceneGraph
43 {
44
45 Material* Material::New()
46 {
47   return new ( gMaterialMemoryPool.AllocateRawThreadSafe() ) Material();
48 }
49
50 Material::Material()
51 : mShader( NULL ),
52   mSamplers(),
53   mTextureId(),
54   mUniformName(),
55   mConnectionObservers(),
56   mResourcesReady( false ),
57   mFinishedResourceAcquisition( false ),
58   mMaterialChanged( true )
59 {
60   // Observe own property-owner's uniform map
61   AddUniformMapObserver( *this );
62 }
63
64 Material::~Material()
65 {
66   mConnectionObservers.Destroy( *this );
67 }
68
69 void Material::operator delete( void* ptr )
70 {
71   gMaterialMemoryPool.FreeThreadSafe( static_cast<Material*>( ptr ) );
72 }
73
74 void Material::Prepare( const ResourceManager& resourceManager )
75 {
76   if( mMaterialChanged )
77   {
78     unsigned int opaqueCount = 0;
79     unsigned int completeCount = 0;
80     unsigned int failedCount = 0;
81     unsigned int frameBufferCount = 0;
82     const std::size_t textureCount( mTextureId.Count() );
83     if( textureCount > 0 )
84     {
85       for( unsigned int i(0); i<textureCount; ++i )
86       {
87         const ResourceId textureId = mTextureId[ i ];
88         TextureMetadata* metadata = NULL;
89         // if there is metadata, resource is loaded
90         if( resourceManager.GetTextureMetadata( textureId, metadata ) )
91         {
92           DALI_ASSERT_DEBUG( metadata );
93           // metadata is valid pointer from now on
94           if( metadata->IsFullyOpaque() )
95           {
96             ++opaqueCount;
97           }
98
99           if( metadata->IsFramebuffer() )
100           {
101             if( metadata->HasFrameBufferBeenRenderedTo() )
102             {
103               ++completeCount;
104             }
105             else
106             {
107               frameBufferCount++;
108             }
109           }
110           else
111           {
112             // loaded so will complete this frame
113             ++completeCount;
114           }
115           // no point checking failure as there is no metadata for failed loads
116         }
117         // if no metadata, loading can be failed
118         else if( resourceManager.HasResourceLoadFailed( textureId ) )
119         {
120           ++failedCount;
121         }
122       }
123     }
124
125     //  whether the textures or the shader require the opacity to be translucent
126     mIsTranslucent = ( opaqueCount != textureCount ) || ( mShader && mShader->GeometryHintEnabled( Dali::ShaderEffect::HINT_BLENDING ) );
127
128     // ready for rendering when all textures are either successfully loaded or they are FBOs
129     mResourcesReady = (completeCount + frameBufferCount >= textureCount);
130
131     // material is complete if all resources are either loaded or failed or, if they are FBOs have been rendererd to
132     mFinishedResourceAcquisition = ( completeCount + failedCount == textureCount );
133
134     if( mFinishedResourceAcquisition )
135     {
136       // material is now considered not changed
137       mMaterialChanged = false;
138     }
139   }
140 }
141
142 void Material::SetShader( Shader* shader )
143 {
144   mMaterialChanged = true;
145   mShader = shader;
146   mShader->AddUniformMapObserver( *this );
147
148   // Inform NewRenderer about this shader: (Will force a re-load of the
149   // shader from the data providers)
150   mConnectionObservers.ConnectionsChanged(*this);
151 }
152
153 Shader* Material::GetShader() const
154 {
155   return mShader;
156 }
157
158 bool Material::IsTranslucent() const
159 {
160   return mIsTranslucent;
161 }
162
163 void Material::AddTexture( const std::string& name, ResourceId id, Render::Sampler* sampler )
164 {
165   mMaterialChanged = true;
166   mTextureId.PushBack( id );
167   mUniformName.push_back( name );
168   mSamplers.PushBack( sampler );
169
170   mConnectionObservers.ConnectionsChanged(*this);
171 }
172
173 void Material::RemoveTexture( size_t index )
174 {
175   mMaterialChanged = true;
176   mTextureId.Erase( mTextureId.Begin()+index );
177   mUniformName.erase( mUniformName.begin() + index );
178   mSamplers.Erase( mSamplers.Begin()+index );
179   mConnectionObservers.ConnectionsChanged( *this );
180 }
181
182 void Material::SetTextureImage( size_t index, ResourceId id )
183 {
184   mMaterialChanged = true;
185   mTextureId[index] = id;
186   mConnectionObservers.ConnectionsChanged(*this);
187 }
188
189 void Material::SetTextureSampler( size_t index, Render::Sampler* sampler)
190 {
191   // sampler does not change material blending of readiness
192   mSamplers[index] = sampler;
193   mConnectionObservers.ConnectionsChanged(*this);
194 }
195
196 void Material::SetTextureUniformName( size_t index, const std::string& uniformName)
197 {
198   // Uniform name does not change material blending of readiness
199   mUniformName[index] = uniformName;
200   mConnectionObservers.ConnectionsChanged(*this);
201 }
202
203 void Material::GetResourcesStatus( bool& resourcesReady, bool& finishedResourceAcquisition )
204 {
205   resourcesReady = mResourcesReady;
206   finishedResourceAcquisition = mFinishedResourceAcquisition;
207 }
208
209 void Material::ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
210 {
211 }
212
213 void Material::DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
214 {
215 }
216
217 void Material::AddConnectionObserver( ConnectionChangePropagator::Observer& observer )
218 {
219   mConnectionObservers.Add(observer);
220 }
221
222 void Material::RemoveConnectionObserver( ConnectionChangePropagator::Observer& observer )
223 {
224   mConnectionObservers.Remove(observer);
225 }
226
227 void Material::UniformMappingsChanged( const UniformMap& mappings )
228 {
229   // Our uniform map, or that of one of the watched children has changed.
230   // Inform connected observers.
231   mConnectionObservers.ConnectedUniformMapChanged();
232 }
233
234 void Material::ConnectionsChanged( PropertyOwner& owner )
235 {
236   // this should happen in the case of shader properties changed
237   mMaterialChanged = true;
238
239   mConnectionObservers.ConnectionsChanged(*this);
240 }
241
242 void Material::ConnectedUniformMapChanged( )
243 {
244   mConnectionObservers.ConnectedUniformMapChanged();
245 }
246
247 } // namespace SceneGraph
248
249 } // namespace Internal
250
251 } // namespace Dali