blob: 983ef19f87f49aef9cd0cecf075c106a90f50d4b [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.com024f1a92011-09-20 16:06:25 +000036Uniform::Uniform(GLenum type, const std::string &_name, unsigned int arraySize)
daniel@transgaming.comc72c6412011-09-20 16:09:17 +000037 : type(type), _name(_name), name(Program::undecorateUniform(_name)), arraySize(arraySize)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038{
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +000039 int bytes = UniformTypeSize(type) * arraySize;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +000040 data = new unsigned char[bytes];
41 memset(data, 0, bytes);
42 dirty = true;
daniel@transgaming.com2d84df02010-05-14 17:31:13 +000043 handlesSet = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000044}
45
46Uniform::~Uniform()
47{
48 delete[] data;
49}
50
daniel@transgaming.com024f1a92011-09-20 16:06:25 +000051bool Uniform::isArray()
52{
daniel@transgaming.com51db7fb2011-09-20 16:11:06 +000053 return _name.compare(0, 3, "ar_") == 0;
daniel@transgaming.com024f1a92011-09-20 16:06:25 +000054}
55
56UniformLocation::UniformLocation(const std::string &_name, unsigned int element, unsigned int index)
daniel@transgaming.comc72c6412011-09-20 16:09:17 +000057 : name(Program::undecorateUniform(_name)), element(element), index(index)
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +000058{
59}
60
daniel@transgaming.com73a5db62010-10-15 17:58:13 +000061Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle), mSerial(issueSerial())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000062{
63 mFragmentShader = NULL;
64 mVertexShader = NULL;
65
66 mPixelExecutable = NULL;
67 mVertexExecutable = NULL;
68 mConstantTablePS = NULL;
69 mConstantTableVS = NULL;
70
daniel@transgaming.comcba50572010-03-28 19:36:09 +000071 mInfoLog = NULL;
daniel@transgaming.com86a7a132010-04-29 03:32:32 +000072 mValidated = false;
daniel@transgaming.comcba50572010-03-28 19:36:09 +000073
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000074 unlink();
75
76 mDeleteStatus = false;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +000077
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000078 mRefCount = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000079}
80
81Program::~Program()
82{
83 unlink(true);
daniel@transgaming.com71cd8682010-04-29 03:35:25 +000084
85 if (mVertexShader != NULL)
86 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000087 mVertexShader->release();
daniel@transgaming.com71cd8682010-04-29 03:35:25 +000088 }
89
90 if (mFragmentShader != NULL)
91 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000092 mFragmentShader->release();
daniel@transgaming.com71cd8682010-04-29 03:35:25 +000093 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000094}
95
96bool Program::attachShader(Shader *shader)
97{
98 if (shader->getType() == GL_VERTEX_SHADER)
99 {
100 if (mVertexShader)
101 {
102 return false;
103 }
104
105 mVertexShader = (VertexShader*)shader;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000106 mVertexShader->addRef();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000107 }
108 else if (shader->getType() == GL_FRAGMENT_SHADER)
109 {
110 if (mFragmentShader)
111 {
112 return false;
113 }
114
115 mFragmentShader = (FragmentShader*)shader;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000116 mFragmentShader->addRef();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000117 }
118 else UNREACHABLE();
119
120 return true;
121}
122
123bool Program::detachShader(Shader *shader)
124{
125 if (shader->getType() == GL_VERTEX_SHADER)
126 {
127 if (mVertexShader != shader)
128 {
129 return false;
130 }
131
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000132 mVertexShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133 mVertexShader = NULL;
134 }
135 else if (shader->getType() == GL_FRAGMENT_SHADER)
136 {
137 if (mFragmentShader != shader)
138 {
139 return false;
140 }
141
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000142 mFragmentShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000143 mFragmentShader = NULL;
144 }
145 else UNREACHABLE();
146
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000147 return true;
148}
149
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000150int Program::getAttachedShadersCount() const
151{
152 return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
153}
154
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000155IDirect3DPixelShader9 *Program::getPixelShader()
156{
157 return mPixelExecutable;
158}
159
160IDirect3DVertexShader9 *Program::getVertexShader()
161{
162 return mVertexExecutable;
163}
164
165void Program::bindAttributeLocation(GLuint index, const char *name)
166{
167 if (index < MAX_VERTEX_ATTRIBS)
168 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000169 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
170 {
171 mAttributeBinding[i].erase(name);
172 }
173
174 mAttributeBinding[index].insert(name);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175 }
176}
177
178GLuint Program::getAttributeLocation(const char *name)
179{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000180 if (name)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000181 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000182 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000183 {
daniel@transgaming.com85423182010-04-22 13:35:27 +0000184 if (mLinkedAttribute[index].name == std::string(name))
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000185 {
186 return index;
187 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000188 }
189 }
190
191 return -1;
192}
193
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000194int Program::getSemanticIndex(int attributeIndex)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000195{
daniel@transgaming.com733ba932011-04-14 15:03:48 +0000196 ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
197
198 return mSemanticIndex[attributeIndex];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000199}
200
jbauman@chromium.orgb6e72222011-10-18 23:01:46 +0000201// Returns one more than the highest sampler index used.
202GLint Program::getUsedSamplerRange(SamplerType type)
203{
204 switch (type)
205 {
206 case SAMPLER_PIXEL:
207 return mUsedPixelSamplerRange;
208 case SAMPLER_VERTEX:
209 return mUsedVertexSamplerRange;
210 default:
211 UNREACHABLE();
212 return 0;
213 }
214}
215
daniel@transgaming.com9ba680a2011-05-11 15:37:11 +0000216// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler
217// index (0-15 for the pixel shader and 0-3 for the vertex shader).
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000218GLint Program::getSamplerMapping(SamplerType type, unsigned int samplerIndex)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000219{
jbauman@chromium.org8b3c1af2011-10-12 01:21:41 +0000220 GLint logicalTextureUnit = -1;
daniel@transgaming.com4071e662010-05-12 16:51:16 +0000221
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000222 switch (type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000223 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000224 case SAMPLER_PIXEL:
225 ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
226
227 if (mSamplersPS[samplerIndex].active)
228 {
229 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
230 }
231 break;
232 case SAMPLER_VERTEX:
233 ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
234
235 if (mSamplersVS[samplerIndex].active)
236 {
237 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
238 }
239 break;
240 default: UNREACHABLE();
daniel@transgaming.com4071e662010-05-12 16:51:16 +0000241 }
242
jbauman@chromium.org8b3c1af2011-10-12 01:21:41 +0000243 if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)getContext()->getMaximumCombinedTextureImageUnits())
daniel@transgaming.com4071e662010-05-12 16:51:16 +0000244 {
245 return logicalTextureUnit;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000246 }
247
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000248 return -1;
249}
250
daniel@transgaming.com9ba680a2011-05-11 15:37:11 +0000251// Returns the texture type for a given Direct3D 9 sampler type and
252// index (0-15 for the pixel shader and 0-3 for the vertex shader).
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000253TextureType Program::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000254{
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000255 switch (type)
256 {
257 case SAMPLER_PIXEL:
258 ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
259 ASSERT(mSamplersPS[samplerIndex].active);
260 return mSamplersPS[samplerIndex].textureType;
261 case SAMPLER_VERTEX:
262 ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
263 ASSERT(mSamplersVS[samplerIndex].active);
264 return mSamplersVS[samplerIndex].textureType;
265 default: UNREACHABLE();
266 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000267
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000268 return TEXTURE_2D;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000269}
270
daniel@transgaming.com024f1a92011-09-20 16:06:25 +0000271GLint Program::getUniformLocation(std::string name)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000272{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000273 int subscript = 0;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000274
daniel@transgaming.comce864422010-11-18 13:16:49 +0000275 // Strip any trailing array operator and retrieve the subscript
daniel@transgaming.com024f1a92011-09-20 16:06:25 +0000276 size_t open = name.find_last_of('[');
277 size_t close = name.find_last_of(']');
278 if (open != std::string::npos && close == name.length() - 1)
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +0000279 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +0000280 subscript = atoi(name.substr(open + 1).c_str());
281 name.erase(open);
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +0000282 }
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000283
daniel@transgaming.comd08ea902010-05-14 19:41:36 +0000284 unsigned int numUniforms = mUniformIndex.size();
285 for (unsigned int location = 0; location < numUniforms; location++)
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000286 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +0000287 if (mUniformIndex[location].name == name &&
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000288 mUniformIndex[location].element == subscript)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000289 {
290 return location;
291 }
292 }
293
294 return -1;
295}
296
297bool Program::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
298{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000299 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000300 {
301 return false;
302 }
303
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000304 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000305 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000306
307 if (targetUniform->type == GL_FLOAT)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000308 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000309 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000310
311 if (arraySize == 1 && count > 1)
312 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
313
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000314 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000315
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000316 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat),
317 v, sizeof(GLfloat) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000318 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000319 else if (targetUniform->type == GL_BOOL)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000320 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000321 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000322
323 if (arraySize == 1 && count > 1)
324 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000325
326 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000327 GLboolean *boolParams = new GLboolean[count];
328
329 for (int i = 0; i < count; ++i)
330 {
331 if (v[i] == 0.0f)
332 {
333 boolParams[i] = GL_FALSE;
334 }
335 else
336 {
337 boolParams[i] = GL_TRUE;
338 }
339 }
340
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000341 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean),
342 boolParams, sizeof(GLboolean) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000343
344 delete [] boolParams;
345 }
346 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000347 {
348 return false;
349 }
350
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000351 return true;
352}
353
354bool Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
355{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000356 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000357 {
358 return false;
359 }
360
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000361 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000362 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000363
364 if (targetUniform->type == GL_FLOAT_VEC2)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000365 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000366 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000367
368 if (arraySize == 1 && count > 1)
369 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
370
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000371 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000372
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000373 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 2,
374 v, 2 * sizeof(GLfloat) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000375 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000376 else if (targetUniform->type == GL_BOOL_VEC2)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000377 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000378 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000379
380 if (arraySize == 1 && count > 1)
381 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
382
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000383 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
384
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000385 GLboolean *boolParams = new GLboolean[count * 2];
386
387 for (int i = 0; i < count * 2; ++i)
388 {
389 if (v[i] == 0.0f)
390 {
391 boolParams[i] = GL_FALSE;
392 }
393 else
394 {
395 boolParams[i] = GL_TRUE;
396 }
397 }
398
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000399 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 2,
400 boolParams, 2 * sizeof(GLboolean) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000401
402 delete [] boolParams;
403 }
404 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000405 {
406 return false;
407 }
408
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000409 return true;
410}
411
412bool Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
413{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000414 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000415 {
416 return false;
417 }
418
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000419 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000420 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000421
422 if (targetUniform->type == GL_FLOAT_VEC3)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000423 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000424 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000425
426 if (arraySize == 1 && count > 1)
427 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
428
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000429 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000430
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000431 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 3,
432 v, 3 * sizeof(GLfloat) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000433 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000434 else if (targetUniform->type == GL_BOOL_VEC3)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000435 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000436 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000437
438 if (arraySize == 1 && count > 1)
439 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
440
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000441 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000442 GLboolean *boolParams = new GLboolean[count * 3];
443
444 for (int i = 0; i < count * 3; ++i)
445 {
446 if (v[i] == 0.0f)
447 {
448 boolParams[i] = GL_FALSE;
449 }
450 else
451 {
452 boolParams[i] = GL_TRUE;
453 }
454 }
455
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000456 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 3,
457 boolParams, 3 * sizeof(GLboolean) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000458
459 delete [] boolParams;
460 }
461 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000462 {
463 return false;
464 }
465
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000466 return true;
467}
468
469bool Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
470{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000471 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000472 {
473 return false;
474 }
475
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000476 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000477 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000478
479 if (targetUniform->type == GL_FLOAT_VEC4)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000480 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000481 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000482
483 if (arraySize == 1 && count > 1)
484 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
485
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000486 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000487
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000488 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4,
489 v, 4 * sizeof(GLfloat) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000490 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000491 else if (targetUniform->type == GL_BOOL_VEC4)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000492 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000493 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000494
495 if (arraySize == 1 && count > 1)
496 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
497
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000498 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000499 GLboolean *boolParams = new GLboolean[count * 4];
500
501 for (int i = 0; i < count * 4; ++i)
502 {
503 if (v[i] == 0.0f)
504 {
505 boolParams[i] = GL_FALSE;
506 }
507 else
508 {
509 boolParams[i] = GL_TRUE;
510 }
511 }
512
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000513 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 4,
514 boolParams, 4 * sizeof(GLboolean) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000515
516 delete [] boolParams;
517 }
518 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000519 {
520 return false;
521 }
522
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000523 return true;
524}
525
526bool Program::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
527{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000528 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000529 {
530 return false;
531 }
532
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000533 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000534 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000535
536 if (targetUniform->type != GL_FLOAT_MAT2)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000537 {
538 return false;
539 }
540
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000541 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000542
543 if (arraySize == 1 && count > 1)
544 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
545
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000546 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000547
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000548 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4,
549 value, 4 * sizeof(GLfloat) * count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000550
551 return true;
552}
553
554bool Program::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
555{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000556 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000557 {
558 return false;
559 }
560
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000561 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000562 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000563
564 if (targetUniform->type != GL_FLOAT_MAT3)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000565 {
566 return false;
567 }
568
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000569 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000570
571 if (arraySize == 1 && count > 1)
572 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
573
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000574 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000575
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000576 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 9,
577 value, 9 * sizeof(GLfloat) * count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000578
579 return true;
580}
581
582bool Program::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
583{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000584 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000585 {
586 return false;
587 }
588
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000589 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000590 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000591
592 if (targetUniform->type != GL_FLOAT_MAT4)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000593 {
594 return false;
595 }
596
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000597 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000598
599 if (arraySize == 1 && count > 1)
600 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
601
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000602 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000603
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000604 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16,
605 value, 16 * sizeof(GLfloat) * count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000606
607 return true;
608}
609
610bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
611{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000612 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000613 {
614 return false;
615 }
616
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000617 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000618 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000619
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +0000620 if (targetUniform->type == GL_INT ||
621 targetUniform->type == GL_SAMPLER_2D ||
622 targetUniform->type == GL_SAMPLER_CUBE)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000623 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000624 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000625
626 if (arraySize == 1 && count > 1)
627 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
628
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000629 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000630
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000631 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint),
632 v, sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000633 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000634 else if (targetUniform->type == GL_BOOL)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000635 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000636 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000637
638 if (arraySize == 1 && count > 1)
639 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
640
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000641 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000642 GLboolean *boolParams = new GLboolean[count];
643
644 for (int i = 0; i < count; ++i)
645 {
646 if (v[i] == 0)
647 {
648 boolParams[i] = GL_FALSE;
649 }
650 else
651 {
652 boolParams[i] = GL_TRUE;
653 }
654 }
655
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000656 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean),
657 boolParams, sizeof(GLboolean) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000658
659 delete [] boolParams;
660 }
661 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000662 {
663 return false;
664 }
665
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000666 return true;
667}
668
669bool Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
670{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000671 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000672 {
673 return false;
674 }
675
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000676 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000677 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000678
679 if (targetUniform->type == GL_INT_VEC2)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000680 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000681 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000682
683 if (arraySize == 1 && count > 1)
684 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
685
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000686 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000687
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000688 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 2,
689 v, 2 * sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000690 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000691 else if (targetUniform->type == GL_BOOL_VEC2)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000692 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000693 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000694
695 if (arraySize == 1 && count > 1)
696 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
697
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000698 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000699 GLboolean *boolParams = new GLboolean[count * 2];
700
701 for (int i = 0; i < count * 2; ++i)
702 {
703 if (v[i] == 0)
704 {
705 boolParams[i] = GL_FALSE;
706 }
707 else
708 {
709 boolParams[i] = GL_TRUE;
710 }
711 }
712
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000713 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 2,
714 boolParams, 2 * sizeof(GLboolean) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000715
716 delete [] boolParams;
717 }
718 else
719 {
720 return false;
721 }
722
723 return true;
724}
725
726bool Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
727{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000728 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000729 {
730 return false;
731 }
732
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000733 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000734 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000735
736 if (targetUniform->type == GL_INT_VEC3)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000737 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000738 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000739
740 if (arraySize == 1 && count > 1)
741 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
742
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000743 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000744
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000745 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 3,
746 v, 3 * sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000747 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000748 else if (targetUniform->type == GL_BOOL_VEC3)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000749 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000750 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000751
752 if (arraySize == 1 && count > 1)
753 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
754
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000755 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000756 GLboolean *boolParams = new GLboolean[count * 3];
757
758 for (int i = 0; i < count * 3; ++i)
759 {
760 if (v[i] == 0)
761 {
762 boolParams[i] = GL_FALSE;
763 }
764 else
765 {
766 boolParams[i] = GL_TRUE;
767 }
768 }
769
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000770 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 3,
771 boolParams, 3 * sizeof(GLboolean) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000772
773 delete [] boolParams;
774 }
775 else
776 {
777 return false;
778 }
779
780 return true;
781}
782
783bool Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
784{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000785 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000786 {
787 return false;
788 }
789
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000790 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000791 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000792
793 if (targetUniform->type == GL_INT_VEC4)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000794 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000795 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000796
797 if (arraySize == 1 && count > 1)
798 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
799
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000800 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000801
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000802 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 4,
803 v, 4 * sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000804 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000805 else if (targetUniform->type == GL_BOOL_VEC4)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000806 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000807 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000808
809 if (arraySize == 1 && count > 1)
810 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
811
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000812 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000813 GLboolean *boolParams = new GLboolean[count * 4];
814
815 for (int i = 0; i < count * 4; ++i)
816 {
817 if (v[i] == 0)
818 {
819 boolParams[i] = GL_FALSE;
820 }
821 else
822 {
823 boolParams[i] = GL_TRUE;
824 }
825 }
826
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000827 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 4,
828 boolParams, 4 * sizeof(GLboolean) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000829
830 delete [] boolParams;
831 }
832 else
833 {
834 return false;
835 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000836
837 return true;
838}
839
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000840bool Program::getUniformfv(GLint location, GLfloat *params)
841{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000842 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000843 {
844 return false;
845 }
846
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000847 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000848
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000849 unsigned int count = UniformComponentCount(targetUniform->type);
850
851 switch (UniformComponentType(targetUniform->type))
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000852 {
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000853 case GL_BOOL:
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000854 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000855 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * count;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000856
857 for (unsigned int i = 0; i < count; ++i)
858 {
859 params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
860 }
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000861 }
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000862 break;
863 case GL_FLOAT:
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000864 memcpy(params, targetUniform->data + mUniformIndex[location].element * count * sizeof(GLfloat),
865 count * sizeof(GLfloat));
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000866 break;
867 case GL_INT:
868 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000869 GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * count;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000870
871 for (unsigned int i = 0; i < count; ++i)
872 {
873 params[i] = (float)intParams[i];
874 }
875 }
876 break;
877 default: UNREACHABLE();
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000878 }
879
880 return true;
881}
882
883bool Program::getUniformiv(GLint location, GLint *params)
884{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000885 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000886 {
887 return false;
888 }
889
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000890 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000891
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000892 unsigned int count = UniformComponentCount(targetUniform->type);
893
894 switch (UniformComponentType(targetUniform->type))
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000895 {
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000896 case GL_BOOL:
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000897 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000898 GLboolean *boolParams = targetUniform->data + mUniformIndex[location].element * count;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000899
900 for (unsigned int i = 0; i < count; ++i)
901 {
902 params[i] = (GLint)boolParams[i];
903 }
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000904 }
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000905 break;
906 case GL_FLOAT:
907 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000908 GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * count;
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000909
910 for (unsigned int i = 0; i < count; ++i)
911 {
912 params[i] = (GLint)floatParams[i];
913 }
914 }
915 break;
916 case GL_INT:
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000917 memcpy(params, targetUniform->data + mUniformIndex[location].element * count * sizeof(GLint),
918 count * sizeof(GLint));
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000919 break;
920 default: UNREACHABLE();
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000921 }
922
923 return true;
924}
925
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000926void Program::dirtyAllUniforms()
927{
daniel@transgaming.comd08ea902010-05-14 19:41:36 +0000928 unsigned int numUniforms = mUniforms.size();
929 for (unsigned int index = 0; index < numUniforms; index++)
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000930 {
931 mUniforms[index]->dirty = true;
932 }
933}
934
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000935// Applies all the uniforms set for this program object to the Direct3D 9 device
936void Program::applyUniforms()
937{
jbauman@chromium.orga28233e2011-10-12 16:51:33 +0000938 for (std::vector<Uniform*>::iterator ub = mUniforms.begin(), ue = mUniforms.end(); ub != ue; ++ub) {
939 Uniform *targetUniform = *ub;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000940
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000941 if (targetUniform->dirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000942 {
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000943 int arraySize = targetUniform->arraySize;
944 GLfloat *f = (GLfloat*)targetUniform->data;
945 GLint *i = (GLint*)targetUniform->data;
946 GLboolean *b = (GLboolean*)targetUniform->data;
947
948 switch (targetUniform->type)
949 {
jbauman@chromium.orga28233e2011-10-12 16:51:33 +0000950 case GL_BOOL: applyUniform1bv(targetUniform, arraySize, b); break;
951 case GL_BOOL_VEC2: applyUniform2bv(targetUniform, arraySize, b); break;
952 case GL_BOOL_VEC3: applyUniform3bv(targetUniform, arraySize, b); break;
953 case GL_BOOL_VEC4: applyUniform4bv(targetUniform, arraySize, b); break;
954 case GL_FLOAT: applyUniform1fv(targetUniform, arraySize, f); break;
955 case GL_FLOAT_VEC2: applyUniform2fv(targetUniform, arraySize, f); break;
956 case GL_FLOAT_VEC3: applyUniform3fv(targetUniform, arraySize, f); break;
957 case GL_FLOAT_VEC4: applyUniform4fv(targetUniform, arraySize, f); break;
958 case GL_FLOAT_MAT2: applyUniformMatrix2fv(targetUniform, arraySize, f); break;
959 case GL_FLOAT_MAT3: applyUniformMatrix3fv(targetUniform, arraySize, f); break;
960 case GL_FLOAT_MAT4: applyUniformMatrix4fv(targetUniform, arraySize, f); break;
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +0000961 case GL_SAMPLER_2D:
962 case GL_SAMPLER_CUBE:
jbauman@chromium.orga28233e2011-10-12 16:51:33 +0000963 case GL_INT: applyUniform1iv(targetUniform, arraySize, i); break;
964 case GL_INT_VEC2: applyUniform2iv(targetUniform, arraySize, i); break;
965 case GL_INT_VEC3: applyUniform3iv(targetUniform, arraySize, i); break;
966 case GL_INT_VEC4: applyUniform4iv(targetUniform, arraySize, i); break;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000967 default:
968 UNREACHABLE();
969 }
970
971 targetUniform->dirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000972 }
973 }
974}
975
976// Compiles the HLSL code of the attached shaders into executable binaries
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000977ID3D10Blob *Program::compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000978{
979 if (!hlsl)
980 {
981 return NULL;
982 }
983
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000984 DWORD result;
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000985 UINT flags = 0;
986 std::string sourceText;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000987 if (perfActive())
988 {
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000989 flags |= D3DCOMPILE_DEBUG;
990#ifdef NDEBUG
991 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
992#else
993 flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000994#endif
995
996 std::string sourcePath = getTempPath();
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +0000997 sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000998 writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +0000999 }
1000 else
1001 {
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001002 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
1003 sourceText = hlsl;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00001004 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001005
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001006 ID3D10Blob *binary = NULL;
1007 ID3D10Blob *errorMessage = NULL;
daniel@transgaming.com8a4dad62011-09-13 00:54:40 +00001008 result = D3DCompile(hlsl, strlen(hlsl), fakepath, NULL, NULL, "main", profile, flags, 0, &binary, &errorMessage);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001009
1010 if (errorMessage)
1011 {
1012 const char *message = (const char*)errorMessage->GetBufferPointer();
daniel@transgaming.comcba50572010-03-28 19:36:09 +00001013
daniel@transgaming.com87891f72011-06-01 15:28:35 +00001014 appendToInfoLogSanitized(message);
daniel@transgaming.com0599dc62010-03-21 04:31:36 +00001015 TRACE("\n%s", hlsl);
1016 TRACE("\n%s", message);
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001017
1018 errorMessage->Release();
1019 errorMessage = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001020 }
1021
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001022 if (FAILED(result))
1023 {
1024 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1025 {
1026 error(GL_OUT_OF_MEMORY);
1027 }
1028
1029 return NULL;
1030 }
1031
1032 result = D3DXGetShaderConstantTable(static_cast<const DWORD*>(binary->GetBufferPointer()), constantTable);
1033
1034 if (FAILED(result))
1035 {
1036 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1037 {
1038 error(GL_OUT_OF_MEMORY);
1039 }
1040
1041 binary->Release();
1042
1043 return NULL;
1044 }
1045
1046 return binary;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001047}
1048
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001049// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
1050// Returns the number of used varying registers, or -1 if unsuccesful
1051int Program::packVaryings(const Varying *packing[][4])
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001052{
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001053 Context *context = getContext();
1054 const int maxVaryingVectors = context->getMaximumVaryingVectors();
1055
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001056 for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.end(); varying++)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001057 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001058 int n = VariableRowCount(varying->type) * varying->size;
1059 int m = VariableColumnCount(varying->type);
1060 bool success = false;
daniel@transgaming.com51d0dc22010-04-29 03:39:11 +00001061
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001062 if (m == 2 || m == 3 || m == 4)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001063 {
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001064 for (int r = 0; r <= maxVaryingVectors - n && !success; r++)
daniel@transgaming.com51d0dc22010-04-29 03:39:11 +00001065 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001066 bool available = true;
1067
1068 for (int y = 0; y < n && available; y++)
1069 {
1070 for (int x = 0; x < m && available; x++)
1071 {
1072 if (packing[r + y][x])
1073 {
1074 available = false;
1075 }
1076 }
1077 }
1078
1079 if (available)
1080 {
1081 varying->reg = r;
1082 varying->col = 0;
1083
1084 for (int y = 0; y < n; y++)
1085 {
1086 for (int x = 0; x < m; x++)
1087 {
1088 packing[r + y][x] = &*varying;
1089 }
1090 }
1091
1092 success = true;
1093 }
daniel@transgaming.com51d0dc22010-04-29 03:39:11 +00001094 }
1095
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001096 if (!success && m == 2)
1097 {
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001098 for (int r = maxVaryingVectors - n; r >= 0 && !success; r--)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001099 {
1100 bool available = true;
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001101
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001102 for (int y = 0; y < n && available; y++)
1103 {
1104 for (int x = 2; x < 4 && available; x++)
1105 {
1106 if (packing[r + y][x])
1107 {
1108 available = false;
1109 }
1110 }
1111 }
1112
1113 if (available)
1114 {
1115 varying->reg = r;
1116 varying->col = 2;
1117
1118 for (int y = 0; y < n; y++)
1119 {
1120 for (int x = 2; x < 4; x++)
1121 {
1122 packing[r + y][x] = &*varying;
1123 }
1124 }
1125
1126 success = true;
1127 }
1128 }
1129 }
1130 }
1131 else if (m == 1)
1132 {
1133 int space[4] = {0};
1134
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001135 for (int y = 0; y < maxVaryingVectors; y++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001136 {
1137 for (int x = 0; x < 4; x++)
1138 {
1139 space[x] += packing[y][x] ? 0 : 1;
1140 }
1141 }
1142
1143 int column = 0;
1144
1145 for (int x = 0; x < 4; x++)
1146 {
daniel@transgaming.com11dd5dd2011-02-11 13:28:14 +00001147 if (space[x] >= n && space[x] < space[column])
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001148 {
1149 column = x;
1150 }
1151 }
1152
daniel@transgaming.com11dd5dd2011-02-11 13:28:14 +00001153 if (space[column] >= n)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001154 {
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001155 for (int r = 0; r < maxVaryingVectors; r++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001156 {
1157 if (!packing[r][column])
1158 {
1159 varying->reg = r;
1160
1161 for (int y = r; y < r + n; y++)
1162 {
1163 packing[y][column] = &*varying;
1164 }
1165
1166 break;
1167 }
1168 }
1169
1170 varying->col = column;
1171
1172 success = true;
1173 }
1174 }
1175 else UNREACHABLE();
1176
1177 if (!success)
1178 {
1179 appendToInfoLog("Could not pack varying %s", varying->name.c_str());
1180
1181 return -1;
1182 }
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001183 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001184
1185 // Return the number of used registers
1186 int registers = 0;
1187
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001188 for (int r = 0; r < maxVaryingVectors; r++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001189 {
1190 if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
1191 {
1192 registers++;
1193 }
1194 }
1195
1196 return registers;
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001197}
1198
1199bool Program::linkVaryings()
1200{
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001201 if (mPixelHLSL.empty() || mVertexHLSL.empty())
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001202 {
1203 return false;
1204 }
1205
daniel@transgaming.com97750022011-02-11 13:23:13 +00001206 // Reset the varying register assignments
1207 for (VaryingList::iterator fragVar = mFragmentShader->varyings.begin(); fragVar != mFragmentShader->varyings.end(); fragVar++)
1208 {
1209 fragVar->reg = -1;
1210 fragVar->col = -1;
1211 }
1212
1213 for (VaryingList::iterator vtxVar = mVertexShader->varyings.begin(); vtxVar != mVertexShader->varyings.end(); vtxVar++)
1214 {
1215 vtxVar->reg = -1;
1216 vtxVar->col = -1;
1217 }
1218
1219 // Map the varyings to the register file
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001220 const Varying *packing[MAX_VARYING_VECTORS_SM3][4] = {NULL};
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001221 int registers = packVaryings(packing);
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001222
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001223 if (registers < 0)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001224 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001225 return false;
1226 }
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001227
daniel@transgaming.com97750022011-02-11 13:23:13 +00001228 // Write the HLSL input/output declarations
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001229 Context *context = getContext();
1230 const bool sm3 = context->supportsShaderModel3();
1231 const int maxVaryingVectors = context->getMaximumVaryingVectors();
1232
1233 if (registers == maxVaryingVectors && mFragmentShader->mUsesFragCoord)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001234 {
1235 appendToInfoLog("No varying registers left to support gl_FragCoord");
1236
1237 return false;
1238 }
1239
1240 for (VaryingList::iterator input = mFragmentShader->varyings.begin(); input != mFragmentShader->varyings.end(); input++)
1241 {
1242 bool matched = false;
1243
1244 for (VaryingList::iterator output = mVertexShader->varyings.begin(); output != mVertexShader->varyings.end(); output++)
1245 {
1246 if (output->name == input->name)
1247 {
1248 if (output->type != input->type || output->size != input->size)
1249 {
1250 appendToInfoLog("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str());
1251
1252 return false;
1253 }
1254
1255 output->reg = input->reg;
1256 output->col = input->col;
1257
1258 matched = true;
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001259 break;
1260 }
1261 }
1262
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001263 if (!matched)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001264 {
daniel@transgaming.com97750022011-02-11 13:23:13 +00001265 appendToInfoLog("Fragment varying %s does not match any vertex varying", input->name.c_str());
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001266
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001267 return false;
1268 }
1269 }
1270
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001271 std::string varyingSemantic = (sm3 ? "COLOR" : "TEXCOORD");
1272
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001273 mVertexHLSL += "struct VS_INPUT\n"
1274 "{\n";
1275
1276 int semanticIndex = 0;
1277 for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
1278 {
1279 switch (attribute->type)
1280 {
1281 case GL_FLOAT: mVertexHLSL += " float "; break;
1282 case GL_FLOAT_VEC2: mVertexHLSL += " float2 "; break;
1283 case GL_FLOAT_VEC3: mVertexHLSL += " float3 "; break;
1284 case GL_FLOAT_VEC4: mVertexHLSL += " float4 "; break;
1285 case GL_FLOAT_MAT2: mVertexHLSL += " float2x2 "; break;
1286 case GL_FLOAT_MAT3: mVertexHLSL += " float3x3 "; break;
1287 case GL_FLOAT_MAT4: mVertexHLSL += " float4x4 "; break;
1288 default: UNREACHABLE();
1289 }
1290
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00001291 mVertexHLSL += decorateAttribute(attribute->name) + " : TEXCOORD" + str(semanticIndex) + ";\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001292
1293 semanticIndex += VariableRowCount(attribute->type);
1294 }
1295
1296 mVertexHLSL += "};\n"
1297 "\n"
1298 "struct VS_OUTPUT\n"
1299 "{\n"
1300 " float4 gl_Position : POSITION;\n";
1301
1302 for (int r = 0; r < registers; r++)
1303 {
1304 int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1));
1305
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001306 mVertexHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001307 }
1308
1309 if (mFragmentShader->mUsesFragCoord)
1310 {
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001311 mVertexHLSL += " float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
1312 }
1313
1314 if (mVertexShader->mUsesPointSize && sm3)
1315 {
1316 mVertexHLSL += " float gl_PointSize : PSIZE;\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001317 }
1318
1319 mVertexHLSL += "};\n"
1320 "\n"
1321 "VS_OUTPUT main(VS_INPUT input)\n"
1322 "{\n";
1323
1324 for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
1325 {
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00001326 mVertexHLSL += " " + decorateAttribute(attribute->name) + " = ";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001327
1328 if (VariableRowCount(attribute->type) > 1) // Matrix
1329 {
1330 mVertexHLSL += "transpose";
1331 }
1332
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00001333 mVertexHLSL += "(input." + decorateAttribute(attribute->name) + ");\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001334 }
1335
1336 mVertexHLSL += "\n"
1337 " gl_main();\n"
1338 "\n"
1339 " VS_OUTPUT output;\n"
1340 " output.gl_Position.x = gl_Position.x - dx_HalfPixelSize.x * gl_Position.w;\n"
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001341 " output.gl_Position.y = gl_Position.y - dx_HalfPixelSize.y * gl_Position.w;\n"
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001342 " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
1343 " output.gl_Position.w = gl_Position.w;\n";
1344
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001345 if (mVertexShader->mUsesPointSize && sm3)
1346 {
1347 mVertexHLSL += " output.gl_PointSize = clamp(gl_PointSize, 1.0, " + str((int)ALIASED_POINT_SIZE_RANGE_MAX_SM3) + ");\n";
1348 }
1349
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001350 if (mFragmentShader->mUsesFragCoord)
1351 {
1352 mVertexHLSL += " output.gl_FragCoord = gl_Position;\n";
1353 }
1354
1355 for (VaryingList::iterator varying = mVertexShader->varyings.begin(); varying != mVertexShader->varyings.end(); varying++)
1356 {
1357 if (varying->reg >= 0)
1358 {
1359 for (int i = 0; i < varying->size; i++)
1360 {
1361 int rows = VariableRowCount(varying->type);
1362
1363 for (int j = 0; j < rows; j++)
1364 {
1365 int r = varying->reg + i * rows + j;
1366 mVertexHLSL += " output.v" + str(r);
1367
1368 bool sharedRegister = false; // Register used by multiple varyings
1369
1370 for (int x = 0; x < 4; x++)
1371 {
1372 if (packing[r][x] && packing[r][x] != packing[r][0])
1373 {
1374 sharedRegister = true;
1375 break;
1376 }
1377 }
1378
1379 if(sharedRegister)
1380 {
1381 mVertexHLSL += ".";
1382
1383 for (int x = 0; x < 4; x++)
1384 {
1385 if (packing[r][x] == &*varying)
1386 {
1387 switch(x)
1388 {
1389 case 0: mVertexHLSL += "x"; break;
1390 case 1: mVertexHLSL += "y"; break;
1391 case 2: mVertexHLSL += "z"; break;
1392 case 3: mVertexHLSL += "w"; break;
1393 }
1394 }
1395 }
1396 }
1397
1398 mVertexHLSL += " = " + varying->name;
1399
1400 if (varying->array)
1401 {
1402 mVertexHLSL += "[" + str(i) + "]";
1403 }
1404
1405 if (rows > 1)
1406 {
1407 mVertexHLSL += "[" + str(j) + "]";
1408 }
1409
1410 mVertexHLSL += ";\n";
1411 }
1412 }
1413 }
1414 }
1415
1416 mVertexHLSL += "\n"
1417 " return output;\n"
1418 "}\n";
1419
1420 mPixelHLSL += "struct PS_INPUT\n"
1421 "{\n";
1422
1423 for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.end(); varying++)
1424 {
1425 if (varying->reg >= 0)
1426 {
1427 for (int i = 0; i < varying->size; i++)
1428 {
1429 int rows = VariableRowCount(varying->type);
1430 for (int j = 0; j < rows; j++)
1431 {
1432 std::string n = str(varying->reg + i * rows + j);
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001433 mPixelHLSL += " float4 v" + n + " : " + varyingSemantic + n + ";\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001434 }
1435 }
1436 }
1437 else UNREACHABLE();
1438 }
1439
1440 if (mFragmentShader->mUsesFragCoord)
1441 {
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001442 mPixelHLSL += " float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001443 if (sm3) {
daniel@transgaming.com996675c2010-11-17 13:06:29 +00001444 mPixelHLSL += " float2 dx_VPos : VPOS;\n";
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001445 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001446 }
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001447
1448 if (mFragmentShader->mUsesPointCoord && sm3)
1449 {
1450 mPixelHLSL += " float2 gl_PointCoord : TEXCOORD0;\n";
1451 }
1452
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001453 if (mFragmentShader->mUsesFrontFacing)
1454 {
1455 mPixelHLSL += " float vFace : VFACE;\n";
1456 }
1457
1458 mPixelHLSL += "};\n"
1459 "\n"
1460 "struct PS_OUTPUT\n"
1461 "{\n"
1462 " float4 gl_Color[1] : COLOR;\n"
1463 "};\n"
1464 "\n"
1465 "PS_OUTPUT main(PS_INPUT input)\n"
1466 "{\n";
1467
1468 if (mFragmentShader->mUsesFragCoord)
1469 {
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001470 mPixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n";
1471 if (sm3) {
apatrick@chromium.orgb1092bf2011-05-11 19:52:39 +00001472 mPixelHLSL += " gl_FragCoord.x = input.dx_VPos.x + 0.5;\n"
1473 " gl_FragCoord.y = 2.0 * dx_Viewport.y - input.dx_VPos.y - 0.5;\n";
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001474 } else {
1475 mPixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_Viewport.x + dx_Viewport.z;\n"
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001476 " gl_FragCoord.y = -(input.gl_FragCoord.y * rhw) * dx_Viewport.y + dx_Viewport.w;\n";
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001477 }
1478 mPixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_Depth.x + dx_Depth.y;\n"
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001479 " gl_FragCoord.w = rhw;\n";
1480 }
1481
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001482 if (mFragmentShader->mUsesPointCoord && sm3)
1483 {
apatrick@chromium.orgda4d0492011-01-22 00:16:10 +00001484 mPixelHLSL += " gl_PointCoord = input.gl_PointCoord;\n";
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001485 }
1486
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001487 if (mFragmentShader->mUsesFrontFacing)
1488 {
1489 mPixelHLSL += " gl_FrontFacing = dx_PointsOrLines || (dx_FrontCCW ? (input.vFace >= 0.0) : (input.vFace <= 0.0));\n";
1490 }
1491
1492 for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.end(); varying++)
1493 {
1494 if (varying->reg >= 0)
1495 {
1496 for (int i = 0; i < varying->size; i++)
1497 {
1498 int rows = VariableRowCount(varying->type);
1499 for (int j = 0; j < rows; j++)
1500 {
1501 std::string n = str(varying->reg + i * rows + j);
1502 mPixelHLSL += " " + varying->name;
1503
1504 if (varying->array)
1505 {
1506 mPixelHLSL += "[" + str(i) + "]";
1507 }
1508
1509 if (rows > 1)
1510 {
1511 mPixelHLSL += "[" + str(j) + "]";
1512 }
1513
1514 mPixelHLSL += " = input.v" + n + ";\n";
1515 }
1516 }
1517 }
1518 else UNREACHABLE();
1519 }
1520
1521 mPixelHLSL += "\n"
1522 " gl_main();\n"
1523 "\n"
1524 " PS_OUTPUT output;\n"
1525 " output.gl_Color[0] = gl_Color[0];\n"
1526 "\n"
1527 " return output;\n"
1528 "}\n";
1529
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001530 return true;
1531}
1532
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001533// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
1534// compiling them into binaries, determining the attribute mappings, and collecting
1535// a list of uniforms
1536void Program::link()
1537{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001538 unlink();
1539
1540 if (!mFragmentShader || !mFragmentShader->isCompiled())
1541 {
1542 return;
1543 }
1544
1545 if (!mVertexShader || !mVertexShader->isCompiled())
1546 {
1547 return;
1548 }
1549
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001550 mPixelHLSL = mFragmentShader->getHLSL();
1551 mVertexHLSL = mVertexShader->getHLSL();
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001552
1553 if (!linkVaryings())
1554 {
1555 return;
1556 }
1557
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001558 Context *context = getContext();
1559 const char *vertexProfile = context->supportsShaderModel3() ? "vs_3_0" : "vs_2_0";
1560 const char *pixelProfile = context->supportsShaderModel3() ? "ps_3_0" : "ps_2_0";
1561
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001562 ID3D10Blob *vertexBinary = compileToBinary(mVertexHLSL.c_str(), vertexProfile, &mConstantTableVS);
1563 ID3D10Blob *pixelBinary = compileToBinary(mPixelHLSL.c_str(), pixelProfile, &mConstantTablePS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001564
1565 if (vertexBinary && pixelBinary)
1566 {
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00001567 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001568 HRESULT vertexResult = device->CreateVertexShader((DWORD*)vertexBinary->GetBufferPointer(), &mVertexExecutable);
1569 HRESULT pixelResult = device->CreatePixelShader((DWORD*)pixelBinary->GetBufferPointer(), &mPixelExecutable);
1570
1571 if (vertexResult == D3DERR_OUTOFVIDEOMEMORY || vertexResult == E_OUTOFMEMORY || pixelResult == D3DERR_OUTOFVIDEOMEMORY || pixelResult == E_OUTOFMEMORY)
1572 {
1573 return error(GL_OUT_OF_MEMORY);
1574 }
1575
1576 ASSERT(SUCCEEDED(vertexResult) && SUCCEEDED(pixelResult));
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001577
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001578 vertexBinary->Release();
1579 pixelBinary->Release();
1580 vertexBinary = NULL;
1581 pixelBinary = NULL;
1582
1583 if (mVertexExecutable && mPixelExecutable)
1584 {
1585 if (!linkAttributes())
1586 {
1587 return;
1588 }
1589
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001590 if (!linkUniforms(mConstantTablePS))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001591 {
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001592 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001593 }
1594
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001595 if (!linkUniforms(mConstantTableVS))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001596 {
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001597 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001598 }
1599
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +00001600 // these uniforms are searched as already-decorated because gl_ and dx_
1601 // are reserved prefixes, and do not receive additional decoration
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001602 mDxDepthRangeLocation = getUniformLocation("dx_DepthRange");
1603 mDxDepthLocation = getUniformLocation("dx_Depth");
1604 mDxViewportLocation = getUniformLocation("dx_Viewport");
1605 mDxHalfPixelSizeLocation = getUniformLocation("dx_HalfPixelSize");
1606 mDxFrontCCWLocation = getUniformLocation("dx_FrontCCW");
1607 mDxPointsOrLinesLocation = getUniformLocation("dx_PointsOrLines");
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001608
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001609 mLinked = true; // Success
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001610 }
1611 }
1612}
1613
1614// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
1615bool Program::linkAttributes()
1616{
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001617 unsigned int usedLocations = 0;
1618
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001619 // Link attributes that have a binding location
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001620 for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001621 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001622 int location = getAttributeBinding(attribute->name);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001623
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001624 if (location != -1) // Set by glBindAttribLocation
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001625 {
daniel@transgaming.com85423182010-04-22 13:35:27 +00001626 if (!mLinkedAttribute[location].name.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001627 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001628 // Multiple active attributes bound to the same location; not an error
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001629 }
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001630
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001631 mLinkedAttribute[location] = *attribute;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001632
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001633 int rows = VariableRowCount(attribute->type);
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001634
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001635 if (rows + location > MAX_VERTEX_ATTRIBS)
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001636 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001637 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 +00001638
1639 return false;
1640 }
1641
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001642 for (int i = 0; i < rows; i++)
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001643 {
1644 usedLocations |= 1 << (location + i);
1645 }
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001646 }
1647 }
1648
1649 // Link attributes that don't have a binding location
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001650 for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001651 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001652 int location = getAttributeBinding(attribute->name);
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001653
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001654 if (location == -1) // Not set by glBindAttribLocation
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001655 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001656 int rows = VariableRowCount(attribute->type);
1657 int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001658
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001659 if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001660 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001661 appendToInfoLog("Too many active attributes (%s)", attribute->name.c_str());
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001662
1663 return false; // Fail to link
1664 }
1665
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001666 mLinkedAttribute[availableIndex] = *attribute;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001667 }
1668 }
1669
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001670 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001671 {
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001672 int index = mVertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001673 int rows = std::max(VariableRowCount(mLinkedAttribute[attributeIndex].type), 1);
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001674
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001675 for (int r = 0; r < rows; r++)
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001676 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001677 mSemanticIndex[attributeIndex++] = index++;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001678 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001679 }
1680
1681 return true;
1682}
1683
daniel@transgaming.com85423182010-04-22 13:35:27 +00001684int Program::getAttributeBinding(const std::string &name)
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001685{
1686 for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
1687 {
1688 if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
1689 {
1690 return location;
1691 }
1692 }
1693
1694 return -1;
1695}
1696
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001697bool Program::linkUniforms(ID3DXConstantTable *constantTable)
1698{
1699 D3DXCONSTANTTABLE_DESC constantTableDescription;
1700 D3DXCONSTANT_DESC constantDescription;
1701 UINT descriptionCount = 1;
1702
1703 constantTable->GetDesc(&constantTableDescription);
1704
1705 for (unsigned int constantIndex = 0; constantIndex < constantTableDescription.Constants; constantIndex++)
1706 {
1707 D3DXHANDLE constantHandle = constantTable->GetConstant(0, constantIndex);
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001708 HRESULT result = constantTable->GetConstantDesc(constantHandle, &constantDescription, &descriptionCount);
1709 ASSERT(SUCCEEDED(result));
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001710
1711 if (!defineUniform(constantHandle, constantDescription))
1712 {
1713 return false;
1714 }
1715 }
1716
1717 return true;
1718}
1719
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001720// Adds the description of a constant found in the binary shader to the list of uniforms
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001721// Returns true if succesful (uniform not already defined)
1722bool Program::defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT_DESC &constantDescription, std::string name)
1723{
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001724 if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
1725 {
daniel@transgaming.com41b2fbd2010-12-13 18:27:12 +00001726 for (unsigned int samplerIndex = constantDescription.RegisterIndex; samplerIndex < constantDescription.RegisterIndex + constantDescription.RegisterCount; samplerIndex++)
1727 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001728 if (mConstantTablePS->GetConstantByName(NULL, constantDescription.Name) != NULL)
1729 {
daniel@transgaming.com424bb492011-05-11 15:36:59 +00001730 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
1731 {
1732 mSamplersPS[samplerIndex].active = true;
1733 mSamplersPS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
1734 mSamplersPS[samplerIndex].logicalTextureUnit = 0;
jbauman@chromium.orgb6e72222011-10-18 23:01:46 +00001735 mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange);
daniel@transgaming.com424bb492011-05-11 15:36:59 +00001736 }
1737 else
1738 {
1739 appendToInfoLog("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
1740 return false;
1741 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001742 }
1743
1744 if (mConstantTableVS->GetConstantByName(NULL, constantDescription.Name) != NULL)
1745 {
daniel@transgaming.com424bb492011-05-11 15:36:59 +00001746 if (samplerIndex < getContext()->getMaximumVertexTextureImageUnits())
1747 {
1748 mSamplersVS[samplerIndex].active = true;
1749 mSamplersVS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
1750 mSamplersVS[samplerIndex].logicalTextureUnit = 0;
jbauman@chromium.orgb6e72222011-10-18 23:01:46 +00001751 mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange);
daniel@transgaming.com424bb492011-05-11 15:36:59 +00001752 }
1753 else
1754 {
1755 appendToInfoLog("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", getContext()->getMaximumVertexTextureImageUnits());
1756 return false;
1757 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001758 }
daniel@transgaming.com41b2fbd2010-12-13 18:27:12 +00001759 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001760 }
1761
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001762 switch(constantDescription.Class)
1763 {
1764 case D3DXPC_STRUCT:
1765 {
daniel@transgaming.comce864422010-11-18 13:16:49 +00001766 for (unsigned int arrayIndex = 0; arrayIndex < constantDescription.Elements; arrayIndex++)
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001767 {
daniel@transgaming.comce864422010-11-18 13:16:49 +00001768 for (unsigned int field = 0; field < constantDescription.StructMembers; field++)
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001769 {
daniel@transgaming.comce864422010-11-18 13:16:49 +00001770 D3DXHANDLE fieldHandle = mConstantTablePS->GetConstant(constantHandle, field);
1771
1772 D3DXCONSTANT_DESC fieldDescription;
1773 UINT descriptionCount = 1;
1774
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001775 HRESULT result = mConstantTablePS->GetConstantDesc(fieldHandle, &fieldDescription, &descriptionCount);
1776 ASSERT(SUCCEEDED(result));
daniel@transgaming.comce864422010-11-18 13:16:49 +00001777
1778 std::string structIndex = (constantDescription.Elements > 1) ? ("[" + str(arrayIndex) + "]") : "";
1779
1780 if (!defineUniform(fieldHandle, fieldDescription, name + constantDescription.Name + structIndex + "."))
1781 {
1782 return false;
1783 }
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001784 }
1785 }
1786
1787 return true;
1788 }
1789 case D3DXPC_SCALAR:
1790 case D3DXPC_VECTOR:
1791 case D3DXPC_MATRIX_COLUMNS:
1792 case D3DXPC_OBJECT:
1793 return defineUniform(constantDescription, name + constantDescription.Name);
1794 default:
1795 UNREACHABLE();
1796 return false;
1797 }
1798}
1799
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001800bool Program::defineUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &_name)
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001801{
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001802 Uniform *uniform = createUniform(constantDescription, _name);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001803
1804 if(!uniform)
1805 {
1806 return false;
1807 }
1808
1809 // Check if already defined
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001810 GLint location = getUniformLocation(uniform->name);
daniel@transgaming.com0361b922010-03-28 19:36:15 +00001811 GLenum type = uniform->type;
daniel@transgaming.comc7d8a932010-03-16 06:16:45 +00001812
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001813 if (location >= 0)
1814 {
1815 delete uniform;
1816
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00001817 if (mUniforms[mUniformIndex[location].index]->type != type)
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001818 {
1819 return false;
1820 }
1821 else
1822 {
1823 return true;
1824 }
1825 }
1826
1827 mUniforms.push_back(uniform);
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00001828 unsigned int uniformIndex = mUniforms.size() - 1;
1829
1830 for (unsigned int i = 0; i < uniform->arraySize; ++i)
1831 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001832 mUniformIndex.push_back(UniformLocation(_name, i, uniformIndex));
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00001833 }
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001834
1835 return true;
1836}
1837
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001838Uniform *Program::createUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &_name)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001839{
1840 if (constantDescription.Rows == 1) // Vectors and scalars
1841 {
1842 switch (constantDescription.Type)
1843 {
1844 case D3DXPT_SAMPLER2D:
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +00001845 switch (constantDescription.Columns)
1846 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001847 case 1: return new Uniform(GL_SAMPLER_2D, _name, constantDescription.Elements);
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +00001848 default: UNREACHABLE();
1849 }
1850 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001851 case D3DXPT_SAMPLERCUBE:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001852 switch (constantDescription.Columns)
1853 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001854 case 1: return new Uniform(GL_SAMPLER_CUBE, _name, constantDescription.Elements);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00001855 default: UNREACHABLE();
1856 }
1857 break;
1858 case D3DXPT_BOOL:
1859 switch (constantDescription.Columns)
1860 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001861 case 1: return new Uniform(GL_BOOL, _name, constantDescription.Elements);
1862 case 2: return new Uniform(GL_BOOL_VEC2, _name, constantDescription.Elements);
1863 case 3: return new Uniform(GL_BOOL_VEC3, _name, constantDescription.Elements);
1864 case 4: return new Uniform(GL_BOOL_VEC4, _name, constantDescription.Elements);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00001865 default: UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001866 }
1867 break;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00001868 case D3DXPT_INT:
1869 switch (constantDescription.Columns)
1870 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001871 case 1: return new Uniform(GL_INT, _name, constantDescription.Elements);
1872 case 2: return new Uniform(GL_INT_VEC2, _name, constantDescription.Elements);
1873 case 3: return new Uniform(GL_INT_VEC3, _name, constantDescription.Elements);
1874 case 4: return new Uniform(GL_INT_VEC4, _name, constantDescription.Elements);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00001875 default: UNREACHABLE();
1876 }
1877 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001878 case D3DXPT_FLOAT:
1879 switch (constantDescription.Columns)
1880 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001881 case 1: return new Uniform(GL_FLOAT, _name, constantDescription.Elements);
1882 case 2: return new Uniform(GL_FLOAT_VEC2, _name, constantDescription.Elements);
1883 case 3: return new Uniform(GL_FLOAT_VEC3, _name, constantDescription.Elements);
1884 case 4: return new Uniform(GL_FLOAT_VEC4, _name, constantDescription.Elements);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001885 default: UNREACHABLE();
1886 }
1887 break;
1888 default:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001889 UNREACHABLE();
1890 }
1891 }
1892 else if (constantDescription.Rows == constantDescription.Columns) // Square matrices
1893 {
1894 switch (constantDescription.Type)
1895 {
1896 case D3DXPT_FLOAT:
1897 switch (constantDescription.Rows)
1898 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001899 case 2: return new Uniform(GL_FLOAT_MAT2, _name, constantDescription.Elements);
1900 case 3: return new Uniform(GL_FLOAT_MAT3, _name, constantDescription.Elements);
1901 case 4: return new Uniform(GL_FLOAT_MAT4, _name, constantDescription.Elements);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001902 default: UNREACHABLE();
1903 }
1904 break;
1905 default: UNREACHABLE();
1906 }
1907 }
1908 else UNREACHABLE();
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001909
1910 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001911}
1912
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00001913// This method needs to match OutputHLSL::decorate
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00001914std::string Program::decorateAttribute(const std::string &name)
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001915{
daniel@transgaming.com51db7fb2011-09-20 16:11:06 +00001916 if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0)
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001917 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001918 return "_" + name;
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001919 }
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001920
1921 return name;
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00001922}
1923
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00001924std::string Program::undecorateUniform(const std::string &_name)
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00001925{
daniel@transgaming.com51db7fb2011-09-20 16:11:06 +00001926 if (_name[0] == '_')
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00001927 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001928 return _name.substr(1);
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00001929 }
daniel@transgaming.com51db7fb2011-09-20 16:11:06 +00001930 else if (_name.compare(0, 3, "ar_") == 0)
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00001931 {
1932 return _name.substr(3);
1933 }
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001934
1935 return _name;
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00001936}
1937
jbauman@chromium.orga28233e2011-10-12 16:51:33 +00001938bool Program::applyUniform1bv(Uniform *targetUniform, GLsizei count, const GLboolean *v)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00001939{
1940 BOOL *vector = new BOOL[count];
1941 for (int i = 0; i < count; i++)
1942 {
1943 if (v[i] == GL_FALSE)
1944 vector[i] = 0;
1945 else
1946 vector[i] = 1;
1947 }
1948
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00001949 D3DXHANDLE constantPS;
1950 D3DXHANDLE constantVS;
1951 getConstantHandles(targetUniform, &constantPS, &constantVS);
1952
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00001953 IDirect3DDevice9 *device = getDevice();
1954
1955 if (constantPS)
1956 {
1957 mConstantTablePS->SetBoolArray(device, constantPS, vector, count);
1958 }
1959
1960 if (constantVS)
1961 {
1962 mConstantTableVS->SetBoolArray(device, constantVS, vector, count);
1963 }
1964
1965 delete [] vector;
1966
1967 return true;
1968}
1969
jbauman@chromium.orga28233e2011-10-12 16:51:33 +00001970bool Program::applyUniform2bv(Uniform *targetUniform, GLsizei count, const GLboolean *v)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00001971{
1972 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
1973
1974 for (int i = 0; i < count; i++)
1975 {
1976 vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
1977 (v[1] == GL_FALSE ? 0.0f : 1.0f), 0, 0);
1978
1979 v += 2;
1980 }
1981
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00001982 D3DXHANDLE constantPS;
1983 D3DXHANDLE constantVS;
1984 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00001985 IDirect3DDevice9 *device = getDevice();
1986
1987 if (constantPS)
1988 {
1989 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
1990 }
1991
1992 if (constantVS)
1993 {
1994 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
1995 }
1996
1997 delete[] vector;
1998
1999 return true;
2000}
2001
jbauman@chromium.orga28233e2011-10-12 16:51:33 +00002002bool Program::applyUniform3bv(Uniform *targetUniform, GLsizei count, const GLboolean *v)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002003{
2004 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2005
2006 for (int i = 0; i < count; i++)
2007 {
2008 vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
2009 (v[1] == GL_FALSE ? 0.0f : 1.0f),
2010 (v[2] == GL_FALSE ? 0.0f : 1.0f), 0);
2011
2012 v += 3;
2013 }
2014
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002015 D3DXHANDLE constantPS;
2016 D3DXHANDLE constantVS;
2017 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002018 IDirect3DDevice9 *device = getDevice();
2019
2020 if (constantPS)
2021 {
2022 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2023 }
2024
2025 if (constantVS)
2026 {
2027 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2028 }
2029
2030 delete[] vector;
2031
2032 return true;
2033}
2034
jbauman@chromium.orga28233e2011-10-12 16:51:33 +00002035bool Program::applyUniform4bv(Uniform *targetUniform, GLsizei count, const GLboolean *v)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002036{
2037 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2038
2039 for (int i = 0; i < count; i++)
2040 {
2041 vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
2042 (v[1] == GL_FALSE ? 0.0f : 1.0f),
2043 (v[2] == GL_FALSE ? 0.0f : 1.0f),
2044 (v[3] == GL_FALSE ? 0.0f : 1.0f));
2045
2046 v += 3;
2047 }
2048
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002049 D3DXHANDLE constantPS;
2050 D3DXHANDLE constantVS;
2051 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002052 IDirect3DDevice9 *device = getDevice();
2053
2054 if (constantPS)
2055 {
2056 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2057 }
2058
2059 if (constantVS)
2060 {
2061 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2062 }
2063
2064 delete [] vector;
2065
2066 return true;
2067}
2068
jbauman@chromium.orga28233e2011-10-12 16:51:33 +00002069bool Program::applyUniform1fv(Uniform *targetUniform, GLsizei count, const GLfloat *v)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002070{
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002071 D3DXHANDLE constantPS;
2072 D3DXHANDLE constantVS;
2073 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002074 IDirect3DDevice9 *device = getDevice();
2075
2076 if (constantPS)
2077 {
2078 mConstantTablePS->SetFloatArray(device, constantPS, v, count);
2079 }
2080
2081 if (constantVS)
2082 {
2083 mConstantTableVS->SetFloatArray(device, constantVS, v, count);
2084 }
2085
2086 return true;
2087}
2088
jbauman@chromium.orga28233e2011-10-12 16:51:33 +00002089bool Program::applyUniform2fv(Uniform *targetUniform, GLsizei count, const GLfloat *v)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002090{
2091 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2092
2093 for (int i = 0; i < count; i++)
2094 {
2095 vector[i] = D3DXVECTOR4(v[0], v[1], 0, 0);
2096
2097 v += 2;
2098 }
2099
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002100 D3DXHANDLE constantPS;
2101 D3DXHANDLE constantVS;
2102 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002103 IDirect3DDevice9 *device = getDevice();
2104
2105 if (constantPS)
2106 {
2107 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2108 }
2109
2110 if (constantVS)
2111 {
2112 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2113 }
2114
2115 delete[] vector;
2116
2117 return true;
2118}
2119
jbauman@chromium.orga28233e2011-10-12 16:51:33 +00002120bool Program::applyUniform3fv(Uniform *targetUniform, GLsizei count, const GLfloat *v)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002121{
2122 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2123
2124 for (int i = 0; i < count; i++)
2125 {
2126 vector[i] = D3DXVECTOR4(v[0], v[1], v[2], 0);
2127
2128 v += 3;
2129 }
2130
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002131 D3DXHANDLE constantPS;
2132 D3DXHANDLE constantVS;
2133 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002134 IDirect3DDevice9 *device = getDevice();
2135
2136 if (constantPS)
2137 {
2138 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2139 }
2140
2141 if (constantVS)
2142 {
2143 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2144 }
2145
2146 delete[] vector;
2147
2148 return true;
2149}
2150
jbauman@chromium.orga28233e2011-10-12 16:51:33 +00002151bool Program::applyUniform4fv(Uniform *targetUniform, GLsizei count, const GLfloat *v)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002152{
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002153 D3DXHANDLE constantPS;
2154 D3DXHANDLE constantVS;
2155 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002156 IDirect3DDevice9 *device = getDevice();
2157
2158 if (constantPS)
2159 {
2160 mConstantTablePS->SetVectorArray(device, constantPS, (D3DXVECTOR4*)v, count);
2161 }
2162
2163 if (constantVS)
2164 {
2165 mConstantTableVS->SetVectorArray(device, constantVS, (D3DXVECTOR4*)v, count);
2166 }
2167
2168 return true;
2169}
2170
jbauman@chromium.orga28233e2011-10-12 16:51:33 +00002171bool Program::applyUniformMatrix2fv(Uniform *targetUniform, GLsizei count, const GLfloat *value)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002172{
2173 D3DXMATRIX *matrix = new D3DXMATRIX[count];
2174
2175 for (int i = 0; i < count; i++)
2176 {
2177 matrix[i] = D3DXMATRIX(value[0], value[2], 0, 0,
2178 value[1], value[3], 0, 0,
2179 0, 0, 1, 0,
2180 0, 0, 0, 1);
2181
2182 value += 4;
2183 }
2184
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002185 D3DXHANDLE constantPS;
2186 D3DXHANDLE constantVS;
2187 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002188 IDirect3DDevice9 *device = getDevice();
2189
2190 if (constantPS)
2191 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002192 mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002193 }
2194
2195 if (constantVS)
2196 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002197 mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002198 }
2199
2200 delete[] matrix;
2201
2202 return true;
2203}
2204
jbauman@chromium.orga28233e2011-10-12 16:51:33 +00002205bool Program::applyUniformMatrix3fv(Uniform *targetUniform, GLsizei count, const GLfloat *value)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002206{
2207 D3DXMATRIX *matrix = new D3DXMATRIX[count];
2208
2209 for (int i = 0; i < count; i++)
2210 {
2211 matrix[i] = D3DXMATRIX(value[0], value[3], value[6], 0,
2212 value[1], value[4], value[7], 0,
2213 value[2], value[5], value[8], 0,
2214 0, 0, 0, 1);
2215
2216 value += 9;
2217 }
2218
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002219 D3DXHANDLE constantPS;
2220 D3DXHANDLE constantVS;
2221 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002222 IDirect3DDevice9 *device = getDevice();
2223
2224 if (constantPS)
2225 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002226 mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002227 }
2228
2229 if (constantVS)
2230 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002231 mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002232 }
2233
2234 delete[] matrix;
2235
2236 return true;
2237}
2238
jbauman@chromium.orga28233e2011-10-12 16:51:33 +00002239bool Program::applyUniformMatrix4fv(Uniform *targetUniform, GLsizei count, const GLfloat *value)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002240{
2241 D3DXMATRIX *matrix = new D3DXMATRIX[count];
2242
2243 for (int i = 0; i < count; i++)
2244 {
2245 matrix[i] = D3DXMATRIX(value[0], value[4], value[8], value[12],
2246 value[1], value[5], value[9], value[13],
2247 value[2], value[6], value[10], value[14],
2248 value[3], value[7], value[11], value[15]);
2249
2250 value += 16;
2251 }
2252
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002253 D3DXHANDLE constantPS;
2254 D3DXHANDLE constantVS;
2255 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002256 IDirect3DDevice9 *device = getDevice();
2257
2258 if (constantPS)
2259 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002260 mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002261 }
2262
2263 if (constantVS)
2264 {
daniel@transgaming.com279e38a2010-04-03 20:56:13 +00002265 mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002266 }
2267
2268 delete[] matrix;
2269
2270 return true;
2271}
2272
jbauman@chromium.orga28233e2011-10-12 16:51:33 +00002273bool Program::applyUniform1iv(Uniform *targetUniform, GLsizei count, const GLint *v)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002274{
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002275 D3DXHANDLE constantPS;
2276 D3DXHANDLE constantVS;
2277 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002278 IDirect3DDevice9 *device = getDevice();
2279
2280 if (constantPS)
2281 {
2282 D3DXCONSTANT_DESC constantDescription;
2283 UINT descriptionCount = 1;
2284 HRESULT result = mConstantTablePS->GetConstantDesc(constantPS, &constantDescription, &descriptionCount);
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002285 ASSERT(SUCCEEDED(result));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002286
2287 if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
2288 {
2289 unsigned int firstIndex = mConstantTablePS->GetSamplerIndex(constantPS);
2290
daniel@transgaming.coma41e6e32010-12-15 15:45:30 +00002291 for (int i = 0; i < count; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002292 {
daniel@transgaming.coma41e6e32010-12-15 15:45:30 +00002293 unsigned int samplerIndex = firstIndex + i;
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002294
daniel@transgaming.coma41e6e32010-12-15 15:45:30 +00002295 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002296 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002297 ASSERT(mSamplersPS[samplerIndex].active);
2298 mSamplersPS[samplerIndex].logicalTextureUnit = v[i];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002299 }
2300 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002301 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002302 else
2303 {
2304 mConstantTablePS->SetIntArray(device, constantPS, v, count);
2305 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002306 }
2307
2308 if (constantVS)
2309 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002310 D3DXCONSTANT_DESC constantDescription;
2311 UINT descriptionCount = 1;
2312 HRESULT result = mConstantTableVS->GetConstantDesc(constantVS, &constantDescription, &descriptionCount);
2313 ASSERT(SUCCEEDED(result));
2314
2315 if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
2316 {
2317 unsigned int firstIndex = mConstantTableVS->GetSamplerIndex(constantVS);
2318
2319 for (int i = 0; i < count; i++)
2320 {
2321 unsigned int samplerIndex = firstIndex + i;
2322
2323 if (samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF)
2324 {
2325 ASSERT(mSamplersVS[samplerIndex].active);
2326 mSamplersVS[samplerIndex].logicalTextureUnit = v[i];
2327 }
2328 }
2329 }
2330 else
2331 {
2332 mConstantTableVS->SetIntArray(device, constantVS, v, count);
2333 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002334 }
2335
2336 return true;
2337}
2338
jbauman@chromium.orga28233e2011-10-12 16:51:33 +00002339bool Program::applyUniform2iv(Uniform *targetUniform, GLsizei count, const GLint *v)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002340{
2341 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2342
2343 for (int i = 0; i < count; i++)
2344 {
2345 vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], 0, 0);
2346
2347 v += 2;
2348 }
2349
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002350 D3DXHANDLE constantPS;
2351 D3DXHANDLE constantVS;
2352 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002353 IDirect3DDevice9 *device = getDevice();
2354
2355 if (constantPS)
2356 {
2357 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2358 }
2359
2360 if (constantVS)
2361 {
2362 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2363 }
2364
2365 delete[] vector;
2366
2367 return true;
2368}
2369
jbauman@chromium.orga28233e2011-10-12 16:51:33 +00002370bool Program::applyUniform3iv(Uniform *targetUniform, GLsizei count, const GLint *v)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002371{
2372 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2373
2374 for (int i = 0; i < count; i++)
2375 {
2376 vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], (float)v[2], 0);
2377
2378 v += 3;
2379 }
2380
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002381 D3DXHANDLE constantPS;
2382 D3DXHANDLE constantVS;
2383 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002384 IDirect3DDevice9 *device = getDevice();
2385
2386 if (constantPS)
2387 {
2388 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2389 }
2390
2391 if (constantVS)
2392 {
2393 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2394 }
2395
2396 delete[] vector;
2397
2398 return true;
2399}
2400
jbauman@chromium.orga28233e2011-10-12 16:51:33 +00002401bool Program::applyUniform4iv(Uniform *targetUniform, GLsizei count, const GLint *v)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002402{
2403 D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
2404
2405 for (int i = 0; i < count; i++)
2406 {
2407 vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], (float)v[2], (float)v[3]);
2408
2409 v += 4;
2410 }
2411
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002412 D3DXHANDLE constantPS;
2413 D3DXHANDLE constantVS;
2414 getConstantHandles(targetUniform, &constantPS, &constantVS);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002415 IDirect3DDevice9 *device = getDevice();
2416
2417 if (constantPS)
2418 {
2419 mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
2420 }
2421
2422 if (constantVS)
2423 {
2424 mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
2425 }
2426
2427 delete [] vector;
2428
2429 return true;
2430}
2431
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002432
2433// append a santized message to the program info log.
daniel@transgaming.com8a4dad62011-09-13 00:54:40 +00002434// The D3D compiler includes a fake file path in some of the warning or error
2435// messages, so lets remove all occurrences of this fake file path from the log.
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002436void Program::appendToInfoLogSanitized(const char *message)
2437{
2438 std::string msg(message);
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002439
daniel@transgaming.com8a4dad62011-09-13 00:54:40 +00002440 size_t found;
2441 do
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002442 {
daniel@transgaming.com8a4dad62011-09-13 00:54:40 +00002443 found = msg.find(fakepath);
2444 if (found != std::string::npos)
2445 {
2446 msg.erase(found, strlen(fakepath));
2447 }
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002448 }
daniel@transgaming.com8a4dad62011-09-13 00:54:40 +00002449 while (found != std::string::npos);
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002450
2451 appendToInfoLog("%s\n", msg.c_str());
2452}
2453
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002454void Program::appendToInfoLog(const char *format, ...)
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002455{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002456 if (!format)
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002457 {
2458 return;
2459 }
2460
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002461 char info[1024];
2462
2463 va_list vararg;
2464 va_start(vararg, format);
2465 vsnprintf(info, sizeof(info), format, vararg);
2466 va_end(vararg);
2467
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002468 size_t infoLength = strlen(info);
2469
2470 if (!mInfoLog)
2471 {
2472 mInfoLog = new char[infoLength + 1];
2473 strcpy(mInfoLog, info);
2474 }
2475 else
2476 {
2477 size_t logLength = strlen(mInfoLog);
2478 char *newLog = new char[logLength + infoLength + 1];
2479 strcpy(newLog, mInfoLog);
2480 strcpy(newLog + logLength, info);
2481
2482 delete[] mInfoLog;
2483 mInfoLog = newLog;
2484 }
2485}
2486
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002487void Program::resetInfoLog()
2488{
2489 if (mInfoLog)
2490 {
2491 delete [] mInfoLog;
daniel@transgaming.com6a20d102010-08-31 13:54:27 +00002492 mInfoLog = NULL;
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002493 }
2494}
2495
daniel@transgaming.comaa5e59b2011-10-04 18:43:12 +00002496// Returns the program object to an unlinked state, before re-linking, or at destruction
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002497void Program::unlink(bool destroy)
2498{
2499 if (destroy) // Object being destructed
2500 {
2501 if (mFragmentShader)
2502 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002503 mFragmentShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002504 mFragmentShader = NULL;
2505 }
2506
2507 if (mVertexShader)
2508 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002509 mVertexShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002510 mVertexShader = NULL;
2511 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002512 }
2513
2514 if (mPixelExecutable)
2515 {
2516 mPixelExecutable->Release();
2517 mPixelExecutable = NULL;
2518 }
2519
2520 if (mVertexExecutable)
2521 {
2522 mVertexExecutable->Release();
2523 mVertexExecutable = NULL;
2524 }
2525
2526 if (mConstantTablePS)
2527 {
2528 mConstantTablePS->Release();
2529 mConstantTablePS = NULL;
2530 }
2531
2532 if (mConstantTableVS)
2533 {
2534 mConstantTableVS->Release();
2535 mConstantTableVS = NULL;
2536 }
2537
2538 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
2539 {
daniel@transgaming.com85423182010-04-22 13:35:27 +00002540 mLinkedAttribute[index].name.clear();
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002541 mSemanticIndex[index] = -1;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002542 }
2543
2544 for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
2545 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002546 mSamplersPS[index].active = false;
2547 }
2548
2549 for (int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; index++)
2550 {
2551 mSamplersVS[index].active = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002552 }
2553
jbauman@chromium.orgb6e72222011-10-18 23:01:46 +00002554 mUsedVertexSamplerRange = 0;
2555 mUsedPixelSamplerRange = 0;
2556
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002557 while (!mUniforms.empty())
2558 {
2559 delete mUniforms.back();
2560 mUniforms.pop_back();
2561 }
2562
daniel@transgaming.com31754962010-11-28 02:02:52 +00002563 mDxDepthRangeLocation = -1;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002564 mDxDepthLocation = -1;
daniel@transgaming.com4f921eb2010-07-28 19:20:44 +00002565 mDxViewportLocation = -1;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002566 mDxHalfPixelSizeLocation = -1;
2567 mDxFrontCCWLocation = -1;
2568 mDxPointsOrLinesLocation = -1;
2569
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002570 mUniformIndex.clear();
2571
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00002572 mPixelHLSL.clear();
2573 mVertexHLSL.clear();
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00002574
2575 delete[] mInfoLog;
2576 mInfoLog = NULL;
2577
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002578 mLinked = false;
2579}
2580
2581bool Program::isLinked()
2582{
2583 return mLinked;
2584}
2585
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002586bool Program::isValidated() const
2587{
2588 return mValidated;
2589}
2590
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002591void Program::release()
2592{
2593 mRefCount--;
2594
2595 if (mRefCount == 0 && mDeleteStatus)
2596 {
2597 mResourceManager->deleteProgram(mHandle);
2598 }
2599}
2600
2601void Program::addRef()
2602{
2603 mRefCount++;
2604}
2605
2606unsigned int Program::getRefCount() const
2607{
2608 return mRefCount;
2609}
2610
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00002611unsigned int Program::getSerial() const
2612{
2613 return mSerial;
2614}
2615
2616unsigned int Program::issueSerial()
2617{
2618 return mCurrentSerial++;
2619}
2620
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002621int Program::getInfoLogLength() const
2622{
2623 if (!mInfoLog)
2624 {
2625 return 0;
2626 }
2627 else
2628 {
2629 return strlen(mInfoLog) + 1;
2630 }
2631}
2632
2633void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
2634{
2635 int index = 0;
2636
2637 if (mInfoLog)
2638 {
2639 while (index < bufSize - 1 && index < (int)strlen(mInfoLog))
2640 {
2641 infoLog[index] = mInfoLog[index];
2642 index++;
2643 }
2644 }
2645
2646 if (bufSize)
2647 {
2648 infoLog[index] = '\0';
2649 }
2650
2651 if (length)
2652 {
2653 *length = index;
2654 }
2655}
2656
daniel@transgaming.com6c785212010-03-30 03:36:17 +00002657void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
2658{
2659 int total = 0;
2660
2661 if (mVertexShader)
2662 {
2663 if (total < maxCount)
2664 {
2665 shaders[total] = mVertexShader->getHandle();
2666 }
2667
2668 total++;
2669 }
2670
2671 if (mFragmentShader)
2672 {
2673 if (total < maxCount)
2674 {
2675 shaders[total] = mFragmentShader->getHandle();
2676 }
2677
2678 total++;
2679 }
2680
2681 if (count)
2682 {
2683 *count = total;
2684 }
2685}
2686
daniel@transgaming.com85423182010-04-22 13:35:27 +00002687void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2688{
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002689 // Skip over inactive attributes
2690 unsigned int activeAttribute = 0;
2691 unsigned int attribute;
2692 for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
daniel@transgaming.com85423182010-04-22 13:35:27 +00002693 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002694 if (mLinkedAttribute[attribute].name.empty())
daniel@transgaming.com85423182010-04-22 13:35:27 +00002695 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002696 continue;
daniel@transgaming.com85423182010-04-22 13:35:27 +00002697 }
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002698
2699 if (activeAttribute == index)
2700 {
2701 break;
2702 }
2703
2704 activeAttribute++;
daniel@transgaming.com85423182010-04-22 13:35:27 +00002705 }
2706
2707 if (bufsize > 0)
2708 {
2709 const char *string = mLinkedAttribute[attribute].name.c_str();
2710
2711 strncpy(name, string, bufsize);
2712 name[bufsize - 1] = '\0';
2713
2714 if (length)
2715 {
2716 *length = strlen(name);
2717 }
2718 }
2719
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00002720 *size = 1; // Always a single 'type' instance
daniel@transgaming.com85423182010-04-22 13:35:27 +00002721
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002722 *type = mLinkedAttribute[attribute].type;
daniel@transgaming.com85423182010-04-22 13:35:27 +00002723}
2724
2725GLint Program::getActiveAttributeCount()
2726{
2727 int count = 0;
2728
2729 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2730 {
2731 if (!mLinkedAttribute[attributeIndex].name.empty())
2732 {
2733 count++;
2734 }
2735 }
2736
2737 return count;
2738}
2739
2740GLint Program::getActiveAttributeMaxLength()
2741{
2742 int maxLength = 0;
2743
2744 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2745 {
2746 if (!mLinkedAttribute[attributeIndex].name.empty())
2747 {
2748 maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength);
2749 }
2750 }
2751
2752 return maxLength;
2753}
2754
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002755void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2756{
daniel@transgaming.com996675c2010-11-17 13:06:29 +00002757 // Skip over internal uniforms
2758 unsigned int activeUniform = 0;
2759 unsigned int uniform;
2760 for (uniform = 0; uniform < mUniforms.size(); uniform++)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002761 {
daniel@transgaming.com51db7fb2011-09-20 16:11:06 +00002762 if (mUniforms[uniform]->name.compare(0, 3, "dx_") == 0)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002763 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002764 continue;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002765 }
daniel@transgaming.com996675c2010-11-17 13:06:29 +00002766
2767 if (activeUniform == index)
2768 {
2769 break;
2770 }
2771
2772 activeUniform++;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002773 }
2774
daniel@transgaming.com996675c2010-11-17 13:06:29 +00002775 ASSERT(uniform < mUniforms.size()); // index must be smaller than getActiveUniformCount()
2776
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002777 if (bufsize > 0)
2778 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00002779 std::string string = mUniforms[uniform]->name;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002780
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00002781 if (mUniforms[uniform]->isArray())
daniel@transgaming.comf3140152010-04-29 03:38:50 +00002782 {
2783 string += "[0]";
2784 }
2785
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00002786 strncpy(name, string.c_str(), bufsize);
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002787 name[bufsize - 1] = '\0';
2788
2789 if (length)
2790 {
2791 *length = strlen(name);
2792 }
2793 }
2794
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00002795 *size = mUniforms[uniform]->arraySize;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002796
2797 *type = mUniforms[uniform]->type;
2798}
2799
2800GLint Program::getActiveUniformCount()
2801{
2802 int count = 0;
2803
daniel@transgaming.comd08ea902010-05-14 19:41:36 +00002804 unsigned int numUniforms = mUniforms.size();
2805 for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002806 {
daniel@transgaming.com51db7fb2011-09-20 16:11:06 +00002807 if (mUniforms[uniformIndex]->name.compare(0, 3, "dx_") != 0)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002808 {
2809 count++;
2810 }
2811 }
2812
2813 return count;
2814}
2815
2816GLint Program::getActiveUniformMaxLength()
2817{
2818 int maxLength = 0;
2819
daniel@transgaming.comd08ea902010-05-14 19:41:36 +00002820 unsigned int numUniforms = mUniforms.size();
2821 for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002822 {
daniel@transgaming.com51db7fb2011-09-20 16:11:06 +00002823 if (!mUniforms[uniformIndex]->name.empty() && mUniforms[uniformIndex]->name.compare(0, 3, "dx_") != 0)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002824 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00002825 int length = (int)(mUniforms[uniformIndex]->name.length() + 1);
2826 if (mUniforms[uniformIndex]->isArray())
zmo@google.com53d73e02011-03-24 21:27:57 +00002827 {
2828 length += 3; // Counting in "[0]".
2829 }
2830 maxLength = std::max(length, maxLength);
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002831 }
2832 }
2833
2834 return maxLength;
2835}
2836
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002837void Program::flagForDeletion()
2838{
2839 mDeleteStatus = true;
2840}
2841
2842bool Program::isFlaggedForDeletion() const
2843{
2844 return mDeleteStatus;
2845}
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002846
2847void Program::validate()
2848{
2849 resetInfoLog();
2850
2851 if (!isLinked())
2852 {
2853 appendToInfoLog("Program has not been successfully linked.");
2854 mValidated = false;
2855 }
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002856 else
2857 {
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002858 applyUniforms();
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002859 if (!validateSamplers(true))
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002860 {
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002861 mValidated = false;
2862 }
2863 else
2864 {
2865 mValidated = true;
2866 }
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002867 }
2868}
2869
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002870bool Program::validateSamplers(bool logErrors)
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002871{
2872 // if any two active samplers in a program are of different types, but refer to the same
2873 // texture image unit, and this is the current program, then ValidateProgram will fail, and
2874 // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002875
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002876 const unsigned int maxCombinedTextureImageUnits = getContext()->getMaximumCombinedTextureImageUnits();
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002877 TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF];
2878
2879 for (unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; ++i)
2880 {
2881 textureUnitType[i] = TEXTURE_UNKNOWN;
2882 }
2883
jbauman@chromium.orgb6e72222011-10-18 23:01:46 +00002884 for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002885 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002886 if (mSamplersPS[i].active)
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002887 {
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002888 unsigned int unit = mSamplersPS[i].logicalTextureUnit;
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002889
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002890 if (unit >= maxCombinedTextureImageUnits)
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002891 {
2892 if (logErrors)
2893 {
2894 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
2895 }
2896
2897 return false;
2898 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002899
2900 if (textureUnitType[unit] != TEXTURE_UNKNOWN)
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002901 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002902 if (mSamplersPS[i].textureType != textureUnitType[unit])
2903 {
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002904 if (logErrors)
2905 {
2906 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
2907 }
2908
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002909 return false;
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002910 }
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002911 }
2912 else
2913 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002914 textureUnitType[unit] = mSamplersPS[i].textureType;
2915 }
2916 }
2917 }
2918
jbauman@chromium.orgb6e72222011-10-18 23:01:46 +00002919 for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002920 {
2921 if (mSamplersVS[i].active)
2922 {
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002923 unsigned int unit = mSamplersVS[i].logicalTextureUnit;
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002924
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002925 if (unit >= maxCombinedTextureImageUnits)
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002926 {
2927 if (logErrors)
2928 {
2929 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
2930 }
2931
2932 return false;
2933 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002934
2935 if (textureUnitType[unit] != TEXTURE_UNKNOWN)
2936 {
2937 if (mSamplersVS[i].textureType != textureUnitType[unit])
2938 {
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002939 if (logErrors)
2940 {
2941 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
2942 }
2943
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002944 return false;
2945 }
2946 }
2947 else
2948 {
2949 textureUnitType[unit] = mSamplersVS[i].textureType;
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002950 }
2951 }
2952 }
2953
2954 return true;
2955}
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002956
2957void Program::getConstantHandles(Uniform *targetUniform, D3DXHANDLE *constantPS, D3DXHANDLE *constantVS)
2958{
2959 if (!targetUniform->handlesSet)
2960 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00002961 targetUniform->psHandle = mConstantTablePS->GetConstantByName(0, targetUniform->_name.c_str());
2962 targetUniform->vsHandle = mConstantTableVS->GetConstantByName(0, targetUniform->_name.c_str());
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002963 targetUniform->handlesSet = true;
2964 }
2965
2966 *constantPS = targetUniform->psHandle;
2967 *constantVS = targetUniform->vsHandle;
2968}
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002969
daniel@transgaming.com31754962010-11-28 02:02:52 +00002970GLint Program::getDxDepthRangeLocation() const
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002971{
daniel@transgaming.com31754962010-11-28 02:02:52 +00002972 return mDxDepthRangeLocation;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002973}
2974
2975GLint Program::getDxDepthLocation() const
2976{
2977 return mDxDepthLocation;
2978}
2979
daniel@transgaming.com4f921eb2010-07-28 19:20:44 +00002980GLint Program::getDxViewportLocation() const
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002981{
daniel@transgaming.com4f921eb2010-07-28 19:20:44 +00002982 return mDxViewportLocation;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002983}
2984
2985GLint Program::getDxHalfPixelSizeLocation() const
2986{
2987 return mDxHalfPixelSizeLocation;
2988}
2989
2990GLint Program::getDxFrontCCWLocation() const
2991{
2992 return mDxFrontCCWLocation;
2993}
2994
2995GLint Program::getDxPointsOrLinesLocation() const
2996{
2997 return mDxPointsOrLinesLocation;
2998}
2999
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003000}