0026936: Drawbacks of inlining in new type system in OCCT 7.0 -- automatic
[occt.git] / src / Graphic3d / Graphic3d_ShaderProgram.cxx
1 // Created on: 2013-09-20
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #include <Standard_Atomic.hxx>
17 #include <Standard_Assert.hxx>
18
19 #include <Graphic3d_GraphicDriver.hxx>
20 #include <Graphic3d_ShaderObject.hxx>
21 #include <Graphic3d_ShaderProgram.hxx>
22 #include <OSD_Directory.hxx>
23 #include <OSD_Environment.hxx>
24 #include <OSD_File.hxx>
25 #include <OSD_Path.hxx>
26
27 IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_ShaderProgram,Standard_Transient)
28
29 namespace
30 {
31   static volatile Standard_Integer THE_PROGRAM_OBJECT_COUNTER = 0;
32 };
33
34
35 // =======================================================================
36 // function : ShadersFolder
37 // purpose  :
38 // =======================================================================
39 const TCollection_AsciiString& Graphic3d_ShaderProgram::ShadersFolder()
40 {
41   static Standard_Boolean        THE_IS_DEFINED = Standard_False;
42   static TCollection_AsciiString THE_SHADERS_FOLDER;
43   if (!THE_IS_DEFINED)
44   {
45     THE_IS_DEFINED = Standard_True;
46     OSD_Environment aDirEnv ("CSF_ShadersDirectory");
47     THE_SHADERS_FOLDER = aDirEnv.Value();
48     if (THE_SHADERS_FOLDER.IsEmpty())
49     {
50       OSD_Environment aCasRootEnv ("CASROOT");
51       THE_SHADERS_FOLDER = aCasRootEnv.Value();
52       if (!THE_SHADERS_FOLDER.IsEmpty())
53       {
54         THE_SHADERS_FOLDER += "/src/Shaders";
55       }
56     }
57
58     if (THE_SHADERS_FOLDER.IsEmpty())
59     {
60       std::cerr << "Both environment variables CSF_ShadersDirectory and CASROOT are undefined!\n"
61                 << "At least one should be defined to use standard GLSL programs.\n";
62       Standard_Failure::Raise ("CSF_ShadersDirectory and CASROOT are undefined");
63       return THE_SHADERS_FOLDER;
64     }
65
66     const OSD_Path aDirPath (THE_SHADERS_FOLDER);
67     OSD_Directory aDir (aDirPath);
68     const TCollection_AsciiString aProgram = THE_SHADERS_FOLDER + "/Declarations.glsl";
69     OSD_File aProgramFile (aProgram);
70     if (!aDir.Exists()
71      || !aProgramFile.Exists())
72     {
73       std::cerr << "Standard GLSL programs are not found in: " << THE_SHADERS_FOLDER.ToCString() << std::endl;
74       Standard_Failure::Raise ("CSF_ShadersDirectory or CASROOT is set incorrectly");
75       return THE_SHADERS_FOLDER;
76     }
77   }
78   return THE_SHADERS_FOLDER;
79 }
80
81 // =======================================================================
82 // function : Graphic3d_ShaderProgram
83 // purpose  : Creates new empty program object
84 // =======================================================================
85 Graphic3d_ShaderProgram::Graphic3d_ShaderProgram()
86 {
87   myID = TCollection_AsciiString ("Graphic3d_ShaderProgram_")
88        + TCollection_AsciiString (Standard_Atomic_Increment (&THE_PROGRAM_OBJECT_COUNTER));
89 }
90
91 // =======================================================================
92 // function : Graphic3d_ShaderProgram
93 // purpose  :
94 // =======================================================================
95 Graphic3d_ShaderProgram::Graphic3d_ShaderProgram (const Graphic3d_ShaderProgram::ShaderName theName)
96 {
97   const TCollection_AsciiString& aShadersRoot = Graphic3d_ShaderProgram::ShadersFolder();
98   switch (theName)
99   {
100     case ShaderName_Phong:
101     {
102       myID = TCollection_AsciiString ("Graphic3d_ShaderProgram_Phong");
103       const TCollection_AsciiString aSrcVert = aShadersRoot + "/PhongShading.vs";
104       const TCollection_AsciiString aSrcFrag = aShadersRoot + "/PhongShading.fs";
105
106       if (!aSrcVert.IsEmpty()
107        && !OSD_File (aSrcVert).Exists())
108       {
109         Standard_Failure::Raise ("Graphic3d_ShaderProgram, PhongShading.vs is not found");
110         return;
111       }
112       if (!aSrcFrag.IsEmpty()
113        && !OSD_File (aSrcFrag).Exists())
114       {
115         Standard_Failure::Raise ("Graphic3d_ShaderProgram, PhongShading.fs is not found");
116         return;
117       }
118
119       AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_VERTEX,   aSrcVert));
120       AttachShader (Graphic3d_ShaderObject::CreateFromFile (Graphic3d_TOS_FRAGMENT, aSrcFrag));
121       break;
122     }
123     case ShaderName_UNKNOWN:
124     default:
125     {
126       Standard_Failure::Raise ("Graphic3d_ShaderProgram, unknown program name");
127       break;
128     }
129   }
130 }
131
132 // =======================================================================
133 // function : ~Graphic3d_ShaderProgram
134 // purpose  : Releases resources of program object
135 // =======================================================================
136 Graphic3d_ShaderProgram::~Graphic3d_ShaderProgram()
137 {
138   Destroy();
139 }
140
141 // =======================================================================
142 // function : Destroy
143 // purpose  : Releases resources of program object
144 // =======================================================================
145 void Graphic3d_ShaderProgram::Destroy() const
146 { }
147
148 // =======================================================================
149 // function : IsDone
150 // purpose  : Checks if the program object is valid or not
151 // =======================================================================
152 Standard_Boolean Graphic3d_ShaderProgram::IsDone() const
153 {
154   if (myShaderObjects.IsEmpty())
155   {
156     return Standard_False;
157   }
158
159   for (Graphic3d_ShaderObjectList::Iterator anIt (myShaderObjects); anIt.More(); anIt.Next())
160   {
161     if (!anIt.Value()->IsDone())
162       return Standard_False;
163   }
164
165   return Standard_True;
166 }
167
168 // =======================================================================
169 // function : AttachShader
170 // purpose  : Attaches shader object to the program object
171 // =======================================================================
172 Standard_Boolean Graphic3d_ShaderProgram::AttachShader (const Handle(Graphic3d_ShaderObject)& theShader)
173 {
174   if (theShader.IsNull())
175   {
176     return Standard_False;
177   }
178
179   for (Graphic3d_ShaderObjectList::Iterator anIt (myShaderObjects); anIt.More(); anIt.Next())
180   {
181     if (anIt.Value() == theShader)
182       return Standard_False;
183   }
184
185   myShaderObjects.Append (theShader);
186   return Standard_True;
187 }
188
189 // =======================================================================
190 // function : DetachShader
191 // purpose  : Detaches shader object from the program object
192 // =======================================================================
193 Standard_Boolean Graphic3d_ShaderProgram::DetachShader (const Handle(Graphic3d_ShaderObject)& theShader)
194 {
195   if (theShader.IsNull())
196   {
197     return Standard_False;
198   }
199
200   for (Graphic3d_ShaderObjectList::Iterator anIt (myShaderObjects); anIt.More(); anIt.Next())
201   {
202     if (anIt.Value() == theShader)
203     {
204       myShaderObjects.Remove (anIt);
205       return Standard_True;
206     }
207   }
208   
209   return Standard_False;
210 }
211
212 // =======================================================================
213 // function : ClearVariables
214 // purpose  : Removes all custom uniform variables from the program
215 // =======================================================================
216 void Graphic3d_ShaderProgram::ClearVariables()
217 {
218   myVariables.Clear();
219 }