• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AttributeBindings()19 AttributeBindings::AttributeBindings()
20 {
21 }
22 
~AttributeBindings()23 AttributeBindings::~AttributeBindings()
24 {
25 }
26 
InfoLog()27 InfoLog::InfoLog() : mInfoLog(NULL)
28 {
29 }
30 
~InfoLog()31 InfoLog::~InfoLog()
32 {
33     delete[] mInfoLog;
34 }
35 
36 
getLength() const37 int InfoLog::getLength() const
38 {
39     if (!mInfoLog)
40     {
41         return 0;
42     }
43     else
44     {
45        return strlen(mInfoLog) + 1;
46     }
47 }
48 
getLog(GLsizei bufSize,GLsizei * length,char * infoLog)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.
appendSanitized(const char * message)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 
append(const char * format,...)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 
reset()126 void InfoLog::reset()
127 {
128     if (mInfoLog)
129     {
130         delete [] mInfoLog;
131         mInfoLog = NULL;
132     }
133 }
134 
Program(rx::Renderer * renderer,ResourceManager * manager,GLuint handle)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 
~Program()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 
attachShader(Shader * shader)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 
detachShader(Shader * shader)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 
getAttachedShadersCount() const215 int Program::getAttachedShadersCount() const
216 {
217     return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
218 }
219 
bindAttributeLocation(GLuint index,const char * name)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 
bindAttributeLocation(GLuint index,const char * name)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
link()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 
getAttributeBinding(const std::string & name) const253 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
unlink(bool destroy)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 
isLinked()288 bool Program::isLinked()
289 {
290     return mLinked;
291 }
292 
getProgramBinary()293 ProgramBinary* Program::getProgramBinary()
294 {
295     return mProgramBinary.get();
296 }
297 
setProgramBinary(const void * binary,GLsizei length)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 
release()314 void Program::release()
315 {
316     mRefCount--;
317 
318     if (mRefCount == 0 && mDeleteStatus)
319     {
320         mResourceManager->deleteProgram(mHandle);
321     }
322 }
323 
addRef()324 void Program::addRef()
325 {
326     mRefCount++;
327 }
328 
getRefCount() const329 unsigned int Program::getRefCount() const
330 {
331     return mRefCount;
332 }
333 
getProgramBinaryLength() const334 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 
getInfoLogLength() const347 int Program::getInfoLogLength() const
348 {
349     return mInfoLog.getLength();
350 }
351 
getInfoLog(GLsizei bufSize,GLsizei * length,char * infoLog)352 void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
353 {
354     return mInfoLog.getLog(bufSize, length, infoLog);
355 }
356 
getAttachedShaders(GLsizei maxCount,GLsizei * count,GLuint * shaders)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 
getActiveAttribute(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name)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 
getActiveAttributeCount()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 
getActiveAttributeMaxLength()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 
getActiveUniform(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name)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 
getActiveUniformCount()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 
getActiveUniformMaxLength()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 
flagForDeletion()487 void Program::flagForDeletion()
488 {
489     mDeleteStatus = true;
490 }
491 
isFlaggedForDeletion() const492 bool Program::isFlaggedForDeletion() const
493 {
494     return mDeleteStatus;
495 }
496 
validate()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 
isValidated() const512 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