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),
76 mUniformMapChanged[0]=false;
77 mUniformMapChanged[1]=false;
79 // Observe our own PropertyOwner's uniform map
80 AddUniformMapObserver( *this );
84 RendererAttachment::~RendererAttachment()
88 mMaterial->RemoveConnectionObserver(*this);
93 mGeometry->RemoveConnectionObserver(*this);
98 void RendererAttachment::Initialize2( BufferIndex updateBufferIndex )
100 DALI_ASSERT_DEBUG( mSceneController );
103 void RendererAttachment::OnDestroy2()
107 void RendererAttachment::ConnectedToSceneGraph()
109 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
110 mParent->AddUniformMapObserver( *this ); // Watch actor's uniform maps
112 DALI_ASSERT_DEBUG( mParent != NULL );
114 RenderDataProvider* dataProvider = NewRenderDataProvider();
116 RenderGeometry* renderGeometry = mGeometry->GetRenderGeometry(mSceneController);
117 mRenderer = NewRenderer::New( *mParent, dataProvider, renderGeometry );
118 mSceneController->GetRenderMessageDispatcher().AddRenderer( *mRenderer );
121 void RendererAttachment::DisconnectedFromSceneGraph()
123 mRegenerateUniformMap = 0;
124 mParent->RemoveUniformMapObserver( *this );
126 mGeometry->OnRendererDisconnect();
128 DALI_ASSERT_DEBUG( mSceneController );
129 mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
133 void RendererAttachment::SetMaterial( BufferIndex updateBufferIndex, Material* material)
135 DALI_ASSERT_DEBUG( material != NULL && "Material pointer is NULL" );
137 mMaterial = material;
138 mMaterial->AddConnectionObserver( *this );
139 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
141 mResendDataProviders = true;
144 Material& RendererAttachment::GetMaterial()
149 void RendererAttachment::SetGeometry( BufferIndex updateBufferIndex, Geometry* geometry)
151 DALI_ASSERT_DEBUG( geometry != NULL && "Geometry pointer is NULL");
154 mGeometry->RemoveConnectionObserver(*this);
155 mGeometry->OnRendererDisconnect();
158 mGeometry = geometry;
159 mGeometry->AddConnectionObserver( *this ); // Observe geometry connections / uniform mapping changes
160 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
164 mResendGeometry = true;
168 Geometry& RendererAttachment::GetGeometry()
173 void RendererAttachment::SetSortAttributes( BufferIndex bufferIndex, RendererWithSortAttributes& sortAttributes )
175 sortAttributes.shader = mMaterial->GetShader();
176 sortAttributes.material = mMaterial;
177 sortAttributes.geometry = mGeometry;
180 void RendererAttachment::SetDepthIndex( int depthIndex )
182 mDepthIndex = depthIndex;
186 // only do this if we are on-stage. Ensures the render lists are re-sorted
187 mParent->SetDirtyFlag( SortModifierFlag );
191 Renderer& RendererAttachment::GetRenderer()
196 const Renderer& RendererAttachment::GetRenderer() const
201 // Called by ProcessRenderTasks after DoPrepareRender
202 bool RendererAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
206 if( mMaterial != NULL )
208 Material::BlendPolicy blendPolicy = mMaterial->GetBlendPolicy();
209 switch( blendPolicy )
211 case Material::OPAQUE:
216 case Material::TRANSPARENT:
221 case Material::USE_ACTOR_COLOR:
225 opaque = mParent->GetWorldColor( updateBufferIndex ).a >= FULLY_OPAQUE;
235 void RendererAttachment::SizeChanged( BufferIndex updateBufferIndex )
240 bool RendererAttachment::DoPrepareResources(
241 BufferIndex updateBufferIndex,
242 ResourceManager& resourceManager )
244 DALI_ASSERT_DEBUG( mSceneController );
246 CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
248 mFinishedResourceAcquisition = false;
250 // Can only be considered ready when all the scene graph objects are connected to the renderer
252 ( mGeometry->GetVertexBuffers().Count() > 0 ) &&
254 ( mMaterial->GetShader() != NULL ) )
256 unsigned int completeCount = 0;
257 unsigned int neverCount = 0;
258 unsigned int frameBufferCount = 0;
260 Vector<Sampler*>& samplers = mMaterial->GetSamplers();
261 for( Vector<Sampler*>::ConstIterator iter = samplers.Begin();
262 iter != samplers.End(); ++iter )
264 Sampler* sampler = *iter;
266 ResourceId textureId = sampler->GetTextureId( updateBufferIndex );
267 BitmapMetadata metaData = resourceManager.GetBitmapMetadata( textureId );
269 sampler->SetFullyOpaque( metaData.IsFullyOpaque() );
271 switch( completeStatusManager.GetStatus( textureId ) )
273 case CompleteStatusManager::NOT_READY:
275 if( metaData.GetIsFramebuffer() )
279 FollowTracker( textureId ); // @todo MESH_REWORK Trackers per sampler rather than per actor?
283 case CompleteStatusManager::COMPLETE:
289 case CompleteStatusManager::NEVER:
297 // We are ready if all samplers are complete, or those that aren't are framebuffers
298 // We are complete if all samplers are either complete or will never complete
300 ready = ( completeCount + frameBufferCount >= samplers.Count() ) ;
301 mFinishedResourceAcquisition = ( completeCount + neverCount >= samplers.Count() );
308 // Uniform maps are checked in the following priority order:
309 // Renderer (this object)
316 void RendererAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
318 // @todo MESH_REWORK - call DoPrepareRender on all scene objects? in caller class?
319 mMaterial->PrepareRender( updateBufferIndex );
321 if( mRegenerateUniformMap > 0)
323 if( mRegenerateUniformMap == REGENERATE_UNIFORM_MAP)
325 DALI_ASSERT_DEBUG( mGeometry != NULL && "No geometry available in DoPrepareRender()" );
326 DALI_ASSERT_DEBUG( mMaterial != NULL && "No geometry available in DoPrepareRender()" );
328 CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
331 const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap();
332 AddMappings( localMap, rendererUniformMap );
334 const UniformMap& actorUniformMap = mParent->GetUniformMap();
335 AddMappings( localMap, actorUniformMap );
337 AddMappings( localMap, mMaterial->GetUniformMap() );
338 Vector<Sampler*>& samplers = mMaterial->GetSamplers();
339 for( Vector<Sampler*>::ConstIterator iter = samplers.Begin(), end = samplers.End();
343 const SceneGraph::Sampler* sampler = (*iter);
344 AddMappings( localMap, sampler->GetUniformMap() );
347 AddMappings( localMap, mMaterial->GetShader()->GetUniformMap() );
349 AddMappings( localMap, mGeometry->GetUniformMap() );
351 Vector<PropertyBuffer*>& vertexBuffers = mGeometry->GetVertexBuffers();
352 for( Vector<PropertyBuffer*>::ConstIterator iter = vertexBuffers.Begin(), end = vertexBuffers.End() ;
356 const SceneGraph::PropertyBuffer* vertexBuffer = *iter;
357 AddMappings( localMap, vertexBuffer->GetUniformMap() );
360 PropertyBuffer* indexBuffer = mGeometry->GetIndexBuffer();
363 AddMappings( localMap, indexBuffer->GetUniformMap() );
366 mUniformMapChanged[updateBufferIndex] = true;
368 else if( mRegenerateUniformMap == COPY_UNIFORM_MAP )
370 // Copy old map into current map
371 CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
372 CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-updateBufferIndex ];
374 localMap.Resize( oldMap.Count() );
376 unsigned int index=0;
377 for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter, ++index )
379 localMap[index] = *iter;
382 mUniformMapChanged[updateBufferIndex] = true;
385 mRegenerateUniformMap--;
388 bool blend = !IsFullyOpaque( updateBufferIndex );
389 if( mUseBlend != blend )
392 mResendDataProviders = true;
395 if( mResendDataProviders )
397 RenderDataProvider* dataProvider = NewRenderDataProvider();
399 // Tell renderer about a new provider
400 // @todo MESH_REWORK Should we instead create a new renderer when these change?
402 typedef MessageValue1< NewRenderer, OwnerPointer<RenderDataProvider> > DerivedType;
403 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
404 new (slot) DerivedType( mRenderer, &NewRenderer::SetRenderDataProvider, dataProvider );
405 mResendDataProviders = false;
408 if( mResendGeometry )
410 // The first call to GetRenderGeometry() creates the geometry and sends it in a message
411 RenderGeometry* geometry = mGeometry->GetRenderGeometry( mSceneController );
413 typedef MessageValue1< NewRenderer, RenderGeometry* > DerivedType;
414 unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
416 new (slot) DerivedType( mRenderer, &NewRenderer::SetGeometry, geometry );
417 mResendGeometry = false;
421 void RendererAttachment::ConnectionsChanged( PropertyOwner& object )
423 // One of our child objects has changed it's connections. Ensure the uniform
424 // map gets regenerated during PrepareRender
425 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
427 // Ensure the child object pointers get re-sent to the renderer
428 mResendDataProviders = true;
431 void RendererAttachment::ConnectedUniformMapChanged()
433 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
436 void RendererAttachment::UniformMappingsChanged( const UniformMap& mappings )
438 // The mappings are either from PropertyOwner base class, or the Actor
439 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
442 bool RendererAttachment::GetUniformMapChanged( BufferIndex bufferIndex ) const
444 return mUniformMapChanged[bufferIndex];
447 const CollectedUniformMap& RendererAttachment::GetUniformMap( BufferIndex bufferIndex ) const
449 return mCollectedUniformMap[ bufferIndex ];
452 void RendererAttachment::AddMappings( CollectedUniformMap& localMap, const UniformMap& uniformMap )
454 // Iterate thru uniformMap.
455 // Any maps that aren't in localMap should be added in a single step
456 CollectedUniformMap newUniformMappings;
458 for( unsigned int i=0, count=uniformMap.Count(); i<count; ++i )
460 UniformPropertyMapping::Hash nameHash = uniformMap[i].uniformNameHash;
463 for( CollectedUniformMap::Iterator iter = localMap.Begin() ; iter != localMap.End() ; ++iter )
465 const UniformPropertyMapping* map = (*iter);
466 if( map->uniformNameHash == nameHash )
468 if( map->uniformName == uniformMap[i].uniformName )
477 // it's a new mapping. Add raw ptr to temporary list
478 newUniformMappings.PushBack( &uniformMap[i] );
482 if( newUniformMappings.Count() > 0 )
484 localMap.Reserve( localMap.Count() + newUniformMappings.Count() );
486 for( CollectedUniformMap::Iterator iter = newUniformMappings.Begin(),
487 end = newUniformMappings.End() ;
491 const UniformPropertyMapping* map = (*iter);
492 localMap.PushBack( map );
494 //@todo MESH_REWORK Use memcpy to copy ptrs from one array to the other
498 RenderDataProvider* RendererAttachment::NewRenderDataProvider()
500 RenderDataProvider* dataProvider = new RenderDataProvider();
502 dataProvider->mMaterialDataProvider = mMaterial;
503 dataProvider->mUniformMapDataProvider = this;
504 dataProvider->mShader = mMaterial->GetShader();
505 dataProvider->mUseBlend = mUseBlend;
507 Vector<Sampler*>& samplers = mMaterial->GetSamplers();
508 dataProvider->mSamplers.Reserve( samplers.Count() );
509 for( Vector<Sampler*>::Iterator iter = samplers.Begin() ;
510 iter != samplers.End();
513 dataProvider->mSamplers.PushBack(*iter); // Convert from derived type to base type
519 } // namespace SceneGraph
520 } // namespace Internal