Home | History | Annotate | Download | only in libGLESv2
      1 //
      2 // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
      3 // 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 
     10 #include "libGLESv2/Program.h"
     11 
     12 #include "common/debug.h"
     13 
     14 #include "libGLESv2/main.h"
     15 #include "libGLESv2/Shader.h"
     16 #include "libGLESv2/utilities.h"
     17 
     18 namespace gl
     19 {
     20 unsigned int Program::mCurrentSerial = 1;
     21 
     22 std::string str(int i)
     23 {
     24     char buffer[20];
     25     sprintf(buffer, "%d", i);
     26     return buffer;
     27 }
     28 
     29 Uniform::Uniform(GLenum type, const std::string &name, unsigned int arraySize) : type(type), name(name), arraySize(arraySize)
     30 {
     31     int bytes = UniformTypeSize(type) * arraySize;
     32     data = new unsigned char[bytes];
     33     memset(data, 0, bytes);
     34     dirty = true;
     35     handlesSet = false;
     36 }
     37 
     38 Uniform::~Uniform()
     39 {
     40     delete[] data;
     41 }
     42 
     43 UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index)
     44     : name(name), element(element), index(index)
     45 {
     46 }
     47 
     48 Program::Program(ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle), mSerial(issueSerial())
     49 {
     50     mFragmentShader = NULL;
     51     mVertexShader = NULL;
     52 
     53     mPixelExecutable = NULL;
     54     mVertexExecutable = NULL;
     55     mConstantTablePS = NULL;
     56     mConstantTableVS = NULL;
     57 
     58     mInfoLog = NULL;
     59     mValidated = false;
     60 
     61     unlink();
     62 
     63     mDeleteStatus = false;
     64 
     65     mRefCount = 0;
     66 }
     67 
     68 Program::~Program()
     69 {
     70     unlink(true);
     71 
     72     if (mVertexShader != NULL)
     73     {
     74         mVertexShader->release();
     75     }
     76 
     77     if (mFragmentShader != NULL)
     78     {
     79         mFragmentShader->release();
     80     }
     81 }
     82 
     83 bool Program::attachShader(Shader *shader)
     84 {
     85     if (shader->getType() == GL_VERTEX_SHADER)
     86     {
     87         if (mVertexShader)
     88         {
     89             return false;
     90         }
     91 
     92         mVertexShader = (VertexShader*)shader;
     93         mVertexShader->addRef();
     94     }
     95     else if (shader->getType() == GL_FRAGMENT_SHADER)
     96     {
     97         if (mFragmentShader)
     98         {
     99             return false;
    100         }
    101 
    102         mFragmentShader = (FragmentShader*)shader;
    103         mFragmentShader->addRef();
    104     }
    105     else UNREACHABLE();
    106 
    107     return true;
    108 }
    109 
    110 bool Program::detachShader(Shader *shader)
    111 {
    112     if (shader->getType() == GL_VERTEX_SHADER)
    113     {
    114         if (mVertexShader != shader)
    115         {
    116             return false;
    117         }
    118 
    119         mVertexShader->release();
    120         mVertexShader = NULL;
    121     }
    122     else if (shader->getType() == GL_FRAGMENT_SHADER)
    123     {
    124         if (mFragmentShader != shader)
    125         {
    126             return false;
    127         }
    128 
    129         mFragmentShader->release();
    130         mFragmentShader = NULL;
    131     }
    132     else UNREACHABLE();
    133 
    134     unlink();
    135 
    136     return true;
    137 }
    138 
    139 int Program::getAttachedShadersCount() const
    140 {
    141     return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
    142 }
    143 
    144 IDirect3DPixelShader9 *Program::getPixelShader()
    145 {
    146     return mPixelExecutable;
    147 }
    148 
    149 IDirect3DVertexShader9 *Program::getVertexShader()
    150 {
    151     return mVertexExecutable;
    152 }
    153 
    154 void Program::bindAttributeLocation(GLuint index, const char *name)
    155 {
    156     if (index < MAX_VERTEX_ATTRIBS)
    157     {
    158         for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
    159         {
    160             mAttributeBinding[i].erase(name);
    161         }
    162 
    163         mAttributeBinding[index].insert(name);
    164     }
    165 }
    166 
    167 GLuint Program::getAttributeLocation(const char *name)
    168 {
    169     if (name)
    170     {
    171         for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
    172         {
    173             if (mLinkedAttribute[index].name == std::string(name))
    174             {
    175                 return index;
    176             }
    177         }
    178     }
    179 
    180     return -1;
    181 }
    182 
    183 int Program::getSemanticIndex(int attributeIndex)
    184 {
    185     if (attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS)
    186     {
    187         return mSemanticIndex[attributeIndex];
    188     }
    189 
    190     return -1;
    191 }
    192 
    193 // Returns the index of the texture unit corresponding to a Direct3D 9 sampler
    194 // index referenced in the compiled HLSL shader
    195 GLint Program::getSamplerMapping(unsigned int samplerIndex)
    196 {
    197     assert(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]));
    198 
    199     GLint logicalTextureUnit = -1;
    200 
    201     if (mSamplers[samplerIndex].active)
    202     {
    203         logicalTextureUnit = mSamplers[samplerIndex].logicalTextureUnit;
    204     }
    205 
    206     if (logicalTextureUnit >= 0 && logicalTextureUnit < MAX_TEXTURE_IMAGE_UNITS)
    207     {
    208         return logicalTextureUnit;
    209     }
    210 
    211     return -1;
    212 }
    213 
    214 SamplerType Program::getSamplerType(unsigned int samplerIndex)
    215 {
    216     assert(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]));
    217     assert(mSamplers[samplerIndex].active);
    218 
    219     return mSamplers[samplerIndex].type;
    220 }
    221 
    222 bool Program::isSamplerDirty(unsigned int samplerIndex) const
    223 {
    224     if (samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]))
    225     {
    226         return mSamplers[samplerIndex].dirty;
    227     }
    228     else UNREACHABLE();
    229 
    230     return false;
    231 }
    232 
    233 void Program::setSamplerDirty(unsigned int samplerIndex, bool dirty)
    234 {
    235     if (samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]))
    236     {
    237         mSamplers[samplerIndex].dirty = dirty;
    238     }
    239     else UNREACHABLE();
    240 }
    241 
    242 GLint Program::getUniformLocation(const char *name, bool decorated)
    243 {
    244     std::string _name = decorated ? name : decorate(name);
    245     int subscript = 0;
    246 
    247     // Strip any trailing array operator and retrieve the subscript
    248     size_t open = _name.find_last_of('[');
    249     size_t close = _name.find_last_of(']');
    250     if (open != std::string::npos && close == _name.length() - 1)
    251     {
    252         subscript = atoi(_name.substr(open + 1).c_str());
    253         _name.erase(open);
    254     }
    255 
    256     unsigned int numUniforms = mUniformIndex.size();
    257     for (unsigned int location = 0; location < numUniforms; location++)
    258     {
    259         if (mUniformIndex[location].name == _name &&
    260             mUniformIndex[location].element == subscript)
    261         {
    262             return location;
    263         }
    264     }
    265 
    266     return -1;
    267 }
    268 
    269 bool Program::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
    270 {
    271     if (location < 0 || location >= (int)mUniformIndex.size())
    272     {
    273         return false;
    274     }
    275 
    276     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    277     targetUniform->dirty = true;
    278 
    279     if (targetUniform->type == GL_FLOAT)
    280     {
    281         int arraySize = targetUniform->arraySize;
    282 
    283         if (arraySize == 1 && count > 1)
    284             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    285 
    286         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    287 
    288         memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat),
    289                v, sizeof(GLfloat) * count);
    290     }
    291     else if (targetUniform->type == GL_BOOL)
    292     {
    293         int arraySize = targetUniform->arraySize;
    294 
    295         if (arraySize == 1 && count > 1)
    296             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    297 
    298         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    299         GLboolean *boolParams = new GLboolean[count];
    300 
    301         for (int i = 0; i < count; ++i)
    302         {
    303             if (v[i] == 0.0f)
    304             {
    305                 boolParams[i] = GL_FALSE;
    306             }
    307             else
    308             {
    309                 boolParams[i] = GL_TRUE;
    310             }
    311         }
    312 
    313         memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean),
    314                boolParams, sizeof(GLboolean) * count);
    315 
    316         delete [] boolParams;
    317     }
    318     else
    319     {
    320         return false;
    321     }
    322 
    323     return true;
    324 }
    325 
    326 bool Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
    327 {
    328     if (location < 0 || location >= (int)mUniformIndex.size())
    329     {
    330         return false;
    331     }
    332 
    333     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    334     targetUniform->dirty = true;
    335 
    336     if (targetUniform->type == GL_FLOAT_VEC2)
    337     {
    338         int arraySize = targetUniform->arraySize;
    339 
    340         if (arraySize == 1 && count > 1)
    341             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    342 
    343         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    344 
    345         memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 2,
    346                v, 2 * sizeof(GLfloat) * count);
    347     }
    348     else if (targetUniform->type == GL_BOOL_VEC2)
    349     {
    350         int arraySize = targetUniform->arraySize;
    351 
    352         if (arraySize == 1 && count > 1)
    353             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    354 
    355         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    356 
    357         GLboolean *boolParams = new GLboolean[count * 2];
    358 
    359         for (int i = 0; i < count * 2; ++i)
    360         {
    361             if (v[i] == 0.0f)
    362             {
    363                 boolParams[i] = GL_FALSE;
    364             }
    365             else
    366             {
    367                 boolParams[i] = GL_TRUE;
    368             }
    369         }
    370 
    371         memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 2,
    372                boolParams, 2 * sizeof(GLboolean) * count);
    373 
    374         delete [] boolParams;
    375     }
    376     else
    377     {
    378         return false;
    379     }
    380 
    381     return true;
    382 }
    383 
    384 bool Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
    385 {
    386     if (location < 0 || location >= (int)mUniformIndex.size())
    387     {
    388         return false;
    389     }
    390 
    391     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    392     targetUniform->dirty = true;
    393 
    394     if (targetUniform->type == GL_FLOAT_VEC3)
    395     {
    396         int arraySize = targetUniform->arraySize;
    397 
    398         if (arraySize == 1 && count > 1)
    399             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    400 
    401         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    402 
    403         memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 3,
    404                v, 3 * sizeof(GLfloat) * count);
    405     }
    406     else if (targetUniform->type == GL_BOOL_VEC3)
    407     {
    408         int arraySize = targetUniform->arraySize;
    409 
    410         if (arraySize == 1 && count > 1)
    411             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    412 
    413         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    414         GLboolean *boolParams = new GLboolean[count * 3];
    415 
    416         for (int i = 0; i < count * 3; ++i)
    417         {
    418             if (v[i] == 0.0f)
    419             {
    420                 boolParams[i] = GL_FALSE;
    421             }
    422             else
    423             {
    424                 boolParams[i] = GL_TRUE;
    425             }
    426         }
    427 
    428         memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 3,
    429                boolParams, 3 * sizeof(GLboolean) * count);
    430 
    431         delete [] boolParams;
    432     }
    433     else
    434     {
    435         return false;
    436     }
    437 
    438     return true;
    439 }
    440 
    441 bool Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
    442 {
    443     if (location < 0 || location >= (int)mUniformIndex.size())
    444     {
    445         return false;
    446     }
    447 
    448     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    449     targetUniform->dirty = true;
    450 
    451     if (targetUniform->type == GL_FLOAT_VEC4)
    452     {
    453         int arraySize = targetUniform->arraySize;
    454 
    455         if (arraySize == 1 && count > 1)
    456             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    457 
    458         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    459 
    460         memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4,
    461                v, 4 * sizeof(GLfloat) * count);
    462     }
    463     else if (targetUniform->type == GL_BOOL_VEC4)
    464     {
    465         int arraySize = targetUniform->arraySize;
    466 
    467         if (arraySize == 1 && count > 1)
    468             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    469 
    470         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    471         GLboolean *boolParams = new GLboolean[count * 4];
    472 
    473         for (int i = 0; i < count * 4; ++i)
    474         {
    475             if (v[i] == 0.0f)
    476             {
    477                 boolParams[i] = GL_FALSE;
    478             }
    479             else
    480             {
    481                 boolParams[i] = GL_TRUE;
    482             }
    483         }
    484 
    485         memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 4,
    486                boolParams, 4 * sizeof(GLboolean) * count);
    487 
    488         delete [] boolParams;
    489     }
    490     else
    491     {
    492         return false;
    493     }
    494 
    495     return true;
    496 }
    497 
    498 bool Program::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
    499 {
    500     if (location < 0 || location >= (int)mUniformIndex.size())
    501     {
    502         return false;
    503     }
    504 
    505     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    506     targetUniform->dirty = true;
    507 
    508     if (targetUniform->type != GL_FLOAT_MAT2)
    509     {
    510         return false;
    511     }
    512 
    513     int arraySize = targetUniform->arraySize;
    514 
    515     if (arraySize == 1 && count > 1)
    516         return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    517 
    518     count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    519 
    520     memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 4,
    521            value, 4 * sizeof(GLfloat) * count);
    522 
    523     return true;
    524 }
    525 
    526 bool Program::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
    527 {
    528     if (location < 0 || location >= (int)mUniformIndex.size())
    529     {
    530         return false;
    531     }
    532 
    533     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    534     targetUniform->dirty = true;
    535 
    536     if (targetUniform->type != GL_FLOAT_MAT3)
    537     {
    538         return false;
    539     }
    540 
    541     int arraySize = targetUniform->arraySize;
    542 
    543     if (arraySize == 1 && count > 1)
    544         return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    545 
    546     count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    547 
    548     memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 9,
    549            value, 9 * sizeof(GLfloat) * count);
    550 
    551     return true;
    552 }
    553 
    554 bool Program::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
    555 {
    556     if (location < 0 || location >= (int)mUniformIndex.size())
    557     {
    558         return false;
    559     }
    560 
    561     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    562     targetUniform->dirty = true;
    563 
    564     if (targetUniform->type != GL_FLOAT_MAT4)
    565     {
    566         return false;
    567     }
    568 
    569     int arraySize = targetUniform->arraySize;
    570 
    571     if (arraySize == 1 && count > 1)
    572         return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    573 
    574     count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    575 
    576     memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16,
    577            value, 16 * sizeof(GLfloat) * count);
    578 
    579     return true;
    580 }
    581 
    582 bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
    583 {
    584     if (location < 0 || location >= (int)mUniformIndex.size())
    585     {
    586         return false;
    587     }
    588 
    589     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    590     targetUniform->dirty = true;
    591 
    592     if (targetUniform->type == GL_INT ||
    593         targetUniform->type == GL_SAMPLER_2D ||
    594         targetUniform->type == GL_SAMPLER_CUBE)
    595     {
    596         int arraySize = targetUniform->arraySize;
    597 
    598         if (arraySize == 1 && count > 1)
    599             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    600 
    601         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    602 
    603         memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint),
    604                v, sizeof(GLint) * count);
    605     }
    606     else if (targetUniform->type == GL_BOOL)
    607     {
    608         int arraySize = targetUniform->arraySize;
    609 
    610         if (arraySize == 1 && count > 1)
    611             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    612 
    613         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    614         GLboolean *boolParams = new GLboolean[count];
    615 
    616         for (int i = 0; i < count; ++i)
    617         {
    618             if (v[i] == 0)
    619             {
    620                 boolParams[i] = GL_FALSE;
    621             }
    622             else
    623             {
    624                 boolParams[i] = GL_TRUE;
    625             }
    626         }
    627 
    628         memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean),
    629                boolParams, sizeof(GLboolean) * count);
    630 
    631         delete [] boolParams;
    632     }
    633     else
    634     {
    635         return false;
    636     }
    637 
    638     return true;
    639 }
    640 
    641 bool Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
    642 {
    643     if (location < 0 || location >= (int)mUniformIndex.size())
    644     {
    645         return false;
    646     }
    647 
    648     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    649     targetUniform->dirty = true;
    650 
    651     if (targetUniform->type == GL_INT_VEC2)
    652     {
    653         int arraySize = targetUniform->arraySize;
    654 
    655         if (arraySize == 1 && count > 1)
    656             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    657 
    658         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    659 
    660         memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 2,
    661                v, 2 * sizeof(GLint) * count);
    662     }
    663     else if (targetUniform->type == GL_BOOL_VEC2)
    664     {
    665         int arraySize = targetUniform->arraySize;
    666 
    667         if (arraySize == 1 && count > 1)
    668             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    669 
    670         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    671         GLboolean *boolParams = new GLboolean[count * 2];
    672 
    673         for (int i = 0; i < count * 2; ++i)
    674         {
    675             if (v[i] == 0)
    676             {
    677                 boolParams[i] = GL_FALSE;
    678             }
    679             else
    680             {
    681                 boolParams[i] = GL_TRUE;
    682             }
    683         }
    684 
    685         memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 2,
    686                boolParams, 2 * sizeof(GLboolean) * count);
    687 
    688         delete [] boolParams;
    689     }
    690     else
    691     {
    692         return false;
    693     }
    694 
    695     return true;
    696 }
    697 
    698 bool Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
    699 {
    700     if (location < 0 || location >= (int)mUniformIndex.size())
    701     {
    702         return false;
    703     }
    704 
    705     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    706     targetUniform->dirty = true;
    707 
    708     if (targetUniform->type == GL_INT_VEC3)
    709     {
    710         int arraySize = targetUniform->arraySize;
    711 
    712         if (arraySize == 1 && count > 1)
    713             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    714 
    715         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    716 
    717         memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 3,
    718                v, 3 * sizeof(GLint) * count);
    719     }
    720     else if (targetUniform->type == GL_BOOL_VEC3)
    721     {
    722         int arraySize = targetUniform->arraySize;
    723 
    724         if (arraySize == 1 && count > 1)
    725             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    726 
    727         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    728         GLboolean *boolParams = new GLboolean[count * 3];
    729 
    730         for (int i = 0; i < count * 3; ++i)
    731         {
    732             if (v[i] == 0)
    733             {
    734                 boolParams[i] = GL_FALSE;
    735             }
    736             else
    737             {
    738                 boolParams[i] = GL_TRUE;
    739             }
    740         }
    741 
    742         memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 3,
    743                boolParams, 3 * sizeof(GLboolean) * count);
    744 
    745         delete [] boolParams;
    746     }
    747     else
    748     {
    749         return false;
    750     }
    751 
    752     return true;
    753 }
    754 
    755 bool Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
    756 {
    757     if (location < 0 || location >= (int)mUniformIndex.size())
    758     {
    759         return false;
    760     }
    761 
    762     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    763     targetUniform->dirty = true;
    764 
    765     if (targetUniform->type == GL_INT_VEC4)
    766     {
    767         int arraySize = targetUniform->arraySize;
    768 
    769         if (arraySize == 1 && count > 1)
    770             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    771 
    772         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    773 
    774         memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLint) * 4,
    775                v, 4 * sizeof(GLint) * count);
    776     }
    777     else if (targetUniform->type == GL_BOOL_VEC4)
    778     {
    779         int arraySize = targetUniform->arraySize;
    780 
    781         if (arraySize == 1 && count > 1)
    782             return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION
    783 
    784         count = std::min(arraySize - (int)mUniformIndex[location].element, count);
    785         GLboolean *boolParams = new GLboolean[count * 4];
    786 
    787         for (int i = 0; i < count * 4; ++i)
    788         {
    789             if (v[i] == 0)
    790             {
    791                 boolParams[i] = GL_FALSE;
    792             }
    793             else
    794             {
    795                 boolParams[i] = GL_TRUE;
    796             }
    797         }
    798 
    799         memcpy(targetUniform->data + mUniformIndex[location].element * sizeof(GLboolean) * 4,
    800                boolParams, 4 * sizeof(GLboolean) * count);
    801 
    802         delete [] boolParams;
    803     }
    804     else
    805     {
    806         return false;
    807     }
    808 
    809     return true;
    810 }
    811 
    812 bool Program::getUniformfv(GLint location, GLfloat *params)
    813 {
    814     if (location < 0 || location >= (int)mUniformIndex.size())
    815     {
    816         return false;
    817     }
    818 
    819     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    820 
    821     unsigned int count = UniformComponentCount(targetUniform->type);
    822 
    823     switch (UniformComponentType(targetUniform->type))
    824     {
    825       case GL_BOOL:
    826         {
    827             GLboolean *boolParams = (GLboolean*)targetUniform->data + mUniformIndex[location].element * count;
    828 
    829             for (unsigned int i = 0; i < count; ++i)
    830             {
    831                 params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
    832             }
    833         }
    834         break;
    835       case GL_FLOAT:
    836         memcpy(params, targetUniform->data + mUniformIndex[location].element * count * sizeof(GLfloat),
    837                count * sizeof(GLfloat));
    838         break;
    839       case GL_INT:
    840         {
    841             GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * count;
    842 
    843             for (unsigned int i = 0; i < count; ++i)
    844             {
    845                 params[i] = (float)intParams[i];
    846             }
    847         }
    848         break;
    849       default: UNREACHABLE();
    850     }
    851 
    852     return true;
    853 }
    854 
    855 bool Program::getUniformiv(GLint location, GLint *params)
    856 {
    857     if (location < 0 || location >= (int)mUniformIndex.size())
    858     {
    859         return false;
    860     }
    861 
    862     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    863 
    864     unsigned int count = UniformComponentCount(targetUniform->type);
    865 
    866     switch (UniformComponentType(targetUniform->type))
    867     {
    868       case GL_BOOL:
    869         {
    870             GLboolean *boolParams = targetUniform->data + mUniformIndex[location].element * count;
    871 
    872             for (unsigned int i = 0; i < count; ++i)
    873             {
    874                 params[i] = (GLint)boolParams[i];
    875             }
    876         }
    877         break;
    878       case GL_FLOAT:
    879         {
    880             GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * count;
    881 
    882             for (unsigned int i = 0; i < count; ++i)
    883             {
    884                 params[i] = (GLint)floatParams[i];
    885             }
    886         }
    887         break;
    888       case GL_INT:
    889         memcpy(params, targetUniform->data + mUniformIndex[location].element * count * sizeof(GLint),
    890                count * sizeof(GLint));
    891         break;
    892       default: UNREACHABLE();
    893     }
    894 
    895     return true;
    896 }
    897 
    898 void Program::dirtyAllUniforms()
    899 {
    900     unsigned int numUniforms = mUniforms.size();
    901     for (unsigned int index = 0; index < numUniforms; index++)
    902     {
    903         mUniforms[index]->dirty = true;
    904     }
    905 }
    906 
    907 void Program::dirtyAllSamplers()
    908 {
    909     for (unsigned int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; ++index)
    910     {
    911         mSamplers[index].dirty = true;
    912     }
    913 }
    914 
    915 // Applies all the uniforms set for this program object to the Direct3D 9 device
    916 void Program::applyUniforms()
    917 {
    918     unsigned int numUniforms = mUniformIndex.size();
    919     for (unsigned int location = 0; location < numUniforms; location++)
    920     {
    921         if (mUniformIndex[location].element != 0)
    922         {
    923             continue;
    924         }
    925 
    926         Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
    927 
    928         if (targetUniform->dirty)
    929         {
    930             int arraySize = targetUniform->arraySize;
    931             GLfloat *f = (GLfloat*)targetUniform->data;
    932             GLint *i = (GLint*)targetUniform->data;
    933             GLboolean *b = (GLboolean*)targetUniform->data;
    934 
    935             switch (targetUniform->type)
    936             {
    937               case GL_BOOL:       applyUniform1bv(location, arraySize, b);       break;
    938               case GL_BOOL_VEC2:  applyUniform2bv(location, arraySize, b);       break;
    939               case GL_BOOL_VEC3:  applyUniform3bv(location, arraySize, b);       break;
    940               case GL_BOOL_VEC4:  applyUniform4bv(location, arraySize, b);       break;
    941               case GL_FLOAT:      applyUniform1fv(location, arraySize, f);       break;
    942               case GL_FLOAT_VEC2: applyUniform2fv(location, arraySize, f);       break;
    943               case GL_FLOAT_VEC3: applyUniform3fv(location, arraySize, f);       break;
    944               case GL_FLOAT_VEC4: applyUniform4fv(location, arraySize, f);       break;
    945               case GL_FLOAT_MAT2: applyUniformMatrix2fv(location, arraySize, f); break;
    946               case GL_FLOAT_MAT3: applyUniformMatrix3fv(location, arraySize, f); break;
    947               case GL_FLOAT_MAT4: applyUniformMatrix4fv(location, arraySize, f); break;
    948               case GL_SAMPLER_2D:
    949               case GL_SAMPLER_CUBE:
    950               case GL_INT:        applyUniform1iv(location, arraySize, i);       break;
    951               case GL_INT_VEC2:   applyUniform2iv(location, arraySize, i);       break;
    952               case GL_INT_VEC3:   applyUniform3iv(location, arraySize, i);       break;
    953               case GL_INT_VEC4:   applyUniform4iv(location, arraySize, i);       break;
    954               default:
    955                 UNREACHABLE();
    956             }
    957 
    958             targetUniform->dirty = false;
    959         }
    960     }
    961 }
    962 
    963 // Compiles the HLSL code of the attached shaders into executable binaries
    964 ID3DXBuffer *Program::compileToBinary(const char *hlsl, const char *profile, ID3DXConstantTable **constantTable)
    965 {
    966     if (!hlsl)
    967     {
    968         return NULL;
    969     }
    970 
    971     ID3DXBuffer *binary = NULL;
    972     ID3DXBuffer *errorMessage = NULL;
    973 
    974     HRESULT result = D3DXCompileShader(hlsl, (UINT)strlen(hlsl), NULL, NULL, "main", profile, 0, &binary, &errorMessage, constantTable);
    975 
    976     if (SUCCEEDED(result))
    977     {
    978         return binary;
    979     }
    980 
    981     if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
    982     {
    983         return error(GL_OUT_OF_MEMORY, (ID3DXBuffer*)NULL);
    984     }
    985 
    986     if (errorMessage)
    987     {
    988         const char *message = (const char*)errorMessage->GetBufferPointer();
    989 
    990         appendToInfoLog("%s\n", message);
    991         TRACE("\n%s", hlsl);
    992         TRACE("\n%s", message);
    993     }
    994 
    995     return NULL;
    996 }
    997 
    998 // Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
    999 // Returns the number of used varying registers, or -1 if unsuccesful
   1000 int Program::packVaryings(const Varying *packing[][4])
   1001 {
   1002     Context *context = getContext();
   1003     const int maxVaryingVectors = context->getMaximumVaryingVectors();
   1004 
   1005     for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.end(); varying++)
   1006     {
   1007         int n = VariableRowCount(varying->type) * varying->size;
   1008         int m = VariableColumnCount(varying->type);
   1009         bool success = false;
   1010 
   1011         if (m == 2 || m == 3 || m == 4)
   1012         {
   1013             for (int r = 0; r <= maxVaryingVectors - n && !success; r++)
   1014             {
   1015                 bool available = true;
   1016 
   1017                 for (int y = 0; y < n && available; y++)
   1018                 {
   1019                     for (int x = 0; x < m && available; x++)
   1020                     {
   1021                         if (packing[r + y][x])
   1022                         {
   1023                             available = false;
   1024                         }
   1025                     }
   1026                 }
   1027 
   1028                 if (available)
   1029                 {
   1030                     varying->reg = r;
   1031                     varying->col = 0;
   1032 
   1033                     for (int y = 0; y < n; y++)
   1034                     {
   1035                         for (int x = 0; x < m; x++)
   1036                         {
   1037                             packing[r + y][x] = &*varying;
   1038                         }
   1039                     }
   1040 
   1041                     success = true;
   1042                 }
   1043             }
   1044 
   1045             if (!success && m == 2)
   1046             {
   1047                 for (int r = maxVaryingVectors - n; r >= 0 && !success; r--)
   1048                 {
   1049                     bool available = true;
   1050 
   1051                     for (int y = 0; y < n && available; y++)
   1052                     {
   1053                         for (int x = 2; x < 4 && available; x++)
   1054                         {
   1055                             if (packing[r + y][x])
   1056                             {
   1057                                 available = false;
   1058                             }
   1059                         }
   1060                     }
   1061 
   1062                     if (available)
   1063                     {
   1064                         varying->reg = r;
   1065                         varying->col = 2;
   1066 
   1067                         for (int y = 0; y < n; y++)
   1068                         {
   1069                             for (int x = 2; x < 4; x++)
   1070                             {
   1071                                 packing[r + y][x] = &*varying;
   1072                             }
   1073                         }
   1074 
   1075                         success = true;
   1076                     }
   1077                 }
   1078             }
   1079         }
   1080         else if (m == 1)
   1081         {
   1082             int space[4] = {0};
   1083 
   1084             for (int y = 0; y < maxVaryingVectors; y++)
   1085             {
   1086                 for (int x = 0; x < 4; x++)
   1087                 {
   1088                     space[x] += packing[y][x] ? 0 : 1;
   1089                 }
   1090             }
   1091 
   1092             int column = 0;
   1093 
   1094             for (int x = 0; x < 4; x++)
   1095             {
   1096                 if (space[x] > n && space[x] < space[column])
   1097                 {
   1098                     column = x;
   1099                 }
   1100             }
   1101 
   1102             if (space[column] > n)
   1103             {
   1104                 for (int r = 0; r < maxVaryingVectors; r++)
   1105                 {
   1106                     if (!packing[r][column])
   1107                     {
   1108                         varying->reg = r;
   1109 
   1110                         for (int y = r; y < r + n; y++)
   1111                         {
   1112                             packing[y][column] = &*varying;
   1113                         }
   1114 
   1115                         break;
   1116                     }
   1117                 }
   1118 
   1119                 varying->col = column;
   1120 
   1121                 success = true;
   1122             }
   1123         }
   1124         else UNREACHABLE();
   1125 
   1126         if (!success)
   1127         {
   1128             appendToInfoLog("Could not pack varying %s", varying->name.c_str());
   1129 
   1130             return -1;
   1131         }
   1132     }
   1133 
   1134     // Return the number of used registers
   1135     int registers = 0;
   1136 
   1137     for (int r = 0; r < maxVaryingVectors; r++)
   1138     {
   1139         if (packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
   1140         {
   1141             registers++;
   1142         }
   1143     }
   1144 
   1145     return registers;
   1146 }
   1147 
   1148 bool Program::linkVaryings()
   1149 {
   1150     if (mPixelHLSL.empty() || mVertexHLSL.empty())
   1151     {
   1152         return false;
   1153     }
   1154 
   1155     const Varying *packing[MAX_VARYING_VECTORS_SM3][4] = {NULL};
   1156     int registers = packVaryings(packing);
   1157 
   1158     if (registers < 0)
   1159     {
   1160         return false;
   1161     }
   1162 
   1163     Context *context = getContext();
   1164     const bool sm3 = context->supportsShaderModel3();
   1165     const int maxVaryingVectors = context->getMaximumVaryingVectors();
   1166 
   1167     if (registers == maxVaryingVectors && mFragmentShader->mUsesFragCoord)
   1168     {
   1169         appendToInfoLog("No varying registers left to support gl_FragCoord");
   1170 
   1171         return false;
   1172     }
   1173 
   1174     for (VaryingList::iterator input = mFragmentShader->varyings.begin(); input != mFragmentShader->varyings.end(); input++)
   1175     {
   1176         bool matched = false;
   1177 
   1178         for (VaryingList::iterator output = mVertexShader->varyings.begin(); output != mVertexShader->varyings.end(); output++)
   1179         {
   1180             if (output->name == input->name)
   1181             {
   1182                 if (output->type != input->type || output->size != input->size)
   1183                 {
   1184                     appendToInfoLog("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str());
   1185 
   1186                     return false;
   1187                 }
   1188 
   1189                 output->reg = input->reg;
   1190                 output->col = input->col;
   1191 
   1192                 matched = true;
   1193                 break;
   1194             }
   1195         }
   1196 
   1197         if (!matched)
   1198         {
   1199             appendToInfoLog("Fragment varying varying %s does not match any vertex varying", input->name.c_str());
   1200 
   1201             return false;
   1202         }
   1203     }
   1204 
   1205     std::string varyingSemantic = (sm3 ? "COLOR" : "TEXCOORD");
   1206 
   1207     mVertexHLSL += "struct VS_INPUT\n"
   1208                    "{\n";
   1209 
   1210     int semanticIndex = 0;
   1211     for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
   1212     {
   1213         switch (attribute->type)
   1214         {
   1215           case GL_FLOAT:      mVertexHLSL += "    float ";    break;
   1216           case GL_FLOAT_VEC2: mVertexHLSL += "    float2 ";   break;
   1217           case GL_FLOAT_VEC3: mVertexHLSL += "    float3 ";   break;
   1218           case GL_FLOAT_VEC4: mVertexHLSL += "    float4 ";   break;
   1219           case GL_FLOAT_MAT2: mVertexHLSL += "    float2x2 "; break;
   1220           case GL_FLOAT_MAT3: mVertexHLSL += "    float3x3 "; break;
   1221           case GL_FLOAT_MAT4: mVertexHLSL += "    float4x4 "; break;
   1222           default:  UNREACHABLE();
   1223         }
   1224 
   1225         mVertexHLSL += decorate(attribute->name) + " : TEXCOORD" + str(semanticIndex) + ";\n";
   1226 
   1227         semanticIndex += VariableRowCount(attribute->type);
   1228     }
   1229 
   1230     mVertexHLSL += "};\n"
   1231                    "\n"
   1232                    "struct VS_OUTPUT\n"
   1233                    "{\n"
   1234                    "    float4 gl_Position : POSITION;\n";
   1235 
   1236     for (int r = 0; r < registers; r++)
   1237     {
   1238         int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1));
   1239 
   1240         mVertexHLSL += "    float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
   1241     }
   1242 
   1243     if (mFragmentShader->mUsesFragCoord)
   1244     {
   1245         mVertexHLSL += "    float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
   1246     }
   1247 
   1248     if (mVertexShader->mUsesPointSize && sm3)
   1249     {
   1250         mVertexHLSL += "    float gl_PointSize : PSIZE;\n";
   1251     }
   1252 
   1253     mVertexHLSL += "};\n"
   1254                    "\n"
   1255                    "VS_OUTPUT main(VS_INPUT input)\n"
   1256                    "{\n";
   1257 
   1258     for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
   1259     {
   1260         mVertexHLSL += "    " + decorate(attribute->name) + " = ";
   1261 
   1262         if (VariableRowCount(attribute->type) > 1)   // Matrix
   1263         {
   1264             mVertexHLSL += "transpose";
   1265         }
   1266 
   1267         mVertexHLSL += "(input." + decorate(attribute->name) + ");\n";
   1268     }
   1269 
   1270     mVertexHLSL += "\n"
   1271                    "    gl_main();\n"
   1272                    "\n"
   1273                    "    VS_OUTPUT output;\n"
   1274                    "    output.gl_Position.x = gl_Position.x - dx_HalfPixelSize.x * gl_Position.w;\n"
   1275                    "    output.gl_Position.y = -(gl_Position.y - dx_HalfPixelSize.y * gl_Position.w);\n"
   1276                    "    output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
   1277                    "    output.gl_Position.w = gl_Position.w;\n";
   1278 
   1279     if (mVertexShader->mUsesPointSize && sm3)
   1280     {
   1281         mVertexHLSL += "    output.gl_PointSize = clamp(gl_PointSize, 1.0, " + str((int)ALIASED_POINT_SIZE_RANGE_MAX_SM3) + ");\n";
   1282     }
   1283 
   1284     if (mFragmentShader->mUsesFragCoord)
   1285     {
   1286         mVertexHLSL += "    output.gl_FragCoord = gl_Position;\n";
   1287     }
   1288 
   1289     for (VaryingList::iterator varying = mVertexShader->varyings.begin(); varying != mVertexShader->varyings.end(); varying++)
   1290     {
   1291         if (varying->reg >= 0)
   1292         {
   1293             for (int i = 0; i < varying->size; i++)
   1294             {
   1295                 int rows = VariableRowCount(varying->type);
   1296 
   1297                 for (int j = 0; j < rows; j++)
   1298                 {
   1299                     int r = varying->reg + i * rows + j;
   1300                     mVertexHLSL += "    output.v" + str(r);
   1301 
   1302                     bool sharedRegister = false;   // Register used by multiple varyings
   1303 
   1304                     for (int x = 0; x < 4; x++)
   1305                     {
   1306                         if (packing[r][x] && packing[r][x] != packing[r][0])
   1307                         {
   1308                             sharedRegister = true;
   1309                             break;
   1310                         }
   1311                     }
   1312 
   1313                     if(sharedRegister)
   1314                     {
   1315                         mVertexHLSL += ".";
   1316 
   1317                         for (int x = 0; x < 4; x++)
   1318                         {
   1319                             if (packing[r][x] == &*varying)
   1320                             {
   1321                                 switch(x)
   1322                                 {
   1323                                   case 0: mVertexHLSL += "x"; break;
   1324                                   case 1: mVertexHLSL += "y"; break;
   1325                                   case 2: mVertexHLSL += "z"; break;
   1326                                   case 3: mVertexHLSL += "w"; break;
   1327                                 }
   1328                             }
   1329                         }
   1330                     }
   1331 
   1332                     mVertexHLSL += " = " + varying->name;
   1333 
   1334                     if (varying->array)
   1335                     {
   1336                         mVertexHLSL += "[" + str(i) + "]";
   1337                     }
   1338 
   1339                     if (rows > 1)
   1340                     {
   1341                         mVertexHLSL += "[" + str(j) + "]";
   1342                     }
   1343 
   1344                     mVertexHLSL += ";\n";
   1345                 }
   1346             }
   1347         }
   1348     }
   1349 
   1350     mVertexHLSL += "\n"
   1351                    "    return output;\n"
   1352                    "}\n";
   1353 
   1354     mPixelHLSL += "struct PS_INPUT\n"
   1355                   "{\n";
   1356 
   1357     for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.end(); varying++)
   1358     {
   1359         if (varying->reg >= 0)
   1360         {
   1361             for (int i = 0; i < varying->size; i++)
   1362             {
   1363                 int rows = VariableRowCount(varying->type);
   1364                 for (int j = 0; j < rows; j++)
   1365                 {
   1366                     std::string n = str(varying->reg + i * rows + j);
   1367                     mPixelHLSL += "    float4 v" + n + " : " + varyingSemantic + n + ";\n";
   1368                 }
   1369             }
   1370         }
   1371         else UNREACHABLE();
   1372     }
   1373 
   1374     if (mFragmentShader->mUsesFragCoord)
   1375     {
   1376         mPixelHLSL += "    float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
   1377         if (sm3) {
   1378             mPixelHLSL += "    float2 dx_VPos : VPOS;\n";
   1379         }
   1380     }
   1381 
   1382     if (mFragmentShader->mUsesPointCoord && sm3)
   1383     {
   1384         mPixelHLSL += "    float2 gl_PointCoord : TEXCOORD0;\n";
   1385     }
   1386 
   1387     if (mFragmentShader->mUsesFrontFacing)
   1388     {
   1389         mPixelHLSL += "    float vFace : VFACE;\n";
   1390     }
   1391 
   1392     mPixelHLSL += "};\n"
   1393                   "\n"
   1394                   "struct PS_OUTPUT\n"
   1395                   "{\n"
   1396                   "    float4 gl_Color[1] : COLOR;\n"
   1397                   "};\n"
   1398                   "\n"
   1399                   "PS_OUTPUT main(PS_INPUT input)\n"
   1400                   "{\n";
   1401 
   1402     if (mFragmentShader->mUsesFragCoord)
   1403     {
   1404         mPixelHLSL += "    float rhw = 1.0 / input.gl_FragCoord.w;\n";
   1405         if (sm3) {
   1406             mPixelHLSL += "    gl_FragCoord.x = input.dx_VPos.x;\n"
   1407                           "    gl_FragCoord.y = input.dx_VPos.y;\n";
   1408         } else {
   1409             mPixelHLSL += "    gl_FragCoord.x = (input.gl_FragCoord.x * rhw) * dx_Viewport.x + dx_Viewport.z;\n"
   1410                           "    gl_FragCoord.y = (input.gl_FragCoord.y * rhw) * dx_Viewport.y + dx_Viewport.w;\n";
   1411         }
   1412         mPixelHLSL += "    gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_Depth.x + dx_Depth.y;\n"
   1413                       "    gl_FragCoord.w = rhw;\n";
   1414     }
   1415 
   1416     if (mFragmentShader->mUsesPointCoord && sm3)
   1417     {
   1418         mPixelHLSL += "    gl_PointCoord = float2(input.gl_PointCoord.x, 1.0 - input.gl_PointCoord.y);\n";
   1419     }
   1420 
   1421     if (mFragmentShader->mUsesFrontFacing)
   1422     {
   1423         mPixelHLSL += "    gl_FrontFacing = dx_PointsOrLines || (dx_FrontCCW ? (input.vFace >= 0.0) : (input.vFace <= 0.0));\n";
   1424     }
   1425 
   1426     for (VaryingList::iterator varying = mFragmentShader->varyings.begin(); varying != mFragmentShader->varyings.end(); varying++)
   1427     {
   1428         if (varying->reg >= 0)
   1429         {
   1430             for (int i = 0; i < varying->size; i++)
   1431             {
   1432                 int rows = VariableRowCount(varying->type);
   1433                 for (int j = 0; j < rows; j++)
   1434                 {
   1435                     std::string n = str(varying->reg + i * rows + j);
   1436                     mPixelHLSL += "    " + varying->name;
   1437 
   1438                     if (varying->array)
   1439                     {
   1440                         mPixelHLSL += "[" + str(i) + "]";
   1441                     }
   1442 
   1443                     if (rows > 1)
   1444                     {
   1445                         mPixelHLSL += "[" + str(j) + "]";
   1446                     }
   1447 
   1448                     mPixelHLSL += " = input.v" + n + ";\n";
   1449                 }
   1450             }
   1451         }
   1452         else UNREACHABLE();
   1453     }
   1454 
   1455     mPixelHLSL += "\n"
   1456                   "    gl_main();\n"
   1457                   "\n"
   1458                   "    PS_OUTPUT output;\n"
   1459                   "    output.gl_Color[0] = gl_Color[0];\n"
   1460                   "\n"
   1461                   "    return output;\n"
   1462                   "}\n";
   1463 
   1464     TRACE("\n%s", mPixelHLSL.c_str());
   1465     TRACE("\n%s", mVertexHLSL.c_str());
   1466 
   1467     return true;
   1468 }
   1469 
   1470 // Links the HLSL code of the vertex and pixel shader by matching up their varyings,
   1471 // compiling them into binaries, determining the attribute mappings, and collecting
   1472 // a list of uniforms
   1473 void Program::link()
   1474 {
   1475     unlink();
   1476 
   1477     if (!mFragmentShader || !mFragmentShader->isCompiled())
   1478     {
   1479         return;
   1480     }
   1481 
   1482     if (!mVertexShader || !mVertexShader->isCompiled())
   1483     {
   1484         return;
   1485     }
   1486 
   1487     mPixelHLSL = mFragmentShader->getHLSL();
   1488     mVertexHLSL = mVertexShader->getHLSL();
   1489 
   1490     if (!linkVaryings())
   1491     {
   1492         return;
   1493     }
   1494 
   1495     Context *context = getContext();
   1496     const char *vertexProfile = context->supportsShaderModel3() ? "vs_3_0" : "vs_2_0";
   1497     const char *pixelProfile = context->supportsShaderModel3() ? "ps_3_0" : "ps_2_0";
   1498 
   1499     ID3DXBuffer *vertexBinary = compileToBinary(mVertexHLSL.c_str(), vertexProfile, &mConstantTableVS);
   1500     ID3DXBuffer *pixelBinary = compileToBinary(mPixelHLSL.c_str(), pixelProfile, &mConstantTablePS);
   1501 
   1502     if (vertexBinary && pixelBinary)
   1503     {
   1504         IDirect3DDevice9 *device = getDevice();
   1505         HRESULT vertexResult = device->CreateVertexShader((DWORD*)vertexBinary->GetBufferPointer(), &mVertexExecutable);
   1506         HRESULT pixelResult = device->CreatePixelShader((DWORD*)pixelBinary->GetBufferPointer(), &mPixelExecutable);
   1507 
   1508         if (vertexResult == D3DERR_OUTOFVIDEOMEMORY || vertexResult == E_OUTOFMEMORY || pixelResult == D3DERR_OUTOFVIDEOMEMORY || pixelResult == E_OUTOFMEMORY)
   1509         {
   1510             return error(GL_OUT_OF_MEMORY);
   1511         }
   1512 
   1513         ASSERT(SUCCEEDED(vertexResult) && SUCCEEDED(pixelResult));
   1514 
   1515         vertexBinary->Release();
   1516         pixelBinary->Release();
   1517         vertexBinary = NULL;
   1518         pixelBinary = NULL;
   1519 
   1520         if (mVertexExecutable && mPixelExecutable)
   1521         {
   1522             if (!linkAttributes())
   1523             {
   1524                 return;
   1525             }
   1526 
   1527             if (!linkUniforms(mConstantTablePS))
   1528             {
   1529                 return;
   1530             }
   1531 
   1532             if (!linkUniforms(mConstantTableVS))
   1533             {
   1534                 return;
   1535             }
   1536 
   1537             // these uniforms are searched as already-decorated because gl_ and dx_
   1538             // are reserved prefixes, and do not receive additional decoration
   1539             mDxDepthRangeLocation = getUniformLocation("dx_DepthRange", true);
   1540             mDxDepthLocation = getUniformLocation("dx_Depth", true);
   1541             mDxViewportLocation = getUniformLocation("dx_Viewport", true);
   1542             mDxHalfPixelSizeLocation = getUniformLocation("dx_HalfPixelSize", true);
   1543             mDxFrontCCWLocation = getUniformLocation("dx_FrontCCW", true);
   1544             mDxPointsOrLinesLocation = getUniformLocation("dx_PointsOrLines", true);
   1545 
   1546             mLinked = true;   // Success
   1547         }
   1548     }
   1549 }
   1550 
   1551 // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
   1552 bool Program::linkAttributes()
   1553 {
   1554     unsigned int usedLocations = 0;
   1555 
   1556     // Link attributes that have a binding location
   1557     for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
   1558     {
   1559         int location = getAttributeBinding(attribute->name);
   1560 
   1561         if (location != -1)   // Set by glBindAttribLocation
   1562         {
   1563             if (!mLinkedAttribute[location].name.empty())
   1564             {
   1565                 // Multiple active attributes bound to the same location; not an error
   1566             }
   1567 
   1568             mLinkedAttribute[location] = *attribute;
   1569 
   1570             int rows = VariableRowCount(attribute->type);
   1571 
   1572             if (rows + location > MAX_VERTEX_ATTRIBS)
   1573             {
   1574                 appendToInfoLog("Active attribute (%s) at location %d is too big to fit", attribute->name.c_str(), location);
   1575 
   1576                 return false;
   1577             }
   1578 
   1579             for (int i = 0; i < rows; i++)
   1580             {
   1581                 usedLocations |= 1 << (location + i);
   1582             }
   1583         }
   1584     }
   1585 
   1586     // Link attributes that don't have a binding location
   1587     for (AttributeArray::iterator attribute = mVertexShader->mAttributes.begin(); attribute != mVertexShader->mAttributes.end(); attribute++)
   1588     {
   1589         int location = getAttributeBinding(attribute->name);
   1590 
   1591         if (location == -1)   // Not set by glBindAttribLocation
   1592         {
   1593             int rows = VariableRowCount(attribute->type);
   1594             int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
   1595 
   1596             if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
   1597             {
   1598                 appendToInfoLog("Too many active attributes (%s)", attribute->name.c_str());
   1599 
   1600                 return false;   // Fail to link
   1601             }
   1602 
   1603             mLinkedAttribute[availableIndex] = *attribute;
   1604         }
   1605     }
   1606 
   1607     for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
   1608     {
   1609         int index = mVertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
   1610         int rows = std::max(VariableRowCount(mLinkedAttribute[attributeIndex].type), 1);
   1611 
   1612         for (int r = 0; r < rows; r++)
   1613         {
   1614             mSemanticIndex[attributeIndex++] = index++;
   1615         }
   1616     }
   1617 
   1618     return true;
   1619 }
   1620 
   1621 int Program::getAttributeBinding(const std::string &name)
   1622 {
   1623     for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
   1624     {
   1625         if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
   1626         {
   1627             return location;
   1628         }
   1629     }
   1630 
   1631     return -1;
   1632 }
   1633 
   1634 bool Program::linkUniforms(ID3DXConstantTable *constantTable)
   1635 {
   1636     D3DXCONSTANTTABLE_DESC constantTableDescription;
   1637     D3DXCONSTANT_DESC constantDescription;
   1638     UINT descriptionCount = 1;
   1639 
   1640     constantTable->GetDesc(&constantTableDescription);
   1641 
   1642     for (unsigned int constantIndex = 0; constantIndex < constantTableDescription.Constants; constantIndex++)
   1643     {
   1644         D3DXHANDLE constantHandle = constantTable->GetConstant(0, constantIndex);
   1645         constantTable->GetConstantDesc(constantHandle, &constantDescription, &descriptionCount);
   1646 
   1647         if (!defineUniform(constantHandle, constantDescription))
   1648         {
   1649             return false;
   1650         }
   1651     }
   1652 
   1653     return true;
   1654 }
   1655 
   1656 // Adds the description of a constant found in the binary shader to the list of uniforms
   1657 // Returns true if succesful (uniform not already defined)
   1658 bool Program::defineUniform(const D3DXHANDLE &constantHandle, const D3DXCONSTANT_DESC &constantDescription, std::string name)
   1659 {
   1660     if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
   1661     {
   1662         for (unsigned int samplerIndex = constantDescription.RegisterIndex; samplerIndex < constantDescription.RegisterIndex + constantDescription.RegisterCount; samplerIndex++)
   1663         {
   1664             ASSERT(samplerIndex < sizeof(mSamplers)/sizeof(mSamplers[0]));
   1665 
   1666             mSamplers[samplerIndex].active = true;
   1667             mSamplers[samplerIndex].type = (constantDescription.Type == D3DXPT_SAMPLERCUBE) ? SAMPLER_CUBE : SAMPLER_2D;
   1668             mSamplers[samplerIndex].logicalTextureUnit = 0;
   1669             mSamplers[samplerIndex].dirty = true;
   1670         }
   1671     }
   1672 
   1673     switch(constantDescription.Class)
   1674     {
   1675       case D3DXPC_STRUCT:
   1676         {
   1677             for (unsigned int arrayIndex = 0; arrayIndex < constantDescription.Elements; arrayIndex++)
   1678             {
   1679                 for (unsigned int field = 0; field < constantDescription.StructMembers; field++)
   1680                 {
   1681                     D3DXHANDLE fieldHandle = mConstantTablePS->GetConstant(constantHandle, field);
   1682 
   1683                     D3DXCONSTANT_DESC fieldDescription;
   1684                     UINT descriptionCount = 1;
   1685 
   1686                     mConstantTablePS->GetConstantDesc(fieldHandle, &fieldDescription, &descriptionCount);
   1687 
   1688                     std::string structIndex = (constantDescription.Elements > 1) ? ("[" + str(arrayIndex) + "]") : "";
   1689 
   1690                     if (!defineUniform(fieldHandle, fieldDescription, name + constantDescription.Name + structIndex + "."))
   1691                     {
   1692                         return false;
   1693                     }
   1694                 }
   1695             }
   1696 
   1697             return true;
   1698         }
   1699       case D3DXPC_SCALAR:
   1700       case D3DXPC_VECTOR:
   1701       case D3DXPC_MATRIX_COLUMNS:
   1702       case D3DXPC_OBJECT:
   1703         return defineUniform(constantDescription, name + constantDescription.Name);
   1704       default:
   1705         UNREACHABLE();
   1706         return false;
   1707     }
   1708 }
   1709 
   1710 bool Program::defineUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name)
   1711 {
   1712     Uniform *uniform = createUniform(constantDescription, name);
   1713 
   1714     if(!uniform)
   1715     {
   1716         return false;
   1717     }
   1718 
   1719     // Check if already defined
   1720     GLint location = getUniformLocation(name.c_str(), true);
   1721     GLenum type = uniform->type;
   1722 
   1723     if (location >= 0)
   1724     {
   1725         delete uniform;
   1726 
   1727         if (mUniforms[mUniformIndex[location].index]->type != type)
   1728         {
   1729             return false;
   1730         }
   1731         else
   1732         {
   1733             return true;
   1734         }
   1735     }
   1736 
   1737     mUniforms.push_back(uniform);
   1738     unsigned int uniformIndex = mUniforms.size() - 1;
   1739 
   1740     for (unsigned int i = 0; i < uniform->arraySize; ++i)
   1741     {
   1742         mUniformIndex.push_back(UniformLocation(name, i, uniformIndex));
   1743     }
   1744 
   1745     return true;
   1746 }
   1747 
   1748 Uniform *Program::createUniform(const D3DXCONSTANT_DESC &constantDescription, std::string &name)
   1749 {
   1750     if (constantDescription.Rows == 1)   // Vectors and scalars
   1751     {
   1752         switch (constantDescription.Type)
   1753         {
   1754           case D3DXPT_SAMPLER2D:
   1755             switch (constantDescription.Columns)
   1756             {
   1757               case 1: return new Uniform(GL_SAMPLER_2D, name, constantDescription.Elements);
   1758               default: UNREACHABLE();
   1759             }
   1760             break;
   1761           case D3DXPT_SAMPLERCUBE:
   1762             switch (constantDescription.Columns)
   1763             {
   1764               case 1: return new Uniform(GL_SAMPLER_CUBE, name, constantDescription.Elements);
   1765               default: UNREACHABLE();
   1766             }
   1767             break;
   1768           case D3DXPT_BOOL:
   1769             switch (constantDescription.Columns)
   1770             {
   1771               case 1: return new Uniform(GL_BOOL, name, constantDescription.Elements);
   1772               case 2: return new Uniform(GL_BOOL_VEC2, name, constantDescription.Elements);
   1773               case 3: return new Uniform(GL_BOOL_VEC3, name, constantDescription.Elements);
   1774               case 4: return new Uniform(GL_BOOL_VEC4, name, constantDescription.Elements);
   1775               default: UNREACHABLE();
   1776             }
   1777             break;
   1778           case D3DXPT_INT:
   1779             switch (constantDescription.Columns)
   1780             {
   1781               case 1: return new Uniform(GL_INT, name, constantDescription.Elements);
   1782               case 2: return new Uniform(GL_INT_VEC2, name, constantDescription.Elements);
   1783               case 3: return new Uniform(GL_INT_VEC3, name, constantDescription.Elements);
   1784               case 4: return new Uniform(GL_INT_VEC4, name, constantDescription.Elements);
   1785               default: UNREACHABLE();
   1786             }
   1787             break;
   1788           case D3DXPT_FLOAT:
   1789             switch (constantDescription.Columns)
   1790             {
   1791               case 1: return new Uniform(GL_FLOAT, name, constantDescription.Elements);
   1792               case 2: return new Uniform(GL_FLOAT_VEC2, name, constantDescription.Elements);
   1793               case 3: return new Uniform(GL_FLOAT_VEC3, name, constantDescription.Elements);
   1794               case 4: return new Uniform(GL_FLOAT_VEC4, name, constantDescription.Elements);
   1795               default: UNREACHABLE();
   1796             }
   1797             break;
   1798           default:
   1799             UNREACHABLE();
   1800         }
   1801     }
   1802     else if (constantDescription.Rows == constantDescription.Columns)  // Square matrices
   1803     {
   1804         switch (constantDescription.Type)
   1805         {
   1806           case D3DXPT_FLOAT:
   1807             switch (constantDescription.Rows)
   1808             {
   1809               case 2: return new Uniform(GL_FLOAT_MAT2, name, constantDescription.Elements);
   1810               case 3: return new Uniform(GL_FLOAT_MAT3, name, constantDescription.Elements);
   1811               case 4: return new Uniform(GL_FLOAT_MAT4, name, constantDescription.Elements);
   1812               default: UNREACHABLE();
   1813             }
   1814             break;
   1815           default: UNREACHABLE();
   1816         }
   1817     }
   1818     else UNREACHABLE();
   1819 
   1820     return 0;
   1821 }
   1822 
   1823 // This method needs to match OutputHLSL::decorate
   1824 std::string Program::decorate(const std::string &string)
   1825 {
   1826     if (string.substr(0, 3) != "gl_" && string.substr(0, 3) != "dx_")
   1827     {
   1828         return "_" + string;
   1829     }
   1830     else
   1831     {
   1832         return string;
   1833     }
   1834 }
   1835 
   1836 std::string Program::undecorate(const std::string &string)
   1837 {
   1838     if (string.substr(0, 1) == "_")
   1839     {
   1840         return string.substr(1);
   1841     }
   1842     else
   1843     {
   1844         return string;
   1845     }
   1846 }
   1847 
   1848 bool Program::applyUniform1bv(GLint location, GLsizei count, const GLboolean *v)
   1849 {
   1850     BOOL *vector = new BOOL[count];
   1851     for (int i = 0; i < count; i++)
   1852     {
   1853         if (v[i] == GL_FALSE)
   1854             vector[i] = 0;
   1855         else
   1856             vector[i] = 1;
   1857     }
   1858 
   1859     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
   1860 
   1861     D3DXHANDLE constantPS;
   1862     D3DXHANDLE constantVS;
   1863     getConstantHandles(targetUniform, &constantPS, &constantVS);
   1864 
   1865     IDirect3DDevice9 *device = getDevice();
   1866 
   1867     if (constantPS)
   1868     {
   1869         mConstantTablePS->SetBoolArray(device, constantPS, vector, count);
   1870     }
   1871 
   1872     if (constantVS)
   1873     {
   1874         mConstantTableVS->SetBoolArray(device, constantVS, vector, count);
   1875     }
   1876 
   1877     delete [] vector;
   1878 
   1879     return true;
   1880 }
   1881 
   1882 bool Program::applyUniform2bv(GLint location, GLsizei count, const GLboolean *v)
   1883 {
   1884     D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
   1885 
   1886     for (int i = 0; i < count; i++)
   1887     {
   1888         vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
   1889                                 (v[1] == GL_FALSE ? 0.0f : 1.0f), 0, 0);
   1890 
   1891         v += 2;
   1892     }
   1893 
   1894     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
   1895 
   1896     D3DXHANDLE constantPS;
   1897     D3DXHANDLE constantVS;
   1898     getConstantHandles(targetUniform, &constantPS, &constantVS);
   1899     IDirect3DDevice9 *device = getDevice();
   1900 
   1901     if (constantPS)
   1902     {
   1903         mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
   1904     }
   1905 
   1906     if (constantVS)
   1907     {
   1908         mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
   1909     }
   1910 
   1911     delete[] vector;
   1912 
   1913     return true;
   1914 }
   1915 
   1916 bool Program::applyUniform3bv(GLint location, GLsizei count, const GLboolean *v)
   1917 {
   1918     D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
   1919 
   1920     for (int i = 0; i < count; i++)
   1921     {
   1922         vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
   1923                                 (v[1] == GL_FALSE ? 0.0f : 1.0f),
   1924                                 (v[2] == GL_FALSE ? 0.0f : 1.0f), 0);
   1925 
   1926         v += 3;
   1927     }
   1928 
   1929     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
   1930 
   1931     D3DXHANDLE constantPS;
   1932     D3DXHANDLE constantVS;
   1933     getConstantHandles(targetUniform, &constantPS, &constantVS);
   1934     IDirect3DDevice9 *device = getDevice();
   1935 
   1936     if (constantPS)
   1937     {
   1938         mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
   1939     }
   1940 
   1941     if (constantVS)
   1942     {
   1943         mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
   1944     }
   1945 
   1946     delete[] vector;
   1947 
   1948     return true;
   1949 }
   1950 
   1951 bool Program::applyUniform4bv(GLint location, GLsizei count, const GLboolean *v)
   1952 {
   1953     D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
   1954 
   1955     for (int i = 0; i < count; i++)
   1956     {
   1957         vector[i] = D3DXVECTOR4((v[0] == GL_FALSE ? 0.0f : 1.0f),
   1958                                 (v[1] == GL_FALSE ? 0.0f : 1.0f),
   1959                                 (v[2] == GL_FALSE ? 0.0f : 1.0f),
   1960                                 (v[3] == GL_FALSE ? 0.0f : 1.0f));
   1961 
   1962         v += 3;
   1963     }
   1964 
   1965     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
   1966 
   1967     D3DXHANDLE constantPS;
   1968     D3DXHANDLE constantVS;
   1969     getConstantHandles(targetUniform, &constantPS, &constantVS);
   1970     IDirect3DDevice9 *device = getDevice();
   1971 
   1972     if (constantPS)
   1973     {
   1974         mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
   1975     }
   1976 
   1977     if (constantVS)
   1978     {
   1979         mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
   1980     }
   1981 
   1982     delete [] vector;
   1983 
   1984     return true;
   1985 }
   1986 
   1987 bool Program::applyUniform1fv(GLint location, GLsizei count, const GLfloat *v)
   1988 {
   1989     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
   1990 
   1991     D3DXHANDLE constantPS;
   1992     D3DXHANDLE constantVS;
   1993     getConstantHandles(targetUniform, &constantPS, &constantVS);
   1994     IDirect3DDevice9 *device = getDevice();
   1995 
   1996     if (constantPS)
   1997     {
   1998         mConstantTablePS->SetFloatArray(device, constantPS, v, count);
   1999     }
   2000 
   2001     if (constantVS)
   2002     {
   2003         mConstantTableVS->SetFloatArray(device, constantVS, v, count);
   2004     }
   2005 
   2006     return true;
   2007 }
   2008 
   2009 bool Program::applyUniform2fv(GLint location, GLsizei count, const GLfloat *v)
   2010 {
   2011     D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
   2012 
   2013     for (int i = 0; i < count; i++)
   2014     {
   2015         vector[i] = D3DXVECTOR4(v[0], v[1], 0, 0);
   2016 
   2017         v += 2;
   2018     }
   2019 
   2020     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
   2021 
   2022     D3DXHANDLE constantPS;
   2023     D3DXHANDLE constantVS;
   2024     getConstantHandles(targetUniform, &constantPS, &constantVS);
   2025     IDirect3DDevice9 *device = getDevice();
   2026 
   2027     if (constantPS)
   2028     {
   2029         mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
   2030     }
   2031 
   2032     if (constantVS)
   2033     {
   2034         mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
   2035     }
   2036 
   2037     delete[] vector;
   2038 
   2039     return true;
   2040 }
   2041 
   2042 bool Program::applyUniform3fv(GLint location, GLsizei count, const GLfloat *v)
   2043 {
   2044     D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
   2045 
   2046     for (int i = 0; i < count; i++)
   2047     {
   2048         vector[i] = D3DXVECTOR4(v[0], v[1], v[2], 0);
   2049 
   2050         v += 3;
   2051     }
   2052 
   2053     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
   2054 
   2055     D3DXHANDLE constantPS;
   2056     D3DXHANDLE constantVS;
   2057     getConstantHandles(targetUniform, &constantPS, &constantVS);
   2058     IDirect3DDevice9 *device = getDevice();
   2059 
   2060     if (constantPS)
   2061     {
   2062         mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
   2063     }
   2064 
   2065     if (constantVS)
   2066     {
   2067         mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
   2068     }
   2069 
   2070     delete[] vector;
   2071 
   2072     return true;
   2073 }
   2074 
   2075 bool Program::applyUniform4fv(GLint location, GLsizei count, const GLfloat *v)
   2076 {
   2077     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
   2078 
   2079     D3DXHANDLE constantPS;
   2080     D3DXHANDLE constantVS;
   2081     getConstantHandles(targetUniform, &constantPS, &constantVS);
   2082     IDirect3DDevice9 *device = getDevice();
   2083 
   2084     if (constantPS)
   2085     {
   2086         mConstantTablePS->SetVectorArray(device, constantPS, (D3DXVECTOR4*)v, count);
   2087     }
   2088 
   2089     if (constantVS)
   2090     {
   2091         mConstantTableVS->SetVectorArray(device, constantVS, (D3DXVECTOR4*)v, count);
   2092     }
   2093 
   2094     return true;
   2095 }
   2096 
   2097 bool Program::applyUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
   2098 {
   2099     D3DXMATRIX *matrix = new D3DXMATRIX[count];
   2100 
   2101     for (int i = 0; i < count; i++)
   2102     {
   2103         matrix[i] = D3DXMATRIX(value[0], value[2], 0, 0,
   2104                                value[1], value[3], 0, 0,
   2105                                0,        0,        1, 0,
   2106                                0,        0,        0, 1);
   2107 
   2108         value += 4;
   2109     }
   2110 
   2111     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
   2112 
   2113     D3DXHANDLE constantPS;
   2114     D3DXHANDLE constantVS;
   2115     getConstantHandles(targetUniform, &constantPS, &constantVS);
   2116     IDirect3DDevice9 *device = getDevice();
   2117 
   2118     if (constantPS)
   2119     {
   2120         mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
   2121     }
   2122 
   2123     if (constantVS)
   2124     {
   2125         mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
   2126     }
   2127 
   2128     delete[] matrix;
   2129 
   2130     return true;
   2131 }
   2132 
   2133 bool Program::applyUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
   2134 {
   2135     D3DXMATRIX *matrix = new D3DXMATRIX[count];
   2136 
   2137     for (int i = 0; i < count; i++)
   2138     {
   2139         matrix[i] = D3DXMATRIX(value[0], value[3], value[6], 0,
   2140                                value[1], value[4], value[7], 0,
   2141                                value[2], value[5], value[8], 0,
   2142                                0,        0,        0,        1);
   2143 
   2144         value += 9;
   2145     }
   2146 
   2147     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
   2148 
   2149     D3DXHANDLE constantPS;
   2150     D3DXHANDLE constantVS;
   2151     getConstantHandles(targetUniform, &constantPS, &constantVS);
   2152     IDirect3DDevice9 *device = getDevice();
   2153 
   2154     if (constantPS)
   2155     {
   2156         mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
   2157     }
   2158 
   2159     if (constantVS)
   2160     {
   2161         mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
   2162     }
   2163 
   2164     delete[] matrix;
   2165 
   2166     return true;
   2167 }
   2168 
   2169 bool Program::applyUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
   2170 {
   2171     D3DXMATRIX *matrix = new D3DXMATRIX[count];
   2172 
   2173     for (int i = 0; i < count; i++)
   2174     {
   2175         matrix[i] = D3DXMATRIX(value[0], value[4], value[8],  value[12],
   2176                                value[1], value[5], value[9],  value[13],
   2177                                value[2], value[6], value[10], value[14],
   2178                                value[3], value[7], value[11], value[15]);
   2179 
   2180         value += 16;
   2181     }
   2182 
   2183     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
   2184 
   2185     D3DXHANDLE constantPS;
   2186     D3DXHANDLE constantVS;
   2187     getConstantHandles(targetUniform, &constantPS, &constantVS);
   2188     IDirect3DDevice9 *device = getDevice();
   2189 
   2190     if (constantPS)
   2191     {
   2192         mConstantTablePS->SetMatrixTransposeArray(device, constantPS, matrix, count);
   2193     }
   2194 
   2195     if (constantVS)
   2196     {
   2197         mConstantTableVS->SetMatrixTransposeArray(device, constantVS, matrix, count);
   2198     }
   2199 
   2200     delete[] matrix;
   2201 
   2202     return true;
   2203 }
   2204 
   2205 bool Program::applyUniform1iv(GLint location, GLsizei count, const GLint *v)
   2206 {
   2207     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
   2208 
   2209     D3DXHANDLE constantPS;
   2210     D3DXHANDLE constantVS;
   2211     getConstantHandles(targetUniform, &constantPS, &constantVS);
   2212     IDirect3DDevice9 *device = getDevice();
   2213 
   2214     if (constantPS)
   2215     {
   2216         D3DXCONSTANT_DESC constantDescription;
   2217         UINT descriptionCount = 1;
   2218         HRESULT result = mConstantTablePS->GetConstantDesc(constantPS, &constantDescription, &descriptionCount);
   2219 
   2220         if (FAILED(result))
   2221         {
   2222             return false;
   2223         }
   2224 
   2225         if (constantDescription.RegisterSet == D3DXRS_SAMPLER)
   2226         {
   2227             unsigned int firstIndex = mConstantTablePS->GetSamplerIndex(constantPS);
   2228 
   2229             for (int i = 0; i < count; i++)
   2230             {
   2231                 unsigned int samplerIndex = firstIndex + i;
   2232 
   2233                 if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
   2234                 {
   2235                     ASSERT(mSamplers[samplerIndex].active);
   2236                     mSamplers[samplerIndex].logicalTextureUnit = v[i];
   2237                     mSamplers[samplerIndex].dirty = true;
   2238                 }
   2239             }
   2240 
   2241             return true;
   2242         }
   2243     }
   2244 
   2245     if (constantPS)
   2246     {
   2247         mConstantTablePS->SetIntArray(device, constantPS, v, count);
   2248     }
   2249 
   2250     if (constantVS)
   2251     {
   2252         mConstantTableVS->SetIntArray(device, constantVS, v, count);
   2253     }
   2254 
   2255     return true;
   2256 }
   2257 
   2258 bool Program::applyUniform2iv(GLint location, GLsizei count, const GLint *v)
   2259 {
   2260     D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
   2261 
   2262     for (int i = 0; i < count; i++)
   2263     {
   2264         vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], 0, 0);
   2265 
   2266         v += 2;
   2267     }
   2268 
   2269     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
   2270 
   2271     D3DXHANDLE constantPS;
   2272     D3DXHANDLE constantVS;
   2273     getConstantHandles(targetUniform, &constantPS, &constantVS);
   2274     IDirect3DDevice9 *device = getDevice();
   2275 
   2276     if (constantPS)
   2277     {
   2278         mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
   2279     }
   2280 
   2281     if (constantVS)
   2282     {
   2283         mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
   2284     }
   2285 
   2286     delete[] vector;
   2287 
   2288     return true;
   2289 }
   2290 
   2291 bool Program::applyUniform3iv(GLint location, GLsizei count, const GLint *v)
   2292 {
   2293     D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
   2294 
   2295     for (int i = 0; i < count; i++)
   2296     {
   2297         vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], (float)v[2], 0);
   2298 
   2299         v += 3;
   2300     }
   2301 
   2302     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
   2303 
   2304     D3DXHANDLE constantPS;
   2305     D3DXHANDLE constantVS;
   2306     getConstantHandles(targetUniform, &constantPS, &constantVS);
   2307     IDirect3DDevice9 *device = getDevice();
   2308 
   2309     if (constantPS)
   2310     {
   2311         mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
   2312     }
   2313 
   2314     if (constantVS)
   2315     {
   2316         mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
   2317     }
   2318 
   2319     delete[] vector;
   2320 
   2321     return true;
   2322 }
   2323 
   2324 bool Program::applyUniform4iv(GLint location, GLsizei count, const GLint *v)
   2325 {
   2326     D3DXVECTOR4 *vector = new D3DXVECTOR4[count];
   2327 
   2328     for (int i = 0; i < count; i++)
   2329     {
   2330         vector[i] = D3DXVECTOR4((float)v[0], (float)v[1], (float)v[2], (float)v[3]);
   2331 
   2332         v += 4;
   2333     }
   2334 
   2335     Uniform *targetUniform = mUniforms[mUniformIndex[location].index];
   2336 
   2337     D3DXHANDLE constantPS;
   2338     D3DXHANDLE constantVS;
   2339     getConstantHandles(targetUniform, &constantPS, &constantVS);
   2340     IDirect3DDevice9 *device = getDevice();
   2341 
   2342     if (constantPS)
   2343     {
   2344         mConstantTablePS->SetVectorArray(device, constantPS, vector, count);
   2345     }
   2346 
   2347     if (constantVS)
   2348     {
   2349         mConstantTableVS->SetVectorArray(device, constantVS, vector, count);
   2350     }
   2351 
   2352     delete [] vector;
   2353 
   2354     return true;
   2355 }
   2356 
   2357 void Program::appendToInfoLog(const char *format, ...)
   2358 {
   2359     if (!format)
   2360     {
   2361         return;
   2362     }
   2363 
   2364     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 
   2371     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 
   2390 void Program::resetInfoLog()
   2391 {
   2392     if (mInfoLog)
   2393     {
   2394         delete [] mInfoLog;
   2395         mInfoLog = NULL;
   2396     }
   2397 }
   2398 
   2399 // Returns the program object to an unlinked state, after detaching a shader, before re-linking, or at destruction
   2400 void Program::unlink(bool destroy)
   2401 {
   2402     if (destroy)   // Object being destructed
   2403     {
   2404         if (mFragmentShader)
   2405         {
   2406             mFragmentShader->release();
   2407             mFragmentShader = NULL;
   2408         }
   2409 
   2410         if (mVertexShader)
   2411         {
   2412             mVertexShader->release();
   2413             mVertexShader = NULL;
   2414         }
   2415     }
   2416 
   2417     if (mPixelExecutable)
   2418     {
   2419         mPixelExecutable->Release();
   2420         mPixelExecutable = NULL;
   2421     }
   2422 
   2423     if (mVertexExecutable)
   2424     {
   2425         mVertexExecutable->Release();
   2426         mVertexExecutable = NULL;
   2427     }
   2428 
   2429     if (mConstantTablePS)
   2430     {
   2431         mConstantTablePS->Release();
   2432         mConstantTablePS = NULL;
   2433     }
   2434 
   2435     if (mConstantTableVS)
   2436     {
   2437         mConstantTableVS->Release();
   2438         mConstantTableVS = NULL;
   2439     }
   2440 
   2441     for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
   2442     {
   2443         mLinkedAttribute[index].name.clear();
   2444         mSemanticIndex[index] = -1;
   2445     }
   2446 
   2447     for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
   2448     {
   2449         mSamplers[index].active = false;
   2450         mSamplers[index].dirty = true;
   2451     }
   2452 
   2453     while (!mUniforms.empty())
   2454     {
   2455         delete mUniforms.back();
   2456         mUniforms.pop_back();
   2457     }
   2458 
   2459     mDxDepthRangeLocation = -1;
   2460     mDxDepthLocation = -1;
   2461     mDxViewportLocation = -1;
   2462     mDxHalfPixelSizeLocation = -1;
   2463     mDxFrontCCWLocation = -1;
   2464     mDxPointsOrLinesLocation = -1;
   2465 
   2466     mUniformIndex.clear();
   2467 
   2468     mPixelHLSL.clear();
   2469     mVertexHLSL.clear();
   2470 
   2471     delete[] mInfoLog;
   2472     mInfoLog = NULL;
   2473 
   2474     mLinked = false;
   2475 }
   2476 
   2477 bool Program::isLinked()
   2478 {
   2479     return mLinked;
   2480 }
   2481 
   2482 bool Program::isValidated() const
   2483 {
   2484     return mValidated;
   2485 }
   2486 
   2487 void Program::release()
   2488 {
   2489     mRefCount--;
   2490 
   2491     if (mRefCount == 0 && mDeleteStatus)
   2492     {
   2493         mResourceManager->deleteProgram(mHandle);
   2494     }
   2495 }
   2496 
   2497 void Program::addRef()
   2498 {
   2499     mRefCount++;
   2500 }
   2501 
   2502 unsigned int Program::getRefCount() const
   2503 {
   2504     return mRefCount;
   2505 }
   2506 
   2507 unsigned int Program::getSerial() const
   2508 {
   2509     return mSerial;
   2510 }
   2511 
   2512 unsigned int Program::issueSerial()
   2513 {
   2514     return mCurrentSerial++;
   2515 }
   2516 
   2517 int Program::getInfoLogLength() const
   2518 {
   2519     if (!mInfoLog)
   2520     {
   2521         return 0;
   2522     }
   2523     else
   2524     {
   2525        return strlen(mInfoLog) + 1;
   2526     }
   2527 }
   2528 
   2529 void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
   2530 {
   2531     int index = 0;
   2532 
   2533     if (mInfoLog)
   2534     {
   2535         while (index < bufSize - 1 && index < (int)strlen(mInfoLog))
   2536         {
   2537             infoLog[index] = mInfoLog[index];
   2538             index++;
   2539         }
   2540     }
   2541 
   2542     if (bufSize)
   2543     {
   2544         infoLog[index] = '\0';
   2545     }
   2546 
   2547     if (length)
   2548     {
   2549         *length = index;
   2550     }
   2551 }
   2552 
   2553 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
   2554 {
   2555     int total = 0;
   2556 
   2557     if (mVertexShader)
   2558     {
   2559         if (total < maxCount)
   2560         {
   2561             shaders[total] = mVertexShader->getHandle();
   2562         }
   2563 
   2564         total++;
   2565     }
   2566 
   2567     if (mFragmentShader)
   2568     {
   2569         if (total < maxCount)
   2570         {
   2571             shaders[total] = mFragmentShader->getHandle();
   2572         }
   2573 
   2574         total++;
   2575     }
   2576 
   2577     if (count)
   2578     {
   2579         *count = total;
   2580     }
   2581 }
   2582 
   2583 void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
   2584 {
   2585     // Skip over inactive attributes
   2586     unsigned int activeAttribute = 0;
   2587     unsigned int attribute;
   2588     for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
   2589     {
   2590         if (mLinkedAttribute[attribute].name.empty())
   2591         {
   2592             continue;
   2593         }
   2594 
   2595         if (activeAttribute == index)
   2596         {
   2597             break;
   2598         }
   2599 
   2600         activeAttribute++;
   2601     }
   2602 
   2603     if (bufsize > 0)
   2604     {
   2605         const char *string = mLinkedAttribute[attribute].name.c_str();
   2606 
   2607         strncpy(name, string, bufsize);
   2608         name[bufsize - 1] = '\0';
   2609 
   2610         if (length)
   2611         {
   2612             *length = strlen(name);
   2613         }
   2614     }
   2615 
   2616     *size = 1;   // Always a single 'type' instance
   2617 
   2618     *type = mLinkedAttribute[attribute].type;
   2619 }
   2620 
   2621 GLint Program::getActiveAttributeCount()
   2622 {
   2623     int count = 0;
   2624 
   2625     for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
   2626     {
   2627         if (!mLinkedAttribute[attributeIndex].name.empty())
   2628         {
   2629             count++;
   2630         }
   2631     }
   2632 
   2633     return count;
   2634 }
   2635 
   2636 GLint Program::getActiveAttributeMaxLength()
   2637 {
   2638     int maxLength = 0;
   2639 
   2640     for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
   2641     {
   2642         if (!mLinkedAttribute[attributeIndex].name.empty())
   2643         {
   2644             maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength);
   2645         }
   2646     }
   2647 
   2648     return maxLength;
   2649 }
   2650 
   2651 void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
   2652 {
   2653     // Skip over internal uniforms
   2654     unsigned int activeUniform = 0;
   2655     unsigned int uniform;
   2656     for (uniform = 0; uniform < mUniforms.size(); uniform++)
   2657     {
   2658         if (mUniforms[uniform]->name.substr(0, 3) == "dx_")
   2659         {
   2660             continue;
   2661         }
   2662 
   2663         if (activeUniform == index)
   2664         {
   2665             break;
   2666         }
   2667 
   2668         activeUniform++;
   2669     }
   2670 
   2671     ASSERT(uniform < mUniforms.size());   // index must be smaller than getActiveUniformCount()
   2672 
   2673     if (bufsize > 0)
   2674     {
   2675         std::string string = undecorate(mUniforms[uniform]->name);
   2676 
   2677         if (mUniforms[uniform]->arraySize != 1)
   2678         {
   2679             string += "[0]";
   2680         }
   2681 
   2682         strncpy(name, string.c_str(), bufsize);
   2683         name[bufsize - 1] = '\0';
   2684 
   2685         if (length)
   2686         {
   2687             *length = strlen(name);
   2688         }
   2689     }
   2690 
   2691     *size = mUniforms[uniform]->arraySize;
   2692 
   2693     *type = mUniforms[uniform]->type;
   2694 }
   2695 
   2696 GLint Program::getActiveUniformCount()
   2697 {
   2698     int count = 0;
   2699 
   2700     unsigned int numUniforms = mUniforms.size();
   2701     for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
   2702     {
   2703         if (mUniforms[uniformIndex]->name.substr(0, 3) != "dx_")
   2704         {
   2705             count++;
   2706         }
   2707     }
   2708 
   2709     return count;
   2710 }
   2711 
   2712 GLint Program::getActiveUniformMaxLength()
   2713 {
   2714     int maxLength = 0;
   2715 
   2716     unsigned int numUniforms = mUniforms.size();
   2717     for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
   2718     {
   2719         if (!mUniforms[uniformIndex]->name.empty() && mUniforms[uniformIndex]->name.substr(0, 3) != "dx_")
   2720         {
   2721             maxLength = std::max((int)(undecorate(mUniforms[uniformIndex]->name).length() + 1), maxLength);
   2722         }
   2723     }
   2724 
   2725     return maxLength;
   2726 }
   2727 
   2728 void Program::flagForDeletion()
   2729 {
   2730     mDeleteStatus = true;
   2731 }
   2732 
   2733 bool Program::isFlaggedForDeletion() const
   2734 {
   2735     return mDeleteStatus;
   2736 }
   2737 
   2738 void Program::validate()
   2739 {
   2740     resetInfoLog();
   2741 
   2742     if (!isLinked())
   2743     {
   2744         appendToInfoLog("Program has not been successfully linked.");
   2745         mValidated = false;
   2746     }
   2747     else
   2748     {
   2749         applyUniforms();
   2750         if (!validateSamplers())
   2751         {
   2752             appendToInfoLog("Samplers of conflicting types refer to the same texture image unit.");
   2753             mValidated = false;
   2754         }
   2755         else
   2756         {
   2757             mValidated = true;
   2758         }
   2759     }
   2760 }
   2761 
   2762 bool Program::validateSamplers() const
   2763 {
   2764     // if any two active samplers in a program are of different types, but refer to the same
   2765     // texture image unit, and this is the current program, then ValidateProgram will fail, and
   2766     // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
   2767     std::map<int, SamplerType> samplerMap;
   2768     for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i)
   2769     {
   2770         if (mSamplers[i].active)
   2771         {
   2772             if (samplerMap.find(mSamplers[i].logicalTextureUnit) != samplerMap.end())
   2773             {
   2774                 if (mSamplers[i].type != samplerMap[mSamplers[i].logicalTextureUnit])
   2775                     return false;
   2776             }
   2777             else
   2778             {
   2779                 samplerMap[mSamplers[i].logicalTextureUnit] = mSamplers[i].type;
   2780             }
   2781         }
   2782     }
   2783 
   2784     return true;
   2785 }
   2786 
   2787 void Program::getConstantHandles(Uniform *targetUniform, D3DXHANDLE *constantPS, D3DXHANDLE *constantVS)
   2788 {
   2789     if (!targetUniform->handlesSet)
   2790     {
   2791         targetUniform->psHandle = mConstantTablePS->GetConstantByName(0, targetUniform->name.c_str());
   2792         targetUniform->vsHandle = mConstantTableVS->GetConstantByName(0, targetUniform->name.c_str());
   2793         targetUniform->handlesSet = true;
   2794     }
   2795 
   2796     *constantPS = targetUniform->psHandle;
   2797     *constantVS = targetUniform->vsHandle;
   2798 }
   2799 
   2800 GLint Program::getDxDepthRangeLocation() const
   2801 {
   2802     return mDxDepthRangeLocation;
   2803 }
   2804 
   2805 GLint Program::getDxDepthLocation() const
   2806 {
   2807     return mDxDepthLocation;
   2808 }
   2809 
   2810 GLint Program::getDxViewportLocation() const
   2811 {
   2812     return mDxViewportLocation;
   2813 }
   2814 
   2815 GLint Program::getDxHalfPixelSizeLocation() const
   2816 {
   2817     return mDxHalfPixelSizeLocation;
   2818 }
   2819 
   2820 GLint Program::getDxFrontCCWLocation() const
   2821 {
   2822     return mDxFrontCCWLocation;
   2823 }
   2824 
   2825 GLint Program::getDxPointsOrLinesLocation() const
   2826 {
   2827     return mDxPointsOrLinesLocation;
   2828 }
   2829 
   2830 }
   2831