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