Added sampler properties, test cases.
[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         const SceneGraph::PropertyBuffer* vertexBuffer = static_cast<const SceneGraph::PropertyBuffer*>( *iter );
221         AddMappings( localMap, vertexBuffer->GetUniformMap() );
222       }
223
224       mUniformMapChanged[updateBufferIndex] = true;
225     }
226     else if( mRegenerateUniformMap == COPY_UNIFORM_MAP )
227     {
228       // Copy old map into current map
229       CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
230       CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-updateBufferIndex ];
231
232       localMap.Resize( oldMap.Count() );
233
234       unsigned int index=0;
235       for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter )
236       {
237         localMap[index] = *iter;
238       }
239
240       mUniformMapChanged[updateBufferIndex] = true;
241     }
242
243     mRegenerateUniformMap--;
244   }
245
246   if( mResendDataProviders )
247   {
248     RenderDataProvider* dataProvider = new RenderDataProvider( *mGeometry,
249                                                                *mMaterial,
250                                                                *this,
251                                                                *mMaterial->GetShader(),
252                                                                mGeometry->GetIndexBuffer(),
253                                                                mGeometry->GetVertexBuffers(),
254                                                                mMaterial->GetSamplers() );
255
256     // Tell renderer about a new provider
257     // @todo MESH_REWORK Should we instead create a new renderer when these change?
258
259     typedef MessageValue1< NewRenderer, OwnerPointer<RenderDataProvider> > DerivedType;
260     unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
261     new (slot) DerivedType( mRenderer, &NewRenderer::SetRenderDataProvider, dataProvider );
262
263     mResendDataProviders = false;
264   }
265 }
266
267 bool RendererAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
268 {
269   bool opaque = false;
270
271   if( mParent )
272   {
273     opaque = mParent->GetWorldColor( updateBufferIndex ).a >= FULLY_OPAQUE;
274   }
275
276   if( mMaterial != NULL )
277   {
278     // Require that all affecting samplers are opaque
279     unsigned int opaqueCount=0;
280     unsigned int affectingCount=0;
281
282     const RenderDataProvider::Samplers& samplers = mMaterial->GetSamplers();
283     for( RenderDataProvider::Samplers::ConstIterator iter = samplers.Begin();
284          iter != samplers.End(); ++iter )
285     {
286       const Sampler* sampler = static_cast<const Sampler*>(*iter);
287       if( sampler != NULL )
288       {
289         if( sampler->AffectsTransparency( updateBufferIndex ) )
290         {
291           affectingCount++;
292           if( sampler->IsFullyOpaque( updateBufferIndex ) )
293           {
294             opaqueCount++;
295           }
296         }
297       }
298     }
299     opaque = (opaqueCount == affectingCount);
300   }
301
302   return opaque;
303 }
304
305 void RendererAttachment::SizeChanged( BufferIndex updateBufferIndex )
306 {
307   // Do nothing.
308 }
309
310 bool RendererAttachment::DoPrepareResources(
311   BufferIndex updateBufferIndex,
312   ResourceManager& resourceManager )
313 {
314   DALI_ASSERT_DEBUG( mSceneController );
315
316   CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
317
318   bool ready = false;
319   mFinishedResourceAcquisition = false;
320
321   // Can only be considered ready when all the scene graph objects are connected to the renderer
322   if( ( mGeometry ) &&
323       ( mGeometry->GetVertexBuffers().Count() > 0 ) &&
324       ( mMaterial ) &&
325       ( mMaterial->GetShader() != NULL ) )
326   {
327     unsigned int completeCount = 0;
328     unsigned int neverCount = 0;
329     unsigned int frameBufferCount = 0;
330
331     const RenderDataProvider::Samplers& samplers = mMaterial->GetSamplers();
332     for( RenderDataProvider::Samplers::ConstIterator iter = samplers.Begin();
333          iter != samplers.End(); ++iter )
334     {
335       const Sampler* sampler = static_cast<const Sampler*>(*iter);
336
337       ResourceId textureId = sampler->GetTextureId( updateBufferIndex );
338       BitmapMetadata metaData = resourceManager.GetBitmapMetadata( textureId );
339
340       Sampler* mutableSampler = const_cast<Sampler*>(sampler);
341       mutableSampler->SetFullyOpaque( metaData.IsFullyOpaque() );
342
343       switch( completeStatusManager.GetStatus( textureId ) )
344       {
345         case CompleteStatusManager::NOT_READY:
346         {
347           ready = false;
348           if( metaData.GetIsFramebuffer() )
349           {
350             frameBufferCount++;
351           }
352           FollowTracker( textureId ); // @todo MESH_REWORK Trackers per sampler rather than per actor?
353         }
354         break;
355
356         case CompleteStatusManager::COMPLETE:
357         {
358           completeCount++;
359         }
360         break;
361
362         case CompleteStatusManager::NEVER:
363         {
364           neverCount++;
365         }
366         break;
367       }
368     }
369
370     // We are ready if all samplers are complete, or those that aren't are framebuffers
371     // We are complete if all samplers are either complete or will never complete
372
373     ready = ( completeCount + frameBufferCount >= samplers.Count() ) ;
374     mFinishedResourceAcquisition = ( completeCount + neverCount >= samplers.Count() );
375   }
376
377   return ready;
378 }
379
380 void RendererAttachment::ConnectionsChanged( PropertyOwner& object )
381 {
382   // One of our child objects has changed it's connections. Ensure the uniform
383   // map gets regenerated during PrepareRender
384   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
385
386   // Ensure the child object pointers get re-sent to the renderer
387   mResendDataProviders = true;
388 }
389
390 void RendererAttachment::ConnectedUniformMapChanged()
391 {
392   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
393 }
394
395 void RendererAttachment::UniformMappingsChanged( const UniformMap& mappings )
396 {
397   // The mappings are either from PropertyOwner base class, or the Actor
398   mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
399 }
400
401 bool RendererAttachment::GetUniformMapChanged( BufferIndex bufferIndex ) const
402 {
403   return mUniformMapChanged[bufferIndex];
404 }
405
406 const CollectedUniformMap& RendererAttachment::GetUniformMap( BufferIndex bufferIndex ) const
407 {
408   return mCollectedUniformMap[ bufferIndex ];
409 }
410
411 void RendererAttachment::AddMappings( CollectedUniformMap& localMap, const UniformMap& uniformMap )
412 {
413   // Iterate thru uniformMap.
414   //   Any maps that aren't in localMap should be added in a single step
415   CollectedUniformMap newUniformMappings;
416
417   for( unsigned int i=0, count=uniformMap.Count(); i<count; ++i )
418   {
419     UniformPropertyMapping::Hash nameHash = uniformMap[i].uniformNameHash;
420     bool found = false;
421
422     for( CollectedUniformMap::Iterator iter = localMap.Begin() ; iter != localMap.End() ; ++iter )
423     {
424       const UniformPropertyMapping* map = (*iter);
425       if( map->uniformNameHash == nameHash )
426       {
427         if( map->uniformName == uniformMap[i].uniformName )
428         {
429           found = true;
430           break;
431         }
432       }
433     }
434     if( !found )
435     {
436       // it's a new mapping. Add raw ptr to temporary list
437       newUniformMappings.PushBack( &uniformMap[i] );
438     }
439   }
440
441   if( newUniformMappings.Count() > 0 )
442   {
443     localMap.Reserve( localMap.Count() + newUniformMappings.Count() );
444
445     for( CollectedUniformMap::Iterator iter = newUniformMappings.Begin(),
446            end = newUniformMappings.End() ;
447          iter != end ;
448          ++iter )
449     {
450       const UniformPropertyMapping* map = (*iter);
451       localMap.PushBack( map );
452     }
453     //@todo MESH_REWORK Use memcpy to copy ptrs from one array to the other
454   }
455 }
456
457
458
459 } // namespace SceneGraph
460 } // namespace Internal
461 } // namespace Dali