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/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>
29 #if defined(DEBUG_ENABLED)
30 Debug::Filter* gImageAttachmentLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_SCENE_GRAPH_IMAGE_ATTACHMENT");
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)
39 #define ATTACHMENT_LOG(level)
40 #define ATTACHMENT_LOG_FMT(level, format, args...)
45 namespace // unnamed namespace
47 const int REGENERATE_UNIFORM_MAP = 2;
48 const int COPY_UNIFORM_MAP = 1;
58 RendererAttachment* RendererAttachment::New()
60 return new RendererAttachment();
64 RendererAttachment::RendererAttachment()
65 : RenderableAttachment( false ),
69 mRegenerateUniformMap(REGENERATE_UNIFORM_MAP),
70 mResendDataProviders(false),
73 mUniformMapChanged[0]=false;
74 mUniformMapChanged[1]=false;
76 // Observe our own PropertyOwner's uniform map
77 AddUniformMapObserver( *this );
81 RendererAttachment::~RendererAttachment()
83 mMaterial->RemoveConnectionObserver(*this);
84 mGeometry->RemoveConnectionObserver(*this);
90 void RendererAttachment::Initialize2( BufferIndex updateBufferIndex )
92 DALI_ASSERT_DEBUG( mSceneController );
95 void RendererAttachment::OnDestroy2()
99 void RendererAttachment::ConnectedToSceneGraph()
101 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
102 mParent->AddUniformMapObserver( *this ); // Watch actor's uniform maps
104 DALI_ASSERT_DEBUG( mParent != NULL );
106 RenderDataProvider* dataProvider = new RenderDataProvider( *mGeometry,
109 *mMaterial->GetShader(),
110 mGeometry->GetIndexBuffer(),
111 mGeometry->GetVertexBuffers(),
112 mMaterial->GetSamplers() );
114 mRenderer = NewRenderer::New( *mParent, dataProvider );
115 mSceneController->GetRenderMessageDispatcher().AddRenderer( *mRenderer );
118 void RendererAttachment::DisconnectedFromSceneGraph()
120 mRegenerateUniformMap = 0;
121 mParent->RemoveUniformMapObserver( *this );
123 DALI_ASSERT_DEBUG( mSceneController );
124 mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
128 void RendererAttachment::SetMaterial( BufferIndex updateBufferIndex, const Material* material)
130 DALI_ASSERT_DEBUG( material != NULL && "Material pointer is NULL" );
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;
136 mResendDataProviders = true;
139 const Material& RendererAttachment::GetMaterial() const
144 void RendererAttachment::SetGeometry( BufferIndex updateBufferIndex, const Geometry* geometry)
146 DALI_ASSERT_DEBUG( geometry != NULL && "Geometry pointer is NULL");
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;
152 mResendDataProviders = true;
155 const Geometry& RendererAttachment::GetGeometry() const
160 int RendererAttachment::GetDepthIndex(BufferIndex bufferIndex) const
162 return mDepthIndex[bufferIndex];
165 Renderer& RendererAttachment::GetRenderer()
170 const Renderer& RendererAttachment::GetRenderer() const
175 // Uniform maps are checked in the following priority order:
176 // Renderer (this object)
183 void RendererAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
185 if( mRegenerateUniformMap > 0)
187 if( mRegenerateUniformMap == REGENERATE_UNIFORM_MAP)
189 DALI_ASSERT_DEBUG( mGeometry != NULL && "No geometry available in DoPrepareRender()" );
190 DALI_ASSERT_DEBUG( mMaterial != NULL && "No geometry available in DoPrepareRender()" );
192 CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
195 const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap();
196 AddMappings( localMap, rendererUniformMap );
198 const UniformMap& actorUniformMap = mParent->GetUniformMap();
199 AddMappings( localMap, actorUniformMap );
201 AddMappings( localMap, mMaterial->GetUniformMap() );
202 const RenderDataProvider::Samplers& samplers = mMaterial->GetSamplers();
203 for( RenderDataProvider::Samplers::ConstIterator iter = samplers.Begin(), end = samplers.End();
207 const SceneGraph::Sampler* sampler = static_cast<const SceneGraph::Sampler*>( *iter );
208 AddMappings( localMap, sampler->GetUniformMap() );
211 AddMappings( localMap, mMaterial->GetShader()->GetUniformMap() );
213 AddMappings( localMap, mGeometry->GetUniformMap() );
215 const GeometryDataProvider::VertexBuffers& vertexBuffers = mGeometry->GetVertexBuffers();
216 for( GeometryDataProvider::VertexBuffers::ConstIterator iter = vertexBuffers.Begin(), end = vertexBuffers.End() ;
220 const SceneGraph::PropertyBuffer* vertexBuffer = static_cast<const SceneGraph::PropertyBuffer*>( *iter );
221 AddMappings( localMap, vertexBuffer->GetUniformMap() );
224 mUniformMapChanged[updateBufferIndex] = true;
226 else if( mRegenerateUniformMap == COPY_UNIFORM_MAP )
228 // Copy old map into current map
229 CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
230 CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-updateBufferIndex ];
232 localMap.Resize( oldMap.Count() );
234 unsigned int index=0;
235 for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter )
237 localMap[index] = *iter;
240 mUniformMapChanged[updateBufferIndex] = true;
243 mRegenerateUniformMap--;
246 if( mResendDataProviders )
248 RenderDataProvider* dataProvider = new RenderDataProvider( *mGeometry,
251 *mMaterial->GetShader(),
252 mGeometry->GetIndexBuffer(),
253 mGeometry->GetVertexBuffers(),
254 mMaterial->GetSamplers() );
256 // Tell renderer about a new provider
257 // @todo MESH_REWORK Should we instead create a new renderer when these change?
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 );
263 mResendDataProviders = false;
267 bool RendererAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
273 opaque = mParent->GetWorldColor( updateBufferIndex ).a >= FULLY_OPAQUE;
276 if( mMaterial != NULL )
278 // Require that all affecting samplers are opaque
279 unsigned int opaqueCount=0;
280 unsigned int affectingCount=0;
282 const RenderDataProvider::Samplers& samplers = mMaterial->GetSamplers();
283 for( RenderDataProvider::Samplers::ConstIterator iter = samplers.Begin();
284 iter != samplers.End(); ++iter )
286 const Sampler* sampler = static_cast<const Sampler*>(*iter);
287 if( sampler != NULL )
289 if( sampler->AffectsTransparency( updateBufferIndex ) )
292 if( sampler->IsFullyOpaque( updateBufferIndex ) )
299 opaque = (opaqueCount == affectingCount);
305 void RendererAttachment::SizeChanged( BufferIndex updateBufferIndex )
310 bool RendererAttachment::DoPrepareResources(
311 BufferIndex updateBufferIndex,
312 ResourceManager& resourceManager )
314 DALI_ASSERT_DEBUG( mSceneController );
316 CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
319 mFinishedResourceAcquisition = false;
321 // Can only be considered ready when all the scene graph objects are connected to the renderer
323 ( mGeometry->GetVertexBuffers().Count() > 0 ) &&
325 ( mMaterial->GetShader() != NULL ) )
327 unsigned int completeCount = 0;
328 unsigned int neverCount = 0;
329 unsigned int frameBufferCount = 0;
331 const RenderDataProvider::Samplers& samplers = mMaterial->GetSamplers();
332 for( RenderDataProvider::Samplers::ConstIterator iter = samplers.Begin();
333 iter != samplers.End(); ++iter )
335 const Sampler* sampler = static_cast<const Sampler*>(*iter);
337 ResourceId textureId = sampler->GetTextureId( updateBufferIndex );
338 BitmapMetadata metaData = resourceManager.GetBitmapMetadata( textureId );
340 Sampler* mutableSampler = const_cast<Sampler*>(sampler);
341 mutableSampler->SetFullyOpaque( metaData.IsFullyOpaque() );
343 switch( completeStatusManager.GetStatus( textureId ) )
345 case CompleteStatusManager::NOT_READY:
348 if( metaData.GetIsFramebuffer() )
352 FollowTracker( textureId ); // @todo MESH_REWORK Trackers per sampler rather than per actor?
356 case CompleteStatusManager::COMPLETE:
362 case CompleteStatusManager::NEVER:
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
373 ready = ( completeCount + frameBufferCount >= samplers.Count() ) ;
374 mFinishedResourceAcquisition = ( completeCount + neverCount >= samplers.Count() );
380 void RendererAttachment::ConnectionsChanged( PropertyOwner& object )
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;
386 // Ensure the child object pointers get re-sent to the renderer
387 mResendDataProviders = true;
390 void RendererAttachment::ConnectedUniformMapChanged()
392 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
395 void RendererAttachment::UniformMappingsChanged( const UniformMap& mappings )
397 // The mappings are either from PropertyOwner base class, or the Actor
398 mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
401 bool RendererAttachment::GetUniformMapChanged( BufferIndex bufferIndex ) const
403 return mUniformMapChanged[bufferIndex];
406 const CollectedUniformMap& RendererAttachment::GetUniformMap( BufferIndex bufferIndex ) const
408 return mCollectedUniformMap[ bufferIndex ];
411 void RendererAttachment::AddMappings( CollectedUniformMap& localMap, const UniformMap& uniformMap )
413 // Iterate thru uniformMap.
414 // Any maps that aren't in localMap should be added in a single step
415 CollectedUniformMap newUniformMappings;
417 for( unsigned int i=0, count=uniformMap.Count(); i<count; ++i )
419 UniformPropertyMapping::Hash nameHash = uniformMap[i].uniformNameHash;
422 for( CollectedUniformMap::Iterator iter = localMap.Begin() ; iter != localMap.End() ; ++iter )
424 const UniformPropertyMapping* map = (*iter);
425 if( map->uniformNameHash == nameHash )
427 if( map->uniformName == uniformMap[i].uniformName )
436 // it's a new mapping. Add raw ptr to temporary list
437 newUniformMappings.PushBack( &uniformMap[i] );
441 if( newUniformMappings.Count() > 0 )
443 localMap.Reserve( localMap.Count() + newUniformMappings.Count() );
445 for( CollectedUniformMap::Iterator iter = newUniformMappings.Begin(),
446 end = newUniformMappings.End() ;
450 const UniformPropertyMapping* map = (*iter);
451 localMap.PushBack( map );
453 //@todo MESH_REWORK Use memcpy to copy ptrs from one array to the other
459 } // namespace SceneGraph
460 } // namespace Internal