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