Added connection for sampler texture
[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 = new RenderDataProvider( *mGeometry,
107                                                              *mMaterial,
108                                                              *this,
109                                                              *mMaterial->GetShader(),
110                                                              mGeometry->GetIndexBuffer(),
111                                                              mGeometry->GetVertexBuffers(),
112                                                              mMaterial->GetSamplers() );
113
114   mRenderer = NewRenderer::New( *mParent, dataProvider );
115   mSceneController->GetRenderMessageDispatcher().AddRenderer( *mRenderer );
116 }
117
118 void RendererAttachment::DisconnectedFromSceneGraph()
119 {
120   mRegenerateUniformMap = 0;
121   mParent->RemoveUniformMapObserver( *this );
122
123   DALI_ASSERT_DEBUG( mSceneController );
124   mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
125   mRenderer = NULL;
126 }
127
128 void RendererAttachment::SetMaterial( BufferIndex updateBufferIndex, const Material* material)
129 {
130   DALI_ASSERT_DEBUG( material != NULL && "Material pointer is NULL" );
131
132   mMaterial = const_cast<Material*>(material); // Need this to be non-const to add observer only.
133   mMaterial->AddConnectionObserver( *this );
134   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
135
136   mResendDataProviders = true;
137 }
138
139 const Material& RendererAttachment::GetMaterial() const
140 {
141   return *mMaterial;
142 }
143
144 void RendererAttachment::SetGeometry( BufferIndex updateBufferIndex, const Geometry* geometry)
145 {
146   DALI_ASSERT_DEBUG( geometry != NULL && "Geometry pointer is NULL");
147
148   mGeometry = const_cast<Geometry*>(geometry); // Need this to be non-const to add observer only
149   mGeometry->AddConnectionObserver( *this ); // Observe geometry connections / uniform mapping changes
150   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
151
152   mResendDataProviders = true;
153 }
154
155 const Geometry& RendererAttachment::GetGeometry() const
156 {
157   return *mGeometry;
158 }
159
160 int RendererAttachment::GetDepthIndex(BufferIndex bufferIndex) const
161 {
162   return mDepthIndex[bufferIndex];
163 }
164
165 Renderer& RendererAttachment::GetRenderer()
166 {
167   return *mRenderer;
168 }
169
170 const Renderer& RendererAttachment::GetRenderer() const
171 {
172   return *mRenderer;
173 }
174
175 // Uniform maps are checked in the following priority order:
176 //   Renderer (this object)
177 //   Actor
178 //   Material
179 //   Samplers
180 //   Shader
181 //   Geometry
182 //   VertexBuffers
183 void RendererAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
184 {
185   if( mRegenerateUniformMap > 0)
186   {
187     if( mRegenerateUniformMap == REGENERATE_UNIFORM_MAP)
188     {
189       DALI_ASSERT_DEBUG( mGeometry != NULL && "No geometry available in DoPrepareRender()" );
190       DALI_ASSERT_DEBUG( mMaterial != NULL && "No geometry available in DoPrepareRender()" );
191
192       CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
193       localMap.Resize(0);
194
195       const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap();
196       AddMappings( localMap, rendererUniformMap );
197
198       const UniformMap& actorUniformMap = mParent->GetUniformMap();
199       AddMappings( localMap, actorUniformMap );
200
201       AddMappings( localMap, mMaterial->GetUniformMap() );
202       const RenderDataProvider::Samplers& samplers = mMaterial->GetSamplers();
203       for( RenderDataProvider::Samplers::ConstIterator iter = samplers.Begin(), end = samplers.End();
204            iter != end ;
205            ++iter )
206       {
207         const SceneGraph::Sampler* sampler = static_cast<const SceneGraph::Sampler*>( *iter );
208         AddMappings( localMap, sampler->GetUniformMap() );
209       }
210
211       AddMappings( localMap, mMaterial->GetShader()->GetUniformMap() );
212
213       AddMappings( localMap, mGeometry->GetUniformMap() );
214
215       const GeometryDataProvider::VertexBuffers& vertexBuffers = mGeometry->GetVertexBuffers();
216       for( GeometryDataProvider::VertexBuffers::ConstIterator iter = vertexBuffers.Begin(), end = vertexBuffers.End() ;
217            iter != end ;
218            ++iter )
219       {
220         AddMappings( localMap, (*iter)->GetUniformMap() );
221       }
222
223       mUniformMapChanged[updateBufferIndex] = true;
224     }
225     else if( mRegenerateUniformMap == COPY_UNIFORM_MAP )
226     {
227       // Copy old map into current map
228       CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
229       CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-updateBufferIndex ];
230
231       localMap.Resize( oldMap.Count() );
232
233       unsigned int index=0;
234       for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter )
235       {
236         localMap[index] = *iter;
237       }
238
239       mUniformMapChanged[updateBufferIndex] = true;
240     }
241
242     mRegenerateUniformMap--;
243   }
244
245   if( mResendDataProviders )
246   {
247     RenderDataProvider* dataProvider = new RenderDataProvider( *mGeometry,
248                                                                *mMaterial,
249                                                                *this,
250                                                                *mMaterial->GetShader(),
251                                                                mGeometry->GetIndexBuffer(),
252                                                                mGeometry->GetVertexBuffers(),
253                                                                mMaterial->GetSamplers() );
254
255     // Tell renderer about a new provider
256     // @todo MESH_REWORK Should we instead create a new renderer when these change?
257
258     typedef MessageValue1< NewRenderer, OwnerPointer<RenderDataProvider> > DerivedType;
259     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
260     new (slot) DerivedType( mRenderer, &NewRenderer::SetRenderDataProvider, dataProvider );
261
262     mResendDataProviders = false;
263   }
264 }
265
266 bool RendererAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
267 {
268   bool opaque = false;
269
270   if( mParent )
271   {
272     opaque = mParent->GetWorldColor( updateBufferIndex ).a >= FULLY_OPAQUE;
273   }
274
275   if( mMaterial != NULL )
276   {
277     // Require that all affecting samplers are opaque
278     unsigned int opaqueCount=0;
279     unsigned int affectingCount=0;
280
281     const RenderDataProvider::Samplers& samplers = mMaterial->GetSamplers();
282     for( RenderDataProvider::Samplers::ConstIterator iter = samplers.Begin();
283          iter != samplers.End(); ++iter )
284     {
285       const Sampler* sampler = static_cast<const Sampler*>(*iter);
286       if( sampler != NULL )
287       {
288         if( sampler->AffectsTransparency( updateBufferIndex ) )
289         {
290           affectingCount++;
291           if( sampler->IsFullyOpaque( updateBufferIndex ) )
292           {
293             opaqueCount++;
294           }
295         }
296       }
297     }
298     opaque = (opaqueCount == affectingCount);
299   }
300
301   return opaque;
302 }
303
304 void RendererAttachment::SizeChanged( BufferIndex updateBufferIndex )
305 {
306   // Do nothing.
307 }
308
309 bool RendererAttachment::DoPrepareResources(
310   BufferIndex updateBufferIndex,
311   ResourceManager& resourceManager )
312 {
313   DALI_ASSERT_DEBUG( mSceneController );
314
315   CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
316
317   bool ready = false;
318   mFinishedResourceAcquisition = false;
319
320   // Can only be considered ready when all the scene graph objects are connected to the renderer
321   if( ( mGeometry ) &&
322       ( mGeometry->GetVertexBuffers().Count() > 0 ) &&
323       ( mMaterial ) &&
324       ( mMaterial->GetShader() != NULL ) )
325   {
326     unsigned int completeCount = 0;
327     unsigned int neverCount = 0;
328     unsigned int frameBufferCount = 0;
329
330     const RenderDataProvider::Samplers& samplers = mMaterial->GetSamplers();
331     for( RenderDataProvider::Samplers::ConstIterator iter = samplers.Begin();
332          iter != samplers.End(); ++iter )
333     {
334       const Sampler* sampler = static_cast<const Sampler*>(*iter);
335
336       ResourceId textureId = sampler->GetTextureId( updateBufferIndex );
337       BitmapMetadata metaData = resourceManager.GetBitmapMetadata( textureId );
338
339       Sampler* mutableSampler = const_cast<Sampler*>(sampler);
340       mutableSampler->SetFullyOpaque( metaData.IsFullyOpaque() );
341
342       switch( completeStatusManager.GetStatus( textureId ) )
343       {
344         case CompleteStatusManager::NOT_READY:
345         {
346           ready = false;
347           if( metaData.GetIsFramebuffer() )
348           {
349             frameBufferCount++;
350           }
351           FollowTracker( textureId ); // @todo MESH_REWORK Trackers per sampler rather than per actor?
352         }
353         break;
354
355         case CompleteStatusManager::COMPLETE:
356         {
357           completeCount++;
358         }
359         break;
360
361         case CompleteStatusManager::NEVER:
362         {
363           neverCount++;
364         }
365         break;
366       }
367     }
368
369     // We are ready if all samplers are complete, or those that aren't are framebuffers
370     // We are complete if all samplers are either complete or will never complete
371
372     ready = ( completeCount + frameBufferCount >= samplers.Count() ) ;
373     mFinishedResourceAcquisition = ( completeCount + neverCount >= samplers.Count() );
374   }
375
376   return ready;
377 }
378
379 void RendererAttachment::ConnectionsChanged( PropertyOwner& object )
380 {
381   // One of our child objects has changed it's connections. Ensure the uniform
382   // map gets regenerated during PrepareRender
383   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
384
385   // Ensure the child object pointers get re-sent to the renderer
386   mResendDataProviders = true;
387 }
388
389 void RendererAttachment::ConnectedUniformMapChanged()
390 {
391   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
392 }
393
394 void RendererAttachment::UniformMappingsChanged( const UniformMap& mappings )
395 {
396   // The mappings are either from PropertyOwner base class, or the Actor
397   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
398 }
399
400 bool RendererAttachment::GetUniformMapChanged( BufferIndex bufferIndex ) const
401 {
402   return mUniformMapChanged[bufferIndex];
403 }
404
405 const CollectedUniformMap& RendererAttachment::GetUniformMap( BufferIndex bufferIndex ) const
406 {
407   return mCollectedUniformMap[ bufferIndex ];
408 }
409
410 void RendererAttachment::AddMappings( CollectedUniformMap& localMap, const UniformMap& uniformMap )
411 {
412   // Iterate thru uniformMap.
413   //   Any maps that aren't in localMap should be added in a single step
414   CollectedUniformMap newUniformMappings;
415
416   for( unsigned int i=0, count=uniformMap.Count(); i<count; ++i )
417   {
418     UniformPropertyMapping::Hash nameHash = uniformMap[i].uniformNameHash;
419     bool found = false;
420
421     for( CollectedUniformMap::Iterator iter = localMap.Begin() ; iter != localMap.End() ; ++iter )
422     {
423       const UniformPropertyMapping* map = (*iter);
424       if( map->uniformNameHash == nameHash )
425       {
426         if( map->uniformName == uniformMap[i].uniformName )
427         {
428           found = true;
429           break;
430         }
431       }
432     }
433     if( !found )
434     {
435       // it's a new mapping. Add raw ptr to temporary list
436       newUniformMappings.PushBack( &uniformMap[i] );
437     }
438   }
439
440   if( newUniformMappings.Count() > 0 )
441   {
442     localMap.Reserve( localMap.Count() + newUniformMappings.Count() );
443
444     for( CollectedUniformMap::Iterator iter = newUniformMappings.Begin(),
445            end = newUniformMappings.End() ;
446          iter != end ;
447          ++iter )
448     {
449       const UniformPropertyMapping* map = (*iter);
450       localMap.PushBack( map );
451     }
452     //@todo MESH_REWORK Use memcpy to copy ptrs from one array to the other
453   }
454 }
455
456
457
458 } // namespace SceneGraph
459 } // namespace Internal
460 } // namespace Dali