2 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "scene-graph-renderer-attachment.h"
18 #include <dali/internal/update/common/uniform-map.h>
19 #include <dali/internal/update/manager/prepare-render-instructions.h>
20 #include <dali/internal/update/rendering/scene-graph-geometry.h>
21 #include <dali/internal/update/rendering/scene-graph-material.h>
22 #include <dali/internal/update/rendering/scene-graph-sampler.h>
23 #include <dali/internal/update/resources/complete-status-manager.h>
24 #include <dali/internal/update/resources/resource-manager.h>
25 #include <dali/internal/render/data-providers/render-data-provider.h>
26 #include <dali/internal/render/queue/render-queue.h>
27 #include <dali/internal/render/renderers/render-renderer.h>
28 #include <dali/internal/render/shaders/scene-graph-shader.h>
30 #if defined(DEBUG_ENABLED)
31 Debug::Filter* gImageAttachmentLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_SCENE_GRAPH_IMAGE_ATTACHMENT");
33 #define ATTACHMENT_LOG(level) \
34 DALI_LOG_INFO(gImageAttachmentLogFilter, level, "SceneGraph::ImageAttachment::%s: this:%p\n", __FUNCTION__, this)
35 #define ATTACHMENT_LOG_FMT(level, format, args...) \
36 DALI_LOG_INFO(gImageAttachmentLogFilter, level, "SceneGraph::ImageAttachment::%s: this:%p " format, __FUNCTION__, this, ## args)
40 #define ATTACHMENT_LOG(level)
41 #define ATTACHMENT_LOG_FMT(level, format, args...)
46 namespace // unnamed namespace
48 const int REGENERATE_UNIFORM_MAP = 2;
49 const int COPY_UNIFORM_MAP = 1;
59 RendererAttachment* RendererAttachment::New()
61 return new RendererAttachment();
65 RendererAttachment::RendererAttachment()
66 : RenderableAttachment( false ),
70 mRegenerateUniformMap(REGENERATE_UNIFORM_MAP),
71 mResendDataProviders(false),
72 mResendGeometry(false),
75 mUniformMapChanged[0]=false;
76 mUniformMapChanged[1]=false;
78 // Observe our own PropertyOwner's uniform map
79 AddUniformMapObserver( *this );
83 RendererAttachment::~RendererAttachment()
87 mMaterial->RemoveConnectionObserver(*this);
92 mGeometry->RemoveConnectionObserver(*this);
97 void RendererAttachment::Initialize2( BufferIndex updateBufferIndex )
99 DALI_ASSERT_DEBUG( mSceneController );
102 void RendererAttachment::OnDestroy2()
106 void RendererAttachment::ConnectedToSceneGraph()
108 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
109 mParent->AddUniformMapObserver( *this ); // Watch actor's uniform maps
111 DALI_ASSERT_DEBUG( mParent != NULL );
113 RenderDataProvider* dataProvider = NewRenderDataProvider();
115 RenderGeometry* renderGeometry = mGeometry->GetRenderGeometry(mSceneController);
116 mRenderer = NewRenderer::New( *mParent, dataProvider, renderGeometry );
117 mSceneController->GetRenderMessageDispatcher().AddRenderer( *mRenderer );
120 void RendererAttachment::DisconnectedFromSceneGraph()
122 mRegenerateUniformMap = 0;
123 mParent->RemoveUniformMapObserver( *this );
125 mGeometry->OnRendererDisconnect();
127 DALI_ASSERT_DEBUG( mSceneController );
128 mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
132 void RendererAttachment::SetMaterial( BufferIndex updateBufferIndex, Material* material)
134 DALI_ASSERT_DEBUG( material != NULL && "Material pointer is NULL" );
136 mMaterial = material;
137 mMaterial->AddConnectionObserver( *this );
138 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
140 mResendDataProviders = true;
143 Material& RendererAttachment::GetMaterial()
148 void RendererAttachment::SetGeometry( BufferIndex updateBufferIndex, Geometry* geometry)
150 DALI_ASSERT_DEBUG( geometry != NULL && "Geometry pointer is NULL");
153 mGeometry->RemoveConnectionObserver(*this);
154 mGeometry->OnRendererDisconnect();
157 mGeometry = geometry;
158 mGeometry->AddConnectionObserver( *this ); // Observe geometry connections / uniform mapping changes
159 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
163 mResendGeometry = true;
167 Geometry& RendererAttachment::GetGeometry()
172 void RendererAttachment::SetSortAttributes( BufferIndex bufferIndex, RendererWithSortAttributes& sortAttributes )
174 sortAttributes.shader = mMaterial->GetShader();
175 sortAttributes.material = mMaterial;
176 sortAttributes.geometry = mGeometry;
179 void RendererAttachment::SetDepthIndex( int depthIndex )
181 mDepthIndex = depthIndex;
185 // only do this if we are on-stage. Ensures the render lists are re-sorted
186 mParent->SetDirtyFlag( SortModifierFlag );
190 Renderer& RendererAttachment::GetRenderer()
195 const Renderer& RendererAttachment::GetRenderer() const
200 // Called by ProcessRenderTasks after DoPrepareRender
201 bool RendererAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
205 if( mMaterial != NULL )
207 Material::BlendPolicy blendPolicy = mMaterial->GetBlendPolicy();
208 switch( blendPolicy )
210 case Material::OPAQUE:
215 case Material::TRANSPARENT:
220 case Material::USE_ACTOR_COLOR:
224 opaque = mParent->GetWorldColor( updateBufferIndex ).a >= FULLY_OPAQUE;
234 void RendererAttachment::SizeChanged( BufferIndex updateBufferIndex )
239 bool RendererAttachment::DoPrepareResources(
240 BufferIndex updateBufferIndex,
241 ResourceManager& resourceManager )
243 DALI_ASSERT_DEBUG( mSceneController );
245 CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
247 mFinishedResourceAcquisition = false;
249 // Can only be considered ready when all the scene graph objects are connected to the renderer
251 ( mGeometry->GetVertexBuffers().Count() > 0 ) &&
253 ( mMaterial->GetShader() != NULL ) )
255 unsigned int completeCount = 0;
256 unsigned int neverCount = 0;
257 unsigned int frameBufferCount = 0;
259 Vector<Sampler*>& samplers = mMaterial->GetSamplers();
260 for( Vector<Sampler*>::ConstIterator iter = samplers.Begin();
261 iter != samplers.End(); ++iter )
263 Sampler* sampler = *iter;
265 ResourceId textureId = sampler->GetTextureId( updateBufferIndex );
266 BitmapMetadata metaData = resourceManager.GetBitmapMetadata( textureId );
268 sampler->SetFullyOpaque( metaData.IsFullyOpaque() );
270 switch( completeStatusManager.GetStatus( textureId ) )
272 case CompleteStatusManager::NOT_READY:
274 if( metaData.GetIsFramebuffer() )
278 FollowTracker( textureId ); // @todo MESH_REWORK Trackers per sampler rather than per actor?
282 case CompleteStatusManager::COMPLETE:
288 case CompleteStatusManager::NEVER:
296 // We are ready if all samplers are complete, or those that aren't are framebuffers
297 // We are complete if all samplers are either complete or will never complete
299 ready = ( completeCount + frameBufferCount >= samplers.Count() ) ;
300 mFinishedResourceAcquisition = ( completeCount + neverCount >= samplers.Count() );
307 // Uniform maps are checked in the following priority order:
308 // Renderer (this object)
315 void RendererAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
317 // @todo MESH_REWORK - call DoPrepareRender on all scene objects? in caller class?
318 mMaterial->PrepareRender( updateBufferIndex );
320 if( mRegenerateUniformMap > 0)
322 if( mRegenerateUniformMap == REGENERATE_UNIFORM_MAP)
324 DALI_ASSERT_DEBUG( mGeometry != NULL && "No geometry available in DoPrepareRender()" );
325 DALI_ASSERT_DEBUG( mMaterial != NULL && "No geometry available in DoPrepareRender()" );
327 CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
330 const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap();
331 AddMappings( localMap, rendererUniformMap );
333 const UniformMap& actorUniformMap = mParent->GetUniformMap();
334 AddMappings( localMap, actorUniformMap );
336 AddMappings( localMap, mMaterial->GetUniformMap() );
337 Vector<Sampler*>& samplers = mMaterial->GetSamplers();
338 for( Vector<Sampler*>::ConstIterator iter = samplers.Begin(), end = samplers.End();
342 const SceneGraph::Sampler* sampler = (*iter);
343 AddMappings( localMap, sampler->GetUniformMap() );
346 AddMappings( localMap, mMaterial->GetShader()->GetUniformMap() );
348 AddMappings( localMap, mGeometry->GetUniformMap() );
350 Vector<PropertyBuffer*>& vertexBuffers = mGeometry->GetVertexBuffers();
351 for( Vector<PropertyBuffer*>::ConstIterator iter = vertexBuffers.Begin(), end = vertexBuffers.End() ;
355 const SceneGraph::PropertyBuffer* vertexBuffer = *iter;
356 AddMappings( localMap, vertexBuffer->GetUniformMap() );
359 PropertyBuffer* indexBuffer = mGeometry->GetIndexBuffer();
362 AddMappings( localMap, indexBuffer->GetUniformMap() );
365 mUniformMapChanged[updateBufferIndex] = true;
367 else if( mRegenerateUniformMap == COPY_UNIFORM_MAP )
369 // Copy old map into current map
370 CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
371 CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-updateBufferIndex ];
373 localMap.Resize( oldMap.Count() );
375 unsigned int index=0;
376 for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter, ++index )
378 localMap[index] = *iter;
381 mUniformMapChanged[updateBufferIndex] = true;
384 mRegenerateUniformMap--;
387 if( mResendDataProviders )
389 RenderDataProvider* dataProvider = NewRenderDataProvider();
391 // Tell renderer about a new provider
392 // @todo MESH_REWORK Should we instead create a new renderer when these change?
394 typedef MessageValue1< NewRenderer, OwnerPointer<RenderDataProvider> > DerivedType;
395 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
396 new (slot) DerivedType( mRenderer, &NewRenderer::SetRenderDataProvider, dataProvider );
397 mResendDataProviders = false;
400 if( mResendGeometry )
402 // The first call to GetRenderGeometry() creates the geometry and sends it in a message
403 RenderGeometry* geometry = mGeometry->GetRenderGeometry( mSceneController );
405 typedef MessageValue1< NewRenderer, RenderGeometry* > DerivedType;
406 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
408 new (slot) DerivedType( mRenderer, &NewRenderer::SetGeometry, geometry );
409 mResendGeometry = false;
413 void RendererAttachment::ConnectionsChanged( PropertyOwner& object )
415 // One of our child objects has changed it's connections. Ensure the uniform
416 // map gets regenerated during PrepareRender
417 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
419 // Ensure the child object pointers get re-sent to the renderer
420 mResendDataProviders = true;
423 void RendererAttachment::ConnectedUniformMapChanged()
425 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
428 void RendererAttachment::UniformMappingsChanged( const UniformMap& mappings )
430 // The mappings are either from PropertyOwner base class, or the Actor
431 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
434 bool RendererAttachment::GetUniformMapChanged( BufferIndex bufferIndex ) const
436 return mUniformMapChanged[bufferIndex];
439 const CollectedUniformMap& RendererAttachment::GetUniformMap( BufferIndex bufferIndex ) const
441 return mCollectedUniformMap[ bufferIndex ];
444 void RendererAttachment::AddMappings( CollectedUniformMap& localMap, const UniformMap& uniformMap )
446 // Iterate thru uniformMap.
447 // Any maps that aren't in localMap should be added in a single step
448 CollectedUniformMap newUniformMappings;
450 for( unsigned int i=0, count=uniformMap.Count(); i<count; ++i )
452 UniformPropertyMapping::Hash nameHash = uniformMap[i].uniformNameHash;
455 for( CollectedUniformMap::Iterator iter = localMap.Begin() ; iter != localMap.End() ; ++iter )
457 const UniformPropertyMapping* map = (*iter);
458 if( map->uniformNameHash == nameHash )
460 if( map->uniformName == uniformMap[i].uniformName )
469 // it's a new mapping. Add raw ptr to temporary list
470 newUniformMappings.PushBack( &uniformMap[i] );
474 if( newUniformMappings.Count() > 0 )
476 localMap.Reserve( localMap.Count() + newUniformMappings.Count() );
478 for( CollectedUniformMap::Iterator iter = newUniformMappings.Begin(),
479 end = newUniformMappings.End() ;
483 const UniformPropertyMapping* map = (*iter);
484 localMap.PushBack( map );
486 //@todo MESH_REWORK Use memcpy to copy ptrs from one array to the other
490 RenderDataProvider* RendererAttachment::NewRenderDataProvider()
492 RenderDataProvider* dataProvider = new RenderDataProvider();
494 dataProvider->mMaterialDataProvider = mMaterial;
495 dataProvider->mUniformMapDataProvider = this;
496 dataProvider->mShader = mMaterial->GetShader();
498 Vector<Sampler*>& samplers = mMaterial->GetSamplers();
499 dataProvider->mSamplers.Reserve( samplers.Count() );
500 for( Vector<Sampler*>::Iterator iter = samplers.Begin() ;
501 iter != samplers.End();
504 dataProvider->mSamplers.PushBack(*iter); // Convert from derived type to base type
510 } // namespace SceneGraph
511 } // namespace Internal