Wed, 31 Dec 2014 07:16:47 +0100
Revert simplistic fix pending revisit of Mozilla integration attempt.
1 //
2 // Copyright (c) 2002-2012 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 //
7 //
8 // Implement the top-level of interface to the compiler,
9 // as defined in ShaderLang.h
10 //
12 #include "GLSLANG/ShaderLang.h"
14 #include "compiler/InitializeDll.h"
15 #include "compiler/preprocessor/length_limits.h"
16 #include "compiler/ShHandle.h"
17 #include "compiler/TranslatorHLSL.h"
19 //
20 // This is the platform independent interface between an OGL driver
21 // and the shading language compiler.
22 //
24 static bool checkActiveUniformAndAttribMaxLengths(const ShHandle handle,
25 size_t expectedValue)
26 {
27 size_t activeUniformLimit = 0;
28 ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
29 size_t activeAttribLimit = 0;
30 ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
31 return (expectedValue == activeUniformLimit && expectedValue == activeAttribLimit);
32 }
34 static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue)
35 {
36 size_t mappedNameMaxLength = 0;
37 ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength);
38 return (expectedValue == mappedNameMaxLength);
39 }
41 static void getVariableInfo(ShShaderInfo varType,
42 const ShHandle handle,
43 int index,
44 size_t* length,
45 int* size,
46 ShDataType* type,
47 char* name,
48 char* mappedName)
49 {
50 if (!handle || !size || !type || !name)
51 return;
52 ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
53 (varType == SH_ACTIVE_UNIFORMS));
55 TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
56 TCompiler* compiler = base->getAsCompiler();
57 if (compiler == 0)
58 return;
60 const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ?
61 compiler->getAttribs() : compiler->getUniforms();
62 if (index < 0 || index >= static_cast<int>(varList.size()))
63 return;
65 const TVariableInfo& varInfo = varList[index];
66 if (length) *length = varInfo.name.size();
67 *size = varInfo.size;
68 *type = varInfo.type;
70 // This size must match that queried by
71 // SH_ACTIVE_UNIFORM_MAX_LENGTH and SH_ACTIVE_ATTRIBUTE_MAX_LENGTH
72 // in ShGetInfo, below.
73 size_t activeUniformAndAttribLength = 1 + MAX_SYMBOL_NAME_LEN;
74 ASSERT(checkActiveUniformAndAttribMaxLengths(handle, activeUniformAndAttribLength));
75 strncpy(name, varInfo.name.c_str(), activeUniformAndAttribLength);
76 name[activeUniformAndAttribLength - 1] = 0;
77 if (mappedName) {
78 // This size must match that queried by
79 // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
80 size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN;
81 ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength));
82 strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength);
83 mappedName[maxMappedNameLength - 1] = 0;
84 }
85 }
87 //
88 // Driver must call this first, once, before doing any other compiler operations.
89 // Subsequent calls to this function are no-op.
90 //
91 int ShInitialize()
92 {
93 static const bool kInitialized = InitProcess();
94 return kInitialized ? 1 : 0;
95 }
97 //
98 // Cleanup symbol tables
99 //
100 int ShFinalize()
101 {
102 DetachProcess();
103 return 1;
104 }
106 //
107 // Initialize built-in resources with minimum expected values.
108 //
109 void ShInitBuiltInResources(ShBuiltInResources* resources)
110 {
111 // Constants.
112 resources->MaxVertexAttribs = 8;
113 resources->MaxVertexUniformVectors = 128;
114 resources->MaxVaryingVectors = 8;
115 resources->MaxVertexTextureImageUnits = 0;
116 resources->MaxCombinedTextureImageUnits = 8;
117 resources->MaxTextureImageUnits = 8;
118 resources->MaxFragmentUniformVectors = 16;
119 resources->MaxDrawBuffers = 1;
121 // Extensions.
122 resources->OES_standard_derivatives = 0;
123 resources->OES_EGL_image_external = 0;
124 resources->ARB_texture_rectangle = 0;
125 resources->EXT_draw_buffers = 0;
126 resources->EXT_frag_depth = 0;
128 // Disable highp precision in fragment shader by default.
129 resources->FragmentPrecisionHigh = 0;
131 // Disable name hashing by default.
132 resources->HashFunction = NULL;
134 resources->ArrayIndexClampingStrategy = SH_CLAMP_WITH_CLAMP_INTRINSIC;
135 }
137 //
138 // Driver calls these to create and destroy compiler objects.
139 //
140 ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
141 ShShaderOutput output,
142 const ShBuiltInResources* resources)
143 {
144 TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec, output));
145 TCompiler* compiler = base->getAsCompiler();
146 if (compiler == 0)
147 return 0;
149 // Generate built-in symbol table.
150 if (!compiler->Init(*resources)) {
151 ShDestruct(base);
152 return 0;
153 }
155 return reinterpret_cast<void*>(base);
156 }
158 void ShDestruct(ShHandle handle)
159 {
160 if (handle == 0)
161 return;
163 TShHandleBase* base = static_cast<TShHandleBase*>(handle);
165 if (base->getAsCompiler())
166 DeleteCompiler(base->getAsCompiler());
167 }
169 //
170 // Do an actual compile on the given strings. The result is left
171 // in the given compile object.
172 //
173 // Return: The return value of ShCompile is really boolean, indicating
174 // success or failure.
175 //
176 int ShCompile(
177 const ShHandle handle,
178 const char* const shaderStrings[],
179 size_t numStrings,
180 int compileOptions)
181 {
182 if (handle == 0)
183 return 0;
185 TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
186 TCompiler* compiler = base->getAsCompiler();
187 if (compiler == 0)
188 return 0;
190 bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
191 return success ? 1 : 0;
192 }
194 void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params)
195 {
196 if (!handle || !params)
197 return;
199 TShHandleBase* base = static_cast<TShHandleBase*>(handle);
200 TCompiler* compiler = base->getAsCompiler();
201 if (!compiler) return;
203 switch(pname)
204 {
205 case SH_INFO_LOG_LENGTH:
206 *params = compiler->getInfoSink().info.size() + 1;
207 break;
208 case SH_OBJECT_CODE_LENGTH:
209 *params = compiler->getInfoSink().obj.size() + 1;
210 break;
211 case SH_ACTIVE_UNIFORMS:
212 *params = compiler->getUniforms().size();
213 break;
214 case SH_ACTIVE_UNIFORM_MAX_LENGTH:
215 *params = 1 + MAX_SYMBOL_NAME_LEN;
216 break;
217 case SH_ACTIVE_ATTRIBUTES:
218 *params = compiler->getAttribs().size();
219 break;
220 case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
221 *params = 1 + MAX_SYMBOL_NAME_LEN;
222 break;
223 case SH_MAPPED_NAME_MAX_LENGTH:
224 // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
225 // handle array and struct dereferences.
226 *params = 1 + MAX_SYMBOL_NAME_LEN;
227 break;
228 case SH_NAME_MAX_LENGTH:
229 *params = 1 + MAX_SYMBOL_NAME_LEN;
230 break;
231 case SH_HASHED_NAME_MAX_LENGTH:
232 if (compiler->getHashFunction() == NULL) {
233 *params = 0;
234 } else {
235 // 64 bits hashing output requires 16 bytes for hex
236 // representation.
237 const char HashedNamePrefix[] = HASHED_NAME_PREFIX;
238 *params = 16 + sizeof(HashedNamePrefix);
239 }
240 break;
241 case SH_HASHED_NAMES_COUNT:
242 *params = compiler->getNameMap().size();
243 break;
244 default: UNREACHABLE();
245 }
246 }
248 //
249 // Return any compiler log of messages for the application.
250 //
251 void ShGetInfoLog(const ShHandle handle, char* infoLog)
252 {
253 if (!handle || !infoLog)
254 return;
256 TShHandleBase* base = static_cast<TShHandleBase*>(handle);
257 TCompiler* compiler = base->getAsCompiler();
258 if (!compiler) return;
260 TInfoSink& infoSink = compiler->getInfoSink();
261 strcpy(infoLog, infoSink.info.c_str());
262 }
264 //
265 // Return any object code.
266 //
267 void ShGetObjectCode(const ShHandle handle, char* objCode)
268 {
269 if (!handle || !objCode)
270 return;
272 TShHandleBase* base = static_cast<TShHandleBase*>(handle);
273 TCompiler* compiler = base->getAsCompiler();
274 if (!compiler) return;
276 TInfoSink& infoSink = compiler->getInfoSink();
277 strcpy(objCode, infoSink.obj.c_str());
278 }
280 void ShGetActiveAttrib(const ShHandle handle,
281 int index,
282 size_t* length,
283 int* size,
284 ShDataType* type,
285 char* name,
286 char* mappedName)
287 {
288 getVariableInfo(SH_ACTIVE_ATTRIBUTES,
289 handle, index, length, size, type, name, mappedName);
290 }
292 void ShGetActiveUniform(const ShHandle handle,
293 int index,
294 size_t* length,
295 int* size,
296 ShDataType* type,
297 char* name,
298 char* mappedName)
299 {
300 getVariableInfo(SH_ACTIVE_UNIFORMS,
301 handle, index, length, size, type, name, mappedName);
302 }
304 void ShGetNameHashingEntry(const ShHandle handle,
305 int index,
306 char* name,
307 char* hashedName)
308 {
309 if (!handle || !name || !hashedName || index < 0)
310 return;
312 TShHandleBase* base = static_cast<TShHandleBase*>(handle);
313 TCompiler* compiler = base->getAsCompiler();
314 if (!compiler) return;
316 const NameMap& nameMap = compiler->getNameMap();
317 if (index >= static_cast<int>(nameMap.size()))
318 return;
320 NameMap::const_iterator it = nameMap.begin();
321 for (int i = 0; i < index; ++i)
322 ++it;
324 size_t len = it->first.length() + 1;
325 size_t max_len = 0;
326 ShGetInfo(handle, SH_NAME_MAX_LENGTH, &max_len);
327 if (len > max_len) {
328 ASSERT(false);
329 len = max_len;
330 }
331 strncpy(name, it->first.c_str(), len);
332 // To be on the safe side in case the source is longer than expected.
333 name[len - 1] = '\0';
335 len = it->second.length() + 1;
336 max_len = 0;
337 ShGetInfo(handle, SH_HASHED_NAME_MAX_LENGTH, &max_len);
338 if (len > max_len) {
339 ASSERT(false);
340 len = max_len;
341 }
342 strncpy(hashedName, it->second.c_str(), len);
343 // To be on the safe side in case the source is longer than expected.
344 hashedName[len - 1] = '\0';
345 }
347 void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params)
348 {
349 if (!handle || !params)
350 return;
352 TShHandleBase* base = static_cast<TShHandleBase*>(handle);
353 TranslatorHLSL* translator = base->getAsTranslatorHLSL();
354 if (!translator) return;
356 switch(pname)
357 {
358 case SH_ACTIVE_UNIFORMS_ARRAY:
359 *params = (void*)&translator->getUniforms();
360 break;
361 default: UNREACHABLE();
362 }
363 }