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