Added setIndicesRange(offset, count) function to the Dali::Renderer which allows...
[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-texture-set.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>
32 #include <dali/internal/common/memory-pool-object-allocator.h>
33
34
35 namespace // unnamed namespace
36 {
37
38 const unsigned int UNIFORM_MAP_READY      = 0;
39 const unsigned int COPY_UNIFORM_MAP       = 1;
40 const unsigned int REGENERATE_UNIFORM_MAP = 2;
41
42 //Memory pool used to allocate new renderers. Memory used by this pool will be released when shutting down DALi
43 Dali::Internal::MemoryPoolObjectAllocator<Dali::Internal::SceneGraph::Renderer> gRendererMemoryPool;
44
45 void AddMappings( Dali::Internal::SceneGraph::CollectedUniformMap& localMap, const Dali::Internal::SceneGraph::UniformMap& uniformMap )
46 {
47   // Iterate thru uniformMap.
48   //   Any maps that aren't in localMap should be added in a single step
49   Dali::Internal::SceneGraph::CollectedUniformMap newUniformMappings;
50
51   for( unsigned int i=0, count=uniformMap.Count(); i<count; ++i )
52   {
53     Dali::Internal::SceneGraph::UniformPropertyMapping::Hash nameHash = uniformMap[i].uniformNameHash;
54     bool found = false;
55
56     for( Dali::Internal::SceneGraph::CollectedUniformMap::Iterator iter = localMap.Begin() ; iter != localMap.End() ; ++iter )
57     {
58       const Dali::Internal::SceneGraph::UniformPropertyMapping* map = (*iter);
59       if( map->uniformNameHash == nameHash )
60       {
61         if( map->uniformName == uniformMap[i].uniformName )
62         {
63           found = true;
64           break;
65         }
66       }
67     }
68     if( !found )
69     {
70       // it's a new mapping. Add raw ptr to temporary list
71       newUniformMappings.PushBack( &uniformMap[i] );
72     }
73   }
74
75   if( newUniformMappings.Count() > 0 )
76   {
77     localMap.Reserve( localMap.Count() + newUniformMappings.Count() );
78
79     for( Dali::Internal::SceneGraph::CollectedUniformMap::Iterator iter = newUniformMappings.Begin(),
80            end = newUniformMappings.End() ;
81          iter != end ;
82          ++iter )
83     {
84       const Dali::Internal::SceneGraph::UniformPropertyMapping* map = (*iter);
85       localMap.PushBack( map );
86     }
87   }
88 }
89
90 // flags for resending data to renderer
91 enum Flags
92 {
93   RESEND_DATA_PROVIDER = 1,
94   RESEND_GEOMETRY = 1 << 1,
95   RESEND_FACE_CULLING_MODE = 1 << 2,
96   RESEND_BLEND_COLOR = 1 << 3,
97   RESEND_BLEND_BIT_MASK = 1 << 4,
98   RESEND_PREMULTIPLIED_ALPHA = 1 << 5,
99   RESEND_INDEXED_DRAW_FIRST_ELEMENT = 1 << 6,
100   RESEND_INDEXED_DRAW_ELEMENTS_COUNT = 1 << 7,
101 };
102
103 }
104
105 namespace Dali
106 {
107 namespace Internal
108 {
109 namespace SceneGraph
110 {
111
112 Renderer* Renderer::New()
113 {
114   return new ( gRendererMemoryPool.AllocateRawThreadSafe() ) Renderer();
115 }
116
117 Renderer::Renderer()
118 :mSceneController( 0 ),
119  mRenderer( NULL ),
120  mTextureSet( NULL ),
121  mGeometry( NULL ),
122  mShader( NULL ),
123  mBlendColor( NULL ),
124  mBlendBitmask( 0u ),
125  mFaceCullingMode( Dali::Renderer::NONE ),
126  mBlendingMode( Dali::BlendingMode::AUTO ),
127  mReferenceCount( 0 ),
128  mRegenerateUniformMap( 0 ),
129  mResendFlag( 0 ),
130  mResourcesReady( false ),
131  mFinishedResourceAcquisition( false ),
132  mIndexedDrawFirstElement( 0 ),
133  mIndexedDrawElementsCount( 0 ),
134  mDepthIndex( 0 )
135 {
136   mUniformMapChanged[0] = false;
137   mUniformMapChanged[1] = false;
138
139   // Observe our own PropertyOwner's uniform map
140   AddUniformMapObserver( *this );
141 }
142
143 Renderer::~Renderer()
144 {
145   if (mTextureSet)
146   {
147     mTextureSet->RemoveConnectionObserver(*this);
148     mTextureSet=NULL;
149   }
150   if (mGeometry)
151   {
152     mGeometry->RemoveConnectionObserver(*this);
153     mGeometry=NULL;
154   }
155   if( mShader )
156   {
157     mShader->RemoveConnectionObserver(*this);
158     mShader=NULL;
159   }
160
161 }
162
163 void Renderer::operator delete( void* ptr )
164 {
165   gRendererMemoryPool.FreeThreadSafe( static_cast<Renderer*>( ptr ) );
166 }
167
168
169 void Renderer::PrepareRender( BufferIndex updateBufferIndex )
170 {
171   mResourcesReady = false;
172   mFinishedResourceAcquisition = false;
173
174   // Can only be considered ready when all the scene graph objects are connected to the renderer
175   if( ( mGeometry ) && ( mGeometry->GetVertexBuffers().Count() > 0 ) && ( mShader ) )
176   {
177     if( mTextureSet )
178     {
179       mTextureSet->GetResourcesStatus( mResourcesReady, mFinishedResourceAcquisition );
180     }
181     else
182     {
183       mResourcesReady = true;
184       mFinishedResourceAcquisition = true;
185     }
186   }
187
188   if( mRegenerateUniformMap > UNIFORM_MAP_READY )
189   {
190     DALI_ASSERT_DEBUG( mGeometry != NULL && "No geometry available in PrepareRender()" );
191     DALI_ASSERT_DEBUG( mShader != NULL && "No shader available in PrepareRender()" );
192
193     if( mRegenerateUniformMap == REGENERATE_UNIFORM_MAP)
194     {
195       CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
196       localMap.Resize(0);
197
198       const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap();
199       AddMappings( localMap, rendererUniformMap );
200
201       if( mTextureSet )
202       {
203         AddMappings( localMap, mTextureSet->GetUniformMap() );
204       }
205
206       AddMappings( localMap, mShader->GetUniformMap() );
207       AddMappings( localMap, mGeometry->GetUniformMap() );
208
209     }
210     else if( mRegenerateUniformMap == COPY_UNIFORM_MAP )
211     {
212       // Copy old map into current map
213       CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
214       CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-updateBufferIndex ];
215
216       localMap.Resize( oldMap.Count() );
217
218       unsigned int index=0;
219       for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter, ++index )
220       {
221         localMap[index] = *iter;
222       }
223     }
224
225     mUniformMapChanged[updateBufferIndex] = true;
226     mRegenerateUniformMap--;
227   }
228
229   if( mResendFlag == 0 )
230   {
231     return;
232   }
233
234   if( mResendFlag & RESEND_DATA_PROVIDER )
235   {
236     RenderDataProvider* dataProvider = NewRenderDataProvider();
237
238     typedef MessageValue1< Render::Renderer, OwnerPointer<RenderDataProvider> > DerivedType;
239     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
240     new (slot) DerivedType( mRenderer, &Render::Renderer::SetRenderDataProvider, dataProvider );
241     mResendFlag &= ~RESEND_DATA_PROVIDER;
242   }
243
244   if( mResendFlag & RESEND_GEOMETRY )
245   {
246     // The first call to GetRenderGeometry() creates the geometry and sends it in a message
247     RenderGeometry* geometry = mGeometry->GetRenderGeometry( mSceneController );
248
249     typedef MessageValue1< Render::Renderer, RenderGeometry* > DerivedType;
250     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
251
252     new (slot) DerivedType( mRenderer, &Render::Renderer::SetGeometry, geometry );
253     mResendFlag &= ~RESEND_GEOMETRY;
254   }
255
256   if( mResendFlag & RESEND_FACE_CULLING_MODE )
257   {
258     typedef MessageValue1< Render::Renderer, Dali::Renderer::FaceCullingMode > DerivedType;
259     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
260     new (slot) DerivedType( mRenderer, &Render::Renderer::SetFaceCullingMode, mFaceCullingMode );
261     mResendFlag &= ~RESEND_FACE_CULLING_MODE;
262   }
263
264   if( mResendFlag & RESEND_BLEND_BIT_MASK )
265   {
266     typedef MessageValue1< Render::Renderer, unsigned int > DerivedType;
267     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
268     new (slot) DerivedType( mRenderer, &Render::Renderer::SetBlendingBitMask, mBlendBitmask );
269     mResendFlag &= ~RESEND_BLEND_BIT_MASK;
270   }
271
272   if( mResendFlag & RESEND_BLEND_COLOR )
273   {
274     typedef MessageValue1< Render::Renderer, const Vector4* > DerivedType;
275     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
276     new (slot) DerivedType( mRenderer, &Render::Renderer::SetBlendColor, mBlendColor );
277     mResendFlag &= ~RESEND_BLEND_COLOR;
278   }
279
280   if( mResendFlag & RESEND_PREMULTIPLIED_ALPHA  )
281   {
282     typedef MessageValue1< Render::Renderer, bool > DerivedType;
283     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
284     new (slot) DerivedType( mRenderer, &Render::Renderer::EnablePreMultipliedAlpha, mPremultipledAlphaEnabled );
285     mResendFlag &= ~RESEND_PREMULTIPLIED_ALPHA;
286   }
287
288   if( mResendFlag & RESEND_INDEXED_DRAW_FIRST_ELEMENT )
289   {
290     typedef MessageValue1< Render::Renderer, size_t > DerivedType;
291     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
292     new (slot) DerivedType( mRenderer, &Render::Renderer::SetIndexedDrawFirstElement, mIndexedDrawFirstElement );
293     mResendFlag &= ~RESEND_INDEXED_DRAW_FIRST_ELEMENT;
294   }
295
296   if( mResendFlag & RESEND_INDEXED_DRAW_ELEMENTS_COUNT )
297   {
298     typedef MessageValue1< Render::Renderer, size_t > DerivedType;
299     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
300     new (slot) DerivedType( mRenderer, &Render::Renderer::SetIndexedDrawElementsCount, mIndexedDrawElementsCount );
301     mResendFlag &= ~RESEND_INDEXED_DRAW_FIRST_ELEMENT;
302   }
303
304
305 }
306
307 void Renderer::SetTextures( TextureSet* textureSet )
308 {
309   DALI_ASSERT_DEBUG( textureSet != NULL && "Texture set pointer is NULL" );
310
311   if( mTextureSet )
312   {
313     mTextureSet->RemoveConnectionObserver(*this);
314   }
315
316   mTextureSet = textureSet;
317   mTextureSet->AddConnectionObserver( *this );
318   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
319   mResendFlag |= RESEND_DATA_PROVIDER;
320 }
321
322 void Renderer::SetShader( Shader* shader )
323 {
324   DALI_ASSERT_DEBUG( shader != NULL && "Shader pointer is NULL" );
325
326   if( mShader )
327   {
328     mShader->RemoveConnectionObserver(*this);
329   }
330
331   mShader = shader;
332   mShader->AddConnectionObserver( *this );
333   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
334   mResendFlag |= RESEND_DATA_PROVIDER;
335 }
336
337 void Renderer::SetGeometry( Geometry* geometry )
338 {
339   DALI_ASSERT_DEBUG( geometry != NULL && "Geometry pointer is NULL");
340   if( mGeometry)
341   {
342     mGeometry->RemoveConnectionObserver(*this);
343     mGeometry->OnRendererDisconnect();
344   }
345
346   mGeometry = geometry;
347   mGeometry->AddConnectionObserver( *this ); // Observe geometry connections / uniform mapping changes
348   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
349
350   if( mRenderer )
351   {
352     mResendFlag |= RESEND_GEOMETRY;
353   }
354 }
355
356 void Renderer::SetDepthIndex( int depthIndex )
357 {
358   mDepthIndex = depthIndex;
359 }
360
361 void Renderer::SetFaceCullingMode( unsigned int faceCullingMode )
362 {
363   mFaceCullingMode = static_cast<Dali::Renderer::FaceCullingMode>(faceCullingMode);
364   mResendFlag |= RESEND_FACE_CULLING_MODE;
365 }
366
367 void Renderer::SetBlendingMode( unsigned int blendingMode )
368 {
369   mBlendingMode = static_cast< BlendingMode::Type >( blendingMode );
370 }
371
372 void Renderer::SetBlendingOptions( unsigned int options )
373 {
374   if( mBlendBitmask != options)
375   {
376     mBlendBitmask = options;
377     mResendFlag |= RESEND_BLEND_BIT_MASK;
378   }
379 }
380
381 void Renderer::SetBlendColor( const Vector4& blendColor )
382 {
383   if( !mBlendColor )
384   {
385     mBlendColor = new Vector4( blendColor );
386   }
387   else
388   {
389     *mBlendColor = blendColor;
390   }
391
392   mResendFlag |= RESEND_BLEND_COLOR;
393 }
394
395 void Renderer::SetIndexedDrawFirstElement( size_t firstElement )
396 {
397   mIndexedDrawFirstElement = firstElement;
398   mResendFlag |= RESEND_INDEXED_DRAW_FIRST_ELEMENT;
399 }
400
401 void Renderer::SetIndexedDrawElementsCount( size_t elementsCount )
402 {
403   mIndexedDrawElementsCount = elementsCount;
404   mResendFlag |= RESEND_INDEXED_DRAW_ELEMENTS_COUNT;
405 }
406
407 void Renderer::EnablePreMultipliedAlpha( bool preMultipled )
408 {
409   mPremultipledAlphaEnabled = preMultipled;
410   mResendFlag |= RESEND_PREMULTIPLIED_ALPHA;
411 }
412
413 //Called when a node with this renderer is added to the stage
414 void Renderer::OnStageConnect()
415 {
416   ++mReferenceCount;
417   if( !mRenderer)
418   {
419     RenderDataProvider* dataProvider = NewRenderDataProvider();
420
421     RenderGeometry* renderGeometry = mGeometry->GetRenderGeometry(mSceneController);
422     mRenderer = Render::Renderer::New( dataProvider, renderGeometry,
423                                        mBlendBitmask, mBlendColor,
424                                        static_cast< Dali::Renderer::FaceCullingMode >( mFaceCullingMode ),
425                                        mPremultipledAlphaEnabled );
426     mSceneController->GetRenderMessageDispatcher().AddRenderer( *mRenderer );
427     mResendFlag = 0;
428   }
429 }
430
431 //Called when the node with this renderer has gone out of the stage
432 void Renderer::OnStageDisconnect()
433 {
434   --mReferenceCount;
435   if( mReferenceCount == 0 )
436   {
437     mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
438     if( mGeometry )
439     {
440       mGeometry->OnRendererDisconnect();
441     }
442     mRenderer = NULL;
443   }
444 }
445
446 //Called when SceneGraph::Renderer is added to update manager ( that happens when an "event-thread renderer" is created )
447 void Renderer::ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
448 {
449   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
450   mSceneController = &sceneController;
451 }
452
453
454 //Called just before destroying the scene-graph renderer ( when the "event-thread renderer" is no longer referenced )
455 void Renderer::DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
456 {
457   //Remove renderer from RenderManager
458   if( mRenderer )
459   {
460     mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
461     mRenderer = NULL;
462     mSceneController = NULL;
463   }
464 }
465
466 RenderDataProvider* Renderer::NewRenderDataProvider()
467 {
468   RenderDataProvider* dataProvider = new RenderDataProvider();
469
470   dataProvider->mUniformMapDataProvider = this;
471   dataProvider->mShader = mShader;
472
473   if( mTextureSet )
474   {
475     size_t textureCount( mTextureSet->GetTextureCount() );
476     dataProvider->mTextures.resize( textureCount );
477     for( unsigned int i(0); i<textureCount; ++i )
478     {
479       dataProvider->mTextures[i] = Render::Texture( mTextureSet->GetTextureId(i),
480                                                     mTextureSet->GetTextureSampler(i));
481     }
482   }
483
484   return dataProvider;
485 }
486
487 Render::Renderer& Renderer::GetRenderer()
488 {
489   return *mRenderer;
490 }
491
492 const CollectedUniformMap& Renderer::GetUniformMap( BufferIndex bufferIndex ) const
493 {
494   return mCollectedUniformMap[bufferIndex];
495 };
496
497 void Renderer::GetReadyAndComplete( bool& ready, bool& complete ) const
498 {
499   ready = mResourcesReady;
500   complete = mFinishedResourceAcquisition;
501 }
502
503 Renderer::Opacity Renderer::GetOpacity( BufferIndex updateBufferIndex, const Node& node ) const
504 {
505   Renderer::Opacity opacity = Renderer::OPAQUE;
506
507   switch( mBlendingMode )
508   {
509     case BlendingMode::ON: // If the renderer should always be use blending
510     {
511       opacity = Renderer::TRANSLUCENT;
512       break;
513     }
514     case BlendingMode::AUTO:
515     {
516       bool shaderRequiresBlending( mShader->GeometryHintEnabled( Dali::ShaderEffect::HINT_BLENDING ) );
517       if( shaderRequiresBlending || ( mTextureSet && mTextureSet->HasAlpha() ) )
518       {
519         opacity = Renderer::TRANSLUCENT;
520       }
521       else // renderer should determine opacity using the actor color
522       {
523         float alpha = node.GetWorldColor( updateBufferIndex ).a;
524         if( alpha <= FULLY_TRANSPARENT )
525         {
526           opacity = TRANSPARENT;
527         }
528         else if( alpha <= FULLY_OPAQUE )
529         {
530           opacity = TRANSLUCENT;
531         }
532       }
533       break;
534     }
535     case BlendingMode::OFF: // the renderer should never use blending
536     default:
537     {
538       opacity = Renderer::OPAQUE;
539       break;
540     }
541   }
542
543
544   return opacity;
545 }
546
547 void Renderer::ConnectionsChanged( PropertyOwner& object )
548 {
549   // One of our child objects has changed it's connections. Ensure the uniform
550   // map gets regenerated during PrepareRender
551   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
552
553   // Ensure the child object pointers get re-sent to the renderer
554   mResendFlag |= RESEND_DATA_PROVIDER;
555 }
556
557 void Renderer::ConnectedUniformMapChanged()
558 {
559   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
560 }
561
562 void Renderer::UniformMappingsChanged( const UniformMap& mappings )
563 {
564   // The mappings are either from PropertyOwner base class, or the Actor
565   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
566 }
567
568 void Renderer::ObservedObjectDestroyed(PropertyOwner& owner)
569 {
570   if( reinterpret_cast<PropertyOwner*>(mGeometry) == &owner )
571   {
572     mGeometry = NULL;
573   }
574   else if( reinterpret_cast<PropertyOwner*>(mTextureSet) == &owner )
575   {
576     mTextureSet = NULL;
577   }
578   else if( reinterpret_cast<PropertyOwner*>(mShader) == &owner )
579   {
580     mShader = NULL;
581   }
582 }
583
584 } // namespace SceneGraph
585 } // namespace Internal
586 } // namespace Dali