blob: fb44fc2d3c001949cf6707c83c38b98245501d2c [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
daniel@transgaming.com3f74c7a2011-05-11 15:36:51 +00002// Copyright (c) 2002-2011 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// Program.cpp: Implements the gl::Program class. Implements GL program objects
8// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
9
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000010#include "libGLESv2/Program.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000011
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000012#include "common/debug.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000013
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000014#include "libGLESv2/main.h"
15#include "libGLESv2/Shader.h"
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000016#include "libGLESv2/utilities.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000017
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +000018#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
19#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
20#endif
21
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000022namespace gl
23{
daniel@transgaming.com4fa08332010-05-11 02:29:27 +000024unsigned int Program::mCurrentSerial = 1;
25
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +000026std::string str(int i)
27{
28 char buffer[20];
29 sprintf(buffer, "%d", i);
30 return buffer;
31}
32
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000033Uniform::Uniform(GLenum type, const std::string &name, unsigned int arraySize) : type(type), name(name), arraySize(arraySize)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000034{
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000035 int bytes = UniformTypeSize(type) * arraySize;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +000036 data = new unsigned char[bytes];
37 memset(data, 0, bytes);
38 dirty = true;
daniel@transgaming.com2d84df02010-05-14 17:31:13 +000039 handlesSet = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000040}
41
42Uniform::~Uniform()
43{
44 delete[] data;
45}
46
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +000047UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index)
48 : name(name), element(element), index(index)
49{
50}
51
daniel@transgaming.com73a5db62010-10-15 17:58:13 +000052Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle), mSerial(issueSerial())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000053{
54 mFragmentShader = NULL;
55 mVertexShader = NULL;
56
57 mPixelExecutable = NULL;
58 mVertexExecutable = NULL;
59 mConstantTablePS = NULL;
60 mConstantTableVS = NULL;
61
daniel@transgaming.comcba50572010-03-28 19:36:09 +000062 mInfoLog = NULL;
daniel@transgaming.com86a7a132010-04-29 03:32:32 +000063 mValidated = false;
daniel@transgaming.comcba50572010-03-28 19:36:09 +000064
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000065 unlink();
66
67 mDeleteStatus = false;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +000068
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000069 mRefCount = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000070}
71
72Program::~Program()
73{
74 unlink(true);
daniel@transgaming.com71cd8682010-04-29 03:35:25 +000075
76 if (mVertexShader != NULL)
77 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000078 mVertexShader->release();
daniel@transgaming.com71cd8682010-04-29 03:35:25 +000079 }
80
81 if (mFragmentShader != NULL)
82 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000083 mFragmentShader->release();
daniel@transgaming.com71cd8682010-04-29 03:35:25 +000084 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000085}
86
87bool Program::attachShader(Shader *shader)
88{
89 if (shader->getType() == GL_VERTEX_SHADER)
90 {
91 if (mVertexShader)
92 {
93 return false;
94 }
95
96 mVertexShader = (VertexShader*)shader;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000097 mVertexShader->addRef();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000098 }
99 else if (shader->getType() == GL_FRAGMENT_SHADER)
100 {
101 if (mFragmentShader)
102 {
103 return false;
104 }
105
106 mFragmentShader = (FragmentShader*)shader;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000107 mFragmentShader->addRef();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000108 }
109 else UNREACHABLE();
110
111 return true;
112}
113
114bool Program::detachShader(Shader *shader)
115{
116 if (shader->getType() == GL_VERTEX_SHADER)
117 {
118 if (mVertexShader != shader)
119 {
120 return false;
121 }
122
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000123 mVertexShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000124 mVertexShader = NULL;
125 }
126 else if (shader->getType() == GL_FRAGMENT_SHADER)
127 {
128 if (mFragmentShader != shader)
129 {
130 return false;
131 }
132
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000133 mFragmentShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000134 mFragmentShader = NULL;
135 }
136 else UNREACHABLE();
137
138 unlink();
139
140 return true;
141}
142
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000143int Program::getAttachedShadersCount() const
144{
145 return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
146}
147
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000148IDirect3DPixelShader9 *Program::getPixelShader()
149{
150 return mPixelExecutable;
151}
152
153IDirect3DVertexShader9 *Program::getVertexShader()
154{
155 return mVertexExecutable;
156}
157
158void Program::bindAttributeLocation(GLuint index, const char *name)
159{
160 if (index < MAX_VERTEX_ATTRIBS)
161 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000162 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
163 {
164 mAttributeBinding[i].erase(name);
165 }
166
167 mAttributeBinding[index].insert(name);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000168 }
169}
170
171GLuint Program::getAttributeLocation(const char *name)
172{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000173 if (name)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000174 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000175 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000176 {
daniel@transgaming.com85423182010-04-22 13:35:27 +0000177 if (mLinkedAttribute[index].name == std::string(name))
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000178 {
179 return index;
180 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000181 }
182 }
183
184 return -1;
185}
186
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000187int Program::getSemanticIndex(int attributeIndex)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000188{
daniel@transgaming.com733ba932011-04-14 15:03:48 +0000189 ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
190
191 return mSemanticIndex[attributeIndex];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000192}
193
daniel@transgaming.com9ba680a2011-05-11 15:37:11 +0000194// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler
195// index (0-15 for the pixel shader and 0-3 for the vertex shader).
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000196GLint Program::getSamplerMapping(SamplerType type, unsigned int samplerIndex)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000197{
daniel@transgaming.comdfd57022011-05-11 15:37:25 +0000198 GLuint logicalTextureUnit = -1;
daniel@transgaming.com4071e662010-05-12 16:51:16 +0000199
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000200 switch (type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000201 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000202 case SAMPLER_PIXEL:
203 ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
204
205 if (mSamplersPS[samplerIndex].active)
206 {
207 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
208 }
209 break;
210 case SAMPLER_VERTEX:
211 ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
212
213 if (mSamplersVS[samplerIndex].active)
214 {
215 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
216 }
217 break;
218 default: UNREACHABLE();
daniel@transgaming.com4071e662010-05-12 16:51:16 +0000219 }
220
daniel@transgaming.com3f74c7a2011-05-11 15:36:51 +0000221 if (logicalTextureUnit >= 0 && logicalTextureUnit < getContext()->getMaximumCombinedTextureImageUnits())
daniel@transgaming.com4071e662010-05-12 16:51:16 +0000222 {
223 return logicalTextureUnit;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000224 }
225
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000226 return -1;
227}
228
daniel@transgaming.com9ba680a2011-05-11 15:37:11 +0000229// Returns the texture type for a given Direct3D 9 sampler type and
230// index (0-15 for the pixel shader and 0-3 for the vertex shader).
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000231TextureType Program::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000232{
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000233 switch (type)
234 {
235 case SAMPLER_PIXEL:
236 ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
237 ASSERT(mSamplersPS[samplerIndex].active);
238 return mSamplersPS[samplerIndex].textureType;
239 case SAMPLER_VERTEX:
240 ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
241 ASSERT(mSamplersVS[samplerIndex].active);
242 return mSamplersVS[samplerIndex].textureType;
243 default: UNREACHABLE();
244 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000245
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000246 return TEXTURE_2D;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000247}
248
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +0000249GLint Program::getUniformLocation(const char *name, bool decorated)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000250{
daniel@transgaming.comce864422010-11-18 13:16:49 +0000251 std::string _name = decorated ? name : decorate(name);
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000252 int subscript = 0;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000253
daniel@transgaming.comce864422010-11-18 13:16:49 +0000254 // Strip any trailing array operator and retrieve the subscript
255 size_t open = _name.find_last_of('[');
256 size_t close = _name.find_last_of(']');
257 if (open != std::string::npos && close == _name.length() - 1)
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +0000258 {
daniel@transgaming.comce864422010-11-18 13:16:49 +0000259 subscript = atoi(_name.substr(open + 1).c_str());
260 _name.erase(open);
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +0000261 }
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000262
daniel@transgaming.comd08ea902010-05-14 19:41:36 +0000263 unsigned int numUniforms = mUniformIndex.size();
264 for (unsigned int location = 0; location < numUniforms; location++)
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000265 {
daniel@transgaming.comce864422010-11-18 13:16:49 +0000266 if (mUniformIndex[location].name == _name &&
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000267 mUniformIndex[location].element == subscript)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000268 {
269 return location;
270 }
271 }
272
273 return -1;
274}
275
276bool Program::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
277{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000278 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000279 {
280 return false;
281 }
282
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000283 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000284 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000285
286 if (targetUniform->type == GL_FLOAT)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000287 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000288 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000289
290 if (arraySize == 1 && count > 1)
291 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
292
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000293 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000294
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000295 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat),
296 v, sizeof(GLfloat) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000297 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000298 else if (targetUniform->type == GL_BOOL)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000299 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000300 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000301
302 if (arraySize == 1 && count > 1)
303 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000304
305 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000306 GLboolean *boolParams = new GLboolean[count];
307
308 for (int i = 0; i < count; ++i)
309 {
310 if (v[i] == 0.0f)
311 {
312 boolParams[i] = GL_FALSE;
313 }
314 else
315 {
316 boolParams[i] = GL_TRUE;
317 }
318 }
319
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000320 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean),
321 boolParams, sizeof(GLboolean) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000322
323 delete [] boolParams;
324 }
325 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000326 {
327 return false;
328 }
329
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000330 return true;
331}
332
333bool Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
334{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000335 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000336 {
337 return false;
338 }
339
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000340 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000341 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000342
343 if (targetUniform->type == GL_FLOAT_VEC2)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000344 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000345 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000346
347 if (arraySize == 1 && count > 1)
348 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
349
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000350 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000351
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000352 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 2,
353 v, 2 * sizeof(GLfloat) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000354 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000355 else if (targetUniform->type == GL_BOOL_VEC2)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000356 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000357 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000358
359 if (arraySize == 1 && count > 1)
360 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
361
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000362 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
363
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000364 GLboolean *boolParams = new GLboolean[count * 2];
365
366 for (int i = 0; i < count * 2; ++i)
367 {
368 if (v[i] == 0.0f)
369 {
370 boolParams[i] = GL_FALSE;
371 }
372 else
373 {
374 boolParams[i] = GL_TRUE;
375 }
376 }
377
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000378 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 2,
379 boolParams, 2 * sizeof(GLboolean) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000380
381 delete [] boolParams;
382 }
383 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000384 {
385 return false;
386 }
387
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000388 return true;
389}
390
391bool Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
392{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000393 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000394 {
395 return false;
396 }
397
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000398 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000399 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000400
401 if (targetUniform->type == GL_FLOAT_VEC3)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000402 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000403 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000404
405 if (arraySize == 1 && count > 1)
406 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
407
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000408 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000409
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000410 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 3,
411 v, 3 * sizeof(GLfloat) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000412 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000413 else if (targetUniform->type == GL_BOOL_VEC3)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000414 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000415 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000416
417 if (arraySize == 1 && count > 1)
418 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
419
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000420 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000421 GLboolean *boolParams = new GLboolean[count * 3];
422
423 for (int i = 0; i < count * 3; ++i)
424 {
425 if (v[i] == 0.0f)
426 {
427 boolParams[i] = GL_FALSE;
428 }
429 else
430 {
431 boolParams[i] = GL_TRUE;
432 }
433 }
434
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000435 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 3,
436 boolParams, 3 * sizeof(GLboolean) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000437
438 delete [] boolParams;
439 }
440 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000441 {
442 return false;
443 }
444
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000445 return true;
446}
447
448bool Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
449{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000450 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000451 {
452 return false;
453 }
454
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000455 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000456 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000457
458 if (targetUniform->type == GL_FLOAT_VEC4)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000459 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000460 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000461
462 if (arraySize == 1 && count > 1)
463 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
464
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000465 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000466
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000467 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4,
468 v, 4 * sizeof(GLfloat) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000469 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000470 else if (targetUniform->type == GL_BOOL_VEC4)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000471 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000472 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000473
474 if (arraySize == 1 && count > 1)
475 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
476
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000477 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000478 GLboolean *boolParams = new GLboolean[count * 4];
479
480 for (int i = 0; i < count * 4; ++i)
481 {
482 if (v[i] == 0.0f)
483 {
484 boolParams[i] = GL_FALSE;
485 }
486 else
487 {
488 boolParams[i] = GL_TRUE;
489 }
490 }
491
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000492 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 4,
493 boolParams, 4 * sizeof(GLboolean) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000494
495 delete [] boolParams;
496 }
497 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000498 {
499 return false;
500 }
501
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000502 return true;
503}
504
505bool Program::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
506{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000507 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000508 {
509 return false;
510 }
511
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000512 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000513 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000514
515 if (targetUniform->type != GL_FLOAT_MAT2)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000516 {
517 return false;
518 }
519
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000520 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000521
522 if (arraySize == 1 && count > 1)
523 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
524
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000525 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000526
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000527 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4,
528 value, 4 * sizeof(GLfloat) * count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000529
530 return true;
531}
532
533bool Program::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
534{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000535 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000536 {
537 return false;
538 }
539
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000540 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000541 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000542
543 if (targetUniform->type != GL_FLOAT_MAT3)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000544 {
545 return false;
546 }
547
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000548 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000549
550 if (arraySize == 1 && count > 1)
551 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
552
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000553 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000554
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000555 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 9,
556 value, 9 * sizeof(GLfloat) * count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000557
558 return true;
559}
560
561bool Program::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
562{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000563 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000564 {
565 return false;
566 }
567
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000568 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000569 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000570
571 if (targetUniform->type != GL_FLOAT_MAT4)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000572 {
573 return false;
574 }
575
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000576 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000577
578 if (arraySize == 1 && count > 1)
579 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
580
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000581 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000582
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000583 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16,
584 value, 16 * sizeof(GLfloat) * count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000585
586 return true;
587}
588
589bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
590{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000591 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000592 {
593 return false;
594 }
595
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000596 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000597 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000598
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +0000599 if (targetUniform->type == GL_INT ||
600 targetUniform->type == GL_SAMPLER_2D ||
601 targetUniform->type == GL_SAMPLER_CUBE)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000602 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000603 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000604
605 if (arraySize == 1 && count > 1)
606 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
607
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000608 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000609
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000610 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint),
611 v, sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000612 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000613 else if (targetUniform->type == GL_BOOL)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000614 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000615 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000616
617 if (arraySize == 1 && count > 1)
618 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
619
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000620 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000621 GLboolean *boolParams = new GLboolean[count];
622
623 for (int i = 0; i < count; ++i)
624 {
625 if (v[i] == 0)
626 {
627 boolParams[i] = GL_FALSE;
628 }
629 else
630 {
631 boolParams[i] = GL_TRUE;
632 }
633 }
634
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000635 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean),
636 boolParams, sizeof(GLboolean) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000637
638 delete [] boolParams;
639 }
640 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000641 {
642 return false;
643 }
644
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000645 return true;
646}
647
648bool Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
649{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000650 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000651 {
652 return false;
653 }
654
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000655 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000656 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000657
658 if (targetUniform->type == GL_INT_VEC2)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000659 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000660 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000661
662 if (arraySize == 1 && count > 1)
663 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
664
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000665 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000666
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000667 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 2,
668 v, 2 * sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000669 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000670 else if (targetUniform->type == GL_BOOL_VEC2)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000671 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000672 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000673
674 if (arraySize == 1 && count > 1)
675 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
676
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000677 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000678 GLboolean *boolParams = new GLboolean[count * 2];
679
680 for (int i = 0; i < count * 2; ++i)
681 {
682 if (v[i] == 0)
683 {
684 boolParams[i] = GL_FALSE;
685 }
686 else
687 {
688 boolParams[i] = GL_TRUE;
689 }
690 }
691
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000692 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 2,
693 boolParams, 2 * sizeof(GLboolean) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000694
695 delete [] boolParams;
696 }
697 else
698 {
699 return false;
700 }
701
702 return true;
703}
704
705bool Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
706{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000707 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000708 {
709 return false;
710 }
711
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000712 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000713 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000714
715 if (targetUniform->type == GL_INT_VEC3)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000716 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000717 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000718
719 if (arraySize == 1 && count > 1)
720 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
721
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000722 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000723
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000724 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 3,
725 v, 3 * sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000726 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000727 else if (targetUniform->type == GL_BOOL_VEC3)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000728 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000729 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000730
731 if (arraySize == 1 && count > 1)
732 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
733
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000734 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000735 GLboolean *boolParams = new GLboolean[count * 3];
736
737 for (int i = 0; i < count * 3; ++i)
738 {
739 if (v[i] == 0)
740 {
741 boolParams[i] = GL_FALSE;
742 }
743 else
744 {
745 boolParams[i] = GL_TRUE;
746 }
747 }
748
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000749 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 3,
750 boolParams, 3 * sizeof(GLboolean) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000751
752 delete [] boolParams;
753 }
754 else
755 {
756 return false;
757 }
758
759 return true;
760}
761
762bool Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
763{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000764 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000765 {
766 return false;
767 }
768
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000769 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000770 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000771
772 if (targetUniform->type == GL_INT_VEC4)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000773 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000774 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000775
776 if (arraySize == 1 && count > 1)
777 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
778
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000779 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000780
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000781 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 4,
782 v, 4 * sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000783 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000784 else if (targetUniform->type == GL_BOOL_VEC4)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000785 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000786 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000787
788 if (arraySize == 1 && count > 1)
789 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
790
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000791 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000792 GLboolean *boolParams = new GLboolean[count * 4];
793
794 for (int i = 0; i < count * 4; ++i)
795 {
796 if (v[i] == 0)
797 {
798 boolParams[i] = GL_FALSE;
799 }
800 else
801 {
802 boolParams[i] = GL_TRUE;
803 }
804 }
805
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000806 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 4,
807 boolParams, 4 * sizeof(GLboolean) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000808
809 delete [] boolParams;
810 }
811 else
812 {
813 return false;
814 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000815
816 return true;
817}
818
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000819bool Program::getUniformfv(GLint location, GLfloat *params)
820{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000821 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000822 {
823 return false;
824 }
825
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000826 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000827
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000828 unsigned int count = UniformComponentCount(targetUniform->type);
829
830 switch (UniformComponentType(targetUniform->type))
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000831 {
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000832 case GL_BOOL:
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000833 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000834 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * count;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000835
836 for (unsigned int i = 0; i < count; ++i)
837 {
838 params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
839 }
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000840 }
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000841 break;
842 case GL_FLOAT:
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000843 memcpy(params, targetUniform->data + mUniformIndex[location].element * count * sizeof(GLfloat),
844 count * sizeof(GLfloat));
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000845 break;
846 case GL_INT:
847 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000848 GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * count;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000849
850 for (unsigned int i = 0; i < count; ++i)
851 {
852 params[i] = (float)intParams[i];
853 }
854 }
855 break;
856 default: UNREACHABLE();
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000857 }
858
859 return true;
860}
861
862bool Program::getUniformiv(GLint location, GLint *params)
863{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000864 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000865 {
866 return false;
867 }
868
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000869 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000870
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000871 unsigned int count = UniformComponentCount(targetUniform->type);
872
873 switch (UniformComponentType(targetUniform->type))
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000874 {
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000875 case GL_BOOL:
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000876 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000877 GLboolean *boolParams = targetUniform->data + mUniformIndex[location].element * count;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000878
879 for (unsigned int i = 0; i < count; ++i)
880 {
881 params[i] = (GLint)boolParams[i];
882 }
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000883 }
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000884 break;
885 case GL_FLOAT:
886 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000887 GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * count;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000888
889 for (unsigned int i = 0; i < count; ++i)
890 {
891 params[i] = (GLint)floatParams[i];
892 }
893 }
894 break;
895 case GL_INT:
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000896 memcpy(params, targetUniform->data + mUniformIndex[location].element * count * sizeof(GLint),
897 count * sizeof(GLint));
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000898 break;
899 default: UNREACHABLE();
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000900 }
901
902 return true;
903}
904
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000905void Program::dirtyAllUniforms()
906{
daniel@transgaming.comd08ea902010-05-14 19:41:36 +0000907 unsigned int numUniforms = mUniforms.size();
908 for (unsigned int index = 0; index < numUniforms; index++)
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000909 {
910 mUniforms[index]->dirty = true;
911 }
912}
913
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000914// Applies all the uniforms set for this program object to the Direct3D 9 device
915void Program::applyUniforms()
916{
daniel@transgaming.comd08ea902010-05-14 19:41:36 +0000917 unsigned int numUniforms = mUniformIndex.size();
918 for (unsigned int location = 0; location < numUniforms; location++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000919 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000920 if (mUniformIndex[location].element != 0)
921 {
922 continue;
923 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000924
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000925 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
926
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000927 if (targetUniform->dirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000928 {
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000929 int arraySize = targetUniform->arraySize;
930 GLfloat *f = (GLfloat*)targetUniform->data;
931 GLint *i = (GLint*)targetUniform->data;
932 GLboolean *b = (GLboolean*)targetUniform->data;
933
934 switch (targetUniform->type)
935 {
936 case GL_BOOL: applyUniform1bv(location, arraySize, b); break;
937 case GL_BOOL_VEC2: applyUniform2bv(location, arraySize, b); break;
938 case GL_BOOL_VEC3: applyUniform3bv(location, arraySize, b); break;
939 case GL_BOOL_VEC4: applyUniform4bv(location, arraySize, b); break;
940 case GL_FLOAT: applyUniform1fv(location, arraySize, f); break;
941 case GL_FLOAT_VEC2: applyUniform2fv(location, arraySize, f); break;
942 case GL_FLOAT_VEC3: applyUniform3fv(location, arraySize, f); break;
943 case GL_FLOAT_VEC4: applyUniform4fv(location, arraySize, f); break;
944 case GL_FLOAT_MAT2: applyUniformMatrix2fv(location, arraySize, f); break;
945 case GL_FLOAT_MAT3: applyUniformMatrix3fv(location, arraySize, f); break;
946 case GL_FLOAT_MAT4: applyUniformMatrix4fv(location, arraySize, f); break;
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +0000947 case GL_SAMPLER_2D:
948 case GL_SAMPLER_CUBE:
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000949 case GL_INT: applyUniform1iv(location, arraySize, i); break;
950 case GL_INT_VEC2: applyUniform2iv(location, arraySize, i); break;
951 case GL_INT_VEC3: applyUniform3iv(location, arraySize, i); break;
952 case GL_INT_VEC4: applyUniform4iv(location, arraySize, i); break;
953 default:
954 UNREACHABLE();
955 }
956
957 targetUniform->dirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000958 }
959 }
960}
961
962// Compiles the HLSL code of the attached shaders into executable binaries
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000963ID3D10Blob *Program::compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000964{
965 if (!hlsl)
966 {
967 return NULL;
968 }
969
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000970 DWORD result;
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000971 UINT flags = 0;
972 std::string sourceText;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000973 if (perfActive())
974 {
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000975 flags |= D3DCOMPILE_DEBUG;
976#ifdef NDEBUG
977 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
978#else
979 flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000980#endif
981
982 std::string sourcePath = getTempPath();
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000983 sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000984 writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000985 }
986 else
987 {
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000988 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
989 sourceText = hlsl;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000990 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000991
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000992 ID3D10Blob *binary = NULL;
993 ID3D10Blob *errorMessage = NULL;
994 result = D3DCompile(hlsl, strlen(hlsl), NULL, NULL, NULL, "main", profile, flags, 0, &binary, &errorMessage);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000995
996 if (errorMessage)
997 {
998 const char *message = (const char*)errorMessage->GetBufferPointer();
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000999
daniel@transgaming.com0df16872010-05-12 16:51:08 +00001000 appendToInfoLog("%s\n", message);
daniel@transgaming.com0599dc62010-03-21 04:31:36 +00001001 TRACE("\n%s", hlsl);
1002 TRACE("\n%s", message);
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001003
1004 errorMessage->Release();
1005 errorMessage = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001006 }
1007
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001008
1009 if (FAILED(result))
1010 {
1011 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1012 {
1013 error(GL_OUT_OF_MEMORY);
1014 }
1015
1016 return NULL;
1017 }
1018
1019 result = D3DXGetShaderConstantTable(static_cast<const DWORD*>(binary->GetBufferPointer()), constantTable);
1020
1021 if (FAILED(result))
1022 {
1023 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1024 {
1025 error(GL_OUT_OF_MEMORY);
1026 }
1027
1028 binary->Release();
1029
1030 return NULL;
1031 }
1032
1033 return binary;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001034}
1035
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001036// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
1037// Returns the number of used varying registers, or -1 if unsuccesful
1038int Program::packVaryings(const Varying *packing[][4])
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001039{
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001040 Context *context = getContext();
1041 const int maxVaryingVectors = context->getMaximumVaryingVectors();
1042
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001043 for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.end(); varying++)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001044 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001045 int n = VariableRowCount(varying->type) * varying->size;
1046 int m = VariableColumnCount(varying->type);
1047 bool success = false;
daniel@transgaming.com51d0dc22010-04-29 03:39:11 +00001048
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001049 if (m == 2 || m == 3 || m == 4)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001050 {
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001051 for (int r = 0; r <= maxVaryingVectors - n && !success; r++)
daniel@transgaming.com51d0dc22010-04-29 03:39:11 +00001052 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001053 bool available = true;
1054
1055 for (int y = 0; y < n && available; y++)
1056 {
1057 for (int x = 0; x < m && available; x++)
1058 {
1059 if (packing[r + y][x])
1060 {
1061 available = false;
1062 }
1063 }
1064 }
1065
1066 if (available)
1067 {
1068 varying->reg = r;
1069 varying->col = 0;
1070
1071 for (int y = 0; y < n; y++)
1072 {
1073 for (int x = 0; x < m; x++)
1074 {
1075 packing[r + y][x] = &*varying;
1076 }
1077 }
1078
1079 success = true;
1080 }
daniel@transgaming.com51d0dc22010-04-29 03:39:11 +00001081 }
1082
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001083 if (!success && m == 2)
1084 {
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001085 for (int r = maxVaryingVectors - n; r >= 0 && !success; r--)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001086 {
1087 bool available = true;
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001088
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001089 for (int y = 0; y < n && available; y++)
1090 {
1091 for (int x = 2; x < 4 && available; x++)
1092 {
1093 if (packing[r + y][x])
1094 {
1095 available = false;
1096 }
1097 }
1098 }
1099
1100 if (available)
1101 {
1102 varying->reg = r;
1103 varying->col = 2;
1104
1105 for (int y = 0; y < n; y++)
1106 {
1107 for (int x = 2; x < 4; x++)
1108 {
1109 packing[r + y][x] = &*varying;
1110 }
1111 }
1112
1113 success = true;
1114 }
1115 }
1116 }
1117 }
1118 else if (m == 1)
1119 {
1120 int space[4] = {0};
1121
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001122 for (int y = 0; y < maxVaryingVectors; y++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001123 {
1124 for (int x = 0; x < 4; x++)
1125 {
1126 space[x] += packing[y][x] ? 0 : 1;
1127 }
1128 }
1129
1130 int column = 0;
1131
1132 for (int x = 0; x < 4; x++)
1133 {
daniel@transgaming.com11dd5dd2011-02-11 13:28:14 +00001134 if (space[x] >= n && space[x] < space[column])
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001135 {
1136 column = x;
1137 }
1138 }
1139
daniel@transgaming.com11dd5dd2011-02-11 13:28:14 +00001140 if (space[column] >= n)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001141 {
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001142 for (int r = 0; r < maxVaryingVectors; r++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001143 {
1144 if (!packing[r][column])
1145 {
1146 varying->reg = r;
1147
1148 for (int y = r; y < r + n; y++)
1149 {
1150 packing[y][column] = &*varying;
1151 }
1152
1153 break;
1154 }
1155 }
1156
1157 varying->col = column;
1158
1159 success = true;
1160 }
1161 }
1162 else UNREACHABLE();
1163
1164 if (!success)
1165 {
1166 appendToInfoLog("Could not pack varying %s", varying->name.c_str());
1167
1168 return -1;
1169 }
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001170 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001171
1172 // Return the number of used registers
1173 int registers = 0;
1174
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001175 for (int r = 0; r < maxVaryingVectors; r++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001176 {
1177 if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
1178 {
1179 registers++;
1180 }
1181 }
1182
1183 return registers;
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001184}
1185
1186bool Program::linkVaryings()
1187{
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001188 if (mPixelHLSL.empty() || mVertexHLSL.empty())
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001189 {
1190 return false;
1191 }
1192
daniel@transgaming.com97750022011-02-11 13:23:13 +00001193 // Reset the varying register assignments
1194 for (VaryingList::iterator fragVar = mFragmentShader->varyings.begin(); fragVar != mFragmentShader->varyings.end(); fragVar++)
1195 {
1196 fragVar->reg = -1;
1197 fragVar->col = -1;
1198 }
1199
1200 for (VaryingList::iterator vtxVar = mVertexShader->varyings.begin(); vtxVar != mVertexShader->varyings.end(); vtxVar++)
1201 {
1202 vtxVar->reg = -1;
1203 vtxVar->col = -1;
1204 }
1205
1206 // Map the varyings to the register file
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001207 const Varying *packing[MAX_VARYING_VECTORS_SM3][4] = {NULL};
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001208 int registers = packVaryings(packing);
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001209
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001210 if (registers < 0)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001211 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001212 return false;
1213 }
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001214
daniel@transgaming.com97750022011-02-11 13:23:13 +00001215 // Write the HLSL input/output declarations
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001216 Context *context = getContext();
1217 const bool sm3 = context->supportsShaderModel3();
1218 const int maxVaryingVectors = context->getMaximumVaryingVectors();
1219
1220 if (registers == maxVaryingVectors && mFragmentShader->mUsesFragCoord)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001221 {
1222 appendToInfoLog("No varying registers left to support gl_FragCoord");
1223
1224 return false;
1225 }
1226
1227 for (VaryingList::iterator input = mFragmentShader->varyings.begin(); input != mFragmentShader->varyings.end(); input++)
1228 {
1229 bool matched = false;
1230
1231 for (VaryingList::iterator output = mVertexShader->varyings.begin(); output != mVertexShader->varyings.end(); output++)
1232 {
1233 if (output->name == input->name)
1234 {
1235 if (output->type != input->type || output->size != input->size)
1236 {
1237 appendToInfoLog("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str());
1238
1239 return false;
1240 }
1241
1242 output->reg = input->reg;
1243 output->col = input->col;
1244
1245 matched = true;
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001246 break;
1247 }
1248 }
1249
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001250 if (!matched)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001251 {
daniel@transgaming.com97750022011-02-11 13:23:13 +00001252 appendToInfoLog("Fragment varying %s does not match any vertex varying", input->name.c_str());
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001253
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001254 return false;
1255 }
1256 }
1257
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001258 std::string varyingSemantic = (sm3 ? "COLOR" : "TEXCOORD");
1259
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001260 mVertexHLSL += "struct VS_INPUT\n"
1261 "{\n";
1262
1263 int semanticIndex = 0;
1264 for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
1265 {
1266 switch (attribute->type)
1267 {
1268 case GL_FLOAT: mVertexHLSL += " float "; break;
1269 case GL_FLOAT_VEC2: mVertexHLSL += " float2 "; break;
1270 case GL_FLOAT_VEC3: mVertexHLSL += " float3 "; break;
1271 case GL_FLOAT_VEC4: mVertexHLSL += " float4 "; break;
1272 case GL_FLOAT_MAT2: mVertexHLSL += " float2x2 "; break;
1273 case GL_FLOAT_MAT3: mVertexHLSL += " float3x3 "; break;
1274 case GL_FLOAT_MAT4: mVertexHLSL += " float4x4 "; break;
1275 default: UNREACHABLE();
1276 }
1277
1278 mVertexHLSL += decorate(attribute->name) + " : TEXCOORD" + str(semanticIndex) + ";\n";
1279
1280 semanticIndex += VariableRowCount(attribute->type);
1281 }
1282
1283 mVertexHLSL += "};\n"
1284 "\n"
1285 "struct VS_OUTPUT\n"
1286 "{\n"
1287 " float4 gl_Position : POSITION;\n";
1288
1289 for (int r = 0; r < registers; r++)
1290 {
1291 int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1));
1292
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001293 mVertexHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001294 }
1295
1296 if (mFragmentShader->mUsesFragCoord)
1297 {
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001298 mVertexHLSL += " float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
1299 }
1300
1301 if (mVertexShader->mUsesPointSize && sm3)
1302 {
1303 mVertexHLSL += " float gl_PointSize : PSIZE;\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001304 }
1305
1306 mVertexHLSL += "};\n"
1307 "\n"
1308 "VS_OUTPUT main(VS_INPUT input)\n"
1309 "{\n";
1310
1311 for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
1312 {
1313 mVertexHLSL += " " + decorate(attribute->name) + " = ";
1314
1315 if (VariableRowCount(attribute->type) > 1) // Matrix
1316 {
1317 mVertexHLSL += "transpose";
1318 }
1319
1320 mVertexHLSL += "(input." + decorate(attribute->name) + ");\n";
1321 }
1322
1323 mVertexHLSL += "\n"
1324 " gl_main();\n"
1325 "\n"
1326 " VS_OUTPUT output;\n"
1327 " output.gl_Position.x = gl_Position.x - dx_HalfPixelSize.x * gl_Position.w;\n"
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001328 " output.gl_Position.y = gl_Position.y - dx_HalfPixelSize.y * gl_Position.w;\n"
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001329 " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
1330 " output.gl_Position.w = gl_Position.w;\n";
1331
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001332 if (mVertexShader->mUsesPointSize && sm3)
1333 {
1334 mVertexHLSL += " output.gl_PointSize = clamp(gl_PointSize, 1.0, " + str((int)ALIASED_POINT_SIZE_RANGE_MAX_SM3) + ");\n";
1335 }
1336
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001337 if (mFragmentShader->mUsesFragCoord)
1338 {
1339 mVertexHLSL += " output.gl_FragCoord = gl_Position;\n";
1340 }
1341
1342 for (VaryingList::iterator varying = mVertexShader->varyings.begin(); varying != mVertexShader->varyings.end(); varying++)
1343 {
1344 if (varying->reg >= 0)
1345 {
1346 for (int i = 0; i < varying->size; i++)
1347 {
1348 int rows = VariableRowCount(varying->type);
1349
1350 for (int j = 0; j < rows; j++)
1351 {
1352 int r = varying->reg + i * rows + j;
1353 mVertexHLSL += " output.v" + str(r);
1354
1355 bool sharedRegister = false; // Register used by multiple varyings
1356
1357 for (int x = 0; x < 4; x++)
1358 {
1359 if (packing[r][x] && packing[r][x] != packing[r][0])
1360 {
1361 sharedRegister = true;
1362 break;
1363 }
1364 }
1365
1366 if(sharedRegister)
1367 {
1368 mVertexHLSL += ".";
1369
1370 for (int x = 0; x < 4; x++)
1371 {
1372 if (packing[r][x] == &*varying)
1373 {
1374 switch(x)
1375 {
1376 case 0: mVertexHLSL += "x"; break;
1377 case 1: mVertexHLSL += "y"; break;
1378 case 2: mVertexHLSL += "z"; break;
1379 case 3: mVertexHLSL += "w"; break;
1380 }
1381 }
1382 }
1383 }
1384
1385 mVertexHLSL += " = " + varying->name;
1386
1387 if (varying->array)
1388 {
1389 mVertexHLSL += "[" + str(i) + "]";
1390 }
1391
1392 if (rows > 1)
1393 {
1394 mVertexHLSL += "[" + str(j) + "]";
1395 }
1396
1397 mVertexHLSL += ";\n";
1398 }
1399 }
1400 }
1401 }
1402
1403 mVertexHLSL += "\n"
1404 " return output;\n"
1405 "}\n";
1406
1407 mPixelHLSL += "struct PS_INPUT\n"
1408 "{\n";
1409
1410 for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.end(); varying++)
1411 {
1412 if (varying->reg >= 0)
1413 {
1414 for (int i = 0; i < varying->size; i++)
1415 {
1416 int rows = VariableRowCount(varying->type);
1417 for (int j = 0; j < rows; j++)
1418 {
1419 std::string n = str(varying->reg + i * rows + j);
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001420 mPixelHLSL += " float4 v" + n + " : " + varyingSemantic + n + ";\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001421 }
1422 }
1423 }
1424 else UNREACHABLE();
1425 }
1426
1427 if (mFragmentShader->mUsesFragCoord)
1428 {
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001429 mPixelHLSL += " float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001430 if (sm3) {
daniel@transgaming.com996675c2010-11-17 13:06:29 +00001431 mPixelHLSL += " float2 dx_VPos : VPOS;\n";
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001432 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001433 }
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001434
1435 if (mFragmentShader->mUsesPointCoord && sm3)
1436 {
1437 mPixelHLSL += " float2 gl_PointCoord : TEXCOORD0;\n";
1438 }
1439
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001440 if (mFragmentShader->mUsesFrontFacing)
1441 {
1442 mPixelHLSL += " float vFace : VFACE;\n";
1443 }
1444
1445 mPixelHLSL += "};\n"
1446 "\n"
1447 "struct PS_OUTPUT\n"
1448 "{\n"
1449 " float4 gl_Color[1] : COLOR;\n"
1450 "};\n"
1451 "\n"
1452 "PS_OUTPUT main(PS_INPUT input)\n"
1453 "{\n";
1454
1455 if (mFragmentShader->mUsesFragCoord)
1456 {
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001457 mPixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n";
1458 if (sm3) {
1459 mPixelHLSL += " gl_FragCoord.x = input.dx_VPos.x;\n"
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001460 " gl_FragCoord.y = 2.0 * dx_Viewport.y - input.dx_VPos.y;\n";
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001461 } else {
1462 mPixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_Viewport.x + dx_Viewport.z;\n"
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001463 " gl_FragCoord.y = -(input.gl_FragCoord.y * rhw) * dx_Viewport.y + dx_Viewport.w;\n";
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001464 }
1465 mPixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_Depth.x + dx_Depth.y;\n"
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001466 " gl_FragCoord.w = rhw;\n";
1467 }
1468
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001469 if (mFragmentShader->mUsesPointCoord && sm3)
1470 {
apatrick@chromium.orgda4d0492011-01-22 00:16:10 +00001471 mPixelHLSL += " gl_PointCoord = input.gl_PointCoord;\n";
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001472 }
1473
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001474 if (mFragmentShader->mUsesFrontFacing)
1475 {
1476 mPixelHLSL += " gl_FrontFacing = dx_PointsOrLines || (dx_FrontCCW ? (input.vFace >= 0.0) : (input.vFace <= 0.0));\n";
1477 }
1478
1479 for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.end(); varying++)
1480 {
1481 if (varying->reg >= 0)
1482 {
1483 for (int i = 0; i < varying->size; i++)
1484 {
1485 int rows = VariableRowCount(varying->type);
1486 for (int j = 0; j < rows; j++)
1487 {
1488 std::string n = str(varying->reg + i * rows + j);
1489 mPixelHLSL += " " + varying->name;
1490
1491 if (varying->array)
1492 {
1493 mPixelHLSL += "[" + str(i) + "]";
1494 }
1495
1496 if (rows > 1)
1497 {
1498 mPixelHLSL += "[" + str(j) + "]";
1499 }
1500
1501 mPixelHLSL += " = input.v" + n + ";\n";
1502 }
1503 }
1504 }
1505 else UNREACHABLE();
1506 }
1507
1508 mPixelHLSL += "\n"
1509 " gl_main();\n"
1510 "\n"
1511 " PS_OUTPUT output;\n"
1512 " output.gl_Color[0] = gl_Color[0];\n"
1513 "\n"
1514 " return output;\n"
1515 "}\n";
1516
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001517 return true;
1518}
1519
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001520// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
1521// compiling them into binaries, determining the attribute mappings, and collecting
1522// a list of uniforms
1523void Program::link()
1524{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001525 unlink();
1526
1527 if (!mFragmentShader || !mFragmentShader->isCompiled())
1528 {
1529 return;
1530 }
1531
1532 if (!mVertexShader || !mVertexShader->isCompiled())
1533 {
1534 return;
1535 }
1536
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001537 mPixelHLSL = mFragmentShader->getHLSL();
1538 mVertexHLSL = mVertexShader->getHLSL();
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001539
1540 if (!linkVaryings())
1541 {
1542 return;
1543 }
1544
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001545 Context *context = getContext();
1546 const char *vertexProfile = context->supportsShaderModel3() ? "vs_3_0" : "vs_2_0";
1547 const char *pixelProfile = context->supportsShaderModel3() ? "ps_3_0" : "ps_2_0";
1548
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001549 ID3D10Blob *vertexBinary = compileToBinary(mVertexHLSL.c_str(), vertexProfile, &mConstantTableVS);
1550 ID3D10Blob *pixelBinary = compileToBinary(mPixelHLSL.c_str(), pixelProfile, &mConstantTablePS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001551
1552 if (vertexBinary && pixelBinary)
1553 {
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00001554 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001555 HRESULT vertexResult = device->CreateVertexShader((DWORD*)vertexBinary->GetBufferPointer(), &mVertexExecutable);
1556 HRESULT pixelResult = device->CreatePixelShader((DWORD*)pixelBinary->GetBufferPointer(), &mPixelExecutable);
1557
1558 if (vertexResult == D3DERR_OUTOFVIDEOMEMORY || vertexResult == E_OUTOFMEMORY || pixelResult == D3DERR_OUTOFVIDEOMEMORY || pixelResult == E_OUTOFMEMORY)
1559 {
1560 return error(GL_OUT_OF_MEMORY);
1561 }
1562
1563 ASSERT(SUCCEEDED(vertexResult) && SUCCEEDED(pixelResult));
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001564
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001565 vertexBinary->Release();
1566 pixelBinary->Release();
1567 vertexBinary = NULL;
1568 pixelBinary = NULL;
1569
1570 if (mVertexExecutable && mPixelExecutable)
1571 {
1572 if (!linkAttributes())
1573 {
1574 return;
1575 }
1576
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001577 if (!linkUniforms(mConstantTablePS))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001578 {
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001579 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001580 }
1581
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001582 if (!linkUniforms(mConstantTableVS))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001583 {
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001584 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001585 }
1586
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +00001587 // these uniforms are searched as already-decorated because gl_ and dx_
1588 // are reserved prefixes, and do not receive additional decoration
daniel@transgaming.com31754962010-11-28 02:02:52 +00001589 mDxDepthRangeLocation = getUniformLocation("dx_DepthRange", true);
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +00001590 mDxDepthLocation = getUniformLocation("dx_Depth", true);
daniel@transgaming.com162267d2010-07-28 19:20:48 +00001591 mDxViewportLocation = getUniformLocation("dx_Viewport", true);
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +00001592 mDxHalfPixelSizeLocation = getUniformLocation("dx_HalfPixelSize", true);
1593 mDxFrontCCWLocation = getUniformLocation("dx_FrontCCW", true);
1594 mDxPointsOrLinesLocation = getUniformLocation("dx_PointsOrLines", true);
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001595
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001596 mLinked = true; // Success
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001597 }
1598 }
1599}
1600
1601// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
1602bool Program::linkAttributes()
1603{
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001604 unsigned int usedLocations = 0;
1605
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001606 // Link attributes that have a binding location
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001607 for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001608 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001609 int location = getAttributeBinding(attribute->name);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001610
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001611 if (location != -1) // Set by glBindAttribLocation
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001612 {
daniel@transgaming.com85423182010-04-22 13:35:27 +00001613 if (!mLinkedAttribute[location].name.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001614 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001615 // Multiple active attributes bound to the same location; not an error
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001616 }
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001617
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001618 mLinkedAttribute[location] = *attribute;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001619
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001620 int rows = VariableRowCount(attribute->type);
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001621
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001622 if (rows + location > MAX_VERTEX_ATTRIBS)
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001623 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001624 appendToInfoLog("Active attribute (%s) at location %d is too big to fit", attribute->name.c_str(), location);
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001625
1626 return false;
1627 }
1628
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001629 for (int i = 0; i < rows; i++)
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001630 {
1631 usedLocations |= 1 << (location + i);
1632 }
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001633 }
1634 }
1635
1636 // Link attributes that don't have a binding location
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001637 for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001638 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001639 int location = getAttributeBinding(attribute->name);
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001640
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001641 if (location == -1) // Not set by glBindAttribLocation
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001642 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001643 int rows = VariableRowCount(attribute->type);
1644 int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001645
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001646 if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001647 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001648 appendToInfoLog("Too many active attributes (%s)", attribute->name.c_str());
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001649
1650 return false; // Fail to link
1651 }
1652
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001653 mLinkedAttribute[availableIndex] = *attribute;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001654 }
1655 }
1656
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001657 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001658 {
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001659 int index = mVertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001660 int rows = std::max(VariableRowCount(mLinkedAttribute[attributeIndex].type), 1);
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001661
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001662 for (int r = 0; r < rows; r++)
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001663 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001664 mSemanticIndex[attributeIndex++] = index++;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001665 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001666 }
1667
1668 return true;
1669}
1670
daniel@transgaming.com85423182010-04-22 13:35:27 +00001671int Program::getAttributeBinding(const std::string &name)
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001672{
1673 for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
1674 {
1675 if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
1676 {
1677 return location;
1678 }
1679 }
1680
1681 return -1;
1682}
1683
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001684bool Program::linkUniforms(ID3DXConstantTable *constantTable)
1685{
1686 D3DXCONSTANTTABLE_DESC constantTableDescription;
1687 D3DXCONSTANT_DESC constantDescription;
1688 UINT descriptionCount = 1;
1689
1690 constantTable->GetDesc(&constantTableDescription);
1691
1692 for (unsigned int constantIndex = 0; constantIndex < constantTableDescription.Constants; constantIndex++)
1693 {
1694 D3DXHANDLE constantHandle = constantTable->GetConstant(0, constantIndex);
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001695 HRESULT result = constantTable->GetConstantDesc(constantHandle, &constantDescription, &descriptionCount);
1696 ASSERT(SUCCEEDED(result));
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001697
1698 if (!defineUniform(constantHandle, constantDescription))
1699 {
1700 return false;
1701 }
1702 }
1703
1704 return true;
1705}
1706
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001707// Adds the description of a constant found in the binary shader to the list of uniforms
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001708// Returns true if succesful (uniform not already defined)
1709bool Program::defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT_DESC &constantDescription, std::string name)
1710{
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001711 if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
1712 {
daniel@transgaming.com41b2fbd2010-12-13 18:27:12 +00001713 for (unsigned int samplerIndex = constantDescription.RegisterIndex; samplerIndex < constantDescription.RegisterIndex + constantDescription.RegisterCount; samplerIndex++)
1714 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001715 if (mConstantTablePS->GetConstantByName(NULL, constantDescription.Name) != NULL)
1716 {
daniel@transgaming.com424bb492011-05-11 15:36:59 +00001717 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
1718 {
1719 mSamplersPS[samplerIndex].active = true;
1720 mSamplersPS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
1721 mSamplersPS[samplerIndex].logicalTextureUnit = 0;
1722 }
1723 else
1724 {
1725 appendToInfoLog("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
1726 return false;
1727 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001728 }
1729
1730 if (mConstantTableVS->GetConstantByName(NULL, constantDescription.Name) != NULL)
1731 {
daniel@transgaming.com424bb492011-05-11 15:36:59 +00001732 if (samplerIndex < getContext()->getMaximumVertexTextureImageUnits())
1733 {
1734 mSamplersVS[samplerIndex].active = true;
1735 mSamplersVS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
1736 mSamplersVS[samplerIndex].logicalTextureUnit = 0;
1737 }
1738 else
1739 {
1740 appendToInfoLog("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", getContext()->getMaximumVertexTextureImageUnits());
1741 return false;
1742 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001743 }
daniel@transgaming.com41b2fbd2010-12-13 18:27:12 +00001744 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001745 }
1746
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001747 switch(constantDescription.Class)
1748 {
1749 case D3DXPC_STRUCT:
1750 {
daniel@transgaming.comce864422010-11-18 13:16:49 +00001751 for (unsigned int arrayIndex = 0; arrayIndex < constantDescription.Elements; arrayIndex++)
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001752 {
daniel@transgaming.comce864422010-11-18 13:16:49 +00001753 for (unsigned int field = 0; field < constantDescription.StructMembers; field++)
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001754 {
daniel@transgaming.comce864422010-11-18 13:16:49 +00001755 D3DXHANDLE fieldHandle = mConstantTablePS->GetConstant(constantHandle, field);
1756
1757 D3DXCONSTANT_DESC fieldDescription;
1758 UINT descriptionCount = 1;
1759
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001760 HRESULT result = mConstantTablePS->GetConstantDesc(fieldHandle, &fieldDescription, &descriptionCount);
1761 ASSERT(SUCCEEDED(result));
daniel@transgaming.comce864422010-11-18 13:16:49 +00001762
1763 std::string structIndex = (constantDescription.Elements > 1) ? ("[" + str(arrayIndex) + "]") : "";
1764
1765 if (!defineUniform(fieldHandle, fieldDescription, name + constantDescription.Name + structIndex + "."))
1766 {
1767 return false;
1768 }
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001769 }
1770 }
1771
1772 return true;
1773 }
1774 case D3DXPC_SCALAR:
1775 case D3DXPC_VECTOR:
1776 case D3DXPC_MATRIX_COLUMNS:
1777 case D3DXPC_OBJECT:
1778 return defineUniform(constantDescription, name + constantDescription.Name);
1779 default:
1780 UNREACHABLE();
1781 return false;
1782 }
1783}
1784
1785bool Program::defineUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name)
1786{
1787 Uniform *uniform = createUniform(constantDescription, name);
1788
1789 if(!uniform)
1790 {
1791 return false;
1792 }
1793
1794 // Check if already defined
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +00001795 GLint location = getUniformLocation(name.c_str(), true);
daniel@transgaming.com0361b922010-03-28 19:36:15 +00001796 GLenum type = uniform->type;
daniel@transgaming.comc7d8a932010-03-16 06:16:45 +00001797
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001798 if (location >= 0)
1799 {
1800 delete uniform;
1801
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00001802 if (mUniforms[mUniformIndex[location].index]->type != type)
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001803 {
1804 return false;
1805 }
1806 else
1807 {
1808 return true;
1809 }
1810 }
1811
1812 mUniforms.push_back(uniform);
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00001813 unsigned int uniformIndex = mUniforms.size() - 1;
1814
1815 for (unsigned int i = 0; i < uniform->arraySize; ++i)
1816 {
1817 mUniformIndex.push_back(UniformLocation(name, i, uniformIndex));
1818 }
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001819
1820 return true;
1821}
1822
1823Uniform *Program::createUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001824{
1825 if (constantDescription.Rows == 1) // Vectors and scalars
1826 {
1827 switch (constantDescription.Type)
1828 {
1829 case D3DXPT_SAMPLER2D:
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +00001830 switch (constantDescription.Columns)
1831 {
1832 case 1: return new Uniform(GL_SAMPLER_2D, name, constantDescription.Elements);
1833 default: UNREACHABLE();
1834 }
1835 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001836 case D3DXPT_SAMPLERCUBE:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001837 switch (constantDescription.Columns)
1838 {
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +00001839 case 1: return new Uniform(GL_SAMPLER_CUBE, name, constantDescription.Elements);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00001840 default: UNREACHABLE();
1841 }
1842 break;
1843 case D3DXPT_BOOL:
1844 switch (constantDescription.Columns)
1845 {
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00001846 case 1: return new Uniform(GL_BOOL, name, constantDescription.Elements);
1847 case 2: return new Uniform(GL_BOOL_VEC2, name, constantDescription.Elements);
1848 case 3: return new Uniform(GL_BOOL_VEC3, name, constantDescription.Elements);
1849 case 4: return new Uniform(GL_BOOL_VEC4, name, constantDescription.Elements);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00001850 default: UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001851 }
1852 break;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00001853 case D3DXPT_INT:
1854 switch (constantDescription.Columns)
1855 {
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00001856 case 1: return new Uniform(GL_INT, name, constantDescription.Elements);
1857 case 2: return new Uniform(GL_INT_VEC2, name, constantDescription.Elements);
1858 case 3: return new Uniform(GL_INT_VEC3, name, constantDescription.Elements);
1859 case 4: return new Uniform(GL_INT_VEC4, name, constantDescription.Elements);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00001860 default: UNREACHABLE();
1861 }
1862 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001863 case D3DXPT_FLOAT:
1864 switch (constantDescription.Columns)
1865 {
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00001866 case 1: return new Uniform(GL_FLOAT, name, constantDescription.Elements);
1867 case 2: return new Uniform(GL_FLOAT_VEC2, name, constantDescription.Elements);
1868 case 3: return new Uniform(GL_FLOAT_VEC3, name, constantDescription.Elements);
1869 case 4: return new Uniform(GL_FLOAT_VEC4, name, constantDescription.Elements);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001870 default: UNREACHABLE();
1871 }
1872 break;
1873 default:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001874 UNREACHABLE();
1875 }
1876 }
1877 else if (constantDescription.Rows == constantDescription.Columns) // Square matrices
1878 {
1879 switch (constantDescription.Type)
1880 {
1881 case D3DXPT_FLOAT:
1882 switch (constantDescription.Rows)
1883 {
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00001884 case 2: return new Uniform(GL_FLOAT_MAT2, name, constantDescription.Elements);
1885 case 3: return new Uniform(GL_FLOAT_MAT3, name, constantDescription.Elements);
1886 case 4: return new Uniform(GL_FLOAT_MAT4, name, constantDescription.Elements);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001887 default: UNREACHABLE();
1888 }
1889 break;
1890 default: UNREACHABLE();
1891 }
1892 }
1893 else UNREACHABLE();
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001894
1895 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001896}
1897
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00001898// This method needs to match OutputHLSL::decorate
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001899std::string Program::decorate(const std::string &string)
1900{
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001901 if (string.substr(0, 3) != "gl_" && string.substr(0, 3) != "dx_")
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001902 {
1903 return "_" + string;
1904 }
1905 else
1906 {
1907 return string;
1908 }
1909}
1910
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00001911std::string Program::undecorate(const std::string &string)
1912{
1913 if (string.substr(0, 1) == "_")
1914 {
1915 return string.substr(1);
1916 }
1917 else
1918 {
1919 return string;
1920 }
1921}
1922
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00001923bool Program::applyUniform1bv(GLint location, GLsizei count, const GLboolean *v)
1924{
1925 BOOL *vector = new BOOL[count];
1926 for (int i = 0; i < count; i++)
1927 {
1928 if (v[i] == GL_FALSE)
1929 vector[i] = 0;
1930 else
1931 vector[i] = 1;
1932 }
1933
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00001934 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
1935
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00001936 D3DXHANDLE constantPS;
1937 D3DXHANDLE constantVS;
1938 getConstantHandles(targetUniform, &constantPS, &constantVS);
1939
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00001940 IDirect3DDevice9 *device = getDevice();
1941
1942 if (constantPS)
1943 {
1944 mConstantTablePS->SetBoolArray(device, constantPS, vector, count);
1945 }
1946
1947 if (constantVS)
1948 {
1949 mConstantTableVS->SetBoolArray(device, constantVS, vector, count);
1950 }
1951
1952 delete [] vector;
1953
1954 return true;
1955}
1956
1957bool Program::applyUniform2bv(GLint location, GLsizei count, const GLboolean *v)
1958{
1959 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
1960
1961 for (int i = 0; i < count; i++)
1962 {
1963 vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
1964 (v[1] == GL_FALSE ? 0.0f : 1.0f), 0, 0);
1965
1966 v += 2;
1967 }
1968
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00001969 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
1970
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00001971 D3DXHANDLE constantPS;
1972 D3DXHANDLE constantVS;
1973 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00001974 IDirect3DDevice9 *device = getDevice();
1975
1976 if (constantPS)
1977 {
1978 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
1979 }
1980
1981 if (constantVS)
1982 {
1983 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
1984 }
1985
1986 delete[] vector;
1987
1988 return true;
1989}
1990
1991bool Program::applyUniform3bv(GLint location, GLsizei count, const GLboolean *v)
1992{
1993 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
1994
1995 for (int i = 0; i < count; i++)
1996 {
1997 vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
1998 (v[1] == GL_FALSE ? 0.0f : 1.0f),
1999 (v[2] == GL_FALSE ? 0.0f : 1.0f), 0);
2000
2001 v += 3;
2002 }
2003
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002004 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2005
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002006 D3DXHANDLE constantPS;
2007 D3DXHANDLE constantVS;
2008 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002009 IDirect3DDevice9 *device = getDevice();
2010
2011 if (constantPS)
2012 {
2013 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2014 }
2015
2016 if (constantVS)
2017 {
2018 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2019 }
2020
2021 delete[] vector;
2022
2023 return true;
2024}
2025
2026bool Program::applyUniform4bv(GLint location, GLsizei count, const GLboolean *v)
2027{
2028 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2029
2030 for (int i = 0; i < count; i++)
2031 {
2032 vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
2033 (v[1] == GL_FALSE ? 0.0f : 1.0f),
2034 (v[2] == GL_FALSE ? 0.0f : 1.0f),
2035 (v[3] == GL_FALSE ? 0.0f : 1.0f));
2036
2037 v += 3;
2038 }
2039
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002040 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2041
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002042 D3DXHANDLE constantPS;
2043 D3DXHANDLE constantVS;
2044 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002045 IDirect3DDevice9 *device = getDevice();
2046
2047 if (constantPS)
2048 {
2049 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2050 }
2051
2052 if (constantVS)
2053 {
2054 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2055 }
2056
2057 delete [] vector;
2058
2059 return true;
2060}
2061
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002062bool Program::applyUniform1fv(GLint location, GLsizei count, const GLfloat *v)
2063{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002064 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2065
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002066 D3DXHANDLE constantPS;
2067 D3DXHANDLE constantVS;
2068 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002069 IDirect3DDevice9 *device = getDevice();
2070
2071 if (constantPS)
2072 {
2073 mConstantTablePS->SetFloatArray(device, constantPS, v, count);
2074 }
2075
2076 if (constantVS)
2077 {
2078 mConstantTableVS->SetFloatArray(device, constantVS, v, count);
2079 }
2080
2081 return true;
2082}
2083
2084bool Program::applyUniform2fv(GLint location, GLsizei count, const GLfloat *v)
2085{
2086 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2087
2088 for (int i = 0; i < count; i++)
2089 {
2090 vector[i] = D3DXVECTOR4(v[0], v[1], 0, 0);
2091
2092 v += 2;
2093 }
2094
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002095 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2096
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002097 D3DXHANDLE constantPS;
2098 D3DXHANDLE constantVS;
2099 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002100 IDirect3DDevice9 *device = getDevice();
2101
2102 if (constantPS)
2103 {
2104 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2105 }
2106
2107 if (constantVS)
2108 {
2109 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2110 }
2111
2112 delete[] vector;
2113
2114 return true;
2115}
2116
2117bool Program::applyUniform3fv(GLint location, GLsizei count, const GLfloat *v)
2118{
2119 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2120
2121 for (int i = 0; i < count; i++)
2122 {
2123 vector[i] = D3DXVECTOR4(v[0], v[1], v[2], 0);
2124
2125 v += 3;
2126 }
2127
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002128 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2129
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002130 D3DXHANDLE constantPS;
2131 D3DXHANDLE constantVS;
2132 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002133 IDirect3DDevice9 *device = getDevice();
2134
2135 if (constantPS)
2136 {
2137 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2138 }
2139
2140 if (constantVS)
2141 {
2142 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2143 }
2144
2145 delete[] vector;
2146
2147 return true;
2148}
2149
2150bool Program::applyUniform4fv(GLint location, GLsizei count, const GLfloat *v)
2151{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002152 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2153
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002154 D3DXHANDLE constantPS;
2155 D3DXHANDLE constantVS;
2156 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002157 IDirect3DDevice9 *device = getDevice();
2158
2159 if (constantPS)
2160 {
2161 mConstantTablePS->SetVectorArray(device, constantPS, (D3DXVECTOR4*)v, count);
2162 }
2163
2164 if (constantVS)
2165 {
2166 mConstantTableVS->SetVectorArray(device, constantVS, (D3DXVECTOR4*)v, count);
2167 }
2168
2169 return true;
2170}
2171
2172bool Program::applyUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
2173{
2174 D3DXMATRIX *matrix = new D3DXMATRIX[count];
2175
2176 for (int i = 0; i < count; i++)
2177 {
2178 matrix[i] = D3DXMATRIX(value[0], value[2], 0, 0,
2179 value[1], value[3], 0, 0,
2180 0, 0, 1, 0,
2181 0, 0, 0, 1);
2182
2183 value += 4;
2184 }
2185
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002186 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2187
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002188 D3DXHANDLE constantPS;
2189 D3DXHANDLE constantVS;
2190 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002191 IDirect3DDevice9 *device = getDevice();
2192
2193 if (constantPS)
2194 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002195 mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002196 }
2197
2198 if (constantVS)
2199 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002200 mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002201 }
2202
2203 delete[] matrix;
2204
2205 return true;
2206}
2207
2208bool Program::applyUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
2209{
2210 D3DXMATRIX *matrix = new D3DXMATRIX[count];
2211
2212 for (int i = 0; i < count; i++)
2213 {
2214 matrix[i] = D3DXMATRIX(value[0], value[3], value[6], 0,
2215 value[1], value[4], value[7], 0,
2216 value[2], value[5], value[8], 0,
2217 0, 0, 0, 1);
2218
2219 value += 9;
2220 }
2221
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002222 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2223
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002224 D3DXHANDLE constantPS;
2225 D3DXHANDLE constantVS;
2226 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002227 IDirect3DDevice9 *device = getDevice();
2228
2229 if (constantPS)
2230 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002231 mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002232 }
2233
2234 if (constantVS)
2235 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002236 mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002237 }
2238
2239 delete[] matrix;
2240
2241 return true;
2242}
2243
2244bool Program::applyUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
2245{
2246 D3DXMATRIX *matrix = new D3DXMATRIX[count];
2247
2248 for (int i = 0; i < count; i++)
2249 {
2250 matrix[i] = D3DXMATRIX(value[0], value[4], value[8], value[12],
2251 value[1], value[5], value[9], value[13],
2252 value[2], value[6], value[10], value[14],
2253 value[3], value[7], value[11], value[15]);
2254
2255 value += 16;
2256 }
2257
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002258 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2259
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002260 D3DXHANDLE constantPS;
2261 D3DXHANDLE constantVS;
2262 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002263 IDirect3DDevice9 *device = getDevice();
2264
2265 if (constantPS)
2266 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002267 mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002268 }
2269
2270 if (constantVS)
2271 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002272 mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002273 }
2274
2275 delete[] matrix;
2276
2277 return true;
2278}
2279
2280bool Program::applyUniform1iv(GLint location, GLsizei count, const GLint *v)
2281{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002282 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2283
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002284 D3DXHANDLE constantPS;
2285 D3DXHANDLE constantVS;
2286 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002287 IDirect3DDevice9 *device = getDevice();
2288
2289 if (constantPS)
2290 {
2291 D3DXCONSTANT_DESC constantDescription;
2292 UINT descriptionCount = 1;
2293 HRESULT result = mConstantTablePS->GetConstantDesc(constantPS, &constantDescription, &descriptionCount);
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002294 ASSERT(SUCCEEDED(result));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002295
2296 if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
2297 {
2298 unsigned int firstIndex = mConstantTablePS->GetSamplerIndex(constantPS);
2299
daniel@transgaming.coma41e6e32010-12-15 15:45:30 +00002300 for (int i = 0; i < count; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002301 {
daniel@transgaming.coma41e6e32010-12-15 15:45:30 +00002302 unsigned int samplerIndex = firstIndex + i;
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002303
daniel@transgaming.coma41e6e32010-12-15 15:45:30 +00002304 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002305 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002306 ASSERT(mSamplersPS[samplerIndex].active);
2307 mSamplersPS[samplerIndex].logicalTextureUnit = v[i];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002308 }
2309 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002310 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002311 else
2312 {
2313 mConstantTablePS->SetIntArray(device, constantPS, v, count);
2314 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002315 }
2316
2317 if (constantVS)
2318 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002319 D3DXCONSTANT_DESC constantDescription;
2320 UINT descriptionCount = 1;
2321 HRESULT result = mConstantTableVS->GetConstantDesc(constantVS, &constantDescription, &descriptionCount);
2322 ASSERT(SUCCEEDED(result));
2323
2324 if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
2325 {
2326 unsigned int firstIndex = mConstantTableVS->GetSamplerIndex(constantVS);
2327
2328 for (int i = 0; i < count; i++)
2329 {
2330 unsigned int samplerIndex = firstIndex + i;
2331
2332 if (samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF)
2333 {
2334 ASSERT(mSamplersVS[samplerIndex].active);
2335 mSamplersVS[samplerIndex].logicalTextureUnit = v[i];
2336 }
2337 }
2338 }
2339 else
2340 {
2341 mConstantTableVS->SetIntArray(device, constantVS, v, count);
2342 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002343 }
2344
2345 return true;
2346}
2347
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002348bool Program::applyUniform2iv(GLint location, GLsizei count, const GLint *v)
2349{
2350 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2351
2352 for (int i = 0; i < count; i++)
2353 {
2354 vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], 0, 0);
2355
2356 v += 2;
2357 }
2358
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002359 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2360
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002361 D3DXHANDLE constantPS;
2362 D3DXHANDLE constantVS;
2363 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002364 IDirect3DDevice9 *device = getDevice();
2365
2366 if (constantPS)
2367 {
2368 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2369 }
2370
2371 if (constantVS)
2372 {
2373 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2374 }
2375
2376 delete[] vector;
2377
2378 return true;
2379}
2380
2381bool Program::applyUniform3iv(GLint location, GLsizei count, const GLint *v)
2382{
2383 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2384
2385 for (int i = 0; i < count; i++)
2386 {
2387 vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], (float)v[2], 0);
2388
2389 v += 3;
2390 }
2391
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002392 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2393
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002394 D3DXHANDLE constantPS;
2395 D3DXHANDLE constantVS;
2396 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002397 IDirect3DDevice9 *device = getDevice();
2398
2399 if (constantPS)
2400 {
2401 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2402 }
2403
2404 if (constantVS)
2405 {
2406 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2407 }
2408
2409 delete[] vector;
2410
2411 return true;
2412}
2413
2414bool Program::applyUniform4iv(GLint location, GLsizei count, const GLint *v)
2415{
2416 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2417
2418 for (int i = 0; i < count; i++)
2419 {
2420 vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], (float)v[2], (float)v[3]);
2421
2422 v += 4;
2423 }
2424
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002425 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2426
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002427 D3DXHANDLE constantPS;
2428 D3DXHANDLE constantVS;
2429 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002430 IDirect3DDevice9 *device = getDevice();
2431
2432 if (constantPS)
2433 {
2434 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2435 }
2436
2437 if (constantVS)
2438 {
2439 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2440 }
2441
2442 delete [] vector;
2443
2444 return true;
2445}
2446
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002447void Program::appendToInfoLog(const char *format, ...)
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002448{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002449 if (!format)
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002450 {
2451 return;
2452 }
2453
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002454 char info[1024];
2455
2456 va_list vararg;
2457 va_start(vararg, format);
2458 vsnprintf(info, sizeof(info), format, vararg);
2459 va_end(vararg);
2460
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002461 size_t infoLength = strlen(info);
2462
2463 if (!mInfoLog)
2464 {
2465 mInfoLog = new char[infoLength + 1];
2466 strcpy(mInfoLog, info);
2467 }
2468 else
2469 {
2470 size_t logLength = strlen(mInfoLog);
2471 char *newLog = new char[logLength + infoLength + 1];
2472 strcpy(newLog, mInfoLog);
2473 strcpy(newLog + logLength, info);
2474
2475 delete[] mInfoLog;
2476 mInfoLog = newLog;
2477 }
2478}
2479
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002480void Program::resetInfoLog()
2481{
2482 if (mInfoLog)
2483 {
2484 delete [] mInfoLog;
daniel@transgaming.com6a20d102010-08-31 13:54:27 +00002485 mInfoLog = NULL;
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002486 }
2487}
2488
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002489// Returns the program object to an unlinked state, after detaching a shader, before re-linking, or at destruction
2490void Program::unlink(bool destroy)
2491{
2492 if (destroy) // Object being destructed
2493 {
2494 if (mFragmentShader)
2495 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002496 mFragmentShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002497 mFragmentShader = NULL;
2498 }
2499
2500 if (mVertexShader)
2501 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002502 mVertexShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002503 mVertexShader = NULL;
2504 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002505 }
2506
2507 if (mPixelExecutable)
2508 {
2509 mPixelExecutable->Release();
2510 mPixelExecutable = NULL;
2511 }
2512
2513 if (mVertexExecutable)
2514 {
2515 mVertexExecutable->Release();
2516 mVertexExecutable = NULL;
2517 }
2518
2519 if (mConstantTablePS)
2520 {
2521 mConstantTablePS->Release();
2522 mConstantTablePS = NULL;
2523 }
2524
2525 if (mConstantTableVS)
2526 {
2527 mConstantTableVS->Release();
2528 mConstantTableVS = NULL;
2529 }
2530
2531 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
2532 {
daniel@transgaming.com85423182010-04-22 13:35:27 +00002533 mLinkedAttribute[index].name.clear();
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002534 mSemanticIndex[index] = -1;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002535 }
2536
2537 for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
2538 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002539 mSamplersPS[index].active = false;
2540 }
2541
2542 for (int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; index++)
2543 {
2544 mSamplersVS[index].active = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002545 }
2546
2547 while (!mUniforms.empty())
2548 {
2549 delete mUniforms.back();
2550 mUniforms.pop_back();
2551 }
2552
daniel@transgaming.com31754962010-11-28 02:02:52 +00002553 mDxDepthRangeLocation = -1;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002554 mDxDepthLocation = -1;
daniel@transgaming.com4f921eb2010-07-28 19:20:44 +00002555 mDxViewportLocation = -1;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002556 mDxHalfPixelSizeLocation = -1;
2557 mDxFrontCCWLocation = -1;
2558 mDxPointsOrLinesLocation = -1;
2559
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002560 mUniformIndex.clear();
2561
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00002562 mPixelHLSL.clear();
2563 mVertexHLSL.clear();
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00002564
2565 delete[] mInfoLog;
2566 mInfoLog = NULL;
2567
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002568 mLinked = false;
2569}
2570
2571bool Program::isLinked()
2572{
2573 return mLinked;
2574}
2575
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002576bool Program::isValidated() const
2577{
2578 return mValidated;
2579}
2580
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002581void Program::release()
2582{
2583 mRefCount--;
2584
2585 if (mRefCount == 0 && mDeleteStatus)
2586 {
2587 mResourceManager->deleteProgram(mHandle);
2588 }
2589}
2590
2591void Program::addRef()
2592{
2593 mRefCount++;
2594}
2595
2596unsigned int Program::getRefCount() const
2597{
2598 return mRefCount;
2599}
2600
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00002601unsigned int Program::getSerial() const
2602{
2603 return mSerial;
2604}
2605
2606unsigned int Program::issueSerial()
2607{
2608 return mCurrentSerial++;
2609}
2610
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002611int Program::getInfoLogLength() const
2612{
2613 if (!mInfoLog)
2614 {
2615 return 0;
2616 }
2617 else
2618 {
2619 return strlen(mInfoLog) + 1;
2620 }
2621}
2622
2623void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
2624{
2625 int index = 0;
2626
2627 if (mInfoLog)
2628 {
2629 while (index < bufSize - 1 && index < (int)strlen(mInfoLog))
2630 {
2631 infoLog[index] = mInfoLog[index];
2632 index++;
2633 }
2634 }
2635
2636 if (bufSize)
2637 {
2638 infoLog[index] = '\0';
2639 }
2640
2641 if (length)
2642 {
2643 *length = index;
2644 }
2645}
2646
daniel@transgaming.com6c785212010-03-30 03:36:17 +00002647void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
2648{
2649 int total = 0;
2650
2651 if (mVertexShader)
2652 {
2653 if (total < maxCount)
2654 {
2655 shaders[total] = mVertexShader->getHandle();
2656 }
2657
2658 total++;
2659 }
2660
2661 if (mFragmentShader)
2662 {
2663 if (total < maxCount)
2664 {
2665 shaders[total] = mFragmentShader->getHandle();
2666 }
2667
2668 total++;
2669 }
2670
2671 if (count)
2672 {
2673 *count = total;
2674 }
2675}
2676
daniel@transgaming.com85423182010-04-22 13:35:27 +00002677void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2678{
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002679 // Skip over inactive attributes
2680 unsigned int activeAttribute = 0;
2681 unsigned int attribute;
2682 for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
daniel@transgaming.com85423182010-04-22 13:35:27 +00002683 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002684 if (mLinkedAttribute[attribute].name.empty())
daniel@transgaming.com85423182010-04-22 13:35:27 +00002685 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002686 continue;
daniel@transgaming.com85423182010-04-22 13:35:27 +00002687 }
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002688
2689 if (activeAttribute == index)
2690 {
2691 break;
2692 }
2693
2694 activeAttribute++;
daniel@transgaming.com85423182010-04-22 13:35:27 +00002695 }
2696
2697 if (bufsize > 0)
2698 {
2699 const char *string = mLinkedAttribute[attribute].name.c_str();
2700
2701 strncpy(name, string, bufsize);
2702 name[bufsize - 1] = '\0';
2703
2704 if (length)
2705 {
2706 *length = strlen(name);
2707 }
2708 }
2709
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00002710 *size = 1; // Always a single 'type' instance
daniel@transgaming.com85423182010-04-22 13:35:27 +00002711
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002712 *type = mLinkedAttribute[attribute].type;
daniel@transgaming.com85423182010-04-22 13:35:27 +00002713}
2714
2715GLint Program::getActiveAttributeCount()
2716{
2717 int count = 0;
2718
2719 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2720 {
2721 if (!mLinkedAttribute[attributeIndex].name.empty())
2722 {
2723 count++;
2724 }
2725 }
2726
2727 return count;
2728}
2729
2730GLint Program::getActiveAttributeMaxLength()
2731{
2732 int maxLength = 0;
2733
2734 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2735 {
2736 if (!mLinkedAttribute[attributeIndex].name.empty())
2737 {
2738 maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength);
2739 }
2740 }
2741
2742 return maxLength;
2743}
2744
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002745void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2746{
daniel@transgaming.com996675c2010-11-17 13:06:29 +00002747 // Skip over internal uniforms
2748 unsigned int activeUniform = 0;
2749 unsigned int uniform;
2750 for (uniform = 0; uniform < mUniforms.size(); uniform++)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002751 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002752 if (mUniforms[uniform]->name.substr(0, 3) == "dx_")
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002753 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002754 continue;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002755 }
daniel@transgaming.com996675c2010-11-17 13:06:29 +00002756
2757 if (activeUniform == index)
2758 {
2759 break;
2760 }
2761
2762 activeUniform++;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002763 }
2764
daniel@transgaming.com996675c2010-11-17 13:06:29 +00002765 ASSERT(uniform < mUniforms.size()); // index must be smaller than getActiveUniformCount()
2766
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002767 if (bufsize > 0)
2768 {
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00002769 std::string string = undecorate(mUniforms[uniform]->name);
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002770
daniel@transgaming.comf3140152010-04-29 03:38:50 +00002771 if (mUniforms[uniform]->arraySize != 1)
2772 {
2773 string += "[0]";
2774 }
2775
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00002776 strncpy(name, string.c_str(), bufsize);
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002777 name[bufsize - 1] = '\0';
2778
2779 if (length)
2780 {
2781 *length = strlen(name);
2782 }
2783 }
2784
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00002785 *size = mUniforms[uniform]->arraySize;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002786
2787 *type = mUniforms[uniform]->type;
2788}
2789
2790GLint Program::getActiveUniformCount()
2791{
2792 int count = 0;
2793
daniel@transgaming.comd08ea902010-05-14 19:41:36 +00002794 unsigned int numUniforms = mUniforms.size();
2795 for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002796 {
2797 if (mUniforms[uniformIndex]->name.substr(0, 3) != "dx_")
2798 {
2799 count++;
2800 }
2801 }
2802
2803 return count;
2804}
2805
2806GLint Program::getActiveUniformMaxLength()
2807{
2808 int maxLength = 0;
2809
daniel@transgaming.comd08ea902010-05-14 19:41:36 +00002810 unsigned int numUniforms = mUniforms.size();
2811 for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002812 {
2813 if (!mUniforms[uniformIndex]->name.empty() && mUniforms[uniformIndex]->name.substr(0, 3) != "dx_")
2814 {
zmo@google.com53d73e02011-03-24 21:27:57 +00002815 int length = (int)(undecorate(mUniforms[uniformIndex]->name).length() + 1);
zmo@google.com2a5645f2011-03-24 21:36:51 +00002816 if (mUniforms[uniformIndex]->arraySize != 1)
zmo@google.com53d73e02011-03-24 21:27:57 +00002817 {
2818 length += 3; // Counting in "[0]".
2819 }
2820 maxLength = std::max(length, maxLength);
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002821 }
2822 }
2823
2824 return maxLength;
2825}
2826
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002827void Program::flagForDeletion()
2828{
2829 mDeleteStatus = true;
2830}
2831
2832bool Program::isFlaggedForDeletion() const
2833{
2834 return mDeleteStatus;
2835}
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002836
2837void Program::validate()
2838{
2839 resetInfoLog();
2840
2841 if (!isLinked())
2842 {
2843 appendToInfoLog("Program has not been successfully linked.");
2844 mValidated = false;
2845 }
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002846 else
2847 {
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002848 applyUniforms();
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002849 if (!validateSamplers(true))
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002850 {
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002851 mValidated = false;
2852 }
2853 else
2854 {
2855 mValidated = true;
2856 }
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002857 }
2858}
2859
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002860bool Program::validateSamplers(bool logErrors)
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002861{
2862 // if any two active samplers in a program are of different types, but refer to the same
2863 // texture image unit, and this is the current program, then ValidateProgram will fail, and
2864 // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002865
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002866 const unsigned int maxCombinedTextureImageUnits = getContext()->getMaximumCombinedTextureImageUnits();
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002867 TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF];
2868
2869 for (unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; ++i)
2870 {
2871 textureUnitType[i] = TEXTURE_UNKNOWN;
2872 }
2873
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002874 for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
2875 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002876 if (mSamplersPS[i].active)
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002877 {
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002878 unsigned int unit = mSamplersPS[i].logicalTextureUnit;
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002879
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002880 if (unit >= maxCombinedTextureImageUnits)
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002881 {
2882 if (logErrors)
2883 {
2884 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
2885 }
2886
2887 return false;
2888 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002889
2890 if (textureUnitType[unit] != TEXTURE_UNKNOWN)
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002891 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002892 if (mSamplersPS[i].textureType != textureUnitType[unit])
2893 {
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002894 if (logErrors)
2895 {
2896 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
2897 }
2898
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002899 return false;
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002900 }
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002901 }
2902 else
2903 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002904 textureUnitType[unit] = mSamplersPS[i].textureType;
2905 }
2906 }
2907 }
2908
2909 for (unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; ++i)
2910 {
2911 if (mSamplersVS[i].active)
2912 {
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002913 unsigned int unit = mSamplersVS[i].logicalTextureUnit;
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002914
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002915 if (unit >= maxCombinedTextureImageUnits)
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002916 {
2917 if (logErrors)
2918 {
2919 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
2920 }
2921
2922 return false;
2923 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002924
2925 if (textureUnitType[unit] != TEXTURE_UNKNOWN)
2926 {
2927 if (mSamplersVS[i].textureType != textureUnitType[unit])
2928 {
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002929 if (logErrors)
2930 {
2931 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
2932 }
2933
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002934 return false;
2935 }
2936 }
2937 else
2938 {
2939 textureUnitType[unit] = mSamplersVS[i].textureType;
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002940 }
2941 }
2942 }
2943
2944 return true;
2945}
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002946
2947void Program::getConstantHandles(Uniform *targetUniform, D3DXHANDLE *constantPS, D3DXHANDLE *constantVS)
2948{
2949 if (!targetUniform->handlesSet)
2950 {
2951 targetUniform->psHandle = mConstantTablePS->GetConstantByName(0, targetUniform->name.c_str());
2952 targetUniform->vsHandle = mConstantTableVS->GetConstantByName(0, targetUniform->name.c_str());
2953 targetUniform->handlesSet = true;
2954 }
2955
2956 *constantPS = targetUniform->psHandle;
2957 *constantVS = targetUniform->vsHandle;
2958}
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002959
daniel@transgaming.com31754962010-11-28 02:02:52 +00002960GLint Program::getDxDepthRangeLocation() const
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002961{
daniel@transgaming.com31754962010-11-28 02:02:52 +00002962 return mDxDepthRangeLocation;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002963}
2964
2965GLint Program::getDxDepthLocation() const
2966{
2967 return mDxDepthLocation;
2968}
2969
daniel@transgaming.com4f921eb2010-07-28 19:20:44 +00002970GLint Program::getDxViewportLocation() const
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002971{
daniel@transgaming.com4f921eb2010-07-28 19:20:44 +00002972 return mDxViewportLocation;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002973}
2974
2975GLint Program::getDxHalfPixelSizeLocation() const
2976{
2977 return mDxHalfPixelSizeLocation;
2978}
2979
2980GLint Program::getDxFrontCCWLocation() const
2981{
2982 return mDxFrontCCWLocation;
2983}
2984
2985GLint Program::getDxPointsOrLinesLocation() const
2986{
2987 return mDxPointsOrLinesLocation;
2988}
2989
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002990}