Minor cleanup of commented out headers and @todos
[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       Vector<PropertyBuffer*>& vertexBuffers = mGeometry->GetVertexBuffers();
154       unsigned int vertexBufferCount( vertexBuffers.Size() );
155       for( unsigned int i(0); i<vertexBufferCount; ++i )
156       {
157         AddMappings( localMap, vertexBuffers[i]->GetUniformMap() );
158       }
159
160       PropertyBuffer* indexBuffer = mGeometry->GetIndexBuffer();
161       if( indexBuffer )
162       {
163         AddMappings( localMap, indexBuffer->GetUniformMap() );
164       }
165     }
166     else if( mRegenerateUniformMap == COPY_UNIFORM_MAP )
167     {
168       // Copy old map into current map
169       CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
170       CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-updateBufferIndex ];
171
172       localMap.Resize( oldMap.Count() );
173
174       unsigned int index=0;
175       for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter, ++index )
176       {
177         localMap[index] = *iter;
178       }
179     }
180
181     mUniformMapChanged[updateBufferIndex] = true;
182     mRegenerateUniformMap--;
183   }
184
185   if( mResendDataProviders )
186   {
187     RenderDataProvider* dataProvider = NewRenderDataProvider();
188
189     // Tell renderer about a new provider
190     // @todo MESH_REWORK Should we instead create a new renderer when these change?
191
192     typedef MessageValue1< Render::NewRenderer, OwnerPointer<RenderDataProvider> > DerivedType;
193     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
194     new (slot) DerivedType( mRenderer, &Render::NewRenderer::SetRenderDataProvider, dataProvider );
195     mResendDataProviders = false;
196   }
197
198   if( mResendGeometry )
199   {
200     // The first call to GetRenderGeometry() creates the geometry and sends it in a message
201     RenderGeometry* geometry = mGeometry->GetRenderGeometry( mSceneController );
202
203     typedef MessageValue1< Render::NewRenderer, RenderGeometry* > DerivedType;
204     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
205
206     new (slot) DerivedType( mRenderer, &Render::NewRenderer::SetGeometry, geometry );
207     mResendGeometry = false;
208   }
209 }
210
211 void Renderer::SetMaterial( BufferIndex bufferIndex, Material* material)
212 {
213   DALI_ASSERT_DEBUG( material != NULL && "Material pointer is NULL" );
214
215   mMaterial = material;
216   mMaterial->AddConnectionObserver( *this );
217   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
218
219   mResendDataProviders = true;
220 }
221
222 void Renderer::SetGeometry( BufferIndex bufferIndex, Geometry* geometry)
223 {
224   DALI_ASSERT_DEBUG( geometry != NULL && "Geometry pointer is NULL");
225   if( mGeometry)
226   {
227     mGeometry->RemoveConnectionObserver(*this);
228     mGeometry->OnRendererDisconnect();
229   }
230
231   mGeometry = geometry;
232   mGeometry->AddConnectionObserver( *this ); // Observe geometry connections / uniform mapping changes
233   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
234
235   if( mRenderer )
236   {
237     mResendGeometry = true;
238   }
239 }
240
241 void Renderer::SetDepthIndex( int depthIndex )
242 {
243   mDepthIndex = depthIndex;
244 }
245
246 //Called when a node with this renderer is added to the stage
247 void Renderer::OnStageConnect()
248 {
249   ++mReferenceCount;
250   if( !mRenderer)
251   {
252     RenderDataProvider* dataProvider = NewRenderDataProvider();
253
254     RenderGeometry* renderGeometry = mGeometry->GetRenderGeometry(mSceneController);
255     mRenderer = Render::NewRenderer::New( dataProvider, renderGeometry );
256     mSceneController->GetRenderMessageDispatcher().AddRenderer( *mRenderer );
257     mResendDataProviders = false;
258     mResendGeometry = false;
259   }
260 }
261
262 //Called when the node with this renderer has gone out of the stage
263 void Renderer::OnStageDisconnect()
264 {
265   --mReferenceCount;
266   if( mReferenceCount == 0 )
267   {
268     mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
269     mRenderer = NULL;
270   }
271 }
272
273 //Called when SceneGraph::Renderer is added to update manager ( that happens when an "event-thread renderer" is created )
274 void Renderer::ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
275 {
276   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
277   mSceneController = &sceneController;
278 }
279
280
281 //Called just before destroying the scene-graph renderer ( when the "event-thread renderer" is no longer referenced )
282 void Renderer::DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
283 {
284   //Remove renderer from RenderManager
285   if( mRenderer )
286   {
287     mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
288     mRenderer = NULL;
289     mSceneController = NULL;
290   }
291 }
292
293 RenderDataProvider* Renderer::NewRenderDataProvider()
294 {
295   RenderDataProvider* dataProvider = new RenderDataProvider();
296
297   dataProvider->mMaterialDataProvider = mMaterial;
298   dataProvider->mUniformMapDataProvider = this;
299   dataProvider->mShader = mMaterial->GetShader();
300
301   size_t textureCount( mMaterial->GetTextureCount() );
302   dataProvider->mTextures.resize( textureCount );
303   for( unsigned int i(0); i<textureCount; ++i )
304   {
305     dataProvider->mTextures[i] = Render::Texture( mMaterial->GetTextureUniformName(i),
306                                                   mMaterial->GetTextureId(i),
307                                                   mMaterial->GetTextureSampler(i));
308   }
309
310   return dataProvider;
311 }
312
313 Render::Renderer& Renderer::GetRenderer()
314 {
315   return *mRenderer;
316 }
317
318 const CollectedUniformMap& Renderer::GetUniformMap( BufferIndex bufferIndex ) const
319 {
320   return mCollectedUniformMap[bufferIndex];
321 };
322
323 void Renderer::PrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager )
324 {
325   mHasUntrackedResources = false;
326   mTrackedResources.Clear(); // Resource trackers are only needed if not yet completea
327
328   DALI_ASSERT_DEBUG( mSceneController );
329
330   CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
331   mResourcesReady = false;
332
333
334   mFinishedResourceAcquisition = false;
335
336   // Can only be considered ready when all the scene graph objects are connected to the renderer
337   if( ( mGeometry ) && ( mGeometry->GetVertexBuffers().Count() > 0 ) &&
338       ( mMaterial ) && ( mMaterial->GetShader() != NULL ) )
339   {
340     unsigned int completeCount = 0;
341     unsigned int neverCount = 0;
342     unsigned int frameBufferCount = 0;
343
344     size_t textureCount( mMaterial->GetTextureCount() );
345     for( unsigned int i(0); i<textureCount; ++i )
346     {
347       ResourceId textureId = mMaterial->GetTextureId(i);
348       BitmapMetadata metaData = resourceManager.GetBitmapMetadata( textureId );
349
350       mMaterial->SetIsFullyOpaque( i, metaData.IsFullyOpaque() );
351
352       switch( completeStatusManager.GetStatus( textureId ) )
353       {
354         case CompleteStatusManager::NOT_READY:
355         {
356           if( metaData.GetIsFramebuffer() )
357           {
358             frameBufferCount++;
359           }
360           if( completeStatusManager.FindResourceTracker(textureId) != NULL )
361           {
362             bool found = false;
363             std::size_t numTrackedResources = mTrackedResources.Count();
364             for( size_t i=0; i < numTrackedResources; ++i )
365             {
366               if(mTrackedResources[i] == textureId)
367               {
368                 found = true;
369                 break;
370               }
371             }
372             if( ! found )
373             {
374               mTrackedResources.PushBack( textureId );
375             }
376           }
377           else
378           {
379             mHasUntrackedResources = true;
380           }
381         }
382         break;
383
384         case CompleteStatusManager::COMPLETE:
385         {
386           completeCount++;
387         }
388         break;
389
390         case CompleteStatusManager::NEVER:
391         {
392           neverCount++;
393         }
394         break;
395       }
396     }
397
398     // We are ready if all samplers are complete, or those that aren't are framebuffers
399     // We are complete if all samplers are either complete or will nmResendGeometryever complete
400     mResourcesReady = ( completeCount + frameBufferCount >= textureCount ) ;
401     mFinishedResourceAcquisition = ( completeCount + neverCount >= textureCount );
402   }
403 }
404
405 void Renderer::GetReadyAndComplete(bool& ready, bool& complete) const
406 {
407   ready = mResourcesReady;
408   complete = false;
409
410   CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
411
412   std::size_t numTrackedResources = mTrackedResources.Count();
413   if( mHasUntrackedResources || numTrackedResources == 0 )
414   {
415     complete = mFinishedResourceAcquisition;
416   }
417   else
418   {
419     // If there are tracked resources and no untracked resources, test the trackers
420     bool trackersComplete = true;
421     for( size_t i=0; i < numTrackedResources; ++i )
422     {
423       ResourceId id = mTrackedResources[i];
424       ResourceTracker* tracker = completeStatusManager.FindResourceTracker(id);
425       if( tracker  && ! tracker->IsComplete() )
426       {
427         trackersComplete = false;
428         break;
429       }
430     }
431
432     complete = mFinishedResourceAcquisition || trackersComplete;
433   }
434 }
435
436 // Called by ProcessRenderTasks after DoPrepareRender
437 bool Renderer::IsFullyOpaque( BufferIndex updateBufferIndex, const Node& node ) const
438 {
439   bool opaque = false;
440
441   if( mMaterial != NULL )
442   {
443     Material::BlendPolicy blendPolicy = mMaterial->GetBlendPolicy();
444     switch( blendPolicy )
445     {
446       case Material::OPAQUE:
447       {
448         opaque = true;
449         break;
450       }
451       case Material::TRANSPARENT:
452       {
453         opaque = false;
454         break;
455       }
456       case Material::USE_ACTOR_COLOR:
457       {
458         opaque = node.GetWorldColor( updateBufferIndex ).a >= FULLY_OPAQUE;
459         break;
460       }
461     }
462   }
463
464   return opaque;
465 }
466
467 void Renderer::ConnectionsChanged( PropertyOwner& object )
468 {
469   // One of our child objects has changed it's connections. Ensure the uniform
470   // map gets regenerated during PrepareRender
471   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
472
473   // Ensure the child object pointers get re-sent to the renderer
474   mResendDataProviders = true;
475 }
476
477 void Renderer::ConnectedUniformMapChanged()
478 {
479   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
480 }
481
482 void Renderer::UniformMappingsChanged( const UniformMap& mappings )
483 {
484   // The mappings are either from PropertyOwner base class, or the Actor
485   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
486 }
487
488 void Renderer::ObservedObjectDestroyed(PropertyOwner& owner)
489 {
490   if( reinterpret_cast<PropertyOwner*>(mGeometry) == &owner )
491   {
492     mGeometry = NULL;
493   }
494   else if( reinterpret_cast<PropertyOwner*>(mMaterial) == &owner )
495   {
496     mMaterial = NULL;
497   }
498 }
499
500 } // namespace SceneGraph
501 } // namespace Internal
502 } // namespace Dali