[dali_2.0.27] Merge branch 'devel/master'
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit / dali-toolkit-test-utils / test-gl-abstraction.h
1 #ifndef TEST_GL_ABSTRACTION_H
2 #define TEST_GL_ABSTRACTION_H
3
4 /*
5  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */
20
21 // EXTERNAL INCLUDES
22 #include <cstdio>
23 #include <cstring>
24 #include <cstring> // for strcmp
25 #include <map>
26 #include <sstream>
27 #include <string>
28 #include <typeinfo>
29
30 // INTERNAL INCLUDES
31 #include <dali/devel-api/rendering/frame-buffer-devel.h>
32 #include <dali/integration-api/core.h>
33 #include <dali/integration-api/gl-abstraction.h>
34 #include <dali/integration-api/gl-defines.h>
35 #include <dali/public-api/dali-core.h>
36 #include <test-compare-types.h>
37 #include <test-trace-call-stack.h>
38
39 namespace Dali
40 {
41 struct UniformData
42 {
43   std::string    name;
44   Property::Type type;
45   UniformData(const std::string& name, Property::Type type = Property::Type::NONE)
46   : name(name),
47     type(type)
48   {
49   }
50 };
51
52 class DALI_CORE_API TestGlAbstraction : public Dali::Integration::GlAbstraction
53 {
54 public:
55   static const int MAX_ATTRIBUTE_CACHE_SIZE{64};
56
57   TestGlAbstraction();
58   ~TestGlAbstraction() override;
59   void Initialize();
60
61   void PreRender() override;
62   void PostRender() override;
63
64   bool IsSurfacelessContextSupported() const override;
65
66   bool IsAdvancedBlendEquationSupported() override;
67
68   bool IsBlendEquationSupported(DevelBlendEquation::Type blendEquation) override;
69
70   std::string GetShaderVersionPrefix();
71
72   std::string GetVertexShaderPrefix();
73
74   std::string GetFragmentShaderPrefix();
75
76   bool TextureRequiresConverting(const GLenum imageGlFormat, const GLenum textureGlFormat, const bool isSubImage) const override;
77
78   /* OpenGL ES 2.0 */
79
80   inline void ActiveTexture(GLenum textureUnit) override
81   {
82     mActiveTextureUnit = textureUnit - GL_TEXTURE0;
83   }
84
85   inline GLenum GetActiveTextureUnit() const
86   {
87     return mActiveTextureUnit + GL_TEXTURE0;
88   }
89
90   inline void AttachShader(GLuint program, GLuint shader) override
91   {
92     std::stringstream out;
93     out << program << ", " << shader;
94
95     TraceCallStack::NamedParams namedParams;
96     namedParams["program"] << program;
97     namedParams["shader"] << shader;
98     mShaderTrace.PushCall("AttachShader", out.str(), namedParams);
99   }
100
101   inline void BindAttribLocation(GLuint program, GLuint index, const char* name) override
102   {
103   }
104
105   inline void BindBuffer(GLenum target, GLuint buffer) override
106   {
107     std::ostringstream o;
108     o << std::hex << target << ", " << buffer;
109     TraceCallStack::NamedParams namedParams;
110     namedParams["target"] << target;
111     namedParams["buffer"] << buffer;
112     mBufferTrace.PushCall("BindBuffer", o.str(), namedParams);
113   }
114
115   inline void BindFramebuffer(GLenum target, GLuint framebuffer) override
116   {
117     //Add 010 bit;
118     mFramebufferStatus |= 2;
119   }
120
121   inline void BindRenderbuffer(GLenum target, GLuint renderbuffer) override
122   {
123   }
124
125   /**
126    * This method can be used by test cases, to query the texture IDs that have been bound by BindTexture.
127    * @return A vector containing the IDs that were bound.
128    */
129   inline const std::vector<GLuint>& GetBoundTextures() const
130   {
131     return mBoundTextures;
132   }
133
134   /**
135    * Query the texture IDs that have been bound with BindTexture, with a specific active texture unit.
136    * @param[in] activeTextureUnit The specific active texture unit.
137    * @return A vector containing the IDs that were bound.
138    */
139   inline const std::vector<GLuint>& GetBoundTextures(GLuint activeTextureUnit) const
140   {
141     return mActiveTextures[activeTextureUnit - GL_TEXTURE0].mBoundTextures;
142   }
143
144   /**
145    * This method can be used by test cases, to clear the record of texture IDs that have been bound by BindTexture.
146    */
147   inline void ClearBoundTextures()
148   {
149     mBoundTextures.clear();
150
151     for(unsigned int i = 0; i < MIN_TEXTURE_UNIT_LIMIT; ++i)
152     {
153       mActiveTextures[i].mBoundTextures.clear();
154     }
155   }
156
157   inline void BindTexture(GLenum target, GLuint texture) override
158   {
159     // Record the bound textures for future checks
160     if(texture)
161     {
162       mBoundTextures.push_back(texture);
163
164       if(mActiveTextureUnit < MIN_TEXTURE_UNIT_LIMIT)
165       {
166         mActiveTextures[mActiveTextureUnit].mBoundTextures.push_back(texture);
167       }
168     }
169
170     std::stringstream out;
171     out << std::hex << target << ", " << std::dec << texture;
172
173     TraceCallStack::NamedParams namedParams;
174     namedParams["target"] << std::hex << target;
175     namedParams["texture"] << texture;
176
177     mTextureTrace.PushCall("BindTexture", out.str(), namedParams);
178   }
179
180   inline void BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) override
181   {
182     mLastBlendColor.r = red;
183     mLastBlendColor.g = green;
184     mLastBlendColor.b = blue;
185     mLastBlendColor.a = alpha;
186   }
187
188   inline const Vector4& GetLastBlendColor() const
189   {
190     return mLastBlendColor;
191   }
192
193   inline void BlendEquation(GLenum mode) override
194   {
195     mLastBlendEquationRgb   = mode;
196     mLastBlendEquationAlpha = mode;
197   }
198
199   inline void BlendEquationSeparate(GLenum modeRgb, GLenum modeAlpha) override
200   {
201     mLastBlendEquationRgb   = modeRgb;
202     mLastBlendEquationAlpha = modeAlpha;
203   }
204
205   inline GLenum GetLastBlendEquationRgb() const
206   {
207     return mLastBlendEquationRgb;
208   }
209
210   inline GLenum GetLastBlendEquationAlpha() const
211   {
212     return mLastBlendEquationAlpha;
213   }
214
215   inline void BlendFunc(GLenum sfactor, GLenum dfactor) override
216   {
217     mLastBlendFuncSrcRgb   = sfactor;
218     mLastBlendFuncDstRgb   = dfactor;
219     mLastBlendFuncSrcAlpha = sfactor;
220     mLastBlendFuncDstAlpha = dfactor;
221   }
222
223   inline void BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) override
224   {
225     mLastBlendFuncSrcRgb   = srcRGB;
226     mLastBlendFuncDstRgb   = dstRGB;
227     mLastBlendFuncSrcAlpha = srcAlpha;
228     mLastBlendFuncDstAlpha = dstAlpha;
229   }
230
231   inline GLenum GetLastBlendFuncSrcRgb() const
232   {
233     return mLastBlendFuncSrcRgb;
234   }
235
236   inline GLenum GetLastBlendFuncDstRgb() const
237   {
238     return mLastBlendFuncDstRgb;
239   }
240
241   inline GLenum GetLastBlendFuncSrcAlpha() const
242   {
243     return mLastBlendFuncSrcAlpha;
244   }
245
246   inline GLenum GetLastBlendFuncDstAlpha() const
247   {
248     return mLastBlendFuncDstAlpha;
249   }
250
251   inline void BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage) override
252   {
253     std::ostringstream o;
254     o << std::hex << target << ", " << size << ", " << data << ", " << usage;
255     TraceCallStack::NamedParams namedParams;
256     namedParams["target"] << std::hex << target;
257     namedParams["size"] << size;
258     namedParams["usage"] << usage;
259
260     mBufferTrace.PushCall("BufferData", o.str(), namedParams);
261
262     mBufferDataCalls.push_back(size);
263   }
264
265   inline void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void* data) override
266   {
267     std::ostringstream o;
268     o << std::hex << target << ", " << offset << ", " << size << ", " << data;
269     TraceCallStack::NamedParams namedParams;
270     namedParams["target"] << std::hex << target;
271     namedParams["offset"] << offset;
272     namedParams["size"] << size;
273     mBufferTrace.PushCall("BufferSubData", o.str());
274
275     mBufferSubDataCalls.push_back(size);
276   }
277
278   inline GLenum CheckFramebufferStatus(GLenum target) override
279   {
280     //If it has the three last bits set to 1 - 111, then the three minimum functions to create a
281     //Framebuffer texture have been called
282     if(mFramebufferStatus == 7)
283     {
284       return GL_FRAMEBUFFER_COMPLETE;
285     }
286
287     return mCheckFramebufferStatusResult;
288   }
289
290   inline GLuint CheckFramebufferColorAttachmentCount()
291   {
292     return mFramebufferColorAttachmentCount;
293   }
294
295   inline GLenum CheckFramebufferDepthAttachment()
296   {
297     return mFramebufferDepthAttached;
298   }
299
300   inline GLenum CheckFramebufferStencilAttachment()
301   {
302     return mFramebufferStencilAttached;
303   }
304
305   inline void Clear(GLbitfield mask) override
306   {
307     mClearCount++;
308     mLastClearBitMask = mask;
309   }
310
311   inline void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) override
312   {
313     mLastClearColor.r = red;
314     mLastClearColor.g = green;
315     mLastClearColor.b = blue;
316     mLastClearColor.a = alpha;
317   }
318
319   inline const Vector4& GetLastClearColor() const
320   {
321     return mLastClearColor;
322   }
323
324   inline void ClearDepthf(GLclampf depth) override
325   {
326   }
327
328   inline void ClearStencil(GLint s) override
329   {
330     std::stringstream out;
331     out << s;
332
333     TraceCallStack::NamedParams namedParams;
334     namedParams["s"] << s;
335
336     mStencilFunctionTrace.PushCall("ClearStencil", out.str(), namedParams);
337   }
338
339   inline void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) override
340   {
341     mColorMaskParams.red   = red;
342     mColorMaskParams.green = green;
343     mColorMaskParams.blue  = blue;
344     mColorMaskParams.alpha = alpha;
345   }
346
347   inline void CompileShader(GLuint shader) override
348   {
349     std::stringstream out;
350     out << shader;
351     TraceCallStack::NamedParams namedParams;
352     namedParams["shader"] << shader;
353
354     mShaderTrace.PushCall("CompileShader", out.str(), namedParams);
355   }
356
357   inline void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) override
358   {
359     std::stringstream out;
360     out << target << ", " << level << ", " << width << ", " << height;
361
362     TraceCallStack::NamedParams namedParams;
363     namedParams["target"] << std::hex << target;
364     namedParams["level"] << level;
365     namedParams["internalformat"] << internalformat;
366     namedParams["width"] << width;
367     namedParams["height"] << height;
368     namedParams["border"] << border;
369     namedParams["size"] << imageSize;
370
371     mTextureTrace.PushCall("CompressedTexImage2D", out.str(), namedParams);
372   }
373
374   inline void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) override
375   {
376     std::stringstream out;
377     out << target << ", " << level << ", " << xoffset << ", " << yoffset << ", " << width << ", " << height;
378
379     TraceCallStack::NamedParams namedParams;
380     namedParams["target"] << std::hex << target;
381     namedParams["level"] << level;
382     namedParams["xoffset"] << xoffset;
383     namedParams["yoffset"] << yoffset;
384     namedParams["width"] << width;
385     namedParams["height"] << height;
386     mTextureTrace.PushCall("CompressedTexSubImage2D", out.str(), namedParams);
387   }
388
389   inline void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) override
390   {
391   }
392
393   inline void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) override
394   {
395   }
396
397   inline GLuint CreateProgram(void) override
398   {
399     mShaderTrace.PushCall("CreateProgram", "");
400
401     ++mLastProgramIdUsed;
402     mUniforms[mLastProgramIdUsed] = UniformIDMap();
403     return mLastProgramIdUsed;
404   }
405
406   inline GLuint CreateShader(GLenum type) override
407   {
408     std::stringstream out;
409     out << type;
410
411     TraceCallStack::NamedParams namedParams;
412     namedParams["type"] << std::hex << type;
413     mShaderTrace.PushCall("CreateShader", out.str(), namedParams);
414
415     return ++mLastShaderIdUsed;
416   }
417
418   inline void CullFace(GLenum mode) override
419   {
420     std::stringstream out;
421     out << std::hex << mode;
422
423     TraceCallStack::NamedParams namedParams;
424     namedParams["mode"] << std::hex << mode;
425
426     mCullFaceTrace.PushCall("CullFace", out.str(), namedParams);
427   }
428
429   inline void DeleteBuffers(GLsizei n, const GLuint* buffers) override
430   {
431   }
432
433   inline void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers) override
434   {
435   }
436
437   inline void DeleteProgram(GLuint program) override
438   {
439     std::stringstream out;
440     out << program;
441
442     TraceCallStack::NamedParams namedParams;
443     namedParams["program"] << program;
444
445     mShaderTrace.PushCall("DeleteProgram", out.str(), namedParams);
446   }
447
448   inline void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) override
449   {
450   }
451
452   inline void DeleteShader(GLuint shader) override
453   {
454     std::stringstream out;
455     out << shader;
456
457     TraceCallStack::NamedParams namedParams;
458     namedParams["shader"] << shader;
459
460     mShaderTrace.PushCall("DeleteShader", out.str(), namedParams);
461   }
462
463   inline void DeleteTextures(GLsizei n, const GLuint* textures) override
464   {
465     std::stringstream out;
466     out << "n:" << n << " textures[";
467
468     TraceCallStack::NamedParams namedParams;
469
470     for(GLsizei i = 0; i < n; i++)
471     {
472       out << (i > 0 ? ", " : "") << textures[i];
473       std::stringstream paramName;
474       paramName << "texture[" << i << "]";
475       namedParams[paramName.str()] << textures[i];
476       mDeletedTextureIds.push_back(textures[i]);
477       mNumGeneratedTextures--;
478     }
479     out << "]";
480
481     mTextureTrace.PushCall("DeleteTextures", out.str(), namedParams);
482   }
483
484   inline bool CheckNoTexturesDeleted()
485   {
486     return mDeletedTextureIds.size() == 0;
487   }
488
489   inline bool CheckTextureDeleted(GLuint textureId)
490   {
491     bool found = false;
492
493     for(std::vector<GLuint>::iterator iter = mDeletedTextureIds.begin(); iter != mDeletedTextureIds.end(); ++iter)
494     {
495       if(*iter == textureId)
496       {
497         found = true;
498         break;
499       }
500     }
501     return found;
502   }
503
504   inline void ClearDeletedTextures()
505   {
506     mDeletedTextureIds.clear();
507   }
508
509   inline void DepthFunc(GLenum func) override
510   {
511     std::stringstream out;
512     out << std::hex << func;
513
514     TraceCallStack::NamedParams namedParams;
515     namedParams["func"] << std::hex << func;
516
517     mDepthFunctionTrace.PushCall("DepthFunc", out.str(), namedParams);
518   }
519
520   inline void DepthMask(GLboolean flag) override
521   {
522     mLastDepthMask = flag;
523   }
524
525   inline bool GetLastDepthMask() const
526   {
527     return mLastDepthMask;
528   }
529
530   inline void DepthRangef(GLclampf zNear, GLclampf zFar) override
531   {
532   }
533
534   inline void DetachShader(GLuint program, GLuint shader) override
535   {
536     std::stringstream out;
537     out << program << ", " << shader;
538     TraceCallStack::NamedParams namedParams;
539     namedParams["program"] << program;
540     namedParams["shader"] << shader;
541     mShaderTrace.PushCall("DetachShader", out.str(), namedParams);
542   }
543
544   inline void Disable(GLenum cap) override
545   {
546     std::stringstream out;
547     out << std::hex << cap;
548     TraceCallStack::NamedParams namedParams;
549     namedParams["cap"] << std::hex << cap;
550     mEnableDisableTrace.PushCall("Disable", out.str(), namedParams);
551   }
552
553   inline void DisableVertexAttribArray(GLuint index) override
554   {
555     std::stringstream out;
556     out << index;
557     TraceCallStack::NamedParams namedParams;
558     namedParams["index"] << index;
559     mBufferTrace.PushCall("DisableVertexAttribArray", out.str(), namedParams);
560     SetVertexAttribArray(index, false);
561   }
562
563   inline void DrawArrays(GLenum mode, GLint first, GLsizei count) override
564   {
565     std::stringstream out;
566     out << mode << ", " << first << ", " << count;
567     TraceCallStack::NamedParams namedParams;
568     namedParams["mode"] << std::hex << mode;
569     namedParams["first"] << first;
570     namedParams["count"] << count;
571     mDrawTrace.PushCall("DrawArrays", out.str(), namedParams);
572   }
573
574   inline void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices) override
575   {
576     std::stringstream out;
577     out << mode << ", " << count << ", " << type << ", indices";
578
579     TraceCallStack::NamedParams namedParams;
580     namedParams["mode"] << std::hex << mode;
581     namedParams["count"] << count;
582     namedParams["type"] << type;
583     // Skip void pointers - are they of any use?
584     mDrawTrace.PushCall("DrawElements", out.str(), namedParams);
585   }
586
587   inline void Enable(GLenum cap) override
588   {
589     std::stringstream out;
590     out << std::hex << cap;
591     TraceCallStack::NamedParams namedParams;
592     namedParams["cap"] << std::hex << cap;
593     mEnableDisableTrace.PushCall("Enable", out.str(), namedParams);
594   }
595
596   inline void EnableVertexAttribArray(GLuint index) override
597   {
598     std::stringstream out;
599     out << index;
600     TraceCallStack::NamedParams namedParams;
601     namedParams["index"] << index;
602     mBufferTrace.PushCall("EnableVertexAttribArray", out.str(), namedParams);
603     SetVertexAttribArray(index, true);
604   }
605
606   inline void Finish(void) override
607   {
608   }
609
610   inline void Flush(void) override
611   {
612   }
613
614   inline void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) override
615   {
616     if(attachment == GL_DEPTH_ATTACHMENT)
617     {
618       mFramebufferDepthAttached = true;
619     }
620     else if(attachment == GL_STENCIL_ATTACHMENT)
621     {
622       mFramebufferStencilAttached = true;
623     }
624   }
625
626   inline void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) override
627   {
628     //Add 100 bit;
629     mFramebufferStatus |= 4;
630
631     //We check 4 attachment colors
632     if((attachment >= GL_COLOR_ATTACHMENT0) && (attachment < GL_COLOR_ATTACHMENT0 + Dali::DevelFrameBuffer::MAX_COLOR_ATTACHMENTS))
633     {
634       uint8_t mask = 1 << (attachment - GL_COLOR_ATTACHMENT0);
635       if((mFrameBufferColorStatus & mask) == 0)
636       {
637         mFrameBufferColorStatus |= mask;
638         ++mFramebufferColorAttachmentCount;
639       }
640     }
641   }
642
643   inline void FrontFace(GLenum mode) override
644   {
645     // do nothing
646   }
647
648   inline void GenBuffers(GLsizei n, GLuint* buffers) override
649   {
650     // avoids an assert in GpuBuffers
651     *buffers = 1u;
652
653     std::ostringstream o;
654     o << n;
655     TraceCallStack::NamedParams namedParams;
656     namedParams["n"] << o.str();
657     mBufferTrace.PushCall("GenBuffers", o.str(), namedParams);
658   }
659
660   inline void GenerateMipmap(GLenum target) override
661   {
662     std::stringstream out;
663     out << target;
664     TraceCallStack::NamedParams namedParams;
665     namedParams["target"] << std::hex << target;
666
667     mTextureTrace.PushCall("GenerateMipmap", out.str(), namedParams);
668   }
669
670   inline void GenFramebuffers(GLsizei n, GLuint* framebuffers) override
671   {
672     for(int i = 0; i < n; i++)
673     {
674       framebuffers[i] = i + 1;
675     }
676
677     //Add 001 bit, this function needs to be called the first one in the chain
678     mFramebufferStatus = 1;
679   }
680
681   inline void GenRenderbuffers(GLsizei n, GLuint* renderbuffers) override
682   {
683     for(int i = 0; i < n; i++)
684     {
685       renderbuffers[i] = i + 1;
686     }
687   }
688
689   /**
690    * This method can be used by test cases, to manipulate the texture IDs generated by GenTextures.
691    * @param[in] ids A vector containing the next IDs to be generated
692    */
693   inline void SetNextTextureIds(const std::vector<GLuint>& ids)
694   {
695     mNextTextureIds = ids;
696   }
697
698   inline const std::vector<GLuint>& GetNextTextureIds()
699   {
700     return mNextTextureIds;
701   }
702
703   inline void GenTextures(GLsizei count, GLuint* textures) override
704   {
705     for(int i = 0; i < count; ++i)
706     {
707       if(!mNextTextureIds.empty())
708       {
709         *(textures + i) = mNextTextureIds[0];
710         mNextTextureIds.erase(mNextTextureIds.begin());
711       }
712       else
713       {
714         *(textures + i) = ++mLastAutoTextureIdUsed;
715       }
716       mNumGeneratedTextures++;
717     }
718
719     TraceCallStack::NamedParams namedParams;
720     namedParams["count"] << count;
721
722     std::stringstream out;
723     for(int i = 0; i < count; i++)
724     {
725       out << textures[i];
726       if(i < count - 1)
727       {
728         out << ", ";
729       }
730       std::ostringstream oss;
731       oss << "indices[" << i << "]";
732       namedParams[oss.str()] << textures[i];
733     }
734
735     mTextureTrace.PushCall("GenTextures", out.str(), namedParams);
736   }
737
738   inline GLuint GetLastGenTextureId()
739   {
740     return mLastAutoTextureIdUsed;
741   }
742
743   inline GLuint GetNumGeneratedTextures()
744   {
745     return mNumGeneratedTextures;
746   }
747
748   inline void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) override
749   {
750   }
751
752   inline void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) override
753   {
754     switch(index)
755     {
756       case 0:
757         *length = snprintf(name, bufsize, "sTexture");
758         *type   = GL_SAMPLER_2D;
759         *size   = 1;
760         break;
761       case 1:
762         *length = snprintf(name, bufsize, "sEffect");
763         *type   = GL_SAMPLER_2D;
764         *size   = 1;
765         break;
766       case 2:
767         *length = snprintf(name, bufsize, "sGloss");
768         *type   = GL_SAMPLER_2D;
769         *size   = 1;
770         break;
771       default:
772         break;
773     }
774   }
775
776   inline void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) override
777   {
778   }
779
780   inline int GetAttribLocation(GLuint program, const char* name) override
781   {
782     std::string check(name);
783     auto        iter = std::find(mAttribLocs.begin(), mAttribLocs.end(), check);
784     if(iter == mAttribLocs.end())
785       return -1;
786     return iter - mAttribLocs.begin();
787   }
788
789   inline void GetBooleanv(GLenum pname, GLboolean* params) override
790   {
791   }
792
793   inline void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params) override
794   {
795   }
796
797   inline GLenum GetError(void) override
798   {
799     return mGetErrorResult;
800   }
801
802   inline void GetFloatv(GLenum pname, GLfloat* params) override
803   {
804   }
805
806   inline void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) override
807   {
808   }
809
810   inline void GetIntegerv(GLenum pname, GLint* params) override
811   {
812     switch(pname)
813     {
814       case GL_MAX_TEXTURE_SIZE:
815         *params = 2048;
816         break;
817       case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
818         *params = 8;
819         break;
820       case GL_NUM_PROGRAM_BINARY_FORMATS_OES:
821         *params = mNumBinaryFormats;
822         break;
823       case GL_PROGRAM_BINARY_FORMATS_OES:
824         *params = mBinaryFormats;
825         break;
826     }
827   }
828
829   inline void GetProgramiv(GLuint program, GLenum pname, GLint* params) override
830   {
831     switch(pname)
832     {
833       case GL_LINK_STATUS:
834         *params = mLinkStatus;
835         break;
836       case GL_PROGRAM_BINARY_LENGTH_OES:
837         *params = mProgramBinaryLength;
838         break;
839       case GL_ACTIVE_UNIFORMS:
840         *params = mNumberOfActiveUniforms;
841         break;
842       case GL_ACTIVE_UNIFORM_MAX_LENGTH:
843         *params = 100;
844         break;
845       case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
846         *params = 100;
847         break;
848     }
849   }
850
851   inline void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) override
852   {
853   }
854
855   inline void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) override
856   {
857   }
858
859   inline void GetShaderiv(GLuint shader, GLenum pname, GLint* params) override
860   {
861     switch(pname)
862     {
863       case GL_COMPILE_STATUS:
864         *params = mCompileStatus;
865         break;
866     }
867   }
868
869   inline void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) override
870   {
871   }
872
873   inline void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) override
874   {
875   }
876
877   inline const GLubyte* GetString(GLenum name) override
878   {
879     return mGetStringResult;
880   }
881
882   inline void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) override
883   {
884   }
885
886   inline void GetTexParameteriv(GLenum target, GLenum pname, GLint* params) override
887   {
888   }
889
890   inline void GetUniformfv(GLuint program, GLint location, GLfloat* params) override
891   {
892   }
893
894   inline void GetUniformiv(GLuint program, GLint location, GLint* params) override
895   {
896   }
897
898   inline GLint GetUniformLocation(GLuint program, const char* name) override
899   {
900     ProgramUniformMap::iterator it = mUniforms.find(program);
901     if(it == mUniforms.end())
902     {
903       // Not a valid program ID
904       mGetErrorResult = GL_INVALID_OPERATION;
905       return -1;
906     }
907
908     UniformIDMap&          uniformIDs = it->second;
909     UniformIDMap::iterator it2        = uniformIDs.find(name);
910     if(it2 == uniformIDs.end())
911     {
912       // Uniform not found, so add it...
913       uniformIDs[name] = mLastUniformIdUsed++;
914       return mLastUniformIdUsed;
915     }
916
917     return it2->second;
918   }
919
920   inline void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) override
921   {
922   }
923
924   inline void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params) override
925   {
926   }
927
928   inline void GetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer) override
929   {
930   }
931
932   inline void Hint(GLenum target, GLenum mode) override
933   {
934   }
935
936   inline GLboolean IsBuffer(GLuint buffer) override
937   {
938     return mIsBufferResult;
939   }
940
941   inline GLboolean IsEnabled(GLenum cap) override
942   {
943     return mIsEnabledResult;
944   }
945
946   inline GLboolean IsFramebuffer(GLuint framebuffer) override
947   {
948     return mIsFramebufferResult;
949   }
950
951   inline GLboolean IsProgram(GLuint program) override
952   {
953     return mIsProgramResult;
954   }
955
956   inline GLboolean IsRenderbuffer(GLuint renderbuffer) override
957   {
958     return mIsRenderbufferResult;
959   }
960
961   inline GLboolean IsShader(GLuint shader) override
962   {
963     return mIsShaderResult;
964   }
965
966   inline GLboolean IsTexture(GLuint texture) override
967   {
968     return mIsTextureResult;
969   }
970
971   inline void LineWidth(GLfloat width) override
972   {
973   }
974
975   inline void LinkProgram(GLuint program) override
976   {
977     std::stringstream out;
978     out << program;
979
980     TraceCallStack::NamedParams namedParams;
981     namedParams["program"] << program;
982     mShaderTrace.PushCall("LinkProgram", out.str(), namedParams);
983
984     mNumberOfActiveUniforms = 3;
985
986     GetUniformLocation(program, "uRendererColor");
987     GetUniformLocation(program, "uCustom");
988     GetUniformLocation(program, "uCustom3");
989     GetUniformLocation(program, "uFadeColor");
990     GetUniformLocation(program, "uUniform1");
991     GetUniformLocation(program, "uUniform2");
992     GetUniformLocation(program, "uUniform3");
993     GetUniformLocation(program, "uFadeProgress");
994     GetUniformLocation(program, "uANormalMatrix");
995     GetUniformLocation(program, "sEffect");
996     GetUniformLocation(program, "sTexture");
997     GetUniformLocation(program, "sTextureRect");
998     GetUniformLocation(program, "sGloss");
999     GetUniformLocation(program, "uColor");
1000     GetUniformLocation(program, "uModelMatrix");
1001     GetUniformLocation(program, "uModelView");
1002     GetUniformLocation(program, "uMvpMatrix");
1003     GetUniformLocation(program, "uNormalMatrix");
1004     GetUniformLocation(program, "uProjection");
1005     GetUniformLocation(program, "uSize");
1006     GetUniformLocation(program, "uViewMatrix");
1007     GetUniformLocation(program, "uLightCameraProjectionMatrix");
1008     GetUniformLocation(program, "uLightCameraViewMatrix");
1009
1010     for(const auto& uniform : mCustomUniformData)
1011     {
1012       GetUniformLocation(program, uniform.name.c_str());
1013     }
1014   }
1015
1016   inline void PixelStorei(GLenum pname, GLint param) override
1017   {
1018   }
1019
1020   inline void PolygonOffset(GLfloat factor, GLfloat units) override
1021   {
1022   }
1023
1024   inline void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) override
1025   {
1026   }
1027
1028   inline void ReleaseShaderCompiler(void) override
1029   {
1030   }
1031
1032   inline void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) override
1033   {
1034   }
1035
1036   inline void SampleCoverage(GLclampf value, GLboolean invert) override
1037   {
1038   }
1039
1040   inline void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) override
1041   {
1042     mScissorParams.x      = x;
1043     mScissorParams.y      = y;
1044     mScissorParams.width  = width;
1045     mScissorParams.height = height;
1046
1047     std::stringstream out;
1048     out << x << ", " << y << ", " << width << ", " << height;
1049     TraceCallStack::NamedParams namedParams;
1050     namedParams["x"] << x;
1051     namedParams["y"] << y;
1052     namedParams["width"] << width;
1053     namedParams["height"] << height;
1054     mScissorTrace.PushCall("Scissor", out.str(), namedParams);
1055   }
1056
1057   inline void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length) override
1058   {
1059   }
1060
1061   inline void ShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length) override
1062   {
1063     std::string stringBuilder;
1064     for(int i = 0; i < count; ++i)
1065     {
1066       stringBuilder += string[i];
1067     }
1068     mShaderSources[shader] = stringBuilder;
1069     mLastShaderCompiled    = shader;
1070   }
1071
1072   inline void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source) override
1073   {
1074     const std::string shaderSource       = mShaderSources[shader];
1075     const int         shaderSourceLength = static_cast<int>(shaderSource.length());
1076     if(shaderSourceLength < bufsize)
1077     {
1078       strncpy(source, shaderSource.c_str(), shaderSourceLength);
1079       *length = shaderSourceLength;
1080     }
1081     else
1082     {
1083       *length = bufsize - 1;
1084       strncpy(source, shaderSource.c_str(), *length);
1085       source[*length] = 0x0;
1086     }
1087   }
1088
1089   inline std::string GetShaderSource(GLuint shader)
1090   {
1091     return mShaderSources[shader];
1092   }
1093
1094   inline void StencilFunc(GLenum func, GLint ref, GLuint mask) override
1095   {
1096     std::stringstream out;
1097     out << func << ", " << ref << ", " << mask;
1098
1099     TraceCallStack::NamedParams namedParams;
1100     namedParams["func"] << std::hex << func;
1101     namedParams["ref"] << ref;
1102     namedParams["mask"] << mask;
1103
1104     mStencilFunctionTrace.PushCall("StencilFunc", out.str(), namedParams);
1105   }
1106
1107   inline void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) override
1108   {
1109     std::stringstream out;
1110     out << face << ", " << func << ", " << ref << ", " << mask;
1111
1112     TraceCallStack::NamedParams namedParams;
1113     namedParams["face"] << std::hex << face;
1114     namedParams["func"] << std::hex << func;
1115     namedParams["ref"] << ref;
1116     namedParams["mask"] << mask;
1117
1118     mStencilFunctionTrace.PushCall("StencilFuncSeparate", out.str(), namedParams);
1119   }
1120
1121   inline void StencilMask(GLuint mask) override
1122   {
1123     std::stringstream out;
1124     out << mask;
1125
1126     TraceCallStack::NamedParams namedParams;
1127     namedParams["mask"] << mask;
1128
1129     mStencilFunctionTrace.PushCall("StencilMask", out.str(), namedParams);
1130   }
1131
1132   inline void StencilMaskSeparate(GLenum face, GLuint mask) override
1133   {
1134     std::stringstream out;
1135     out << face << ", " << mask;
1136
1137     TraceCallStack::NamedParams namedParams;
1138     namedParams["face"] << std::hex << face;
1139     namedParams["mask"] << mask;
1140
1141     mStencilFunctionTrace.PushCall("StencilMaskSeparate", out.str(), namedParams);
1142   }
1143
1144   inline void StencilOp(GLenum fail, GLenum zfail, GLenum zpass) override
1145   {
1146     std::stringstream out;
1147     out << fail << ", " << zfail << ", " << zpass;
1148
1149     TraceCallStack::NamedParams namedParams;
1150     namedParams["fail"] << std::hex << fail;
1151     namedParams["zfail"] << std::hex << zfail;
1152     namedParams["zpass"] << std::hex << zpass;
1153
1154     mStencilFunctionTrace.PushCall("StencilOp", out.str(), namedParams);
1155   }
1156
1157   inline void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) override
1158   {
1159     std::stringstream out;
1160     out << face << ", " << fail << ", " << zfail << "," << zpass;
1161
1162     TraceCallStack::NamedParams namedParams;
1163     namedParams["face"] << std::hex << face;
1164     namedParams["fail"] << std::hex << fail;
1165     namedParams["zfail"] << std::hex << zfail;
1166     namedParams["zpass"] << std::hex << zpass;
1167
1168     mStencilFunctionTrace.PushCall("StencilOpSeparate", out.str(), namedParams);
1169   }
1170
1171   inline void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels) override
1172   {
1173     std::stringstream out;
1174     out << target << ", " << level << ", " << width << ", " << height;
1175
1176     TraceCallStack::NamedParams namedParams;
1177     namedParams["target"] << std::hex << target;
1178     namedParams["level"] << level;
1179     namedParams["internalformat"] << internalformat;
1180     namedParams["width"] << width;
1181     namedParams["height"] << height;
1182     namedParams["border"] << border;
1183     namedParams["format"] << std::hex << format;
1184     namedParams["type"] << std::hex << type;
1185
1186     mTextureTrace.PushCall("TexImage2D", out.str(), namedParams);
1187   }
1188
1189   inline void TexParameterf(GLenum target, GLenum pname, GLfloat param) override
1190   {
1191     std::stringstream out;
1192     out << target << ", " << pname << ", " << param;
1193
1194     TraceCallStack::NamedParams namedParams;
1195     namedParams["target"] << std::hex << target;
1196     namedParams["pname"] << std::hex << pname;
1197     namedParams["param"] << param;
1198
1199     mTexParameterTrace.PushCall("TexParameterf", out.str(), namedParams);
1200   }
1201
1202   inline void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params) override
1203   {
1204     std::stringstream out;
1205     out << target << ", " << pname << ", " << params[0];
1206
1207     TraceCallStack::NamedParams namedParams;
1208     namedParams["target"] << std::hex << target;
1209     namedParams["pname"] << std::hex << pname;
1210     namedParams["params[0]"] << params[0];
1211
1212     mTexParameterTrace.PushCall("TexParameterfv", out.str(), namedParams);
1213   }
1214
1215   inline void TexParameteri(GLenum target, GLenum pname, GLint param) override
1216   {
1217     std::stringstream out;
1218     out << std::hex << target << ", " << pname << ", " << param;
1219     std::string params = out.str();
1220
1221     TraceCallStack::NamedParams namedParams;
1222     namedParams["target"] << std::hex << target;
1223     namedParams["pname"] << std::hex << pname;
1224     namedParams["param"] << param;
1225     mTexParameterTrace.PushCall("TexParameteri", params, namedParams);
1226   }
1227
1228   inline void TexParameteriv(GLenum target, GLenum pname, const GLint* params) override
1229   {
1230     std::stringstream out;
1231     out << target << ", " << pname << ", " << params[0];
1232     TraceCallStack::NamedParams namedParams;
1233     namedParams["target"] << std::hex << target;
1234     namedParams["pname"] << std::hex << pname;
1235     namedParams["params[0]"] << params[0];
1236     mTexParameterTrace.PushCall("TexParameteriv", out.str(), namedParams);
1237   }
1238
1239   inline void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) override
1240   {
1241     std::stringstream out;
1242     out << target << ", " << level << ", " << xoffset << ", " << yoffset << ", " << width << ", " << height;
1243
1244     TraceCallStack::NamedParams namedParams;
1245     namedParams["target"] << std::hex << target;
1246     namedParams["level"] << level;
1247     namedParams["xoffset"] << xoffset;
1248     namedParams["yoffset"] << yoffset;
1249     namedParams["width"] << width;
1250     namedParams["height"] << height;
1251     mTextureTrace.PushCall("TexSubImage2D", out.str(), namedParams);
1252   }
1253
1254   inline void Uniform1f(GLint location, GLfloat value) override
1255   {
1256     std::string params = std::to_string(value);
1257     AddUniformCallToTraceStack(location, params);
1258
1259     if(!mProgramUniforms1f.SetUniformValue(mCurrentProgram, location, value))
1260     {
1261       mGetErrorResult = GL_INVALID_OPERATION;
1262     }
1263   }
1264
1265   inline void Uniform1fv(GLint location, GLsizei count, const GLfloat* v) override
1266   {
1267     std::string params;
1268     for(int i = 0; i < count; ++i)
1269     {
1270       params = params + std::to_string(v[i]) + ",";
1271     }
1272
1273     AddUniformCallToTraceStack(location, params);
1274
1275     for(int i = 0; i < count; ++i)
1276     {
1277       if(!mProgramUniforms1f.SetUniformValue(mCurrentProgram, location, v[i]))
1278       {
1279         mGetErrorResult = GL_INVALID_OPERATION;
1280         break;
1281       }
1282     }
1283   }
1284
1285   inline void Uniform1i(GLint location, GLint x) override
1286   {
1287     std::string params = std::to_string(x);
1288
1289     AddUniformCallToTraceStack(location, params);
1290
1291     if(!mProgramUniforms1i.SetUniformValue(mCurrentProgram, location, x))
1292     {
1293       mGetErrorResult = GL_INVALID_OPERATION;
1294     }
1295   }
1296
1297   inline void Uniform1iv(GLint location, GLsizei count, const GLint* v) override
1298   {
1299     std::ostringstream out;
1300     for(GLsizei i = 0; i < count; ++i) out << (!i ? "" : ", ") << v[i];
1301     AddUniformCallToTraceStack(location, out.str());
1302
1303     for(int i = 0; i < count; ++i)
1304     {
1305       if(!mProgramUniforms1i.SetUniformValue(mCurrentProgram,
1306                                              location,
1307                                              v[i]))
1308       {
1309         mGetErrorResult = GL_INVALID_OPERATION;
1310         break;
1311       }
1312     }
1313   }
1314
1315   inline void Uniform2f(GLint location, GLfloat x, GLfloat y) override
1316   {
1317     std::string params = std::to_string(x) + "," + std::to_string(y);
1318     AddUniformCallToTraceStack(location, params);
1319
1320     if(!mProgramUniforms2f.SetUniformValue(mCurrentProgram,
1321                                            location,
1322                                            Vector2(x, y)))
1323     {
1324       mGetErrorResult = GL_INVALID_OPERATION;
1325     }
1326   }
1327
1328   inline void Uniform2fv(GLint location, GLsizei count, const GLfloat* v) override
1329   {
1330     std::ostringstream out;
1331     for(GLsizei i = 0; i < count; ++i) out << (!i ? "" : ", ") << v[i];
1332     AddUniformCallToTraceStack(location, out.str());
1333
1334     for(int i = 0; i < count; ++i)
1335     {
1336       if(!mProgramUniforms2f.SetUniformValue(mCurrentProgram,
1337                                              location,
1338                                              Vector2(v[2 * i], v[2 * i + 1])))
1339       {
1340         mGetErrorResult = GL_INVALID_OPERATION;
1341         break;
1342       }
1343     }
1344   }
1345
1346   inline void Uniform2i(GLint location, GLint x, GLint y) override
1347   {
1348     std::string params = std::to_string(x) + "," + std::to_string(y);
1349     AddUniformCallToTraceStack(location, params);
1350   }
1351
1352   inline void Uniform2iv(GLint location, GLsizei count, const GLint* v) override
1353   {
1354     std::ostringstream out;
1355     for(GLsizei i = 0; i < count; ++i) out << (!i ? "" : ", ") << v[i];
1356     AddUniformCallToTraceStack(location, out.str());
1357   }
1358
1359   inline void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) override
1360   {
1361     std::string params = std::to_string(x) + "," + std::to_string(y) + "," + std::to_string(z);
1362     AddUniformCallToTraceStack(location, params);
1363
1364     if(!mProgramUniforms3f.SetUniformValue(mCurrentProgram,
1365                                            location,
1366                                            Vector3(x, y, z)))
1367     {
1368       mGetErrorResult = GL_INVALID_OPERATION;
1369     }
1370   }
1371
1372   inline void Uniform3fv(GLint location, GLsizei count, const GLfloat* v) override
1373   {
1374     std::ostringstream out;
1375     for(GLsizei i = 0; i < count; ++i) out << (!i ? "" : ", ") << v[i];
1376     AddUniformCallToTraceStack(location, out.str());
1377
1378     for(int i = 0; i < count; ++i)
1379     {
1380       if(!mProgramUniforms3f.SetUniformValue(
1381            mCurrentProgram,
1382            location,
1383            Vector3(v[3 * i], v[3 * i + 1], v[3 * i + 2])))
1384       {
1385         mGetErrorResult = GL_INVALID_OPERATION;
1386         break;
1387       }
1388     }
1389   }
1390
1391   inline void Uniform3i(GLint location, GLint x, GLint y, GLint z) override
1392   {
1393     std::string params = std::to_string(x) + "," + std::to_string(y) + "," + std::to_string(z);
1394     AddUniformCallToTraceStack(location, params);
1395   }
1396
1397   inline void Uniform3iv(GLint location, GLsizei count, const GLint* v) override
1398   {
1399     std::ostringstream out;
1400     for(GLsizei i = 0; i < count; ++i) out << (!i ? "" : ", ") << v[i];
1401     AddUniformCallToTraceStack(location, out.str());
1402   }
1403
1404   inline void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) override
1405   {
1406     std::string params = std::to_string(x) + "," + std::to_string(y) + "," + std::to_string(z) + "," + std::to_string(w);
1407     AddUniformCallToTraceStack(location, params);
1408
1409     if(!mProgramUniforms4f.SetUniformValue(mCurrentProgram,
1410                                            location,
1411                                            Vector4(x, y, z, w)))
1412     {
1413       mGetErrorResult = GL_INVALID_OPERATION;
1414     }
1415   }
1416
1417   inline void Uniform4fv(GLint location, GLsizei count, const GLfloat* v) override
1418   {
1419     std::ostringstream out;
1420     for(GLsizei i = 0; i < count; ++i) out << (!i ? "" : ", ") << v[i];
1421     AddUniformCallToTraceStack(location, out.str());
1422
1423     for(int i = 0; i < count; ++i)
1424     {
1425       if(!mProgramUniforms4f.SetUniformValue(
1426            mCurrentProgram,
1427            location,
1428            Vector4(v[4 * i], v[4 * i + 1], v[4 * i + 2], v[4 * i + 3])))
1429       {
1430         mGetErrorResult = GL_INVALID_OPERATION;
1431         break;
1432       }
1433     }
1434   }
1435
1436   inline void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) override
1437   {
1438     std::string params = std::to_string(x) + "," + std::to_string(y) + "," + std::to_string(z) + "," + std::to_string(w);
1439     AddUniformCallToTraceStack(location, params);
1440   }
1441
1442   inline void Uniform4iv(GLint location, GLsizei count, const GLint* v) override
1443   {
1444     std::ostringstream out;
1445     for(GLsizei i = 0; i < count; ++i) out << (!i ? "" : ", ") << v[i];
1446     AddUniformCallToTraceStack(location, out.str());
1447   }
1448
1449   inline void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) override
1450   {
1451     std::ostringstream out;
1452     for(GLsizei i = 0; i < count; ++i) out << (!i ? "" : ", ") << value[i];
1453     AddUniformCallToTraceStack(location, out.str());
1454   }
1455
1456   inline void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) override
1457   {
1458     std::ostringstream out;
1459     for(GLsizei i = 0; i < count; ++i) out << (!i ? "" : ", ") << value[i];
1460     AddUniformCallToTraceStack(location, out.str());
1461
1462     for(int i = 0; i < count; ++i)
1463     {
1464       if(!mProgramUniformsMat3.SetUniformValue(
1465            mCurrentProgram,
1466            location,
1467            Matrix3(value[0], value[1], value[2], value[3], value[4], value[5], value[6], value[7], value[8])))
1468       {
1469         mGetErrorResult = GL_INVALID_OPERATION;
1470         break;
1471       }
1472     }
1473   }
1474
1475   inline void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) override
1476   {
1477     std::ostringstream out;
1478     for(GLsizei i = 0; i < count; ++i) out << (!i ? "" : ", ") << value[i];
1479     AddUniformCallToTraceStack(location, out.str());
1480
1481     for(int i = 0; i < count; ++i)
1482     {
1483       if(!mProgramUniformsMat4.SetUniformValue(
1484            mCurrentProgram,
1485            location,
1486            Matrix(value)))
1487       {
1488         mGetErrorResult = GL_INVALID_OPERATION;
1489         break;
1490       }
1491     }
1492   }
1493
1494   inline void UseProgram(GLuint program) override
1495   {
1496     mCurrentProgram = program;
1497   }
1498
1499   inline void ValidateProgram(GLuint program) override
1500   {
1501   }
1502
1503   inline void VertexAttrib1f(GLuint indx, GLfloat x) override
1504   {
1505   }
1506
1507   inline void VertexAttrib1fv(GLuint indx, const GLfloat* values) override
1508   {
1509   }
1510
1511   inline void VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) override
1512   {
1513   }
1514
1515   inline void VertexAttrib2fv(GLuint indx, const GLfloat* values) override
1516   {
1517   }
1518
1519   inline void VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) override
1520   {
1521   }
1522
1523   inline void VertexAttrib3fv(GLuint indx, const GLfloat* values) override
1524   {
1525   }
1526
1527   inline void VertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) override
1528   {
1529   }
1530
1531   inline void VertexAttrib4fv(GLuint indx, const GLfloat* values) override
1532   {
1533   }
1534
1535   inline void VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) override
1536   {
1537     TraceCallStack::NamedParams namedParams;
1538     namedParams["index"] << index;
1539     namedParams["size"] << size;
1540     namedParams["type"] << std::hex << type;
1541     namedParams["normalized"] << (normalized ? "T" : "F");
1542     namedParams["stride"] << stride;
1543     namedParams["offset"] << std::to_string(reinterpret_cast<unsigned long>(ptr));
1544
1545     mBufferTrace.PushCall("VertexAttribPointer", namedParams.str(), namedParams);
1546   }
1547
1548   inline void Viewport(GLint x, GLint y, GLsizei width, GLsizei height) override
1549   {
1550     std::string commaString(", ");
1551     std::string params(std::to_string(x) + commaString + std::to_string(y) + commaString + std::to_string(width) + commaString + std::to_string(height));
1552
1553     mViewportTrace.PushCall("Viewport", params);
1554   }
1555
1556   /* OpenGL ES 3.0 */
1557
1558   inline void ReadBuffer(GLenum mode) override
1559   {
1560   }
1561
1562   inline void DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices) override
1563   {
1564   }
1565
1566   inline void TexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels) override
1567   {
1568   }
1569
1570   inline void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels) override
1571   {
1572   }
1573
1574   inline void CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) override
1575   {
1576   }
1577
1578   inline void CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) override
1579   {
1580   }
1581
1582   inline void CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data) override
1583   {
1584   }
1585
1586   inline void GenQueries(GLsizei n, GLuint* ids) override
1587   {
1588   }
1589
1590   inline void DeleteQueries(GLsizei n, const GLuint* ids) override
1591   {
1592   }
1593
1594   inline GLboolean IsQuery(GLuint id) override
1595   {
1596     return false;
1597   }
1598
1599   inline void BeginQuery(GLenum target, GLuint id) override
1600   {
1601   }
1602
1603   inline void EndQuery(GLenum target) override
1604   {
1605   }
1606
1607   inline void GetQueryiv(GLenum target, GLenum pname, GLint* params) override
1608   {
1609   }
1610
1611   inline void GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) override
1612   {
1613   }
1614
1615   inline GLboolean UnmapBuffer(GLenum target) override
1616   {
1617     if(mMappedBuffer)
1618     {
1619       free(mMappedBuffer);
1620       mMappedBuffer = nullptr;
1621     }
1622     return true; // false indicates corruption, nothing else.
1623   }
1624
1625   inline void GetBufferPointerv(GLenum target, GLenum pname, GLvoid** params) override
1626   {
1627   }
1628
1629   inline void DrawBuffers(GLsizei n, const GLenum* bufs) override
1630   {
1631   }
1632
1633   inline void UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) override
1634   {
1635   }
1636
1637   inline void UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) override
1638   {
1639   }
1640
1641   inline void UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) override
1642   {
1643   }
1644
1645   inline void UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) override
1646   {
1647   }
1648
1649   inline void UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) override
1650   {
1651   }
1652
1653   inline void UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) override
1654   {
1655   }
1656
1657   inline void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) override
1658   {
1659   }
1660
1661   inline void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) override
1662   {
1663   }
1664
1665   inline void FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) override
1666   {
1667   }
1668
1669   inline GLvoid* MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) override
1670   {
1671     mMappedBuffer = reinterpret_cast<GLvoid*>(malloc(offset + length));
1672     return mMappedBuffer;
1673   }
1674
1675   inline void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) override
1676   {
1677   }
1678
1679   inline void BindVertexArray(GLuint array) override
1680   {
1681   }
1682
1683   inline void DeleteVertexArrays(GLsizei n, const GLuint* arrays) override
1684   {
1685   }
1686
1687   inline void GenVertexArrays(GLsizei n, GLuint* arrays) override
1688   {
1689   }
1690
1691   inline GLboolean IsVertexArray(GLuint array) override
1692   {
1693     return false;
1694   }
1695
1696   inline void GetIntegeri_v(GLenum target, GLuint index, GLint* data) override
1697   {
1698   }
1699
1700   inline void BeginTransformFeedback(GLenum primitiveMode) override
1701   {
1702   }
1703
1704   inline void EndTransformFeedback(void) override
1705   {
1706   }
1707
1708   inline void BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) override
1709   {
1710   }
1711
1712   inline void BindBufferBase(GLenum target, GLuint index, GLuint buffer) override
1713   {
1714   }
1715
1716   inline void TransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode) override
1717   {
1718   }
1719
1720   inline void GetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name) override
1721   {
1722   }
1723
1724   inline void VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) override
1725   {
1726   }
1727
1728   inline void GetVertexAttribIiv(GLuint index, GLenum pname, GLint* params) override
1729   {
1730   }
1731
1732   inline void GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params) override
1733   {
1734   }
1735
1736   inline void VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w) override
1737   {
1738   }
1739
1740   inline void VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) override
1741   {
1742   }
1743
1744   inline void VertexAttribI4iv(GLuint index, const GLint* v) override
1745   {
1746   }
1747
1748   inline void VertexAttribI4uiv(GLuint index, const GLuint* v) override
1749   {
1750   }
1751
1752   inline void GetUniformuiv(GLuint program, GLint location, GLuint* params) override
1753   {
1754   }
1755
1756   inline GLint GetFragDataLocation(GLuint program, const GLchar* name) override
1757   {
1758     return -1;
1759   }
1760
1761   inline void Uniform1ui(GLint location, GLuint v0) override
1762   {
1763   }
1764
1765   inline void Uniform2ui(GLint location, GLuint v0, GLuint v1) override
1766   {
1767   }
1768
1769   inline void Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) override
1770   {
1771   }
1772
1773   inline void Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) override
1774   {
1775   }
1776
1777   inline void Uniform1uiv(GLint location, GLsizei count, const GLuint* value) override
1778   {
1779   }
1780
1781   inline void Uniform2uiv(GLint location, GLsizei count, const GLuint* value) override
1782   {
1783   }
1784
1785   inline void Uniform3uiv(GLint location, GLsizei count, const GLuint* value) override
1786   {
1787   }
1788
1789   inline void Uniform4uiv(GLint location, GLsizei count, const GLuint* value) override
1790   {
1791   }
1792
1793   inline void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) override
1794   {
1795   }
1796
1797   inline void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) override
1798   {
1799   }
1800
1801   inline void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) override
1802   {
1803   }
1804
1805   inline void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) override
1806   {
1807   }
1808
1809   inline const GLubyte* GetStringi(GLenum name, GLuint index) override
1810   {
1811     return NULL;
1812   }
1813
1814   inline void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) override
1815   {
1816   }
1817
1818   inline void GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices) override
1819   {
1820   }
1821
1822   inline void GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params) override
1823   {
1824   }
1825
1826   inline GLuint GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) override
1827   {
1828     return GL_INVALID_INDEX;
1829   }
1830
1831   inline void GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) override
1832   {
1833   }
1834
1835   inline void GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName) override
1836   {
1837   }
1838
1839   inline void UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) override
1840   {
1841   }
1842
1843   inline void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) override
1844   {
1845   }
1846
1847   inline void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount) override
1848   {
1849   }
1850
1851   inline GLsync FenceSync(GLenum condition, GLbitfield flags) override
1852   {
1853     return NULL;
1854   }
1855
1856   inline GLboolean IsSync(GLsync sync) override
1857   {
1858     return false;
1859   }
1860
1861   inline void DeleteSync(GLsync sync) override
1862   {
1863   }
1864
1865   inline GLenum ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) override
1866   {
1867     return 0;
1868   }
1869
1870   inline void WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) override
1871   {
1872   }
1873
1874   inline void GetInteger64v(GLenum pname, GLint64* params) override
1875   {
1876   }
1877
1878   inline void GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) override
1879   {
1880   }
1881
1882   inline void GetInteger64i_v(GLenum target, GLuint index, GLint64* data) override
1883   {
1884   }
1885
1886   inline void GetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params) override
1887   {
1888   }
1889
1890   inline void GenSamplers(GLsizei count, GLuint* samplers) override
1891   {
1892   }
1893
1894   inline void DeleteSamplers(GLsizei count, const GLuint* samplers) override
1895   {
1896   }
1897
1898   inline GLboolean IsSampler(GLuint sampler) override
1899   {
1900     return false;
1901   }
1902
1903   inline void BindSampler(GLuint unit, GLuint sampler) override
1904   {
1905   }
1906
1907   inline void SamplerParameteri(GLuint sampler, GLenum pname, GLint param) override
1908   {
1909   }
1910
1911   inline void SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param) override
1912   {
1913   }
1914
1915   inline void SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) override
1916   {
1917   }
1918
1919   inline void SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param) override
1920   {
1921   }
1922
1923   inline void GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params) override
1924   {
1925   }
1926
1927   inline void GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) override
1928   {
1929   }
1930
1931   inline void VertexAttribDivisor(GLuint index, GLuint divisor) override
1932   {
1933   }
1934
1935   inline void BindTransformFeedback(GLenum target, GLuint id) override
1936   {
1937   }
1938
1939   inline void DeleteTransformFeedbacks(GLsizei n, const GLuint* ids) override
1940   {
1941   }
1942
1943   inline void GenTransformFeedbacks(GLsizei n, GLuint* ids) override
1944   {
1945   }
1946
1947   inline GLboolean IsTransformFeedback(GLuint id) override
1948   {
1949     return false;
1950   }
1951
1952   inline void PauseTransformFeedback(void) override
1953   {
1954   }
1955
1956   inline void ResumeTransformFeedback(void) override
1957   {
1958   }
1959
1960   inline void GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary) override
1961   {
1962     mGetProgramBinaryCalled = true;
1963   }
1964
1965   inline void ProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length) override
1966   {
1967   }
1968
1969   inline void ProgramParameteri(GLuint program, GLenum pname, GLint value) override
1970   {
1971   }
1972
1973   inline void InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments) override
1974   {
1975   }
1976
1977   inline void InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) override
1978   {
1979   }
1980
1981   inline void TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) override
1982   {
1983   }
1984
1985   inline void TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) override
1986   {
1987   }
1988
1989   inline void GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) override
1990   {
1991   }
1992
1993   inline void BlendBarrier(void)
1994   {
1995   }
1996
1997 private:
1998   inline void AddUniformCallToTraceStack(GLint location, const std::string& value)
1999   {
2000     std::string name    = "<not found>";
2001     bool        matched = false;
2002
2003     UniformIDMap& map = mUniforms[mCurrentProgram];
2004     for(UniformIDMap::iterator it = map.begin(); it != map.end(); ++it)
2005     {
2006       if(it->second == location)
2007       {
2008         name    = it->first;
2009         matched = true;
2010         break;
2011       }
2012     }
2013
2014     if(matched)
2015     {
2016       mSetUniformTrace.PushCall(name, value);
2017     }
2018   }
2019
2020 public: // TEST FUNCTIONS
2021   inline void SetCompileStatus(GLuint value)
2022   {
2023     mCompileStatus = value;
2024   }
2025   inline void SetLinkStatus(GLuint value)
2026   {
2027     mLinkStatus = value;
2028   }
2029   inline void SetAttribLocations(std::vector<std::string> locs)
2030   {
2031     mAttribLocs = locs;
2032   }
2033   inline void SetGetErrorResult(GLenum result)
2034   {
2035     mGetErrorResult = result;
2036   }
2037   inline void SetGetStringResult(GLubyte* result)
2038   {
2039     mGetStringResult = result;
2040   }
2041   inline void SetIsBufferResult(GLboolean result)
2042   {
2043     mIsBufferResult = result;
2044   }
2045   inline void SetIsEnabledResult(GLboolean result)
2046   {
2047     mIsEnabledResult = result;
2048   }
2049   inline void SetIsFramebufferResult(GLboolean result)
2050   {
2051     mIsFramebufferResult = result;
2052   }
2053   inline void SetIsProgramResult(GLboolean result)
2054   {
2055     mIsProgramResult = result;
2056   }
2057   inline void SetIsRenderbufferResult(GLboolean result)
2058   {
2059     mIsRenderbufferResult = result;
2060   }
2061   inline void SetIsShaderResult(GLboolean result)
2062   {
2063     mIsShaderResult = result;
2064   }
2065   inline void SetIsTextureResult(GLboolean result)
2066   {
2067     mIsTextureResult = result;
2068   }
2069   inline void SetCheckFramebufferStatusResult(GLenum result)
2070   {
2071     mCheckFramebufferStatusResult = result;
2072   }
2073   inline void SetNumBinaryFormats(GLint numFormats)
2074   {
2075     mNumBinaryFormats = numFormats;
2076   }
2077   inline void SetBinaryFormats(GLint binaryFormats)
2078   {
2079     mBinaryFormats = binaryFormats;
2080   }
2081   inline void SetProgramBinaryLength(GLint length)
2082   {
2083     mProgramBinaryLength = length;
2084   }
2085
2086   inline bool GetVertexAttribArrayState(GLuint index)
2087   {
2088     if(index >= MAX_ATTRIBUTE_CACHE_SIZE)
2089     {
2090       // out of range
2091       return false;
2092     }
2093     return mVertexAttribArrayState[index];
2094   }
2095   inline void ClearVertexAttribArrayChanged()
2096   {
2097     mVertexAttribArrayChanged = false;
2098   }
2099   inline bool GetVertexAttribArrayChanged()
2100   {
2101     return mVertexAttribArrayChanged;
2102   }
2103
2104   //Methods for CullFace verification
2105   inline void EnableCullFaceCallTrace(bool enable)
2106   {
2107     mCullFaceTrace.Enable(enable);
2108   }
2109   inline void ResetCullFaceCallStack()
2110   {
2111     mCullFaceTrace.Reset();
2112   }
2113   inline TraceCallStack& GetCullFaceTrace()
2114   {
2115     return mCullFaceTrace;
2116   }
2117
2118   //Methods for Enable/Disable call verification
2119   inline void EnableEnableDisableCallTrace(bool enable)
2120   {
2121     mEnableDisableTrace.Enable(enable);
2122   }
2123   inline void ResetEnableDisableCallStack()
2124   {
2125     mEnableDisableTrace.Reset();
2126   }
2127   inline TraceCallStack& GetEnableDisableTrace()
2128   {
2129     return mEnableDisableTrace;
2130   }
2131
2132   //Methods for Shader verification
2133   inline void EnableShaderCallTrace(bool enable)
2134   {
2135     mShaderTrace.Enable(enable);
2136   }
2137   inline void ResetShaderCallStack()
2138   {
2139     mShaderTrace.Reset();
2140   }
2141   inline TraceCallStack& GetShaderTrace()
2142   {
2143     return mShaderTrace;
2144   }
2145
2146   //Methods for Texture verification
2147   inline void EnableTextureCallTrace(bool enable)
2148   {
2149     mTextureTrace.Enable(enable);
2150   }
2151   inline void ResetTextureCallStack()
2152   {
2153     mTextureTrace.Reset();
2154   }
2155   inline TraceCallStack& GetTextureTrace()
2156   {
2157     return mTextureTrace;
2158   }
2159
2160   //Methods for Texture verification
2161   inline void EnableTexParameterCallTrace(bool enable)
2162   {
2163     mTexParameterTrace.Enable(enable);
2164   }
2165   inline void ResetTexParameterCallStack()
2166   {
2167     mTexParameterTrace.Reset();
2168   }
2169   inline TraceCallStack& GetTexParameterTrace()
2170   {
2171     return mTexParameterTrace;
2172   }
2173
2174   //Methods for Draw verification
2175   inline void EnableDrawCallTrace(bool enable)
2176   {
2177     mDrawTrace.Enable(enable);
2178   }
2179   inline void ResetDrawCallStack()
2180   {
2181     mDrawTrace.Reset();
2182   }
2183   inline TraceCallStack& GetDrawTrace()
2184   {
2185     return mDrawTrace;
2186   }
2187
2188   //Methods for Depth function verification
2189   inline void EnableDepthFunctionCallTrace(bool enable)
2190   {
2191     mDepthFunctionTrace.Enable(enable);
2192   }
2193   inline void ResetDepthFunctionCallStack()
2194   {
2195     mDepthFunctionTrace.Reset();
2196   }
2197   inline TraceCallStack& GetDepthFunctionTrace()
2198   {
2199     return mDepthFunctionTrace;
2200   }
2201
2202   //Methods for Stencil function verification
2203   inline void EnableStencilFunctionCallTrace(bool enable)
2204   {
2205     mStencilFunctionTrace.Enable(enable);
2206   }
2207   inline void ResetStencilFunctionCallStack()
2208   {
2209     mStencilFunctionTrace.Reset();
2210   }
2211   inline TraceCallStack& GetStencilFunctionTrace()
2212   {
2213     return mStencilFunctionTrace;
2214   }
2215
2216   //Methods for Scissor verification
2217   inline void EnableScissorCallTrace(bool enable)
2218   {
2219     mScissorTrace.Enable(enable);
2220   }
2221   inline void ResetScissorCallStack()
2222   {
2223     mScissorTrace.Reset();
2224   }
2225   inline TraceCallStack& GetScissorTrace()
2226   {
2227     return mScissorTrace;
2228   }
2229
2230   //Methods for Uniform function verification
2231   inline void EnableSetUniformCallTrace(bool enable)
2232   {
2233     mSetUniformTrace.Enable(enable);
2234   }
2235   inline void ResetSetUniformCallStack()
2236   {
2237     mSetUniformTrace.Reset();
2238   }
2239   inline TraceCallStack& GetSetUniformTrace()
2240   {
2241     return mSetUniformTrace;
2242   }
2243
2244   //Methods for Viewport verification
2245   inline void EnableViewportCallTrace(bool enable)
2246   {
2247     mViewportTrace.Enable(enable);
2248   }
2249   inline void ResetViewportCallStack()
2250   {
2251     mViewportTrace.Reset();
2252   }
2253   inline TraceCallStack& GetViewportTrace()
2254   {
2255     return mViewportTrace;
2256   }
2257   inline TraceCallStack& GetBufferTrace()
2258   {
2259     return mBufferTrace;
2260   }
2261
2262   template<typename T>
2263   inline bool GetUniformValue(const char* name, T& value) const
2264   {
2265     for(ProgramUniformMap::const_iterator program_it = mUniforms.begin();
2266         program_it != mUniforms.end();
2267         ++program_it)
2268     {
2269       const UniformIDMap& uniformIDs = program_it->second;
2270
2271       UniformIDMap::const_iterator uniform_it = uniformIDs.find(name);
2272       if(uniform_it != uniformIDs.end())
2273       {
2274         // found one matching uniform name, lets check the value...
2275         GLuint programId = program_it->first;
2276         GLint  uniformId = uniform_it->second;
2277
2278         const ProgramUniformValue<T>& mProgramUniforms = GetProgramUniformsForType(value);
2279         return mProgramUniforms.GetUniformValue(programId, uniformId, value);
2280       }
2281     }
2282     return false;
2283   }
2284
2285   template<typename T>
2286   inline bool CheckUniformValue(const char* name, const T& value) const
2287   {
2288     for(ProgramUniformMap::const_iterator program_it = mUniforms.begin();
2289         program_it != mUniforms.end();
2290         ++program_it)
2291     {
2292       const UniformIDMap& uniformIDs = program_it->second;
2293
2294       UniformIDMap::const_iterator uniform_it = uniformIDs.find(name);
2295       if(uniform_it != uniformIDs.end())
2296       {
2297         // found one matching uniform name, lets check the value...
2298         GLuint programId = program_it->first;
2299         GLint  uniformId = uniform_it->second;
2300
2301         const ProgramUniformValue<T>& mProgramUniforms = GetProgramUniformsForType(value);
2302         if(mProgramUniforms.CheckUniformValue(programId, uniformId, value))
2303         {
2304           // the value matches
2305           return true;
2306         }
2307       }
2308     }
2309
2310     fprintf(stderr, "%s Not found, printing possible values:\n", name);
2311     for(ProgramUniformMap::const_iterator program_it = mUniforms.begin();
2312         program_it != mUniforms.end();
2313         ++program_it)
2314     {
2315       const UniformIDMap& uniformIDs = program_it->second;
2316
2317       UniformIDMap::const_iterator uniform_it = uniformIDs.find(name);
2318       if(uniform_it != uniformIDs.end())
2319       {
2320         // found one matching uniform name, lets check the value...
2321         GLuint programId = program_it->first;
2322         GLint  uniformId = uniform_it->second;
2323
2324         const ProgramUniformValue<T>& mProgramUniforms = GetProgramUniformsForType(value);
2325         T                             origValue;
2326         if(mProgramUniforms.GetUniformValue(programId, uniformId, origValue))
2327         {
2328           std::stringstream out;
2329           out << "Program: " << programId << ", " << uniform_it->first << ": " << origValue;
2330           fprintf(stderr, "%s\n", out.str().c_str());
2331         }
2332       }
2333     }
2334     return false;
2335   }
2336
2337   template<typename T>
2338   inline bool GetUniformValue(GLuint programId, GLuint uniformId, T& outValue) const
2339   {
2340     const ProgramUniformValue<T>& mProgramUniforms = GetProgramUniformsForType(outValue);
2341     return mProgramUniforms.GetUniformValue(programId, uniformId, outValue);
2342   }
2343
2344   inline bool GetUniformIds(const char* name, GLuint& programId, GLuint& uniformId) const
2345   {
2346     for(ProgramUniformMap::const_iterator program_it = mUniforms.begin();
2347         program_it != mUniforms.end();
2348         ++program_it)
2349     {
2350       const UniformIDMap& uniformIDs = program_it->second;
2351
2352       UniformIDMap::const_iterator uniform_it = uniformIDs.find(name);
2353       if(uniform_it != uniformIDs.end())
2354       {
2355         programId = program_it->first;
2356         uniformId = uniform_it->second;
2357         return true;
2358       }
2359     }
2360     return false;
2361   }
2362
2363   inline void SetCustomUniforms(std::vector<UniformData>& customUniformData)
2364   {
2365     mCustomUniformData = customUniformData;
2366   }
2367
2368   inline GLuint GetLastShaderCompiled() const
2369   {
2370     return mLastShaderCompiled;
2371   }
2372
2373   inline GLuint GetLastProgramCreated() const
2374   {
2375     return mLastProgramIdUsed;
2376   }
2377
2378   inline GLbitfield GetLastClearMask() const
2379   {
2380     return mLastClearBitMask;
2381   }
2382
2383   enum AttribType
2384   {
2385     ATTRIB_UNKNOWN = -1,
2386     ATTRIB_POSITION,
2387     ATTRIB_NORMAL,
2388     ATTRIB_TEXCOORD,
2389     ATTRIB_COLOR,
2390     ATTRIB_BONE_WEIGHTS,
2391     ATTRIB_BONE_INDICES,
2392     ATTRIB_TYPE_LAST
2393   };
2394
2395   struct ScissorParams
2396   {
2397     GLint   x;
2398     GLint   y;
2399     GLsizei width;
2400     GLsizei height;
2401
2402     ScissorParams()
2403     : x(0),
2404       y(0),
2405       width(0),
2406       height(0)
2407     {
2408     }
2409   };
2410
2411   // Methods to check scissor tests
2412   inline const ScissorParams& GetScissorParams() const
2413   {
2414     return mScissorParams;
2415   }
2416
2417   struct ColorMaskParams
2418   {
2419     GLboolean red;
2420     GLboolean green;
2421     GLboolean blue;
2422     GLboolean alpha;
2423
2424     ColorMaskParams()
2425     : red(true),
2426       green(true),
2427       blue(true),
2428       alpha(true)
2429     {
2430     }
2431   };
2432
2433   inline bool GetProgramBinaryCalled() const
2434   {
2435     return mGetProgramBinaryCalled;
2436   }
2437
2438   inline unsigned int GetClearCountCalled() const
2439   {
2440     return mClearCount;
2441   }
2442
2443   inline const ColorMaskParams& GetColorMaskParams() const
2444   {
2445     return mColorMaskParams;
2446   }
2447
2448   typedef std::vector<size_t>   BufferDataCalls;
2449   inline const BufferDataCalls& GetBufferDataCalls() const
2450   {
2451     return mBufferDataCalls;
2452   }
2453   inline void ResetBufferDataCalls()
2454   {
2455     mBufferDataCalls.clear();
2456   }
2457
2458   typedef std::vector<size_t>      BufferSubDataCalls;
2459   inline const BufferSubDataCalls& GetBufferSubDataCalls() const
2460   {
2461     return mBufferSubDataCalls;
2462   }
2463   inline void ResetBufferSubDataCalls()
2464   {
2465     mBufferSubDataCalls.clear();
2466   }
2467
2468 private:
2469   GLuint                                mCurrentProgram;
2470   GLuint                                mCompileStatus;
2471   BufferDataCalls                       mBufferDataCalls;
2472   BufferSubDataCalls                    mBufferSubDataCalls;
2473   GLvoid*                               mMappedBuffer{nullptr};
2474   GLuint                                mLinkStatus;
2475   GLint                                 mNumberOfActiveUniforms;
2476   GLenum                                mGetErrorResult;
2477   GLubyte*                              mGetStringResult;
2478   GLboolean                             mIsBufferResult;
2479   GLboolean                             mIsEnabledResult;
2480   GLboolean                             mIsFramebufferResult;
2481   GLboolean                             mIsProgramResult;
2482   GLboolean                             mIsRenderbufferResult;
2483   GLboolean                             mIsShaderResult;
2484   GLboolean                             mIsTextureResult;
2485   GLenum                                mActiveTextureUnit;
2486   GLenum                                mCheckFramebufferStatusResult;
2487   GLint                                 mFramebufferStatus;
2488   GLenum                                mFramebufferDepthAttached;
2489   GLenum                                mFramebufferStencilAttached;
2490   GLuint                                mFramebufferColorAttachmentCount;
2491   GLuint                                mFrameBufferColorStatus;
2492   GLint                                 mNumBinaryFormats;
2493   GLint                                 mBinaryFormats;
2494   GLint                                 mProgramBinaryLength;
2495   bool                                  mVertexAttribArrayState[MAX_ATTRIBUTE_CACHE_SIZE];
2496   bool                                  mVertexAttribArrayChanged; // whether the vertex attrib array has been changed
2497   bool                                  mGetProgramBinaryCalled;
2498   typedef std::map<GLuint, std::string> ShaderSourceMap;
2499   ShaderSourceMap                       mShaderSources;
2500   std::vector<std::string>              mAttribLocs; // should be bound to shader
2501   GLuint                                mLastShaderCompiled;
2502   GLbitfield                            mLastClearBitMask;
2503   Vector4                               mLastClearColor;
2504   unsigned int                          mClearCount;
2505
2506   Vector4 mLastBlendColor;
2507   GLenum  mLastBlendEquationRgb;
2508   GLenum  mLastBlendEquationAlpha;
2509   GLenum  mLastBlendFuncSrcRgb;
2510   GLenum  mLastBlendFuncDstRgb;
2511   GLenum  mLastBlendFuncSrcAlpha;
2512   GLenum  mLastBlendFuncDstAlpha;
2513
2514   GLboolean mLastDepthMask;
2515
2516   // Data for manipulating the IDs returned by GenTextures
2517   GLuint              mLastAutoTextureIdUsed;
2518   GLuint              mNumGeneratedTextures;
2519   std::vector<GLuint> mNextTextureIds;
2520   std::vector<GLuint> mDeletedTextureIds;
2521   std::vector<GLuint> mBoundTextures;
2522
2523   struct ActiveTextureType
2524   {
2525     std::vector<GLuint> mBoundTextures;
2526   };
2527
2528   ActiveTextureType mActiveTextures[MIN_TEXTURE_UNIT_LIMIT];
2529
2530   TraceCallStack mBufferTrace;
2531   TraceCallStack mCullFaceTrace;
2532   TraceCallStack mEnableDisableTrace;
2533   TraceCallStack mShaderTrace;
2534   TraceCallStack mTextureTrace;
2535   TraceCallStack mTexParameterTrace;
2536   TraceCallStack mDrawTrace;
2537   TraceCallStack mDepthFunctionTrace;
2538   TraceCallStack mStencilFunctionTrace;
2539   TraceCallStack mScissorTrace;
2540   TraceCallStack mSetUniformTrace;
2541   TraceCallStack mViewportTrace;
2542
2543   // Shaders & Uniforms
2544   GLuint                                 mLastShaderIdUsed;
2545   GLuint                                 mLastProgramIdUsed{0u};
2546   GLuint                                 mLastUniformIdUsed;
2547   typedef std::map<std::string, GLint>   UniformIDMap;
2548   typedef std::map<GLuint, UniformIDMap> ProgramUniformMap;
2549   ProgramUniformMap                      mUniforms;
2550
2551   std::vector<UniformData> mCustomUniformData{};
2552
2553   template<typename T>
2554   struct ProgramUniformValue : public std::map<GLuint, std::map<GLint, T> >
2555   {
2556   public:
2557     typedef std::map<GLint, T>                UniformValueMap;
2558     typedef std::map<GLuint, UniformValueMap> Map;
2559
2560     bool SetUniformValue(GLuint program, GLuint uniform, const T& value)
2561     {
2562       if(program == 0)
2563       {
2564         return false;
2565       }
2566
2567       typename Map::iterator it = Map::find(program);
2568       if(it == Map::end())
2569       {
2570         // if its the first uniform for this program add it
2571         std::pair<typename Map::iterator, bool> result =
2572           Map::insert(typename Map::value_type(program, UniformValueMap()));
2573         it = result.first;
2574       }
2575
2576       UniformValueMap& uniforms = it->second;
2577       uniforms[uniform]         = value;
2578
2579       return true;
2580     }
2581
2582     bool CheckUniformValue(GLuint program, GLuint uniform, const T& value) const
2583     {
2584       T uniformValue;
2585       if(GetUniformValue(program, uniform, uniformValue))
2586       {
2587         return CompareType<T>(value, uniformValue, Math::MACHINE_EPSILON_10);
2588       }
2589
2590       return false;
2591     }
2592
2593     bool GetUniformValue(GLuint program, GLuint uniform, T& value) const
2594     {
2595       if(program == 0)
2596       {
2597         return false;
2598       }
2599
2600       typename Map::const_iterator it = Map::find(program);
2601       if(it == Map::end())
2602       {
2603         // Uniform values always initialised as 0
2604         value = GetZero();
2605         return true;
2606       }
2607
2608       const UniformValueMap&                   uniforms = it->second;
2609       typename UniformValueMap::const_iterator it2      = uniforms.find(uniform);
2610       if(it2 == uniforms.end())
2611       {
2612         // Uniform values always initialised as 0
2613         value = GetZero();
2614         return true;
2615       }
2616       value = it2->second;
2617
2618       return true;
2619     }
2620
2621     T GetZero() const;
2622   };
2623   ProgramUniformValue<int>     mProgramUniforms1i;
2624   ProgramUniformValue<float>   mProgramUniforms1f;
2625   ProgramUniformValue<Vector2> mProgramUniforms2f;
2626   ProgramUniformValue<Vector3> mProgramUniforms3f;
2627   ProgramUniformValue<Vector4> mProgramUniforms4f;
2628   ProgramUniformValue<Matrix>  mProgramUniformsMat4;
2629   ProgramUniformValue<Matrix3> mProgramUniformsMat3;
2630
2631   inline const ProgramUniformValue<int>& GetProgramUniformsForType(const int) const
2632   {
2633     return mProgramUniforms1i;
2634   }
2635   inline const ProgramUniformValue<float>& GetProgramUniformsForType(const float) const
2636   {
2637     return mProgramUniforms1f;
2638   }
2639   inline const ProgramUniformValue<Vector2>& GetProgramUniformsForType(const Vector2&) const
2640   {
2641     return mProgramUniforms2f;
2642   }
2643   inline const ProgramUniformValue<Vector3>& GetProgramUniformsForType(const Vector3&) const
2644   {
2645     return mProgramUniforms3f;
2646   }
2647   inline const ProgramUniformValue<Vector4>& GetProgramUniformsForType(const Vector4&) const
2648   {
2649     return mProgramUniforms4f;
2650   }
2651   inline const ProgramUniformValue<Matrix>& GetProgramUniformsForType(const Matrix&) const
2652   {
2653     return mProgramUniformsMat4;
2654   }
2655   inline const ProgramUniformValue<Matrix3>& GetProgramUniformsForType(const Matrix3&) const
2656   {
2657     return mProgramUniformsMat3;
2658   }
2659   inline void SetVertexAttribArray(GLuint index, bool state)
2660   {
2661     if(index >= MAX_ATTRIBUTE_CACHE_SIZE)
2662     {
2663       // out of range
2664       return;
2665     }
2666     mVertexAttribArrayState[index] = state;
2667     mVertexAttribArrayChanged      = true;
2668   }
2669
2670   ScissorParams   mScissorParams;
2671   ColorMaskParams mColorMaskParams;
2672 };
2673
2674 template<>
2675 inline int TestGlAbstraction::ProgramUniformValue<int>::GetZero() const
2676 {
2677   return 0;
2678 }
2679
2680 template<>
2681 inline float TestGlAbstraction::ProgramUniformValue<float>::GetZero() const
2682 {
2683   return 0.0f;
2684 }
2685
2686 template<>
2687 inline Vector2 TestGlAbstraction::ProgramUniformValue<Vector2>::GetZero() const
2688 {
2689   return Vector2::ZERO;
2690 }
2691
2692 template<>
2693 inline Vector3 TestGlAbstraction::ProgramUniformValue<Vector3>::GetZero() const
2694 {
2695   return Vector3::ZERO;
2696 }
2697
2698 template<>
2699 inline Vector4 TestGlAbstraction::ProgramUniformValue<Vector4>::GetZero() const
2700 {
2701   return Vector4::ZERO;
2702 }
2703
2704 template<>
2705 inline Matrix TestGlAbstraction::ProgramUniformValue<Matrix>::GetZero() const
2706 {
2707   return Matrix();
2708 }
2709
2710 template<>
2711 inline Matrix3 TestGlAbstraction::ProgramUniformValue<Matrix3>::GetZero() const
2712 {
2713   return Matrix3(Matrix());
2714 }
2715
2716 } // namespace Dali
2717
2718 bool BlendEnabled(const Dali::TraceCallStack& callStack);
2719 bool BlendDisabled(const Dali::TraceCallStack& callStack);
2720
2721 #endif // TEST_GL_ABSTRACTION_H