blob: 7144a8fabdc826aaff57cad0fad5f0f892915293 [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"
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000014#include "GLSLANG/Shaderlang.h"
15#include "compiler/OutputHLSL.h"
16#include "common/debug.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000017
18namespace gl
19{
20void *Shader::mFragmentCompiler = NULL;
21void *Shader::mVertexCompiler = NULL;
22
daniel@transgaming.com6c785212010-03-30 03:36:17 +000023Shader::Shader(GLuint handle) : mHandle(handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000024{
25 mSource = NULL;
26 mHlsl = NULL;
daniel@transgaming.comcba50572010-03-28 19:36:09 +000027 mInfoLog = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000028
29 // Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
30 if (!mFragmentCompiler)
31 {
32 int result = ShInitialize();
33
34 if (result)
35 {
36 mFragmentCompiler = ShConstructCompiler(EShLangFragment, EDebugOpObjectCode);
37 mVertexCompiler = ShConstructCompiler(EShLangVertex, EDebugOpObjectCode);
38 }
39 }
40
41 mAttachCount = 0;
42 mDeleteStatus = false;
43}
44
45Shader::~Shader()
46{
47 delete[] mSource;
48 delete[] mHlsl;
daniel@transgaming.comcba50572010-03-28 19:36:09 +000049 delete[] mInfoLog;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000050}
51
daniel@transgaming.com6c785212010-03-30 03:36:17 +000052GLuint Shader::getHandle() const
53{
54 return mHandle;
55}
56
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000057void Shader::setSource(GLsizei count, const char **string, const GLint *length)
58{
59 delete[] mSource;
60 int totalLength = 0;
61
62 for (int i = 0; i < count; i++)
63 {
64 if (length && length[i] >= 0)
65 {
66 totalLength += length[i];
67 }
68 else
69 {
70 totalLength += (int)strlen(string[i]);
71 }
72 }
73
74 mSource = new char[totalLength + 1];
75 char *code = mSource;
76
77 for (int i = 0; i < count; i++)
78 {
79 int stringLength;
80
81 if (length && length[i] >= 0)
82 {
83 stringLength = length[i];
84 }
85 else
86 {
87 stringLength = (int)strlen(string[i]);
88 }
89
90 strncpy(code, string[i], stringLength);
91 code += stringLength;
92 }
93
94 mSource[totalLength] = '\0';
95}
96
daniel@transgaming.comcba50572010-03-28 19:36:09 +000097int Shader::getInfoLogLength() const
98{
99 if (!mInfoLog)
100 {
101 return 0;
102 }
103 else
104 {
105 return strlen(mInfoLog) + 1;
106 }
107}
108
109void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
110{
111 int index = 0;
112
113 if (mInfoLog)
114 {
115 while (index < bufSize - 1 && index < (int)strlen(mInfoLog))
116 {
117 infoLog[index] = mInfoLog[index];
118 index++;
119 }
120 }
121
122 if (bufSize)
123 {
124 infoLog[index] = '\0';
125 }
126
127 if (length)
128 {
129 *length = index;
130 }
131}
132
133int Shader::getSourceLength() const
134{
135 if (!mSource)
136 {
137 return 0;
138 }
139 else
140 {
141 return strlen(mSource) + 1;
142 }
143}
144
145void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source)
146{
147 int index = 0;
148
149 if (mSource)
150 {
daniel@transgaming.com41187f12010-04-01 13:39:29 +0000151 while (index < bufSize - 1 && index < (int)strlen(mSource))
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000152 {
153 source[index] = mSource[index];
154 index++;
155 }
156 }
157
158 if (bufSize)
159 {
160 source[index] = '\0';
161 }
162
163 if (length)
164 {
165 *length = index;
166 }
167}
168
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000169bool Shader::isCompiled()
170{
171 return mHlsl != NULL;
172}
173
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +0000174const char *Shader::getHLSL()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175{
176 return mHlsl;
177}
178
179void Shader::attach()
180{
181 mAttachCount++;
182}
183
184void Shader::detach()
185{
186 mAttachCount--;
187}
188
189bool Shader::isAttached() const
190{
191 return mAttachCount > 0;
192}
193
194bool Shader::isDeletable() const
195{
196 return mDeleteStatus == true && mAttachCount == 0;
197}
198
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000199bool Shader::isFlaggedForDeletion() const
200{
201 return mDeleteStatus;
202}
203
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204void Shader::flagForDeletion()
205{
206 mDeleteStatus = true;
207}
208
209void Shader::releaseCompiler()
210{
211 ShDestruct(mFragmentCompiler);
212 ShDestruct(mVertexCompiler);
213
214 mFragmentCompiler = NULL;
215 mVertexCompiler = NULL;
216}
217
218void Shader::compileToHLSL(void *compiler)
219{
220 if (isCompiled() || !mSource)
221 {
222 return;
223 }
224
daniel@transgaming.com0599dc62010-03-21 04:31:36 +0000225 TRACE("\n%s", mSource);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000226
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000227 delete[] mInfoLog;
228 mInfoLog = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000229
230 TBuiltInResource resources;
231
232 resources.maxVertexAttribs = MAX_VERTEX_ATTRIBS;
233 resources.maxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
234 resources.maxVaryingVectors = MAX_VARYING_VECTORS;
235 resources.maxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
236 resources.maxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
237 resources.maxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
238 resources.maxFragmentUniformVectors = MAX_FRAGMENT_UNIFORM_VECTORS;
239 resources.maxDrawBuffers = MAX_DRAW_BUFFERS;
240
241 int result = ShCompile(compiler, &mSource, 1, EShOptNone, &resources, EDebugOpObjectCode);
242 const char *obj = ShGetObjectCode(compiler);
243 const char *info = ShGetInfoLog(compiler);
244
245 if (result)
246 {
247 mHlsl = new char[strlen(obj) + 1];
248 strcpy(mHlsl, obj);
249
daniel@transgaming.com0599dc62010-03-21 04:31:36 +0000250 TRACE("\n%s", mHlsl);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000251 }
252 else
253 {
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000254 mInfoLog = new char[strlen(info) + 1];
255 strcpy(mInfoLog, info);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000256
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000257 TRACE("\n%s", mInfoLog);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000258 }
259}
260
261InputMapping::InputMapping()
262{
263 mAttribute = NULL;
264 mSemanticIndex = -1;
265}
266
267InputMapping::InputMapping(const char *attribute, int semanticIndex)
268{
269 mAttribute = new char[strlen(attribute) + 1];
270 strcpy(mAttribute, attribute);
271 mSemanticIndex = semanticIndex;
272}
273
274InputMapping &InputMapping::operator=(const InputMapping &inputMapping)
275{
276 delete[] mAttribute;
277
278 mAttribute = new char[strlen(inputMapping.mAttribute) + 1];
279 strcpy(mAttribute, inputMapping.mAttribute);
280 mSemanticIndex = inputMapping.mSemanticIndex;
281
282 return *this;
283}
284
285InputMapping::~InputMapping()
286{
287 delete[] mAttribute;
288}
289
daniel@transgaming.com6c785212010-03-30 03:36:17 +0000290VertexShader::VertexShader(GLuint handle) : Shader(handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000291{
292}
293
294VertexShader::~VertexShader()
295{
296}
297
298GLenum VertexShader::getType()
299{
300 return GL_VERTEX_SHADER;
301}
302
303void VertexShader::compile()
304{
305 compileToHLSL(mVertexCompiler);
306 parseAttributes();
307}
308
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000309const char *VertexShader::getAttributeName(unsigned int attributeIndex)
310{
311 if (attributeIndex < MAX_VERTEX_ATTRIBS)
312 {
313 return mInputMapping[attributeIndex].mAttribute;
314 }
315
316 return 0;
317}
318
319bool VertexShader::isActiveAttribute(const char *attributeName)
320{
321 return getInputMapping(attributeName) != -1;
322}
323
324int VertexShader::getInputMapping(const char *attributeName)
325{
326 if (attributeName)
327 {
328 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
329 {
330 if (mInputMapping[index].mAttribute && strcmp(mInputMapping[index].mAttribute, attributeName) == 0)
331 {
332 return mInputMapping[index].mSemanticIndex;
333 }
334 }
335 }
336
337 return -1;
338}
339
340void VertexShader::parseAttributes()
341{
342 if (mHlsl)
343 {
344 const char *input = strstr(mHlsl, "struct VS_INPUT");
345
346 for (int attributeIndex = 0; *input != '}'; input++)
347 {
348 char attributeName[100];
349 int semanticIndex;
350
351 int matches = sscanf(input, "%s : TEXCOORD%d;", attributeName, &semanticIndex);
352
353 if (matches == 2)
354 {
355 ASSERT(attributeIndex < MAX_VERTEX_ATTRIBS);
356 mInputMapping[attributeIndex] = InputMapping(attributeName, semanticIndex);
357 attributeIndex++;
358
359 input = strstr(input, ";");
360 }
361 }
362 }
363}
364
daniel@transgaming.com6c785212010-03-30 03:36:17 +0000365FragmentShader::FragmentShader(GLuint handle) : Shader(handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000366{
367}
368
369FragmentShader::~FragmentShader()
370{
371}
372
373GLenum FragmentShader::getType()
374{
375 return GL_FRAGMENT_SHADER;
376}
377
378void FragmentShader::compile()
379{
380 compileToHLSL(mFragmentCompiler);
381}
382}