1 // Created on: 2013-09-19
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #include <Graphic3d_ShaderObject.hxx>
17 #include <OpenGl_Context.hxx>
18 #include <OpenGl_ShaderObject.hxx>
19 #include <OSD_Path.hxx>
20 #include <Standard_Assert.hxx>
21 #include <TCollection_AsciiString.hxx>
24 #include <malloc.h> // for alloca()
27 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderObject,OpenGl_Resource)
29 // =======================================================================
30 // function : CreateFromSource
32 // =======================================================================
33 Handle(Graphic3d_ShaderObject) OpenGl_ShaderObject::CreateFromSource (TCollection_AsciiString& theSource,
34 Graphic3d_TypeOfShaderObject theType,
35 const ShaderVariableList& theUniforms,
36 const ShaderVariableList& theStageInOuts,
37 const TCollection_AsciiString& theInName,
38 const TCollection_AsciiString& theOutName,
39 Standard_Integer theNbGeomInputVerts)
41 TCollection_AsciiString aSrcUniforms, aSrcInOuts, aSrcInStructs, aSrcOutStructs;
42 for (ShaderVariableList::Iterator anUniformIter (theUniforms); anUniformIter.More(); anUniformIter.Next())
44 const ShaderVariable& aVar = anUniformIter.Value();
45 if ((aVar.Stages & theType) != 0)
47 aSrcUniforms += TCollection_AsciiString("\nuniform ") + aVar.Name + ";";
50 for (ShaderVariableList::Iterator aVarListIter (theStageInOuts); aVarListIter.More(); aVarListIter.Next())
52 const ShaderVariable& aVar = aVarListIter.Value();
53 Standard_Integer aStageLower = IntegerLast(), aStageUpper = IntegerFirst();
54 Standard_Integer aNbStages = 0;
55 for (Standard_Integer aStageIter = Graphic3d_TOS_VERTEX; aStageIter <= (Standard_Integer )Graphic3d_TOS_COMPUTE; aStageIter = aStageIter << 1)
57 if ((aVar.Stages & aStageIter) != 0)
60 aStageLower = Min (aStageLower, aStageIter);
61 aStageUpper = Max (aStageUpper, aStageIter);
64 if ((Standard_Integer )theType < aStageLower
65 || (Standard_Integer )theType > aStageUpper)
70 const Standard_Boolean hasGeomStage = theNbGeomInputVerts > 0
71 && aStageLower < Graphic3d_TOS_GEOMETRY
72 && aStageUpper >= Graphic3d_TOS_GEOMETRY;
74 || !theInName.IsEmpty()
75 || !theOutName.IsEmpty())
77 if (aSrcInStructs.IsEmpty()
78 && aSrcOutStructs.IsEmpty())
80 if (theType == aStageLower)
82 aSrcOutStructs = "\nout VertexData\n{";
84 else if (theType == aStageUpper)
86 aSrcInStructs = "\nin VertexData\n{";
88 else // requires theInName/theOutName
90 aSrcInStructs = "\nin VertexData\n{";
91 aSrcOutStructs = "\nout VertexData\n{";
96 if (!aSrcInStructs.IsEmpty()
97 || !aSrcOutStructs.IsEmpty())
99 if (!aSrcInStructs.IsEmpty())
101 aSrcInStructs += TCollection_AsciiString("\n ") + aVar.Name + ";";
103 if (!aSrcOutStructs.IsEmpty())
105 aSrcOutStructs += TCollection_AsciiString("\n ") + aVar.Name + ";";
110 if (theType == aStageLower)
112 aSrcInOuts += TCollection_AsciiString("\nTHE_SHADER_OUT ") + aVar.Name + ";";
114 else if (theType == aStageUpper)
116 aSrcInOuts += TCollection_AsciiString("\nTHE_SHADER_IN ") + aVar.Name + ";";
121 if (!aSrcInStructs.IsEmpty()
122 && theType == Graphic3d_TOS_GEOMETRY)
124 aSrcInStructs += TCollection_AsciiString ("\n} ") + theInName + "[" + theNbGeomInputVerts + "];";
126 else if (!aSrcInStructs.IsEmpty())
128 aSrcInStructs += "\n}";
129 if (!theInName.IsEmpty())
131 aSrcInStructs += " ";
132 aSrcInStructs += theInName;
134 aSrcInStructs += ";";
136 else if (!aSrcOutStructs.IsEmpty())
138 aSrcOutStructs += "\n}";
139 if (!theInName.IsEmpty())
141 aSrcOutStructs += " ";
142 aSrcOutStructs += theOutName;
144 aSrcOutStructs += ";";
147 theSource.Prepend (aSrcUniforms + aSrcInStructs + aSrcOutStructs + aSrcInOuts);
148 return Graphic3d_ShaderObject::CreateFromSource (theType, theSource);
151 // =======================================================================
152 // function : OpenGl_ShaderObject
153 // purpose : Creates uninitialized shader object
154 // =======================================================================
155 OpenGl_ShaderObject::OpenGl_ShaderObject (GLenum theType)
157 myShaderID (NO_SHADER)
162 // =======================================================================
163 // function : ~OpenGl_ShaderObject
164 // purpose : Releases resources of shader object
165 // =======================================================================
166 OpenGl_ShaderObject::~OpenGl_ShaderObject()
171 // =======================================================================
172 // function : LoadSource
173 // purpose : Loads shader source code
174 // =======================================================================
175 Standard_Boolean OpenGl_ShaderObject::LoadSource (const Handle(OpenGl_Context)& theCtx,
176 const TCollection_AsciiString& theSource)
178 if (myShaderID == NO_SHADER)
180 return Standard_False;
183 const GLchar* aLines = theSource.ToCString();
184 theCtx->core20fwd->glShaderSource (myShaderID, 1, &aLines, NULL);
185 return Standard_True;
188 // =======================================================================
189 // function : Compile
190 // purpose : Compiles the shader object
191 // =======================================================================
192 Standard_Boolean OpenGl_ShaderObject::Compile (const Handle(OpenGl_Context)& theCtx)
194 if (myShaderID == NO_SHADER)
196 return Standard_False;
199 // Try to compile shader
200 theCtx->core20fwd->glCompileShader (myShaderID);
202 // Check compile status
203 GLint aStatus = GL_FALSE;
204 theCtx->core20fwd->glGetShaderiv (myShaderID, GL_COMPILE_STATUS, &aStatus);
205 return aStatus != GL_FALSE;
208 // =======================================================================
209 // function : FetchInfoLog
210 // purpose : Fetches information log of the last compile operation
211 // =======================================================================
212 Standard_Boolean OpenGl_ShaderObject::FetchInfoLog (const Handle(OpenGl_Context)& theCtx,
213 TCollection_AsciiString& theLog)
215 if (myShaderID == NO_SHADER)
217 return Standard_False;
220 // Load information log of the compiler
222 theCtx->core20fwd->glGetShaderiv (myShaderID, GL_INFO_LOG_LENGTH, &aLength);
225 GLchar* aLog = (GLchar*) alloca (aLength);
226 memset (aLog, 0, aLength);
227 theCtx->core20fwd->glGetShaderInfoLog (myShaderID, aLength, NULL, aLog);
231 return Standard_True;
234 // =======================================================================
236 // purpose : Creates new empty shader object of specified type
237 // =======================================================================
238 Standard_Boolean OpenGl_ShaderObject::Create (const Handle(OpenGl_Context)& theCtx)
240 if (myShaderID == NO_SHADER
241 && theCtx->core20fwd != NULL)
243 myShaderID = theCtx->core20fwd->glCreateShader (myType);
246 return myShaderID != NO_SHADER;
249 // =======================================================================
250 // function : Release
251 // purpose : Destroys shader object
252 // =======================================================================
253 void OpenGl_ShaderObject::Release (OpenGl_Context* theCtx)
255 if (myShaderID == NO_SHADER)
260 Standard_ASSERT_RETURN (theCtx != NULL,
261 "OpenGl_ShaderObject destroyed without GL context! Possible GPU memory leakage...",);
263 if (theCtx->core20fwd != NULL
264 && theCtx->IsValid())
266 theCtx->core20fwd->glDeleteShader (myShaderID);
268 myShaderID = NO_SHADER;