From 0b7b233c4007025cca19303d3e5a64ef99a8fbc4 Mon Sep 17 00:00:00 2001 From: David Steele Date: Wed, 8 Apr 2015 19:55:56 +0100 Subject: [PATCH] Added connection for sampler texture Adding an object connection for the sampler texture enables the material to be informed when the sampler texture changes. This is chained up to the renderable attachment, which re-sends the data providers to the renderer, updating the texture. Note, doubleBufferedProperty[i] = value does not enable the aging behaviour, whereas doubleBufferedProperty.Set(i, value) does. Change-Id: I3c43839e86cbc59a6c47598d287bfae512b18639 Signed-off-by: David Steele --- dali/internal/event/effects/sampler-impl.cpp | 7 +- dali/internal/event/effects/sampler-impl.h | 2 +- .../render/data-providers/material-data-provider.h | 2 - .../render/data-providers/render-data-provider.h | 1 + .../update/common/double-buffered-property.h | 173 +++++++++++++++++---- .../update/effects/scene-graph-material.cpp | 20 ++- .../internal/update/effects/scene-graph-material.h | 14 +- .../update/effects/scene-graph-sampler.cpp | 43 +++-- dali/internal/update/effects/scene-graph-sampler.h | 33 +++- .../scene-graph-renderer-attachment.cpp | 8 +- dali/public-api/shader-effects/sampler.cpp | 6 +- 11 files changed, 254 insertions(+), 55 deletions(-) diff --git a/dali/internal/event/effects/sampler-impl.cpp b/dali/internal/event/effects/sampler-impl.cpp index 9634eb5..ddd0e6f 100644 --- a/dali/internal/event/effects/sampler-impl.cpp +++ b/dali/internal/event/effects/sampler-impl.cpp @@ -61,12 +61,15 @@ void Sampler::SetUniformName( const std::string& name ) SetUnitNameMessage( GetEventThreadServices(), *mSceneObject, name); } -void Sampler::SetImage( Image& image ) +void Sampler::SetImage( ImagePtr& image ) { - unsigned int resourceId = image.GetResourceId(); + // Keep a reference to the image object + mImageConnector.Set( image, OnStage() ); // sceneObject is being used in a separate thread; queue a message to set + unsigned int resourceId = image->GetResourceId(); SetTextureMessage( GetEventThreadServices(), *mSceneObject, resourceId ); + } void Sampler::SetFilterMode( Dali::Sampler::FilterMode minFilter, Dali::Sampler::FilterMode magFilter ) diff --git a/dali/internal/event/effects/sampler-impl.h b/dali/internal/event/effects/sampler-impl.h index 9cb2347..358313e 100644 --- a/dali/internal/event/effects/sampler-impl.h +++ b/dali/internal/event/effects/sampler-impl.h @@ -61,7 +61,7 @@ public: /** * @copydoc Dali::Sampler::SetImage() */ - void SetImage( Image& image ); + void SetImage( ImagePtr& image ); /** * @copydoc Dali::Sampler::SetFilterMode() diff --git a/dali/internal/render/data-providers/material-data-provider.h b/dali/internal/render/data-providers/material-data-provider.h index f6e4234..dfc31f2 100644 --- a/dali/internal/render/data-providers/material-data-provider.h +++ b/dali/internal/render/data-providers/material-data-provider.h @@ -24,8 +24,6 @@ namespace Internal { namespace SceneGraph { -class SamplerDataProvider; -class Shader; /** * Interface to provide data of the material to the renderer. diff --git a/dali/internal/render/data-providers/render-data-provider.h b/dali/internal/render/data-providers/render-data-provider.h index d499db3..47170e3 100644 --- a/dali/internal/render/data-providers/render-data-provider.h +++ b/dali/internal/render/data-providers/render-data-provider.h @@ -31,6 +31,7 @@ namespace Internal namespace SceneGraph { class PropertyBuffer; +class Shader; /** * Wraps all the data providers for the renderer. This allows the diff --git a/dali/internal/update/common/double-buffered-property.h b/dali/internal/update/common/double-buffered-property.h index be934b1..aa84dd0 100644 --- a/dali/internal/update/common/double-buffered-property.h +++ b/dali/internal/update/common/double-buffered-property.h @@ -235,20 +235,19 @@ private: }; - /** - * A float doubleBuffered property of a scene-graph object. + * A double buffered integer property of a scene-graph object. */ template <> -class DoubleBufferedProperty : public DoubleBufferedPropertyBase +class DoubleBufferedProperty : public DoubleBufferedPropertyBase { public: /** - * Create a doubleBuffered property. - * @param[in] initialValue The initial value of the property. + * Create a double buffered property. + * @param [in] initialValue The initial value of the property. */ - DoubleBufferedProperty( float initialValue ) + DoubleBufferedProperty( int initialValue ) : mValue( initialValue ) { } @@ -265,7 +264,7 @@ public: */ virtual Dali::Property::Type GetType() const { - return Dali::PropertyTypes::Get(); + return Dali::PropertyTypes::Get(); } /** @@ -281,9 +280,9 @@ public: } /** - * @copydoc Dali::Internal::PropertyInputImpl::GetFloat() + * @copydoc Dali::Internal::PropertyInputImpl::GetInteger() */ - virtual const float& GetFloat( BufferIndex bufferIndex ) const + virtual const int& GetInteger( BufferIndex bufferIndex ) const { return mValue[ bufferIndex ]; } @@ -294,16 +293,21 @@ public: * @param[in] bufferIndex The buffer to write. * @param[in] value The new property value. */ - void Set(BufferIndex bufferIndex, float value) + void Set(BufferIndex bufferIndex, int value) { - mValue[bufferIndex] = value; - OnSet(); + // check if the value actually changed to avoid dirtying nodes unnecessarily + if( mValue[bufferIndex] != value ) + { + mValue[bufferIndex] = value; + + OnSet(); + } } /** * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get() */ - float& Get(size_t bufferIndex) + int& Get(size_t bufferIndex) { return mValue[bufferIndex]; } @@ -311,7 +315,7 @@ public: /** * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get() */ - const float& Get(size_t bufferIndex) const + const int& Get(size_t bufferIndex) const { return mValue[bufferIndex]; } @@ -321,7 +325,7 @@ public: * @param[in] bufferIndex The buffer to read. * @return The property value. */ - float& operator[](size_t bufferIndex) + int& operator[](size_t bufferIndex) { return mValue[bufferIndex]; } @@ -331,7 +335,7 @@ public: * @param[in] bufferIndex The buffer to read. * @return The property value. */ - const float& operator[](size_t bufferIndex) const + const int& operator[](size_t bufferIndex) const { return mValue[bufferIndex]; } @@ -344,23 +348,24 @@ private: DoubleBufferedProperty& operator=(const DoubleBufferedProperty& rhs); private: - DoubleBuffered mValue; ///< The double-buffered property value + DoubleBuffered mValue; ///< The double-buffered property value }; /** - * A double buffered integer property of a scene-graph object. + * A double buffered unsigned integer property of a scene-graph object. */ template <> -class DoubleBufferedProperty : public DoubleBufferedPropertyBase +class DoubleBufferedProperty : public DoubleBufferedPropertyBase { public: + typedef unsigned int OwnType; /** * Create a double buffered property. * @param [in] initialValue The initial value of the property. */ - DoubleBufferedProperty( int initialValue ) + DoubleBufferedProperty( OwnType initialValue ) : mValue( initialValue ) { } @@ -377,7 +382,7 @@ public: */ virtual Dali::Property::Type GetType() const { - return Dali::PropertyTypes::Get(); + return Dali::PropertyTypes::Get(); } /** @@ -395,7 +400,7 @@ public: /** * @copydoc Dali::Internal::PropertyInputImpl::GetInteger() */ - virtual const int& GetInteger( BufferIndex bufferIndex ) const + virtual const OwnType& GetUnsignedInteger( BufferIndex bufferIndex ) const { return mValue[ bufferIndex ]; } @@ -406,7 +411,7 @@ public: * @param[in] bufferIndex The buffer to write. * @param[in] value The new property value. */ - void Set(BufferIndex bufferIndex, int value) + void Set(BufferIndex bufferIndex, OwnType value) { // check if the value actually changed to avoid dirtying nodes unnecessarily if( mValue[bufferIndex] != value ) @@ -420,7 +425,7 @@ public: /** * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get() */ - int& Get(size_t bufferIndex) + OwnType& Get(size_t bufferIndex) { return mValue[bufferIndex]; } @@ -428,7 +433,7 @@ public: /** * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get() */ - const int& Get(size_t bufferIndex) const + const OwnType& Get(size_t bufferIndex) const { return mValue[bufferIndex]; } @@ -438,7 +443,7 @@ public: * @param[in] bufferIndex The buffer to read. * @return The property value. */ - int& operator[](size_t bufferIndex) + OwnType& operator[](size_t bufferIndex) { return mValue[bufferIndex]; } @@ -448,7 +453,7 @@ public: * @param[in] bufferIndex The buffer to read. * @return The property value. */ - const int& operator[](size_t bufferIndex) const + const OwnType& operator[](size_t bufferIndex) const { return mValue[bufferIndex]; } @@ -461,7 +466,119 @@ private: DoubleBufferedProperty& operator=(const DoubleBufferedProperty& rhs); private: - DoubleBuffered mValue; ///< The double-buffered property value + DoubleBuffered mValue; ///< The double-buffered property value +}; + + +/** + * A float doubleBuffered property of a scene-graph object. + */ +template <> +class DoubleBufferedProperty : public DoubleBufferedPropertyBase +{ +public: + + /** + * Create a doubleBuffered property. + * @param[in] initialValue The initial value of the property. + */ + DoubleBufferedProperty( float initialValue ) + : mValue( initialValue ) + { + } + + /** + * Virtual destructor. + */ + virtual ~DoubleBufferedProperty() + { + } + + /** + * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType() + */ + virtual Dali::Property::Type GetType() const + { + return Dali::PropertyTypes::Get(); + } + + /** + * @copydoc Dali::Internal::SceneGraph::DoubleBufferedPropertyBase::CopyPrevious() + */ + virtual void CopyPrevious( BufferIndex updateBufferIndex ) + { + if( DoubleBufferedPropertyFlags::SET_FLAG == mDirtyFlags) + { + mValue[ updateBufferIndex ] = mValue[ 1-updateBufferIndex ]; + mDirtyFlags = ( mDirtyFlags >> 1 ); + } + } + + /** + * @copydoc Dali::Internal::PropertyInputImpl::GetFloat() + */ + virtual const float& GetFloat( BufferIndex bufferIndex ) const + { + return mValue[ bufferIndex ]; + } + + /** + * Set the property value. This will persist for the current frame, and will + * be copied to the other buffer next frame (unless it is set again) + * @param[in] bufferIndex The buffer to write. + * @param[in] value The new property value. + */ + void Set(BufferIndex bufferIndex, float value) + { + mValue[bufferIndex] = value; + OnSet(); + } + + /** + * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get() + */ + float& Get(size_t bufferIndex) + { + return mValue[bufferIndex]; + } + + /** + * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get() + */ + const float& Get(size_t bufferIndex) const + { + return mValue[bufferIndex]; + } + + /** + * Retrieve the property value. + * @param[in] bufferIndex The buffer to read. + * @return The property value. + */ + float& operator[](size_t bufferIndex) + { + return mValue[bufferIndex]; + } + + /** + * Retrieve the property value. + * @param[in] bufferIndex The buffer to read. + * @return The property value. + */ + const float& operator[](size_t bufferIndex) const + { + return mValue[bufferIndex]; + } + +private: + // Undefined + DoubleBufferedProperty(const DoubleBufferedProperty& property); + + // Undefined + DoubleBufferedProperty& operator=(const DoubleBufferedProperty& rhs); + +private: + DoubleBuffered mValue; ///< The double-buffered property value }; /** diff --git a/dali/internal/update/effects/scene-graph-material.cpp b/dali/internal/update/effects/scene-graph-material.cpp index 952ae2a..c0ee2ca 100644 --- a/dali/internal/update/effects/scene-graph-material.cpp +++ b/dali/internal/update/effects/scene-graph-material.cpp @@ -46,7 +46,8 @@ Material::~Material() void Material::SetShader( const Shader* shader ) { mShader = shader; - // @todo inform NewRenderer about this shader + // Inform NewRenderer about this shader: (Will force a re-load of the + // shader from the data providers) mConnectionObservers.ConnectionsChanged(*this); } @@ -61,6 +62,10 @@ void Material::AddSampler( const Sampler* sampler ) const SamplerDataProvider* sdp = static_cast< const SamplerDataProvider*>( sampler ); mSamplers.PushBack( sdp ); + Sampler* mutableSampler = const_cast(sampler); + mutableSampler->AddConnectionObserver( *this ); + mutableSampler->AddUniformMapObserver( *this ); + mConnectionObservers.ConnectionsChanged(*this); } @@ -81,6 +86,9 @@ void Material::RemoveSampler( const Sampler* sampler ) if( found ) { + Sampler* mutableSampler = const_cast(sampler); + mutableSampler->RemoveConnectionObserver( *this ); + mutableSampler->RemoveUniformMapObserver( *this ); mSamplers.Erase(iter); mConnectionObservers.ConnectionsChanged(*this); } @@ -120,6 +128,16 @@ void Material::UniformMappingsChanged( const UniformMap& mappings ) mConnectionObservers.ConnectedUniformMapChanged(); } +void Material::ConnectionsChanged( PropertyOwner& owner ) +{ + mConnectionObservers.ConnectionsChanged(*this); +} + +void Material::ConnectedUniformMapChanged( ) +{ + mConnectionObservers.ConnectedUniformMapChanged(); +} + void Material::ResetDefaultProperties( BufferIndex updateBufferIndex ) { mColor.ResetToBaseValue( updateBufferIndex ); diff --git a/dali/internal/update/effects/scene-graph-material.h b/dali/internal/update/effects/scene-graph-material.h index 14201e1..f4e7f56 100644 --- a/dali/internal/update/effects/scene-graph-material.h +++ b/dali/internal/update/effects/scene-graph-material.h @@ -39,7 +39,7 @@ class Shader; class ConnectionObserver; class SceneController; -class Material : public PropertyOwner, public MaterialDataProvider, public UniformMap::Observer +class Material : public PropertyOwner, public MaterialDataProvider, public UniformMap::Observer, public ConnectionObservers::Observer { public: /** @@ -114,6 +114,18 @@ public: // UniformMap::Observer */ virtual void UniformMappingsChanged( const UniformMap& mappings ); +public: // ConnectionObserver::Observer + + /** + * @copydoc ConnectionObservers::ConnectionsChanged + */ + virtual void ConnectionsChanged( PropertyOwner& owner ); + + /** + * @copydoc ConnectionObservers::ConnectedUniformMapChanged + */ + virtual void ConnectedUniformMapChanged( ); + public: // PropertyOwner implementation /** * @copydoc Dali::Internal::SceneGraph::PropertyOwner::ResetDefaultProperties() diff --git a/dali/internal/update/effects/scene-graph-sampler.cpp b/dali/internal/update/effects/scene-graph-sampler.cpp index 02410d0..228e122 100644 --- a/dali/internal/update/effects/scene-graph-sampler.cpp +++ b/dali/internal/update/effects/scene-graph-sampler.cpp @@ -29,14 +29,14 @@ namespace SceneGraph Sampler::Sampler( const std::string& unitName ) : mUnitName( unitName ), + mTextureId( 0u ), mMinFilter( Dali::Sampler::DEFAULT ), mMagFilter( Dali::Sampler::DEFAULT ), mUWrapMode( Dali::Sampler::CLAMP_TO_EDGE ), mVWrapMode( Dali::Sampler::CLAMP_TO_EDGE ), - mAffectsTransparency( false ) + mAffectsTransparency( false ), + mFullyOpaque(true) { - mTextureId[0] = 0; - mTextureId[1] = 0; } Sampler::~Sampler() @@ -50,11 +50,11 @@ void Sampler::SetUnitName( const std::string& unitName ) void Sampler::SetTexture( BufferIndex bufferIndex, Integration::ResourceId textureId ) { - mTextureId[bufferIndex] = textureId; - - // @todo MESH_REWORK - //const BitmapMetadata& metadata - get it from ResourceManager - //mBitmapMetadata[bufferIndex] = metadata; + if( mTextureId[bufferIndex] != textureId ) + { + mTextureId.Set( bufferIndex, textureId ); + mConnectionObservers.ConnectionsChanged(*this); + } } void Sampler::SetFilterMode( BufferIndex bufferIndex, FilterMode minFilter, FilterMode magFilter ) @@ -102,9 +102,14 @@ bool Sampler::AffectsTransparency( BufferIndex bufferIndex ) const return mAffectsTransparency[bufferIndex] ; } +void Sampler::SetFullyOpaque( bool fullyOpaque ) +{ + mFullyOpaque = fullyOpaque; +} + bool Sampler::IsFullyOpaque( BufferIndex bufferIndex ) const { - return mBitmapMetadata[bufferIndex].IsFullyOpaque(); + return mFullyOpaque; } void Sampler::ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex ) @@ -115,6 +120,26 @@ void Sampler::DisconnectFromSceneGraph(SceneController& sceneController, BufferI { } +void Sampler::AddConnectionObserver( ConnectionObservers::Observer& observer ) +{ + mConnectionObservers.Add(observer); +} + +void Sampler::RemoveConnectionObserver( ConnectionObservers::Observer& observer ) +{ + mConnectionObservers.Remove(observer); +} + +void Sampler::ResetDefaultProperties( BufferIndex bufferIndex ) +{ + mTextureId.CopyPrevious( bufferIndex ); + mMinFilter.CopyPrevious( bufferIndex ); + mMagFilter.CopyPrevious( bufferIndex ); + mUWrapMode.CopyPrevious( bufferIndex ); + mVWrapMode.CopyPrevious( bufferIndex ); + mAffectsTransparency.CopyPrevious( bufferIndex ); +} + } // namespace SceneGraph } // namespace Internal } // namespace Dali diff --git a/dali/internal/update/effects/scene-graph-sampler.h b/dali/internal/update/effects/scene-graph-sampler.h index d50ccc5..a9f3817 100644 --- a/dali/internal/update/effects/scene-graph-sampler.h +++ b/dali/internal/update/effects/scene-graph-sampler.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -87,6 +88,12 @@ public: bool AffectsTransparency( BufferIndex bufferIndex ) const; /** + * Sets whether the associated texture is fully opaque or not. + * @param[in] fullyOpaque true if it's fully opaque + */ + void SetFullyOpaque( bool fullyOpaque ); + + /** * @param[in] bufferIndex The buffer index to use * @return true if the texture is fully opaque * @note this should only be called from Update thread @@ -150,17 +157,26 @@ public: // SamplerDataProvider interface - called from RenderThread * @param[in] bufferIndex The current buffer index - used for sending messages to render thread */ void DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex ); + /** + * @copydoc ConnectionObservers::AddObserver + */ + void AddConnectionObserver(ConnectionObservers::Observer& observer); -private: - std::string mUnitName; ///< The name of the uniform of the texture unit - - // @todo MESH_REWORK Need these to automatically copy - // new value into old value on frame change + /** + * @copydoc ConnectionObservers::RemoveObserver + */ + void RemoveConnectionObserver(ConnectionObservers::Observer& observer); - ResourceId mTextureId[2]; ///< The identity of the associated texture for this frame (Can be read from RenderThread) +public: // PropertyOwner implementation + /** + * @copydoc Dali::Internal::SceneGraph::PropertyOwner::ResetDefaultProperties() + */ + virtual void ResetDefaultProperties( BufferIndex updateBufferIndex ); - BitmapMetadata mBitmapMetadata[2]; /// The meta data of the associated texture for this frame (Not needed in RenderThread) +private: + std::string mUnitName; ///< The name of the uniform of the texture unit + DoubleBufferedProperty mTextureId; DoubleBufferedProperty mMinFilter; ///< The minify filter DoubleBufferedProperty mMagFilter; ///< The magnify filter DoubleBufferedProperty mUWrapMode; ///< The horizontal wrap mode @@ -168,6 +184,9 @@ private: // Note, this is only called from UpdateThread DoubleBufferedProperty mAffectsTransparency; ///< If this sampler affects renderer transparency + + ConnectionObservers mConnectionObservers; ///< Connection observers that will be informed when textures change. + bool mFullyOpaque; // Update only flag - no need for double buffering }; } // namespace SceneGraph diff --git a/dali/internal/update/node-attachments/scene-graph-renderer-attachment.cpp b/dali/internal/update/node-attachments/scene-graph-renderer-attachment.cpp index 582dd93..841fcf9 100644 --- a/dali/internal/update/node-attachments/scene-graph-renderer-attachment.cpp +++ b/dali/internal/update/node-attachments/scene-graph-renderer-attachment.cpp @@ -99,7 +99,7 @@ void RendererAttachment::OnDestroy2() void RendererAttachment::ConnectedToSceneGraph() { mRegenerateUniformMap = REGENERATE_UNIFORM_MAP; - mParent->AddUniformMapObserver( *this ); + mParent->AddUniformMapObserver( *this ); // Watch actor's uniform maps DALI_ASSERT_DEBUG( mParent != NULL ); @@ -334,12 +334,16 @@ bool RendererAttachment::DoPrepareResources( const Sampler* sampler = static_cast(*iter); ResourceId textureId = sampler->GetTextureId( updateBufferIndex ); + BitmapMetadata metaData = resourceManager.GetBitmapMetadata( textureId ); + + Sampler* mutableSampler = const_cast(sampler); + mutableSampler->SetFullyOpaque( metaData.IsFullyOpaque() ); + switch( completeStatusManager.GetStatus( textureId ) ) { case CompleteStatusManager::NOT_READY: { ready = false; - BitmapMetadata metaData = resourceManager.GetBitmapMetadata( textureId ); if( metaData.GetIsFramebuffer() ) { frameBufferCount++; diff --git a/dali/public-api/shader-effects/sampler.cpp b/dali/public-api/shader-effects/sampler.cpp index ceaee68..c8bdfc3 100644 --- a/dali/public-api/shader-effects/sampler.cpp +++ b/dali/public-api/shader-effects/sampler.cpp @@ -27,7 +27,8 @@ namespace Dali Sampler Sampler::New( Image& image, const std::string& textureUnitUniformName ) { Internal::SamplerPtr sampler = Internal::Sampler::New(textureUnitUniformName); - sampler->SetImage( GetImplementation( image ) ); + Internal::ImagePtr imagePtr = &GetImplementation( image ); + sampler->SetImage( imagePtr ); return Sampler( sampler.Get() ); } @@ -57,7 +58,8 @@ void Sampler::SetUniformName( const std::string& name ) void Sampler::SetImage( Image& image ) { - GetImplementation(*this).SetImage( GetImplementation( image ) ); + Internal::ImagePtr imagePtr = &GetImplementation( image ); + GetImplementation(*this).SetImage( imagePtr ); } void Sampler::SetFilterMode( FilterMode minFilter, FilterMode magFilter ) -- 2.7.4