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