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