Home | History | Annotate | Download | only in libGLESv2
      1 #include "precompiled.h"
      2 //
      3 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style license that can be
      5 // found in the LICENSE file.
      6 //
      7 
      8 // Program.cpp: Implements the gl::Program class. Implements GL program objects
      9 // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
     10 
     11 #include "libGLESv2/Program.h"
     12 #include "libGLESv2/ProgramBinary.h"
     13 #include "libGLESv2/ResourceManager.h"
     14 
     15 namespace gl
     16 {
     17 const char * const g_fakepath = "C:\\fakepath";
     18 
     19 AttributeBindings::AttributeBindings()
     20 {
     21 }
     22 
     23 AttributeBindings::~AttributeBindings()
     24 {
     25 }
     26 
     27 InfoLog::InfoLog() : mInfoLog(NULL)
     28 {
     29 }
     30 
     31 InfoLog::~InfoLog()
     32 {
     33     delete[] mInfoLog;
     34 }
     35 
     36 
     37 int InfoLog::getLength() const
     38 {
     39     if (!mInfoLog)
     40     {
     41         return 0;
     42     }
     43     else
     44     {
     45        return strlen(mInfoLog) + 1;
     46     }
     47 }
     48 
     49 void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog)
     50 {
     51     int index = 0;
     52 
     53     if (bufSize > 0)
     54     {
     55         if (mInfoLog)
     56         {
     57             index = std::min(bufSize - 1, (int)strlen(mInfoLog));
     58             memcpy(infoLog, mInfoLog, index);
     59         }
     60 
     61         infoLog[index] = '\0';
     62     }
     63 
     64     if (length)
     65     {
     66         *length = index;
     67     }
     68 }
     69 
     70 // append a santized message to the program info log.
     71 // The D3D compiler includes a fake file path in some of the warning or error
     72 // messages, so lets remove all occurrences of this fake file path from the log.
     73 void InfoLog::appendSanitized(const char *message)
     74 {
     75     std::string msg(message);
     76 
     77     size_t found;
     78     do
     79     {
     80         found = msg.find(g_fakepath);
     81         if (found != std::string::npos)
     82         {
     83             msg.erase(found, strlen(g_fakepath));
     84         }
     85     }
     86     while (found != std::string::npos);
     87 
     88     append("%s", msg.c_str());
     89 }
     90 
     91 void InfoLog::append(const char *format, ...)
     92 {
     93     if (!format)
     94     {
     95         return;
     96     }
     97 
     98     char info[1024];
     99 
    100     va_list vararg;
    101     va_start(vararg, format);
    102     vsnprintf(info, sizeof(info), format, vararg);
    103     va_end(vararg);
    104 
    105     size_t infoLength = strlen(info);
    106 
    107     if (!mInfoLog)
    108     {
    109         mInfoLog = new char[infoLength + 2];
    110         strcpy(mInfoLog, info);
    111         strcpy(mInfoLog + infoLength, "\n");
    112     }
    113     else
    114     {
    115         size_t logLength = strlen(mInfoLog);
    116         char *newLog = new char[logLength + infoLength + 2];
    117         strcpy(newLog, mInfoLog);
    118         strcpy(newLog + logLength, info);
    119         strcpy(newLog + logLength + infoLength, "\n");
    120 
    121         delete[] mInfoLog;
    122         mInfoLog = newLog;
    123     }
    124 }
    125 
    126 void InfoLog::reset()
    127 {
    128     if (mInfoLog)
    129     {
    130         delete [] mInfoLog;
    131         mInfoLog = NULL;
    132     }
    133 }
    134 
    135 Program::Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle)
    136 {
    137     mFragmentShader = NULL;
    138     mVertexShader = NULL;
    139     mProgramBinary.set(NULL);
    140     mDeleteStatus = false;
    141     mLinked = false;
    142     mRefCount = 0;
    143     mRenderer = renderer;
    144 }
    145 
    146 Program::~Program()
    147 {
    148     unlink(true);
    149 
    150     if (mVertexShader != NULL)
    151     {
    152         mVertexShader->release();
    153     }
    154 
    155     if (mFragmentShader != NULL)
    156     {
    157         mFragmentShader->release();
    158     }
    159 }
    160 
    161 bool Program::attachShader(Shader *shader)
    162 {
    163     if (shader->getType() == GL_VERTEX_SHADER)
    164     {
    165         if (mVertexShader)
    166         {
    167             return false;
    168         }
    169 
    170         mVertexShader = (VertexShader*)shader;
    171         mVertexShader->addRef();
    172     }
    173     else if (shader->getType() == GL_FRAGMENT_SHADER)
    174     {
    175         if (mFragmentShader)
    176         {
    177             return false;
    178         }
    179 
    180         mFragmentShader = (FragmentShader*)shader;
    181         mFragmentShader->addRef();
    182     }
    183     else UNREACHABLE();
    184 
    185     return true;
    186 }
    187 
    188 bool Program::detachShader(Shader *shader)
    189 {
    190     if (shader->getType() == GL_VERTEX_SHADER)
    191     {
    192         if (mVertexShader != shader)
    193         {
    194             return false;
    195         }
    196 
    197         mVertexShader->release();
    198         mVertexShader = NULL;
    199     }
    200     else if (shader->getType() == GL_FRAGMENT_SHADER)
    201     {
    202         if (mFragmentShader != shader)
    203         {
    204             return false;
    205         }
    206 
    207         mFragmentShader->release();
    208         mFragmentShader = NULL;
    209     }
    210     else UNREACHABLE();
    211 
    212     return true;
    213 }
    214 
    215 int Program::getAttachedShadersCount() const
    216 {
    217     return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
    218 }
    219 
    220 void AttributeBindings::bindAttributeLocation(GLuint index, const char *name)
    221 {
    222     if (index < MAX_VERTEX_ATTRIBS)
    223     {
    224         for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
    225         {
    226             mAttributeBinding[i].erase(name);
    227         }
    228 
    229         mAttributeBinding[index].insert(name);
    230     }
    231 }
    232 
    233 void Program::bindAttributeLocation(GLuint index, const char *name)
    234 {
    235     mAttributeBindings.bindAttributeLocation(index, name);
    236 }
    237 
    238 // Links the HLSL code of the vertex and pixel shader by matching up their varyings,
    239 // compiling them into binaries, determining the attribute mappings, and collecting
    240 // a list of uniforms
    241 bool Program::link()
    242 {
    243     unlink(false);
    244 
    245     mInfoLog.reset();
    246 
    247     mProgramBinary.set(new ProgramBinary(mRenderer));
    248     mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader);
    249 
    250     return mLinked;
    251 }
    252 
    253 int AttributeBindings::getAttributeBinding(const std::string &name) const
    254 {
    255     for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
    256     {
    257         if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
    258         {
    259             return location;
    260         }
    261     }
    262 
    263     return -1;
    264 }
    265 
    266 // Returns the program object to an unlinked state, before re-linking, or at destruction
    267 void Program::unlink(bool destroy)
    268 {
    269     if (destroy)   // Object being destructed
    270     {
    271         if (mFragmentShader)
    272         {
    273             mFragmentShader->release();
    274             mFragmentShader = NULL;
    275         }
    276 
    277         if (mVertexShader)
    278         {
    279             mVertexShader->release();
    280             mVertexShader = NULL;
    281         }
    282     }
    283 
    284     mProgramBinary.set(NULL);
    285     mLinked = false;
    286 }
    287 
    288 bool Program::isLinked()
    289 {
    290     return mLinked;
    291 }
    292 
    293 ProgramBinary* Program::getProgramBinary()
    294 {
    295     return mProgramBinary.get();
    296 }
    297 
    298 bool Program::setProgramBinary(const void *binary, GLsizei length)
    299 {
    300     unlink(false);
    301 
    302     mInfoLog.reset();
    303 
    304     mProgramBinary.set(new ProgramBinary(mRenderer));
    305     mLinked = mProgramBinary->load(mInfoLog, binary, length);
    306     if (!mLinked)
    307     {
    308         mProgramBinary.set(NULL);
    309     }
    310 
    311     return mLinked;
    312 }
    313 
    314 void Program::release()
    315 {
    316     mRefCount--;
    317 
    318     if (mRefCount == 0 && mDeleteStatus)
    319     {
    320         mResourceManager->deleteProgram(mHandle);
    321     }
    322 }
    323 
    324 void Program::addRef()
    325 {
    326     mRefCount++;
    327 }
    328 
    329 unsigned int Program::getRefCount() const
    330 {
    331     return mRefCount;
    332 }
    333 
    334 GLint Program::getProgramBinaryLength() const
    335 {
    336     ProgramBinary *programBinary = mProgramBinary.get();
    337     if (programBinary)
    338     {
    339         return programBinary->getLength();
    340     }
    341     else
    342     {
    343         return 0;
    344     }
    345 }
    346 
    347 int Program::getInfoLogLength() const
    348 {
    349     return mInfoLog.getLength();
    350 }
    351 
    352 void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
    353 {
    354     return mInfoLog.getLog(bufSize, length, infoLog);
    355 }
    356 
    357 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
    358 {
    359     int total = 0;
    360 
    361     if (mVertexShader)
    362     {
    363         if (total < maxCount)
    364         {
    365             shaders[total] = mVertexShader->getHandle();
    366         }
    367 
    368         total++;
    369     }
    370 
    371     if (mFragmentShader)
    372     {
    373         if (total < maxCount)
    374         {
    375             shaders[total] = mFragmentShader->getHandle();
    376         }
    377 
    378         total++;
    379     }
    380 
    381     if (count)
    382     {
    383         *count = total;
    384     }
    385 }
    386 
    387 void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
    388 {
    389     ProgramBinary *programBinary = getProgramBinary();
    390     if (programBinary)
    391     {
    392         programBinary->getActiveAttribute(index, bufsize, length, size, type, name);
    393     }
    394     else
    395     {
    396         if (bufsize > 0)
    397         {
    398             name[0] = '\0';
    399         }
    400 
    401         if (length)
    402         {
    403             *length = 0;
    404         }
    405 
    406         *type = GL_NONE;
    407         *size = 1;
    408     }
    409 }
    410 
    411 GLint Program::getActiveAttributeCount()
    412 {
    413     ProgramBinary *programBinary = getProgramBinary();
    414     if (programBinary)
    415     {
    416         return programBinary->getActiveAttributeCount();
    417     }
    418     else
    419     {
    420         return 0;
    421     }
    422 }
    423 
    424 GLint Program::getActiveAttributeMaxLength()
    425 {
    426     ProgramBinary *programBinary = getProgramBinary();
    427     if (programBinary)
    428     {
    429         return programBinary->getActiveAttributeMaxLength();
    430     }
    431     else
    432     {
    433         return 0;
    434     }
    435 }
    436 
    437 void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
    438 {
    439     ProgramBinary *programBinary = getProgramBinary();
    440     if (programBinary)
    441     {
    442         return programBinary->getActiveUniform(index, bufsize, length, size, type, name);
    443     }
    444     else
    445     {
    446         if (bufsize > 0)
    447         {
    448             name[0] = '\0';
    449         }
    450 
    451         if (length)
    452         {
    453             *length = 0;
    454         }
    455 
    456         *size = 0;
    457         *type = GL_NONE;
    458     }
    459 }
    460 
    461 GLint Program::getActiveUniformCount()
    462 {
    463     ProgramBinary *programBinary = getProgramBinary();
    464     if (programBinary)
    465     {
    466         return programBinary->getActiveUniformCount();
    467     }
    468     else
    469     {
    470         return 0;
    471     }
    472 }
    473 
    474 GLint Program::getActiveUniformMaxLength()
    475 {
    476     ProgramBinary *programBinary = getProgramBinary();
    477     if (programBinary)
    478     {
    479         return programBinary->getActiveUniformMaxLength();
    480     }
    481     else
    482     {
    483         return 0;
    484     }
    485 }
    486 
    487 void Program::flagForDeletion()
    488 {
    489     mDeleteStatus = true;
    490 }
    491 
    492 bool Program::isFlaggedForDeletion() const
    493 {
    494     return mDeleteStatus;
    495 }
    496 
    497 void Program::validate()
    498 {
    499     mInfoLog.reset();
    500 
    501     ProgramBinary *programBinary = getProgramBinary();
    502     if (isLinked() && programBinary)
    503     {
    504         programBinary->validate(mInfoLog);
    505     }
    506     else
    507     {
    508         mInfoLog.append("Program has not been successfully linked.");
    509     }
    510 }
    511 
    512 bool Program::isValidated() const
    513 {
    514     ProgramBinary *programBinary = mProgramBinary.get();
    515     if (programBinary)
    516     {
    517         return programBinary->isValidated();
    518     }
    519     else
    520     {
    521         return false;
    522     }
    523 }
    524 
    525 }
    526