Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / Program.cpp
1 //
2 // Copyright (c) 2002-2014 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 #include "libGLESv2/ProgramBinary.h"
12 #include "libGLESv2/ResourceManager.h"
13 #include "libGLESv2/renderer/Renderer.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     va_list vararg;
99     va_start(vararg, format);
100     size_t infoLength = vsnprintf(NULL, 0, format, vararg);
101     va_end(vararg);
102
103     char *logPointer = NULL;
104
105     if (!mInfoLog)
106     {
107         mInfoLog = new char[infoLength + 2];
108         logPointer = mInfoLog;
109     }
110     else
111     {
112         size_t currentlogLength = strlen(mInfoLog);
113         char *newLog = new char[currentlogLength + infoLength + 2];
114         strcpy(newLog, mInfoLog);
115
116         delete[] mInfoLog;
117         mInfoLog = newLog;
118
119         logPointer = mInfoLog + currentlogLength;
120     }
121
122     va_start(vararg, format);
123     vsnprintf(logPointer, infoLength, format, vararg);
124     va_end(vararg);
125
126     logPointer[infoLength] = 0;
127     strcpy(logPointer + infoLength, "\n");
128 }
129
130 void InfoLog::reset()
131 {
132     if (mInfoLog)
133     {
134         delete [] mInfoLog;
135         mInfoLog = NULL;
136     }
137 }
138
139 Program::Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle)
140 {
141     mFragmentShader = NULL;
142     mVertexShader = NULL;
143     mProgramBinary.set(NULL);
144     mDeleteStatus = false;
145     mLinked = false;
146     mRefCount = 0;
147     mRenderer = renderer;
148
149     resetUniformBlockBindings();
150 }
151
152 Program::~Program()
153 {
154     unlink(true);
155
156     if (mVertexShader != NULL)
157     {
158         mVertexShader->release();
159     }
160
161     if (mFragmentShader != NULL)
162     {
163         mFragmentShader->release();
164     }
165 }
166
167 bool Program::attachShader(Shader *shader)
168 {
169     if (shader->getType() == GL_VERTEX_SHADER)
170     {
171         if (mVertexShader)
172         {
173             return false;
174         }
175
176         mVertexShader = shader;
177         mVertexShader->addRef();
178     }
179     else if (shader->getType() == GL_FRAGMENT_SHADER)
180     {
181         if (mFragmentShader)
182         {
183             return false;
184         }
185
186         mFragmentShader = shader;
187         mFragmentShader->addRef();
188     }
189     else UNREACHABLE();
190
191     return true;
192 }
193
194 bool Program::detachShader(Shader *shader)
195 {
196     if (shader->getType() == GL_VERTEX_SHADER)
197     {
198         if (mVertexShader != shader)
199         {
200             return false;
201         }
202
203         mVertexShader->release();
204         mVertexShader = NULL;
205     }
206     else if (shader->getType() == GL_FRAGMENT_SHADER)
207     {
208         if (mFragmentShader != shader)
209         {
210             return false;
211         }
212
213         mFragmentShader->release();
214         mFragmentShader = NULL;
215     }
216     else UNREACHABLE();
217
218     return true;
219 }
220
221 int Program::getAttachedShadersCount() const
222 {
223     return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
224 }
225
226 void AttributeBindings::bindAttributeLocation(GLuint index, const char *name)
227 {
228     if (index < MAX_VERTEX_ATTRIBS)
229     {
230         for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
231         {
232             mAttributeBinding[i].erase(name);
233         }
234
235         mAttributeBinding[index].insert(name);
236     }
237 }
238
239 void Program::bindAttributeLocation(GLuint index, const char *name)
240 {
241     mAttributeBindings.bindAttributeLocation(index, name);
242 }
243
244 // Links the HLSL code of the vertex and pixel shader by matching up their varyings,
245 // compiling them into binaries, determining the attribute mappings, and collecting
246 // a list of uniforms
247 bool Program::link(const Caps &caps)
248 {
249     unlink(false);
250
251     mInfoLog.reset();
252     resetUniformBlockBindings();
253
254     mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
255     mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
256                                    mTransformFeedbackVaryings, mTransformFeedbackBufferMode, caps);
257
258     return mLinked;
259 }
260
261 int AttributeBindings::getAttributeBinding(const std::string &name) const
262 {
263     for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
264     {
265         if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
266         {
267             return location;
268         }
269     }
270
271     return -1;
272 }
273
274 // Returns the program object to an unlinked state, before re-linking, or at destruction
275 void Program::unlink(bool destroy)
276 {
277     if (destroy)   // Object being destructed
278     {
279         if (mFragmentShader)
280         {
281             mFragmentShader->release();
282             mFragmentShader = NULL;
283         }
284
285         if (mVertexShader)
286         {
287             mVertexShader->release();
288             mVertexShader = NULL;
289         }
290     }
291
292     mProgramBinary.set(NULL);
293     mLinked = false;
294 }
295
296 bool Program::isLinked()
297 {
298     return mLinked;
299 }
300
301 ProgramBinary* Program::getProgramBinary() const
302 {
303     return mProgramBinary.get();
304 }
305
306 bool Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length)
307 {
308     unlink(false);
309
310     mInfoLog.reset();
311
312     mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
313     mLinked = mProgramBinary->load(mInfoLog, binaryFormat, binary, length);
314
315     if (!mLinked)
316     {
317         mProgramBinary.set(NULL);
318     }
319
320     return mLinked;
321 }
322
323 void Program::release()
324 {
325     mRefCount--;
326
327     if (mRefCount == 0 && mDeleteStatus)
328     {
329         mResourceManager->deleteProgram(mHandle);
330     }
331 }
332
333 void Program::addRef()
334 {
335     mRefCount++;
336 }
337
338 unsigned int Program::getRefCount() const
339 {
340     return mRefCount;
341 }
342
343 GLint Program::getProgramBinaryLength() const
344 {
345     ProgramBinary *programBinary = mProgramBinary.get();
346     if (programBinary)
347     {
348         return programBinary->getLength();
349     }
350     else
351     {
352         return 0;
353     }
354 }
355
356 int Program::getInfoLogLength() const
357 {
358     return mInfoLog.getLength();
359 }
360
361 void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
362 {
363     return mInfoLog.getLog(bufSize, length, infoLog);
364 }
365
366 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
367 {
368     int total = 0;
369
370     if (mVertexShader)
371     {
372         if (total < maxCount)
373         {
374             shaders[total] = mVertexShader->getHandle();
375         }
376
377         total++;
378     }
379
380     if (mFragmentShader)
381     {
382         if (total < maxCount)
383         {
384             shaders[total] = mFragmentShader->getHandle();
385         }
386
387         total++;
388     }
389
390     if (count)
391     {
392         *count = total;
393     }
394 }
395
396 void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
397 {
398     ProgramBinary *programBinary = getProgramBinary();
399     if (programBinary)
400     {
401         programBinary->getActiveAttribute(index, bufsize, length, size, type, name);
402     }
403     else
404     {
405         if (bufsize > 0)
406         {
407             name[0] = '\0';
408         }
409         
410         if (length)
411         {
412             *length = 0;
413         }
414
415         *type = GL_NONE;
416         *size = 1;
417     }
418 }
419
420 GLint Program::getActiveAttributeCount()
421 {
422     ProgramBinary *programBinary = getProgramBinary();
423     if (programBinary)
424     {
425         return programBinary->getActiveAttributeCount();
426     }
427     else
428     {
429         return 0;
430     }
431 }
432
433 GLint Program::getActiveAttributeMaxLength()
434 {
435     ProgramBinary *programBinary = getProgramBinary();
436     if (programBinary)
437     {
438         return programBinary->getActiveAttributeMaxLength();
439     }
440     else
441     {
442         return 0;
443     }
444 }
445
446 void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
447 {
448     ProgramBinary *programBinary = getProgramBinary();
449     if (programBinary)
450     {
451         return programBinary->getActiveUniform(index, bufsize, length, size, type, name);
452     }
453     else
454     {
455         if (bufsize > 0)
456         {
457             name[0] = '\0';
458         }
459
460         if (length)
461         {
462             *length = 0;
463         }
464
465         *size = 0;
466         *type = GL_NONE;
467     }
468 }
469
470 GLint Program::getActiveUniformCount()
471 {
472     ProgramBinary *programBinary = getProgramBinary();
473     if (programBinary)
474     {
475         return programBinary->getActiveUniformCount();
476     }
477     else
478     {
479         return 0;
480     }
481 }
482
483 GLint Program::getActiveUniformMaxLength()
484 {
485     ProgramBinary *programBinary = getProgramBinary();
486     if (programBinary)
487     {
488         return programBinary->getActiveUniformMaxLength();
489     }
490     else
491     {
492         return 0;
493     }
494 }
495
496 void Program::flagForDeletion()
497 {
498     mDeleteStatus = true;
499 }
500
501 bool Program::isFlaggedForDeletion() const
502 {
503     return mDeleteStatus;
504 }
505
506 void Program::validate(const Caps &caps)
507 {
508     mInfoLog.reset();
509
510     ProgramBinary *programBinary = getProgramBinary();
511     if (isLinked() && programBinary)
512     {
513         programBinary->validate(mInfoLog, caps);
514     }
515     else
516     {
517         mInfoLog.append("Program has not been successfully linked.");
518     }
519 }
520
521 bool Program::isValidated() const
522 {
523     ProgramBinary *programBinary = mProgramBinary.get();
524     if (programBinary)
525     {
526         return programBinary->isValidated();
527     }
528     else
529     {
530         return false;
531     }
532 }
533
534 GLint Program::getActiveUniformBlockCount()
535 {
536     ProgramBinary *programBinary = getProgramBinary();
537     if (programBinary)
538     {
539         return static_cast<GLint>(programBinary->getActiveUniformBlockCount());
540     }
541     else
542     {
543         return 0;
544     }
545 }
546
547 GLint Program::getActiveUniformBlockMaxLength()
548 {
549     ProgramBinary *programBinary = getProgramBinary();
550     if (programBinary)
551     {
552         return static_cast<GLint>(programBinary->getActiveUniformBlockMaxLength());
553     }
554     else
555     {
556         return 0;
557     }
558 }
559
560 void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
561 {
562     mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding;
563 }
564
565 GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
566 {
567     return mUniformBlockBindings[uniformBlockIndex];
568 }
569
570 void Program::resetUniformBlockBindings()
571 {
572     for (unsigned int blockId = 0; blockId < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; blockId++)
573     {
574         mUniformBlockBindings[blockId] = 0;
575     }
576 }
577
578 void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode)
579 {
580     mTransformFeedbackVaryings.resize(count);
581     for (GLsizei i = 0; i < count; i++)
582     {
583         mTransformFeedbackVaryings[i] = varyings[i];
584     }
585
586     mTransformFeedbackBufferMode = bufferMode;
587 }
588
589 void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const
590 {
591     ProgramBinary *programBinary = getProgramBinary();
592     if (programBinary && index < programBinary->getTransformFeedbackVaryingCount())
593     {
594         const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(index);
595         GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varying.name.length()));
596         if (length)
597         {
598             *length = lastNameIdx;
599         }
600         if (size)
601         {
602             *size = varying.size;
603         }
604         if (type)
605         {
606             *type = varying.type;
607         }
608         if (name)
609         {
610             memcpy(name, varying.name.c_str(), lastNameIdx);
611             name[lastNameIdx] = '\0';
612         }
613     }
614 }
615
616 GLsizei Program::getTransformFeedbackVaryingCount() const
617 {
618     ProgramBinary *programBinary = getProgramBinary();
619     if (programBinary)
620     {
621         return static_cast<GLsizei>(programBinary->getTransformFeedbackVaryingCount());
622     }
623     else
624     {
625         return 0;
626     }
627 }
628
629 GLsizei Program::getTransformFeedbackVaryingMaxLength() const
630 {
631     ProgramBinary *programBinary = getProgramBinary();
632     if (programBinary)
633     {
634         GLsizei maxSize = 0;
635         for (size_t i = 0; i < programBinary->getTransformFeedbackVaryingCount(); i++)
636         {
637             const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(i);
638             maxSize = std::max(maxSize, static_cast<GLsizei>(varying.name.length() + 1));
639         }
640
641         return maxSize;
642     }
643     else
644     {
645         return 0;
646     }
647 }
648
649 GLenum Program::getTransformFeedbackBufferMode() const
650 {
651     ProgramBinary *programBinary = getProgramBinary();
652     if (programBinary)
653     {
654         return programBinary->getTransformFeedbackBufferMode();
655     }
656     else
657     {
658         return mTransformFeedbackBufferMode;
659     }
660 }
661
662 }