Merge "Change dali-scene-loader to dali-scene3d" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-scene3d / public-api / loader / shader-definition.cpp
1 /*
2  * Copyright (c) 2022 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 // INTERNAL INCLUDES
19 #include "dali-scene3d/public-api/loader/shader-definition.h"
20 #include <dali-scene3d/internal/graphics/builtin-shader-extern-gen.h>
21 #include "dali-scene3d/public-api/loader/utils.h"
22
23 namespace Dali
24 {
25 namespace Scene3D
26 {
27 namespace Loader
28 {
29 namespace
30 {
31 const std::string SHADER_HINT_OUTPUT_IS_TRANSPARENT("OUTPUT_IS_TRANSPARENT"); ///< Might generate transparent alpha from opaque inputs.
32 const std::string SHADER_HINT_MODIFIES_GEOMETRY("MODIFIES_GEOMETRY");         ///< Might change position of vertices, this option disables any culling optimizations.
33
34 } // namespace
35
36 ShaderDefinition::ShaderDefinition(const ShaderDefinition& other)
37 : mRendererState(other.mRendererState),
38   mVertexShaderPath(other.mVertexShaderPath),
39   mFragmentShaderPath(other.mFragmentShaderPath),
40   mDefines(other.mDefines),
41   mHints(other.mHints),
42   mUniforms(other.mUniforms),
43   mUseBuiltInShader(other.mUseBuiltInShader)
44 {
45 }
46
47 void ShaderDefinition::ApplyDefine(std::string& shaderCode, const std::string& definevar)
48 {
49   const std::string IF_1 = "#if 1";
50
51   std::size_t found = shaderCode.find(definevar);
52   while(found != std::string::npos)
53   {
54     // Greater then "@" character means is a letter,
55     // therefore is not has the definevar we looking for.
56     if((found + definevar.length()) < shaderCode.length() && shaderCode.at(found + definevar.length()) > '@')
57     {
58       found = shaderCode.find(definevar, found + definevar.length());
59       continue;
60     }
61     if(found > 0u && shaderCode.at(found - 1) > '@')
62     {
63       found = shaderCode.find(definevar, found + definevar.length());
64       continue;
65     }
66
67     std::size_t defidx     = shaderCode.rfind("#ifdef", found);
68     std::size_t newlineidx = shaderCode.rfind("\n", found);
69     if(newlineidx < defidx && defidx != std::string::npos)
70     {
71       shaderCode.replace(defidx, found - defidx + definevar.length(), IF_1);
72       found = defidx + IF_1.length();
73     }
74     else
75     {
76       found += definevar.length();
77     }
78     found = shaderCode.find(definevar, found);
79   }
80 }
81
82 ShaderDefinition::RawData
83 ShaderDefinition::LoadRaw(const std::string& shadersPath) const
84 {
85   RawData raw;
86
87   bool fail = false;
88   if(!mUseBuiltInShader)
89   {
90     raw.mVertexShaderSource = LoadTextFile((shadersPath + mVertexShaderPath).c_str(), &fail);
91     if(!fail)
92     {
93       raw.mFragmentShaderSource = LoadTextFile((shadersPath + mFragmentShaderPath).c_str(), &fail);
94       if(fail)
95       {
96         ExceptionFlinger(ASSERT_LOCATION) << "Failed to load shader source from '" << shadersPath + mFragmentShaderPath << "'.";
97       }
98     }
99     else
100     {
101       ExceptionFlinger(ASSERT_LOCATION) << "Failed to load shader source from '" << shadersPath + mVertexShaderPath << "'.";
102     }
103   }
104   else
105   {
106     raw.mVertexShaderSource   = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_VERT.data();
107     raw.mFragmentShaderSource = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_FRAG.data();
108   }
109
110   if(!fail)
111   {
112     for(auto definevar : mDefines)
113     {
114       ApplyDefine(raw.mVertexShaderSource, definevar);
115       ApplyDefine(raw.mFragmentShaderSource, definevar);
116     }
117   }
118
119   return raw;
120 }
121
122 Shader ShaderDefinition::Load(RawData&& raw) const
123 {
124   uint32_t hints = Shader::Hint::NONE;
125   for(const auto& hint : mHints)
126   {
127     if(hint == SHADER_HINT_OUTPUT_IS_TRANSPARENT)
128     {
129       hints |= Shader::Hint::OUTPUT_IS_TRANSPARENT;
130     }
131     else if(hint == SHADER_HINT_MODIFIES_GEOMETRY)
132     {
133       hints |= Shader::Hint::MODIFIES_GEOMETRY;
134     }
135   }
136
137   Shader shader = Shader::New(raw.mVertexShaderSource, raw.mFragmentShaderSource, static_cast<Shader::Hint::Value>(hints));
138   for(Property::Map::SizeType i0 = 0, i1 = mUniforms.Count(); i0 != i1; ++i0)
139   {
140     auto pair = mUniforms.GetKeyValue(i0);
141     DALI_ASSERT_ALWAYS(pair.first.type == Property::Key::STRING);
142     shader.RegisterProperty(pair.first.stringKey, pair.second);
143   }
144
145   return shader;
146 }
147
148 } // namespace Loader
149 } // namespace Scene3D
150 } // namespace Dali