Replace std::string global variables with C-style string.
[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 char* SHADER_HINT_OUTPUT_IS_TRANSPARENT("OUTPUT_IS_TRANSPARENT"); ///< Might generate transparent alpha from opaque inputs.
32 const char* SHADER_HINT_MODIFIES_GEOMETRY("MODIFIES_GEOMETRY");         ///< Might change position of vertices, this option disables any culling optimizations.
33 } // namespace
34
35 ShaderDefinition::ShaderDefinition(const ShaderDefinition& other)
36 : mRendererState(other.mRendererState),
37   mVertexShaderPath(other.mVertexShaderPath),
38   mFragmentShaderPath(other.mFragmentShaderPath),
39   mDefines(other.mDefines),
40   mHints(other.mHints),
41   mUniforms(other.mUniforms),
42   mUseBuiltInShader(other.mUseBuiltInShader)
43 {
44 }
45
46 void ShaderDefinition::ApplyDefine(std::string& shaderCode, const std::string& definevar)
47 {
48   const std::string IF_1 = "#if 1";
49
50   std::size_t found = shaderCode.find(definevar);
51   while(found != std::string::npos)
52   {
53     // Greater then "@" character means is a letter,
54     // therefore is not has the definevar we looking for.
55     if((found + definevar.length()) < shaderCode.length() && shaderCode.at(found + definevar.length()) > '@')
56     {
57       found = shaderCode.find(definevar, found + definevar.length());
58       continue;
59     }
60     if(found > 0u && shaderCode.at(found - 1) > '@')
61     {
62       found = shaderCode.find(definevar, found + definevar.length());
63       continue;
64     }
65
66     std::size_t defidx     = shaderCode.rfind("#ifdef", found);
67     std::size_t newlineidx = shaderCode.rfind("\n", found);
68     if(newlineidx < defidx && defidx != std::string::npos)
69     {
70       shaderCode.replace(defidx, found - defidx + definevar.length(), IF_1);
71       found = defidx + IF_1.length();
72     }
73     else
74     {
75       found += definevar.length();
76     }
77     found = shaderCode.find(definevar, found);
78   }
79 }
80
81 ShaderDefinition::RawData
82 ShaderDefinition::LoadRaw(const std::string& shadersPath) const
83 {
84   RawData raw;
85
86   bool fail = false;
87   if(!mUseBuiltInShader)
88   {
89     raw.mVertexShaderSource = LoadTextFile((shadersPath + mVertexShaderPath).c_str(), &fail);
90     if(!fail)
91     {
92       raw.mFragmentShaderSource = LoadTextFile((shadersPath + mFragmentShaderPath).c_str(), &fail);
93       if(fail)
94       {
95         ExceptionFlinger(ASSERT_LOCATION) << "Failed to load shader source from '" << shadersPath + mFragmentShaderPath << "'.";
96       }
97     }
98     else
99     {
100       ExceptionFlinger(ASSERT_LOCATION) << "Failed to load shader source from '" << shadersPath + mVertexShaderPath << "'.";
101     }
102   }
103   else
104   {
105     raw.mVertexShaderSource   = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_VERT.data();
106     raw.mFragmentShaderSource = SHADER_DEFAULT_PHYSICALLY_BASED_SHADER_FRAG.data();
107   }
108
109   if(!fail)
110   {
111     for(const auto& definevar : mDefines)
112     {
113       ApplyDefine(raw.mVertexShaderSource, definevar);
114       ApplyDefine(raw.mFragmentShaderSource, definevar);
115     }
116   }
117
118   return raw;
119 }
120
121 Shader ShaderDefinition::Load(RawData&& raw) const
122 {
123   uint32_t hints = Shader::Hint::NONE;
124   for(const auto& hint : mHints)
125   {
126     if(hint == SHADER_HINT_OUTPUT_IS_TRANSPARENT)
127     {
128       hints |= Shader::Hint::OUTPUT_IS_TRANSPARENT;
129     }
130     else if(hint == SHADER_HINT_MODIFIES_GEOMETRY)
131     {
132       hints |= Shader::Hint::MODIFIES_GEOMETRY;
133     }
134   }
135
136   Shader shader = Shader::New(raw.mVertexShaderSource, raw.mFragmentShaderSource, static_cast<Shader::Hint::Value>(hints));
137   for(Property::Map::SizeType i0 = 0, i1 = mUniforms.Count(); i0 != i1; ++i0)
138   {
139     auto pair = mUniforms.GetKeyValue(i0);
140     DALI_ASSERT_ALWAYS(pair.first.type == Property::Key::STRING);
141     shader.RegisterProperty(pair.first.stringKey, pair.second);
142   }
143
144   return shader;
145 }
146
147 } // namespace Loader
148 } // namespace Scene3D
149 } // namespace Dali