blob: 3a84497429d8b4864c1a363a888d5288ddd9e470 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
daniel@transgaming.comcde6a612012-02-17 18:01:10 +00002// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// 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];
kbr@chromium.orgddb6e8e2012-04-25 00:48:13 +000032 snprintf(buffer, sizeof(buffer), "%d", i);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +000033 return buffer;
34}
35
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +000036AttributeBindings::AttributeBindings()
37{
38}
39
40AttributeBindings::~AttributeBindings()
41{
apatrick@chromium.org9a30b092012-06-06 20:21:55 +000042}
43
daniel@transgaming.com024f1a92011-09-20 16:06:25 +000044Uniform::Uniform(GLenum type, const std::string &_name, unsigned int arraySize)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +000045 : type(type), _name(_name), name(ProgramBinary::undecorateUniform(_name)), arraySize(arraySize)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000046{
daniel@transgaming.come918ea22011-11-12 03:15:28 +000047 int bytes = UniformInternalSize(type) * arraySize;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +000048 data = new unsigned char[bytes];
49 memset(data, 0, bytes);
50 dirty = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000051}
52
53Uniform::~Uniform()
54{
55 delete[] data;
56}
57
daniel@transgaming.com024f1a92011-09-20 16:06:25 +000058bool Uniform::isArray()
59{
daniel@transgaming.com51db7fb2011-09-20 16:11:06 +000060 return _name.compare(0, 3, "ar_") == 0;
daniel@transgaming.com024f1a92011-09-20 16:06:25 +000061}
62
63UniformLocation::UniformLocation(const std::string &_name, unsigned int element, unsigned int index)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +000064 : name(ProgramBinary::undecorateUniform(_name)), element(element), index(index)
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +000065{
66}
67
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +000068ProgramBinary::ProgramBinary()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000069{
daniel@transgaming.com96a4a6c2011-10-26 02:33:46 +000070 mDevice = getDevice();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000071
72 mPixelExecutable = NULL;
73 mVertexExecutable = NULL;
74 mConstantTablePS = NULL;
75 mConstantTableVS = NULL;
76
daniel@transgaming.comcba50572010-03-28 19:36:09 +000077 mInfoLog = NULL;
daniel@transgaming.com86a7a132010-04-29 03:32:32 +000078 mValidated = false;
daniel@transgaming.comcba50572010-03-28 19:36:09 +000079
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +000080 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
81 {
82 mSemanticIndex[index] = -1;
83 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000084
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +000085 for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
86 {
87 mSamplersPS[index].active = false;
88 }
89
90 for (int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; index++)
91 {
92 mSamplersVS[index].active = false;
93 }
94
95 mUsedVertexSamplerRange = 0;
96 mUsedPixelSamplerRange = 0;
97
98 mDxDepthRangeLocation = -1;
99 mDxDepthLocation = -1;
100 mDxCoordLocation = -1;
101 mDxHalfPixelSizeLocation = -1;
102 mDxFrontCCWLocation = -1;
103 mDxPointsOrLinesLocation = -1;
104}
105
106Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle), mSerial(issueSerial())
107{
108 mFragmentShader = NULL;
109 mVertexShader = NULL;
110 mProgramBinary = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000111 mDeleteStatus = false;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000112 mRefCount = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000113}
114
115Program::~Program()
116{
117 unlink(true);
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000118
119 if (mVertexShader != NULL)
120 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000121 mVertexShader->release();
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000122 }
123
124 if (mFragmentShader != NULL)
125 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000126 mFragmentShader->release();
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000127 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000128}
129
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000130ProgramBinary::~ProgramBinary()
131{
132 if (mPixelExecutable)
133 {
134 mPixelExecutable->Release();
135 }
136
137 if (mVertexExecutable)
138 {
139 mVertexExecutable->Release();
140 }
141
142 if (mConstantTablePS)
143 {
144 mConstantTablePS->Release();
145 }
146
147 if (mConstantTableVS)
148 {
149 mConstantTableVS->Release();
150 }
151
152 while (!mUniforms.empty())
153 {
154 delete mUniforms.back();
155 mUniforms.pop_back();
156 }
157
158 delete[] mInfoLog;
159}
160
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000161bool Program::attachShader(Shader *shader)
162{
163 if (shader->getType() == GL_VERTEX_SHADER)
164 {
165 if (mVertexShader)
166 {
167 return false;
168 }
169
170 mVertexShader = (VertexShader*)shader;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000171 mVertexShader->addRef();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000172 }
173 else if (shader->getType() == GL_FRAGMENT_SHADER)
174 {
175 if (mFragmentShader)
176 {
177 return false;
178 }
179
180 mFragmentShader = (FragmentShader*)shader;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000181 mFragmentShader->addRef();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182 }
183 else UNREACHABLE();
184
185 return true;
186}
187
188bool Program::detachShader(Shader *shader)
189{
190 if (shader->getType() == GL_VERTEX_SHADER)
191 {
192 if (mVertexShader != shader)
193 {
194 return false;
195 }
196
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000197 mVertexShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000198 mVertexShader = NULL;
199 }
200 else if (shader->getType() == GL_FRAGMENT_SHADER)
201 {
202 if (mFragmentShader != shader)
203 {
204 return false;
205 }
206
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000207 mFragmentShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000208 mFragmentShader = NULL;
209 }
210 else UNREACHABLE();
211
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000212 return true;
213}
214
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000215int Program::getAttachedShadersCount() const
216{
217 return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
218}
219
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000220IDirect3DPixelShader9 *ProgramBinary::getPixelShader()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221{
222 return mPixelExecutable;
223}
224
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000225IDirect3DVertexShader9 *ProgramBinary::getVertexShader()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000226{
227 return mVertexExecutable;
228}
229
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000230void AttributeBindings::bindAttributeLocation(GLuint index, const char *name)
231{
232 if (index < MAX_VERTEX_ATTRIBS)
233 {
234 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
235 {
236 mAttributeBinding[i].erase(name);
237 }
238
239 mAttributeBinding[index].insert(name);
240 }
apatrick@chromium.org9a30b092012-06-06 20:21:55 +0000241}
242
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000243void Program::bindAttributeLocation(GLuint index, const char *name)
244{
apatrick@chromium.org9a30b092012-06-06 20:21:55 +0000245 mAttributeBindings.bindAttributeLocation(index, name);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000246}
247
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000248GLuint ProgramBinary::getAttributeLocation(const char *name)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000250 if (name)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000251 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000252 for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000253 {
daniel@transgaming.com85423182010-04-22 13:35:27 +0000254 if (mLinkedAttribute[index].name == std::string(name))
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000255 {
256 return index;
257 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000258 }
259 }
260
261 return -1;
262}
263
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000264int ProgramBinary::getSemanticIndex(int attributeIndex)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000265{
daniel@transgaming.com733ba932011-04-14 15:03:48 +0000266 ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
267
268 return mSemanticIndex[attributeIndex];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000269}
270
jbauman@chromium.orgb6e72222011-10-18 23:01:46 +0000271// Returns one more than the highest sampler index used.
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000272GLint ProgramBinary::getUsedSamplerRange(SamplerType type)
jbauman@chromium.orgb6e72222011-10-18 23:01:46 +0000273{
274 switch (type)
275 {
276 case SAMPLER_PIXEL:
277 return mUsedPixelSamplerRange;
278 case SAMPLER_VERTEX:
279 return mUsedVertexSamplerRange;
280 default:
281 UNREACHABLE();
282 return 0;
283 }
284}
285
daniel@transgaming.com9ba680a2011-05-11 15:37:11 +0000286// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler
287// index (0-15 for the pixel shader and 0-3 for the vertex shader).
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000288GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000289{
jbauman@chromium.org8b3c1af2011-10-12 01:21:41 +0000290 GLint logicalTextureUnit = -1;
daniel@transgaming.com4071e662010-05-12 16:51:16 +0000291
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000292 switch (type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000293 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000294 case SAMPLER_PIXEL:
295 ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
296
297 if (mSamplersPS[samplerIndex].active)
298 {
299 logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit;
300 }
301 break;
302 case SAMPLER_VERTEX:
303 ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
304
305 if (mSamplersVS[samplerIndex].active)
306 {
307 logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit;
308 }
309 break;
310 default: UNREACHABLE();
daniel@transgaming.com4071e662010-05-12 16:51:16 +0000311 }
312
jbauman@chromium.org8b3c1af2011-10-12 01:21:41 +0000313 if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)getContext()->getMaximumCombinedTextureImageUnits())
daniel@transgaming.com4071e662010-05-12 16:51:16 +0000314 {
315 return logicalTextureUnit;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000316 }
317
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000318 return -1;
319}
320
daniel@transgaming.com9ba680a2011-05-11 15:37:11 +0000321// Returns the texture type for a given Direct3D 9 sampler type and
322// index (0-15 for the pixel shader and 0-3 for the vertex shader).
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000323TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000324{
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000325 switch (type)
326 {
327 case SAMPLER_PIXEL:
328 ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0]));
329 ASSERT(mSamplersPS[samplerIndex].active);
330 return mSamplersPS[samplerIndex].textureType;
331 case SAMPLER_VERTEX:
332 ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0]));
333 ASSERT(mSamplersVS[samplerIndex].active);
334 return mSamplersVS[samplerIndex].textureType;
335 default: UNREACHABLE();
336 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000337
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000338 return TEXTURE_2D;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000339}
340
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000341GLint ProgramBinary::getUniformLocation(std::string name)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000342{
apatrick@chromium.orga1d80592012-01-25 21:52:10 +0000343 unsigned int subscript = 0;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000344
daniel@transgaming.comce864422010-11-18 13:16:49 +0000345 // Strip any trailing array operator and retrieve the subscript
daniel@transgaming.com024f1a92011-09-20 16:06:25 +0000346 size_t open = name.find_last_of('[');
347 size_t close = name.find_last_of(']');
348 if (open != std::string::npos && close == name.length() - 1)
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +0000349 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +0000350 subscript = atoi(name.substr(open + 1).c_str());
351 name.erase(open);
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +0000352 }
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000353
daniel@transgaming.comd08ea902010-05-14 19:41:36 +0000354 unsigned int numUniforms = mUniformIndex.size();
355 for (unsigned int location = 0; location < numUniforms; location++)
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000356 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +0000357 if (mUniformIndex[location].name == name &&
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000358 mUniformIndex[location].element == subscript)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000359 {
360 return location;
361 }
362 }
363
364 return -1;
365}
366
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000367bool ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000368{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000369 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000370 {
371 return false;
372 }
373
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000374 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000375 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000376
377 if (targetUniform->type == GL_FLOAT)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000378 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000379 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000380
381 if (arraySize == 1 && count > 1)
382 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
383
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000384 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000385
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000386 GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
387
388 for (int i = 0; i < count; i++)
389 {
390 target[0] = v[0];
391 target[1] = 0;
392 target[2] = 0;
393 target[3] = 0;
394 target += 4;
395 v += 1;
396 }
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000397 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000398 else if (targetUniform->type == GL_BOOL)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000399 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000400 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000401
402 if (arraySize == 1 && count > 1)
403 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000404
405 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
jbauman@chromium.orge0f059c2012-01-24 23:21:52 +0000406 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000407
408 for (int i = 0; i < count; ++i)
409 {
410 if (v[i] == 0.0f)
411 {
412 boolParams[i] = GL_FALSE;
413 }
414 else
415 {
416 boolParams[i] = GL_TRUE;
417 }
418 }
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000419 }
420 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000421 {
422 return false;
423 }
424
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000425 return true;
426}
427
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000428bool ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000429{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000430 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000431 {
432 return false;
433 }
434
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000435 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000436 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000437
438 if (targetUniform->type == GL_FLOAT_VEC2)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000439 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000440 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000441
442 if (arraySize == 1 && count > 1)
443 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
444
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000445 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000446
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000447 GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
448
449 for (int i = 0; i < count; i++)
450 {
451 target[0] = v[0];
452 target[1] = v[1];
453 target[2] = 0;
454 target[3] = 0;
455 target += 4;
456 v += 2;
457 }
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000458 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000459 else if (targetUniform->type == GL_BOOL_VEC2)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000460 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000461 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000462
463 if (arraySize == 1 && count > 1)
464 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
465
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000466 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
467
jbauman@chromium.orge0f059c2012-01-24 23:21:52 +0000468 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 2;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000469
470 for (int i = 0; i < count * 2; ++i)
471 {
472 if (v[i] == 0.0f)
473 {
474 boolParams[i] = GL_FALSE;
475 }
476 else
477 {
478 boolParams[i] = GL_TRUE;
479 }
480 }
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000481 }
482 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000483 {
484 return false;
485 }
486
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000487 return true;
488}
489
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000490bool ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000491{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000492 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000493 {
494 return false;
495 }
496
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000497 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000498 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000499
500 if (targetUniform->type == GL_FLOAT_VEC3)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000501 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000502 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000503
504 if (arraySize == 1 && count > 1)
505 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
506
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000507 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000508
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000509 GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4;
510
511 for (int i = 0; i < count; i++)
512 {
513 target[0] = v[0];
514 target[1] = v[1];
515 target[2] = v[2];
516 target[3] = 0;
517 target += 4;
518 v += 3;
519 }
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000520 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000521 else if (targetUniform->type == GL_BOOL_VEC3)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000522 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000523 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000524
525 if (arraySize == 1 && count > 1)
526 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
527
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000528 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
jbauman@chromium.orge0f059c2012-01-24 23:21:52 +0000529 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 3;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000530
531 for (int i = 0; i < count * 3; ++i)
532 {
533 if (v[i] == 0.0f)
534 {
535 boolParams[i] = GL_FALSE;
536 }
537 else
538 {
539 boolParams[i] = GL_TRUE;
540 }
541 }
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000542 }
543 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000544 {
545 return false;
546 }
547
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000548 return true;
549}
550
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000551bool ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000552{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000553 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000554 {
555 return false;
556 }
557
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000558 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000559 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000560
561 if (targetUniform->type == GL_FLOAT_VEC4)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000562 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000563 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000564
565 if (arraySize == 1 && count > 1)
566 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
567
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000568 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000569
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000570 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4,
571 v, 4 * sizeof(GLfloat) * count);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000572 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000573 else if (targetUniform->type == GL_BOOL_VEC4)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000574 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000575 int arraySize = targetUniform->arraySize;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000576
577 if (arraySize == 1 && count > 1)
578 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
579
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000580 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
jbauman@chromium.orge0f059c2012-01-24 23:21:52 +0000581 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 4;
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000582
583 for (int i = 0; i < count * 4; ++i)
584 {
585 if (v[i] == 0.0f)
586 {
587 boolParams[i] = GL_FALSE;
588 }
589 else
590 {
591 boolParams[i] = GL_TRUE;
592 }
593 }
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +0000594 }
595 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000596 {
597 return false;
598 }
599
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000600 return true;
601}
602
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000603template<typename T, int targetWidth, int targetHeight, int srcWidth, int srcHeight>
604void transposeMatrix(T *target, const GLfloat *value)
605{
606 int copyWidth = std::min(targetWidth, srcWidth);
607 int copyHeight = std::min(targetHeight, srcHeight);
608
609 for (int x = 0; x < copyWidth; x++)
610 {
611 for (int y = 0; y < copyHeight; y++)
612 {
daniel@transgaming.comc9d81a22011-11-12 03:14:30 +0000613 target[x * targetWidth + y] = (T)value[y * srcWidth + x];
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000614 }
615 }
616 // clear unfilled right side
617 for (int y = 0; y < copyHeight; y++)
618 {
619 for (int x = srcWidth; x < targetWidth; x++)
620 {
daniel@transgaming.comc9d81a22011-11-12 03:14:30 +0000621 target[y * targetWidth + x] = (T)0;
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000622 }
623 }
624 // clear unfilled bottom.
625 for (int y = srcHeight; y < targetHeight; y++)
626 {
627 for (int x = 0; x < targetWidth; x++)
628 {
daniel@transgaming.comc9d81a22011-11-12 03:14:30 +0000629 target[y * targetWidth + x] = (T)0;
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000630 }
631 }
632}
633
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000634bool ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000635{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000636 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000637 {
638 return false;
639 }
640
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000641 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000642 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000643
644 if (targetUniform->type != GL_FLOAT_MAT2)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000645 {
646 return false;
647 }
648
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000649 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000650
651 if (arraySize == 1 && count > 1)
652 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
653
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000654 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000655
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000656 GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8;
657 for (int i = 0; i < count; i++)
658 {
659 transposeMatrix<GLfloat,4,2,2,2>(target, value);
660 target += 8;
661 value += 4;
662 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000663
664 return true;
665}
666
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000667bool ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000668{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000669 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000670 {
671 return false;
672 }
673
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000674 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000675 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000676
677 if (targetUniform->type != GL_FLOAT_MAT3)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000678 {
679 return false;
680 }
681
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000682 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000683
684 if (arraySize == 1 && count > 1)
685 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
686
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000687 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000688
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000689 GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12;
690 for (int i = 0; i < count; i++)
691 {
692 transposeMatrix<GLfloat,4,3,3,3>(target, value);
693 target += 12;
694 value += 9;
695 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000696
697 return true;
698}
699
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000700
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000701bool ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000702{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000703 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000704 {
705 return false;
706 }
707
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000708 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000709 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000710
711 if (targetUniform->type != GL_FLOAT_MAT4)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000712 {
713 return false;
714 }
715
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000716 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000717
718 if (arraySize == 1 && count > 1)
719 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
720
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000721 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000722
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000723 GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16);
724 for (int i = 0; i < count; i++)
725 {
726 transposeMatrix<GLfloat,4,4,4,4>(target, value);
727 target += 16;
728 value += 16;
729 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000730
731 return true;
732}
733
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000734bool ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000735{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000736 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000737 {
738 return false;
739 }
740
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000741 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000742 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000743
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +0000744 if (targetUniform->type == GL_INT ||
745 targetUniform->type == GL_SAMPLER_2D ||
746 targetUniform->type == GL_SAMPLER_CUBE)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000747 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000748 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000749
750 if (arraySize == 1 && count > 1)
751 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
752
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000753 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000754
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000755 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint),
756 v, sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000757 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000758 else if (targetUniform->type == GL_BOOL)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000759 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000760 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000761
762 if (arraySize == 1 && count > 1)
763 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
764
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000765 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
jbauman@chromium.orge0f059c2012-01-24 23:21:52 +0000766 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000767
768 for (int i = 0; i < count; ++i)
769 {
770 if (v[i] == 0)
771 {
772 boolParams[i] = GL_FALSE;
773 }
774 else
775 {
776 boolParams[i] = GL_TRUE;
777 }
778 }
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000779 }
780 else
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000781 {
782 return false;
783 }
784
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000785 return true;
786}
787
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000788bool ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000789{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000790 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000791 {
792 return false;
793 }
794
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000795 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000796 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000797
798 if (targetUniform->type == GL_INT_VEC2)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000799 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000800 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000801
802 if (arraySize == 1 && count > 1)
803 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
804
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000805 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000806
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000807 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 2,
808 v, 2 * sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000809 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000810 else if (targetUniform->type == GL_BOOL_VEC2)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000811 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000812 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000813
814 if (arraySize == 1 && count > 1)
815 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
816
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000817 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
jbauman@chromium.orge0f059c2012-01-24 23:21:52 +0000818 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 2;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000819
820 for (int i = 0; i < count * 2; ++i)
821 {
822 if (v[i] == 0)
823 {
824 boolParams[i] = GL_FALSE;
825 }
826 else
827 {
828 boolParams[i] = GL_TRUE;
829 }
830 }
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000831 }
832 else
833 {
834 return false;
835 }
836
837 return true;
838}
839
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000840bool ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000841{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000842 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000843 {
844 return false;
845 }
846
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000847 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000848 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000849
850 if (targetUniform->type == GL_INT_VEC3)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000851 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000852 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000853
854 if (arraySize == 1 && count > 1)
855 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
856
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000857 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000858
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000859 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 3,
860 v, 3 * sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000861 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000862 else if (targetUniform->type == GL_BOOL_VEC3)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000863 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000864 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000865
866 if (arraySize == 1 && count > 1)
867 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
868
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000869 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
jbauman@chromium.orge0f059c2012-01-24 23:21:52 +0000870 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 3;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000871
872 for (int i = 0; i < count * 3; ++i)
873 {
874 if (v[i] == 0)
875 {
876 boolParams[i] = GL_FALSE;
877 }
878 else
879 {
880 boolParams[i] = GL_TRUE;
881 }
882 }
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000883 }
884 else
885 {
886 return false;
887 }
888
889 return true;
890}
891
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000892bool ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000893{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000894 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000895 {
896 return false;
897 }
898
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000899 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000900 targetUniform->dirty = true;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000901
902 if (targetUniform->type == GL_INT_VEC4)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000903 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000904 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000905
906 if (arraySize == 1 && count > 1)
907 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
908
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000909 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000910
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000911 memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 4,
912 v, 4 * sizeof(GLint) * count);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000913 }
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000914 else if (targetUniform->type == GL_BOOL_VEC4)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000915 {
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000916 int arraySize = targetUniform->arraySize;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000917
918 if (arraySize == 1 && count > 1)
919 return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
920
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000921 count = std::min(arraySize - (int)mUniformIndex[location].element, count);
jbauman@chromium.orge0f059c2012-01-24 23:21:52 +0000922 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * 4;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000923
924 for (int i = 0; i < count * 4; ++i)
925 {
926 if (v[i] == 0)
927 {
928 boolParams[i] = GL_FALSE;
929 }
930 else
931 {
932 boolParams[i] = GL_TRUE;
933 }
934 }
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +0000935 }
936 else
937 {
938 return false;
939 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000940
941 return true;
942}
943
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000944bool ProgramBinary::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params)
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000945{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000946 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000947 {
948 return false;
949 }
950
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +0000951 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000952
daniel@transgaming.com9a849122011-11-12 03:18:00 +0000953 // sized queries -- ensure the provided buffer is large enough
954 if (bufSize)
955 {
956 int requiredBytes = UniformExternalSize(targetUniform->type);
957 if (*bufSize < requiredBytes)
958 {
959 return false;
960 }
961 }
962
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000963 switch (targetUniform->type)
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000964 {
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000965 case GL_FLOAT_MAT2:
966 transposeMatrix<GLfloat,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8);
967 break;
968 case GL_FLOAT_MAT3:
969 transposeMatrix<GLfloat,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12);
970 break;
971 case GL_FLOAT_MAT4:
972 transposeMatrix<GLfloat,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16);
973 break;
974 default:
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +0000975 {
daniel@transgaming.comedc31502011-11-12 03:14:56 +0000976 unsigned int count = UniformExternalComponentCount(targetUniform->type);
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000977 unsigned int internalCount = UniformInternalComponentCount(targetUniform->type);
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000978
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000979 switch (UniformComponentType(targetUniform->type))
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +0000980 {
jbauman@chromium.org72e8f442011-10-20 00:22:01 +0000981 case GL_BOOL:
982 {
983 GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * internalCount;
984
985 for (unsigned int i = 0; i < count; ++i)
986 {
987 params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
988 }
989 }
990 break;
991 case GL_FLOAT:
992 memcpy(params, targetUniform->data + mUniformIndex[location].element * internalCount * sizeof(GLfloat),
993 count * sizeof(GLfloat));
994 break;
995 case GL_INT:
996 {
997 GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * internalCount;
998
999 for (unsigned int i = 0; i < count; ++i)
1000 {
1001 params[i] = (float)intParams[i];
1002 }
1003 }
1004 break;
1005 default: UNREACHABLE();
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00001006 }
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +00001007 }
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +00001008 }
1009
1010 return true;
1011}
1012
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001013bool ProgramBinary::getUniformiv(GLint location, GLsizei *bufSize, GLint *params)
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +00001014{
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00001015 if (location < 0 || location >= (int)mUniformIndex.size())
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +00001016 {
1017 return false;
1018 }
1019
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00001020 Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +00001021
daniel@transgaming.com9a849122011-11-12 03:18:00 +00001022 // sized queries -- ensure the provided buffer is large enough
1023 if (bufSize)
1024 {
1025 int requiredBytes = UniformExternalSize(targetUniform->type);
1026 if (*bufSize < requiredBytes)
1027 {
1028 return false;
1029 }
1030 }
1031
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00001032 switch (targetUniform->type)
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +00001033 {
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00001034 case GL_FLOAT_MAT2:
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +00001035 {
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00001036 transposeMatrix<GLint,2,2,4,2>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8);
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +00001037 }
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00001038 break;
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00001039 case GL_FLOAT_MAT3:
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00001040 {
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00001041 transposeMatrix<GLint,3,3,4,3>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12);
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00001042 }
1043 break;
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00001044 case GL_FLOAT_MAT4:
1045 {
1046 transposeMatrix<GLint,4,4,4,4>(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16);
1047 }
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00001048 break;
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00001049 default:
1050 {
daniel@transgaming.comedc31502011-11-12 03:14:56 +00001051 unsigned int count = UniformExternalComponentCount(targetUniform->type);
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00001052 unsigned int internalCount = UniformInternalComponentCount(targetUniform->type);
1053
1054 switch (UniformComponentType(targetUniform->type))
1055 {
1056 case GL_BOOL:
1057 {
1058 GLboolean *boolParams = targetUniform->data + mUniformIndex[location].element * internalCount;
1059
1060 for (unsigned int i = 0; i < count; ++i)
1061 {
1062 params[i] = (GLint)boolParams[i];
1063 }
1064 }
1065 break;
1066 case GL_FLOAT:
1067 {
1068 GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * internalCount;
1069
1070 for (unsigned int i = 0; i < count; ++i)
1071 {
1072 params[i] = (GLint)floatParams[i];
1073 }
1074 }
1075 break;
1076 case GL_INT:
1077 memcpy(params, targetUniform->data + mUniformIndex[location].element * internalCount * sizeof(GLint),
1078 count * sizeof(GLint));
1079 break;
1080 default: UNREACHABLE();
1081 }
1082 }
daniel@transgaming.combb3d9d02010-04-13 03:26:06 +00001083 }
1084
1085 return true;
1086}
1087
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001088void ProgramBinary::dirtyAllUniforms()
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00001089{
daniel@transgaming.comd08ea902010-05-14 19:41:36 +00001090 unsigned int numUniforms = mUniforms.size();
1091 for (unsigned int index = 0; index < numUniforms; index++)
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00001092 {
1093 mUniforms[index]->dirty = true;
1094 }
1095}
1096
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001097// Applies all the uniforms set for this program object to the Direct3D 9 device
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001098void ProgramBinary::applyUniforms()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001099{
jbauman@chromium.orga28233e2011-10-12 16:51:33 +00001100 for (std::vector<Uniform*>::iterator ub = mUniforms.begin(), ue = mUniforms.end(); ub != ue; ++ub) {
1101 Uniform *targetUniform = *ub;
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00001102
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00001103 if (targetUniform->dirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001104 {
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00001105 int arraySize = targetUniform->arraySize;
1106 GLfloat *f = (GLfloat*)targetUniform->data;
1107 GLint *i = (GLint*)targetUniform->data;
1108 GLboolean *b = (GLboolean*)targetUniform->data;
1109
1110 switch (targetUniform->type)
1111 {
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00001112 case GL_BOOL: applyUniformnbv(targetUniform, arraySize, 1, b); break;
1113 case GL_BOOL_VEC2: applyUniformnbv(targetUniform, arraySize, 2, b); break;
1114 case GL_BOOL_VEC3: applyUniformnbv(targetUniform, arraySize, 3, b); break;
1115 case GL_BOOL_VEC4: applyUniformnbv(targetUniform, arraySize, 4, b); break;
1116 case GL_FLOAT:
1117 case GL_FLOAT_VEC2:
1118 case GL_FLOAT_VEC3:
1119 case GL_FLOAT_VEC4:
1120 case GL_FLOAT_MAT2:
1121 case GL_FLOAT_MAT3:
1122 case GL_FLOAT_MAT4: applyUniformnfv(targetUniform, f); break;
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +00001123 case GL_SAMPLER_2D:
1124 case GL_SAMPLER_CUBE:
jbauman@chromium.orga28233e2011-10-12 16:51:33 +00001125 case GL_INT: applyUniform1iv(targetUniform, arraySize, i); break;
1126 case GL_INT_VEC2: applyUniform2iv(targetUniform, arraySize, i); break;
1127 case GL_INT_VEC3: applyUniform3iv(targetUniform, arraySize, i); break;
1128 case GL_INT_VEC4: applyUniform4iv(targetUniform, arraySize, i); break;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00001129 default:
1130 UNREACHABLE();
1131 }
1132
1133 targetUniform->dirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001134 }
1135 }
1136}
1137
1138// Compiles the HLSL code of the attached shaders into executable binaries
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001139ID3D10Blob *ProgramBinary::compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001140{
1141 if (!hlsl)
1142 {
1143 return NULL;
1144 }
1145
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00001146 DWORD result;
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001147 UINT flags = 0;
1148 std::string sourceText;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00001149 if (perfActive())
1150 {
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001151 flags |= D3DCOMPILE_DEBUG;
1152#ifdef NDEBUG
1153 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
1154#else
1155 flags |= D3DCOMPILE_SKIP_OPTIMIZATION;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00001156#endif
1157
1158 std::string sourcePath = getTempPath();
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001159 sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl);
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00001160 writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size());
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00001161 }
1162 else
1163 {
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001164 flags |= ANGLE_COMPILE_OPTIMIZATION_LEVEL;
1165 sourceText = hlsl;
apatrick@chromium.org0f4cefe2011-01-26 19:30:57 +00001166 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001167
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001168 ID3D10Blob *binary = NULL;
1169 ID3D10Blob *errorMessage = NULL;
daniel@transgaming.com8a4dad62011-09-13 00:54:40 +00001170 result = D3DCompile(hlsl, strlen(hlsl), fakepath, NULL, NULL, "main", profile, flags, 0, &binary, &errorMessage);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001171
1172 if (errorMessage)
1173 {
1174 const char *message = (const char*)errorMessage->GetBufferPointer();
daniel@transgaming.comcba50572010-03-28 19:36:09 +00001175
daniel@transgaming.com87891f72011-06-01 15:28:35 +00001176 appendToInfoLogSanitized(message);
daniel@transgaming.com0599dc62010-03-21 04:31:36 +00001177 TRACE("\n%s", hlsl);
1178 TRACE("\n%s", message);
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001179
1180 errorMessage->Release();
1181 errorMessage = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001182 }
1183
apatrick@chromium.org8ea5afe2011-03-23 20:44:36 +00001184 if (FAILED(result))
1185 {
1186 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1187 {
1188 error(GL_OUT_OF_MEMORY);
1189 }
1190
1191 return NULL;
1192 }
1193
1194 result = D3DXGetShaderConstantTable(static_cast<const DWORD*>(binary->GetBufferPointer()), constantTable);
1195
1196 if (FAILED(result))
1197 {
1198 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1199 {
1200 error(GL_OUT_OF_MEMORY);
1201 }
1202
1203 binary->Release();
1204
1205 return NULL;
1206 }
1207
1208 return binary;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001209}
1210
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001211// Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
1212// Returns the number of used varying registers, or -1 if unsuccesful
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001213int ProgramBinary::packVaryings(const Varying *packing[][4], FragmentShader *fragmentShader)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001214{
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001215 Context *context = getContext();
1216 const int maxVaryingVectors = context->getMaximumVaryingVectors();
1217
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001218 for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001219 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001220 int n = VariableRowCount(varying->type) * varying->size;
1221 int m = VariableColumnCount(varying->type);
1222 bool success = false;
daniel@transgaming.com51d0dc22010-04-29 03:39:11 +00001223
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001224 if (m == 2 || m == 3 || m == 4)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001225 {
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001226 for (int r = 0; r <= maxVaryingVectors - n && !success; r++)
daniel@transgaming.com51d0dc22010-04-29 03:39:11 +00001227 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001228 bool available = true;
1229
1230 for (int y = 0; y < n && available; y++)
1231 {
1232 for (int x = 0; x < m && available; x++)
1233 {
1234 if (packing[r + y][x])
1235 {
1236 available = false;
1237 }
1238 }
1239 }
1240
1241 if (available)
1242 {
1243 varying->reg = r;
1244 varying->col = 0;
1245
1246 for (int y = 0; y < n; y++)
1247 {
1248 for (int x = 0; x < m; x++)
1249 {
1250 packing[r + y][x] = &*varying;
1251 }
1252 }
1253
1254 success = true;
1255 }
daniel@transgaming.com51d0dc22010-04-29 03:39:11 +00001256 }
1257
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001258 if (!success && m == 2)
1259 {
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001260 for (int r = maxVaryingVectors - n; r >= 0 && !success; r--)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001261 {
1262 bool available = true;
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001263
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001264 for (int y = 0; y < n && available; y++)
1265 {
1266 for (int x = 2; x < 4 && available; x++)
1267 {
1268 if (packing[r + y][x])
1269 {
1270 available = false;
1271 }
1272 }
1273 }
1274
1275 if (available)
1276 {
1277 varying->reg = r;
1278 varying->col = 2;
1279
1280 for (int y = 0; y < n; y++)
1281 {
1282 for (int x = 2; x < 4; x++)
1283 {
1284 packing[r + y][x] = &*varying;
1285 }
1286 }
1287
1288 success = true;
1289 }
1290 }
1291 }
1292 }
1293 else if (m == 1)
1294 {
1295 int space[4] = {0};
1296
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001297 for (int y = 0; y < maxVaryingVectors; y++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001298 {
1299 for (int x = 0; x < 4; x++)
1300 {
1301 space[x] += packing[y][x] ? 0 : 1;
1302 }
1303 }
1304
1305 int column = 0;
1306
1307 for (int x = 0; x < 4; x++)
1308 {
daniel@transgaming.com11dd5dd2011-02-11 13:28:14 +00001309 if (space[x] >= n && space[x] < space[column])
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001310 {
1311 column = x;
1312 }
1313 }
1314
daniel@transgaming.com11dd5dd2011-02-11 13:28:14 +00001315 if (space[column] >= n)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001316 {
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001317 for (int r = 0; r < maxVaryingVectors; r++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001318 {
1319 if (!packing[r][column])
1320 {
1321 varying->reg = r;
1322
1323 for (int y = r; y < r + n; y++)
1324 {
1325 packing[y][column] = &*varying;
1326 }
1327
1328 break;
1329 }
1330 }
1331
1332 varying->col = column;
1333
1334 success = true;
1335 }
1336 }
1337 else UNREACHABLE();
1338
1339 if (!success)
1340 {
1341 appendToInfoLog("Could not pack varying %s", varying->name.c_str());
1342
1343 return -1;
1344 }
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001345 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001346
1347 // Return the number of used registers
1348 int registers = 0;
1349
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001350 for (int r = 0; r < maxVaryingVectors; r++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001351 {
1352 if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
1353 {
1354 registers++;
1355 }
1356 }
1357
1358 return registers;
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001359}
1360
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001361bool ProgramBinary::linkVaryings(std::string& pixelHLSL, std::string& vertexHLSL, FragmentShader *fragmentShader, VertexShader *vertexShader)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001362{
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001363 if (pixelHLSL.empty() || vertexHLSL.empty())
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001364 {
1365 return false;
1366 }
1367
daniel@transgaming.com97750022011-02-11 13:23:13 +00001368 // Reset the varying register assignments
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001369 for (VaryingList::iterator fragVar = fragmentShader->mVaryings.begin(); fragVar != fragmentShader->mVaryings.end(); fragVar++)
daniel@transgaming.com97750022011-02-11 13:23:13 +00001370 {
1371 fragVar->reg = -1;
1372 fragVar->col = -1;
1373 }
1374
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001375 for (VaryingList::iterator vtxVar = vertexShader->mVaryings.begin(); vtxVar != vertexShader->mVaryings.end(); vtxVar++)
daniel@transgaming.com97750022011-02-11 13:23:13 +00001376 {
1377 vtxVar->reg = -1;
1378 vtxVar->col = -1;
1379 }
1380
1381 // Map the varyings to the register file
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001382 const Varying *packing[MAX_VARYING_VECTORS_SM3][4] = {NULL};
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001383 int registers = packVaryings(packing, fragmentShader);
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001384
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001385 if (registers < 0)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001386 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001387 return false;
1388 }
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001389
daniel@transgaming.com97750022011-02-11 13:23:13 +00001390 // Write the HLSL input/output declarations
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001391 Context *context = getContext();
1392 const bool sm3 = context->supportsShaderModel3();
1393 const int maxVaryingVectors = context->getMaximumVaryingVectors();
1394
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001395 if (registers == maxVaryingVectors && fragmentShader->mUsesFragCoord)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001396 {
1397 appendToInfoLog("No varying registers left to support gl_FragCoord");
1398
1399 return false;
1400 }
1401
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001402 for (VaryingList::iterator input = fragmentShader->mVaryings.begin(); input != fragmentShader->mVaryings.end(); input++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001403 {
1404 bool matched = false;
1405
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001406 for (VaryingList::iterator output = vertexShader->mVaryings.begin(); output != vertexShader->mVaryings.end(); output++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001407 {
1408 if (output->name == input->name)
1409 {
1410 if (output->type != input->type || output->size != input->size)
1411 {
1412 appendToInfoLog("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str());
1413
1414 return false;
1415 }
1416
1417 output->reg = input->reg;
1418 output->col = input->col;
1419
1420 matched = true;
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001421 break;
1422 }
1423 }
1424
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001425 if (!matched)
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001426 {
daniel@transgaming.com97750022011-02-11 13:23:13 +00001427 appendToInfoLog("Fragment varying %s does not match any vertex varying", input->name.c_str());
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001428
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001429 return false;
1430 }
1431 }
1432
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001433 std::string varyingSemantic = (sm3 ? "COLOR" : "TEXCOORD");
1434
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001435 vertexHLSL += "struct VS_INPUT\n"
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001436 "{\n";
1437
1438 int semanticIndex = 0;
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001439 for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001440 {
1441 switch (attribute->type)
1442 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001443 case GL_FLOAT: vertexHLSL += " float "; break;
1444 case GL_FLOAT_VEC2: vertexHLSL += " float2 "; break;
1445 case GL_FLOAT_VEC3: vertexHLSL += " float3 "; break;
1446 case GL_FLOAT_VEC4: vertexHLSL += " float4 "; break;
1447 case GL_FLOAT_MAT2: vertexHLSL += " float2x2 "; break;
1448 case GL_FLOAT_MAT3: vertexHLSL += " float3x3 "; break;
1449 case GL_FLOAT_MAT4: vertexHLSL += " float4x4 "; break;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001450 default: UNREACHABLE();
1451 }
1452
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001453 vertexHLSL += decorateAttribute(attribute->name) + " : TEXCOORD" + str(semanticIndex) + ";\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001454
1455 semanticIndex += VariableRowCount(attribute->type);
1456 }
1457
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001458 vertexHLSL += "};\n"
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001459 "\n"
1460 "struct VS_OUTPUT\n"
1461 "{\n"
1462 " float4 gl_Position : POSITION;\n";
1463
1464 for (int r = 0; r < registers; r++)
1465 {
1466 int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1));
1467
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001468 vertexHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001469 }
1470
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001471 if (fragmentShader->mUsesFragCoord)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001472 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001473 vertexHLSL += " float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001474 }
1475
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001476 if (vertexShader->mUsesPointSize && sm3)
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001477 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001478 vertexHLSL += " float gl_PointSize : PSIZE;\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001479 }
1480
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001481 vertexHLSL += "};\n"
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001482 "\n"
1483 "VS_OUTPUT main(VS_INPUT input)\n"
1484 "{\n";
1485
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001486 for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001487 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001488 vertexHLSL += " " + decorateAttribute(attribute->name) + " = ";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001489
1490 if (VariableRowCount(attribute->type) > 1) // Matrix
1491 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001492 vertexHLSL += "transpose";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001493 }
1494
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001495 vertexHLSL += "(input." + decorateAttribute(attribute->name) + ");\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001496 }
1497
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001498 vertexHLSL += "\n"
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001499 " gl_main();\n"
1500 "\n"
1501 " VS_OUTPUT output;\n"
1502 " output.gl_Position.x = gl_Position.x - dx_HalfPixelSize.x * gl_Position.w;\n"
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001503 " output.gl_Position.y = gl_Position.y - dx_HalfPixelSize.y * gl_Position.w;\n"
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001504 " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
1505 " output.gl_Position.w = gl_Position.w;\n";
1506
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001507 if (vertexShader->mUsesPointSize && sm3)
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001508 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001509 vertexHLSL += " output.gl_PointSize = clamp(gl_PointSize, 1.0, " + str((int)ALIASED_POINT_SIZE_RANGE_MAX_SM3) + ");\n";
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001510 }
1511
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001512 if (fragmentShader->mUsesFragCoord)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001513 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001514 vertexHLSL += " output.gl_FragCoord = gl_Position;\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001515 }
1516
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001517 for (VaryingList::iterator varying = vertexShader->mVaryings.begin(); varying != vertexShader->mVaryings.end(); varying++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001518 {
1519 if (varying->reg >= 0)
1520 {
1521 for (int i = 0; i < varying->size; i++)
1522 {
1523 int rows = VariableRowCount(varying->type);
1524
1525 for (int j = 0; j < rows; j++)
1526 {
1527 int r = varying->reg + i * rows + j;
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001528 vertexHLSL += " output.v" + str(r);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001529
1530 bool sharedRegister = false; // Register used by multiple varyings
1531
1532 for (int x = 0; x < 4; x++)
1533 {
1534 if (packing[r][x] && packing[r][x] != packing[r][0])
1535 {
1536 sharedRegister = true;
1537 break;
1538 }
1539 }
1540
1541 if(sharedRegister)
1542 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001543 vertexHLSL += ".";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001544
1545 for (int x = 0; x < 4; x++)
1546 {
1547 if (packing[r][x] == &*varying)
1548 {
1549 switch(x)
1550 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001551 case 0: vertexHLSL += "x"; break;
1552 case 1: vertexHLSL += "y"; break;
1553 case 2: vertexHLSL += "z"; break;
1554 case 3: vertexHLSL += "w"; break;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001555 }
1556 }
1557 }
1558 }
1559
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001560 vertexHLSL += " = " + varying->name;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001561
1562 if (varying->array)
1563 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001564 vertexHLSL += "[" + str(i) + "]";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001565 }
1566
1567 if (rows > 1)
1568 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001569 vertexHLSL += "[" + str(j) + "]";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001570 }
1571
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001572 vertexHLSL += ";\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001573 }
1574 }
1575 }
1576 }
1577
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001578 vertexHLSL += "\n"
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001579 " return output;\n"
1580 "}\n";
1581
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001582 pixelHLSL += "struct PS_INPUT\n"
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001583 "{\n";
1584
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001585 for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001586 {
1587 if (varying->reg >= 0)
1588 {
1589 for (int i = 0; i < varying->size; i++)
1590 {
1591 int rows = VariableRowCount(varying->type);
1592 for (int j = 0; j < rows; j++)
1593 {
1594 std::string n = str(varying->reg + i * rows + j);
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001595 pixelHLSL += " float4 v" + n + " : " + varyingSemantic + n + ";\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001596 }
1597 }
1598 }
1599 else UNREACHABLE();
1600 }
1601
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001602 if (fragmentShader->mUsesFragCoord)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001603 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001604 pixelHLSL += " float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001605 if (sm3) {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001606 pixelHLSL += " float2 dx_VPos : VPOS;\n";
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001607 }
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001608 }
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001609
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001610 if (fragmentShader->mUsesPointCoord && sm3)
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001611 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001612 pixelHLSL += " float2 gl_PointCoord : TEXCOORD0;\n";
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001613 }
1614
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001615 if (fragmentShader->mUsesFrontFacing)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001616 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001617 pixelHLSL += " float vFace : VFACE;\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001618 }
1619
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001620 pixelHLSL += "};\n"
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001621 "\n"
1622 "struct PS_OUTPUT\n"
1623 "{\n"
1624 " float4 gl_Color[1] : COLOR;\n"
1625 "};\n"
1626 "\n"
1627 "PS_OUTPUT main(PS_INPUT input)\n"
1628 "{\n";
1629
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001630 if (fragmentShader->mUsesFragCoord)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001631 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001632 pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n";
daniel@transgaming.comd9a54f92011-12-22 18:32:53 +00001633
1634 if (sm3)
1635 {
1636 // dx_Coord.y contains the render target height. See Context::applyRenderTarget()
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001637 pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x + 0.5;\n"
daniel@transgaming.comd9a54f92011-12-22 18:32:53 +00001638 " gl_FragCoord.y = dx_Coord.y - input.dx_VPos.y - 0.5;\n";
kbr@chromium.org72d58c42010-11-05 22:55:28 +00001639 }
daniel@transgaming.comd9a54f92011-12-22 18:32:53 +00001640 else
1641 {
1642 // dx_Coord contains the viewport width/2, height/2, center.x and center.y. See Context::applyRenderTarget()
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001643 pixelHLSL += " gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_Coord.x + dx_Coord.z;\n"
daniel@transgaming.comd9a54f92011-12-22 18:32:53 +00001644 " gl_FragCoord.y = -(input.gl_FragCoord.y * rhw) * dx_Coord.y + dx_Coord.w;\n";
1645 }
1646
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001647 pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_Depth.x + dx_Depth.y;\n"
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001648 " gl_FragCoord.w = rhw;\n";
1649 }
1650
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001651 if (fragmentShader->mUsesPointCoord && sm3)
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001652 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001653 pixelHLSL += " gl_PointCoord = input.gl_PointCoord;\n";
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001654 }
1655
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001656 if (fragmentShader->mUsesFrontFacing)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001657 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001658 pixelHLSL += " gl_FrontFacing = dx_PointsOrLines || (dx_FrontCCW ? (input.vFace >= 0.0) : (input.vFace <= 0.0));\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001659 }
1660
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001661 for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++)
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001662 {
1663 if (varying->reg >= 0)
1664 {
1665 for (int i = 0; i < varying->size; i++)
1666 {
1667 int rows = VariableRowCount(varying->type);
1668 for (int j = 0; j < rows; j++)
1669 {
1670 std::string n = str(varying->reg + i * rows + j);
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001671 pixelHLSL += " " + varying->name;
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001672
1673 if (varying->array)
1674 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001675 pixelHLSL += "[" + str(i) + "]";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001676 }
1677
1678 if (rows > 1)
1679 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001680 pixelHLSL += "[" + str(j) + "]";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001681 }
1682
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001683 pixelHLSL += " = input.v" + n + ";\n";
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001684 }
1685 }
1686 }
1687 else UNREACHABLE();
1688 }
1689
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001690 pixelHLSL += "\n"
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001691 " gl_main();\n"
1692 "\n"
1693 " PS_OUTPUT output;\n"
1694 " output.gl_Color[0] = gl_Color[0];\n"
1695 "\n"
1696 " return output;\n"
1697 "}\n";
1698
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001699 return true;
1700}
1701
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001702// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
1703// compiling them into binaries, determining the attribute mappings, and collecting
1704// a list of uniforms
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001705void Program::link()
1706{
1707 unlink(false);
1708
1709 mProgramBinary = new ProgramBinary;
1710 if (!mProgramBinary->link(mAttributeBindings, mFragmentShader, mVertexShader))
1711 {
1712 unlink(false);
1713 }
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001714}
1715
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001716bool ProgramBinary::link(const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001717{
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001718 if (!fragmentShader || !fragmentShader->isCompiled())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001719 {
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001720 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001721 }
1722
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001723 if (!vertexShader || !vertexShader->isCompiled())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001724 {
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001725 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001726 }
1727
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001728 std::string pixelHLSL = fragmentShader->getHLSL();
1729 std::string vertexHLSL = vertexShader->getHLSL();
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001730
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001731 if (!linkVaryings(pixelHLSL, vertexHLSL, fragmentShader, vertexShader))
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001732 {
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001733 return false;
daniel@transgaming.com0e3358a2010-04-05 20:32:42 +00001734 }
1735
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001736 Context *context = getContext();
1737 const char *vertexProfile = context->supportsShaderModel3() ? "vs_3_0" : "vs_2_0";
1738 const char *pixelProfile = context->supportsShaderModel3() ? "ps_3_0" : "ps_2_0";
1739
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001740 ID3D10Blob *vertexBinary = compileToBinary(vertexHLSL.c_str(), vertexProfile, &mConstantTableVS);
1741 ID3D10Blob *pixelBinary = compileToBinary(pixelHLSL.c_str(), pixelProfile, &mConstantTablePS);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001742
1743 if (vertexBinary && pixelBinary)
1744 {
daniel@transgaming.com96a4a6c2011-10-26 02:33:46 +00001745 HRESULT vertexResult = mDevice->CreateVertexShader((DWORD*)vertexBinary->GetBufferPointer(), &mVertexExecutable);
1746 HRESULT pixelResult = mDevice->CreatePixelShader((DWORD*)pixelBinary->GetBufferPointer(), &mPixelExecutable);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001747
1748 if (vertexResult == D3DERR_OUTOFVIDEOMEMORY || vertexResult == E_OUTOFMEMORY || pixelResult == D3DERR_OUTOFVIDEOMEMORY || pixelResult == E_OUTOFMEMORY)
1749 {
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001750 return error(GL_OUT_OF_MEMORY, false);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001751 }
1752
1753 ASSERT(SUCCEEDED(vertexResult) && SUCCEEDED(pixelResult));
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001754
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001755 vertexBinary->Release();
1756 pixelBinary->Release();
1757 vertexBinary = NULL;
1758 pixelBinary = NULL;
1759
1760 if (mVertexExecutable && mPixelExecutable)
1761 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001762 if (!linkAttributes(attributeBindings, fragmentShader, vertexShader))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001763 {
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001764 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001765 }
1766
daniel@transgaming.comf5c8a2e2012-06-05 19:51:43 +00001767 if (!linkUniforms(GL_FRAGMENT_SHADER, mConstantTablePS))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001768 {
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001769 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001770 }
1771
daniel@transgaming.comf5c8a2e2012-06-05 19:51:43 +00001772 if (!linkUniforms(GL_VERTEX_SHADER, mConstantTableVS))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001773 {
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001774 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001775 }
1776
daniel@transgaming.coma3bbfd42010-06-07 02:06:09 +00001777 // these uniforms are searched as already-decorated because gl_ and dx_
1778 // are reserved prefixes, and do not receive additional decoration
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001779 mDxDepthRangeLocation = getUniformLocation("dx_DepthRange");
1780 mDxDepthLocation = getUniformLocation("dx_Depth");
daniel@transgaming.comd9a54f92011-12-22 18:32:53 +00001781 mDxCoordLocation = getUniformLocation("dx_Coord");
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001782 mDxHalfPixelSizeLocation = getUniformLocation("dx_HalfPixelSize");
1783 mDxFrontCCWLocation = getUniformLocation("dx_FrontCCW");
1784 mDxPointsOrLinesLocation = getUniformLocation("dx_PointsOrLines");
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001785
daniel@transgaming.com11399d52012-04-28 00:35:14 +00001786 context->markDxUniformsDirty();
1787
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001788 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001789 }
1790 }
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001791
1792 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001793}
1794
1795// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001796bool ProgramBinary::linkAttributes(const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001797{
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001798 unsigned int usedLocations = 0;
1799
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001800 // Link attributes that have a binding location
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001801 for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001802 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001803 int location = attributeBindings.getAttributeBinding(attribute->name);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001804
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001805 if (location != -1) // Set by glBindAttribLocation
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001806 {
daniel@transgaming.com85423182010-04-22 13:35:27 +00001807 if (!mLinkedAttribute[location].name.empty())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001808 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001809 // Multiple active attributes bound to the same location; not an error
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001810 }
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001811
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001812 mLinkedAttribute[location] = *attribute;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001813
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001814 int rows = VariableRowCount(attribute->type);
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001815
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001816 if (rows + location > MAX_VERTEX_ATTRIBS)
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001817 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001818 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 +00001819
1820 return false;
1821 }
1822
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001823 for (int i = 0; i < rows; i++)
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001824 {
1825 usedLocations |= 1 << (location + i);
1826 }
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001827 }
1828 }
1829
1830 // Link attributes that don't have a binding location
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001831 for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++)
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001832 {
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001833 int location = attributeBindings.getAttributeBinding(attribute->name);
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001834
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001835 if (location == -1) // Not set by glBindAttribLocation
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001836 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001837 int rows = VariableRowCount(attribute->type);
1838 int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001839
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001840 if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001841 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001842 appendToInfoLog("Too many active attributes (%s)", attribute->name.c_str());
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001843
1844 return false; // Fail to link
1845 }
1846
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001847 mLinkedAttribute[availableIndex] = *attribute;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001848 }
1849 }
1850
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001851 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001852 {
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001853 int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001854 int rows = std::max(VariableRowCount(mLinkedAttribute[attributeIndex].type), 1);
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001855
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001856 for (int r = 0; r < rows; r++)
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001857 {
daniel@transgaming.com4af7acc2010-05-14 17:30:53 +00001858 mSemanticIndex[attributeIndex++] = index++;
daniel@transgaming.com0b6b8342010-04-26 15:33:45 +00001859 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001860 }
1861
1862 return true;
1863}
1864
apatrick@chromium.org9a30b092012-06-06 20:21:55 +00001865int AttributeBindings::getAttributeBinding(const std::string &name) const
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001866{
1867 for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
1868 {
1869 if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
1870 {
1871 return location;
1872 }
1873 }
1874
1875 return -1;
1876}
1877
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001878bool ProgramBinary::linkUniforms(GLenum shader, ID3DXConstantTable *constantTable)
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001879{
1880 D3DXCONSTANTTABLE_DESC constantTableDescription;
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001881
1882 constantTable->GetDesc(&constantTableDescription);
1883
1884 for (unsigned int constantIndex = 0; constantIndex < constantTableDescription.Constants; constantIndex++)
1885 {
1886 D3DXHANDLE constantHandle = constantTable->GetConstant(0, constantIndex);
daniel@transgaming.comf5c8a2e2012-06-05 19:51:43 +00001887
1888 D3DXCONSTANT_DESC constantDescription;
1889 UINT descriptionCount = 1;
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001890 HRESULT result = constantTable->GetConstantDesc(constantHandle, &constantDescription, &descriptionCount);
1891 ASSERT(SUCCEEDED(result));
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001892
daniel@transgaming.comf5c8a2e2012-06-05 19:51:43 +00001893 if (!defineUniform(shader, constantHandle, constantDescription))
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001894 {
1895 return false;
1896 }
1897 }
1898
1899 return true;
1900}
1901
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001902// Adds the description of a constant found in the binary shader to the list of uniforms
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001903// Returns true if succesful (uniform not already defined)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001904bool ProgramBinary::defineUniform(GLenum shader, const D3DXHANDLE &constantHandle, const D3DXCONSTANT_DESC &constantDescription, std::string name)
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001905{
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001906 if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
1907 {
daniel@transgaming.comc3336992011-11-14 21:15:45 +00001908 for (unsigned int i = 0; i < constantDescription.RegisterCount; i++)
daniel@transgaming.com41b2fbd2010-12-13 18:27:12 +00001909 {
daniel@transgaming.comc3336992011-11-14 21:15:45 +00001910 D3DXHANDLE psConstant = mConstantTablePS->GetConstantByName(NULL, constantDescription.Name);
1911 D3DXHANDLE vsConstant = mConstantTableVS->GetConstantByName(NULL, constantDescription.Name);
1912
1913 if (psConstant)
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001914 {
daniel@transgaming.comc3336992011-11-14 21:15:45 +00001915 unsigned int samplerIndex = mConstantTablePS->GetSamplerIndex(psConstant) + i;
1916
daniel@transgaming.com424bb492011-05-11 15:36:59 +00001917 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
1918 {
1919 mSamplersPS[samplerIndex].active = true;
1920 mSamplersPS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
1921 mSamplersPS[samplerIndex].logicalTextureUnit = 0;
jbauman@chromium.orgb6e72222011-10-18 23:01:46 +00001922 mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange);
daniel@transgaming.com424bb492011-05-11 15:36:59 +00001923 }
1924 else
1925 {
1926 appendToInfoLog("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
1927 return false;
1928 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001929 }
1930
daniel@transgaming.comc3336992011-11-14 21:15:45 +00001931 if (vsConstant)
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001932 {
daniel@transgaming.comc3336992011-11-14 21:15:45 +00001933 unsigned int samplerIndex = mConstantTableVS->GetSamplerIndex(vsConstant) + i;
1934
daniel@transgaming.com424bb492011-05-11 15:36:59 +00001935 if (samplerIndex < getContext()->getMaximumVertexTextureImageUnits())
1936 {
1937 mSamplersVS[samplerIndex].active = true;
1938 mSamplersVS[samplerIndex].textureType = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? TEXTURE_CUBE : TEXTURE_2D;
1939 mSamplersVS[samplerIndex].logicalTextureUnit = 0;
jbauman@chromium.orgb6e72222011-10-18 23:01:46 +00001940 mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange);
daniel@transgaming.com424bb492011-05-11 15:36:59 +00001941 }
1942 else
1943 {
1944 appendToInfoLog("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", getContext()->getMaximumVertexTextureImageUnits());
1945 return false;
1946 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001947 }
daniel@transgaming.com41b2fbd2010-12-13 18:27:12 +00001948 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001949 }
1950
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001951 switch(constantDescription.Class)
1952 {
1953 case D3DXPC_STRUCT:
1954 {
daniel@transgaming.comce864422010-11-18 13:16:49 +00001955 for (unsigned int arrayIndex = 0; arrayIndex < constantDescription.Elements; arrayIndex++)
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001956 {
daniel@transgaming.comce864422010-11-18 13:16:49 +00001957 for (unsigned int field = 0; field < constantDescription.StructMembers; field++)
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001958 {
daniel@transgaming.comce864422010-11-18 13:16:49 +00001959 D3DXHANDLE fieldHandle = mConstantTablePS->GetConstant(constantHandle, field);
1960
1961 D3DXCONSTANT_DESC fieldDescription;
1962 UINT descriptionCount = 1;
1963
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00001964 HRESULT result = mConstantTablePS->GetConstantDesc(fieldHandle, &fieldDescription, &descriptionCount);
1965 ASSERT(SUCCEEDED(result));
daniel@transgaming.comce864422010-11-18 13:16:49 +00001966
1967 std::string structIndex = (constantDescription.Elements > 1) ? ("[" + str(arrayIndex) + "]") : "";
1968
daniel@transgaming.comf5c8a2e2012-06-05 19:51:43 +00001969 if (!defineUniform(shader, fieldHandle, fieldDescription, name + constantDescription.Name + structIndex + "."))
daniel@transgaming.comce864422010-11-18 13:16:49 +00001970 {
1971 return false;
1972 }
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001973 }
1974 }
1975
1976 return true;
1977 }
1978 case D3DXPC_SCALAR:
1979 case D3DXPC_VECTOR:
1980 case D3DXPC_MATRIX_COLUMNS:
1981 case D3DXPC_OBJECT:
daniel@transgaming.comf5c8a2e2012-06-05 19:51:43 +00001982 return defineUniform(shader, constantDescription, name + constantDescription.Name);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001983 default:
1984 UNREACHABLE();
1985 return false;
1986 }
1987}
1988
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00001989bool ProgramBinary::defineUniform(GLenum shader, const D3DXCONSTANT_DESC &constantDescription, const std::string &_name)
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001990{
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001991 Uniform *uniform = createUniform(constantDescription, _name);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001992
1993 if(!uniform)
1994 {
1995 return false;
1996 }
1997
1998 // Check if already defined
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00001999 GLint location = getUniformLocation(uniform->name);
daniel@transgaming.com0361b922010-03-28 19:36:15 +00002000 GLenum type = uniform->type;
daniel@transgaming.comc7d8a932010-03-16 06:16:45 +00002001
daniel@transgaming.com86487c22010-03-11 19:41:43 +00002002 if (location >= 0)
2003 {
2004 delete uniform;
daniel@transgaming.comec909fc2012-06-05 19:51:49 +00002005 uniform = mUniforms[mUniformIndex[location].index];
daniel@transgaming.com86487c22010-03-11 19:41:43 +00002006 }
2007
daniel@transgaming.comf5c8a2e2012-06-05 19:51:43 +00002008 if (shader == GL_FRAGMENT_SHADER) uniform->ps.set(constantDescription);
2009 if (shader == GL_VERTEX_SHADER) uniform->vs.set(constantDescription);
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002010
daniel@transgaming.comec909fc2012-06-05 19:51:49 +00002011 if (location >= 0)
2012 {
2013 return uniform->type == type;
2014 }
2015
daniel@transgaming.com86487c22010-03-11 19:41:43 +00002016 mUniforms.push_back(uniform);
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002017 unsigned int uniformIndex = mUniforms.size() - 1;
2018
2019 for (unsigned int i = 0; i < uniform->arraySize; ++i)
2020 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00002021 mUniformIndex.push_back(UniformLocation(_name, i, uniformIndex));
daniel@transgaming.com916ffaa2010-04-23 18:34:52 +00002022 }
daniel@transgaming.com86487c22010-03-11 19:41:43 +00002023
2024 return true;
2025}
2026
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002027Uniform *ProgramBinary::createUniform(const D3DXCONSTANT_DESC &constantDescription, const std::string &_name)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002028{
2029 if (constantDescription.Rows == 1) // Vectors and scalars
2030 {
2031 switch (constantDescription.Type)
2032 {
2033 case D3DXPT_SAMPLER2D:
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +00002034 switch (constantDescription.Columns)
2035 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00002036 case 1: return new Uniform(GL_SAMPLER_2D, _name, constantDescription.Elements);
daniel@transgaming.coma9cd70a2010-09-15 15:48:57 +00002037 default: UNREACHABLE();
2038 }
2039 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002040 case D3DXPT_SAMPLERCUBE:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002041 switch (constantDescription.Columns)
2042 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00002043 case 1: return new Uniform(GL_SAMPLER_CUBE, _name, constantDescription.Elements);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002044 default: UNREACHABLE();
2045 }
2046 break;
2047 case D3DXPT_BOOL:
2048 switch (constantDescription.Columns)
2049 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00002050 case 1: return new Uniform(GL_BOOL, _name, constantDescription.Elements);
2051 case 2: return new Uniform(GL_BOOL_VEC2, _name, constantDescription.Elements);
2052 case 3: return new Uniform(GL_BOOL_VEC3, _name, constantDescription.Elements);
2053 case 4: return new Uniform(GL_BOOL_VEC4, _name, constantDescription.Elements);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002054 default: UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002055 }
2056 break;
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002057 case D3DXPT_INT:
2058 switch (constantDescription.Columns)
2059 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00002060 case 1: return new Uniform(GL_INT, _name, constantDescription.Elements);
2061 case 2: return new Uniform(GL_INT_VEC2, _name, constantDescription.Elements);
2062 case 3: return new Uniform(GL_INT_VEC3, _name, constantDescription.Elements);
2063 case 4: return new Uniform(GL_INT_VEC4, _name, constantDescription.Elements);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002064 default: UNREACHABLE();
2065 }
2066 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002067 case D3DXPT_FLOAT:
2068 switch (constantDescription.Columns)
2069 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00002070 case 1: return new Uniform(GL_FLOAT, _name, constantDescription.Elements);
2071 case 2: return new Uniform(GL_FLOAT_VEC2, _name, constantDescription.Elements);
2072 case 3: return new Uniform(GL_FLOAT_VEC3, _name, constantDescription.Elements);
2073 case 4: return new Uniform(GL_FLOAT_VEC4, _name, constantDescription.Elements);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002074 default: UNREACHABLE();
2075 }
2076 break;
2077 default:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002078 UNREACHABLE();
2079 }
2080 }
2081 else if (constantDescription.Rows == constantDescription.Columns) // Square matrices
2082 {
2083 switch (constantDescription.Type)
2084 {
2085 case D3DXPT_FLOAT:
2086 switch (constantDescription.Rows)
2087 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00002088 case 2: return new Uniform(GL_FLOAT_MAT2, _name, constantDescription.Elements);
2089 case 3: return new Uniform(GL_FLOAT_MAT3, _name, constantDescription.Elements);
2090 case 4: return new Uniform(GL_FLOAT_MAT4, _name, constantDescription.Elements);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002091 default: UNREACHABLE();
2092 }
2093 break;
2094 default: UNREACHABLE();
2095 }
2096 }
2097 else UNREACHABLE();
daniel@transgaming.com86487c22010-03-11 19:41:43 +00002098
2099 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002100}
2101
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00002102// This method needs to match OutputHLSL::decorate
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002103std::string ProgramBinary::decorateAttribute(const std::string &name)
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00002104{
daniel@transgaming.com51db7fb2011-09-20 16:11:06 +00002105 if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0)
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00002106 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00002107 return "_" + name;
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00002108 }
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00002109
2110 return name;
daniel@transgaming.com72d0b522010-04-13 19:53:44 +00002111}
2112
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002113std::string ProgramBinary::undecorateUniform(const std::string &_name)
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00002114{
daniel@transgaming.com2e793f02012-04-11 19:41:35 +00002115 std::string name = _name;
2116
2117 // Remove any structure field decoration
2118 size_t pos = 0;
2119 while ((pos = name.find("._", pos)) != std::string::npos)
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00002120 {
daniel@transgaming.com2e793f02012-04-11 19:41:35 +00002121 name.replace(pos, 2, ".");
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00002122 }
daniel@transgaming.com2e793f02012-04-11 19:41:35 +00002123
2124 // Remove the leading decoration
2125 if (name[0] == '_')
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00002126 {
daniel@transgaming.com2e793f02012-04-11 19:41:35 +00002127 return name.substr(1);
2128 }
2129 else if (name.compare(0, 3, "ar_") == 0)
2130 {
2131 return name.substr(3);
daniel@transgaming.comc72c6412011-09-20 16:09:17 +00002132 }
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00002133
daniel@transgaming.com2e793f02012-04-11 19:41:35 +00002134 return name;
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00002135}
2136
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002137void ProgramBinary::applyUniformnbv(Uniform *targetUniform, GLsizei count, int width, const GLboolean *v)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002138{
jbauman@chromium.orge0f059c2012-01-24 23:21:52 +00002139 float vector[D3D9_MAX_FLOAT_CONSTANTS * 4];
2140 BOOL boolVector[D3D9_MAX_BOOL_CONSTANTS];
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002141
daniel@transgaming.com28be96b2012-06-05 19:51:46 +00002142 if (targetUniform->ps.float4Index >= 0 || targetUniform->vs.float4Index >= 0)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002143 {
jbauman@chromium.orge0f059c2012-01-24 23:21:52 +00002144 ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002145 for (int i = 0; i < count; i++)
2146 {
2147 for (int j = 0; j < 4; j++)
2148 {
2149 if (j < width)
2150 {
2151 vector[i * 4 + j] = (v[i * width + j] == GL_FALSE) ? 0.0f : 1.0f;
2152 }
2153 else
2154 {
2155 vector[i * 4 + j] = 0.0f;
2156 }
2157 }
2158 }
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002159 }
2160
daniel@transgaming.com28be96b2012-06-05 19:51:46 +00002161 if (targetUniform->ps.boolIndex >= 0 || targetUniform->vs.boolIndex >= 0)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002162 {
daniel@transgaming.comea7c3452012-06-05 19:51:40 +00002163 int psCount = targetUniform->ps.boolIndex >= 0 ? targetUniform->ps.registerCount : 0;
2164 int vsCount = targetUniform->vs.boolIndex >= 0 ? targetUniform->vs.registerCount : 0;
jbauman@chromium.orge0f059c2012-01-24 23:21:52 +00002165 int copyCount = std::min(count * width, std::max(psCount, vsCount));
2166 ASSERT(copyCount <= D3D9_MAX_BOOL_CONSTANTS);
2167 for (int i = 0; i < copyCount; i++)
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002168 {
2169 boolVector[i] = v[i] != GL_FALSE;
2170 }
2171 }
2172
daniel@transgaming.com28be96b2012-06-05 19:51:46 +00002173 if (targetUniform->ps.float4Index >= 0)
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002174 {
daniel@transgaming.com28be96b2012-06-05 19:51:46 +00002175 mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, vector, targetUniform->ps.registerCount);
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002176 }
daniel@transgaming.comea7c3452012-06-05 19:51:40 +00002177
daniel@transgaming.com28be96b2012-06-05 19:51:46 +00002178 if (targetUniform->ps.boolIndex >= 0)
2179 {
2180 mDevice->SetPixelShaderConstantB(targetUniform->ps.boolIndex, boolVector, targetUniform->ps.registerCount);
2181 }
2182
2183 if (targetUniform->vs.float4Index >= 0)
2184 {
2185 mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, vector, targetUniform->vs.registerCount);
2186 }
2187
2188 if (targetUniform->vs.boolIndex >= 0)
2189 {
2190 mDevice->SetVertexShaderConstantB(targetUniform->vs.boolIndex, boolVector, targetUniform->vs.registerCount);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002191 }
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002192}
2193
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002194bool ProgramBinary::applyUniformnfv(Uniform *targetUniform, const GLfloat *v)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002195{
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002196 if (targetUniform->ps.registerCount)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002197 {
daniel@transgaming.comea7c3452012-06-05 19:51:40 +00002198 mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, v, targetUniform->ps.registerCount);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002199 }
2200
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002201 if (targetUniform->vs.registerCount)
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002202 {
daniel@transgaming.comea7c3452012-06-05 19:51:40 +00002203 mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, v, targetUniform->vs.registerCount);
daniel@transgaming.comf4a0c8e2010-04-13 03:26:01 +00002204 }
2205
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002206 return true;
2207}
2208
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002209bool ProgramBinary::applyUniform1iv(Uniform *targetUniform, GLsizei count, const GLint *v)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002210{
jbauman@chromium.orge0f059c2012-01-24 23:21:52 +00002211 ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
2212 D3DXVECTOR4 vector[D3D9_MAX_FLOAT_CONSTANTS];
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002213
2214 for (int i = 0; i < count; i++)
2215 {
2216 vector[i] = D3DXVECTOR4((float)v[i], 0, 0, 0);
2217 }
2218
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002219 if (targetUniform->ps.registerCount)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002220 {
daniel@transgaming.comea7c3452012-06-05 19:51:40 +00002221 if (targetUniform->ps.samplerIndex >= 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002222 {
daniel@transgaming.comea7c3452012-06-05 19:51:40 +00002223 unsigned int firstIndex = targetUniform->ps.samplerIndex;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002224
daniel@transgaming.coma41e6e32010-12-15 15:45:30 +00002225 for (int i = 0; i < count; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002226 {
daniel@transgaming.coma41e6e32010-12-15 15:45:30 +00002227 unsigned int samplerIndex = firstIndex + i;
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002228
daniel@transgaming.coma41e6e32010-12-15 15:45:30 +00002229 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002230 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002231 ASSERT(mSamplersPS[samplerIndex].active);
2232 mSamplersPS[samplerIndex].logicalTextureUnit = v[i];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002233 }
2234 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002235 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002236 else
2237 {
daniel@transgaming.comea7c3452012-06-05 19:51:40 +00002238 ASSERT(targetUniform->ps.float4Index >= 0);
2239 mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, (const float*)vector, targetUniform->ps.registerCount);
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002240 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002241 }
2242
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002243 if (targetUniform->vs.registerCount)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002244 {
daniel@transgaming.comea7c3452012-06-05 19:51:40 +00002245 if (targetUniform->vs.samplerIndex >= 0)
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002246 {
daniel@transgaming.comea7c3452012-06-05 19:51:40 +00002247 unsigned int firstIndex = targetUniform->vs.samplerIndex;
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002248
2249 for (int i = 0; i < count; i++)
2250 {
2251 unsigned int samplerIndex = firstIndex + i;
2252
2253 if (samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF)
2254 {
2255 ASSERT(mSamplersVS[samplerIndex].active);
2256 mSamplersVS[samplerIndex].logicalTextureUnit = v[i];
2257 }
2258 }
2259 }
2260 else
2261 {
daniel@transgaming.comea7c3452012-06-05 19:51:40 +00002262 ASSERT(targetUniform->vs.float4Index >= 0);
2263 mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, (const float *)vector, targetUniform->vs.registerCount);
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002264 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002265 }
2266
2267 return true;
2268}
2269
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002270bool ProgramBinary::applyUniform2iv(Uniform *targetUniform, GLsizei count, const GLint *v)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002271{
jbauman@chromium.orge0f059c2012-01-24 23:21:52 +00002272 ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
2273 D3DXVECTOR4 vector[D3D9_MAX_FLOAT_CONSTANTS];
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002274
2275 for (int i = 0; i < count; i++)
2276 {
2277 vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], 0, 0);
2278
2279 v += 2;
2280 }
2281
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002282 applyUniformniv(targetUniform, count, vector);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002283
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002284 return true;
2285}
2286
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002287bool ProgramBinary::applyUniform3iv(Uniform *targetUniform, GLsizei count, const GLint *v)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002288{
jbauman@chromium.orge0f059c2012-01-24 23:21:52 +00002289 ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
2290 D3DXVECTOR4 vector[D3D9_MAX_FLOAT_CONSTANTS];
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002291
2292 for (int i = 0; i < count; i++)
2293 {
2294 vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], (float)v[2], 0);
2295
2296 v += 3;
2297 }
2298
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002299 applyUniformniv(targetUniform, count, vector);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002300
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002301 return true;
2302}
2303
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002304bool ProgramBinary::applyUniform4iv(Uniform *targetUniform, GLsizei count, const GLint *v)
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002305{
jbauman@chromium.orge0f059c2012-01-24 23:21:52 +00002306 ASSERT(count <= D3D9_MAX_FLOAT_CONSTANTS);
2307 D3DXVECTOR4 vector[D3D9_MAX_FLOAT_CONSTANTS];
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002308
2309 for (int i = 0; i < count; i++)
2310 {
2311 vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], (float)v[2], (float)v[3]);
2312
2313 v += 4;
2314 }
2315
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002316 applyUniformniv(targetUniform, count, vector);
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002317
daniel@transgaming.com9a95e2b2010-04-13 03:26:03 +00002318 return true;
2319}
2320
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002321void ProgramBinary::applyUniformniv(Uniform *targetUniform, GLsizei count, const D3DXVECTOR4 *vector)
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002322{
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002323 if (targetUniform->ps.registerCount)
2324 {
daniel@transgaming.comea7c3452012-06-05 19:51:40 +00002325 ASSERT(targetUniform->ps.float4Index >= 0);
2326 mDevice->SetPixelShaderConstantF(targetUniform->ps.float4Index, (const float *)vector, targetUniform->ps.registerCount);
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002327 }
2328
2329 if (targetUniform->vs.registerCount)
2330 {
daniel@transgaming.comea7c3452012-06-05 19:51:40 +00002331 ASSERT(targetUniform->vs.float4Index >= 0);
2332 mDevice->SetVertexShaderConstantF(targetUniform->vs.float4Index, (const float *)vector, targetUniform->vs.registerCount);
jbauman@chromium.org72e8f442011-10-20 00:22:01 +00002333 }
2334}
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002335
2336// append a santized message to the program info log.
daniel@transgaming.com8a4dad62011-09-13 00:54:40 +00002337// The D3D compiler includes a fake file path in some of the warning or error
2338// messages, so lets remove all occurrences of this fake file path from the log.
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002339void ProgramBinary::appendToInfoLogSanitized(const char *message)
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002340{
2341 std::string msg(message);
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002342
daniel@transgaming.com8a4dad62011-09-13 00:54:40 +00002343 size_t found;
2344 do
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002345 {
daniel@transgaming.com8a4dad62011-09-13 00:54:40 +00002346 found = msg.find(fakepath);
2347 if (found != std::string::npos)
2348 {
2349 msg.erase(found, strlen(fakepath));
2350 }
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002351 }
daniel@transgaming.com8a4dad62011-09-13 00:54:40 +00002352 while (found != std::string::npos);
daniel@transgaming.com87891f72011-06-01 15:28:35 +00002353
2354 appendToInfoLog("%s\n", msg.c_str());
2355}
2356
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002357void ProgramBinary::appendToInfoLog(const char *format, ...)
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002358{
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002359 if (!format)
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002360 {
2361 return;
2362 }
2363
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00002364 char info[1024];
2365
2366 va_list vararg;
2367 va_start(vararg, format);
2368 vsnprintf(info, sizeof(info), format, vararg);
2369 va_end(vararg);
2370
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002371 size_t infoLength = strlen(info);
2372
2373 if (!mInfoLog)
2374 {
2375 mInfoLog = new char[infoLength + 1];
2376 strcpy(mInfoLog, info);
2377 }
2378 else
2379 {
2380 size_t logLength = strlen(mInfoLog);
2381 char *newLog = new char[logLength + infoLength + 1];
2382 strcpy(newLog, mInfoLog);
2383 strcpy(newLog + logLength, info);
2384
2385 delete[] mInfoLog;
2386 mInfoLog = newLog;
2387 }
2388}
2389
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002390void ProgramBinary::resetInfoLog()
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002391{
2392 if (mInfoLog)
2393 {
2394 delete [] mInfoLog;
daniel@transgaming.com6a20d102010-08-31 13:54:27 +00002395 mInfoLog = NULL;
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002396 }
2397}
2398
daniel@transgaming.comaa5e59b2011-10-04 18:43:12 +00002399// Returns the program object to an unlinked state, before re-linking, or at destruction
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002400void Program::unlink(bool destroy)
2401{
2402 if (destroy) // Object being destructed
2403 {
2404 if (mFragmentShader)
2405 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002406 mFragmentShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002407 mFragmentShader = NULL;
2408 }
2409
2410 if (mVertexShader)
2411 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002412 mVertexShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002413 mVertexShader = NULL;
2414 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002415 }
2416
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002417 if (mProgramBinary)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002418 {
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002419 delete mProgramBinary;
2420 mProgramBinary = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002421 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002422}
2423
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002424ProgramBinary* Program::getProgramBinary()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002425{
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002426 return mProgramBinary;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002427}
2428
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002429bool ProgramBinary::isValidated() const
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002430{
2431 return mValidated;
2432}
2433
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002434void Program::release()
2435{
2436 mRefCount--;
2437
2438 if (mRefCount == 0 && mDeleteStatus)
2439 {
2440 mResourceManager->deleteProgram(mHandle);
2441 }
2442}
2443
2444void Program::addRef()
2445{
2446 mRefCount++;
2447}
2448
2449unsigned int Program::getRefCount() const
2450{
2451 return mRefCount;
2452}
2453
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00002454unsigned int Program::getSerial() const
2455{
2456 return mSerial;
2457}
2458
2459unsigned int Program::issueSerial()
2460{
2461 return mCurrentSerial++;
2462}
2463
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002464int ProgramBinary::getInfoLogLength() const
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002465{
2466 if (!mInfoLog)
2467 {
2468 return 0;
2469 }
2470 else
2471 {
2472 return strlen(mInfoLog) + 1;
2473 }
2474}
2475
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002476int Program::getInfoLogLength() const
2477{
2478 if (mProgramBinary)
2479 {
2480 return mProgramBinary->getInfoLogLength();
2481 }
2482 else
2483 {
2484 return 0;
2485 }
2486}
2487
2488void ProgramBinary::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002489{
2490 int index = 0;
2491
daniel@transgaming.com807d8c32012-04-04 15:06:04 +00002492 if (bufSize > 0)
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002493 {
daniel@transgaming.com807d8c32012-04-04 15:06:04 +00002494 if (mInfoLog)
2495 {
2496 index = std::min(bufSize - 1, (int)strlen(mInfoLog));
2497 memcpy(infoLog, mInfoLog, index);
2498 }
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002499
daniel@transgaming.comcba50572010-03-28 19:36:09 +00002500 infoLog[index] = '\0';
2501 }
2502
2503 if (length)
2504 {
2505 *length = index;
2506 }
2507}
2508
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002509void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
2510{
2511 if (mProgramBinary)
2512 {
2513 return mProgramBinary->getInfoLog(bufSize, length, infoLog);
2514 }
2515 else
2516 {
2517 if (bufSize > 0)
2518 {
2519 infoLog[0] = '\0';
2520 }
2521
2522 if (length)
2523 {
2524 *length = 0;
2525 }
2526 }
2527}
2528
daniel@transgaming.com6c785212010-03-30 03:36:17 +00002529void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
2530{
2531 int total = 0;
2532
2533 if (mVertexShader)
2534 {
2535 if (total < maxCount)
2536 {
2537 shaders[total] = mVertexShader->getHandle();
2538 }
2539
2540 total++;
2541 }
2542
2543 if (mFragmentShader)
2544 {
2545 if (total < maxCount)
2546 {
2547 shaders[total] = mFragmentShader->getHandle();
2548 }
2549
2550 total++;
2551 }
2552
2553 if (count)
2554 {
2555 *count = total;
2556 }
2557}
2558
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002559void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
daniel@transgaming.com85423182010-04-22 13:35:27 +00002560{
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002561 // Skip over inactive attributes
2562 unsigned int activeAttribute = 0;
2563 unsigned int attribute;
2564 for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
daniel@transgaming.com85423182010-04-22 13:35:27 +00002565 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002566 if (mLinkedAttribute[attribute].name.empty())
daniel@transgaming.com85423182010-04-22 13:35:27 +00002567 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002568 continue;
daniel@transgaming.com85423182010-04-22 13:35:27 +00002569 }
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002570
2571 if (activeAttribute == index)
2572 {
2573 break;
2574 }
2575
2576 activeAttribute++;
daniel@transgaming.com85423182010-04-22 13:35:27 +00002577 }
2578
2579 if (bufsize > 0)
2580 {
2581 const char *string = mLinkedAttribute[attribute].name.c_str();
2582
2583 strncpy(name, string, bufsize);
2584 name[bufsize - 1] = '\0';
2585
2586 if (length)
2587 {
2588 *length = strlen(name);
2589 }
2590 }
2591
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00002592 *size = 1; // Always a single 'type' instance
daniel@transgaming.com85423182010-04-22 13:35:27 +00002593
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002594 *type = mLinkedAttribute[attribute].type;
daniel@transgaming.com85423182010-04-22 13:35:27 +00002595}
2596
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002597void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2598{
2599 if (mProgramBinary)
2600 {
2601 mProgramBinary->getActiveAttribute(index, bufsize, length, size, type, name);
2602 }
2603 else
2604 {
2605 if (bufsize > 0)
2606 {
2607 name[0] = '\0';
2608 }
2609
2610 if (length)
2611 {
2612 *length = 0;
2613 }
2614
2615 *type = GL_NONE;
2616 *size = 1;
2617 }
2618}
2619
2620GLint ProgramBinary::getActiveAttributeCount()
daniel@transgaming.com85423182010-04-22 13:35:27 +00002621{
2622 int count = 0;
2623
2624 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2625 {
2626 if (!mLinkedAttribute[attributeIndex].name.empty())
2627 {
2628 count++;
2629 }
2630 }
2631
2632 return count;
2633}
2634
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002635GLint Program::getActiveAttributeCount()
2636{
2637 if (mProgramBinary)
2638 {
2639 return mProgramBinary->getActiveAttributeCount();
2640 }
2641 else
2642 {
2643 return 0;
2644 }
2645}
2646
2647GLint ProgramBinary::getActiveAttributeMaxLength()
daniel@transgaming.com85423182010-04-22 13:35:27 +00002648{
2649 int maxLength = 0;
2650
2651 for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2652 {
2653 if (!mLinkedAttribute[attributeIndex].name.empty())
2654 {
2655 maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength);
2656 }
2657 }
2658
2659 return maxLength;
2660}
2661
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002662GLint Program::getActiveAttributeMaxLength()
2663{
2664 if (mProgramBinary)
2665 {
2666 return mProgramBinary->getActiveAttributeMaxLength();
2667 }
2668 else
2669 {
2670 return 0;
2671 }
2672}
2673
2674void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002675{
daniel@transgaming.com996675c2010-11-17 13:06:29 +00002676 // Skip over internal uniforms
2677 unsigned int activeUniform = 0;
2678 unsigned int uniform;
2679 for (uniform = 0; uniform < mUniforms.size(); uniform++)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002680 {
daniel@transgaming.com51db7fb2011-09-20 16:11:06 +00002681 if (mUniforms[uniform]->name.compare(0, 3, "dx_") == 0)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002682 {
daniel@transgaming.comeea70792010-12-15 15:44:59 +00002683 continue;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002684 }
daniel@transgaming.com996675c2010-11-17 13:06:29 +00002685
2686 if (activeUniform == index)
2687 {
2688 break;
2689 }
2690
2691 activeUniform++;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002692 }
2693
daniel@transgaming.com996675c2010-11-17 13:06:29 +00002694 ASSERT(uniform < mUniforms.size()); // index must be smaller than getActiveUniformCount()
2695
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002696 if (bufsize > 0)
2697 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00002698 std::string string = mUniforms[uniform]->name;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002699
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00002700 if (mUniforms[uniform]->isArray())
daniel@transgaming.comf3140152010-04-29 03:38:50 +00002701 {
2702 string += "[0]";
2703 }
2704
daniel@transgaming.comfeba9ba2010-04-29 03:32:45 +00002705 strncpy(name, string.c_str(), bufsize);
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002706 name[bufsize - 1] = '\0';
2707
2708 if (length)
2709 {
2710 *length = strlen(name);
2711 }
2712 }
2713
daniel@transgaming.com1b3a8152010-04-22 13:35:37 +00002714 *size = mUniforms[uniform]->arraySize;
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002715
2716 *type = mUniforms[uniform]->type;
2717}
2718
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002719void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
2720{
2721 if (mProgramBinary)
2722 {
2723 return mProgramBinary->getActiveUniform(index, bufsize, length, size, type, name);
2724 }
2725 else
2726 {
2727 if (bufsize > 0)
2728 {
2729 name[0] = '\0';
2730 }
2731
2732 if (length)
2733 {
2734 *length = 0;
2735 }
2736
2737 *size = 0;
2738 *type = GL_NONE;
2739 }
2740}
2741
2742GLint ProgramBinary::getActiveUniformCount()
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002743{
2744 int count = 0;
2745
daniel@transgaming.comd08ea902010-05-14 19:41:36 +00002746 unsigned int numUniforms = mUniforms.size();
2747 for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002748 {
daniel@transgaming.com51db7fb2011-09-20 16:11:06 +00002749 if (mUniforms[uniformIndex]->name.compare(0, 3, "dx_") != 0)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002750 {
2751 count++;
2752 }
2753 }
2754
2755 return count;
2756}
2757
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002758GLint Program::getActiveUniformCount()
2759{
2760 if (mProgramBinary)
2761 {
2762 return mProgramBinary->getActiveUniformCount();
2763 }
2764 else
2765 {
2766 return 0;
2767 }
2768}
2769
2770GLint ProgramBinary::getActiveUniformMaxLength()
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002771{
2772 int maxLength = 0;
2773
daniel@transgaming.comd08ea902010-05-14 19:41:36 +00002774 unsigned int numUniforms = mUniforms.size();
2775 for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002776 {
daniel@transgaming.com51db7fb2011-09-20 16:11:06 +00002777 if (!mUniforms[uniformIndex]->name.empty() && mUniforms[uniformIndex]->name.compare(0, 3, "dx_") != 0)
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002778 {
daniel@transgaming.com024f1a92011-09-20 16:06:25 +00002779 int length = (int)(mUniforms[uniformIndex]->name.length() + 1);
2780 if (mUniforms[uniformIndex]->isArray())
zmo@google.com53d73e02011-03-24 21:27:57 +00002781 {
2782 length += 3; // Counting in "[0]".
2783 }
2784 maxLength = std::max(length, maxLength);
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00002785 }
2786 }
2787
2788 return maxLength;
2789}
2790
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002791GLint Program::getActiveUniformMaxLength()
2792{
2793 if (mProgramBinary)
2794 {
2795 return mProgramBinary->getActiveUniformMaxLength();
2796 }
2797 else
2798 {
2799 return 0;
2800 }
2801}
2802
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002803void Program::flagForDeletion()
2804{
2805 mDeleteStatus = true;
2806}
2807
2808bool Program::isFlaggedForDeletion() const
2809{
2810 return mDeleteStatus;
2811}
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002812
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002813bool Program::isValidated() const
2814{
2815 if (mProgramBinary)
2816 {
2817 return mProgramBinary->isValidated();
2818 }
2819 else
2820 {
2821 return false;
2822 }
2823}
2824
2825void ProgramBinary::validate()
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002826{
2827 resetInfoLog();
2828
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002829 applyUniforms();
2830 if (!validateSamplers(true))
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002831 {
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002832 mValidated = false;
2833 }
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002834 else
2835 {
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002836 mValidated = true;
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002837 }
2838}
2839
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002840bool ProgramBinary::validateSamplers(bool logErrors)
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002841{
2842 // if any two active samplers in a program are of different types, but refer to the same
2843 // texture image unit, and this is the current program, then ValidateProgram will fail, and
2844 // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002845
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002846 const unsigned int maxCombinedTextureImageUnits = getContext()->getMaximumCombinedTextureImageUnits();
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002847 TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF];
2848
2849 for (unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; ++i)
2850 {
2851 textureUnitType[i] = TEXTURE_UNKNOWN;
2852 }
2853
jbauman@chromium.orgb6e72222011-10-18 23:01:46 +00002854 for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002855 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002856 if (mSamplersPS[i].active)
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002857 {
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002858 unsigned int unit = mSamplersPS[i].logicalTextureUnit;
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002859
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002860 if (unit >= maxCombinedTextureImageUnits)
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002861 {
2862 if (logErrors)
2863 {
2864 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
2865 }
2866
2867 return false;
2868 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002869
2870 if (textureUnitType[unit] != TEXTURE_UNKNOWN)
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002871 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002872 if (mSamplersPS[i].textureType != textureUnitType[unit])
2873 {
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002874 if (logErrors)
2875 {
2876 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
2877 }
2878
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002879 return false;
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002880 }
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002881 }
2882 else
2883 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002884 textureUnitType[unit] = mSamplersPS[i].textureType;
2885 }
2886 }
2887 }
2888
jbauman@chromium.orgb6e72222011-10-18 23:01:46 +00002889 for (unsigned int i = 0; i < mUsedVertexSamplerRange; ++i)
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002890 {
2891 if (mSamplersVS[i].active)
2892 {
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002893 unsigned int unit = mSamplersVS[i].logicalTextureUnit;
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002894
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00002895 if (unit >= maxCombinedTextureImageUnits)
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002896 {
2897 if (logErrors)
2898 {
2899 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits);
2900 }
2901
2902 return false;
2903 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002904
2905 if (textureUnitType[unit] != TEXTURE_UNKNOWN)
2906 {
2907 if (mSamplersVS[i].textureType != textureUnitType[unit])
2908 {
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002909 if (logErrors)
2910 {
2911 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
2912 }
2913
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002914 return false;
2915 }
2916 }
2917 else
2918 {
2919 textureUnitType[unit] = mSamplersVS[i].textureType;
daniel@transgaming.com86a7a132010-04-29 03:32:32 +00002920 }
2921 }
2922 }
2923
2924 return true;
2925}
daniel@transgaming.com2d84df02010-05-14 17:31:13 +00002926
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002927GLint ProgramBinary::getDxDepthRangeLocation() const
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002928{
daniel@transgaming.com31754962010-11-28 02:02:52 +00002929 return mDxDepthRangeLocation;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002930}
2931
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002932GLint ProgramBinary::getDxDepthLocation() const
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002933{
2934 return mDxDepthLocation;
2935}
2936
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002937GLint ProgramBinary::getDxCoordLocation() const
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002938{
daniel@transgaming.comd9a54f92011-12-22 18:32:53 +00002939 return mDxCoordLocation;
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002940}
2941
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002942GLint ProgramBinary::getDxHalfPixelSizeLocation() const
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002943{
2944 return mDxHalfPixelSizeLocation;
2945}
2946
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002947GLint ProgramBinary::getDxFrontCCWLocation() const
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002948{
2949 return mDxFrontCCWLocation;
2950}
2951
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +00002952GLint ProgramBinary::getDxPointsOrLinesLocation() const
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00002953{
2954 return mDxPointsOrLinesLocation;
2955}
2956
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002957}