Added Blending handling for materials and renderers
[platform/core/uifw/dali-core.git] / dali / internal / update / node-attachments / scene-graph-renderer-attachment.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 #include "scene-graph-renderer-attachment.h"
18 #include <dali/internal/update/effects/scene-graph-material.h>
19 #include <dali/internal/update/effects/scene-graph-sampler.h>
20 #include <dali/internal/update/common/uniform-map.h>
21 #include <dali/internal/update/geometry/scene-graph-geometry.h>
22 #include <dali/internal/update/resources/complete-status-manager.h>
23 #include <dali/internal/update/resources/resource-manager.h>
24 #include <dali/internal/render/data-providers/render-data-provider.h>
25 #include <dali/internal/render/queue/render-queue.h>
26 #include <dali/internal/render/renderers/render-renderer.h>
27 #include <dali/internal/render/shaders/scene-graph-shader.h>
28
29 #if defined(DEBUG_ENABLED)
30 Debug::Filter* gImageAttachmentLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_SCENE_GRAPH_IMAGE_ATTACHMENT");
31
32 #define ATTACHMENT_LOG(level)                                                 \
33   DALI_LOG_INFO(gImageAttachmentLogFilter, level, "SceneGraph::ImageAttachment::%s: this:%p\n", __FUNCTION__, this)
34 #define ATTACHMENT_LOG_FMT(level, format, args...) \
35   DALI_LOG_INFO(gImageAttachmentLogFilter, level, "SceneGraph::ImageAttachment::%s: this:%p " format, __FUNCTION__, this, ## args)
36
37 #else
38
39 #define ATTACHMENT_LOG(level)
40 #define ATTACHMENT_LOG_FMT(level, format, args...)
41
42 #endif
43
44
45 namespace // unnamed namespace
46 {
47 const int REGENERATE_UNIFORM_MAP = 2;
48 const int COPY_UNIFORM_MAP       = 1;
49 }
50
51 namespace Dali
52 {
53 namespace Internal
54 {
55 namespace SceneGraph
56 {
57
58 RendererAttachment* RendererAttachment::New()
59 {
60   return new RendererAttachment();
61 }
62
63
64 RendererAttachment::RendererAttachment()
65 : RenderableAttachment( false ),
66   mRenderer(NULL),
67   mMaterial(NULL),
68   mGeometry(NULL),
69   mRegenerateUniformMap(REGENERATE_UNIFORM_MAP),
70   mResendDataProviders(false),
71   mDepthIndex(0)
72 {
73   mUniformMapChanged[0]=false;
74   mUniformMapChanged[1]=false;
75
76   // Observe our own PropertyOwner's uniform map
77   AddUniformMapObserver( *this );
78 }
79
80
81 RendererAttachment::~RendererAttachment()
82 {
83   mMaterial->RemoveConnectionObserver(*this);
84   mGeometry->RemoveConnectionObserver(*this);
85
86   mMaterial=NULL;
87   mGeometry=NULL;
88 }
89
90 void RendererAttachment::Initialize2( BufferIndex updateBufferIndex )
91 {
92   DALI_ASSERT_DEBUG( mSceneController );
93 }
94
95 void RendererAttachment::OnDestroy2()
96 {
97 }
98
99 void RendererAttachment::ConnectedToSceneGraph()
100 {
101   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
102   mParent->AddUniformMapObserver( *this ); // Watch actor's uniform maps
103
104   DALI_ASSERT_DEBUG( mParent != NULL );
105
106   RenderDataProvider* dataProvider = NewRenderDataProvider();
107
108   mRenderer = NewRenderer::New( *mParent, dataProvider );
109   mSceneController->GetRenderMessageDispatcher().AddRenderer( *mRenderer );
110 }
111
112 void RendererAttachment::DisconnectedFromSceneGraph()
113 {
114   mRegenerateUniformMap = 0;
115   mParent->RemoveUniformMapObserver( *this );
116
117   DALI_ASSERT_DEBUG( mSceneController );
118   mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
119   mRenderer = NULL;
120 }
121
122 void RendererAttachment::SetMaterial( BufferIndex updateBufferIndex, Material* material)
123 {
124   DALI_ASSERT_DEBUG( material != NULL && "Material pointer is NULL" );
125
126   mMaterial = material;
127   mMaterial->AddConnectionObserver( *this );
128   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
129
130   mResendDataProviders = true;
131 }
132
133 Material& RendererAttachment::GetMaterial()
134 {
135   return *mMaterial;
136 }
137
138 void RendererAttachment::SetGeometry( BufferIndex updateBufferIndex, Geometry* geometry)
139 {
140   DALI_ASSERT_DEBUG( geometry != NULL && "Geometry pointer is NULL");
141
142   mGeometry = geometry;
143   mGeometry->AddConnectionObserver( *this ); // Observe geometry connections / uniform mapping changes
144   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
145
146   mResendDataProviders = true;
147 }
148
149 Geometry& RendererAttachment::GetGeometry()
150 {
151   return *mGeometry;
152 }
153
154 void RendererAttachment::SetDepthIndex( BufferIndex updateBufferIndex, int depthIndex )
155 {
156   mDepthIndex.Bake(updateBufferIndex, depthIndex);
157
158   if( mParent )
159   {
160     // only do this if we are on-stage
161     mParent->SetDirtyFlag( SortModifierFlag );
162   }
163
164   // @todo MESH_REWORK Change SortTransparentRenderItems to use GetDepthIndex instead
165   mSortModifier = depthIndex;
166 }
167
168 void RendererAttachment::ResetToBaseValues( BufferIndex updateBufferIndex )
169 {
170   mDepthIndex.ResetToBaseValue( updateBufferIndex );
171 }
172
173 Renderer& RendererAttachment::GetRenderer()
174 {
175   return *mRenderer;
176 }
177
178 const Renderer& RendererAttachment::GetRenderer() const
179 {
180   return *mRenderer;
181 }
182
183 // Called by ProcessRenderTasks after DoPrepareRender
184 bool RendererAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
185 {
186   bool opaque = false;
187
188   if( mParent )
189   {
190     opaque = mParent->GetWorldColor( updateBufferIndex ).a >= FULLY_OPAQUE;
191   }
192
193   if( opaque && mMaterial != NULL )
194   {
195     // Calculated by material in PrepareRender step
196     opaque = ! mMaterial->GetBlendingEnabled( updateBufferIndex );
197   }
198
199   return opaque;
200 }
201
202 void RendererAttachment::SizeChanged( BufferIndex updateBufferIndex )
203 {
204   // Do nothing.
205 }
206
207 bool RendererAttachment::DoPrepareResources(
208   BufferIndex updateBufferIndex,
209   ResourceManager& resourceManager )
210 {
211   DALI_ASSERT_DEBUG( mSceneController );
212
213   CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
214   bool ready = false;
215   mFinishedResourceAcquisition = false;
216
217   // Can only be considered ready when all the scene graph objects are connected to the renderer
218   if( ( mGeometry ) &&
219       ( mGeometry->GetVertexBuffers().Count() > 0 ) &&
220       ( mMaterial ) &&
221       ( mMaterial->GetShader() != NULL ) )
222   {
223     unsigned int completeCount = 0;
224     unsigned int neverCount = 0;
225     unsigned int frameBufferCount = 0;
226
227     Vector<Sampler*>& samplers = mMaterial->GetSamplers();
228     for( Vector<Sampler*>::ConstIterator iter = samplers.Begin();
229          iter != samplers.End(); ++iter )
230     {
231       Sampler* sampler = *iter;
232
233       ResourceId textureId = sampler->GetTextureId( updateBufferIndex );
234       BitmapMetadata metaData = resourceManager.GetBitmapMetadata( textureId );
235
236       sampler->SetFullyOpaque( metaData.IsFullyOpaque() );
237
238       switch( completeStatusManager.GetStatus( textureId ) )
239       {
240         case CompleteStatusManager::NOT_READY:
241         {
242           ready = false;
243           if( metaData.GetIsFramebuffer() )
244           {
245             frameBufferCount++;
246           }
247           FollowTracker( textureId ); // @todo MESH_REWORK Trackers per sampler rather than per actor?
248         }
249         break;
250
251         case CompleteStatusManager::COMPLETE:
252         {
253           completeCount++;
254         }
255         break;
256
257         case CompleteStatusManager::NEVER:
258         {
259           neverCount++;
260         }
261         break;
262       }
263     }
264
265     // We are ready if all samplers are complete, or those that aren't are framebuffers
266     // We are complete if all samplers are either complete or will never complete
267
268     ready = ( completeCount + frameBufferCount >= samplers.Count() ) ;
269     mFinishedResourceAcquisition = ( completeCount + neverCount >= samplers.Count() );
270   }
271
272   return ready;
273 }
274
275
276 // Uniform maps are checked in the following priority order:
277 //   Renderer (this object)
278 //   Actor
279 //   Material
280 //   Samplers
281 //   Shader
282 //   Geometry
283 //   VertexBuffers
284 void RendererAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
285 {
286   // @todo MESH_REWORK - call DoPrepareRender on all scene objects? in caller class?
287   mMaterial->PrepareRender( updateBufferIndex );
288
289   if( mRegenerateUniformMap > 0)
290   {
291     if( mRegenerateUniformMap == REGENERATE_UNIFORM_MAP)
292     {
293       DALI_ASSERT_DEBUG( mGeometry != NULL && "No geometry available in DoPrepareRender()" );
294       DALI_ASSERT_DEBUG( mMaterial != NULL && "No geometry available in DoPrepareRender()" );
295
296       CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
297       localMap.Resize(0);
298
299       const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap();
300       AddMappings( localMap, rendererUniformMap );
301
302       const UniformMap& actorUniformMap = mParent->GetUniformMap();
303       AddMappings( localMap, actorUniformMap );
304
305       AddMappings( localMap, mMaterial->GetUniformMap() );
306       Vector<Sampler*>& samplers = mMaterial->GetSamplers();
307       for( Vector<Sampler*>::ConstIterator iter = samplers.Begin(), end = samplers.End();
308            iter != end ;
309            ++iter )
310       {
311         const SceneGraph::Sampler* sampler = (*iter);
312         AddMappings( localMap, sampler->GetUniformMap() );
313       }
314
315       AddMappings( localMap, mMaterial->GetShader()->GetUniformMap() );
316
317       AddMappings( localMap, mGeometry->GetUniformMap() );
318
319       Vector<PropertyBuffer*>& vertexBuffers = mGeometry->GetVertexBuffers();
320       for( Vector<PropertyBuffer*>::ConstIterator iter = vertexBuffers.Begin(), end = vertexBuffers.End() ;
321            iter != end ;
322            ++iter )
323       {
324         const SceneGraph::PropertyBuffer* vertexBuffer = *iter;
325         AddMappings( localMap, vertexBuffer->GetUniformMap() );
326       }
327
328       PropertyBuffer* indexBuffer = mGeometry->GetIndexBuffer();
329       if( indexBuffer )
330       {
331         AddMappings( localMap, indexBuffer->GetUniformMap() );
332       }
333
334       mUniformMapChanged[updateBufferIndex] = true;
335     }
336     else if( mRegenerateUniformMap == COPY_UNIFORM_MAP )
337     {
338       // Copy old map into current map
339       CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
340       CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-updateBufferIndex ];
341
342       localMap.Resize( oldMap.Count() );
343
344       unsigned int index=0;
345       for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter )
346       {
347         localMap[index] = *iter;
348       }
349
350       mUniformMapChanged[updateBufferIndex] = true;
351     }
352
353     mRegenerateUniformMap--;
354   }
355
356   if( mResendDataProviders )
357   {
358     RenderDataProvider* dataProvider = NewRenderDataProvider();
359
360     // Tell renderer about a new provider
361     // @todo MESH_REWORK Should we instead create a new renderer when these change?
362
363     typedef MessageValue1< NewRenderer, OwnerPointer<RenderDataProvider> > DerivedType;
364     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
365     new (slot) DerivedType( mRenderer, &NewRenderer::SetRenderDataProvider, dataProvider );
366     mResendDataProviders = false;
367   }
368 }
369
370
371 void RendererAttachment::ConnectionsChanged( PropertyOwner& object )
372 {
373   // One of our child objects has changed it's connections. Ensure the uniform
374   // map gets regenerated during PrepareRender
375   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
376
377   // Ensure the child object pointers get re-sent to the renderer
378   mResendDataProviders = true;
379 }
380
381 void RendererAttachment::ConnectedUniformMapChanged()
382 {
383   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
384 }
385
386 void RendererAttachment::UniformMappingsChanged( const UniformMap& mappings )
387 {
388   // The mappings are either from PropertyOwner base class, or the Actor
389   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
390 }
391
392 bool RendererAttachment::GetUniformMapChanged( BufferIndex bufferIndex ) const
393 {
394   return mUniformMapChanged[bufferIndex];
395 }
396
397 const CollectedUniformMap& RendererAttachment::GetUniformMap( BufferIndex bufferIndex ) const
398 {
399   return mCollectedUniformMap[ bufferIndex ];
400 }
401
402 void RendererAttachment::AddMappings( CollectedUniformMap& localMap, const UniformMap& uniformMap )
403 {
404   // Iterate thru uniformMap.
405   //   Any maps that aren't in localMap should be added in a single step
406   CollectedUniformMap newUniformMappings;
407
408   for( unsigned int i=0, count=uniformMap.Count(); i<count; ++i )
409   {
410     UniformPropertyMapping::Hash nameHash = uniformMap[i].uniformNameHash;
411     bool found = false;
412
413     for( CollectedUniformMap::Iterator iter = localMap.Begin() ; iter != localMap.End() ; ++iter )
414     {
415       const UniformPropertyMapping* map = (*iter);
416       if( map->uniformNameHash == nameHash )
417       {
418         if( map->uniformName == uniformMap[i].uniformName )
419         {
420           found = true;
421           break;
422         }
423       }
424     }
425     if( !found )
426     {
427       // it's a new mapping. Add raw ptr to temporary list
428       newUniformMappings.PushBack( &uniformMap[i] );
429     }
430   }
431
432   if( newUniformMappings.Count() > 0 )
433   {
434     localMap.Reserve( localMap.Count() + newUniformMappings.Count() );
435
436     for( CollectedUniformMap::Iterator iter = newUniformMappings.Begin(),
437            end = newUniformMappings.End() ;
438          iter != end ;
439          ++iter )
440     {
441       const UniformPropertyMapping* map = (*iter);
442       localMap.PushBack( map );
443     }
444     //@todo MESH_REWORK Use memcpy to copy ptrs from one array to the other
445   }
446 }
447
448 RenderDataProvider* RendererAttachment::NewRenderDataProvider()
449 {
450   RenderDataProvider* dataProvider = new RenderDataProvider();
451
452   dataProvider->mGeometryDataProvider = mGeometry;
453   dataProvider->mMaterialDataProvider = mMaterial;
454   dataProvider->mUniformMapDataProvider = this;
455   dataProvider->mShader = mMaterial->GetShader();
456   dataProvider->mIndexBuffer = mGeometry->GetIndexBuffer();
457
458   Vector<PropertyBuffer*>& vertexBuffers = mGeometry->GetVertexBuffers();
459   dataProvider->mVertexBuffers.Reserve( vertexBuffers.Count() );
460
461   for( Vector<PropertyBuffer*>::Iterator iter = vertexBuffers.Begin() ;
462        iter != vertexBuffers.End();
463        ++iter )
464   {
465     dataProvider->mVertexBuffers.PushBack(*iter); // Convert from derived type to base type
466   }
467
468   Vector<Sampler*>& samplers = mMaterial->GetSamplers();
469   dataProvider->mSamplers.Reserve( samplers.Count() );
470   for( Vector<Sampler*>::Iterator iter = samplers.Begin() ;
471        iter != samplers.End();
472        ++iter )
473   {
474     dataProvider->mSamplers.PushBack(*iter); // Convert from derived type to base type
475   }
476   return dataProvider;
477 }
478
479
480 } // namespace SceneGraph
481 } // namespace Internal
482 } // namespace Dali