blob: 0a25bc2af5270dc49e612bc0e38961ec9ccdbacf [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
daniel@transgaming.com87891f72011-06-01 15:28:35 +000018#include <string>
19
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +000020#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
21#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3
22#endif
23
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000024namespace gl
25{
daniel@transgaming.com4fa08332010-05-11 02:29:27 +000026unsigned int Program::mCurrentSerial = 1;
27
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +000028std::string str(int i)
29{
30 char buffer[20];
31 sprintf(buffer, "%d", i);
32 return buffer;
33}
34
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000035Uniform::Uniform(GLenum type, const std::string &name, unsigned int arraySize) : type(type), name(name), arraySize(arraySize)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000036{
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000037 int bytes = UniformTypeSize(type) * arraySize;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +000038 data = new unsigned char[bytes];
39 memset(data, 0, bytes);
40 dirty = true;
daniel@transgaming.com2d84df02010-05-14 17:31:13 +000041 handlesSet = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000042}
43
44Uniform::~Uniform()
45{
46 delete[] data;
47}
48
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +000049UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index)
50 : name(name), element(element), index(index)
51{
52}
53
daniel@transgaming.com73a5db62010-10-15 17:58:13 +000054Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle), mSerial(issueSerial())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000055{
56 mFragmentShader = NULL;
57 mVertexShader = NULL;
58
59 mPixelExecutable = NULL;
60 mVertexExecutable = NULL;
61 mConstantTablePS = NULL;
62 mConstantTableVS = NULL;
63
daniel@transgaming.comcba50572010-03-28 19:36:09 +000064 mInfoLog = NULL;
daniel@transgaming.com86a7a132010-04-29 03:32:32 +000065 mValidated = false;
daniel@transgaming.comcba50572010-03-28 19:36:09 +000066
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000067 unlink();
68
69 mDeleteStatus = false;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +000070
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000071 mRefCount = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000072}
73
74Program::~Program()
75{
76 unlink(true);
daniel@transgaming.com71cd8682010-04-29 03:35:25 +000077
78 if (mVertexShader != NULL)
79 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000080 mVertexShader->release();
daniel@transgaming.com71cd8682010-04-29 03:35:25 +000081 }
82
83 if (mFragmentShader != NULL)
84 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000085 mFragmentShader->release();
daniel@transgaming.com71cd8682010-04-29 03:35:25 +000086 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000087}
88
89bool Program::attachShader(Shader *shader)
90{
91 if (shader->getType() == GL_VERTEX_SHADER)
92 {
93 if (mVertexShader)
94 {
95 return false;
96 }
97
98 mVertexShader = (VertexShader*)shader;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000099 mVertexShader->addRef();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000100 }
101 else if (shader->getType() == GL_FRAGMENT_SHADER)
102 {
103 if (mFragmentShader)
104 {
105 return false;
106 }
107
108 mFragmentShader = (FragmentShader*)shader;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000109 mFragmentShader->addRef();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000110 }
111 else UNREACHABLE();
112
113 return true;
114}
115
116bool Program::detachShader(Shader *shader)
117{
118 if (shader->getType() == GL_VERTEX_SHADER)
119 {
120 if (mVertexShader != shader)
121 {
122 return false;
123 }
124
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000125 mVertexShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000126 mVertexShader = NULL;
127 }
128 else if (shader->getType() == GL_FRAGMENT_SHADER)
129 {
130 if (mFragmentShader != shader)
131 {
132 return false;
133 }
134
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000135 mFragmentShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000136 mFragmentShader = NULL;
137 }
138 else UNREACHABLE();
139
140 unlink();
141
142 return true;
143}
144
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000145int Program::getAttachedShadersCount() const
146{
147 return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
148}
149
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150IDirect3DPixelShader9 *Program::getPixelShader()
151{
152 return mPixelExecutable;
153}
154
155IDirect3DVertexShader9 *Program::getVertexShader()
156{
157 return mVertexExecutable;
158}
159
160void Program::bindAttributeLocation(GLuint index, const char *name)
161{
162 if (index < MAX_VERTEX_ATTRIBS)
163 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000164 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
165 {
166 mAttributeBinding[i].erase(name);
167 }
168
169 mAttributeBinding[index].insert(name);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000170 }
171}
172
173GLuint Program::getAttributeLocation(const char *name)
174{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000175 if (name)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000176 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000177 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000178 {
daniel@transgaming.com85423182010-04-22 13:35:27 +0000179 if (mLinkedAttribute[index].name == std::string(name))
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000180 {
181 return index;
182 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000183 }
184 }
185
186 return -1;
187}
188
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000189int Program::getSemanticIndex(int attributeIndex)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000190{
daniel@transgaming.com733ba932011-04-14 15:03:48 +0000191 ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
192
193 return mSemanticIndex[attributeIndex];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000194}
195
daniel@transgaming.com9ba680a2011-05-11 15:37:11 +0000196// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler
197// index (0-15 for the pixel shader and 0-3 for the vertex shader).
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000198GLint Program::getSamplerMapping(SamplerType type, unsigned int samplerIndex)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000199{
daniel@transgaming.comdfd57022011-05-11 15:37:25 +0000200 GLuint logicalTextureUnit = -1;
daniel@transgaming.com4071e662010-05-12 16:51:16 +0000201
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000202 switch (type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000203 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000204 case SAMPLER_PIXEL:
205 ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
206
207 if (mSamplersPS[samplerIndex].active)
208 {
209 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
210 }
211 break;
212 case SAMPLER_VERTEX:
213 ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
214
215 if (mSamplersVS[samplerIndex].active)
216 {
217 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
218 }
219 break;
220 default: UNREACHABLE();
daniel@transgaming.com4071e662010-05-12 16:51:16 +0000221 }
222
daniel@transgaming.com3f74c7a2011-05-11 15:36:51 +0000223 if (logicalTextureUnit >= 0 && logicalTextureUnit < getContext()->getMaximumCombinedTextureImageUnits())
daniel@transgaming.com4071e662010-05-12 16:51:16 +0000224 {
225 return logicalTextureUnit;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000226 }
227
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000228 return -1;
229}
230
daniel@transgaming.com9ba680a2011-05-11 15:37:11 +0000231// Returns the texture type for a given Direct3D 9 sampler type and
232// index (0-15 for the pixel shader and 0-3 for the vertex shader).
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000233TextureType Program::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000234{
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000235 switch (type)
236 {
237 case SAMPLER_PIXEL:
238 ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
239 ASSERT(mSamplersPS[samplerIndex].active);
240 return mSamplersPS[samplerIndex].textureType;
241 case SAMPLER_VERTEX:
242 ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
243 ASSERT(mSamplersVS[samplerIndex].active);
244 return mSamplersVS[samplerIndex].textureType;
245 default: UNREACHABLE();
246 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000247
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000248 return TEXTURE_2D;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249}
250
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +0000251GLint Program::getUniformLocation(const char *name, bool decorated)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000252{
daniel@transgaming.comce864422010-11-18 13:16:49 +0000253 std::string _name = decorated ? name : decorate(name);
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000254 int subscript = 0;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000255
daniel@transgaming.comce864422010-11-18 13:16:49 +0000256 // Strip any trailing array operator and retrieve the subscript
257 size_t open = _name.find_last_of('[');
258 size_t close = _name.find_last_of(']');
259 if (open != std::string::npos && close == _name.length() - 1)
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +0000260 {
daniel@transgaming.comce864422010-11-18 13:16:49 +0000261 subscript = atoi(_name.substr(open + 1).c_str());
262 _name.erase(open);
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +0000263 }
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000264
daniel@transgaming.comd08ea902010-05-14 19:41:36 +0000265 unsigned int numUniforms = mUniformIndex.size();
266 for (unsigned int location = 0; location < numUniforms; location++)
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000267 {
daniel@transgaming.comce864422010-11-18 13:16:49 +0000268 if (mUniformIndex[location].name == _name &&
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000269 mUniformIndex[location].element == subscript)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000270 {
271 return location;
272 }
273 }
274
275 return -1;
276}
277
278bool Program::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
279{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000280 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000281 {
282 return false;
283 }
284
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000285 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000286 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000287
288 if (targetUniform->type == GL_FLOAT)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000289 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000290 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000291
292 if (arraySize == 1 && count > 1)
293 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
294
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000295 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000296
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000297 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat),
298 v, sizeof(GLfloat) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000299 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000300 else if (targetUniform->type == GL_BOOL)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000301 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000302 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000303
304 if (arraySize == 1 && count > 1)
305 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000306
307 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000308 GLboolean *boolParams = new GLboolean[count];
309
310 for (int i = 0; i < count; ++i)
311 {
312 if (v[i] == 0.0f)
313 {
314 boolParams[i] = GL_FALSE;
315 }
316 else
317 {
318 boolParams[i] = GL_TRUE;
319 }
320 }
321
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000322 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean),
323 boolParams, sizeof(GLboolean) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000324
325 delete [] boolParams;
326 }
327 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000328 {
329 return false;
330 }
331
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000332 return true;
333}
334
335bool Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
336{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000337 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000338 {
339 return false;
340 }
341
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000342 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000343 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000344
345 if (targetUniform->type == GL_FLOAT_VEC2)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000346 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000347 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000348
349 if (arraySize == 1 && count > 1)
350 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
351
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000352 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000353
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000354 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 2,
355 v, 2 * sizeof(GLfloat) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000356 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000357 else if (targetUniform->type == GL_BOOL_VEC2)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000358 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000359 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000360
361 if (arraySize == 1 && count > 1)
362 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
363
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000364 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
365
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000366 GLboolean *boolParams = new GLboolean[count * 2];
367
368 for (int i = 0; i < count * 2; ++i)
369 {
370 if (v[i] == 0.0f)
371 {
372 boolParams[i] = GL_FALSE;
373 }
374 else
375 {
376 boolParams[i] = GL_TRUE;
377 }
378 }
379
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000380 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 2,
381 boolParams, 2 * sizeof(GLboolean) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000382
383 delete [] boolParams;
384 }
385 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000386 {
387 return false;
388 }
389
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000390 return true;
391}
392
393bool Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
394{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000395 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000396 {
397 return false;
398 }
399
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000400 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000401 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000402
403 if (targetUniform->type == GL_FLOAT_VEC3)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000404 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000405 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000406
407 if (arraySize == 1 && count > 1)
408 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
409
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000410 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000411
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000412 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 3,
413 v, 3 * sizeof(GLfloat) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000414 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000415 else if (targetUniform->type == GL_BOOL_VEC3)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000416 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000417 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000418
419 if (arraySize == 1 && count > 1)
420 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
421
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000422 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000423 GLboolean *boolParams = new GLboolean[count * 3];
424
425 for (int i = 0; i < count * 3; ++i)
426 {
427 if (v[i] == 0.0f)
428 {
429 boolParams[i] = GL_FALSE;
430 }
431 else
432 {
433 boolParams[i] = GL_TRUE;
434 }
435 }
436
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000437 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 3,
438 boolParams, 3 * sizeof(GLboolean) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000439
440 delete [] boolParams;
441 }
442 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000443 {
444 return false;
445 }
446
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000447 return true;
448}
449
450bool Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
451{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000452 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000453 {
454 return false;
455 }
456
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000457 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000458 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000459
460 if (targetUniform->type == GL_FLOAT_VEC4)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000461 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000462 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000463
464 if (arraySize == 1 && count > 1)
465 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
466
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000467 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000468
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000469 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4,
470 v, 4 * sizeof(GLfloat) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000471 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000472 else if (targetUniform->type == GL_BOOL_VEC4)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000473 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000474 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000475
476 if (arraySize == 1 && count > 1)
477 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
478
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000479 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000480 GLboolean *boolParams = new GLboolean[count * 4];
481
482 for (int i = 0; i < count * 4; ++i)
483 {
484 if (v[i] == 0.0f)
485 {
486 boolParams[i] = GL_FALSE;
487 }
488 else
489 {
490 boolParams[i] = GL_TRUE;
491 }
492 }
493
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000494 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 4,
495 boolParams, 4 * sizeof(GLboolean) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000496
497 delete [] boolParams;
498 }
499 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000500 {
501 return false;
502 }
503
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000504 return true;
505}
506
507bool Program::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
508{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000509 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000510 {
511 return false;
512 }
513
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000514 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000515 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000516
517 if (targetUniform->type != GL_FLOAT_MAT2)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000518 {
519 return false;
520 }
521
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000522 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000523
524 if (arraySize == 1 && count > 1)
525 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
526
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000527 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000528
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000529 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4,
530 value, 4 * sizeof(GLfloat) * count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000531
532 return true;
533}
534
535bool Program::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
536{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000537 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000538 {
539 return false;
540 }
541
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000542 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000543 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000544
545 if (targetUniform->type != GL_FLOAT_MAT3)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000546 {
547 return false;
548 }
549
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000550 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000551
552 if (arraySize == 1 && count > 1)
553 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
554
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000555 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000556
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000557 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 9,
558 value, 9 * sizeof(GLfloat) * count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000559
560 return true;
561}
562
563bool Program::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
564{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000565 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000566 {
567 return false;
568 }
569
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000570 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000571 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000572
573 if (targetUniform->type != GL_FLOAT_MAT4)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000574 {
575 return false;
576 }
577
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000578 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000579
580 if (arraySize == 1 && count > 1)
581 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
582
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000583 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000584
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000585 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16,
586 value, 16 * sizeof(GLfloat) * count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000587
588 return true;
589}
590
591bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
592{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000593 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000594 {
595 return false;
596 }
597
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000598 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000599 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000600
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +0000601 if (targetUniform->type == GL_INT ||
602 targetUniform->type == GL_SAMPLER_2D ||
603 targetUniform->type == GL_SAMPLER_CUBE)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000604 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000605 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000606
607 if (arraySize == 1 && count > 1)
608 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
609
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000610 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000611
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000612 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint),
613 v, sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000614 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000615 else if (targetUniform->type == GL_BOOL)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000616 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000617 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000618
619 if (arraySize == 1 && count > 1)
620 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
621
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000622 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000623 GLboolean *boolParams = new GLboolean[count];
624
625 for (int i = 0; i < count; ++i)
626 {
627 if (v[i] == 0)
628 {
629 boolParams[i] = GL_FALSE;
630 }
631 else
632 {
633 boolParams[i] = GL_TRUE;
634 }
635 }
636
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000637 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean),
638 boolParams, sizeof(GLboolean) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000639
640 delete [] boolParams;
641 }
642 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000643 {
644 return false;
645 }
646
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000647 return true;
648}
649
650bool Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
651{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000652 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000653 {
654 return false;
655 }
656
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000657 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000658 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000659
660 if (targetUniform->type == GL_INT_VEC2)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000661 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000662 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000663
664 if (arraySize == 1 && count > 1)
665 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
666
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000667 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000668
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000669 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 2,
670 v, 2 * sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000671 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000672 else if (targetUniform->type == GL_BOOL_VEC2)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000673 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000674 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000675
676 if (arraySize == 1 && count > 1)
677 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
678
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000679 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000680 GLboolean *boolParams = new GLboolean[count * 2];
681
682 for (int i = 0; i < count * 2; ++i)
683 {
684 if (v[i] == 0)
685 {
686 boolParams[i] = GL_FALSE;
687 }
688 else
689 {
690 boolParams[i] = GL_TRUE;
691 }
692 }
693
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000694 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 2,
695 boolParams, 2 * sizeof(GLboolean) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000696
697 delete [] boolParams;
698 }
699 else
700 {
701 return false;
702 }
703
704 return true;
705}
706
707bool Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
708{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000709 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000710 {
711 return false;
712 }
713
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000714 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000715 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000716
717 if (targetUniform->type == GL_INT_VEC3)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000718 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000719 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000720
721 if (arraySize == 1 && count > 1)
722 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
723
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000724 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000725
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000726 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 3,
727 v, 3 * sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000728 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000729 else if (targetUniform->type == GL_BOOL_VEC3)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000730 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000731 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000732
733 if (arraySize == 1 && count > 1)
734 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
735
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000736 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000737 GLboolean *boolParams = new GLboolean[count * 3];
738
739 for (int i = 0; i < count * 3; ++i)
740 {
741 if (v[i] == 0)
742 {
743 boolParams[i] = GL_FALSE;
744 }
745 else
746 {
747 boolParams[i] = GL_TRUE;
748 }
749 }
750
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000751 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 3,
752 boolParams, 3 * sizeof(GLboolean) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000753
754 delete [] boolParams;
755 }
756 else
757 {
758 return false;
759 }
760
761 return true;
762}
763
764bool Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
765{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000766 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000767 {
768 return false;
769 }
770
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000771 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000772 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000773
774 if (targetUniform->type == GL_INT_VEC4)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000775 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000776 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000777
778 if (arraySize == 1 && count > 1)
779 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
780
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000781 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000782
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000783 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 4,
784 v, 4 * sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000785 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000786 else if (targetUniform->type == GL_BOOL_VEC4)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000787 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000788 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000789
790 if (arraySize == 1 && count > 1)
791 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
792
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000793 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000794 GLboolean *boolParams = new GLboolean[count * 4];
795
796 for (int i = 0; i < count * 4; ++i)
797 {
798 if (v[i] == 0)
799 {
800 boolParams[i] = GL_FALSE;
801 }
802 else
803 {
804 boolParams[i] = GL_TRUE;
805 }
806 }
807
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000808 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 4,
809 boolParams, 4 * sizeof(GLboolean) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000810
811 delete [] boolParams;
812 }
813 else
814 {
815 return false;
816 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000817
818 return true;
819}
820
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000821bool Program::getUniformfv(GLint location, GLfloat *params)
822{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000823 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000824 {
825 return false;
826 }
827
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000828 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000829
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000830 unsigned int count = UniformComponentCount(targetUniform->type);
831
832 switch (UniformComponentType(targetUniform->type))
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000833 {
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000834 case GL_BOOL:
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000835 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000836 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * count;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000837
838 for (unsigned int i = 0; i < count; ++i)
839 {
840 params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
841 }
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000842 }
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000843 break;
844 case GL_FLOAT:
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000845 memcpy(params, targetUniform->data + mUniformIndex[location].element * count * sizeof(GLfloat),
846 count * sizeof(GLfloat));
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000847 break;
848 case GL_INT:
849 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000850 GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * count;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000851
852 for (unsigned int i = 0; i < count; ++i)
853 {
854 params[i] = (float)intParams[i];
855 }
856 }
857 break;
858 default: UNREACHABLE();
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000859 }
860
861 return true;
862}
863
864bool Program::getUniformiv(GLint location, GLint *params)
865{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000866 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000867 {
868 return false;
869 }
870
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000871 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000872
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000873 unsigned int count = UniformComponentCount(targetUniform->type);
874
875 switch (UniformComponentType(targetUniform->type))
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000876 {
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000877 case GL_BOOL:
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000878 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000879 GLboolean *boolParams = targetUniform->data + mUniformIndex[location].element * count;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000880
881 for (unsigned int i = 0; i < count; ++i)
882 {
883 params[i] = (GLint)boolParams[i];
884 }
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000885 }
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000886 break;
887 case GL_FLOAT:
888 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000889 GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * count;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000890
891 for (unsigned int i = 0; i < count; ++i)
892 {
893 params[i] = (GLint)floatParams[i];
894 }
895 }
896 break;
897 case GL_INT:
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000898 memcpy(params, targetUniform->data + mUniformIndex[location].element * count * sizeof(GLint),
899 count * sizeof(GLint));
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000900 break;
901 default: UNREACHABLE();
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000902 }
903
904 return true;
905}
906
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000907void Program::dirtyAllUniforms()
908{
daniel@transgaming.comd08ea902010-05-14 19:41:36 +0000909 unsigned int numUniforms = mUniforms.size();
910 for (unsigned int index = 0; index < numUniforms; index++)
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000911 {
912 mUniforms[index]->dirty = true;
913 }
914}
915
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000916// Applies all the uniforms set for this program object to the Direct3D 9 device
917void Program::applyUniforms()
918{
daniel@transgaming.comd08ea902010-05-14 19:41:36 +0000919 unsigned int numUniforms = mUniformIndex.size();
920 for (unsigned int location = 0; location < numUniforms; location++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000921 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000922 if (mUniformIndex[location].element != 0)
923 {
924 continue;
925 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000926
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000927 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
928
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000929 if (targetUniform->dirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000930 {
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000931 int arraySize = targetUniform->arraySize;
932 GLfloat *f = (GLfloat*)targetUniform->data;
933 GLint *i = (GLint*)targetUniform->data;
934 GLboolean *b = (GLboolean*)targetUniform->data;
935
936 switch (targetUniform->type)
937 {
938 case GL_BOOL: applyUniform1bv(location, arraySize, b); break;
939 case GL_BOOL_VEC2: applyUniform2bv(location, arraySize, b); break;
940 case GL_BOOL_VEC3: applyUniform3bv(location, arraySize, b); break;
941 case GL_BOOL_VEC4: applyUniform4bv(location, arraySize, b); break;
942 case GL_FLOAT: applyUniform1fv(location, arraySize, f); break;
943 case GL_FLOAT_VEC2: applyUniform2fv(location, arraySize, f); break;
944 case GL_FLOAT_VEC3: applyUniform3fv(location, arraySize, f); break;
945 case GL_FLOAT_VEC4: applyUniform4fv(location, arraySize, f); break;
946 case GL_FLOAT_MAT2: applyUniformMatrix2fv(location, arraySize, f); break;
947 case GL_FLOAT_MAT3: applyUniformMatrix3fv(location, arraySize, f); break;
948 case GL_FLOAT_MAT4: applyUniformMatrix4fv(location, arraySize, f); break;
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +0000949 case GL_SAMPLER_2D:
950 case GL_SAMPLER_CUBE:
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000951 case GL_INT: applyUniform1iv(location, arraySize, i); break;
952 case GL_INT_VEC2: applyUniform2iv(location, arraySize, i); break;
953 case GL_INT_VEC3: applyUniform3iv(location, arraySize, i); break;
954 case GL_INT_VEC4: applyUniform4iv(location, arraySize, i); break;
955 default:
956 UNREACHABLE();
957 }
958
959 targetUniform->dirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000960 }
961 }
962}
963
964// Compiles the HLSL code of the attached shaders into executable binaries
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000965ID3D10Blob *Program::compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000966{
967 if (!hlsl)
968 {
969 return NULL;
970 }
971
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000972 DWORD result;
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000973 UINT flags = 0;
974 std::string sourceText;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000975 if (perfActive())
976 {
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000977 flags |= D3DCOMPILE_DEBUG;
978#ifdef NDEBUG
979 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
980#else
981 flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000982#endif
983
984 std::string sourcePath = getTempPath();
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000985 sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000986 writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000987 }
988 else
989 {
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000990 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
991 sourceText = hlsl;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000992 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000993
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000994 ID3D10Blob *binary = NULL;
995 ID3D10Blob *errorMessage = NULL;
996 result = D3DCompile(hlsl, strlen(hlsl), NULL, NULL, NULL, "main", profile, flags, 0, &binary, &errorMessage);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000997
998 if (errorMessage)
999 {
1000 const char *message = (const char*)errorMessage->GetBufferPointer();
daniel@transgaming.comcba50572010-03-28 19:36:09 +00001001
daniel@transgaming.com87891f72011-06-01 15:28:35 +00001002 appendToInfoLogSanitized(message);
daniel@transgaming.com0599dc62010-03-21 04:31:36 +00001003 TRACE("\n%s", hlsl);
1004 TRACE("\n%s", message);
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001005
1006 errorMessage->Release();
1007 errorMessage = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001008 }
1009
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001010
1011 if (FAILED(result))
1012 {
1013 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1014 {
1015 error(GL_OUT_OF_MEMORY);
1016 }
1017
1018 return NULL;
1019 }
1020
1021 result = D3DXGetShaderConstantTable(static_cast<const DWORD*>(binary->GetBufferPointer()), constantTable);
1022
1023 if (FAILED(result))
1024 {
1025 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1026 {
1027 error(GL_OUT_OF_MEMORY);
1028 }
1029
1030 binary->Release();
1031
1032 return NULL;
1033 }
1034
1035 return binary;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001036}
1037
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001038// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
1039// Returns the number of used varying registers, or -1 if unsuccesful
1040int Program::packVaryings(const Varying *packing[][4])
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001041{
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001042 Context *context = getContext();
1043 const int maxVaryingVectors = context->getMaximumVaryingVectors();
1044
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001045 for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.end(); varying++)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001046 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001047 int n = VariableRowCount(varying->type) * varying->size;
1048 int m = VariableColumnCount(varying->type);
1049 bool success = false;
daniel@transgaming.com51d0dc22010-04-29 03:39:11 +00001050
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001051 if (m == 2 || m == 3 || m == 4)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001052 {
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001053 for (int r = 0; r <= maxVaryingVectors - n && !success; r++)
daniel@transgaming.com51d0dc22010-04-29 03:39:11 +00001054 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001055 bool available = true;
1056
1057 for (int y = 0; y < n && available; y++)
1058 {
1059 for (int x = 0; x < m && available; x++)
1060 {
1061 if (packing[r + y][x])
1062 {
1063 available = false;
1064 }
1065 }
1066 }
1067
1068 if (available)
1069 {
1070 varying->reg = r;
1071 varying->col = 0;
1072
1073 for (int y = 0; y < n; y++)
1074 {
1075 for (int x = 0; x < m; x++)
1076 {
1077 packing[r + y][x] = &*varying;
1078 }
1079 }
1080
1081 success = true;
1082 }
daniel@transgaming.com51d0dc22010-04-29 03:39:11 +00001083 }
1084
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001085 if (!success && m == 2)
1086 {
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001087 for (int r = maxVaryingVectors - n; r >= 0 && !success; r--)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001088 {
1089 bool available = true;
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001090
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001091 for (int y = 0; y < n && available; y++)
1092 {
1093 for (int x = 2; x < 4 && available; x++)
1094 {
1095 if (packing[r + y][x])
1096 {
1097 available = false;
1098 }
1099 }
1100 }
1101
1102 if (available)
1103 {
1104 varying->reg = r;
1105 varying->col = 2;
1106
1107 for (int y = 0; y < n; y++)
1108 {
1109 for (int x = 2; x < 4; x++)
1110 {
1111 packing[r + y][x] = &*varying;
1112 }
1113 }
1114
1115 success = true;
1116 }
1117 }
1118 }
1119 }
1120 else if (m == 1)
1121 {
1122 int space[4] = {0};
1123
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001124 for (int y = 0; y < maxVaryingVectors; y++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001125 {
1126 for (int x = 0; x < 4; x++)
1127 {
1128 space[x] += packing[y][x] ? 0 : 1;
1129 }
1130 }
1131
1132 int column = 0;
1133
1134 for (int x = 0; x < 4; x++)
1135 {
daniel@transgaming.com11dd5dd2011-02-11 13:28:14 +00001136 if (space[x] >= n && space[x] < space[column])
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001137 {
1138 column = x;
1139 }
1140 }
1141
daniel@transgaming.com11dd5dd2011-02-11 13:28:14 +00001142 if (space[column] >= n)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001143 {
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001144 for (int r = 0; r < maxVaryingVectors; r++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001145 {
1146 if (!packing[r][column])
1147 {
1148 varying->reg = r;
1149
1150 for (int y = r; y < r + n; y++)
1151 {
1152 packing[y][column] = &*varying;
1153 }
1154
1155 break;
1156 }
1157 }
1158
1159 varying->col = column;
1160
1161 success = true;
1162 }
1163 }
1164 else UNREACHABLE();
1165
1166 if (!success)
1167 {
1168 appendToInfoLog("Could not pack varying %s", varying->name.c_str());
1169
1170 return -1;
1171 }
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001172 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001173
1174 // Return the number of used registers
1175 int registers = 0;
1176
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001177 for (int r = 0; r < maxVaryingVectors; r++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001178 {
1179 if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
1180 {
1181 registers++;
1182 }
1183 }
1184
1185 return registers;
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001186}
1187
1188bool Program::linkVaryings()
1189{
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001190 if (mPixelHLSL.empty() || mVertexHLSL.empty())
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001191 {
1192 return false;
1193 }
1194
daniel@transgaming.com97750022011-02-11 13:23:13 +00001195 // Reset the varying register assignments
1196 for (VaryingList::iterator fragVar = mFragmentShader->varyings.begin(); fragVar != mFragmentShader->varyings.end(); fragVar++)
1197 {
1198 fragVar->reg = -1;
1199 fragVar->col = -1;
1200 }
1201
1202 for (VaryingList::iterator vtxVar = mVertexShader->varyings.begin(); vtxVar != mVertexShader->varyings.end(); vtxVar++)
1203 {
1204 vtxVar->reg = -1;
1205 vtxVar->col = -1;
1206 }
1207
1208 // Map the varyings to the register file
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001209 const Varying *packing[MAX_VARYING_VECTORS_SM3][4] = {NULL};
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001210 int registers = packVaryings(packing);
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001211
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001212 if (registers < 0)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001213 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001214 return false;
1215 }
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001216
daniel@transgaming.com97750022011-02-11 13:23:13 +00001217 // Write the HLSL input/output declarations
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001218 Context *context = getContext();
1219 const bool sm3 = context->supportsShaderModel3();
1220 const int maxVaryingVectors = context->getMaximumVaryingVectors();
1221
1222 if (registers == maxVaryingVectors && mFragmentShader->mUsesFragCoord)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001223 {
1224 appendToInfoLog("No varying registers left to support gl_FragCoord");
1225
1226 return false;
1227 }
1228
1229 for (VaryingList::iterator input = mFragmentShader->varyings.begin(); input != mFragmentShader->varyings.end(); input++)
1230 {
1231 bool matched = false;
1232
1233 for (VaryingList::iterator output = mVertexShader->varyings.begin(); output != mVertexShader->varyings.end(); output++)
1234 {
1235 if (output->name == input->name)
1236 {
1237 if (output->type != input->type || output->size != input->size)
1238 {
1239 appendToInfoLog("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str());
1240
1241 return false;
1242 }
1243
1244 output->reg = input->reg;
1245 output->col = input->col;
1246
1247 matched = true;
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001248 break;
1249 }
1250 }
1251
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001252 if (!matched)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001253 {
daniel@transgaming.com97750022011-02-11 13:23:13 +00001254 appendToInfoLog("Fragment varying %s does not match any vertex varying", input->name.c_str());
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001255
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001256 return false;
1257 }
1258 }
1259
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001260 std::string varyingSemantic = (sm3 ? "COLOR" : "TEXCOORD");
1261
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001262 mVertexHLSL += "struct VS_INPUT\n"
1263 "{\n";
1264
1265 int semanticIndex = 0;
1266 for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
1267 {
1268 switch (attribute->type)
1269 {
1270 case GL_FLOAT: mVertexHLSL += " float "; break;
1271 case GL_FLOAT_VEC2: mVertexHLSL += " float2 "; break;
1272 case GL_FLOAT_VEC3: mVertexHLSL += " float3 "; break;
1273 case GL_FLOAT_VEC4: mVertexHLSL += " float4 "; break;
1274 case GL_FLOAT_MAT2: mVertexHLSL += " float2x2 "; break;
1275 case GL_FLOAT_MAT3: mVertexHLSL += " float3x3 "; break;
1276 case GL_FLOAT_MAT4: mVertexHLSL += " float4x4 "; break;
1277 default: UNREACHABLE();
1278 }
1279
1280 mVertexHLSL += decorate(attribute->name) + " : TEXCOORD" + str(semanticIndex) + ";\n";
1281
1282 semanticIndex += VariableRowCount(attribute->type);
1283 }
1284
1285 mVertexHLSL += "};\n"
1286 "\n"
1287 "struct VS_OUTPUT\n"
1288 "{\n"
1289 " float4 gl_Position : POSITION;\n";
1290
1291 for (int r = 0; r < registers; r++)
1292 {
1293 int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1));
1294
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001295 mVertexHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001296 }
1297
1298 if (mFragmentShader->mUsesFragCoord)
1299 {
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001300 mVertexHLSL += " float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
1301 }
1302
1303 if (mVertexShader->mUsesPointSize && sm3)
1304 {
1305 mVertexHLSL += " float gl_PointSize : PSIZE;\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001306 }
1307
1308 mVertexHLSL += "};\n"
1309 "\n"
1310 "VS_OUTPUT main(VS_INPUT input)\n"
1311 "{\n";
1312
1313 for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
1314 {
1315 mVertexHLSL += " " + decorate(attribute->name) + " = ";
1316
1317 if (VariableRowCount(attribute->type) > 1) // Matrix
1318 {
1319 mVertexHLSL += "transpose";
1320 }
1321
1322 mVertexHLSL += "(input." + decorate(attribute->name) + ");\n";
1323 }
1324
1325 mVertexHLSL += "\n"
1326 " gl_main();\n"
1327 "\n"
1328 " VS_OUTPUT output;\n"
1329 " output.gl_Position.x = gl_Position.x - dx_HalfPixelSize.x * gl_Position.w;\n"
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001330 " output.gl_Position.y = gl_Position.y - dx_HalfPixelSize.y * gl_Position.w;\n"
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001331 " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
1332 " output.gl_Position.w = gl_Position.w;\n";
1333
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001334 if (mVertexShader->mUsesPointSize && sm3)
1335 {
1336 mVertexHLSL += " output.gl_PointSize = clamp(gl_PointSize, 1.0, " + str((int)ALIASED_POINT_SIZE_RANGE_MAX_SM3) + ");\n";
1337 }
1338
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001339 if (mFragmentShader->mUsesFragCoord)
1340 {
1341 mVertexHLSL += " output.gl_FragCoord = gl_Position;\n";
1342 }
1343
1344 for (VaryingList::iterator varying = mVertexShader->varyings.begin(); varying != mVertexShader->varyings.end(); varying++)
1345 {
1346 if (varying->reg >= 0)
1347 {
1348 for (int i = 0; i < varying->size; i++)
1349 {
1350 int rows = VariableRowCount(varying->type);
1351
1352 for (int j = 0; j < rows; j++)
1353 {
1354 int r = varying->reg + i * rows + j;
1355 mVertexHLSL += " output.v" + str(r);
1356
1357 bool sharedRegister = false; // Register used by multiple varyings
1358
1359 for (int x = 0; x < 4; x++)
1360 {
1361 if (packing[r][x] && packing[r][x] != packing[r][0])
1362 {
1363 sharedRegister = true;
1364 break;
1365 }
1366 }
1367
1368 if(sharedRegister)
1369 {
1370 mVertexHLSL += ".";
1371
1372 for (int x = 0; x < 4; x++)
1373 {
1374 if (packing[r][x] == &*varying)
1375 {
1376 switch(x)
1377 {
1378 case 0: mVertexHLSL += "x"; break;
1379 case 1: mVertexHLSL += "y"; break;
1380 case 2: mVertexHLSL += "z"; break;
1381 case 3: mVertexHLSL += "w"; break;
1382 }
1383 }
1384 }
1385 }
1386
1387 mVertexHLSL += " = " + varying->name;
1388
1389 if (varying->array)
1390 {
1391 mVertexHLSL += "[" + str(i) + "]";
1392 }
1393
1394 if (rows > 1)
1395 {
1396 mVertexHLSL += "[" + str(j) + "]";
1397 }
1398
1399 mVertexHLSL += ";\n";
1400 }
1401 }
1402 }
1403 }
1404
1405 mVertexHLSL += "\n"
1406 " return output;\n"
1407 "}\n";
1408
1409 mPixelHLSL += "struct PS_INPUT\n"
1410 "{\n";
1411
1412 for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.end(); varying++)
1413 {
1414 if (varying->reg >= 0)
1415 {
1416 for (int i = 0; i < varying->size; i++)
1417 {
1418 int rows = VariableRowCount(varying->type);
1419 for (int j = 0; j < rows; j++)
1420 {
1421 std::string n = str(varying->reg + i * rows + j);
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001422 mPixelHLSL += " float4 v" + n + " : " + varyingSemantic + n + ";\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001423 }
1424 }
1425 }
1426 else UNREACHABLE();
1427 }
1428
1429 if (mFragmentShader->mUsesFragCoord)
1430 {
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001431 mPixelHLSL += " float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001432 if (sm3) {
daniel@transgaming.com996675c2010-11-17 13:06:29 +00001433 mPixelHLSL += " float2 dx_VPos : VPOS;\n";
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001434 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001435 }
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001436
1437 if (mFragmentShader->mUsesPointCoord && sm3)
1438 {
1439 mPixelHLSL += " float2 gl_PointCoord : TEXCOORD0;\n";
1440 }
1441
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001442 if (mFragmentShader->mUsesFrontFacing)
1443 {
1444 mPixelHLSL += " float vFace : VFACE;\n";
1445 }
1446
1447 mPixelHLSL += "};\n"
1448 "\n"
1449 "struct PS_OUTPUT\n"
1450 "{\n"
1451 " float4 gl_Color[1] : COLOR;\n"
1452 "};\n"
1453 "\n"
1454 "PS_OUTPUT main(PS_INPUT input)\n"
1455 "{\n";
1456
1457 if (mFragmentShader->mUsesFragCoord)
1458 {
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001459 mPixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n";
1460 if (sm3) {
apatrick@chromium.orgb1092bf2011-05-11 19:52:39 +00001461 mPixelHLSL += " gl_FragCoord.x = input.dx_VPos.x + 0.5;\n"
1462 " gl_FragCoord.y = 2.0 * dx_Viewport.y - input.dx_VPos.y - 0.5;\n";
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001463 } else {
1464 mPixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_Viewport.x + dx_Viewport.z;\n"
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001465 " gl_FragCoord.y = -(input.gl_FragCoord.y * rhw) * dx_Viewport.y + dx_Viewport.w;\n";
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001466 }
1467 mPixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_Depth.x + dx_Depth.y;\n"
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001468 " gl_FragCoord.w = rhw;\n";
1469 }
1470
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001471 if (mFragmentShader->mUsesPointCoord && sm3)
1472 {
apatrick@chromium.orgda4d0492011-01-22 00:16:10 +00001473 mPixelHLSL += " gl_PointCoord = input.gl_PointCoord;\n";
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001474 }
1475
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001476 if (mFragmentShader->mUsesFrontFacing)
1477 {
1478 mPixelHLSL += " gl_FrontFacing = dx_PointsOrLines || (dx_FrontCCW ? (input.vFace >= 0.0) : (input.vFace <= 0.0));\n";
1479 }
1480
1481 for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.end(); varying++)
1482 {
1483 if (varying->reg >= 0)
1484 {
1485 for (int i = 0; i < varying->size; i++)
1486 {
1487 int rows = VariableRowCount(varying->type);
1488 for (int j = 0; j < rows; j++)
1489 {
1490 std::string n = str(varying->reg + i * rows + j);
1491 mPixelHLSL += " " + varying->name;
1492
1493 if (varying->array)
1494 {
1495 mPixelHLSL += "[" + str(i) + "]";
1496 }
1497
1498 if (rows > 1)
1499 {
1500 mPixelHLSL += "[" + str(j) + "]";
1501 }
1502
1503 mPixelHLSL += " = input.v" + n + ";\n";
1504 }
1505 }
1506 }
1507 else UNREACHABLE();
1508 }
1509
1510 mPixelHLSL += "\n"
1511 " gl_main();\n"
1512 "\n"
1513 " PS_OUTPUT output;\n"
1514 " output.gl_Color[0] = gl_Color[0];\n"
1515 "\n"
1516 " return output;\n"
1517 "}\n";
1518
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001519 return true;
1520}
1521
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001522// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
1523// compiling them into binaries, determining the attribute mappings, and collecting
1524// a list of uniforms
1525void Program::link()
1526{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001527 unlink();
1528
1529 if (!mFragmentShader || !mFragmentShader->isCompiled())
1530 {
1531 return;
1532 }
1533
1534 if (!mVertexShader || !mVertexShader->isCompiled())
1535 {
1536 return;
1537 }
1538
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001539 mPixelHLSL = mFragmentShader->getHLSL();
1540 mVertexHLSL = mVertexShader->getHLSL();
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001541
1542 if (!linkVaryings())
1543 {
1544 return;
1545 }
1546
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001547 Context *context = getContext();
1548 const char *vertexProfile = context->supportsShaderModel3() ? "vs_3_0" : "vs_2_0";
1549 const char *pixelProfile = context->supportsShaderModel3() ? "ps_3_0" : "ps_2_0";
1550
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001551 ID3D10Blob *vertexBinary = compileToBinary(mVertexHLSL.c_str(), vertexProfile, &mConstantTableVS);
1552 ID3D10Blob *pixelBinary = compileToBinary(mPixelHLSL.c_str(), pixelProfile, &mConstantTablePS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001553
1554 if (vertexBinary && pixelBinary)
1555 {
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00001556 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001557 HRESULT vertexResult = device->CreateVertexShader((DWORD*)vertexBinary->GetBufferPointer(), &mVertexExecutable);
1558 HRESULT pixelResult = device->CreatePixelShader((DWORD*)pixelBinary->GetBufferPointer(), &mPixelExecutable);
1559
1560 if (vertexResult == D3DERR_OUTOFVIDEOMEMORY || vertexResult == E_OUTOFMEMORY || pixelResult == D3DERR_OUTOFVIDEOMEMORY || pixelResult == E_OUTOFMEMORY)
1561 {
1562 return error(GL_OUT_OF_MEMORY);
1563 }
1564
1565 ASSERT(SUCCEEDED(vertexResult) && SUCCEEDED(pixelResult));
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001566
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001567 vertexBinary->Release();
1568 pixelBinary->Release();
1569 vertexBinary = NULL;
1570 pixelBinary = NULL;
1571
1572 if (mVertexExecutable && mPixelExecutable)
1573 {
1574 if (!linkAttributes())
1575 {
1576 return;
1577 }
1578
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001579 if (!linkUniforms(mConstantTablePS))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001580 {
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001581 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001582 }
1583
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001584 if (!linkUniforms(mConstantTableVS))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001585 {
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001586 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001587 }
1588
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +00001589 // these uniforms are searched as already-decorated because gl_ and dx_
1590 // are reserved prefixes, and do not receive additional decoration
daniel@transgaming.com31754962010-11-28 02:02:52 +00001591 mDxDepthRangeLocation = getUniformLocation("dx_DepthRange", true);
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +00001592 mDxDepthLocation = getUniformLocation("dx_Depth", true);
daniel@transgaming.com162267d2010-07-28 19:20:48 +00001593 mDxViewportLocation = getUniformLocation("dx_Viewport", true);
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +00001594 mDxHalfPixelSizeLocation = getUniformLocation("dx_HalfPixelSize", true);
1595 mDxFrontCCWLocation = getUniformLocation("dx_FrontCCW", true);
1596 mDxPointsOrLinesLocation = getUniformLocation("dx_PointsOrLines", true);
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001597
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001598 mLinked = true; // Success
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001599 }
1600 }
1601}
1602
1603// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
1604bool Program::linkAttributes()
1605{
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001606 unsigned int usedLocations = 0;
1607
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001608 // Link attributes that have a binding location
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001609 for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001610 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001611 int location = getAttributeBinding(attribute->name);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001612
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001613 if (location != -1) // Set by glBindAttribLocation
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001614 {
daniel@transgaming.com85423182010-04-22 13:35:27 +00001615 if (!mLinkedAttribute[location].name.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001616 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001617 // Multiple active attributes bound to the same location; not an error
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001618 }
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001619
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001620 mLinkedAttribute[location] = *attribute;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001621
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001622 int rows = VariableRowCount(attribute->type);
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001623
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001624 if (rows + location > MAX_VERTEX_ATTRIBS)
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001625 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001626 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 +00001627
1628 return false;
1629 }
1630
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001631 for (int i = 0; i < rows; i++)
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001632 {
1633 usedLocations |= 1 << (location + i);
1634 }
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001635 }
1636 }
1637
1638 // Link attributes that don't have a binding location
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001639 for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001640 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001641 int location = getAttributeBinding(attribute->name);
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001642
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001643 if (location == -1) // Not set by glBindAttribLocation
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001644 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001645 int rows = VariableRowCount(attribute->type);
1646 int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001647
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001648 if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001649 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001650 appendToInfoLog("Too many active attributes (%s)", attribute->name.c_str());
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001651
1652 return false; // Fail to link
1653 }
1654
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001655 mLinkedAttribute[availableIndex] = *attribute;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001656 }
1657 }
1658
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001659 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001660 {
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001661 int index = mVertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001662 int rows = std::max(VariableRowCount(mLinkedAttribute[attributeIndex].type), 1);
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001663
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001664 for (int r = 0; r < rows; r++)
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001665 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001666 mSemanticIndex[attributeIndex++] = index++;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001667 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001668 }
1669
1670 return true;
1671}
1672
daniel@transgaming.com85423182010-04-22 13:35:27 +00001673int Program::getAttributeBinding(const std::string &name)
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001674{
1675 for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
1676 {
1677 if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
1678 {
1679 return location;
1680 }
1681 }
1682
1683 return -1;
1684}
1685
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001686bool Program::linkUniforms(ID3DXConstantTable *constantTable)
1687{
1688 D3DXCONSTANTTABLE_DESC constantTableDescription;
1689 D3DXCONSTANT_DESC constantDescription;
1690 UINT descriptionCount = 1;
1691
1692 constantTable->GetDesc(&constantTableDescription);
1693
1694 for (unsigned int constantIndex = 0; constantIndex < constantTableDescription.Constants; constantIndex++)
1695 {
1696 D3DXHANDLE constantHandle = constantTable->GetConstant(0, constantIndex);
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001697 HRESULT result = constantTable->GetConstantDesc(constantHandle, &constantDescription, &descriptionCount);
1698 ASSERT(SUCCEEDED(result));
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001699
1700 if (!defineUniform(constantHandle, constantDescription))
1701 {
1702 return false;
1703 }
1704 }
1705
1706 return true;
1707}
1708
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001709// Adds the description of a constant found in the binary shader to the list of uniforms
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001710// Returns true if succesful (uniform not already defined)
1711bool Program::defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT_DESC &constantDescription, std::string name)
1712{
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001713 if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
1714 {
daniel@transgaming.com41b2fbd2010-12-13 18:27:12 +00001715 for (unsigned int samplerIndex = constantDescription.RegisterIndex; samplerIndex < constantDescription.RegisterIndex + constantDescription.RegisterCount; samplerIndex++)
1716 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001717 if (mConstantTablePS->GetConstantByName(NULL, constantDescription.Name) != NULL)
1718 {
daniel@transgaming.com424bb492011-05-11 15:36:59 +00001719 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
1720 {
1721 mSamplersPS[samplerIndex].active = true;
1722 mSamplersPS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
1723 mSamplersPS[samplerIndex].logicalTextureUnit = 0;
1724 }
1725 else
1726 {
1727 appendToInfoLog("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
1728 return false;
1729 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001730 }
1731
1732 if (mConstantTableVS->GetConstantByName(NULL, constantDescription.Name) != NULL)
1733 {
daniel@transgaming.com424bb492011-05-11 15:36:59 +00001734 if (samplerIndex < getContext()->getMaximumVertexTextureImageUnits())
1735 {
1736 mSamplersVS[samplerIndex].active = true;
1737 mSamplersVS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
1738 mSamplersVS[samplerIndex].logicalTextureUnit = 0;
1739 }
1740 else
1741 {
1742 appendToInfoLog("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", getContext()->getMaximumVertexTextureImageUnits());
1743 return false;
1744 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001745 }
daniel@transgaming.com41b2fbd2010-12-13 18:27:12 +00001746 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001747 }
1748
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001749 switch(constantDescription.Class)
1750 {
1751 case D3DXPC_STRUCT:
1752 {
daniel@transgaming.comce864422010-11-18 13:16:49 +00001753 for (unsigned int arrayIndex = 0; arrayIndex < constantDescription.Elements; arrayIndex++)
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001754 {
daniel@transgaming.comce864422010-11-18 13:16:49 +00001755 for (unsigned int field = 0; field < constantDescription.StructMembers; field++)
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001756 {
daniel@transgaming.comce864422010-11-18 13:16:49 +00001757 D3DXHANDLE fieldHandle = mConstantTablePS->GetConstant(constantHandle, field);
1758
1759 D3DXCONSTANT_DESC fieldDescription;
1760 UINT descriptionCount = 1;
1761
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001762 HRESULT result = mConstantTablePS->GetConstantDesc(fieldHandle, &fieldDescription, &descriptionCount);
1763 ASSERT(SUCCEEDED(result));
daniel@transgaming.comce864422010-11-18 13:16:49 +00001764
1765 std::string structIndex = (constantDescription.Elements > 1) ? ("[" + str(arrayIndex) + "]") : "";
1766
1767 if (!defineUniform(fieldHandle, fieldDescription, name + constantDescription.Name + structIndex + "."))
1768 {
1769 return false;
1770 }
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001771 }
1772 }
1773
1774 return true;
1775 }
1776 case D3DXPC_SCALAR:
1777 case D3DXPC_VECTOR:
1778 case D3DXPC_MATRIX_COLUMNS:
1779 case D3DXPC_OBJECT:
1780 return defineUniform(constantDescription, name + constantDescription.Name);
1781 default:
1782 UNREACHABLE();
1783 return false;
1784 }
1785}
1786
1787bool Program::defineUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name)
1788{
1789 Uniform *uniform = createUniform(constantDescription, name);
1790
1791 if(!uniform)
1792 {
1793 return false;
1794 }
1795
1796 // Check if already defined
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +00001797 GLint location = getUniformLocation(name.c_str(), true);
daniel@transgaming.com0361b922010-03-28 19:36:15 +00001798 GLenum type = uniform->type;
daniel@transgaming.comc7d8a932010-03-16 06:16:45 +00001799
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001800 if (location >= 0)
1801 {
1802 delete uniform;
1803
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00001804 if (mUniforms[mUniformIndex[location].index]->type != type)
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001805 {
1806 return false;
1807 }
1808 else
1809 {
1810 return true;
1811 }
1812 }
1813
1814 mUniforms.push_back(uniform);
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00001815 unsigned int uniformIndex = mUniforms.size() - 1;
1816
1817 for (unsigned int i = 0; i < uniform->arraySize; ++i)
1818 {
1819 mUniformIndex.push_back(UniformLocation(name, i, uniformIndex));
1820 }
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001821
1822 return true;
1823}
1824
1825Uniform *Program::createUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001826{
1827 if (constantDescription.Rows == 1) // Vectors and scalars
1828 {
1829 switch (constantDescription.Type)
1830 {
1831 case D3DXPT_SAMPLER2D:
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +00001832 switch (constantDescription.Columns)
1833 {
1834 case 1: return new Uniform(GL_SAMPLER_2D, name, constantDescription.Elements);
1835 default: UNREACHABLE();
1836 }
1837 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001838 case D3DXPT_SAMPLERCUBE:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001839 switch (constantDescription.Columns)
1840 {
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +00001841 case 1: return new Uniform(GL_SAMPLER_CUBE, name, constantDescription.Elements);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00001842 default: UNREACHABLE();
1843 }
1844 break;
1845 case D3DXPT_BOOL:
1846 switch (constantDescription.Columns)
1847 {
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00001848 case 1: return new Uniform(GL_BOOL, name, constantDescription.Elements);
1849 case 2: return new Uniform(GL_BOOL_VEC2, name, constantDescription.Elements);
1850 case 3: return new Uniform(GL_BOOL_VEC3, name, constantDescription.Elements);
1851 case 4: return new Uniform(GL_BOOL_VEC4, name, constantDescription.Elements);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00001852 default: UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001853 }
1854 break;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00001855 case D3DXPT_INT:
1856 switch (constantDescription.Columns)
1857 {
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00001858 case 1: return new Uniform(GL_INT, name, constantDescription.Elements);
1859 case 2: return new Uniform(GL_INT_VEC2, name, constantDescription.Elements);
1860 case 3: return new Uniform(GL_INT_VEC3, name, constantDescription.Elements);
1861 case 4: return new Uniform(GL_INT_VEC4, name, constantDescription.Elements);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00001862 default: UNREACHABLE();
1863 }
1864 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001865 case D3DXPT_FLOAT:
1866 switch (constantDescription.Columns)
1867 {
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00001868 case 1: return new Uniform(GL_FLOAT, name, constantDescription.Elements);
1869 case 2: return new Uniform(GL_FLOAT_VEC2, name, constantDescription.Elements);
1870 case 3: return new Uniform(GL_FLOAT_VEC3, name, constantDescription.Elements);
1871 case 4: return new Uniform(GL_FLOAT_VEC4, name, constantDescription.Elements);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001872 default: UNREACHABLE();
1873 }
1874 break;
1875 default:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001876 UNREACHABLE();
1877 }
1878 }
1879 else if (constantDescription.Rows == constantDescription.Columns) // Square matrices
1880 {
1881 switch (constantDescription.Type)
1882 {
1883 case D3DXPT_FLOAT:
1884 switch (constantDescription.Rows)
1885 {
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00001886 case 2: return new Uniform(GL_FLOAT_MAT2, name, constantDescription.Elements);
1887 case 3: return new Uniform(GL_FLOAT_MAT3, name, constantDescription.Elements);
1888 case 4: return new Uniform(GL_FLOAT_MAT4, name, constantDescription.Elements);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001889 default: UNREACHABLE();
1890 }
1891 break;
1892 default: UNREACHABLE();
1893 }
1894 }
1895 else UNREACHABLE();
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001896
1897 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001898}
1899
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00001900// This method needs to match OutputHLSL::decorate
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001901std::string Program::decorate(const std::string &string)
1902{
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001903 if (string.substr(0, 3) != "gl_" && string.substr(0, 3) != "dx_")
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001904 {
1905 return "_" + string;
1906 }
1907 else
1908 {
1909 return string;
1910 }
1911}
1912
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00001913std::string Program::undecorate(const std::string &string)
1914{
1915 if (string.substr(0, 1) == "_")
1916 {
1917 return string.substr(1);
1918 }
1919 else
1920 {
1921 return string;
1922 }
1923}
1924
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00001925bool Program::applyUniform1bv(GLint location, GLsizei count, const GLboolean *v)
1926{
1927 BOOL *vector = new BOOL[count];
1928 for (int i = 0; i < count; i++)
1929 {
1930 if (v[i] == GL_FALSE)
1931 vector[i] = 0;
1932 else
1933 vector[i] = 1;
1934 }
1935
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00001936 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
1937
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00001938 D3DXHANDLE constantPS;
1939 D3DXHANDLE constantVS;
1940 getConstantHandles(targetUniform, &constantPS, &constantVS);
1941
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00001942 IDirect3DDevice9 *device = getDevice();
1943
1944 if (constantPS)
1945 {
1946 mConstantTablePS->SetBoolArray(device, constantPS, vector, count);
1947 }
1948
1949 if (constantVS)
1950 {
1951 mConstantTableVS->SetBoolArray(device, constantVS, vector, count);
1952 }
1953
1954 delete [] vector;
1955
1956 return true;
1957}
1958
1959bool Program::applyUniform2bv(GLint location, GLsizei count, const GLboolean *v)
1960{
1961 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
1962
1963 for (int i = 0; i < count; i++)
1964 {
1965 vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
1966 (v[1] == GL_FALSE ? 0.0f : 1.0f), 0, 0);
1967
1968 v += 2;
1969 }
1970
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00001971 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
1972
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00001973 D3DXHANDLE constantPS;
1974 D3DXHANDLE constantVS;
1975 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00001976 IDirect3DDevice9 *device = getDevice();
1977
1978 if (constantPS)
1979 {
1980 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
1981 }
1982
1983 if (constantVS)
1984 {
1985 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
1986 }
1987
1988 delete[] vector;
1989
1990 return true;
1991}
1992
1993bool Program::applyUniform3bv(GLint location, GLsizei count, const GLboolean *v)
1994{
1995 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
1996
1997 for (int i = 0; i < count; i++)
1998 {
1999 vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
2000 (v[1] == GL_FALSE ? 0.0f : 1.0f),
2001 (v[2] == GL_FALSE ? 0.0f : 1.0f), 0);
2002
2003 v += 3;
2004 }
2005
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002006 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2007
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002008 D3DXHANDLE constantPS;
2009 D3DXHANDLE constantVS;
2010 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002011 IDirect3DDevice9 *device = getDevice();
2012
2013 if (constantPS)
2014 {
2015 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2016 }
2017
2018 if (constantVS)
2019 {
2020 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2021 }
2022
2023 delete[] vector;
2024
2025 return true;
2026}
2027
2028bool Program::applyUniform4bv(GLint location, GLsizei count, const GLboolean *v)
2029{
2030 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2031
2032 for (int i = 0; i < count; i++)
2033 {
2034 vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
2035 (v[1] == GL_FALSE ? 0.0f : 1.0f),
2036 (v[2] == GL_FALSE ? 0.0f : 1.0f),
2037 (v[3] == GL_FALSE ? 0.0f : 1.0f));
2038
2039 v += 3;
2040 }
2041
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002042 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2043
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002044 D3DXHANDLE constantPS;
2045 D3DXHANDLE constantVS;
2046 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002047 IDirect3DDevice9 *device = getDevice();
2048
2049 if (constantPS)
2050 {
2051 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2052 }
2053
2054 if (constantVS)
2055 {
2056 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2057 }
2058
2059 delete [] vector;
2060
2061 return true;
2062}
2063
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002064bool Program::applyUniform1fv(GLint location, GLsizei count, const GLfloat *v)
2065{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002066 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2067
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002068 D3DXHANDLE constantPS;
2069 D3DXHANDLE constantVS;
2070 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002071 IDirect3DDevice9 *device = getDevice();
2072
2073 if (constantPS)
2074 {
2075 mConstantTablePS->SetFloatArray(device, constantPS, v, count);
2076 }
2077
2078 if (constantVS)
2079 {
2080 mConstantTableVS->SetFloatArray(device, constantVS, v, count);
2081 }
2082
2083 return true;
2084}
2085
2086bool Program::applyUniform2fv(GLint location, GLsizei count, const GLfloat *v)
2087{
2088 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2089
2090 for (int i = 0; i < count; i++)
2091 {
2092 vector[i] = D3DXVECTOR4(v[0], v[1], 0, 0);
2093
2094 v += 2;
2095 }
2096
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002097 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2098
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002099 D3DXHANDLE constantPS;
2100 D3DXHANDLE constantVS;
2101 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002102 IDirect3DDevice9 *device = getDevice();
2103
2104 if (constantPS)
2105 {
2106 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2107 }
2108
2109 if (constantVS)
2110 {
2111 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2112 }
2113
2114 delete[] vector;
2115
2116 return true;
2117}
2118
2119bool Program::applyUniform3fv(GLint location, GLsizei count, const GLfloat *v)
2120{
2121 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2122
2123 for (int i = 0; i < count; i++)
2124 {
2125 vector[i] = D3DXVECTOR4(v[0], v[1], v[2], 0);
2126
2127 v += 3;
2128 }
2129
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002130 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2131
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002132 D3DXHANDLE constantPS;
2133 D3DXHANDLE constantVS;
2134 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002135 IDirect3DDevice9 *device = getDevice();
2136
2137 if (constantPS)
2138 {
2139 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2140 }
2141
2142 if (constantVS)
2143 {
2144 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2145 }
2146
2147 delete[] vector;
2148
2149 return true;
2150}
2151
2152bool Program::applyUniform4fv(GLint location, GLsizei count, const GLfloat *v)
2153{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002154 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2155
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002156 D3DXHANDLE constantPS;
2157 D3DXHANDLE constantVS;
2158 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002159 IDirect3DDevice9 *device = getDevice();
2160
2161 if (constantPS)
2162 {
2163 mConstantTablePS->SetVectorArray(device, constantPS, (D3DXVECTOR4*)v, count);
2164 }
2165
2166 if (constantVS)
2167 {
2168 mConstantTableVS->SetVectorArray(device, constantVS, (D3DXVECTOR4*)v, count);
2169 }
2170
2171 return true;
2172}
2173
2174bool Program::applyUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
2175{
2176 D3DXMATRIX *matrix = new D3DXMATRIX[count];
2177
2178 for (int i = 0; i < count; i++)
2179 {
2180 matrix[i] = D3DXMATRIX(value[0], value[2], 0, 0,
2181 value[1], value[3], 0, 0,
2182 0, 0, 1, 0,
2183 0, 0, 0, 1);
2184
2185 value += 4;
2186 }
2187
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002188 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2189
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002190 D3DXHANDLE constantPS;
2191 D3DXHANDLE constantVS;
2192 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002193 IDirect3DDevice9 *device = getDevice();
2194
2195 if (constantPS)
2196 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002197 mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002198 }
2199
2200 if (constantVS)
2201 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002202 mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002203 }
2204
2205 delete[] matrix;
2206
2207 return true;
2208}
2209
2210bool Program::applyUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
2211{
2212 D3DXMATRIX *matrix = new D3DXMATRIX[count];
2213
2214 for (int i = 0; i < count; i++)
2215 {
2216 matrix[i] = D3DXMATRIX(value[0], value[3], value[6], 0,
2217 value[1], value[4], value[7], 0,
2218 value[2], value[5], value[8], 0,
2219 0, 0, 0, 1);
2220
2221 value += 9;
2222 }
2223
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002224 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2225
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002226 D3DXHANDLE constantPS;
2227 D3DXHANDLE constantVS;
2228 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002229 IDirect3DDevice9 *device = getDevice();
2230
2231 if (constantPS)
2232 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002233 mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002234 }
2235
2236 if (constantVS)
2237 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002238 mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002239 }
2240
2241 delete[] matrix;
2242
2243 return true;
2244}
2245
2246bool Program::applyUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
2247{
2248 D3DXMATRIX *matrix = new D3DXMATRIX[count];
2249
2250 for (int i = 0; i < count; i++)
2251 {
2252 matrix[i] = D3DXMATRIX(value[0], value[4], value[8], value[12],
2253 value[1], value[5], value[9], value[13],
2254 value[2], value[6], value[10], value[14],
2255 value[3], value[7], value[11], value[15]);
2256
2257 value += 16;
2258 }
2259
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002260 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2261
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002262 D3DXHANDLE constantPS;
2263 D3DXHANDLE constantVS;
2264 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002265 IDirect3DDevice9 *device = getDevice();
2266
2267 if (constantPS)
2268 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002269 mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002270 }
2271
2272 if (constantVS)
2273 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002274 mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002275 }
2276
2277 delete[] matrix;
2278
2279 return true;
2280}
2281
2282bool Program::applyUniform1iv(GLint location, GLsizei count, const GLint *v)
2283{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002284 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2285
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002286 D3DXHANDLE constantPS;
2287 D3DXHANDLE constantVS;
2288 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002289 IDirect3DDevice9 *device = getDevice();
2290
2291 if (constantPS)
2292 {
2293 D3DXCONSTANT_DESC constantDescription;
2294 UINT descriptionCount = 1;
2295 HRESULT result = mConstantTablePS->GetConstantDesc(constantPS, &constantDescription, &descriptionCount);
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002296 ASSERT(SUCCEEDED(result));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002297
2298 if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
2299 {
2300 unsigned int firstIndex = mConstantTablePS->GetSamplerIndex(constantPS);
2301
daniel@transgaming.coma41e6e32010-12-15 15:45:30 +00002302 for (int i = 0; i < count; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002303 {
daniel@transgaming.coma41e6e32010-12-15 15:45:30 +00002304 unsigned int samplerIndex = firstIndex + i;
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002305
daniel@transgaming.coma41e6e32010-12-15 15:45:30 +00002306 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002307 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002308 ASSERT(mSamplersPS[samplerIndex].active);
2309 mSamplersPS[samplerIndex].logicalTextureUnit = v[i];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002310 }
2311 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002312 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002313 else
2314 {
2315 mConstantTablePS->SetIntArray(device, constantPS, v, count);
2316 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002317 }
2318
2319 if (constantVS)
2320 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002321 D3DXCONSTANT_DESC constantDescription;
2322 UINT descriptionCount = 1;
2323 HRESULT result = mConstantTableVS->GetConstantDesc(constantVS, &constantDescription, &descriptionCount);
2324 ASSERT(SUCCEEDED(result));
2325
2326 if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
2327 {
2328 unsigned int firstIndex = mConstantTableVS->GetSamplerIndex(constantVS);
2329
2330 for (int i = 0; i < count; i++)
2331 {
2332 unsigned int samplerIndex = firstIndex + i;
2333
2334 if (samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF)
2335 {
2336 ASSERT(mSamplersVS[samplerIndex].active);
2337 mSamplersVS[samplerIndex].logicalTextureUnit = v[i];
2338 }
2339 }
2340 }
2341 else
2342 {
2343 mConstantTableVS->SetIntArray(device, constantVS, v, count);
2344 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002345 }
2346
2347 return true;
2348}
2349
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002350bool Program::applyUniform2iv(GLint location, GLsizei count, const GLint *v)
2351{
2352 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2353
2354 for (int i = 0; i < count; i++)
2355 {
2356 vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], 0, 0);
2357
2358 v += 2;
2359 }
2360
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002361 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2362
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002363 D3DXHANDLE constantPS;
2364 D3DXHANDLE constantVS;
2365 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002366 IDirect3DDevice9 *device = getDevice();
2367
2368 if (constantPS)
2369 {
2370 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2371 }
2372
2373 if (constantVS)
2374 {
2375 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2376 }
2377
2378 delete[] vector;
2379
2380 return true;
2381}
2382
2383bool Program::applyUniform3iv(GLint location, GLsizei count, const GLint *v)
2384{
2385 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2386
2387 for (int i = 0; i < count; i++)
2388 {
2389 vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], (float)v[2], 0);
2390
2391 v += 3;
2392 }
2393
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002394 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2395
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002396 D3DXHANDLE constantPS;
2397 D3DXHANDLE constantVS;
2398 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002399 IDirect3DDevice9 *device = getDevice();
2400
2401 if (constantPS)
2402 {
2403 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2404 }
2405
2406 if (constantVS)
2407 {
2408 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2409 }
2410
2411 delete[] vector;
2412
2413 return true;
2414}
2415
2416bool Program::applyUniform4iv(GLint location, GLsizei count, const GLint *v)
2417{
2418 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2419
2420 for (int i = 0; i < count; i++)
2421 {
2422 vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], (float)v[2], (float)v[3]);
2423
2424 v += 4;
2425 }
2426
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002427 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
2428
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002429 D3DXHANDLE constantPS;
2430 D3DXHANDLE constantVS;
2431 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002432 IDirect3DDevice9 *device = getDevice();
2433
2434 if (constantPS)
2435 {
2436 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2437 }
2438
2439 if (constantVS)
2440 {
2441 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2442 }
2443
2444 delete [] vector;
2445
2446 return true;
2447}
2448
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002449
2450// append a santized message to the program info log.
2451// The D3D compiler includes the current working directory
2452// in some of the warning or error messages, so lets remove
2453// any occurrances of those that we find in the log.
2454void Program::appendToInfoLogSanitized(const char *message)
2455{
2456 std::string msg(message);
2457 CHAR path[MAX_PATH] = "";
2458 size_t len;
2459
2460 len = GetCurrentDirectoryA(MAX_PATH, path);
2461 if (len > 0 && len < MAX_PATH)
2462 {
2463 size_t found;
2464 do {
2465 found = msg.find(path);
2466 if (found != std::string::npos)
2467 {
2468 // the +1 here is intentional so that we remove
2469 // the trailing '\' that occurs after the path
2470 msg.erase(found, len+1);
2471 }
2472 } while (found != std::string::npos);
2473 }
2474
2475 appendToInfoLog("%s\n", msg.c_str());
2476}
2477
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002478void Program::appendToInfoLog(const char *format, ...)
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002479{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002480 if (!format)
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002481 {
2482 return;
2483 }
2484
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002485 char info[1024];
2486
2487 va_list vararg;
2488 va_start(vararg, format);
2489 vsnprintf(info, sizeof(info), format, vararg);
2490 va_end(vararg);
2491
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002492 size_t infoLength = strlen(info);
2493
2494 if (!mInfoLog)
2495 {
2496 mInfoLog = new char[infoLength + 1];
2497 strcpy(mInfoLog, info);
2498 }
2499 else
2500 {
2501 size_t logLength = strlen(mInfoLog);
2502 char *newLog = new char[logLength + infoLength + 1];
2503 strcpy(newLog, mInfoLog);
2504 strcpy(newLog + logLength, info);
2505
2506 delete[] mInfoLog;
2507 mInfoLog = newLog;
2508 }
2509}
2510
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002511void Program::resetInfoLog()
2512{
2513 if (mInfoLog)
2514 {
2515 delete [] mInfoLog;
daniel@transgaming.com6a20d102010-08-31 13:54:27 +00002516 mInfoLog = NULL;
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002517 }
2518}
2519
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002520// Returns the program object to an unlinked state, after detaching a shader, before re-linking, or at destruction
2521void Program::unlink(bool destroy)
2522{
2523 if (destroy) // Object being destructed
2524 {
2525 if (mFragmentShader)
2526 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002527 mFragmentShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002528 mFragmentShader = NULL;
2529 }
2530
2531 if (mVertexShader)
2532 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002533 mVertexShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002534 mVertexShader = NULL;
2535 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002536 }
2537
2538 if (mPixelExecutable)
2539 {
2540 mPixelExecutable->Release();
2541 mPixelExecutable = NULL;
2542 }
2543
2544 if (mVertexExecutable)
2545 {
2546 mVertexExecutable->Release();
2547 mVertexExecutable = NULL;
2548 }
2549
2550 if (mConstantTablePS)
2551 {
2552 mConstantTablePS->Release();
2553 mConstantTablePS = NULL;
2554 }
2555
2556 if (mConstantTableVS)
2557 {
2558 mConstantTableVS->Release();
2559 mConstantTableVS = NULL;
2560 }
2561
2562 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
2563 {
daniel@transgaming.com85423182010-04-22 13:35:27 +00002564 mLinkedAttribute[index].name.clear();
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002565 mSemanticIndex[index] = -1;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002566 }
2567
2568 for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
2569 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002570 mSamplersPS[index].active = false;
2571 }
2572
2573 for (int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; index++)
2574 {
2575 mSamplersVS[index].active = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002576 }
2577
2578 while (!mUniforms.empty())
2579 {
2580 delete mUniforms.back();
2581 mUniforms.pop_back();
2582 }
2583
daniel@transgaming.com31754962010-11-28 02:02:52 +00002584 mDxDepthRangeLocation = -1;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002585 mDxDepthLocation = -1;
daniel@transgaming.com4f921eb2010-07-28 19:20:44 +00002586 mDxViewportLocation = -1;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002587 mDxHalfPixelSizeLocation = -1;
2588 mDxFrontCCWLocation = -1;
2589 mDxPointsOrLinesLocation = -1;
2590
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002591 mUniformIndex.clear();
2592
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00002593 mPixelHLSL.clear();
2594 mVertexHLSL.clear();
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00002595
2596 delete[] mInfoLog;
2597 mInfoLog = NULL;
2598
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002599 mLinked = false;
2600}
2601
2602bool Program::isLinked()
2603{
2604 return mLinked;
2605}
2606
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002607bool Program::isValidated() const
2608{
2609 return mValidated;
2610}
2611
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002612void Program::release()
2613{
2614 mRefCount--;
2615
2616 if (mRefCount == 0 && mDeleteStatus)
2617 {
2618 mResourceManager->deleteProgram(mHandle);
2619 }
2620}
2621
2622void Program::addRef()
2623{
2624 mRefCount++;
2625}
2626
2627unsigned int Program::getRefCount() const
2628{
2629 return mRefCount;
2630}
2631
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00002632unsigned int Program::getSerial() const
2633{
2634 return mSerial;
2635}
2636
2637unsigned int Program::issueSerial()
2638{
2639 return mCurrentSerial++;
2640}
2641
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002642int Program::getInfoLogLength() const
2643{
2644 if (!mInfoLog)
2645 {
2646 return 0;
2647 }
2648 else
2649 {
2650 return strlen(mInfoLog) + 1;
2651 }
2652}
2653
2654void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
2655{
2656 int index = 0;
2657
2658 if (mInfoLog)
2659 {
2660 while (index < bufSize - 1 && index < (int)strlen(mInfoLog))
2661 {
2662 infoLog[index] = mInfoLog[index];
2663 index++;
2664 }
2665 }
2666
2667 if (bufSize)
2668 {
2669 infoLog[index] = '\0';
2670 }
2671
2672 if (length)
2673 {
2674 *length = index;
2675 }
2676}
2677
daniel@transgaming.com6c785212010-03-30 03:36:17 +00002678void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
2679{
2680 int total = 0;
2681
2682 if (mVertexShader)
2683 {
2684 if (total < maxCount)
2685 {
2686 shaders[total] = mVertexShader->getHandle();
2687 }
2688
2689 total++;
2690 }
2691
2692 if (mFragmentShader)
2693 {
2694 if (total < maxCount)
2695 {
2696 shaders[total] = mFragmentShader->getHandle();
2697 }
2698
2699 total++;
2700 }
2701
2702 if (count)
2703 {
2704 *count = total;
2705 }
2706}
2707
daniel@transgaming.com85423182010-04-22 13:35:27 +00002708void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2709{
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002710 // Skip over inactive attributes
2711 unsigned int activeAttribute = 0;
2712 unsigned int attribute;
2713 for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
daniel@transgaming.com85423182010-04-22 13:35:27 +00002714 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002715 if (mLinkedAttribute[attribute].name.empty())
daniel@transgaming.com85423182010-04-22 13:35:27 +00002716 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002717 continue;
daniel@transgaming.com85423182010-04-22 13:35:27 +00002718 }
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002719
2720 if (activeAttribute == index)
2721 {
2722 break;
2723 }
2724
2725 activeAttribute++;
daniel@transgaming.com85423182010-04-22 13:35:27 +00002726 }
2727
2728 if (bufsize > 0)
2729 {
2730 const char *string = mLinkedAttribute[attribute].name.c_str();
2731
2732 strncpy(name, string, bufsize);
2733 name[bufsize - 1] = '\0';
2734
2735 if (length)
2736 {
2737 *length = strlen(name);
2738 }
2739 }
2740
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00002741 *size = 1; // Always a single 'type' instance
daniel@transgaming.com85423182010-04-22 13:35:27 +00002742
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002743 *type = mLinkedAttribute[attribute].type;
daniel@transgaming.com85423182010-04-22 13:35:27 +00002744}
2745
2746GLint Program::getActiveAttributeCount()
2747{
2748 int count = 0;
2749
2750 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2751 {
2752 if (!mLinkedAttribute[attributeIndex].name.empty())
2753 {
2754 count++;
2755 }
2756 }
2757
2758 return count;
2759}
2760
2761GLint Program::getActiveAttributeMaxLength()
2762{
2763 int maxLength = 0;
2764
2765 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2766 {
2767 if (!mLinkedAttribute[attributeIndex].name.empty())
2768 {
2769 maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength);
2770 }
2771 }
2772
2773 return maxLength;
2774}
2775
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002776void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2777{
daniel@transgaming.com996675c2010-11-17 13:06:29 +00002778 // Skip over internal uniforms
2779 unsigned int activeUniform = 0;
2780 unsigned int uniform;
2781 for (uniform = 0; uniform < mUniforms.size(); uniform++)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002782 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002783 if (mUniforms[uniform]->name.substr(0, 3) == "dx_")
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002784 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002785 continue;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002786 }
daniel@transgaming.com996675c2010-11-17 13:06:29 +00002787
2788 if (activeUniform == index)
2789 {
2790 break;
2791 }
2792
2793 activeUniform++;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002794 }
2795
daniel@transgaming.com996675c2010-11-17 13:06:29 +00002796 ASSERT(uniform < mUniforms.size()); // index must be smaller than getActiveUniformCount()
2797
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002798 if (bufsize > 0)
2799 {
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00002800 std::string string = undecorate(mUniforms[uniform]->name);
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002801
daniel@transgaming.comf3140152010-04-29 03:38:50 +00002802 if (mUniforms[uniform]->arraySize != 1)
2803 {
2804 string += "[0]";
2805 }
2806
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00002807 strncpy(name, string.c_str(), bufsize);
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002808 name[bufsize - 1] = '\0';
2809
2810 if (length)
2811 {
2812 *length = strlen(name);
2813 }
2814 }
2815
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00002816 *size = mUniforms[uniform]->arraySize;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002817
2818 *type = mUniforms[uniform]->type;
2819}
2820
2821GLint Program::getActiveUniformCount()
2822{
2823 int count = 0;
2824
daniel@transgaming.comd08ea902010-05-14 19:41:36 +00002825 unsigned int numUniforms = mUniforms.size();
2826 for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002827 {
2828 if (mUniforms[uniformIndex]->name.substr(0, 3) != "dx_")
2829 {
2830 count++;
2831 }
2832 }
2833
2834 return count;
2835}
2836
2837GLint Program::getActiveUniformMaxLength()
2838{
2839 int maxLength = 0;
2840
daniel@transgaming.comd08ea902010-05-14 19:41:36 +00002841 unsigned int numUniforms = mUniforms.size();
2842 for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002843 {
2844 if (!mUniforms[uniformIndex]->name.empty() && mUniforms[uniformIndex]->name.substr(0, 3) != "dx_")
2845 {
zmo@google.com53d73e02011-03-24 21:27:57 +00002846 int length = (int)(undecorate(mUniforms[uniformIndex]->name).length() + 1);
zmo@google.com2a5645f2011-03-24 21:36:51 +00002847 if (mUniforms[uniformIndex]->arraySize != 1)
zmo@google.com53d73e02011-03-24 21:27:57 +00002848 {
2849 length += 3; // Counting in "[0]".
2850 }
2851 maxLength = std::max(length, maxLength);
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002852 }
2853 }
2854
2855 return maxLength;
2856}
2857
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002858void Program::flagForDeletion()
2859{
2860 mDeleteStatus = true;
2861}
2862
2863bool Program::isFlaggedForDeletion() const
2864{
2865 return mDeleteStatus;
2866}
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002867
2868void Program::validate()
2869{
2870 resetInfoLog();
2871
2872 if (!isLinked())
2873 {
2874 appendToInfoLog("Program has not been successfully linked.");
2875 mValidated = false;
2876 }
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002877 else
2878 {
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002879 applyUniforms();
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002880 if (!validateSamplers(true))
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002881 {
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002882 mValidated = false;
2883 }
2884 else
2885 {
2886 mValidated = true;
2887 }
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002888 }
2889}
2890
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002891bool Program::validateSamplers(bool logErrors)
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002892{
2893 // if any two active samplers in a program are of different types, but refer to the same
2894 // texture image unit, and this is the current program, then ValidateProgram will fail, and
2895 // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002896
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002897 const unsigned int maxCombinedTextureImageUnits = getContext()->getMaximumCombinedTextureImageUnits();
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002898 TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF];
2899
2900 for (unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; ++i)
2901 {
2902 textureUnitType[i] = TEXTURE_UNKNOWN;
2903 }
2904
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002905 for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
2906 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002907 if (mSamplersPS[i].active)
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002908 {
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002909 unsigned int unit = mSamplersPS[i].logicalTextureUnit;
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002910
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002911 if (unit >= maxCombinedTextureImageUnits)
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002912 {
2913 if (logErrors)
2914 {
2915 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
2916 }
2917
2918 return false;
2919 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002920
2921 if (textureUnitType[unit] != TEXTURE_UNKNOWN)
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002922 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002923 if (mSamplersPS[i].textureType != textureUnitType[unit])
2924 {
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002925 if (logErrors)
2926 {
2927 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
2928 }
2929
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002930 return false;
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002931 }
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002932 }
2933 else
2934 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002935 textureUnitType[unit] = mSamplersPS[i].textureType;
2936 }
2937 }
2938 }
2939
2940 for (unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; ++i)
2941 {
2942 if (mSamplersVS[i].active)
2943 {
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002944 unsigned int unit = mSamplersVS[i].logicalTextureUnit;
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002945
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002946 if (unit >= maxCombinedTextureImageUnits)
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002947 {
2948 if (logErrors)
2949 {
2950 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
2951 }
2952
2953 return false;
2954 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002955
2956 if (textureUnitType[unit] != TEXTURE_UNKNOWN)
2957 {
2958 if (mSamplersVS[i].textureType != textureUnitType[unit])
2959 {
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002960 if (logErrors)
2961 {
2962 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
2963 }
2964
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002965 return false;
2966 }
2967 }
2968 else
2969 {
2970 textureUnitType[unit] = mSamplersVS[i].textureType;
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002971 }
2972 }
2973 }
2974
2975 return true;
2976}
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002977
2978void Program::getConstantHandles(Uniform *targetUniform, D3DXHANDLE *constantPS, D3DXHANDLE *constantVS)
2979{
2980 if (!targetUniform->handlesSet)
2981 {
2982 targetUniform->psHandle = mConstantTablePS->GetConstantByName(0, targetUniform->name.c_str());
2983 targetUniform->vsHandle = mConstantTableVS->GetConstantByName(0, targetUniform->name.c_str());
2984 targetUniform->handlesSet = true;
2985 }
2986
2987 *constantPS = targetUniform->psHandle;
2988 *constantVS = targetUniform->vsHandle;
2989}
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002990
daniel@transgaming.com31754962010-11-28 02:02:52 +00002991GLint Program::getDxDepthRangeLocation() const
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002992{
daniel@transgaming.com31754962010-11-28 02:02:52 +00002993 return mDxDepthRangeLocation;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002994}
2995
2996GLint Program::getDxDepthLocation() const
2997{
2998 return mDxDepthLocation;
2999}
3000
daniel@transgaming.com4f921eb2010-07-28 19:20:44 +00003001GLint Program::getDxViewportLocation() const
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00003002{
daniel@transgaming.com4f921eb2010-07-28 19:20:44 +00003003 return mDxViewportLocation;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00003004}
3005
3006GLint Program::getDxHalfPixelSizeLocation() const
3007{
3008 return mDxHalfPixelSizeLocation;
3009}
3010
3011GLint Program::getDxFrontCCWLocation() const
3012{
3013 return mDxFrontCCWLocation;
3014}
3015
3016GLint Program::getDxPointsOrLinesLocation() const
3017{
3018 return mDxPointsOrLinesLocation;
3019}
3020
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003021}