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