blob: 775a7362a46627c5756e364d18f6d97d255b0f73 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
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// Shader.cpp: Implements the gl::Shader class and its derived classes
8// VertexShader and FragmentShader. Implements GL shader objects and related
9// functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
10
11#include "Shader.h"
12
13#include "main.h"
14#include "Shaderlang.h"
15#include "debug.h"
16
17namespace gl
18{
19void *Shader::mFragmentCompiler = NULL;
20void *Shader::mVertexCompiler = NULL;
21
22Shader::Shader()
23{
24 mSource = NULL;
25 mHlsl = NULL;
26 mErrors = NULL;
27
28 // Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
29 if (!mFragmentCompiler)
30 {
31 int result = ShInitialize();
32
33 if (result)
34 {
35 mFragmentCompiler = ShConstructCompiler(EShLangFragment, EDebugOpObjectCode);
36 mVertexCompiler = ShConstructCompiler(EShLangVertex, EDebugOpObjectCode);
37 }
38 }
39
40 mAttachCount = 0;
41 mDeleteStatus = false;
42}
43
44Shader::~Shader()
45{
46 delete[] mSource;
47 delete[] mHlsl;
48 delete[] mErrors;
49}
50
51void Shader::setSource(GLsizei count, const char **string, const GLint *length)
52{
53 delete[] mSource;
54 int totalLength = 0;
55
56 for (int i = 0; i < count; i++)
57 {
58 if (length && length[i] >= 0)
59 {
60 totalLength += length[i];
61 }
62 else
63 {
64 totalLength += (int)strlen(string[i]);
65 }
66 }
67
68 mSource = new char[totalLength + 1];
69 char *code = mSource;
70
71 for (int i = 0; i < count; i++)
72 {
73 int stringLength;
74
75 if (length && length[i] >= 0)
76 {
77 stringLength = length[i];
78 }
79 else
80 {
81 stringLength = (int)strlen(string[i]);
82 }
83
84 strncpy(code, string[i], stringLength);
85 code += stringLength;
86 }
87
88 mSource[totalLength] = '\0';
89}
90
91bool Shader::isCompiled()
92{
93 return mHlsl != NULL;
94}
95
96const char *Shader::linkHLSL()
97{
98 return mHlsl;
99}
100
101void Shader::attach()
102{
103 mAttachCount++;
104}
105
106void Shader::detach()
107{
108 mAttachCount--;
109}
110
111bool Shader::isAttached() const
112{
113 return mAttachCount > 0;
114}
115
116bool Shader::isDeletable() const
117{
118 return mDeleteStatus == true && mAttachCount == 0;
119}
120
121void Shader::flagForDeletion()
122{
123 mDeleteStatus = true;
124}
125
126void Shader::releaseCompiler()
127{
128 ShDestruct(mFragmentCompiler);
129 ShDestruct(mVertexCompiler);
130
131 mFragmentCompiler = NULL;
132 mVertexCompiler = NULL;
133}
134
135void Shader::compileToHLSL(void *compiler)
136{
137 if (isCompiled() || !mSource)
138 {
139 return;
140 }
141
142 trace(mSource);
143
144 delete[] mErrors;
145 mErrors = NULL;
146
147 TBuiltInResource resources;
148
149 resources.maxVertexAttribs = MAX_VERTEX_ATTRIBS;
150 resources.maxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
151 resources.maxVaryingVectors = MAX_VARYING_VECTORS;
152 resources.maxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
153 resources.maxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
154 resources.maxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
155 resources.maxFragmentUniformVectors = MAX_FRAGMENT_UNIFORM_VECTORS;
156 resources.maxDrawBuffers = MAX_DRAW_BUFFERS;
157
158 int result = ShCompile(compiler, &mSource, 1, EShOptNone, &resources, EDebugOpObjectCode);
159 const char *obj = ShGetObjectCode(compiler);
160 const char *info = ShGetInfoLog(compiler);
161
162 if (result)
163 {
164 mHlsl = new char[strlen(obj) + 1];
165 strcpy(mHlsl, obj);
166
167 trace(mHlsl);
168 }
169 else
170 {
171 mErrors = new char[strlen(info) + 1];
172 strcpy(mErrors, info);
173
174 trace(mErrors);
175 }
176}
177
178InputMapping::InputMapping()
179{
180 mAttribute = NULL;
181 mSemanticIndex = -1;
182}
183
184InputMapping::InputMapping(const char *attribute, int semanticIndex)
185{
186 mAttribute = new char[strlen(attribute) + 1];
187 strcpy(mAttribute, attribute);
188 mSemanticIndex = semanticIndex;
189}
190
191InputMapping &InputMapping::operator=(const InputMapping &inputMapping)
192{
193 delete[] mAttribute;
194
195 mAttribute = new char[strlen(inputMapping.mAttribute) + 1];
196 strcpy(mAttribute, inputMapping.mAttribute);
197 mSemanticIndex = inputMapping.mSemanticIndex;
198
199 return *this;
200}
201
202InputMapping::~InputMapping()
203{
204 delete[] mAttribute;
205}
206
207VertexShader::VertexShader()
208{
209}
210
211VertexShader::~VertexShader()
212{
213}
214
215GLenum VertexShader::getType()
216{
217 return GL_VERTEX_SHADER;
218}
219
220void VertexShader::compile()
221{
222 compileToHLSL(mVertexCompiler);
223 parseAttributes();
224}
225
226const char *VertexShader::linkHLSL(const char *pixelHLSL)
227{
228 if (mHlsl && pixelHLSL)
229 {
230 const char *input = strstr(pixelHLSL, "struct PS_INPUT");
231 char *output = strstr(mHlsl, "struct VS_OUTPUT");
232
233 while (*input != '}' && output)
234 {
235 char varyingName[100];
236 int semanticIndex;
237 int matches = sscanf(input, "%s : TEXCOORD%d;", varyingName, &semanticIndex);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000238
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000239 if (matches == 2)
240 {
241 ASSERT(semanticIndex < 10 && semanticIndex < MAX_VARYING_VECTORS);
242 char *varying = strstr(output, varyingName);
243 varying = strstr(varying, " : TEXCOORD0;");
244
245 if (output)
246 {
247 varying[11] = '0' + semanticIndex;
248 }
249 else
250 {
251 return NULL;
252 }
253
254 input = strstr(input, ";");
255 }
256
257 input++;
258 }
259 }
260
261 return mHlsl;
262}
263
264const char *VertexShader::getAttributeName(unsigned int attributeIndex)
265{
266 if (attributeIndex < MAX_VERTEX_ATTRIBS)
267 {
268 return mInputMapping[attributeIndex].mAttribute;
269 }
270
271 return 0;
272}
273
274bool VertexShader::isActiveAttribute(const char *attributeName)
275{
276 return getInputMapping(attributeName) != -1;
277}
278
279int VertexShader::getInputMapping(const char *attributeName)
280{
281 if (attributeName)
282 {
283 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
284 {
285 if (mInputMapping[index].mAttribute && strcmp(mInputMapping[index].mAttribute, attributeName) == 0)
286 {
287 return mInputMapping[index].mSemanticIndex;
288 }
289 }
290 }
291
292 return -1;
293}
294
295void VertexShader::parseAttributes()
296{
297 if (mHlsl)
298 {
299 const char *input = strstr(mHlsl, "struct VS_INPUT");
300
301 for (int attributeIndex = 0; *input != '}'; input++)
302 {
303 char attributeName[100];
304 int semanticIndex;
305
306 int matches = sscanf(input, "%s : TEXCOORD%d;", attributeName, &semanticIndex);
307
308 if (matches == 2)
309 {
310 ASSERT(attributeIndex < MAX_VERTEX_ATTRIBS);
311 mInputMapping[attributeIndex] = InputMapping(attributeName, semanticIndex);
312 attributeIndex++;
313
314 input = strstr(input, ";");
315 }
316 }
317 }
318}
319
320FragmentShader::FragmentShader()
321{
322}
323
324FragmentShader::~FragmentShader()
325{
326}
327
328GLenum FragmentShader::getType()
329{
330 return GL_FRAGMENT_SHADER;
331}
332
333void FragmentShader::compile()
334{
335 compileToHLSL(mFragmentCompiler);
336}
337}