1//
2// Copyright (c) 2002-2010 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/ShHandle.h"
16
17//
18// This is the platform independent interface between an OGL driver
19// and the shading language compiler.
20//
21
22static int getVariableMaxLength(const TVariableInfoList& varList)
23{
24    TString::size_type maxLen = 0;
25    for (TVariableInfoList::const_iterator i = varList.begin();
26         i != varList.end(); ++i)
27    {
28        maxLen = std::max(maxLen, i->name.size());
29    }
30    // Add 1 to include null-termination character.
31    return static_cast<int>(maxLen) + 1;
32}
33
34static void getVariableInfo(ShShaderInfo varType,
35                            const ShHandle handle,
36                            int index,
37                            int* length,
38                            int* size,
39                            ShDataType* type,
40                            char* name)
41{
42    if (!handle || !size || !type || !name)
43        return;
44    ASSERT((varType == SH_ACTIVE_ATTRIBUTES) ||
45           (varType == SH_ACTIVE_UNIFORMS));
46
47    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
48    TCompiler* compiler = base->getAsCompiler();
49    if (compiler == 0)
50        return;
51
52    const TVariableInfoList& varList = varType == SH_ACTIVE_ATTRIBUTES ?
53        compiler->getAttribs() : compiler->getUniforms();
54    if (index < 0 || index >= static_cast<int>(varList.size()))
55        return;
56
57    const TVariableInfo& varInfo = varList[index];
58    if (length) *length = varInfo.name.size();
59    *size = varInfo.size;
60    *type = varInfo.type;
61    strcpy(name, varInfo.name.c_str());
62}
63
64//
65// Driver must call this first, once, before doing any other
66// compiler operations.
67//
68int ShInitialize()
69{
70    if (!InitProcess())
71        return 0;
72
73    return 1;
74}
75
76//
77// Cleanup symbol tables
78//
79int ShFinalize()
80{
81    if (!DetachProcess())
82        return 0;
83
84    return 1;
85}
86
87//
88// Initialize built-in resources with minimum expected values.
89//
90void ShInitBuiltInResources(ShBuiltInResources* resources)
91{
92    // Constants.
93    resources->MaxVertexAttribs = 8;
94    resources->MaxVertexUniformVectors = 128;
95    resources->MaxVaryingVectors = 8;
96    resources->MaxVertexTextureImageUnits = 0;
97    resources->MaxCombinedTextureImageUnits = 8;
98    resources->MaxTextureImageUnits = 8;
99    resources->MaxFragmentUniformVectors = 16;
100    resources->MaxDrawBuffers = 1;
101
102    // Extensions.
103    resources->OES_standard_derivatives = 0;
104}
105
106//
107// Driver calls these to create and destroy compiler objects.
108//
109ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec,
110                             const ShBuiltInResources* resources)
111{
112    if (!InitThread())
113        return 0;
114
115    TShHandleBase* base = static_cast<TShHandleBase*>(ConstructCompiler(type, spec));
116    TCompiler* compiler = base->getAsCompiler();
117    if (compiler == 0)
118        return 0;
119
120    // Generate built-in symbol table.
121    if (!compiler->Init(*resources)) {
122        ShDestruct(base);
123        return 0;
124    }
125
126    return reinterpret_cast<void*>(base);
127}
128
129void ShDestruct(ShHandle handle)
130{
131    if (handle == 0)
132        return;
133
134    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
135
136    if (base->getAsCompiler())
137        DeleteCompiler(base->getAsCompiler());
138}
139
140//
141// Do an actual compile on the given strings.  The result is left
142// in the given compile object.
143//
144// Return:  The return value of ShCompile is really boolean, indicating
145// success or failure.
146//
147int ShCompile(
148    const ShHandle handle,
149    const char* const shaderStrings[],
150    const int numStrings,
151    int compileOptions)
152{
153    if (!InitThread())
154        return 0;
155
156    if (handle == 0)
157        return 0;
158
159    TShHandleBase* base = reinterpret_cast<TShHandleBase*>(handle);
160    TCompiler* compiler = base->getAsCompiler();
161    if (compiler == 0)
162        return 0;
163
164    bool success = compiler->compile(shaderStrings, numStrings, compileOptions);
165    return success ? 1 : 0;
166}
167
168void ShGetInfo(const ShHandle handle, ShShaderInfo pname, int* params)
169{
170    if (!handle || !params)
171        return;
172
173    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
174    TCompiler* compiler = base->getAsCompiler();
175    if (!compiler) return;
176
177    switch(pname)
178    {
179    case SH_INFO_LOG_LENGTH:
180        *params = compiler->getInfoSink().info.size() + 1;
181        break;
182    case SH_OBJECT_CODE_LENGTH:
183        *params = compiler->getInfoSink().obj.size() + 1;
184        break;
185    case SH_ACTIVE_UNIFORMS:
186        *params = compiler->getUniforms().size();
187        break;
188    case SH_ACTIVE_UNIFORM_MAX_LENGTH:
189        *params = getVariableMaxLength(compiler->getUniforms());
190        break;
191    case SH_ACTIVE_ATTRIBUTES:
192        *params = compiler->getAttribs().size();
193        break;
194    case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
195        *params = getVariableMaxLength(compiler->getAttribs());
196        break;
197
198    default: UNREACHABLE();
199    }
200}
201
202//
203// Return any compiler log of messages for the application.
204//
205void ShGetInfoLog(const ShHandle handle, char* infoLog)
206{
207    if (!handle || !infoLog)
208        return;
209
210    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
211    TCompiler* compiler = base->getAsCompiler();
212    if (!compiler) return;
213
214    TInfoSink& infoSink = compiler->getInfoSink();
215    strcpy(infoLog, infoSink.info.c_str());
216}
217
218//
219// Return any object code.
220//
221void ShGetObjectCode(const ShHandle handle, char* objCode)
222{
223    if (!handle || !objCode)
224        return;
225
226    TShHandleBase* base = static_cast<TShHandleBase*>(handle);
227    TCompiler* compiler = base->getAsCompiler();
228    if (!compiler) return;
229
230    TInfoSink& infoSink = compiler->getInfoSink();
231    strcpy(objCode, infoSink.obj.c_str());
232}
233
234void ShGetActiveAttrib(const ShHandle handle,
235                       int index,
236                       int* length,
237                       int* size,
238                       ShDataType* type,
239                       char* name)
240{
241    getVariableInfo(SH_ACTIVE_ATTRIBUTES,
242                    handle, index, length, size, type, name);
243}
244
245void ShGetActiveUniform(const ShHandle handle,
246                        int index,
247                        int* length,
248                        int* size,
249                        ShDataType* type,
250                        char* name)
251{
252    getVariableInfo(SH_ACTIVE_UNIFORMS,
253                    handle, index, length, size, type, name);
254}
255