-//
-// Copyright (c) 2014 Samsung Electronics Co., Ltd.
-//
-// Licensed under the Flora License, Version 1.0 (the License);
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://floralicense.org/license/
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an AS IS BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
+/*
+ * Copyright (c) 2014 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
// CLASS HEADER
#include <dali/internal/event/effects/shader-effect-impl.h>
-// EXTERNAL INCLUDES
-#include <fstream>
-
// INTERNAL INCLUDES
#include <dali/public-api/math/vector2.h>
#include <dali/public-api/math/matrix.h>
#include <dali/public-api/shader-effects/shader-effect.h>
#include <dali/public-api/object/type-registry.h>
#include <dali/public-api/scripting/scripting.h>
-#include "dali-shaders.h"
#include <dali/internal/event/effects/shader-declarations.h>
#include <dali/internal/event/effects/shader-factory.h>
#include <dali/internal/event/images/image-impl.h>
#include <dali/internal/event/common/stage-impl.h>
#include <dali/internal/event/common/thread-local-storage.h>
#include <dali/internal/render/shaders/shader.h>
-#include <dali/internal/update/common/property-owner-messages.h>
+#include <dali/internal/render/shaders/uniform-meta.h>
#include <dali/internal/update/animation/scene-graph-constraint-base.h>
+#include "dali-shaders.h"
using Dali::Internal::SceneGraph::UpdateManager;
using Dali::Internal::SceneGraph::UniformMeta;
using Dali::Internal::SceneGraph::Shader;
using Dali::Internal::SceneGraph::AnimatableProperty;
using Dali::Internal::SceneGraph::PropertyBase;
-using Dali::Internal::SceneGraph::PropertyBase;
using Dali::Internal::SceneGraph::RenderQueue;
+using std::string;
namespace Dali
{
namespace Internal
{
-ShaderEffect::DefaultPropertyLookup* ShaderEffect::mDefaultPropertyLookup = NULL;
-
namespace
{
+const PropertyDetails DEFAULT_PROPERTY_DETAILS[] =
+{
+ // Name Type writable animatable constraint-input
+ { "grid-density", Property::FLOAT, true, false, false }, // GRID_DENSITY
+ { "image", Property::MAP, true, false, false }, // IMAGE
+ { "program", Property::MAP, true, false, false }, // PROGRAM
+ { "geometry-hints", Property::INTEGER, true, false, false }, // GEOMETRY_HINTS
+};
+
+const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_DETAILS ) / sizeof( DEFAULT_PROPERTY_DETAILS[0] );
BaseHandle Create()
{
- Internal::ShaderEffectPtr internal = Internal::ShaderEffect::New( );
-
- ShaderFactory::LoadTextSubtypeShaders(internal);
+ Internal::ShaderEffectPtr internal = Internal::ShaderEffect::New();
return Dali::ShaderEffect(internal.Get());
}
TypeRegistration mType( typeid(Dali::ShaderEffect), typeid(Dali::Handle), Create );
-const std::string DEFAULT_PROPERTY_NAMES[] =
-{
- "grid-density",
- "image",
- "program",
- "geometry-hints",
-};
-const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_NAMES ) / sizeof( std::string );
-
-const Property::Type DEFAULT_PROPERTY_TYPES[DEFAULT_PROPERTY_COUNT] =
+struct WrapperStrings
{
- Property::FLOAT, // "grid-density",
- Property::MAP, // "image",
- Property::MAP, // "program",
- Property::INTEGER, // "geometry-hints",
+ const char* vertexShaderPrefix;
+ const char* fragmentShaderPrefix;
+ const char* vertexShaderPostfix;
+ const char* fragmentShaderPostfix;
};
-void SetShaderProgram( const std::string& imageVertexSnippet, const std::string& imageFragmentSnippet,
- const std::string& textVertexSnippet, const std::string& textFragmentSnippet,
- const std::string& texturedMeshVertexSnippet, const std::string& texturedMeshFragmentSnippet,
- const std::string& meshVertexSnippet, const std::string& meshFragmentSnippet,
- const std::string& vertexShaderPrefix, const std::string& fragmentShaderPrefix,
- ShaderEffectPtr shaderEffect )
+WrapperStrings customShaderWrappers [] =
{
- DALI_ASSERT_DEBUG(shaderEffect);
-
- // create complete shader program strings for GEOMETRY_TYPE_IMAGE
- std::string vertexSource = vertexShaderPrefix + CustomImagePrefixVertex;
- std::string fragmentSource = fragmentShaderPrefix + CustomImagePrefixFragment;
-
- // Append the custom vertex shader code if supplied, otherwise append the default
- if ( imageVertexSnippet.length() > 0 )
{
- vertexSource.append( imageVertexSnippet );
- }
- else
+ CustomImagePrefixVertex, CustomImagePrefixFragment,
+ CustomImagePostfixVertex, CustomImagePostfixFragment
+ },
{
- vertexSource.append( CustomImagePostfixVertex );
- }
-
- // Append the custom fragment shader code if supplied, otherwise append the default
- if ( imageFragmentSnippet.length() > 0 )
- {
- fragmentSource.append( imageFragmentSnippet );
- }
- else
+ CustomTextDistanceFieldPrefixVertex, CustomTextDistanceFieldPrefixFragment,
+ CustomTextDistanceFieldPostfixVertex, CustomTextDistanceFieldPostfixFragment
+ },
{
- fragmentSource.append( CustomImagePostfixFragment );
- }
-
- // Add the program
- shaderEffect->SetProgram( GEOMETRY_TYPE_IMAGE, SHADER_SUBTYPE_ALL, vertexSource, fragmentSource );
-
-
- // create complete shader program strings for GEOMETRY_TYPE_TEXT
- vertexSource = CustomFontPrefixVertex;
- fragmentSource = CustomFontPrefixFragment;
-
- // Append the custom vertex shader code if supplied, otherwise append the default
- if ( textVertexSnippet.length() > 0 )
- {
- vertexSource.append( textVertexSnippet );
- }
- else
- {
- vertexSource.append( CustomFontPostfixVertex );
- }
-
- // Append the custom fragment shader code if supplied, otherwise append the default
- if ( textFragmentSnippet.length() > 0 )
- {
- fragmentSource.append( textFragmentSnippet );
- }
- else
- {
- fragmentSource.append( CustomFontPostfixFragment );
- }
-
- // Add Program. Note, we only change the default program here, and leave the other sub-types as-is
- shaderEffect->SetProgram(GEOMETRY_TYPE_TEXT, SHADER_DEFAULT, vertexSource, fragmentSource);
-
- // create complete shader program strings for GEOMETRY_TYPE_TEXTURED_MESH
- if( texturedMeshVertexSnippet.length() > 0 )
- {
- vertexSource = CustomMeshPrefixVertex;
- vertexSource.append( texturedMeshVertexSnippet );
- }
- else
- {
- vertexSource = MeshVertex;
- }
-
- if( texturedMeshFragmentSnippet.length() > 0 )
- {
- fragmentSource = CustomMeshPrefixFragment;
- fragmentSource.append( texturedMeshFragmentSnippet );
- }
- else
- {
- fragmentSource = MeshFragment;
- }
-
- // Add Program
- shaderEffect->SetProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_SUBTYPE_ALL, vertexSource, fragmentSource );
-
- // create complete shader program strings for GEOMETRY_TYPE_MESH
- if( meshVertexSnippet.length() > 0 )
- {
- vertexSource = CustomMeshPrefixVertex;
- vertexSource.append( meshVertexSnippet );
- }
- else
- {
- vertexSource = MeshVertex;
- }
-
- if( meshFragmentSnippet.length() > 0 )
- {
- fragmentSource = CustomMeshPrefixFragment;
- fragmentSource.append( meshFragmentSnippet );
- }
- else
+ CustomUntexturedMeshPrefixVertex, CustomUntexturedMeshPrefixFragment,
+ CustomUntexturedMeshPostfixVertex, CustomUntexturedMeshPostfixFragment
+ },
{
- fragmentSource = MeshFragment;
+ CustomTexturedMeshPrefixVertex, CustomTexturedMeshPrefixFragment,
+ CustomTexturedMeshPostfixVertex, CustomTexturedMeshPostfixFragment
}
+};
- // Add Program
- shaderEffect->SetProgram( GEOMETRY_TYPE_MESH, SHADER_SUBTYPE_ALL, vertexSource, fragmentSource );
-}
-
-void SetShaderProgram( const std::string& vertexShaderPrefix, const std::string& vertexShader,
- const std::string& fragmentShaderPrefix, const std::string& fragmentShader,
- GeometryType geometryTypes,
- ShaderEffectPtr shaderEffect )
-{
- DALI_ASSERT_DEBUG(shaderEffect);
-
- if( geometryTypes & GEOMETRY_TYPE_IMAGE )
- {
- shaderEffect->SetProgram( GEOMETRY_TYPE_IMAGE, SHADER_SUBTYPE_ALL,
- vertexShaderPrefix + CustomImagePrefixVertex + ( !vertexShader.empty() ? vertexShader : CustomImagePostfixVertex ),
- fragmentShaderPrefix + CustomImagePrefixFragment + ( !fragmentShader.empty() ? fragmentShader : CustomImagePostfixFragment ) );
- }
- else
- {
- shaderEffect->SetProgram( GEOMETRY_TYPE_IMAGE, SHADER_SUBTYPE_ALL,
- CustomImagePrefixVertex + CustomImagePostfixVertex,
- CustomImagePrefixFragment + CustomImagePostfixFragment );
- }
+/**
+ * Helper to wrap the program with our default pre and postfix if needed and then send it to update/render thread
+ * @param[in] effect of the shader
+ * @param[in] actualGeometryType of the shader
+ * @param[in] expectedGeometryType of the shader
+ * @param[in] vertexPrefix from application
+ * @param[in] fragmentPrefix from application
+ * @param[in] vertexBody from application
+ * @param[in] fragmentBody from application
+ * @param[in] modifiesGeometry based on flags and vertex shader
+ */
+void WrapAndSetProgram( Internal::ShaderEffect& effect,
+ GeometryType actualGeometryType, GeometryType expectedGeometryType,
+ const std::string& vertexPrefix, const std::string& fragmentPrefix,
+ const std::string& vertexBody, const std::string& fragmentBody,
+ bool modifiesGeometry )
+{
+ // if geometry type matches and there is some real data in the strings
+ if( ( actualGeometryType & expectedGeometryType )&&
+ ( ( vertexPrefix.length() > 0 )||
+ ( fragmentPrefix.length() > 0 )||
+ ( vertexBody.length() > 0 )||
+ ( fragmentBody.length() > 0 ) ) )
+ {
+ std::string vertexSource = vertexPrefix;
+ std::string fragmentSource = fragmentPrefix;
+
+ // create complete shader program strings for the given geometry type
+ unsigned int index = 0;
+ switch( expectedGeometryType )
+ {
+ case GEOMETRY_TYPE_IMAGE:
+ {
+ index = 0;
+ break;
+ }
+ case GEOMETRY_TYPE_TEXT:
+ {
+ index = 1;
+ break;
+ }
+ case GEOMETRY_TYPE_UNTEXTURED_MESH:
+ {
+ index = 2;
+ break;
+ }
+ case GEOMETRY_TYPE_TEXTURED_MESH:
+ {
+ index = 3;
+ break;
+ }
+ case GEOMETRY_TYPE_LAST:
+ {
+ DALI_ASSERT_DEBUG(0 && "Wrong geometry type");
+ break;
+ }
+ }
- if( geometryTypes & GEOMETRY_TYPE_TEXT )
- {
- shaderEffect->SetProgram( GEOMETRY_TYPE_TEXT, SHADER_DEFAULT,
- vertexShaderPrefix + CustomFontPrefixVertex + ( !vertexShader.empty() ? vertexShader : CustomFontPostfixVertex ),
- fragmentShaderPrefix + CustomFontPrefixFragment + ( !fragmentShader.empty() ? fragmentShader : CustomFontPostfixFragment ) );
- }
- else
- {
- shaderEffect->SetProgram( GEOMETRY_TYPE_TEXT, SHADER_DEFAULT,
- CustomFontPrefixVertex + CustomFontPostfixVertex,
- CustomFontPrefixFragment + CustomFontPostfixFragment );
- }
+ vertexSource += customShaderWrappers[index].vertexShaderPrefix;
+ // Append the custom vertex shader code if supplied, otherwise append the default
+ if ( vertexBody.length() > 0 )
+ {
+ vertexSource.append( vertexBody );
+ }
+ else
+ {
+ vertexSource.append( customShaderWrappers[index].vertexShaderPostfix );
+ }
- if( geometryTypes & GEOMETRY_TYPE_TEXTURED_MESH )
- {
- shaderEffect->SetProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_SUBTYPE_ALL,
- vertexShaderPrefix + ( !vertexShader.empty() ? CustomMeshPrefixVertex + vertexShader : MeshVertex ),
- fragmentShaderPrefix + ( !fragmentShader.empty() ? CustomMeshPrefixFragment + fragmentShader : MeshFragment ) );
- }
- else
- {
- shaderEffect->SetProgram( GEOMETRY_TYPE_TEXTURED_MESH, SHADER_SUBTYPE_ALL, MeshVertex, MeshFragment );
- }
+ fragmentSource += customShaderWrappers[index].fragmentShaderPrefix;
+ // Append the custom fragment shader code if supplied, otherwise append the default
+ if ( fragmentBody.length() > 0 )
+ {
+ fragmentSource.append( fragmentBody );
+ }
+ else
+ {
+ fragmentSource.append( customShaderWrappers[index].fragmentShaderPostfix );
+ }
- if( geometryTypes & GEOMETRY_TYPE_MESH )
- {
- shaderEffect->SetProgram( GEOMETRY_TYPE_MESH, SHADER_SUBTYPE_ALL,
- vertexShaderPrefix + ( !vertexShader.empty() ? CustomMeshPrefixVertex + vertexShader : MeshColorNoTextureVertex ),
- fragmentShaderPrefix + ( !fragmentShader.empty() ? CustomMeshPrefixFragment + fragmentShader : MeshColorNoTextureFragment ) );
+ effect.SendProgramMessage( expectedGeometryType, SHADER_SUBTYPE_ALL, vertexSource, fragmentSource, modifiesGeometry );
}
- else
- {
- shaderEffect->SetProgram( GEOMETRY_TYPE_MESH, SHADER_SUBTYPE_ALL, MeshColorNoTextureVertex, MeshColorNoTextureFragment );
- }
-}
-
-std::string GetFileContents( const std::string& filename )
-{
- std::ifstream input( filename.c_str() );
- return std::string( std::istreambuf_iterator<char>(input), std::istreambuf_iterator<char>() );
}
std::string GetShader(const std::string& field, const Property::Value& property)
{
+ std::string value;
if( property.HasKey(field) )
{
DALI_ASSERT_ALWAYS(property.GetValue(field).GetType() == Property::STRING && "Shader property is not a string" );
// we could also check here for an array of strings as convenience for json not having multi line strings
- return property.GetValue(field).Get<std::string>();
- }
- else
- {
- // convention of shader field appended with -filename signifies a file
- std::string filenameKey(std::string(field) + std::string("-filename"));
-
- if( property.HasKey( filenameKey ) )
- {
- DALI_ASSERT_ALWAYS(property.GetValue(filenameKey).GetType() == Property::STRING && "Shader filename property is not a string" );
- // this should eventually be done by an adaptor interface
- return GetFileContents( property.GetValue(filenameKey).Get<std::string>() );
- }
+ value = property.GetValue(field).Get<std::string>();
}
- // if we got here
- return std::string();
+ return value;
}
-} // anon namespace
-
+} // unnamed namespace
ShaderEffectPtr ShaderEffect::New( Dali::ShaderEffect::GeometryHints hints )
{
ThreadLocalStorage& tls = ThreadLocalStorage::Get();
UpdateManager& updateManager = tls.GetUpdateManager();
- ShaderFactory& shaderFactory = tls.GetShaderFactory();
- // Create a new scene-object, temporarily owned
- Shader* sceneObject = new Shader( hints );
- DALI_ASSERT_DEBUG( NULL != sceneObject );
-
- ShaderEffectPtr shaderEffect( new ShaderEffect( updateManager, shaderFactory, *sceneObject ) );
+ ShaderEffectPtr shaderEffect( new ShaderEffect( updateManager, hints ) );
shaderEffect->RegisterObject();
return shaderEffect;
}
-ShaderEffectPtr ShaderEffect::New( const std::string& vertexShader,
- const std::string& fragmentShader,
- GeometryType geometryType,
- Dali::ShaderEffect::GeometryHints hints )
-{
- return NewWithPrefix( "", vertexShader, "", fragmentShader, geometryType, hints);
-}
-
-ShaderEffectPtr ShaderEffect::NewWithPrefix( const std::string& vertexShaderPrefix,
- const std::string& vertexShader,
- const std::string& fragmentShaderPrefix,
- const std::string& fragmentShader,
- GeometryType geometryTypes,
- Dali::ShaderEffect::GeometryHints hints )
-{
- ShaderEffectPtr shaderEffect( New(hints) );
-
- ShaderFactory::LoadTextSubtypeShaders(shaderEffect);
-
- SetShaderProgram( vertexShaderPrefix, vertexShader,
- fragmentShaderPrefix, fragmentShader,
- geometryTypes,
- shaderEffect );
-
- return shaderEffect;
-}
-
-ShaderEffectPtr ShaderEffect::New( const std::string& imageVertexShader,
- const std::string& imageFragmentShader,
- const std::string& textVertexShader,
- const std::string& textFragmentShader,
- const std::string& texturedMeshVertexShader,
- const std::string& texturedMeshFragmentShader,
- const std::string& meshVertexShader,
- const std::string& meshFragmentShader,
- Dali::ShaderEffect::GeometryHints hints )
+ShaderEffect::ShaderEffect( UpdateManager& updateManager, Dali::ShaderEffect::GeometryHints hints )
+: mUpdateManager( updateManager ),
+ mConnectionCount (0),
+ mGeometryHints( hints )
{
- ShaderEffectPtr shaderEffect( New(hints) );
-
- ShaderFactory::LoadTextSubtypeShaders(shaderEffect);
+ mSceneObject = new Shader( hints );
+ DALI_ASSERT_DEBUG( NULL != mSceneObject );
- SetShaderProgram( imageVertexShader, imageFragmentShader,
- textVertexShader, textFragmentShader,
- texturedMeshVertexShader, texturedMeshFragmentShader,
- meshVertexShader, meshFragmentShader,
- "", "",
- shaderEffect );
-
- return shaderEffect;
+ // Transfer shader ownership to a scene message
+ AddShaderMessage( mUpdateManager, *mSceneObject );
}
ShaderEffect::~ShaderEffect()
{
- DALI_ASSERT_DEBUG( mSceneObject != NULL );
-
// Guard to allow handle destruction after Core has been destroyed
if ( Stage::IsInstalled() )
{
// Remove scene-object using a message to the UpdateManager
- RemoveShaderMessage( mUpdateManager, *mSceneObject );
-
+ if( mSceneObject )
+ {
+ RemoveShaderMessage( mUpdateManager, *mSceneObject );
+ }
UnregisterObject();
}
}
-ShaderEffect::ShaderEffect( UpdateManager& updateManager, ShaderFactory& shaderFactory, Shader& sceneObject )
-: mUpdateManager( updateManager ),
- mShaderFactory( shaderFactory ),
- mSceneObject( &sceneObject ),
- mConnectionCount (0)
-{
- // Transfer shader ownership to a scene message
- AddShaderMessage( mUpdateManager, *mSceneObject );
-}
-
void ShaderEffect::SetEffectImage( Dali::Image image )
{
// if images are the same, do nothing
SetProperty( index, value );
- SetCoordinateTypeMessage( mUpdateManager.GetEventToUpdate(), *mCustomMetadata[index], uniformCoordinateType );
+ // RegisterProperty guarantees a positive value as index
+ DALI_ASSERT_DEBUG( static_cast<unsigned int>(index) >= CustomPropertyStartIndex() );
+ unsigned int metaIndex = index - CustomPropertyStartIndex();
+ // check if there's space in cache
+ if( mCoordinateTypes.Count() < (metaIndex + 1) )
+ {
+ mCoordinateTypes.Resize( metaIndex + 1 );
+ }
+ // only send message if the value is different than current, initial value is COORDINATE_TYPE_DEFAULT (0)
+ if( uniformCoordinateType != mCoordinateTypes[ metaIndex ] )
+ {
+ mCoordinateTypes[ metaIndex ] = uniformCoordinateType;
+ SetCoordinateTypeMessage( mUpdateManager.GetEventToUpdate(), *mSceneObject, metaIndex, uniformCoordinateType );
+ }
}
void ShaderEffect::AttachExtension( Dali::ShaderEffect::Extension *extension )
return *mExtension;
}
-void ShaderEffect::SetProgram( GeometryType geometryType, ShaderSubTypes subType,
- const std::string& vertexSource, const std::string& fragmentSource )
+void ShaderEffect::SetPrograms( GeometryType geometryType, const string& vertexSource, const string& fragmentSource )
{
- // Load done asynchronously in update thread. SetProgram message below must be processed afterwards.
- // Therefore, resource manager cannot farm out the loading to the adaptor resource threads,
- // but must instead use synchronous loading via PlatformAbstraction::LoadFile()
+ SetPrograms( geometryType, "", "", vertexSource, fragmentSource );
+}
+
+void ShaderEffect::SetPrograms( GeometryType geometryType,
+ const std::string& vertexPrefix, const std::string& fragmentPrefix,
+ const std::string& vertexSource, const std::string& fragmentSource )
+{
+ bool modifiesGeometry = true;
+ // check if the vertex shader is empty (means it cannot modify geometry)
+ if( (vertexPrefix.length() == 0 )&&( vertexSource.length() == 0 ) )
+ {
+ modifiesGeometry = false;
+ }
+ // check the hint second
+ if( (mGeometryHints & Dali::ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY ) != 0 )
+ {
+ modifiesGeometry = false;
+ }
+
+ WrapAndSetProgram( *this, geometryType, GEOMETRY_TYPE_IMAGE, vertexPrefix, fragmentPrefix, vertexSource, fragmentSource, modifiesGeometry );
+ WrapAndSetProgram( *this, geometryType, GEOMETRY_TYPE_TEXT, vertexPrefix, fragmentPrefix, vertexSource, fragmentSource, modifiesGeometry );
+ WrapAndSetProgram( *this, geometryType, GEOMETRY_TYPE_TEXTURED_MESH, vertexPrefix, fragmentPrefix, vertexSource, fragmentSource, modifiesGeometry );
+ WrapAndSetProgram( *this, geometryType, GEOMETRY_TYPE_UNTEXTURED_MESH, vertexPrefix, fragmentPrefix, vertexSource, fragmentSource, modifiesGeometry );
+}
+
+void ShaderEffect::SendProgramMessage( GeometryType geometryType, ShaderSubTypes subType,
+ const string& vertexSource, const string& fragmentSource,
+ bool modifiesGeometry )
+{
+ ThreadLocalStorage& tls = ThreadLocalStorage::Get();
+ ShaderFactory& shaderFactory = tls.GetShaderFactory();
size_t shaderHash;
- ResourceTicketPtr ticket( mShaderFactory.Load(vertexSource, fragmentSource, shaderHash) );
+
+ ResourceTicketPtr ticket( shaderFactory.Load(vertexSource, fragmentSource, shaderHash) );
DALI_LOG_INFO( Debug::Filter::gShader, Debug::General, "ShaderEffect: SetProgram(geometryType %d subType:%d ticket.id:%d)\n", geometryType, subType, ticket->GetId() );
// Add shader program to scene-object using a message to the UpdateManager
- SetShaderProgramMessage( mUpdateManager, *mSceneObject, geometryType, subType, ticket->GetId(), shaderHash );
+ SetShaderProgramMessage( mUpdateManager, *mSceneObject, geometryType, subType, ticket->GetId(), shaderHash, modifiesGeometry );
mTickets.push_back(ticket); // add ticket to collection to keep it alive.
}
-
-void ShaderEffect::SetProgram( GeometryType geometryType, ShaderSubTypes subType,
- const std::string& vertexPrefix, const std::string& fragmentPrefix,
- const std::string& vertexSource, const std::string& fragmentSource )
-{
- const std::string vertex( vertexPrefix + vertexSource );
- const std::string fragment( fragmentPrefix + fragmentSource );
- SetProgram( geometryType, subType, vertex, fragment );
-}
-
void ShaderEffect::Connect()
{
++mConnectionCount;
}
}
-bool ShaderEffect::IsSceneObjectRemovable() const
-{
- return false; // The Shader is not removed during this proxy's lifetime
-}
-
unsigned int ShaderEffect::GetDefaultPropertyCount() const
{
return DEFAULT_PROPERTY_COUNT;
}
}
-const std::string& ShaderEffect::GetDefaultPropertyName(Property::Index index) const
+const char* ShaderEffect::GetDefaultPropertyName(Property::Index index) const
{
if( index < DEFAULT_PROPERTY_COUNT )
{
- return DEFAULT_PROPERTY_NAMES[index];
+ return DEFAULT_PROPERTY_DETAILS[index].name;
}
else
{
- // index out of range..return empty string
- static const std::string INVALID_PROPERTY_NAME;
- return INVALID_PROPERTY_NAME;
+ return NULL;
}
}
{
Property::Index index = Property::INVALID_INDEX;
- // Lazy initialization of static mDefaultPropertyLookup
- if (!mDefaultPropertyLookup)
+ // Look for name in default properties
+ for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
{
- mDefaultPropertyLookup = new DefaultPropertyLookup();
-
- for (int i=0; i<DEFAULT_PROPERTY_COUNT; ++i)
+ const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
+ if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
{
- (*mDefaultPropertyLookup)[DEFAULT_PROPERTY_NAMES[i]] = i;
+ index = i;
+ break;
}
}
- DALI_ASSERT_DEBUG( NULL != mDefaultPropertyLookup );
-
- // Look for name in default properties
- DefaultPropertyLookup::const_iterator result = mDefaultPropertyLookup->find( name );
- if ( mDefaultPropertyLookup->end() != result )
- {
- index = result->second;
- }
return index;
+
}
bool ShaderEffect::IsDefaultPropertyWritable(Property::Index index) const
{
- return true;
+ return true; // all properties are writable
}
bool ShaderEffect::IsDefaultPropertyAnimatable(Property::Index index) const
{
- return false;
+ return false; // all properties are non animatable
+}
+
+bool ShaderEffect::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+ return false; // all properties cannot be used as constraint input
}
Property::Type ShaderEffect::GetDefaultPropertyType(Property::Index index) const
{
if( index < DEFAULT_PROPERTY_COUNT )
{
- return DEFAULT_PROPERTY_TYPES[index];
+ return DEFAULT_PROPERTY_DETAILS[index].type;
}
else
{
std::string vertex = GetShader("vertex", propertyValue);
std::string fragment = GetShader("fragment", propertyValue);
+ GeometryType geometryType = GEOMETRY_TYPE_IMAGE;
+
if( propertyValue.HasKey("geometry-type") )
{
- GeometryType geometryType = GEOMETRY_TYPE_IMAGE;
Property::Value geometryValue = propertyValue.GetValue("geometry-type");
DALI_ASSERT_ALWAYS(geometryValue.GetType() == Property::STRING && "Geometry type is not a string" );
{
geometryType = GEOMETRY_TYPE_TEXT;
}
- else if( s == "GEOMETRY_TYPE_MESH")
+ else if( s == "GEOMETRY_TYPE_UNTEXTURED_MESH")
{
- geometryType = GEOMETRY_TYPE_MESH;
+ geometryType = GEOMETRY_TYPE_UNTEXTURED_MESH;
}
else if( s == "GEOMETRY_TYPE_TEXTURED_MESH")
{
{
DALI_ASSERT_ALWAYS(!"Geometry type unknown" );
}
-
- SetShaderProgram( vertexPrefix, vertex, fragmentPrefix, fragment, geometryType, ShaderEffectPtr(this) );
}
+ SetPrograms( geometryType, vertexPrefix, fragmentPrefix, vertex, fragment );
break;
}
{
hint = Dali::ShaderEffect::HINT_BLENDING;
}
+ else if(s == "HINT_DOESNT_MODIFY_GEOMETRY")
+ {
+ hint = Dali::ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY;
+ }
else
{
DALI_ASSERT_ALWAYS(!"Geometry hint unknown" );
default:
{
- DALI_ASSERT_ALWAYS(false && "ShaderEffect property enumeration out of range"); // should not come here
- break;
- }
- }
-}
-
-void ShaderEffect::SetCustomProperty( Property::Index /* index */, const CustomProperty& entry, const Property::Value& value )
-{
- DALI_ASSERT_ALWAYS(entry.IsAnimatable() && "shader effect has only animatable properties");
-
- switch ( entry.type )
- {
- case Property::BOOLEAN:
- {
- AnimatableProperty<bool>* property = dynamic_cast< AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
-
- // property is being used in a separate thread; queue a message to set the property
- BakeMessage<bool>( mUpdateManager.GetEventToUpdate(), *property, value.Get<bool>() );
- break;
- }
-
- case Property::FLOAT:
- {
- AnimatableProperty<float>* property = dynamic_cast< AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
-
- // property is being used in a separate thread; queue a message to set the property
- BakeMessage<float>( mUpdateManager.GetEventToUpdate(), *property, value.Get<float>() );
- break;
- }
-
- case Property::VECTOR2:
- {
- AnimatableProperty<Vector2>* property = dynamic_cast< AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
-
- // property is being used in a separate thread; queue a message to set the property
- BakeMessage<Vector2>( mUpdateManager.GetEventToUpdate(), *property, value.Get<Vector2>() );
- break;
- }
-
- case Property::VECTOR3:
- {
- AnimatableProperty<Vector3>* property = dynamic_cast< AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
-
- // property is being used in a separate thread; queue a message to set the property
- BakeMessage<Vector3>( mUpdateManager.GetEventToUpdate(), *property, value.Get<Vector3>() );
- break;
- }
-
- case Property::VECTOR4:
- {
- AnimatableProperty<Vector4>* property = dynamic_cast< AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
-
- // property is being used in a separate thread; queue a message to set the property
- BakeMessage<Vector4>( mUpdateManager.GetEventToUpdate(), *property, value.Get<Vector4>() );
- break;
- }
-
- case Property::ROTATION:
- {
- AnimatableProperty<Quaternion>* property = dynamic_cast< AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
-
- // property is being used in a separate thread; queue a message to set the property
- BakeMessage<Quaternion>( mUpdateManager.GetEventToUpdate(), *property, value.Get<Quaternion>() );
- break;
- }
-
- case Property::MATRIX:
- {
- AnimatableProperty<Matrix>* property = dynamic_cast< AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
-
- // property is being used in a separate thread; queue a message to set the property
- BakeMessage<Matrix>( mUpdateManager.GetEventToUpdate(), *property, value.Get<Matrix>() );
- break;
- }
-
- case Property::MATRIX3:
- {
- AnimatableProperty<Matrix3>* property = dynamic_cast< AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
- DALI_ASSERT_DEBUG( NULL != property );
-
- // property is being used in a separate thread; queue a message to set the property
- BakeMessage<Matrix3>( mUpdateManager.GetEventToUpdate(), *property, value.Get<Matrix3>() );
- break;
- }
-
- default:
- {
- DALI_ASSERT_ALWAYS(false && "Property type enumeration out of bounds"); // should not come here
+ // nothing to do
break;
}
}
return Property::Value();
}
-void ShaderEffect::InstallSceneObjectProperty( PropertyBase& newProperty, const std::string& name, unsigned int index )
+void ShaderEffect::NotifyScenePropertyInstalled( const SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index )
{
// Warning - the property is added to the Shader object in the Update thread and the meta-data is added in the Render thread (through a secondary message)
- // mSceneObject is being used in a separate thread; queue a message to add the property
- InstallCustomPropertyMessage( mUpdateManager.GetEventToUpdate(), *mSceneObject, newProperty ); // Message takes ownership
-
// mSceneObject requires metadata for each custom property (uniform)
UniformMeta* meta = UniformMeta::New( name, newProperty, Dali::ShaderEffect::COORDINATE_TYPE_DEFAULT );
// mSceneObject is being used in a separate thread; queue a message to add the property
InstallUniformMetaMessage( mUpdateManager.GetEventToUpdate(), *mSceneObject, *meta ); // Message takes ownership
-
- // Add entry to the metadata lookup
- mCustomMetadata[index] = meta;
}
const SceneGraph::PropertyOwner* ShaderEffect::GetSceneObject() const
const PropertyBase* ShaderEffect::GetSceneObjectAnimatableProperty( Property::Index index ) const
{
- CustomPropertyLookup::const_iterator entry = GetCustomPropertyLookup().find( index );
-
- DALI_ASSERT_ALWAYS( GetCustomPropertyLookup().end() != entry && "Property index is invalid" );
-
- DALI_ASSERT_ALWAYS( entry->second.IsAnimatable() && "shader effect has only animatable properties" );
-
- return dynamic_cast<const PropertyBase*>( entry->second.GetSceneGraphProperty() );
+ CustomProperty* custom = FindCustomProperty( index );
+ DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
+ return custom->GetSceneGraphProperty();
}
const PropertyInputImpl* ShaderEffect::GetSceneObjectInputProperty( Property::Index index ) const
{
- CustomPropertyLookup::const_iterator entry = GetCustomPropertyLookup().find( index );
-
- DALI_ASSERT_ALWAYS( GetCustomPropertyLookup().end() != entry && "Property index is invalid" );
-
- DALI_ASSERT_ALWAYS( entry->second.IsAnimatable() && "shader effect has only animatable properties" );
-
- return entry->second.GetSceneGraphProperty();
+ return GetSceneObjectAnimatableProperty( index );
}
} // namespace Internal