blob: 7d9d4504f5f4f43c9d14ad41239f4ca2d427f072 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
daniel@transgaming.com2cdf8332012-02-17 18:00:50 +00002// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// 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
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000011#include "libGLESv2/Shader.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000012
alokp@chromium.org91b72322010-06-02 15:50:56 +000013#include <string>
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000014
daniel@transgaming.com29ab9522012-08-27 16:25:37 +000015#include "GLSLANG/ShaderLang.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000016#include "libGLESv2/main.h"
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +000017#include "libGLESv2/utilities.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000018
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000019namespace gl
20{
21void *Shader::mFragmentCompiler = NULL;
22void *Shader::mVertexCompiler = NULL;
23
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000024Shader::Shader(ResourceManager *manager, GLuint handle) : mHandle(handle), mResourceManager(manager)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000025{
26 mSource = NULL;
27 mHlsl = NULL;
daniel@transgaming.comcba50572010-03-28 19:36:09 +000028 mInfoLog = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000029
daniel@transgaming.com938009c2012-02-17 18:02:15 +000030 uncompile();
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +000031 initializeCompiler();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000032
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000033 mRefCount = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000034 mDeleteStatus = false;
35}
36
37Shader::~Shader()
38{
39 delete[] mSource;
40 delete[] mHlsl;
daniel@transgaming.comcba50572010-03-28 19:36:09 +000041 delete[] mInfoLog;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000042}
43
daniel@transgaming.com6c785212010-03-30 03:36:17 +000044GLuint Shader::getHandle() const
45{
46 return mHandle;
47}
48
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000049void Shader::setSource(GLsizei count, const char **string, const GLint *length)
50{
51 delete[] mSource;
52 int totalLength = 0;
53
54 for (int i = 0; i < count; i++)
55 {
56 if (length && length[i] >= 0)
57 {
58 totalLength += length[i];
59 }
60 else
61 {
62 totalLength += (int)strlen(string[i]);
63 }
64 }
65
66 mSource = new char[totalLength + 1];
67 char *code = mSource;
68
69 for (int i = 0; i < count; i++)
70 {
71 int stringLength;
72
73 if (length && length[i] >= 0)
74 {
75 stringLength = length[i];
76 }
77 else
78 {
79 stringLength = (int)strlen(string[i]);
80 }
81
82 strncpy(code, string[i], stringLength);
83 code += stringLength;
84 }
85
86 mSource[totalLength] = '\0';
87}
88
daniel@transgaming.comcba50572010-03-28 19:36:09 +000089int Shader::getInfoLogLength() const
90{
91 if (!mInfoLog)
92 {
93 return 0;
94 }
95 else
96 {
97 return strlen(mInfoLog) + 1;
98 }
99}
100
101void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
102{
103 int index = 0;
104
daniel@transgaming.com807d8c32012-04-04 15:06:04 +0000105 if (bufSize > 0)
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000106 {
daniel@transgaming.com807d8c32012-04-04 15:06:04 +0000107 if (mInfoLog)
108 {
109 index = std::min(bufSize - 1, (int)strlen(mInfoLog));
110 memcpy(infoLog, mInfoLog, index);
111 }
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000112
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000113 infoLog[index] = '\0';
114 }
115
116 if (length)
117 {
118 *length = index;
119 }
120}
121
122int Shader::getSourceLength() const
123{
124 if (!mSource)
125 {
126 return 0;
127 }
128 else
129 {
130 return strlen(mSource) + 1;
131 }
132}
133
zmo@google.coma574f782011-10-03 21:45:23 +0000134int Shader::getTranslatedSourceLength() const
135{
136 if (!mHlsl)
137 {
138 return 0;
139 }
140 else
141 {
142 return strlen(mHlsl) + 1;
143 }
144}
145
146void Shader::getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char *buffer)
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000147{
148 int index = 0;
149
daniel@transgaming.com807d8c32012-04-04 15:06:04 +0000150 if (bufSize > 0)
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000151 {
daniel@transgaming.com807d8c32012-04-04 15:06:04 +0000152 if (source)
153 {
154 index = std::min(bufSize - 1, (int)strlen(source));
155 memcpy(buffer, source, index);
156 }
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000157
zmo@google.coma574f782011-10-03 21:45:23 +0000158 buffer[index] = '\0';
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000159 }
160
161 if (length)
162 {
163 *length = index;
164 }
165}
166
zmo@google.coma574f782011-10-03 21:45:23 +0000167void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer)
168{
169 getSourceImpl(mSource, bufSize, length, buffer);
170}
171
172void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer)
173{
174 getSourceImpl(mHlsl, bufSize, length, buffer);
175}
176
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000177const sh::ActiveUniforms &Shader::getUniforms()
178{
179 return mActiveUniforms;
180}
181
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182bool Shader::isCompiled()
183{
184 return mHlsl != NULL;
185}
186
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +0000187const char *Shader::getHLSL()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000188{
189 return mHlsl;
190}
191
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000192void Shader::addRef()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000193{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000194 mRefCount++;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000195}
196
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000197void Shader::release()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000198{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000199 mRefCount--;
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000200
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000201 if (mRefCount == 0 && mDeleteStatus)
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000202 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000203 mResourceManager->deleteShader(mHandle);
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000204 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000205}
206
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000207unsigned int Shader::getRefCount() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000208{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000209 return mRefCount;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000210}
211
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000212bool Shader::isFlaggedForDeletion() const
213{
214 return mDeleteStatus;
215}
216
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000217void Shader::flagForDeletion()
218{
219 mDeleteStatus = true;
220}
221
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000222// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
223void Shader::initializeCompiler()
224{
225 if (!mFragmentCompiler)
226 {
227 int result = ShInitialize();
228
229 if (result)
230 {
231 ShBuiltInResources resources;
232 ShInitBuiltInResources(&resources);
233 Context *context = getContext();
234
235 resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS;
236 resources.MaxVertexUniformVectors = MAX_VERTEX_UNIFORM_VECTORS;
237 resources.MaxVaryingVectors = context->getMaximumVaryingVectors();
238 resources.MaxVertexTextureImageUnits = context->getMaximumVertexTextureImageUnits();
239 resources.MaxCombinedTextureImageUnits = context->getMaximumCombinedTextureImageUnits();
240 resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS;
241 resources.MaxFragmentUniformVectors = context->getMaximumFragmentUniformVectors();
242 resources.MaxDrawBuffers = MAX_DRAW_BUFFERS;
daniel@transgaming.com7629bb62013-01-11 04:12:28 +0000243 resources.OES_standard_derivatives = context->supportsDerivativeInstructions() ? 1 : 0;
daniel@transgaming.com7cb796e2012-10-31 18:46:44 +0000244 // resources.OES_EGL_image_external = getDisplay()->getRenderer()->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported.
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000245
246 mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, SH_HLSL_OUTPUT, &resources);
247 mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, SH_HLSL_OUTPUT, &resources);
248 }
249 }
250}
251
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000252void Shader::releaseCompiler()
253{
254 ShDestruct(mFragmentCompiler);
255 ShDestruct(mVertexCompiler);
256
257 mFragmentCompiler = NULL;
258 mVertexCompiler = NULL;
alokp@chromium.org90033b92010-05-24 15:02:43 +0000259
260 ShFinalize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000261}
262
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000263void Shader::parseVaryings()
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000264{
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000265 if (mHlsl)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000266 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000267 const char *input = strstr(mHlsl, "// Varyings") + 12;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000268
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000269 while(true)
270 {
271 char varyingType[256];
272 char varyingName[256];
273
daniel@transgaming.com7ea933f2010-12-12 08:52:42 +0000274 int matches = sscanf(input, "static %255s %255s", varyingType, varyingName);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000275
276 if (matches != 2)
277 {
278 break;
279 }
280
281 char *array = strstr(varyingName, "[");
282 int size = 1;
283
284 if (array)
285 {
286 size = atoi(array + 1);
287 *array = '\0';
288 }
289
daniel@transgaming.comcde6a612012-02-17 18:01:10 +0000290 mVaryings.push_back(Varying(parseType(varyingType), varyingName, size, array != NULL));
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000291
292 input = strstr(input, ";") + 2;
293 }
294
295 mUsesFragCoord = strstr(mHlsl, "GL_USES_FRAG_COORD") != NULL;
296 mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL;
daniel@transgaming.combe5a0862010-07-28 19:20:37 +0000297 mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL;
298 mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000299 }
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +0000300}
301
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000302// initialize/clean up previous state
303void Shader::uncompile()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000304{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000305 // set by compileToHLSL
306 delete[] mHlsl;
307 mHlsl = NULL;
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000308 delete[] mInfoLog;
309 mInfoLog = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000310
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000311 // set by parseVaryings
312 mVaryings.clear();
313
314 mUsesFragCoord = false;
315 mUsesFrontFacing = false;
316 mUsesPointSize = false;
317 mUsesPointCoord = false;
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000318
319 mActiveUniforms.clear();
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000320}
321
322void Shader::compileToHLSL(void *compiler)
323{
324 // ensure we don't pass a NULL source to the compiler
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000325 const char *source = "\0";
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000326 if (mSource)
327 {
328 source = mSource;
329 }
330
daniel@transgaming.com0725e7d2012-02-17 18:02:20 +0000331 // ensure the compiler is loaded
332 initializeCompiler();
333
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000334 int compileOptions = SH_OBJECT_CODE;
335 std::string sourcePath;
336 if (perfActive())
337 {
338 sourcePath = getTempPath();
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000339 writeFile(sourcePath.c_str(), source, strlen(source));
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000340 compileOptions |= SH_LINE_DIRECTIVES;
341 }
342
343 int result;
344 if (sourcePath.empty())
345 {
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000346 result = ShCompile(compiler, &source, 1, compileOptions);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000347 }
348 else
349 {
350 const char* sourceStrings[2] =
351 {
352 sourcePath.c_str(),
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000353 source
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000354 };
355
356 result = ShCompile(compiler, sourceStrings, 2, compileOptions | SH_SOURCE_PATH);
357 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000358
359 if (result)
360 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000361 int objCodeLen = 0;
362 ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen);
363 mHlsl = new char[objCodeLen];
364 ShGetObjectCode(compiler, mHlsl);
daniel@transgaming.comc5c9e3c2012-12-20 21:12:32 +0000365
366 void *activeUniforms;
367 ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms);
368 mActiveUniforms = *(sh::ActiveUniforms*)activeUniforms;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000369 }
370 else
371 {
alokp@chromium.org7beea402010-09-15 21:18:34 +0000372 int infoLogLen = 0;
373 ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen);
374 mInfoLog = new char[infoLogLen];
375 ShGetInfoLog(compiler, mInfoLog);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000376
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000377 TRACE("\n%s", mInfoLog);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000378 }
379}
380
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000381GLenum Shader::parseType(const std::string &type)
382{
383 if (type == "float")
384 {
385 return GL_FLOAT;
386 }
387 else if (type == "float2")
388 {
389 return GL_FLOAT_VEC2;
390 }
391 else if (type == "float3")
392 {
393 return GL_FLOAT_VEC3;
394 }
395 else if (type == "float4")
396 {
397 return GL_FLOAT_VEC4;
398 }
399 else if (type == "float2x2")
400 {
401 return GL_FLOAT_MAT2;
402 }
403 else if (type == "float3x3")
404 {
405 return GL_FLOAT_MAT3;
406 }
407 else if (type == "float4x4")
408 {
409 return GL_FLOAT_MAT4;
410 }
411 else UNREACHABLE();
412
413 return GL_NONE;
414}
415
416// true if varying x has a higher priority in packing than y
417bool Shader::compareVarying(const Varying &x, const Varying &y)
418{
419 if(x.type == y.type)
420 {
421 return x.size > y.size;
422 }
423
424 switch (x.type)
425 {
426 case GL_FLOAT_MAT4: return true;
427 case GL_FLOAT_MAT2:
428 switch(y.type)
429 {
430 case GL_FLOAT_MAT4: return false;
431 case GL_FLOAT_MAT2: return true;
432 case GL_FLOAT_VEC4: return true;
433 case GL_FLOAT_MAT3: return true;
434 case GL_FLOAT_VEC3: return true;
435 case GL_FLOAT_VEC2: return true;
436 case GL_FLOAT: return true;
437 default: UNREACHABLE();
438 }
439 break;
440 case GL_FLOAT_VEC4:
441 switch(y.type)
442 {
443 case GL_FLOAT_MAT4: return false;
444 case GL_FLOAT_MAT2: return false;
445 case GL_FLOAT_VEC4: return true;
446 case GL_FLOAT_MAT3: return true;
447 case GL_FLOAT_VEC3: return true;
448 case GL_FLOAT_VEC2: return true;
449 case GL_FLOAT: return true;
450 default: UNREACHABLE();
451 }
452 break;
453 case GL_FLOAT_MAT3:
454 switch(y.type)
455 {
456 case GL_FLOAT_MAT4: return false;
457 case GL_FLOAT_MAT2: return false;
458 case GL_FLOAT_VEC4: return false;
459 case GL_FLOAT_MAT3: return true;
460 case GL_FLOAT_VEC3: return true;
461 case GL_FLOAT_VEC2: return true;
462 case GL_FLOAT: return true;
463 default: UNREACHABLE();
464 }
465 break;
466 case GL_FLOAT_VEC3:
467 switch(y.type)
468 {
469 case GL_FLOAT_MAT4: return false;
470 case GL_FLOAT_MAT2: return false;
471 case GL_FLOAT_VEC4: return false;
472 case GL_FLOAT_MAT3: return false;
473 case GL_FLOAT_VEC3: return true;
474 case GL_FLOAT_VEC2: return true;
475 case GL_FLOAT: return true;
476 default: UNREACHABLE();
477 }
478 break;
479 case GL_FLOAT_VEC2:
480 switch(y.type)
481 {
482 case GL_FLOAT_MAT4: return false;
483 case GL_FLOAT_MAT2: return false;
484 case GL_FLOAT_VEC4: return false;
485 case GL_FLOAT_MAT3: return false;
486 case GL_FLOAT_VEC3: return false;
487 case GL_FLOAT_VEC2: return true;
488 case GL_FLOAT: return true;
489 default: UNREACHABLE();
490 }
491 break;
492 case GL_FLOAT: return false;
493 default: UNREACHABLE();
494 }
495
496 return false;
497}
498
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000499VertexShader::VertexShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000500{
501}
502
503VertexShader::~VertexShader()
504{
505}
506
507GLenum VertexShader::getType()
508{
509 return GL_VERTEX_SHADER;
510}
511
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000512void VertexShader::uncompile()
513{
514 Shader::uncompile();
515
516 // set by ParseAttributes
517 mAttributes.clear();
daniel@transgaming.come3e826d2012-11-28 19:42:35 +0000518}
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000519
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000520void VertexShader::compile()
521{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000522 uncompile();
523
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000524 compileToHLSL(mVertexCompiler);
525 parseAttributes();
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000526 parseVaryings();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000527}
528
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000529int VertexShader::getSemanticIndex(const std::string &attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000530{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000531 if (!attributeName.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000532 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000533 int semanticIndex = 0;
534 for (AttributeArray::iterator attribute = mAttributes.begin(); attribute != mAttributes.end(); attribute++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000535 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000536 if (attribute->name == attributeName)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000537 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000538 return semanticIndex;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000539 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000540
541 semanticIndex += VariableRowCount(attribute->type);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000542 }
543 }
544
545 return -1;
546}
547
548void VertexShader::parseAttributes()
549{
daniel@transgaming.com2cdf8332012-02-17 18:00:50 +0000550 const char *hlsl = getHLSL();
551 if (hlsl)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000552 {
daniel@transgaming.com2cdf8332012-02-17 18:00:50 +0000553 const char *input = strstr(hlsl, "// Attributes") + 14;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000554
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000555 while(true)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000556 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000557 char attributeType[256];
558 char attributeName[256];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000559
daniel@transgaming.com7ea933f2010-12-12 08:52:42 +0000560 int matches = sscanf(input, "static %255s _%255s", attributeType, attributeName);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000561
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000562 if (matches != 2)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000563 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000564 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000565 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000566
567 mAttributes.push_back(Attribute(parseType(attributeType), attributeName));
568
569 input = strstr(input, ";") + 2;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000570 }
571 }
572}
573
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000574FragmentShader::FragmentShader(ResourceManager *manager, GLuint handle) : Shader(manager, handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000575{
576}
577
578FragmentShader::~FragmentShader()
579{
580}
581
582GLenum FragmentShader::getType()
583{
584 return GL_FRAGMENT_SHADER;
585}
586
587void FragmentShader::compile()
588{
daniel@transgaming.com938009c2012-02-17 18:02:15 +0000589 uncompile();
590
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000591 compileToHLSL(mFragmentCompiler);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +0000592 parseVaryings();
daniel@transgaming.comcde6a612012-02-17 18:01:10 +0000593 mVaryings.sort(compareVarying);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000594}
595}