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