1 : //
2 : // Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
3 : // Use of this source code is governed by a BSD-style license that can be
4 : // found in the LICENSE file.
5 : //
6 :
7 : //
8 : // Implement the top-level of interface to the compiler,
9 : // as defined in ShaderLang.h
10 : //
11 :
12 : #include "GLSLANG/ShaderLang.h"
13 :
14 : #include "compiler/InitializeDll.h"
15 : #include "compiler/preprocessor/length_limits.h"
16 : #include "compiler/ShHandle.h"
17 :
18 : //
19 : // This is the platform independent interface between an OGL driver
20 : // and the shading language compiler.
21 : //
22 :
23 0 : static bool checkActiveUniformAndAttribMaxLengths(const ShHandle handle,
24 : int expectedValue)
25 : {
26 0 : int activeUniformLimit = 0;
27 0 : ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
28 0 : int activeAttribLimit = 0;
29 0 : ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
30 0 : return (expectedValue == activeUniformLimit && expectedValue == activeAttribLimit);
31 : }
32 :
33 0 : static bool checkMappedNameMaxLength(const ShHandle handle, int expectedValue)
34 : {
35 0 : int mappedNameMaxLength = 0;
36 0 : ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength);
37 0 : return (expectedValue == mappedNameMaxLength);
38 : }
39 :
40 0 : static void getVariableInfo(ShShaderInfo varType,
41 : const ShHandle handle,
42 : int index,
43 : int* length,
44 : int* size,
45 : ShDataType* type,
46 : char* name,
47 : char* mappedName)
48 : {
49 0 : if (!handle || !size || !type || !name)
50 0 : return;
51 0 : ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
52 : (varType == SH_ACTIVE_UNIFORMS));
53 :
54 0 : TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
55 0 : TCompiler* compiler = base->getAsCompiler();
56 0 : if (compiler == 0)
57 0 : return;
58 :
59 : const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ?
60 0 : compiler->getAttribs() : compiler->getUniforms();
61 0 : if (index < 0 || index >= static_cast<int>(varList.size()))
62 0 : return;
63 :
64 0 : const TVariableInfo& varInfo = varList[index];
65 0 : if (length) *length = varInfo.name.size();
66 0 : *size = varInfo.size;
67 0 : *type = varInfo.type;
68 :
69 : // This size must match that queried by
70 : // SH_ACTIVE_UNIFORM_MAX_LENGTH and SH_ACTIVE_ATTRIBUTE_MAX_LENGTH
71 : // in ShGetInfo, below.
72 0 : int activeUniformAndAttribLength = 1 + MAX_SYMBOL_NAME_LEN;
73 0 : ASSERT(checkActiveUniformAndAttribMaxLengths(handle, activeUniformAndAttribLength));
74 0 : strncpy(name, varInfo.name.c_str(), activeUniformAndAttribLength);
75 0 : name[activeUniformAndAttribLength - 1] = 0;
76 0 : if (mappedName) {
77 : // This size must match that queried by
78 : // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
79 0 : int maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN;
80 0 : ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength));
81 0 : strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength);
82 0 : mappedName[maxMappedNameLength - 1] = 0;
83 : }
84 : }
85 :
86 : //
87 : // Driver must call this first, once, before doing any other
88 : // compiler operations.
89 : //
90 0 : int ShInitialize()
91 : {
92 0 : if (!InitProcess())
93 0 : return 0;
94 :
95 0 : return 1;
96 : }
97 :
98 : //
99 : // Cleanup symbol tables
100 : //
101 0 : int ShFinalize()
102 : {
103 0 : if (!DetachProcess())
104 0 : return 0;
105 :
106 0 : return 1;
107 : }
108 :
109 : //
110 : // Initialize built-in resources with minimum expected values.
111 : //
112 0 : void ShInitBuiltInResources(ShBuiltInResources* resources)
113 : {
114 : // Constants.
115 0 : resources->MaxVertexAttribs = 8;
116 0 : resources->MaxVertexUniformVectors = 128;
117 0 : resources->MaxVaryingVectors = 8;
118 0 : resources->MaxVertexTextureImageUnits = 0;
119 0 : resources->MaxCombinedTextureImageUnits = 8;
120 0 : resources->MaxTextureImageUnits = 8;
121 0 : resources->MaxFragmentUniformVectors = 16;
122 0 : resources->MaxDrawBuffers = 1;
123 :
124 : // Extensions.
125 0 : resources->OES_standard_derivatives = 0;
126 0 : resources->OES_EGL_image_external = 0;
127 0 : resources->ARB_texture_rectangle = 0;
128 0 : }
129 :
130 : //
131 : // Driver calls these to create and destroy compiler objects.
132 : //
133 0 : ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
134 : ShShaderOutput output,
135 : const ShBuiltInResources* resources)
136 : {
137 0 : if (!InitThread())
138 0 : return 0;
139 :
140 0 : TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
141 0 : TCompiler* compiler = base->getAsCompiler();
142 0 : if (compiler == 0)
143 0 : return 0;
144 :
145 : // Generate built-in symbol table.
146 0 : if (!compiler->Init(*resources)) {
147 0 : ShDestruct(base);
148 0 : return 0;
149 : }
150 :
151 0 : return reinterpret_cast<void*>(base);
152 : }
153 :
154 0 : void ShDestruct(ShHandle handle)
155 : {
156 0 : if (handle == 0)
157 0 : return;
158 :
159 0 : TShHandleBase* base = static_cast<TShHandleBase*>(handle);
160 :
161 0 : if (base->getAsCompiler())
162 0 : DeleteCompiler(base->getAsCompiler());
163 : }
164 :
165 : //
166 : // Do an actual compile on the given strings. The result is left
167 : // in the given compile object.
168 : //
169 : // Return: The return value of ShCompile is really boolean, indicating
170 : // success or failure.
171 : //
172 0 : int ShCompile(
173 : const ShHandle handle,
174 : const char* const shaderStrings[],
175 : const int numStrings,
176 : int compileOptions)
177 : {
178 0 : if (!InitThread())
179 0 : return 0;
180 :
181 0 : if (handle == 0)
182 0 : return 0;
183 :
184 0 : TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
185 0 : TCompiler* compiler = base->getAsCompiler();
186 0 : if (compiler == 0)
187 0 : return 0;
188 :
189 0 : bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
190 0 : return success ? 1 : 0;
191 : }
192 :
193 0 : void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params)
194 : {
195 0 : if (!handle || !params)
196 0 : return;
197 :
198 0 : TShHandleBase* base = static_cast<TShHandleBase*>(handle);
199 0 : TCompiler* compiler = base->getAsCompiler();
200 0 : if (!compiler) return;
201 :
202 0 : switch(pname)
203 : {
204 : case SH_INFO_LOG_LENGTH:
205 0 : *params = compiler->getInfoSink().info.size() + 1;
206 0 : break;
207 : case SH_OBJECT_CODE_LENGTH:
208 0 : *params = compiler->getInfoSink().obj.size() + 1;
209 0 : break;
210 : case SH_ACTIVE_UNIFORMS:
211 0 : *params = compiler->getUniforms().size();
212 0 : break;
213 : case SH_ACTIVE_UNIFORM_MAX_LENGTH:
214 0 : *params = 1 + MAX_SYMBOL_NAME_LEN;
215 0 : break;
216 : case SH_ACTIVE_ATTRIBUTES:
217 0 : *params = compiler->getAttribs().size();
218 0 : break;
219 : case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
220 0 : *params = 1 + MAX_SYMBOL_NAME_LEN;
221 0 : break;
222 : case SH_MAPPED_NAME_MAX_LENGTH:
223 : // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
224 : // handle array and struct dereferences.
225 0 : *params = 1 + MAX_SYMBOL_NAME_LEN;
226 0 : break;
227 0 : default: UNREACHABLE();
228 : }
229 : }
230 :
231 : //
232 : // Return any compiler log of messages for the application.
233 : //
234 0 : void ShGetInfoLog(const ShHandle handle, char* infoLog)
235 : {
236 0 : if (!handle || !infoLog)
237 0 : return;
238 :
239 0 : TShHandleBase* base = static_cast<TShHandleBase*>(handle);
240 0 : TCompiler* compiler = base->getAsCompiler();
241 0 : if (!compiler) return;
242 :
243 0 : TInfoSink& infoSink = compiler->getInfoSink();
244 0 : strcpy(infoLog, infoSink.info.c_str());
245 : }
246 :
247 : //
248 : // Return any object code.
249 : //
250 0 : void ShGetObjectCode(const ShHandle handle, char* objCode)
251 : {
252 0 : if (!handle || !objCode)
253 0 : return;
254 :
255 0 : TShHandleBase* base = static_cast<TShHandleBase*>(handle);
256 0 : TCompiler* compiler = base->getAsCompiler();
257 0 : if (!compiler) return;
258 :
259 0 : TInfoSink& infoSink = compiler->getInfoSink();
260 0 : strcpy(objCode, infoSink.obj.c_str());
261 : }
262 :
263 0 : void ShGetActiveAttrib(const ShHandle handle,
264 : int index,
265 : int* length,
266 : int* size,
267 : ShDataType* type,
268 : char* name,
269 : char* mappedName)
270 : {
271 : getVariableInfo(SH_ACTIVE_ATTRIBUTES,
272 0 : handle, index, length, size, type, name, mappedName);
273 0 : }
274 :
275 0 : void ShGetActiveUniform(const ShHandle handle,
276 : int index,
277 : int* length,
278 : int* size,
279 : ShDataType* type,
280 : char* name,
281 : char* mappedName)
282 : {
283 : getVariableInfo(SH_ACTIVE_UNIFORMS,
284 0 : handle, index, length, size, type, name, mappedName);
285 0 : }
|