2 * Copyright (c) 2021 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.
19 #include <dali/internal/event/rendering/shader-impl.h> // Dali::Internal::Shader
22 #include <dali/devel-api/scripting/scripting.h>
23 #include <dali/internal/event/common/property-helper.h> // DALI_PROPERTY_TABLE_BEGIN, DALI_PROPERTY, DALI_PROPERTY_TABLE_END
24 #include <dali/internal/event/common/thread-local-storage.h>
25 #include <dali/internal/event/effects/shader-factory.h>
26 #include <dali/internal/update/manager/update-manager.h>
27 #include <dali/public-api/object/type-registry.h>
36 * |name |type |writable|animatable|constraint-input|enum for index-checking|
38 DALI_PROPERTY_TABLE_BEGIN
39 DALI_PROPERTY("program", MAP, true, false, false, Dali::Shader::Property::PROGRAM)
40 DALI_PROPERTY_TABLE_END(DEFAULT_ACTOR_PROPERTY_START_INDEX, ShaderDefaultProperties)
42 Dali::Scripting::StringEnum ShaderHintsTable[] =
43 {{"NONE", Dali::Shader::Hint::NONE},
44 {"OUTPUT_IS_TRANSPARENT", Dali::Shader::Hint::OUTPUT_IS_TRANSPARENT},
45 {"MODIFIES_GEOMETRY", Dali::Shader::Hint::MODIFIES_GEOMETRY}};
47 const uint32_t ShaderHintsTableSize = static_cast<uint32_t>(sizeof(ShaderHintsTable) / sizeof(ShaderHintsTable[0]));
51 return Dali::BaseHandle();
54 TypeRegistration mType(typeid(Dali::Shader), typeid(Dali::Handle), Create, ShaderDefaultProperties);
56 #define TOKEN_STRING(x) (#x)
58 void AppendString(std::string& to, const std::string& append)
67 Property::Value HintString(const Dali::Shader::Hint::Value& hints)
71 if(hints == Dali::Shader::Hint::NONE)
76 if(hints & Dali::Shader::Hint::OUTPUT_IS_TRANSPARENT)
78 AppendString(s, "OUTPUT_IS_TRANSPARENT");
81 if(hints & Dali::Shader::Hint::MODIFIES_GEOMETRY)
83 AppendString(s, "MODIFIES_GEOMETRY");
86 return Property::Value(s);
89 } // unnamed namespace
91 ShaderPtr Shader::New(std::string_view vertexShader,
92 std::string_view fragmentShader,
93 Dali::Shader::Hint::Value hints)
95 // create scene object first so it's guaranteed to exist for the event side
96 auto sceneObject = new SceneGraph::Shader(hints);
97 OwnerPointer<SceneGraph::Shader> transferOwnership(sceneObject);
98 // pass the pointer to base for message passing
99 ShaderPtr shader(new Shader(sceneObject));
100 // transfer scene object ownership to update manager
101 auto&& services = shader->GetEventThreadServices();
102 SceneGraph::UpdateManager& updateManager = services.GetUpdateManager();
103 AddShaderMessage(updateManager, transferOwnership);
105 services.RegisterObject(shader.Get());
106 shader->SetShader(vertexShader, fragmentShader, hints);
111 const SceneGraph::Shader& Shader::GetShaderSceneObject() const
113 return static_cast<const SceneGraph::Shader&>(GetSceneObject());
116 void Shader::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue)
120 case Dali::Shader::Property::PROGRAM:
122 if(propertyValue.GetType() == Property::MAP)
124 const Dali::Property::Map* map = propertyValue.GetMap();
128 std::string fragment;
129 Dali::Shader::Hint::Value hints(Dali::Shader::Hint::NONE);
131 if(Property::Value* value = map->Find("vertex"))
133 vertex = value->Get<std::string>();
136 if(Property::Value* value = map->Find("fragment"))
138 fragment = value->Get<std::string>();
141 if(Property::Value* value = map->Find("hints"))
143 static_cast<void>( // ignore return
144 Scripting::GetEnumeration<Dali::Shader::Hint::Value>(value->Get<std::string>().c_str(),
146 ShaderHintsTableSize,
150 SetShader(vertex, fragment, hints);
155 DALI_LOG_WARNING("Shader program property should be a map\n");
162 Property::Value Shader::GetDefaultProperty(Property::Index index) const
164 Property::Value value;
168 case Dali::Shader::Property::PROGRAM:
170 Dali::Property::Map map;
173 map["vertex"] = Property::Value(mShaderData->GetVertexShader());
174 map["fragment"] = Property::Value(mShaderData->GetFragmentShader());
175 map["hints"] = HintString(mShaderData->GetHints());
185 Property::Value Shader::GetDefaultPropertyCurrentValue(Property::Index index) const
187 return GetDefaultProperty(index); // Event-side only properties
190 Shader::Shader(const SceneGraph::Shader* sceneObject)
191 : Object(sceneObject),
196 void Shader::SetShader(std::string_view vertexSource,
197 std::string_view fragmentSource,
198 Dali::Shader::Hint::Value hints)
200 // Try to load a pre-compiled shader binary for the source pair:
201 ThreadLocalStorage& tls = ThreadLocalStorage::Get();
202 ShaderFactory& shaderFactory = tls.GetShaderFactory();
204 mShaderData = shaderFactory.Load(vertexSource, fragmentSource, hints, shaderHash);
206 // Add shader data to scene-object
208 SceneGraph::SetShaderDataMessage(GetEventThreadServices(), GetShaderSceneObject(), mShaderData);
213 if(EventThreadServices::IsCoreRunning())
215 EventThreadServices& eventThreadServices = GetEventThreadServices();
216 SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
217 RemoveShaderMessage(updateManager, &GetShaderSceneObject());
219 eventThreadServices.UnregisterObject(this);
223 std::string Shader::GetShaderVersionPrefix()
225 Dali::Internal::ThreadLocalStorage& tls = Dali::Internal::ThreadLocalStorage::Get();
226 return tls.GetShaderVersionPrefix();
229 std::string Shader::GetVertexShaderPrefix()
231 Dali::Internal::ThreadLocalStorage& tls = Dali::Internal::ThreadLocalStorage::Get();
232 return tls.GetVertexShaderPrefix();
235 std::string Shader::GetFragmentShaderPrefix()
237 Dali::Internal::ThreadLocalStorage& tls = Dali::Internal::ThreadLocalStorage::Get();
238 return tls.GetFragmentShaderPrefix();
241 } // namespace Internal