2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #include "scene-graph-renderer.h"
21 #include <dali/internal/update/controllers/scene-controller.h>
22 #include <dali/internal/render/renderers/render-geometry.h>
23 #include <dali/internal/update/controllers/render-message-dispatcher.h>
24 #include <dali/internal/update/rendering/scene-graph-geometry.h>
25 #include <dali/internal/update/rendering/scene-graph-material.h>
26 #include <dali/internal/render/shaders/scene-graph-shader.h>
27 #include <dali/internal/render/renderers/render-renderer.h>
28 #include <dali/internal/render/data-providers/node-data-provider.h>
29 #include <dali/internal/update/nodes/node.h>
30 #include <dali/internal/render/queue/render-queue.h>
31 #include <dali/internal/common/internal-constants.h>
34 namespace // unnamed namespace
37 const unsigned int UNIFORM_MAP_READY = 0;
38 const unsigned int COPY_UNIFORM_MAP = 1;
39 const unsigned int REGENERATE_UNIFORM_MAP = 2;
41 void AddMappings( Dali::Internal::SceneGraph::CollectedUniformMap& localMap, const Dali::Internal::SceneGraph::UniformMap& uniformMap )
43 // Iterate thru uniformMap.
44 // Any maps that aren't in localMap should be added in a single step
45 Dali::Internal::SceneGraph::CollectedUniformMap newUniformMappings;
47 for( unsigned int i=0, count=uniformMap.Count(); i<count; ++i )
49 Dali::Internal::SceneGraph::UniformPropertyMapping::Hash nameHash = uniformMap[i].uniformNameHash;
52 for( Dali::Internal::SceneGraph::CollectedUniformMap::Iterator iter = localMap.Begin() ; iter != localMap.End() ; ++iter )
54 const Dali::Internal::SceneGraph::UniformPropertyMapping* map = (*iter);
55 if( map->uniformNameHash == nameHash )
57 if( map->uniformName == uniformMap[i].uniformName )
66 // it's a new mapping. Add raw ptr to temporary list
67 newUniformMappings.PushBack( &uniformMap[i] );
71 if( newUniformMappings.Count() > 0 )
73 localMap.Reserve( localMap.Count() + newUniformMappings.Count() );
75 for( Dali::Internal::SceneGraph::CollectedUniformMap::Iterator iter = newUniformMappings.Begin(),
76 end = newUniformMappings.End() ;
80 const Dali::Internal::SceneGraph::UniformPropertyMapping* map = (*iter);
81 localMap.PushBack( map );
83 //@todo MESH_REWORK Use memcpy to copy ptrs from one array to the other
101 mRegenerateUniformMap(0),
102 mResendDataProviders(false),
103 mResendGeometry(false),
104 mResourcesReady(false),
105 mFinishedResourceAcquisition(false),
108 mUniformMapChanged[0]=false;
109 mUniformMapChanged[1]=false;
111 // Observe our own PropertyOwner's uniform map
112 AddUniformMapObserver( *this );
115 Renderer::~Renderer()
119 mMaterial->RemoveConnectionObserver(*this);
124 mGeometry->RemoveConnectionObserver(*this);
129 void Renderer::PrepareRender( BufferIndex updateBufferIndex )
131 mResourcesReady = false;
132 mFinishedResourceAcquisition = false;
134 // Can only be considered ready when all the scene graph objects are connected to the renderer
135 if( ( mGeometry ) && ( mGeometry->GetVertexBuffers().Count() > 0 ) &&
136 ( mMaterial ) && ( mMaterial->GetShader() != NULL ) )
138 mMaterial->GetResourcesStatus( mResourcesReady, mFinishedResourceAcquisition );
141 if( mRegenerateUniformMap > UNIFORM_MAP_READY )
143 DALI_ASSERT_DEBUG( mGeometry != NULL && "No geometry available in DoPrepareRender()" );
144 DALI_ASSERT_DEBUG( mMaterial != NULL && "No geometry available in DoPrepareRender()" );
146 if( mRegenerateUniformMap == REGENERATE_UNIFORM_MAP)
148 CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
151 const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap();
152 AddMappings( localMap, rendererUniformMap );
154 AddMappings( localMap, mMaterial->GetUniformMap() );
155 AddMappings( localMap, mMaterial->GetShader()->GetUniformMap() );
156 AddMappings( localMap, mGeometry->GetUniformMap() );
159 else if( mRegenerateUniformMap == COPY_UNIFORM_MAP )
161 // Copy old map into current map
162 CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
163 CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-updateBufferIndex ];
165 localMap.Resize( oldMap.Count() );
167 unsigned int index=0;
168 for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter, ++index )
170 localMap[index] = *iter;
174 mUniformMapChanged[updateBufferIndex] = true;
175 mRegenerateUniformMap--;
178 if( mResendDataProviders )
180 RenderDataProvider* dataProvider = NewRenderDataProvider();
182 typedef MessageValue1< Render::Renderer, OwnerPointer<RenderDataProvider> > DerivedType;
183 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
184 new (slot) DerivedType( mRenderer, &Render::Renderer::SetRenderDataProvider, dataProvider );
185 mResendDataProviders = false;
188 if( mResendGeometry )
190 // The first call to GetRenderGeometry() creates the geometry and sends it in a message
191 RenderGeometry* geometry = mGeometry->GetRenderGeometry( mSceneController );
193 typedef MessageValue1< Render::Renderer, RenderGeometry* > DerivedType;
194 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
196 new (slot) DerivedType( mRenderer, &Render::Renderer::SetGeometry, geometry );
197 mResendGeometry = false;
201 void Renderer::SetMaterial( BufferIndex bufferIndex, Material* material)
203 DALI_ASSERT_DEBUG( material != NULL && "Material pointer is NULL" );
205 mMaterial = material;
206 mMaterial->AddConnectionObserver( *this );
207 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
209 mResendDataProviders = true;
212 void Renderer::SetGeometry( BufferIndex bufferIndex, Geometry* geometry)
214 DALI_ASSERT_DEBUG( geometry != NULL && "Geometry pointer is NULL");
217 mGeometry->RemoveConnectionObserver(*this);
218 mGeometry->OnRendererDisconnect();
221 mGeometry = geometry;
222 mGeometry->AddConnectionObserver( *this ); // Observe geometry connections / uniform mapping changes
223 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
227 mResendGeometry = true;
231 void Renderer::SetDepthIndex( int depthIndex )
233 mDepthIndex = depthIndex;
236 //Called when a node with this renderer is added to the stage
237 void Renderer::OnStageConnect()
242 RenderDataProvider* dataProvider = NewRenderDataProvider();
244 RenderGeometry* renderGeometry = mGeometry->GetRenderGeometry(mSceneController);
245 mRenderer = Render::Renderer::New( dataProvider, renderGeometry );
246 mSceneController->GetRenderMessageDispatcher().AddRenderer( *mRenderer );
247 mResendDataProviders = false;
248 mResendGeometry = false;
252 //Called when the node with this renderer has gone out of the stage
253 void Renderer::OnStageDisconnect()
256 if( mReferenceCount == 0 )
258 mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
261 mGeometry->OnRendererDisconnect();
267 //Called when SceneGraph::Renderer is added to update manager ( that happens when an "event-thread renderer" is created )
268 void Renderer::ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
270 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
271 mSceneController = &sceneController;
275 //Called just before destroying the scene-graph renderer ( when the "event-thread renderer" is no longer referenced )
276 void Renderer::DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
278 //Remove renderer from RenderManager
281 mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
283 mSceneController = NULL;
287 RenderDataProvider* Renderer::NewRenderDataProvider()
289 RenderDataProvider* dataProvider = new RenderDataProvider();
291 dataProvider->mMaterialDataProvider = mMaterial;
292 dataProvider->mUniformMapDataProvider = this;
293 dataProvider->mShader = mMaterial->GetShader();
295 size_t textureCount( mMaterial->GetTextureCount() );
296 dataProvider->mTextures.resize( textureCount );
297 for( unsigned int i(0); i<textureCount; ++i )
299 dataProvider->mTextures[i] = Render::Texture( mMaterial->GetTextureUniformName(i),
300 mMaterial->GetTextureId(i),
301 mMaterial->GetTextureSampler(i));
307 Render::Renderer& Renderer::GetRenderer()
312 const CollectedUniformMap& Renderer::GetUniformMap( BufferIndex bufferIndex ) const
314 return mCollectedUniformMap[bufferIndex];
317 void Renderer::GetReadyAndComplete( bool& ready, bool& complete ) const
319 ready = mResourcesReady;
320 complete = mFinishedResourceAcquisition;
323 // Called by ProcessRenderTasks after DoPrepareRender
324 bool Renderer::IsFullyOpaque( BufferIndex updateBufferIndex, const Node& node ) const
328 if( mMaterial != NULL )
330 Material::BlendPolicy blendPolicy = mMaterial->GetBlendPolicy();
331 switch( blendPolicy )
333 case Material::OPAQUE:
338 case Material::TRANSPARENT:
343 case Material::USE_ACTOR_COLOR:
345 opaque = node.GetWorldColor( updateBufferIndex ).a >= FULLY_OPAQUE;
354 void Renderer::ConnectionsChanged( PropertyOwner& object )
356 // One of our child objects has changed it's connections. Ensure the uniform
357 // map gets regenerated during PrepareRender
358 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
360 // Ensure the child object pointers get re-sent to the renderer
361 mResendDataProviders = true;
364 void Renderer::ConnectedUniformMapChanged()
366 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
369 void Renderer::UniformMappingsChanged( const UniformMap& mappings )
371 // The mappings are either from PropertyOwner base class, or the Actor
372 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
375 void Renderer::ObservedObjectDestroyed(PropertyOwner& owner)
377 if( reinterpret_cast<PropertyOwner*>(mGeometry) == &owner )
381 else if( reinterpret_cast<PropertyOwner*>(mMaterial) == &owner )
387 } // namespace SceneGraph
388 } // namespace Internal