blob: b17a6c9836a255ed0e2567895b94ca03093f93cb [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
23Shader::Shader()
24{
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
52void Shader::setSource(GLsizei count, const char **string, const GLint *length)
53{
54 delete[] mSource;
55 int totalLength = 0;
56
57 for (int i = 0; i < count; i++)
58 {
59 if (length && length[i] >= 0)
60 {
61 totalLength += length[i];
62 }
63 else
64 {
65 totalLength += (int)strlen(string[i]);
66 }
67 }
68
69 mSource = new char[totalLength + 1];
70 char *code = mSource;
71
72 for (int i = 0; i < count; i++)
73 {
74 int stringLength;
75
76 if (length && length[i] >= 0)
77 {
78 stringLength = length[i];
79 }
80 else
81 {
82 stringLength = (int)strlen(string[i]);
83 }
84
85 strncpy(code, string[i], stringLength);
86 code += stringLength;
87 }
88
89 mSource[totalLength] = '\0';
90}
91
daniel@transgaming.comcba50572010-03-28 19:36:09 +000092int Shader::getInfoLogLength() const
93{
94 if (!mInfoLog)
95 {
96 return 0;
97 }
98 else
99 {
100 return strlen(mInfoLog) + 1;
101 }
102}
103
104void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
105{
106 int index = 0;
107
108 if (mInfoLog)
109 {
110 while (index < bufSize - 1 && index < (int)strlen(mInfoLog))
111 {
112 infoLog[index] = mInfoLog[index];
113 index++;
114 }
115 }
116
117 if (bufSize)
118 {
119 infoLog[index] = '\0';
120 }
121
122 if (length)
123 {
124 *length = index;
125 }
126}
127
128int Shader::getSourceLength() const
129{
130 if (!mSource)
131 {
132 return 0;
133 }
134 else
135 {
136 return strlen(mSource) + 1;
137 }
138}
139
140void Shader::getSource(GLsizei bufSize, GLsizei *length, char *source)
141{
142 int index = 0;
143
144 if (mSource)
145 {
146 while (index < bufSize - 1 && index < (int)strlen(mInfoLog))
147 {
148 source[index] = mSource[index];
149 index++;
150 }
151 }
152
153 if (bufSize)
154 {
155 source[index] = '\0';
156 }
157
158 if (length)
159 {
160 *length = index;
161 }
162}
163
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164bool Shader::isCompiled()
165{
166 return mHlsl != NULL;
167}
168
169const char *Shader::linkHLSL()
170{
171 return mHlsl;
172}
173
174void Shader::attach()
175{
176 mAttachCount++;
177}
178
179void Shader::detach()
180{
181 mAttachCount--;
182}
183
184bool Shader::isAttached() const
185{
186 return mAttachCount > 0;
187}
188
189bool Shader::isDeletable() const
190{
191 return mDeleteStatus == true && mAttachCount == 0;
192}
193
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000194bool Shader::isFlaggedForDeletion() const
195{
196 return mDeleteStatus;
197}
198
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000199void Shader::flagForDeletion()
200{
201 mDeleteStatus = true;
202}
203
204void Shader::releaseCompiler()
205{
206 ShDestruct(mFragmentCompiler);
207 ShDestruct(mVertexCompiler);
208
209 mFragmentCompiler = NULL;
210 mVertexCompiler = NULL;
211}
212
213void Shader::compileToHLSL(void *compiler)
214{
215 if (isCompiled() || !mSource)
216 {
217 return;
218 }
219
daniel@transgaming.com0599dc62010-03-21 04:31:36 +0000220 TRACE("\n%s", mSource);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000222 delete[] mInfoLog;
223 mInfoLog = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000224
225 TBuiltInResource resources;
226
227 resources.maxVertexAttribs = MAX_VERTEX_ATTRIBS;
228 resources.maxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
229 resources.maxVaryingVectors = MAX_VARYING_VECTORS;
230 resources.maxVertexTextureImageUnits = MAX_VERTEX_TEXTURE_IMAGE_UNITS;
231 resources.maxCombinedTextureImageUnits = MAX_COMBINED_TEXTURE_IMAGE_UNITS;
232 resources.maxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
233 resources.maxFragmentUniformVectors = MAX_FRAGMENT_UNIFORM_VECTORS;
234 resources.maxDrawBuffers = MAX_DRAW_BUFFERS;
235
236 int result = ShCompile(compiler, &mSource, 1, EShOptNone, &resources, EDebugOpObjectCode);
237 const char *obj = ShGetObjectCode(compiler);
238 const char *info = ShGetInfoLog(compiler);
239
240 if (result)
241 {
242 mHlsl = new char[strlen(obj) + 1];
243 strcpy(mHlsl, obj);
244
daniel@transgaming.com0599dc62010-03-21 04:31:36 +0000245 TRACE("\n%s", mHlsl);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000246 }
247 else
248 {
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000249 mInfoLog = new char[strlen(info) + 1];
250 strcpy(mInfoLog, info);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000251
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000252 TRACE("\n%s", mInfoLog);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000253 }
254}
255
256InputMapping::InputMapping()
257{
258 mAttribute = NULL;
259 mSemanticIndex = -1;
260}
261
262InputMapping::InputMapping(const char *attribute, int semanticIndex)
263{
264 mAttribute = new char[strlen(attribute) + 1];
265 strcpy(mAttribute, attribute);
266 mSemanticIndex = semanticIndex;
267}
268
269InputMapping &InputMapping::operator=(const InputMapping &inputMapping)
270{
271 delete[] mAttribute;
272
273 mAttribute = new char[strlen(inputMapping.mAttribute) + 1];
274 strcpy(mAttribute, inputMapping.mAttribute);
275 mSemanticIndex = inputMapping.mSemanticIndex;
276
277 return *this;
278}
279
280InputMapping::~InputMapping()
281{
282 delete[] mAttribute;
283}
284
285VertexShader::VertexShader()
286{
287}
288
289VertexShader::~VertexShader()
290{
291}
292
293GLenum VertexShader::getType()
294{
295 return GL_VERTEX_SHADER;
296}
297
298void VertexShader::compile()
299{
300 compileToHLSL(mVertexCompiler);
301 parseAttributes();
302}
303
304const char *VertexShader::linkHLSL(const char *pixelHLSL)
305{
306 if (mHlsl && pixelHLSL)
307 {
308 const char *input = strstr(pixelHLSL, "struct PS_INPUT");
309 char *output = strstr(mHlsl, "struct VS_OUTPUT");
310
311 while (*input != '}' && output)
312 {
313 char varyingName[100];
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000314 unsigned int semanticIndex;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000315 int matches = sscanf(input, "%s : TEXCOORD%d;", varyingName, &semanticIndex);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000316
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +0000317 if (matches == 2 && semanticIndex != sh::HLSL_FRAG_COORD_SEMANTIC)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000318 {
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000319 ASSERT(semanticIndex < MAX_VARYING_VECTORS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000320 char *varying = strstr(output, varyingName);
daniel@transgaming.comc7d8a932010-03-16 06:16:45 +0000321
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000322 if (varying)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000323 {
daniel@transgaming.com86487c22010-03-11 19:41:43 +0000324 ASSERT(semanticIndex <= 9); // Single character
325 varying = strstr(varying, " : TEXCOORD0;");
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000326 varying[11] = '0' + semanticIndex;
327 }
328 else
329 {
330 return NULL;
331 }
332
333 input = strstr(input, ";");
334 }
335
336 input++;
337 }
338 }
339
340 return mHlsl;
341}
342
343const char *VertexShader::getAttributeName(unsigned int attributeIndex)
344{
345 if (attributeIndex < MAX_VERTEX_ATTRIBS)
346 {
347 return mInputMapping[attributeIndex].mAttribute;
348 }
349
350 return 0;
351}
352
353bool VertexShader::isActiveAttribute(const char *attributeName)
354{
355 return getInputMapping(attributeName) != -1;
356}
357
358int VertexShader::getInputMapping(const char *attributeName)
359{
360 if (attributeName)
361 {
362 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
363 {
364 if (mInputMapping[index].mAttribute && strcmp(mInputMapping[index].mAttribute, attributeName) == 0)
365 {
366 return mInputMapping[index].mSemanticIndex;
367 }
368 }
369 }
370
371 return -1;
372}
373
374void VertexShader::parseAttributes()
375{
376 if (mHlsl)
377 {
378 const char *input = strstr(mHlsl, "struct VS_INPUT");
379
380 for (int attributeIndex = 0; *input != '}'; input++)
381 {
382 char attributeName[100];
383 int semanticIndex;
384
385 int matches = sscanf(input, "%s : TEXCOORD%d;", attributeName, &semanticIndex);
386
387 if (matches == 2)
388 {
389 ASSERT(attributeIndex < MAX_VERTEX_ATTRIBS);
390 mInputMapping[attributeIndex] = InputMapping(attributeName, semanticIndex);
391 attributeIndex++;
392
393 input = strstr(input, ";");
394 }
395 }
396 }
397}
398
399FragmentShader::FragmentShader()
400{
401}
402
403FragmentShader::~FragmentShader()
404{
405}
406
407GLenum FragmentShader::getType()
408{
409 return GL_FRAGMENT_SHADER;
410}
411
412void FragmentShader::compile()
413{
414 compileToHLSL(mFragmentCompiler);
415}
416}