blob: 98dc20145e318416d881a260142f23eead866f20 [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;
daniel@transgaming.com8a4dad62011-09-13 00:54:40 +000027const char *fakepath = "C:\\fakepath";
daniel@transgaming.com4fa08332010-05-11 02:29:27 +000028
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +000029std::string str(int i)
30{
31 char buffer[20];
32 sprintf(buffer, "%d", i);
33 return buffer;
34}
35
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000036Uniform::Uniform(GLenum type, const std::string &name, unsigned int arraySize) : type(type), name(name), arraySize(arraySize)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000037{
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000038 int bytes = UniformTypeSize(type) * arraySize;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +000039 data = new unsigned char[bytes];
40 memset(data, 0, bytes);
41 dirty = true;
daniel@transgaming.com2d84df02010-05-14 17:31:13 +000042 handlesSet = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000043}
44
45Uniform::~Uniform()
46{
47 delete[] data;
48}
49
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +000050UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index)
51 : name(name), element(element), index(index)
52{
53}
54
daniel@transgaming.com73a5db62010-10-15 17:58:13 +000055Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle), mSerial(issueSerial())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000056{
57 mFragmentShader = NULL;
58 mVertexShader = NULL;
59
60 mPixelExecutable = NULL;
61 mVertexExecutable = NULL;
62 mConstantTablePS = NULL;
63 mConstantTableVS = NULL;
64
daniel@transgaming.comcba50572010-03-28 19:36:09 +000065 mInfoLog = NULL;
daniel@transgaming.com86a7a132010-04-29 03:32:32 +000066 mValidated = false;
daniel@transgaming.comcba50572010-03-28 19:36:09 +000067
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000068 unlink();
69
70 mDeleteStatus = false;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +000071
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000072 mRefCount = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000073}
74
75Program::~Program()
76{
77 unlink(true);
daniel@transgaming.com71cd8682010-04-29 03:35:25 +000078
79 if (mVertexShader != NULL)
80 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000081 mVertexShader->release();
daniel@transgaming.com71cd8682010-04-29 03:35:25 +000082 }
83
84 if (mFragmentShader != NULL)
85 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000086 mFragmentShader->release();
daniel@transgaming.com71cd8682010-04-29 03:35:25 +000087 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000088}
89
90bool Program::attachShader(Shader *shader)
91{
92 if (shader->getType() == GL_VERTEX_SHADER)
93 {
94 if (mVertexShader)
95 {
96 return false;
97 }
98
99 mVertexShader = (VertexShader*)shader;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000100 mVertexShader->addRef();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101 }
102 else if (shader->getType() == GL_FRAGMENT_SHADER)
103 {
104 if (mFragmentShader)
105 {
106 return false;
107 }
108
109 mFragmentShader = (FragmentShader*)shader;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000110 mFragmentShader->addRef();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000111 }
112 else UNREACHABLE();
113
114 return true;
115}
116
117bool Program::detachShader(Shader *shader)
118{
119 if (shader->getType() == GL_VERTEX_SHADER)
120 {
121 if (mVertexShader != shader)
122 {
123 return false;
124 }
125
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000126 mVertexShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000127 mVertexShader = NULL;
128 }
129 else if (shader->getType() == GL_FRAGMENT_SHADER)
130 {
131 if (mFragmentShader != shader)
132 {
133 return false;
134 }
135
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000136 mFragmentShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000137 mFragmentShader = NULL;
138 }
139 else UNREACHABLE();
140
141 unlink();
142
143 return true;
144}
145
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000146int Program::getAttachedShadersCount() const
147{
148 return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
149}
150
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000151IDirect3DPixelShader9 *Program::getPixelShader()
152{
153 return mPixelExecutable;
154}
155
156IDirect3DVertexShader9 *Program::getVertexShader()
157{
158 return mVertexExecutable;
159}
160
161void Program::bindAttributeLocation(GLuint index, const char *name)
162{
163 if (index < MAX_VERTEX_ATTRIBS)
164 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000165 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
166 {
167 mAttributeBinding[i].erase(name);
168 }
169
170 mAttributeBinding[index].insert(name);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000171 }
172}
173
174GLuint Program::getAttributeLocation(const char *name)
175{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000176 if (name)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000177 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000178 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000179 {
daniel@transgaming.com85423182010-04-22 13:35:27 +0000180 if (mLinkedAttribute[index].name == std::string(name))
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000181 {
182 return index;
183 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000184 }
185 }
186
187 return -1;
188}
189
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000190int Program::getSemanticIndex(int attributeIndex)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000191{
daniel@transgaming.com733ba932011-04-14 15:03:48 +0000192 ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
193
194 return mSemanticIndex[attributeIndex];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000195}
196
daniel@transgaming.com9ba680a2011-05-11 15:37:11 +0000197// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler
198// index (0-15 for the pixel shader and 0-3 for the vertex shader).
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000199GLint Program::getSamplerMapping(SamplerType type, unsigned int samplerIndex)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000200{
daniel@transgaming.comdfd57022011-05-11 15:37:25 +0000201 GLuint logicalTextureUnit = -1;
daniel@transgaming.com4071e662010-05-12 16:51:16 +0000202
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000203 switch (type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000205 case SAMPLER_PIXEL:
206 ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
207
208 if (mSamplersPS[samplerIndex].active)
209 {
210 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
211 }
212 break;
213 case SAMPLER_VERTEX:
214 ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
215
216 if (mSamplersVS[samplerIndex].active)
217 {
218 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
219 }
220 break;
221 default: UNREACHABLE();
daniel@transgaming.com4071e662010-05-12 16:51:16 +0000222 }
223
daniel@transgaming.com3f74c7a2011-05-11 15:36:51 +0000224 if (logicalTextureUnit >= 0 && logicalTextureUnit < getContext()->getMaximumCombinedTextureImageUnits())
daniel@transgaming.com4071e662010-05-12 16:51:16 +0000225 {
226 return logicalTextureUnit;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000227 }
228
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000229 return -1;
230}
231
daniel@transgaming.com9ba680a2011-05-11 15:37:11 +0000232// Returns the texture type for a given Direct3D 9 sampler type and
233// index (0-15 for the pixel shader and 0-3 for the vertex shader).
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000234TextureType Program::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000235{
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000236 switch (type)
237 {
238 case SAMPLER_PIXEL:
239 ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
240 ASSERT(mSamplersPS[samplerIndex].active);
241 return mSamplersPS[samplerIndex].textureType;
242 case SAMPLER_VERTEX:
243 ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
244 ASSERT(mSamplersVS[samplerIndex].active);
245 return mSamplersVS[samplerIndex].textureType;
246 default: UNREACHABLE();
247 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000248
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000249 return TEXTURE_2D;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000250}
251
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +0000252GLint Program::getUniformLocation(const char *name, bool decorated)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000253{
daniel@transgaming.comce864422010-11-18 13:16:49 +0000254 std::string _name = decorated ? name : decorate(name);
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000255 int subscript = 0;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000256
daniel@transgaming.comce864422010-11-18 13:16:49 +0000257 // Strip any trailing array operator and retrieve the subscript
258 size_t open = _name.find_last_of('[');
259 size_t close = _name.find_last_of(']');
260 if (open != std::string::npos && close == _name.length() - 1)
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +0000261 {
daniel@transgaming.comce864422010-11-18 13:16:49 +0000262 subscript = atoi(_name.substr(open + 1).c_str());
263 _name.erase(open);
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +0000264 }
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000265
daniel@transgaming.comd08ea902010-05-14 19:41:36 +0000266 unsigned int numUniforms = mUniformIndex.size();
267 for (unsigned int location = 0; location < numUniforms; location++)
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000268 {
daniel@transgaming.comce864422010-11-18 13:16:49 +0000269 if (mUniformIndex[location].name == _name &&
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000270 mUniformIndex[location].element == subscript)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000271 {
272 return location;
273 }
274 }
275
276 return -1;
277}
278
279bool Program::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
280{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000281 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000282 {
283 return false;
284 }
285
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000286 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000287 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000288
289 if (targetUniform->type == GL_FLOAT)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000290 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000291 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000292
293 if (arraySize == 1 && count > 1)
294 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
295
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000296 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000297
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000298 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat),
299 v, sizeof(GLfloat) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000300 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000301 else if (targetUniform->type == GL_BOOL)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000302 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000303 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000304
305 if (arraySize == 1 && count > 1)
306 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000307
308 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000309 GLboolean *boolParams = new GLboolean[count];
310
311 for (int i = 0; i < count; ++i)
312 {
313 if (v[i] == 0.0f)
314 {
315 boolParams[i] = GL_FALSE;
316 }
317 else
318 {
319 boolParams[i] = GL_TRUE;
320 }
321 }
322
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000323 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean),
324 boolParams, sizeof(GLboolean) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000325
326 delete [] boolParams;
327 }
328 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000329 {
330 return false;
331 }
332
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000333 return true;
334}
335
336bool Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
337{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000338 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000339 {
340 return false;
341 }
342
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000343 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000344 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000345
346 if (targetUniform->type == GL_FLOAT_VEC2)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000347 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000348 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000349
350 if (arraySize == 1 && count > 1)
351 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
352
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000353 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000354
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000355 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 2,
356 v, 2 * sizeof(GLfloat) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000357 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000358 else if (targetUniform->type == GL_BOOL_VEC2)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000359 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000360 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000361
362 if (arraySize == 1 && count > 1)
363 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
364
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000365 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
366
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000367 GLboolean *boolParams = new GLboolean[count * 2];
368
369 for (int i = 0; i < count * 2; ++i)
370 {
371 if (v[i] == 0.0f)
372 {
373 boolParams[i] = GL_FALSE;
374 }
375 else
376 {
377 boolParams[i] = GL_TRUE;
378 }
379 }
380
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000381 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 2,
382 boolParams, 2 * sizeof(GLboolean) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000383
384 delete [] boolParams;
385 }
386 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000387 {
388 return false;
389 }
390
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000391 return true;
392}
393
394bool Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
395{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000396 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000397 {
398 return false;
399 }
400
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000401 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000402 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000403
404 if (targetUniform->type == GL_FLOAT_VEC3)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000405 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000406 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000407
408 if (arraySize == 1 && count > 1)
409 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
410
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000411 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000412
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000413 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 3,
414 v, 3 * sizeof(GLfloat) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000415 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000416 else if (targetUniform->type == GL_BOOL_VEC3)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000417 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000418 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000419
420 if (arraySize == 1 && count > 1)
421 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
422
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000423 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000424 GLboolean *boolParams = new GLboolean[count * 3];
425
426 for (int i = 0; i < count * 3; ++i)
427 {
428 if (v[i] == 0.0f)
429 {
430 boolParams[i] = GL_FALSE;
431 }
432 else
433 {
434 boolParams[i] = GL_TRUE;
435 }
436 }
437
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000438 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 3,
439 boolParams, 3 * sizeof(GLboolean) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000440
441 delete [] boolParams;
442 }
443 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000444 {
445 return false;
446 }
447
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000448 return true;
449}
450
451bool Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
452{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000453 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000454 {
455 return false;
456 }
457
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000458 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000459 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000460
461 if (targetUniform->type == GL_FLOAT_VEC4)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000462 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000463 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000464
465 if (arraySize == 1 && count > 1)
466 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
467
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000468 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000469
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000470 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4,
471 v, 4 * sizeof(GLfloat) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000472 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000473 else if (targetUniform->type == GL_BOOL_VEC4)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000474 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000475 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000476
477 if (arraySize == 1 && count > 1)
478 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
479
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000480 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000481 GLboolean *boolParams = new GLboolean[count * 4];
482
483 for (int i = 0; i < count * 4; ++i)
484 {
485 if (v[i] == 0.0f)
486 {
487 boolParams[i] = GL_FALSE;
488 }
489 else
490 {
491 boolParams[i] = GL_TRUE;
492 }
493 }
494
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000495 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 4,
496 boolParams, 4 * sizeof(GLboolean) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000497
498 delete [] boolParams;
499 }
500 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000501 {
502 return false;
503 }
504
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000505 return true;
506}
507
508bool Program::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
509{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000510 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000511 {
512 return false;
513 }
514
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000515 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000516 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000517
518 if (targetUniform->type != GL_FLOAT_MAT2)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000519 {
520 return false;
521 }
522
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000523 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000524
525 if (arraySize == 1 && count > 1)
526 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
527
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000528 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000529
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000530 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4,
531 value, 4 * sizeof(GLfloat) * count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000532
533 return true;
534}
535
536bool Program::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
537{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000538 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000539 {
540 return false;
541 }
542
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000543 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000544 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000545
546 if (targetUniform->type != GL_FLOAT_MAT3)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000547 {
548 return false;
549 }
550
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000551 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000552
553 if (arraySize == 1 && count > 1)
554 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
555
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000556 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000557
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000558 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 9,
559 value, 9 * sizeof(GLfloat) * count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000560
561 return true;
562}
563
564bool Program::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
565{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000566 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000567 {
568 return false;
569 }
570
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000571 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000572 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000573
574 if (targetUniform->type != GL_FLOAT_MAT4)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000575 {
576 return false;
577 }
578
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000579 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000580
581 if (arraySize == 1 && count > 1)
582 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
583
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000584 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000585
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000586 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16,
587 value, 16 * sizeof(GLfloat) * count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000588
589 return true;
590}
591
592bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
593{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000594 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000595 {
596 return false;
597 }
598
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000599 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000600 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000601
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +0000602 if (targetUniform->type == GL_INT ||
603 targetUniform->type == GL_SAMPLER_2D ||
604 targetUniform->type == GL_SAMPLER_CUBE)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000605 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000606 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000607
608 if (arraySize == 1 && count > 1)
609 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
610
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000611 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000612
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000613 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint),
614 v, sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000615 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000616 else if (targetUniform->type == GL_BOOL)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000617 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000618 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000619
620 if (arraySize == 1 && count > 1)
621 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
622
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000623 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000624 GLboolean *boolParams = new GLboolean[count];
625
626 for (int i = 0; i < count; ++i)
627 {
628 if (v[i] == 0)
629 {
630 boolParams[i] = GL_FALSE;
631 }
632 else
633 {
634 boolParams[i] = GL_TRUE;
635 }
636 }
637
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000638 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean),
639 boolParams, sizeof(GLboolean) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000640
641 delete [] boolParams;
642 }
643 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000644 {
645 return false;
646 }
647
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000648 return true;
649}
650
651bool Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
652{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000653 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000654 {
655 return false;
656 }
657
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000658 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000659 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000660
661 if (targetUniform->type == GL_INT_VEC2)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000662 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000663 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000664
665 if (arraySize == 1 && count > 1)
666 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
667
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000668 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000669
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000670 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 2,
671 v, 2 * sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000672 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000673 else if (targetUniform->type == GL_BOOL_VEC2)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000674 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000675 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000676
677 if (arraySize == 1 && count > 1)
678 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
679
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000680 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000681 GLboolean *boolParams = new GLboolean[count * 2];
682
683 for (int i = 0; i < count * 2; ++i)
684 {
685 if (v[i] == 0)
686 {
687 boolParams[i] = GL_FALSE;
688 }
689 else
690 {
691 boolParams[i] = GL_TRUE;
692 }
693 }
694
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000695 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 2,
696 boolParams, 2 * sizeof(GLboolean) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000697
698 delete [] boolParams;
699 }
700 else
701 {
702 return false;
703 }
704
705 return true;
706}
707
708bool Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
709{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000710 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000711 {
712 return false;
713 }
714
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000715 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000716 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000717
718 if (targetUniform->type == GL_INT_VEC3)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000719 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000720 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000721
722 if (arraySize == 1 && count > 1)
723 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
724
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000725 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000726
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000727 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 3,
728 v, 3 * sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000729 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000730 else if (targetUniform->type == GL_BOOL_VEC3)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000731 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000732 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000733
734 if (arraySize == 1 && count > 1)
735 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
736
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000737 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000738 GLboolean *boolParams = new GLboolean[count * 3];
739
740 for (int i = 0; i < count * 3; ++i)
741 {
742 if (v[i] == 0)
743 {
744 boolParams[i] = GL_FALSE;
745 }
746 else
747 {
748 boolParams[i] = GL_TRUE;
749 }
750 }
751
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000752 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 3,
753 boolParams, 3 * sizeof(GLboolean) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000754
755 delete [] boolParams;
756 }
757 else
758 {
759 return false;
760 }
761
762 return true;
763}
764
765bool Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
766{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000767 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000768 {
769 return false;
770 }
771
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000772 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000773 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000774
775 if (targetUniform->type == GL_INT_VEC4)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000776 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000777 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000778
779 if (arraySize == 1 && count > 1)
780 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
781
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000782 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000783
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000784 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 4,
785 v, 4 * sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000786 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000787 else if (targetUniform->type == GL_BOOL_VEC4)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000788 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000789 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000790
791 if (arraySize == 1 && count > 1)
792 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
793
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000794 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000795 GLboolean *boolParams = new GLboolean[count * 4];
796
797 for (int i = 0; i < count * 4; ++i)
798 {
799 if (v[i] == 0)
800 {
801 boolParams[i] = GL_FALSE;
802 }
803 else
804 {
805 boolParams[i] = GL_TRUE;
806 }
807 }
808
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000809 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 4,
810 boolParams, 4 * sizeof(GLboolean) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000811
812 delete [] boolParams;
813 }
814 else
815 {
816 return false;
817 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000818
819 return true;
820}
821
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000822bool Program::getUniformfv(GLint location, GLfloat *params)
823{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000824 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000825 {
826 return false;
827 }
828
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000829 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000830
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000831 unsigned int count = UniformComponentCount(targetUniform->type);
832
833 switch (UniformComponentType(targetUniform->type))
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000834 {
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000835 case GL_BOOL:
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000836 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000837 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * count;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000838
839 for (unsigned int i = 0; i < count; ++i)
840 {
841 params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
842 }
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000843 }
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000844 break;
845 case GL_FLOAT:
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000846 memcpy(params, targetUniform->data + mUniformIndex[location].element * count * sizeof(GLfloat),
847 count * sizeof(GLfloat));
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000848 break;
849 case GL_INT:
850 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000851 GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * count;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000852
853 for (unsigned int i = 0; i < count; ++i)
854 {
855 params[i] = (float)intParams[i];
856 }
857 }
858 break;
859 default: UNREACHABLE();
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000860 }
861
862 return true;
863}
864
865bool Program::getUniformiv(GLint location, GLint *params)
866{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000867 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000868 {
869 return false;
870 }
871
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000872 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000873
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000874 unsigned int count = UniformComponentCount(targetUniform->type);
875
876 switch (UniformComponentType(targetUniform->type))
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000877 {
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000878 case GL_BOOL:
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000879 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000880 GLboolean *boolParams = targetUniform->data + mUniformIndex[location].element * count;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000881
882 for (unsigned int i = 0; i < count; ++i)
883 {
884 params[i] = (GLint)boolParams[i];
885 }
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000886 }
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000887 break;
888 case GL_FLOAT:
889 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000890 GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * count;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000891
892 for (unsigned int i = 0; i < count; ++i)
893 {
894 params[i] = (GLint)floatParams[i];
895 }
896 }
897 break;
898 case GL_INT:
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000899 memcpy(params, targetUniform->data + mUniformIndex[location].element * count * sizeof(GLint),
900 count * sizeof(GLint));
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000901 break;
902 default: UNREACHABLE();
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000903 }
904
905 return true;
906}
907
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000908void Program::dirtyAllUniforms()
909{
daniel@transgaming.comd08ea902010-05-14 19:41:36 +0000910 unsigned int numUniforms = mUniforms.size();
911 for (unsigned int index = 0; index < numUniforms; index++)
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000912 {
913 mUniforms[index]->dirty = true;
914 }
915}
916
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000917// Applies all the uniforms set for this program object to the Direct3D 9 device
918void Program::applyUniforms()
919{
daniel@transgaming.comd08ea902010-05-14 19:41:36 +0000920 unsigned int numUniforms = mUniformIndex.size();
921 for (unsigned int location = 0; location < numUniforms; location++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000922 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000923 if (mUniformIndex[location].element != 0)
924 {
925 continue;
926 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000927
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000928 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
929
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000930 if (targetUniform->dirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000931 {
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000932 int arraySize = targetUniform->arraySize;
933 GLfloat *f = (GLfloat*)targetUniform->data;
934 GLint *i = (GLint*)targetUniform->data;
935 GLboolean *b = (GLboolean*)targetUniform->data;
936
937 switch (targetUniform->type)
938 {
939 case GL_BOOL: applyUniform1bv(location, arraySize, b); break;
940 case GL_BOOL_VEC2: applyUniform2bv(location, arraySize, b); break;
941 case GL_BOOL_VEC3: applyUniform3bv(location, arraySize, b); break;
942 case GL_BOOL_VEC4: applyUniform4bv(location, arraySize, b); break;
943 case GL_FLOAT: applyUniform1fv(location, arraySize, f); break;
944 case GL_FLOAT_VEC2: applyUniform2fv(location, arraySize, f); break;
945 case GL_FLOAT_VEC3: applyUniform3fv(location, arraySize, f); break;
946 case GL_FLOAT_VEC4: applyUniform4fv(location, arraySize, f); break;
947 case GL_FLOAT_MAT2: applyUniformMatrix2fv(location, arraySize, f); break;
948 case GL_FLOAT_MAT3: applyUniformMatrix3fv(location, arraySize, f); break;
949 case GL_FLOAT_MAT4: applyUniformMatrix4fv(location, arraySize, f); break;
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +0000950 case GL_SAMPLER_2D:
951 case GL_SAMPLER_CUBE:
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000952 case GL_INT: applyUniform1iv(location, arraySize, i); break;
953 case GL_INT_VEC2: applyUniform2iv(location, arraySize, i); break;
954 case GL_INT_VEC3: applyUniform3iv(location, arraySize, i); break;
955 case GL_INT_VEC4: applyUniform4iv(location, arraySize, i); break;
956 default:
957 UNREACHABLE();
958 }
959
960 targetUniform->dirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000961 }
962 }
963}
964
965// Compiles the HLSL code of the attached shaders into executable binaries
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000966ID3D10Blob *Program::compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000967{
968 if (!hlsl)
969 {
970 return NULL;
971 }
972
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000973 DWORD result;
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000974 UINT flags = 0;
975 std::string sourceText;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000976 if (perfActive())
977 {
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000978 flags |= D3DCOMPILE_DEBUG;
979#ifdef NDEBUG
980 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
981#else
982 flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000983#endif
984
985 std::string sourcePath = getTempPath();
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000986 sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000987 writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000988 }
989 else
990 {
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000991 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
992 sourceText = hlsl;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000993 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000994
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000995 ID3D10Blob *binary = NULL;
996 ID3D10Blob *errorMessage = NULL;
daniel@transgaming.com8a4dad62011-09-13 00:54:40 +0000997 result = D3DCompile(hlsl, strlen(hlsl), fakepath, NULL, NULL, "main", profile, flags, 0, &binary, &errorMessage);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000998
999 if (errorMessage)
1000 {
1001 const char *message = (const char*)errorMessage->GetBufferPointer();
daniel@transgaming.comcba50572010-03-28 19:36:09 +00001002
daniel@transgaming.com87891f72011-06-01 15:28:35 +00001003 appendToInfoLogSanitized(message);
daniel@transgaming.com0599dc62010-03-21 04:31:36 +00001004 TRACE("\n%s", hlsl);
1005 TRACE("\n%s", message);
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001006
1007 errorMessage->Release();
1008 errorMessage = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001009 }
1010
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001011 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.
daniel@transgaming.com8a4dad62011-09-13 00:54:40 +00002451// The D3D compiler includes a fake file path in some of the warning or error
2452// messages, so lets remove all occurrences of this fake file path from the log.
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002453void Program::appendToInfoLogSanitized(const char *message)
2454{
2455 std::string msg(message);
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002456
daniel@transgaming.com8a4dad62011-09-13 00:54:40 +00002457 size_t found;
2458 do
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002459 {
daniel@transgaming.com8a4dad62011-09-13 00:54:40 +00002460 found = msg.find(fakepath);
2461 if (found != std::string::npos)
2462 {
2463 msg.erase(found, strlen(fakepath));
2464 }
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002465 }
daniel@transgaming.com8a4dad62011-09-13 00:54:40 +00002466 while (found != std::string::npos);
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002467
2468 appendToInfoLog("%s\n", msg.c_str());
2469}
2470
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002471void Program::appendToInfoLog(const char *format, ...)
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002472{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002473 if (!format)
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002474 {
2475 return;
2476 }
2477
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002478 char info[1024];
2479
2480 va_list vararg;
2481 va_start(vararg, format);
2482 vsnprintf(info, sizeof(info), format, vararg);
2483 va_end(vararg);
2484
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002485 size_t infoLength = strlen(info);
2486
2487 if (!mInfoLog)
2488 {
2489 mInfoLog = new char[infoLength + 1];
2490 strcpy(mInfoLog, info);
2491 }
2492 else
2493 {
2494 size_t logLength = strlen(mInfoLog);
2495 char *newLog = new char[logLength + infoLength + 1];
2496 strcpy(newLog, mInfoLog);
2497 strcpy(newLog + logLength, info);
2498
2499 delete[] mInfoLog;
2500 mInfoLog = newLog;
2501 }
2502}
2503
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002504void Program::resetInfoLog()
2505{
2506 if (mInfoLog)
2507 {
2508 delete [] mInfoLog;
daniel@transgaming.com6a20d102010-08-31 13:54:27 +00002509 mInfoLog = NULL;
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002510 }
2511}
2512
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002513// Returns the program object to an unlinked state, after detaching a shader, before re-linking, or at destruction
2514void Program::unlink(bool destroy)
2515{
2516 if (destroy) // Object being destructed
2517 {
2518 if (mFragmentShader)
2519 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002520 mFragmentShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002521 mFragmentShader = NULL;
2522 }
2523
2524 if (mVertexShader)
2525 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002526 mVertexShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002527 mVertexShader = NULL;
2528 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002529 }
2530
2531 if (mPixelExecutable)
2532 {
2533 mPixelExecutable->Release();
2534 mPixelExecutable = NULL;
2535 }
2536
2537 if (mVertexExecutable)
2538 {
2539 mVertexExecutable->Release();
2540 mVertexExecutable = NULL;
2541 }
2542
2543 if (mConstantTablePS)
2544 {
2545 mConstantTablePS->Release();
2546 mConstantTablePS = NULL;
2547 }
2548
2549 if (mConstantTableVS)
2550 {
2551 mConstantTableVS->Release();
2552 mConstantTableVS = NULL;
2553 }
2554
2555 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
2556 {
daniel@transgaming.com85423182010-04-22 13:35:27 +00002557 mLinkedAttribute[index].name.clear();
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002558 mSemanticIndex[index] = -1;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002559 }
2560
2561 for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
2562 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002563 mSamplersPS[index].active = false;
2564 }
2565
2566 for (int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; index++)
2567 {
2568 mSamplersVS[index].active = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002569 }
2570
2571 while (!mUniforms.empty())
2572 {
2573 delete mUniforms.back();
2574 mUniforms.pop_back();
2575 }
2576
daniel@transgaming.com31754962010-11-28 02:02:52 +00002577 mDxDepthRangeLocation = -1;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002578 mDxDepthLocation = -1;
daniel@transgaming.com4f921eb2010-07-28 19:20:44 +00002579 mDxViewportLocation = -1;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002580 mDxHalfPixelSizeLocation = -1;
2581 mDxFrontCCWLocation = -1;
2582 mDxPointsOrLinesLocation = -1;
2583
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002584 mUniformIndex.clear();
2585
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00002586 mPixelHLSL.clear();
2587 mVertexHLSL.clear();
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00002588
2589 delete[] mInfoLog;
2590 mInfoLog = NULL;
2591
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002592 mLinked = false;
2593}
2594
2595bool Program::isLinked()
2596{
2597 return mLinked;
2598}
2599
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002600bool Program::isValidated() const
2601{
2602 return mValidated;
2603}
2604
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002605void Program::release()
2606{
2607 mRefCount--;
2608
2609 if (mRefCount == 0 && mDeleteStatus)
2610 {
2611 mResourceManager->deleteProgram(mHandle);
2612 }
2613}
2614
2615void Program::addRef()
2616{
2617 mRefCount++;
2618}
2619
2620unsigned int Program::getRefCount() const
2621{
2622 return mRefCount;
2623}
2624
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00002625unsigned int Program::getSerial() const
2626{
2627 return mSerial;
2628}
2629
2630unsigned int Program::issueSerial()
2631{
2632 return mCurrentSerial++;
2633}
2634
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002635int Program::getInfoLogLength() const
2636{
2637 if (!mInfoLog)
2638 {
2639 return 0;
2640 }
2641 else
2642 {
2643 return strlen(mInfoLog) + 1;
2644 }
2645}
2646
2647void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
2648{
2649 int index = 0;
2650
2651 if (mInfoLog)
2652 {
2653 while (index < bufSize - 1 && index < (int)strlen(mInfoLog))
2654 {
2655 infoLog[index] = mInfoLog[index];
2656 index++;
2657 }
2658 }
2659
2660 if (bufSize)
2661 {
2662 infoLog[index] = '\0';
2663 }
2664
2665 if (length)
2666 {
2667 *length = index;
2668 }
2669}
2670
daniel@transgaming.com6c785212010-03-30 03:36:17 +00002671void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
2672{
2673 int total = 0;
2674
2675 if (mVertexShader)
2676 {
2677 if (total < maxCount)
2678 {
2679 shaders[total] = mVertexShader->getHandle();
2680 }
2681
2682 total++;
2683 }
2684
2685 if (mFragmentShader)
2686 {
2687 if (total < maxCount)
2688 {
2689 shaders[total] = mFragmentShader->getHandle();
2690 }
2691
2692 total++;
2693 }
2694
2695 if (count)
2696 {
2697 *count = total;
2698 }
2699}
2700
daniel@transgaming.com85423182010-04-22 13:35:27 +00002701void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2702{
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002703 // Skip over inactive attributes
2704 unsigned int activeAttribute = 0;
2705 unsigned int attribute;
2706 for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
daniel@transgaming.com85423182010-04-22 13:35:27 +00002707 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002708 if (mLinkedAttribute[attribute].name.empty())
daniel@transgaming.com85423182010-04-22 13:35:27 +00002709 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002710 continue;
daniel@transgaming.com85423182010-04-22 13:35:27 +00002711 }
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002712
2713 if (activeAttribute == index)
2714 {
2715 break;
2716 }
2717
2718 activeAttribute++;
daniel@transgaming.com85423182010-04-22 13:35:27 +00002719 }
2720
2721 if (bufsize > 0)
2722 {
2723 const char *string = mLinkedAttribute[attribute].name.c_str();
2724
2725 strncpy(name, string, bufsize);
2726 name[bufsize - 1] = '\0';
2727
2728 if (length)
2729 {
2730 *length = strlen(name);
2731 }
2732 }
2733
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00002734 *size = 1; // Always a single 'type' instance
daniel@transgaming.com85423182010-04-22 13:35:27 +00002735
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002736 *type = mLinkedAttribute[attribute].type;
daniel@transgaming.com85423182010-04-22 13:35:27 +00002737}
2738
2739GLint Program::getActiveAttributeCount()
2740{
2741 int count = 0;
2742
2743 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2744 {
2745 if (!mLinkedAttribute[attributeIndex].name.empty())
2746 {
2747 count++;
2748 }
2749 }
2750
2751 return count;
2752}
2753
2754GLint Program::getActiveAttributeMaxLength()
2755{
2756 int maxLength = 0;
2757
2758 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2759 {
2760 if (!mLinkedAttribute[attributeIndex].name.empty())
2761 {
2762 maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength);
2763 }
2764 }
2765
2766 return maxLength;
2767}
2768
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002769void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2770{
daniel@transgaming.com996675c2010-11-17 13:06:29 +00002771 // Skip over internal uniforms
2772 unsigned int activeUniform = 0;
2773 unsigned int uniform;
2774 for (uniform = 0; uniform < mUniforms.size(); uniform++)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002775 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002776 if (mUniforms[uniform]->name.substr(0, 3) == "dx_")
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002777 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002778 continue;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002779 }
daniel@transgaming.com996675c2010-11-17 13:06:29 +00002780
2781 if (activeUniform == index)
2782 {
2783 break;
2784 }
2785
2786 activeUniform++;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002787 }
2788
daniel@transgaming.com996675c2010-11-17 13:06:29 +00002789 ASSERT(uniform < mUniforms.size()); // index must be smaller than getActiveUniformCount()
2790
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002791 if (bufsize > 0)
2792 {
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00002793 std::string string = undecorate(mUniforms[uniform]->name);
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002794
daniel@transgaming.comf3140152010-04-29 03:38:50 +00002795 if (mUniforms[uniform]->arraySize != 1)
2796 {
2797 string += "[0]";
2798 }
2799
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00002800 strncpy(name, string.c_str(), bufsize);
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002801 name[bufsize - 1] = '\0';
2802
2803 if (length)
2804 {
2805 *length = strlen(name);
2806 }
2807 }
2808
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00002809 *size = mUniforms[uniform]->arraySize;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002810
2811 *type = mUniforms[uniform]->type;
2812}
2813
2814GLint Program::getActiveUniformCount()
2815{
2816 int count = 0;
2817
daniel@transgaming.comd08ea902010-05-14 19:41:36 +00002818 unsigned int numUniforms = mUniforms.size();
2819 for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002820 {
2821 if (mUniforms[uniformIndex]->name.substr(0, 3) != "dx_")
2822 {
2823 count++;
2824 }
2825 }
2826
2827 return count;
2828}
2829
2830GLint Program::getActiveUniformMaxLength()
2831{
2832 int maxLength = 0;
2833
daniel@transgaming.comd08ea902010-05-14 19:41:36 +00002834 unsigned int numUniforms = mUniforms.size();
2835 for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002836 {
2837 if (!mUniforms[uniformIndex]->name.empty() && mUniforms[uniformIndex]->name.substr(0, 3) != "dx_")
2838 {
zmo@google.com53d73e02011-03-24 21:27:57 +00002839 int length = (int)(undecorate(mUniforms[uniformIndex]->name).length() + 1);
zmo@google.com2a5645f2011-03-24 21:36:51 +00002840 if (mUniforms[uniformIndex]->arraySize != 1)
zmo@google.com53d73e02011-03-24 21:27:57 +00002841 {
2842 length += 3; // Counting in "[0]".
2843 }
2844 maxLength = std::max(length, maxLength);
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002845 }
2846 }
2847
2848 return maxLength;
2849}
2850
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002851void Program::flagForDeletion()
2852{
2853 mDeleteStatus = true;
2854}
2855
2856bool Program::isFlaggedForDeletion() const
2857{
2858 return mDeleteStatus;
2859}
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002860
2861void Program::validate()
2862{
2863 resetInfoLog();
2864
2865 if (!isLinked())
2866 {
2867 appendToInfoLog("Program has not been successfully linked.");
2868 mValidated = false;
2869 }
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002870 else
2871 {
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002872 applyUniforms();
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002873 if (!validateSamplers(true))
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002874 {
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002875 mValidated = false;
2876 }
2877 else
2878 {
2879 mValidated = true;
2880 }
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002881 }
2882}
2883
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002884bool Program::validateSamplers(bool logErrors)
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002885{
2886 // if any two active samplers in a program are of different types, but refer to the same
2887 // texture image unit, and this is the current program, then ValidateProgram will fail, and
2888 // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002889
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002890 const unsigned int maxCombinedTextureImageUnits = getContext()->getMaximumCombinedTextureImageUnits();
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002891 TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF];
2892
2893 for (unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; ++i)
2894 {
2895 textureUnitType[i] = TEXTURE_UNKNOWN;
2896 }
2897
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002898 for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
2899 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002900 if (mSamplersPS[i].active)
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002901 {
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002902 unsigned int unit = mSamplersPS[i].logicalTextureUnit;
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002903
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002904 if (unit >= maxCombinedTextureImageUnits)
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002905 {
2906 if (logErrors)
2907 {
2908 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
2909 }
2910
2911 return false;
2912 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002913
2914 if (textureUnitType[unit] != TEXTURE_UNKNOWN)
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002915 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002916 if (mSamplersPS[i].textureType != textureUnitType[unit])
2917 {
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002918 if (logErrors)
2919 {
2920 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
2921 }
2922
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002923 return false;
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002924 }
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002925 }
2926 else
2927 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002928 textureUnitType[unit] = mSamplersPS[i].textureType;
2929 }
2930 }
2931 }
2932
2933 for (unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; ++i)
2934 {
2935 if (mSamplersVS[i].active)
2936 {
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002937 unsigned int unit = mSamplersVS[i].logicalTextureUnit;
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002938
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002939 if (unit >= maxCombinedTextureImageUnits)
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002940 {
2941 if (logErrors)
2942 {
2943 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
2944 }
2945
2946 return false;
2947 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002948
2949 if (textureUnitType[unit] != TEXTURE_UNKNOWN)
2950 {
2951 if (mSamplersVS[i].textureType != textureUnitType[unit])
2952 {
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002953 if (logErrors)
2954 {
2955 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
2956 }
2957
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002958 return false;
2959 }
2960 }
2961 else
2962 {
2963 textureUnitType[unit] = mSamplersVS[i].textureType;
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002964 }
2965 }
2966 }
2967
2968 return true;
2969}
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002970
2971void Program::getConstantHandles(Uniform *targetUniform, D3DXHANDLE *constantPS, D3DXHANDLE *constantVS)
2972{
2973 if (!targetUniform->handlesSet)
2974 {
2975 targetUniform->psHandle = mConstantTablePS->GetConstantByName(0, targetUniform->name.c_str());
2976 targetUniform->vsHandle = mConstantTableVS->GetConstantByName(0, targetUniform->name.c_str());
2977 targetUniform->handlesSet = true;
2978 }
2979
2980 *constantPS = targetUniform->psHandle;
2981 *constantVS = targetUniform->vsHandle;
2982}
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002983
daniel@transgaming.com31754962010-11-28 02:02:52 +00002984GLint Program::getDxDepthRangeLocation() const
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002985{
daniel@transgaming.com31754962010-11-28 02:02:52 +00002986 return mDxDepthRangeLocation;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002987}
2988
2989GLint Program::getDxDepthLocation() const
2990{
2991 return mDxDepthLocation;
2992}
2993
daniel@transgaming.com4f921eb2010-07-28 19:20:44 +00002994GLint Program::getDxViewportLocation() const
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002995{
daniel@transgaming.com4f921eb2010-07-28 19:20:44 +00002996 return mDxViewportLocation;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002997}
2998
2999GLint Program::getDxHalfPixelSizeLocation() const
3000{
3001 return mDxHalfPixelSizeLocation;
3002}
3003
3004GLint Program::getDxFrontCCWLocation() const
3005{
3006 return mDxFrontCCWLocation;
3007}
3008
3009GLint Program::getDxPointsOrLinesLocation() const
3010{
3011 return mDxPointsOrLinesLocation;
3012}
3013
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003014}