X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Fupdate%2Fmanager%2Fupdate-manager.cpp;h=0c6f697b892cdf8108a38e91695a37bb59c4d9e2;hb=4c8af0dfb14efdf61ab9eaf507dca05d13b36d0c;hp=0fbd58c0da529a923da51314d3ff2162896c4795;hpb=c97a9fd0be34a4187b5886582bb82fbe14e4fea2;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/update/manager/update-manager.cpp b/dali/internal/update/manager/update-manager.cpp index 0fbd58c..0c6f697 100644 --- a/dali/internal/update/manager/update-manager.cpp +++ b/dali/internal/update/manager/update-manager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015 Samsung Electronics Co., Ltd. + * Copyright (c) 2016 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -41,32 +41,32 @@ #include #include #include +#include #include #include #include #include -#include +#include #include #include #include #include -#include #include #include #include #include #include #include -#include #include -#include #include #include #include #include #include +#include #include +#include // Un-comment to enable node tree debug logging //#define NODE_TREE_LOGGING 1 @@ -114,6 +114,9 @@ typedef OwnerContainer GestureContainer; typedef GestureContainer::Iterator GestureIter; typedef GestureContainer::ConstIterator GestureConstIter; +typedef OwnerContainer< TextureSet* > TextureSetContainer; +typedef TextureSetContainer::Iterator TextureSetIter; +typedef TextureSetContainer::ConstIterator TextureSetConstIter; /** * Structure to contain UpdateManager internal data @@ -128,9 +131,8 @@ struct UpdateManager::Impl RenderController& renderController, RenderManager& renderManager, RenderQueue& renderQueue, - TextureCache& textureCache, - TouchResampler& touchResampler, - SceneGraphBuffers& sceneGraphBuffers ) + SceneGraphBuffers& sceneGraphBuffers, + RenderTaskProcessor& renderTaskProcessor ) : renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ), notificationManager( notificationManager ), transformManager(), @@ -144,29 +146,25 @@ struct UpdateManager::Impl renderManager( renderManager ), renderQueue( renderQueue ), renderInstructions( renderManager.GetRenderInstructionContainer() ), - touchResampler( touchResampler ), + renderTaskProcessor( renderTaskProcessor ), backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ), taskList( renderMessageDispatcher, resourceManager ), systemLevelTaskList( renderMessageDispatcher, resourceManager ), root( NULL ), systemLevelRoot( NULL ), renderers( sceneGraphBuffers, discardQueue ), - geometries( sceneGraphBuffers, discardQueue ), - textureSets( sceneGraphBuffers, discardQueue ), + textureSets(), messageQueue( renderController, sceneGraphBuffers ), keepRenderingSeconds( 0.0f ), animationFinishedDuringUpdate( false ), nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update() previousUpdateScene( false ), frameCounter( 0 ), - renderSortingHelper(), renderTaskWaiting( false ) { - sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache ); + sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue ); renderers.SetSceneController( *sceneController ); - geometries.SetSceneController( *sceneController ); - textureSets.SetSceneController( *sceneController ); // create first 'dummy' node nodes.PushBack(0u); @@ -193,7 +191,7 @@ struct UpdateManager::Impl for(;iter!=endIter;++iter) { (*iter)->OnDestroy(); - delete(*iter); + Node::Delete(*iter); } // If there is root, reset it, otherwise do nothing as rendering was never started @@ -201,7 +199,7 @@ struct UpdateManager::Impl { root->OnDestroy(); - delete root; + Node::Delete( root ); root = NULL; } @@ -209,11 +207,10 @@ struct UpdateManager::Impl { systemLevelRoot->OnDestroy(); - delete systemLevelRoot; + Node::Delete( systemLevelRoot ); systemLevelRoot = NULL; } - sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove delete sceneController; } @@ -231,7 +228,7 @@ struct UpdateManager::Impl RenderManager& renderManager; ///< This is responsible for rendering the results of each "update" RenderQueue& renderQueue; ///< Used to queue messages for the next render RenderInstructionContainer& renderInstructions; ///< Used to prepare the render instructions - TouchResampler& touchResampler; ///< Used to resample touch events on every update. + RenderTaskProcessor& renderTaskProcessor; ///< Handles RenderTasks and RenderInstrucitons Vector4 backgroundColor; ///< The glClear color used at the beginning of each frame. @@ -246,14 +243,14 @@ struct UpdateManager::Impl SortedLayerPointers sortedLayers; ///< A container of Layer pointers sorted by depth SortedLayerPointers systemLevelSortedLayers; ///< A separate container of system-level Layers + OwnerContainer< Camera* > cameras; ///< A container of cameras OwnerContainer< PropertyOwner* > customObjects; ///< A container of owned objects (with custom properties) AnimationContainer animations; ///< A container of owned animations PropertyNotificationContainer propertyNotifications; ///< A container of owner property notifications. ObjectOwnerContainer renderers; - ObjectOwnerContainer geometries; ///< A container of geometries - ObjectOwnerContainer textureSets; ///< A container of texture sets + TextureSetContainer textureSets; ///< A container of texture sets ShaderContainer shaders; ///< A container of owned shaders @@ -269,7 +266,6 @@ struct UpdateManager::Impl bool previousUpdateScene; ///< True if the scene was updated in the previous frame (otherwise it was optimized out) int frameCounter; ///< Frame counter used in debugging to choose which frame to debug and which to ignore. - RendererSortingHelper renderSortingHelper; ///< helper used to sort transparent renderers GestureContainer gestures; ///< A container of owned gesture detectors bool renderTaskWaiting; ///< A REFRESH_ONCE render task is waiting to be rendered @@ -283,8 +279,8 @@ UpdateManager::UpdateManager( NotificationManager& notificationManager, RenderController& controller, RenderManager& renderManager, RenderQueue& renderQueue, - TextureCache& textureCache, - TouchResampler& touchResampler ) + TextureCacheDispatcher& textureCacheDispatcher, + RenderTaskProcessor& renderTaskProcessor ) : mImpl(NULL) { mImpl = new Impl( notificationManager, @@ -295,11 +291,10 @@ UpdateManager::UpdateManager( NotificationManager& notificationManager, controller, renderManager, renderQueue, - textureCache, - touchResampler, - mSceneGraphBuffers ); + mSceneGraphBuffers, + renderTaskProcessor ); - textureCache.SetBufferIndices( &mSceneGraphBuffers ); + textureCacheDispatcher.SetBufferIndices( &mSceneGraphBuffers ); } UpdateManager::~UpdateManager() @@ -386,14 +381,30 @@ void UpdateManager::DestroyNode( Node* node ) node->OnDestroy(); } -//@todo MESH_REWORK Extend to allow arbitrary scene objects to connect to each other -void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment ) +void UpdateManager::AddCamera( Camera* camera ) { - DALI_ASSERT_DEBUG( node != NULL ); - DALI_ASSERT_DEBUG( attachment != NULL ); + DALI_ASSERT_DEBUG( camera != NULL ); + + mImpl->cameras.PushBack( camera ); // takes ownership +} + +void UpdateManager::RemoveCamera( const Camera* camera ) +{ + // Find the camera + OwnerContainer::Iterator iter = mImpl->cameras.Begin(); + OwnerContainer::ConstIterator end = mImpl->cameras.End(); + for ( ; iter != end; ++iter ) + { + Camera* value = *iter; + if ( camera == value ) + { + // Transfer ownership to the discard queue + mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), mImpl->cameras.Release( iter ) ); + + return; + } + } - // attach node to attachment first so that parent is known by the time attachment is connected - node->Attach( *attachment ); // node takes ownership } void UpdateManager::AddObject( PropertyOwner* object ) @@ -496,22 +507,11 @@ void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propert propertyNotification->SetNotifyMode( notifyMode ); } -ObjectOwnerContainer& UpdateManager::GetGeometryOwner() -{ - return mImpl->geometries; -} - ObjectOwnerContainer& UpdateManager::GetRendererOwner() { return mImpl->renderers; } - -ObjectOwnerContainer& UpdateManager::GetTexturesOwner() -{ - return mImpl->textureSets; -} - void UpdateManager::AddShader( Shader* shader ) { DALI_ASSERT_DEBUG( NULL != shader ); @@ -623,6 +623,29 @@ void UpdateManager::RemoveGesture( PanGesture* gesture ) DALI_ASSERT_DEBUG(false); } +void UpdateManager::AddTextureSet( TextureSet* textureSet ) +{ + DALI_ASSERT_DEBUG( NULL != textureSet ); + mImpl->textureSets.PushBack( textureSet ); +} + +void UpdateManager::RemoveTextureSet( TextureSet* textureSet ) +{ + DALI_ASSERT_DEBUG(textureSet != NULL); + size_t textureSetCount( mImpl->textureSets.Size() ); + for( size_t i(0); itextureSets[i] ) + { + mImpl->textureSets.Remove( mImpl->textureSets.Begin() + i ); + + // Update manager has ownership of the TextureSet + delete textureSet; + return; + } + } +} + unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene ) { return mImpl->messageQueue.ReserveMessageSlot( size, updateScene ); @@ -685,8 +708,6 @@ void UpdateManager::ResetProperties( BufferIndex bufferIndex ) (*iter)->ResetToBaseValues( bufferIndex ); } - mImpl->textureSets.ResetToBaseValues( bufferIndex ); - mImpl->geometries.ResetToBaseValues( bufferIndex ); mImpl->renderers.ResetToBaseValues( bufferIndex ); // Reset animatable shader properties to base values @@ -808,15 +829,11 @@ void UpdateManager::ProcessPropertyNotifications( BufferIndex bufferIndex ) void UpdateManager::PrepareTextureSets( BufferIndex bufferIndex ) { - ObjectOwnerContainer::Iterator iter = mImpl->textureSets.GetObjectContainer().Begin(); - const ObjectOwnerContainer::Iterator end = mImpl->textureSets.GetObjectContainer().End(); - for( ; iter != end; ++iter ) + size_t textureSetCount( mImpl->textureSets.Size() ); + for( size_t i(0); iPrepare( mImpl->resourceManager ); + mImpl->textureSets[i]->Prepare( mImpl->resourceManager ); } } @@ -856,10 +873,7 @@ void UpdateManager::UpdateRenderers( BufferIndex bufferIndex ) //Apply constraints ConstrainPropertyOwner( *rendererContainer[i], bufferIndex ); - if( rendererContainer[i]->IsReferenced() ) - { - rendererContainer[i]->PrepareRender( bufferIndex ); - } + rendererContainer[i]->PrepareRender( bufferIndex ); } } @@ -872,19 +886,19 @@ void UpdateManager::UpdateNodes( BufferIndex bufferIndex ) return; } - // Prepare resources, update shaders, update attachments, for each node + // Prepare resources, update shaders, for each node // And add the renderers to the sorted layers. Start from root, which is also a layer - mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ), - bufferIndex, - mImpl->resourceManager, - mImpl->renderQueue ); + mImpl->nodeDirtyFlags = UpdateNodeTree( *( mImpl->root ), + bufferIndex, + mImpl->resourceManager, + mImpl->renderQueue ); if ( mImpl->systemLevelRoot ) { - mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ), - bufferIndex, - mImpl->resourceManager, - mImpl->renderQueue ); + mImpl->nodeDirtyFlags |= UpdateNodeTree( *( mImpl->systemLevelRoot ), + bufferIndex, + mImpl->resourceManager, + mImpl->renderQueue ); } } @@ -901,10 +915,9 @@ unsigned int UpdateManager::Update( float elapsedSeconds, bool resourceChanged = mImpl->resourceManager.UpdateCache( bufferIndex ); //Process Touches & Gestures - mImpl->touchResampler.Update(); const bool gestureUpdated = ProcessGestures( bufferIndex, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds ); - const bool updateScene = // The scene-graph requires an update if.. + bool updateScene = // The scene-graph requires an update if.. (mImpl->nodeDirtyFlags & RenderableUpdateFlags) || // ..nodes were dirty in previous frame OR IsAnimationRunning() || // ..at least one animation is running OR mImpl->messageQueue.IsSceneUpdateRequired() || // ..a message that modifies the scene graph node tree is queued OR @@ -921,8 +934,10 @@ unsigned int UpdateManager::Update( float elapsedSeconds, mImpl->transformManager.ResetToBaseValue(); } - //Process the queued scene messages - mImpl->messageQueue.ProcessMessages( bufferIndex ); + // Process the queued scene messages. Note, MessageQueue::FlushQueue may be called + // between calling IsSceneUpdateRequired() above and here, so updateScene should + // be set again + updateScene |= mImpl->messageQueue.ProcessMessages( bufferIndex ); //Post Process Ids of resources updated by renderer mImpl->resourceManager.PostProcessResources( bufferIndex ); @@ -944,7 +959,7 @@ unsigned int UpdateManager::Update( float elapsedSeconds, //Prepare texture sets and apply constraints to them PrepareTextureSets( bufferIndex ); - //Clear the lists of renderable-attachments from the previous update + //Clear the lists of renderers from the previous update for( size_t i(0); isortedLayers.size(); ++i ) { mImpl->sortedLayers[i]->ClearRenderables(); @@ -959,10 +974,9 @@ unsigned int UpdateManager::Update( float elapsedSeconds, //This will populate each Layer with a list of renderers which are ready. UpdateNodes( bufferIndex ); - //Apply constraints to RenderTasks, shaders and geometries + //Apply constraints to RenderTasks, shaders ConstrainRenderTasks( bufferIndex ); ConstrainShaders( bufferIndex ); - mImpl->geometries.ConstrainObjects( bufferIndex ); //Update renderers and apply constraints UpdateRenderers( bufferIndex ); @@ -980,22 +994,20 @@ unsigned int UpdateManager::Update( float elapsedSeconds, if ( NULL != mImpl->root ) { - ProcessRenderTasks( bufferIndex, - mImpl->taskList, - *mImpl->root, - mImpl->sortedLayers, - mImpl->renderSortingHelper, - mImpl->renderInstructions ); + mImpl->renderTaskProcessor.Process( bufferIndex, + mImpl->taskList, + *mImpl->root, + mImpl->sortedLayers, + mImpl->renderInstructions ); // Process the system-level RenderTasks last if ( NULL != mImpl->systemLevelRoot ) { - ProcessRenderTasks( bufferIndex, - mImpl->systemLevelTaskList, - *mImpl->systemLevelRoot, - mImpl->systemLevelSortedLayers, - mImpl->renderSortingHelper, - mImpl->renderInstructions ); + mImpl->renderTaskProcessor.Process( bufferIndex, + mImpl->systemLevelTaskList, + *mImpl->systemLevelRoot, + mImpl->systemLevelSortedLayers, + mImpl->renderInstructions ); } } } @@ -1160,15 +1172,15 @@ void UpdateManager::SetFilterMode( Render::Sampler* sampler, unsigned int minFil new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetFilterMode, sampler, minFilterMode, magFilterMode ); } -void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int uWrapMode, unsigned int vWrapMode ) +void UpdateManager::SetWrapMode( Render::Sampler* sampler, unsigned int rWrapMode, unsigned int sWrapMode, unsigned int tWrapMode ) { - typedef MessageValue3< RenderManager, Render::Sampler*, unsigned int, unsigned int > DerivedType; + typedef MessageValue4< RenderManager, Render::Sampler*, unsigned int, unsigned int, unsigned int > DerivedType; // Reserve some memory inside the render queue unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) ); // Construct message in the render queue memory; note that delete should not be called on the return value - new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, uWrapMode, vWrapMode ); + new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetWrapMode, sampler, rWrapMode, sWrapMode, tWrapMode ); } void UpdateManager::AddPropertyBuffer( Render::PropertyBuffer* propertyBuffer ) @@ -1215,6 +1227,149 @@ void UpdateManager::SetPropertyBufferData( Render::PropertyBuffer* propertyBuffe new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetPropertyBufferData, propertyBuffer, data, size ); } +void UpdateManager::AddGeometry( Render::Geometry* geometry ) +{ + typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType; + + // Reserve some memory inside the render queue + unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) ); + + // Construct message in the render queue memory; note that delete should not be called on the return value + new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddGeometry, geometry ); +} + +void UpdateManager::RemoveGeometry( Render::Geometry* geometry ) +{ + typedef MessageValue1< RenderManager, Render::Geometry* > DerivedType; + + // Reserve some memory inside the render queue + unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) ); + + // Construct message in the render queue memory; note that delete should not be called on the return value + new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveGeometry, geometry ); +} + +void UpdateManager::SetGeometryType( Render::Geometry* geometry, unsigned int geometryType ) +{ + typedef MessageValue2< RenderManager, Render::Geometry*, unsigned int > DerivedType; + + // Reserve some memory inside the render queue + unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) ); + + // Construct message in the render queue memory; note that delete should not be called on the return value + new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetGeometryType, geometry, geometryType ); +} + +void UpdateManager::SetIndexBuffer( Render::Geometry* geometry, Dali::Vector& indices ) +{ + typedef IndexBufferMessage< RenderManager > DerivedType; + + // Reserve some memory inside the render queue + unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) ); + + // Construct message in the render queue memory; note that delete should not be called on the return value + new (slot) DerivedType( &mImpl->renderManager, geometry, indices ); +} + +void UpdateManager::RemoveVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer ) +{ + typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType; + + // Reserve some memory inside the render queue + unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) ); + + // Construct message in the render queue memory; note that delete should not be called on the return value + new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveVertexBuffer, geometry, propertyBuffer ); +} + +void UpdateManager::AddVertexBuffer( Render::Geometry* geometry, Render::PropertyBuffer* propertyBuffer ) +{ + typedef MessageValue2< RenderManager, Render::Geometry*, Render::PropertyBuffer* > DerivedType; + + // Reserve some memory inside the render queue + unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) ); + + // Construct message in the render queue memory; note that delete should not be called on the return value + new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddVertexBuffer, geometry, propertyBuffer ); +} + +void UpdateManager::AddTexture( Render::NewTexture* texture ) +{ + typedef MessageValue1< RenderManager, Render::NewTexture* > DerivedType; + + // Reserve some memory inside the render queue + unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) ); + + // Construct message in the render queue memory; note that delete should not be called on the return value + new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddTexture, texture ); +} + +void UpdateManager::RemoveTexture( Render::NewTexture* texture) +{ + typedef MessageValue1< RenderManager, Render::NewTexture* > DerivedType; + + // Reserve some memory inside the render queue + unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) ); + + // Construct message in the render queue memory; note that delete should not be called on the return value + new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveTexture, texture ); +} + +void UpdateManager::UploadTexture( Render::NewTexture* texture, PixelDataPtr pixelData, const NewTexture::UploadParams& params ) +{ + typedef MessageValue3< RenderManager, Render::NewTexture*, PixelDataPtr, NewTexture::UploadParams > DerivedType; + + // Reserve some memory inside the message queue + unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) ); + + // Construct message in the message queue memory; note that delete should not be called on the return value + new (slot) DerivedType( &mImpl->renderManager, &RenderManager::UploadTexture, texture, pixelData, params ); +} + +void UpdateManager::GenerateMipmaps( Render::NewTexture* texture ) +{ + typedef MessageValue1< RenderManager, Render::NewTexture* > DerivedType; + + // Reserve some memory inside the render queue + unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) ); + + // Construct message in the render queue memory; note that delete should not be called on the return value + new (slot) DerivedType( &mImpl->renderManager, &RenderManager::GenerateMipmaps, texture ); +} + +void UpdateManager::AddFrameBuffer( Render::FrameBuffer* frameBuffer ) +{ + typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType; + + // Reserve some memory inside the render queue + unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) ); + + // Construct message in the render queue memory; note that delete should not be called on the return value + new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AddFrameBuffer, frameBuffer ); +} + +void UpdateManager::RemoveFrameBuffer( Render::FrameBuffer* frameBuffer) +{ + typedef MessageValue1< RenderManager, Render::FrameBuffer* > DerivedType; + + // Reserve some memory inside the render queue + unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) ); + + // Construct message in the render queue memory; note that delete should not be called on the return value + new (slot) DerivedType( &mImpl->renderManager, &RenderManager::RemoveFrameBuffer, frameBuffer ); +} + +void UpdateManager::AttachColorTextureToFrameBuffer( Render::FrameBuffer* frameBuffer, Render::NewTexture* texture, unsigned int mipmapLevel, unsigned int layer ) +{ + typedef MessageValue4< RenderManager, Render::FrameBuffer*, Render::NewTexture*, unsigned int, unsigned int > DerivedType; + + // Reserve some memory inside the render queue + unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) ); + + // Construct message in the render queue memory; note that delete should not be called on the return value + new (slot) DerivedType( &mImpl->renderManager, &RenderManager::AttachColorTextureToFrameBuffer, frameBuffer, texture, mipmapLevel, layer ); +} + } // namespace SceneGraph } // namespace Internal