gfx/angle/src/libGLESv2/Program.cpp

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

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

mercurial