Remove scene graph property buffer
[platform/core/uifw/dali-core.git] / dali / internal / update / rendering / scene-graph-renderer.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-renderer.h"
19
20 // INTERNAL HEADERS
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-new-renderer.h>
28 #include <dali/internal/render/data-providers/node-data-provider.h>
29 #include <dali/internal/update/resources/complete-status-manager.h>
30 #include <dali/internal/update/nodes/node.h>
31 #include <dali/internal/update/resources/resource-tracker.h>
32 #include <dali/internal/render/queue/render-queue.h>
33 #include <dali/internal/common/internal-constants.h>
34
35
36 namespace // unnamed namespace
37 {
38
39 const unsigned int UNIFORM_MAP_READY      = 0;
40 const unsigned int COPY_UNIFORM_MAP       = 1;
41 const unsigned int REGENERATE_UNIFORM_MAP = 2;
42
43 void AddMappings( Dali::Internal::SceneGraph::CollectedUniformMap& localMap, const Dali::Internal::SceneGraph::UniformMap& uniformMap )
44 {
45   // Iterate thru uniformMap.
46   //   Any maps that aren't in localMap should be added in a single step
47   Dali::Internal::SceneGraph::CollectedUniformMap newUniformMappings;
48
49   for( unsigned int i=0, count=uniformMap.Count(); i<count; ++i )
50   {
51     Dali::Internal::SceneGraph::UniformPropertyMapping::Hash nameHash = uniformMap[i].uniformNameHash;
52     bool found = false;
53
54     for( Dali::Internal::SceneGraph::CollectedUniformMap::Iterator iter = localMap.Begin() ; iter != localMap.End() ; ++iter )
55     {
56       const Dali::Internal::SceneGraph::UniformPropertyMapping* map = (*iter);
57       if( map->uniformNameHash == nameHash )
58       {
59         if( map->uniformName == uniformMap[i].uniformName )
60         {
61           found = true;
62           break;
63         }
64       }
65     }
66     if( !found )
67     {
68       // it's a new mapping. Add raw ptr to temporary list
69       newUniformMappings.PushBack( &uniformMap[i] );
70     }
71   }
72
73   if( newUniformMappings.Count() > 0 )
74   {
75     localMap.Reserve( localMap.Count() + newUniformMappings.Count() );
76
77     for( Dali::Internal::SceneGraph::CollectedUniformMap::Iterator iter = newUniformMappings.Begin(),
78            end = newUniformMappings.End() ;
79          iter != end ;
80          ++iter )
81     {
82       const Dali::Internal::SceneGraph::UniformPropertyMapping* map = (*iter);
83       localMap.PushBack( map );
84     }
85     //@todo MESH_REWORK Use memcpy to copy ptrs from one array to the other
86   }
87 }
88 }
89
90 namespace Dali
91 {
92 namespace Internal
93 {
94 namespace SceneGraph
95 {
96
97 Renderer::Renderer()
98 :mSceneController(0),
99  mRenderer(NULL),
100  mMaterial(NULL),
101  mGeometry(NULL),
102  mReferenceCount(0),
103  mRegenerateUniformMap(0),
104  mResendDataProviders(false),
105  mResendGeometry(false),
106  mHasUntrackedResources(false),
107  mFinishedResourceAcquisition(false),
108  mResourcesReady(false),
109  mDepthIndex(0)
110 {
111   mUniformMapChanged[0]=false;
112   mUniformMapChanged[1]=false;
113
114   // Observe our own PropertyOwner's uniform map
115   AddUniformMapObserver( *this );
116 }
117
118 Renderer::~Renderer()
119 {
120   if (mMaterial)
121   {
122     mMaterial->RemoveConnectionObserver(*this);
123     mMaterial=NULL;
124   }
125   if (mGeometry)
126   {
127     mGeometry->RemoveConnectionObserver(*this);
128     mGeometry=NULL;
129   }
130 }
131
132 void Renderer::PrepareRender( BufferIndex updateBufferIndex )
133 {
134   mMaterial->PrepareRender( updateBufferIndex );
135
136   if( mRegenerateUniformMap > UNIFORM_MAP_READY )
137   {
138     DALI_ASSERT_DEBUG( mGeometry != NULL && "No geometry available in DoPrepareRender()" );
139     DALI_ASSERT_DEBUG( mMaterial != NULL && "No geometry available in DoPrepareRender()" );
140
141     if( mRegenerateUniformMap == REGENERATE_UNIFORM_MAP)
142     {
143       CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
144       localMap.Resize(0);
145
146       const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap();
147       AddMappings( localMap, rendererUniformMap );
148
149       AddMappings( localMap, mMaterial->GetUniformMap() );
150       AddMappings( localMap, mMaterial->GetShader()->GetUniformMap() );
151       AddMappings( localMap, mGeometry->GetUniformMap() );
152
153     }
154     else if( mRegenerateUniformMap == COPY_UNIFORM_MAP )
155     {
156       // Copy old map into current map
157       CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
158       CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-updateBufferIndex ];
159
160       localMap.Resize( oldMap.Count() );
161
162       unsigned int index=0;
163       for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter, ++index )
164       {
165         localMap[index] = *iter;
166       }
167     }
168
169     mUniformMapChanged[updateBufferIndex] = true;
170     mRegenerateUniformMap--;
171   }
172
173   if( mResendDataProviders )
174   {
175     RenderDataProvider* dataProvider = NewRenderDataProvider();
176
177     // Tell renderer about a new provider
178     // @todo MESH_REWORK Should we instead create a new renderer when these change?
179
180     typedef MessageValue1< Render::NewRenderer, OwnerPointer<RenderDataProvider> > DerivedType;
181     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
182     new (slot) DerivedType( mRenderer, &Render::NewRenderer::SetRenderDataProvider, dataProvider );
183     mResendDataProviders = false;
184   }
185
186   if( mResendGeometry )
187   {
188     // The first call to GetRenderGeometry() creates the geometry and sends it in a message
189     RenderGeometry* geometry = mGeometry->GetRenderGeometry( mSceneController );
190
191     typedef MessageValue1< Render::NewRenderer, RenderGeometry* > DerivedType;
192     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
193
194     new (slot) DerivedType( mRenderer, &Render::NewRenderer::SetGeometry, geometry );
195     mResendGeometry = false;
196   }
197 }
198
199 void Renderer::SetMaterial( BufferIndex bufferIndex, Material* material)
200 {
201   DALI_ASSERT_DEBUG( material != NULL && "Material pointer is NULL" );
202
203   mMaterial = material;
204   mMaterial->AddConnectionObserver( *this );
205   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
206
207   mResendDataProviders = true;
208 }
209
210 void Renderer::SetGeometry( BufferIndex bufferIndex, Geometry* geometry)
211 {
212   DALI_ASSERT_DEBUG( geometry != NULL && "Geometry pointer is NULL");
213   if( mGeometry)
214   {
215     mGeometry->RemoveConnectionObserver(*this);
216     mGeometry->OnRendererDisconnect();
217   }
218
219   mGeometry = geometry;
220   mGeometry->AddConnectionObserver( *this ); // Observe geometry connections / uniform mapping changes
221   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
222
223   if( mRenderer )
224   {
225     mResendGeometry = true;
226   }
227 }
228
229 void Renderer::SetDepthIndex( int depthIndex )
230 {
231   mDepthIndex = depthIndex;
232 }
233
234 //Called when a node with this renderer is added to the stage
235 void Renderer::OnStageConnect()
236 {
237   ++mReferenceCount;
238   if( !mRenderer)
239   {
240     RenderDataProvider* dataProvider = NewRenderDataProvider();
241
242     RenderGeometry* renderGeometry = mGeometry->GetRenderGeometry(mSceneController);
243     mRenderer = Render::NewRenderer::New( dataProvider, renderGeometry );
244     mSceneController->GetRenderMessageDispatcher().AddRenderer( *mRenderer );
245     mResendDataProviders = false;
246     mResendGeometry = false;
247   }
248 }
249
250 //Called when the node with this renderer has gone out of the stage
251 void Renderer::OnStageDisconnect()
252 {
253   --mReferenceCount;
254   if( mReferenceCount == 0 )
255   {
256     mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
257     if( mGeometry )
258     {
259       mGeometry->OnRendererDisconnect();
260     }
261     mRenderer = NULL;
262   }
263 }
264
265 //Called when SceneGraph::Renderer is added to update manager ( that happens when an "event-thread renderer" is created )
266 void Renderer::ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
267 {
268   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
269   mSceneController = &sceneController;
270 }
271
272
273 //Called just before destroying the scene-graph renderer ( when the "event-thread renderer" is no longer referenced )
274 void Renderer::DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
275 {
276   //Remove renderer from RenderManager
277   if( mRenderer )
278   {
279     mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
280     mRenderer = NULL;
281     mSceneController = NULL;
282   }
283 }
284
285 RenderDataProvider* Renderer::NewRenderDataProvider()
286 {
287   RenderDataProvider* dataProvider = new RenderDataProvider();
288
289   dataProvider->mMaterialDataProvider = mMaterial;
290   dataProvider->mUniformMapDataProvider = this;
291   dataProvider->mShader = mMaterial->GetShader();
292
293   size_t textureCount( mMaterial->GetTextureCount() );
294   dataProvider->mTextures.resize( textureCount );
295   for( unsigned int i(0); i<textureCount; ++i )
296   {
297     dataProvider->mTextures[i] = Render::Texture( mMaterial->GetTextureUniformName(i),
298                                                   mMaterial->GetTextureId(i),
299                                                   mMaterial->GetTextureSampler(i));
300   }
301
302   return dataProvider;
303 }
304
305 Render::Renderer& Renderer::GetRenderer()
306 {
307   return *mRenderer;
308 }
309
310 const CollectedUniformMap& Renderer::GetUniformMap( BufferIndex bufferIndex ) const
311 {
312   return mCollectedUniformMap[bufferIndex];
313 };
314
315 void Renderer::PrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager )
316 {
317   mHasUntrackedResources = false;
318   mTrackedResources.Clear(); // Resource trackers are only needed if not yet completea
319
320   DALI_ASSERT_DEBUG( mSceneController );
321
322   CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
323   mResourcesReady = false;
324
325
326   mFinishedResourceAcquisition = false;
327
328   // Can only be considered ready when all the scene graph objects are connected to the renderer
329   if( ( mGeometry ) && ( mGeometry->GetVertexBuffers().Count() > 0 ) &&
330       ( mMaterial ) && ( mMaterial->GetShader() != NULL ) )
331   {
332     unsigned int completeCount = 0;
333     unsigned int neverCount = 0;
334     unsigned int frameBufferCount = 0;
335
336     size_t textureCount( mMaterial->GetTextureCount() );
337     for( unsigned int i(0); i<textureCount; ++i )
338     {
339       ResourceId textureId = mMaterial->GetTextureId(i);
340       BitmapMetadata metaData = resourceManager.GetBitmapMetadata( textureId );
341
342       mMaterial->SetIsFullyOpaque( i, metaData.IsFullyOpaque() );
343
344       switch( completeStatusManager.GetStatus( textureId ) )
345       {
346         case CompleteStatusManager::NOT_READY:
347         {
348           if( metaData.GetIsFramebuffer() )
349           {
350             frameBufferCount++;
351           }
352           if( completeStatusManager.FindResourceTracker(textureId) != NULL )
353           {
354             bool found = false;
355             std::size_t numTrackedResources = mTrackedResources.Count();
356             for( size_t i=0; i < numTrackedResources; ++i )
357             {
358               if(mTrackedResources[i] == textureId)
359               {
360                 found = true;
361                 break;
362               }
363             }
364             if( ! found )
365             {
366               mTrackedResources.PushBack( textureId );
367             }
368           }
369           else
370           {
371             mHasUntrackedResources = true;
372           }
373         }
374         break;
375
376         case CompleteStatusManager::COMPLETE:
377         {
378           completeCount++;
379         }
380         break;
381
382         case CompleteStatusManager::NEVER:
383         {
384           neverCount++;
385         }
386         break;
387       }
388     }
389
390     // We are ready if all samplers are complete, or those that aren't are framebuffers
391     // We are complete if all samplers are either complete or will nmResendGeometryever complete
392     mResourcesReady = ( completeCount + frameBufferCount >= textureCount ) ;
393     mFinishedResourceAcquisition = ( completeCount + neverCount >= textureCount );
394   }
395 }
396
397 void Renderer::GetReadyAndComplete(bool& ready, bool& complete) const
398 {
399   ready = mResourcesReady;
400   complete = false;
401
402   CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
403
404   std::size_t numTrackedResources = mTrackedResources.Count();
405   if( mHasUntrackedResources || numTrackedResources == 0 )
406   {
407     complete = mFinishedResourceAcquisition;
408   }
409   else
410   {
411     // If there are tracked resources and no untracked resources, test the trackers
412     bool trackersComplete = true;
413     for( size_t i=0; i < numTrackedResources; ++i )
414     {
415       ResourceId id = mTrackedResources[i];
416       ResourceTracker* tracker = completeStatusManager.FindResourceTracker(id);
417       if( tracker  && ! tracker->IsComplete() )
418       {
419         trackersComplete = false;
420         break;
421       }
422     }
423
424     complete = mFinishedResourceAcquisition || trackersComplete;
425   }
426 }
427
428 // Called by ProcessRenderTasks after DoPrepareRender
429 bool Renderer::IsFullyOpaque( BufferIndex updateBufferIndex, const Node& node ) const
430 {
431   bool opaque = false;
432
433   if( mMaterial != NULL )
434   {
435     Material::BlendPolicy blendPolicy = mMaterial->GetBlendPolicy();
436     switch( blendPolicy )
437     {
438       case Material::OPAQUE:
439       {
440         opaque = true;
441         break;
442       }
443       case Material::TRANSPARENT:
444       {
445         opaque = false;
446         break;
447       }
448       case Material::USE_ACTOR_COLOR:
449       {
450         opaque = node.GetWorldColor( updateBufferIndex ).a >= FULLY_OPAQUE;
451         break;
452       }
453     }
454   }
455
456   return opaque;
457 }
458
459 void Renderer::ConnectionsChanged( PropertyOwner& object )
460 {
461   // One of our child objects has changed it's connections. Ensure the uniform
462   // map gets regenerated during PrepareRender
463   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
464
465   // Ensure the child object pointers get re-sent to the renderer
466   mResendDataProviders = true;
467 }
468
469 void Renderer::ConnectedUniformMapChanged()
470 {
471   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
472 }
473
474 void Renderer::UniformMappingsChanged( const UniformMap& mappings )
475 {
476   // The mappings are either from PropertyOwner base class, or the Actor
477   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
478 }
479
480 void Renderer::ObservedObjectDestroyed(PropertyOwner& owner)
481 {
482   if( reinterpret_cast<PropertyOwner*>(mGeometry) == &owner )
483   {
484     mGeometry = NULL;
485   }
486   else if( reinterpret_cast<PropertyOwner*>(mMaterial) == &owner )
487   {
488     mMaterial = NULL;
489   }
490 }
491
492 } // namespace SceneGraph
493 } // namespace Internal
494 } // namespace Dali