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