Merge "Add ECORE_IMF_CALLBACK_SELECTION_SET to IMFContext" into devel/master
[platform/core/uifw/dali-toolkit.git] / dali-scene-loader / public-api / shader-definition.cpp
1 /*
2  * Copyright (c) 2021 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 const std::string SHADER_HINT_OUTPUT_IS_TRANSPARENT("OUTPUT_IS_TRANSPARENT"); ///< Might generate transparent alpha from opaque inputs.
29 const std::string SHADER_HINT_MODIFIES_GEOMETRY("MODIFIES_GEOMETRY");         ///< Might change position of vertices, this option disables any culling optimizations.
30
31 } // namespace
32
33 ShaderDefinition::ShaderDefinition(const ShaderDefinition& other)
34 : mRendererState(other.mRendererState),
35   mVertexShaderPath(other.mVertexShaderPath),
36   mFragmentShaderPath(other.mFragmentShaderPath),
37   mDefines(other.mDefines),
38   mHints(other.mHints),
39   mUniforms(other.mUniforms)
40 {
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 '" << shadersPath + mFragmentShaderPath << "'.";
99     }
100   }
101   else
102   {
103     ExceptionFlinger(ASSERT_LOCATION) << "Failed to load shader source from '" << shadersPath + mVertexShaderPath << "'.";
104   }
105   return raw;
106 }
107
108 Shader ShaderDefinition::Load(RawData&& raw) const
109 {
110   uint32_t hints = Shader::Hint::NONE;
111   for(const auto& hint : mHints)
112   {
113     if(hint == SHADER_HINT_OUTPUT_IS_TRANSPARENT)
114     {
115       hints |= Shader::Hint::OUTPUT_IS_TRANSPARENT;
116     }
117     else if(hint == SHADER_HINT_MODIFIES_GEOMETRY)
118     {
119       hints |= Shader::Hint::MODIFIES_GEOMETRY;
120     }
121   }
122
123   Shader shader = Shader::New(raw.mVertexShaderSource, raw.mFragmentShaderSource, static_cast<Shader::Hint::Value>(hints));
124   for(Property::Map::SizeType i0 = 0, i1 = mUniforms.Count(); i0 != i1; ++i0)
125   {
126     auto pair = mUniforms.GetKeyValue(i0);
127     DALI_ASSERT_ALWAYS(pair.first.type == Property::Key::STRING);
128     shader.RegisterProperty(pair.first.stringKey, pair.second);
129   }
130
131   return shader;
132 }
133
134 } // namespace SceneLoader
135 } // namespace Dali