Merge "Apply font size scale to markup text" into devel/master
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit / dali-toolkit-test-utils / test-graphics-controller.cpp
1 /*
2  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "test-graphics-controller.h"
18
19 #include "test-graphics-buffer.h"
20 #include "test-graphics-command-buffer.h"
21 #include "test-graphics-framebuffer.h"
22 #include "test-graphics-reflection.h"
23 #include "test-graphics-render-pass.h"
24 #include "test-graphics-render-target.h"
25 #include "test-graphics-sampler.h"
26 #include "test-graphics-shader.h"
27 #include "test-graphics-sync-object.h"
28 #include "test-graphics-texture.h"
29
30 #include <dali/integration-api/gl-defines.h>
31 #include <cstdio>
32 #include <iostream>
33 #include <sstream>
34
35 #include <any>
36
37 namespace Dali
38 {
39 std::ostream& operator<<(std::ostream& o, const Graphics::BufferCreateInfo& bufferCreateInfo)
40 {
41   return o << "usage:" << std::hex << bufferCreateInfo.usage << ", size:" << std::dec << bufferCreateInfo.size;
42 }
43
44 std::ostream& operator<<(std::ostream& o, const Graphics::CommandBufferCreateInfo& commandBufferCreateInfo)
45 {
46   return o << "level:" << (commandBufferCreateInfo.level == Graphics::CommandBufferLevel::PRIMARY ? "PRIMARY" : "SECONDARY")
47            << ", fixedCapacity:" << std::dec << commandBufferCreateInfo.fixedCapacity;
48 }
49
50 std::ostream& operator<<(std::ostream& o, const Graphics::TextureType& textureType)
51 {
52   switch(textureType)
53   {
54     case Graphics::TextureType::TEXTURE_2D:
55       o << "TEXTURE_2D";
56       break;
57     case Graphics::TextureType::TEXTURE_3D:
58       o << "TEXTURE_3D";
59       break;
60     case Graphics::TextureType::TEXTURE_CUBEMAP:
61       o << "TEXTURE_CUBEMAP";
62       break;
63   }
64   return o;
65 }
66
67 std::ostream& operator<<(std::ostream& o, const Graphics::Extent2D extent)
68 {
69   o << "width:" << extent.width << ", height:" << extent.height;
70   return o;
71 }
72
73 std::ostream& operator<<(std::ostream& o, const Graphics::TextureCreateInfo& createInfo)
74 {
75   o << "textureType:" << createInfo.textureType
76     << " size:" << createInfo.size
77     << " format:" << static_cast<uint32_t>(createInfo.format)
78     << " mipMapFlag:" << createInfo.mipMapFlag
79     << " layout:" << (createInfo.layout == Graphics::TextureLayout::LINEAR ? "LINEAR" : "OPTIMAL")
80     << " usageFlags:" << std::hex << createInfo.usageFlags
81     << " data:" << std::hex << createInfo.data
82     << " dataSize:" << std::dec << createInfo.dataSize
83     << " nativeImagePtr:" << std::hex << createInfo.nativeImagePtr.Get();
84   return o;
85 }
86
87 std::ostream& operator<<(std::ostream& o, Graphics::SamplerAddressMode addressMode)
88 {
89   switch(addressMode)
90   {
91     case Graphics::SamplerAddressMode::REPEAT:
92       o << "REPEAT";
93       break;
94     case Graphics::SamplerAddressMode::MIRRORED_REPEAT:
95       o << "MIRRORED_REPEAT";
96       break;
97     case Graphics::SamplerAddressMode::CLAMP_TO_EDGE:
98       o << "CLAMP_TO_EDGE";
99       break;
100     case Graphics::SamplerAddressMode::CLAMP_TO_BORDER:
101       o << "CLAMP_TO_BORDER";
102       break;
103     case Graphics::SamplerAddressMode::MIRROR_CLAMP_TO_EDGE:
104       o << "MIRROR_CLAMP_TO_EDGE";
105       break;
106   }
107   return o;
108 }
109
110 std::ostream& operator<<(std::ostream& o, Graphics::SamplerFilter filterMode)
111 {
112   switch(filterMode)
113   {
114     case Graphics::SamplerFilter::LINEAR:
115       o << "LINEAR";
116       break;
117     case Graphics::SamplerFilter::NEAREST:
118       o << "NEAREST";
119       break;
120   }
121   return o;
122 }
123
124 std::ostream& operator<<(std::ostream& o, Graphics::SamplerMipmapMode mipmapMode)
125 {
126   switch(mipmapMode)
127   {
128     case Graphics::SamplerMipmapMode::NONE:
129       o << "NONE";
130       break;
131     case Graphics::SamplerMipmapMode::LINEAR:
132       o << "LINEAR";
133       break;
134     case Graphics::SamplerMipmapMode::NEAREST:
135       o << "NEAREST";
136       break;
137   }
138   return o;
139 }
140
141 std::ostream& operator<<(std::ostream& o, const Graphics::SamplerCreateInfo& createInfo)
142 {
143   o << "minFilter:" << createInfo.minFilter
144     << " magFilter:" << createInfo.magFilter
145     << " wrapModeU:" << createInfo.addressModeU
146     << " wrapModeV:" << createInfo.addressModeV
147     << " wrapModeW:" << createInfo.addressModeW
148     << " mipMapMode:" << createInfo.mipMapMode;
149   return o;
150 }
151
152 std::ostream& operator<<(std::ostream& o, const Graphics::ColorAttachment& colorAttachment)
153 {
154   o << "attachmentId:" << colorAttachment.attachmentId
155     << " layerId:" << colorAttachment.layerId
156     << " levelId:" << colorAttachment.levelId
157     << " texture:" << colorAttachment.texture;
158   return o;
159 }
160
161 std::ostream& operator<<(std::ostream& o, const Graphics::DepthStencilAttachment& depthStencilAttachment)
162 {
163   o << "depthTexture:" << depthStencilAttachment.depthTexture
164     << "depthLevel:" << depthStencilAttachment.depthLevel
165     << "stencilTexture:" << depthStencilAttachment.stencilTexture
166     << "stencilLevel:" << depthStencilAttachment.stencilLevel;
167   return o;
168 }
169
170 std::ostream& operator<<(std::ostream& o, const Graphics::FramebufferCreateInfo& createInfo)
171 {
172   o << "colorAttachments:";
173   for(auto i = 0u; i < createInfo.colorAttachments.size(); ++i)
174   {
175     o << "[" << i << "]=" << createInfo.colorAttachments[i] << "  ";
176   }
177   o << "depthStencilAttachment:" << createInfo.depthStencilAttachment;
178   o << "size: " << createInfo.size;
179   return o;
180 }
181
182 int GetNumComponents(Graphics::VertexInputFormat vertexFormat)
183 {
184   switch(vertexFormat)
185   {
186     case Graphics::VertexInputFormat::UNDEFINED:
187     case Graphics::VertexInputFormat::FLOAT:
188     case Graphics::VertexInputFormat::INTEGER:
189       return 1;
190     case Graphics::VertexInputFormat::IVECTOR2:
191     case Graphics::VertexInputFormat::FVECTOR2:
192       return 2;
193     case Graphics::VertexInputFormat::IVECTOR3:
194     case Graphics::VertexInputFormat::FVECTOR3:
195       return 3;
196     case Graphics::VertexInputFormat::FVECTOR4:
197     case Graphics::VertexInputFormat::IVECTOR4:
198       return 4;
199   }
200   return 1;
201 }
202
203 GLint GetSize(Graphics::VertexInputFormat vertexFormat)
204 {
205   switch(vertexFormat)
206   {
207     case Graphics::VertexInputFormat::UNDEFINED:
208       return 1u;
209     case Graphics::VertexInputFormat::INTEGER:
210     case Graphics::VertexInputFormat::IVECTOR2:
211     case Graphics::VertexInputFormat::IVECTOR3:
212     case Graphics::VertexInputFormat::IVECTOR4:
213       return 2u;
214     case Graphics::VertexInputFormat::FLOAT:
215     case Graphics::VertexInputFormat::FVECTOR2:
216     case Graphics::VertexInputFormat::FVECTOR3:
217     case Graphics::VertexInputFormat::FVECTOR4:
218       return 4u;
219   }
220   return 1u;
221 }
222
223 GLint GetGlType(Graphics::VertexInputFormat vertexFormat)
224 {
225   switch(vertexFormat)
226   {
227     case Graphics::VertexInputFormat::UNDEFINED:
228       return GL_BYTE;
229     case Graphics::VertexInputFormat::INTEGER:
230     case Graphics::VertexInputFormat::IVECTOR2:
231     case Graphics::VertexInputFormat::IVECTOR3:
232     case Graphics::VertexInputFormat::IVECTOR4:
233       return GL_SHORT;
234     case Graphics::VertexInputFormat::FLOAT:
235     case Graphics::VertexInputFormat::FVECTOR2:
236     case Graphics::VertexInputFormat::FVECTOR3:
237     case Graphics::VertexInputFormat::FVECTOR4:
238       return GL_FLOAT;
239   }
240   return GL_BYTE;
241 }
242
243 GLenum GetTopology(Graphics::PrimitiveTopology topology)
244 {
245   switch(topology)
246   {
247     case Graphics::PrimitiveTopology::POINT_LIST:
248       return GL_POINTS;
249
250     case Graphics::PrimitiveTopology::LINE_LIST:
251       return GL_LINES;
252
253     case Graphics::PrimitiveTopology::LINE_LOOP:
254       return GL_LINE_LOOP;
255
256     case Graphics::PrimitiveTopology::LINE_STRIP:
257       return GL_LINE_STRIP;
258
259     case Graphics::PrimitiveTopology::TRIANGLE_LIST:
260       return GL_TRIANGLES;
261
262     case Graphics::PrimitiveTopology::TRIANGLE_STRIP:
263       return GL_TRIANGLE_STRIP;
264
265     case Graphics::PrimitiveTopology::TRIANGLE_FAN:
266       return GL_TRIANGLE_FAN;
267   }
268   return GL_TRIANGLES;
269 }
270
271 GLenum GetCullFace(Graphics::CullMode cullMode)
272 {
273   switch(cullMode)
274   {
275     case Graphics::CullMode::NONE:
276       return GL_NONE;
277     case Graphics::CullMode::FRONT:
278       return GL_FRONT;
279     case Graphics::CullMode::BACK:
280       return GL_BACK;
281     case Graphics::CullMode::FRONT_AND_BACK:
282       return GL_FRONT_AND_BACK;
283   }
284   return GL_NONE;
285 }
286
287 GLenum GetFrontFace(Graphics::FrontFace frontFace)
288 {
289   if(frontFace == Graphics::FrontFace::CLOCKWISE)
290   {
291     return GL_CW;
292   }
293   return GL_CCW;
294 }
295
296 GLenum GetBlendFactor(Graphics::BlendFactor blendFactor)
297 {
298   GLenum glFactor = GL_ZERO;
299
300   switch(blendFactor)
301   {
302     case Graphics::BlendFactor::ZERO:
303       glFactor = GL_ZERO;
304       break;
305     case Graphics::BlendFactor::ONE:
306       glFactor = GL_ONE;
307       break;
308     case Graphics::BlendFactor::SRC_COLOR:
309       glFactor = GL_SRC_COLOR;
310       break;
311     case Graphics::BlendFactor::ONE_MINUS_SRC_COLOR:
312       glFactor = GL_ONE_MINUS_SRC_COLOR;
313       break;
314     case Graphics::BlendFactor::DST_COLOR:
315       glFactor = GL_DST_COLOR;
316       break;
317     case Graphics::BlendFactor::ONE_MINUS_DST_COLOR:
318       glFactor = GL_ONE_MINUS_DST_COLOR;
319       break;
320     case Graphics::BlendFactor::SRC_ALPHA:
321       glFactor = GL_SRC_ALPHA;
322       break;
323     case Graphics::BlendFactor::ONE_MINUS_SRC_ALPHA:
324       glFactor = GL_ONE_MINUS_SRC_ALPHA;
325       break;
326     case Graphics::BlendFactor::DST_ALPHA:
327       glFactor = GL_DST_ALPHA;
328       break;
329     case Graphics::BlendFactor::ONE_MINUS_DST_ALPHA:
330       glFactor = GL_ONE_MINUS_DST_ALPHA;
331       break;
332     case Graphics::BlendFactor::CONSTANT_COLOR:
333       glFactor = GL_CONSTANT_COLOR;
334       break;
335     case Graphics::BlendFactor::ONE_MINUS_CONSTANT_COLOR:
336       glFactor = GL_ONE_MINUS_CONSTANT_COLOR;
337       break;
338     case Graphics::BlendFactor::CONSTANT_ALPHA:
339       glFactor = GL_CONSTANT_ALPHA;
340       break;
341     case Graphics::BlendFactor::ONE_MINUS_CONSTANT_ALPHA:
342       glFactor = GL_ONE_MINUS_CONSTANT_ALPHA;
343       break;
344     case Graphics::BlendFactor::SRC_ALPHA_SATURATE:
345       glFactor = GL_SRC_ALPHA_SATURATE;
346       break;
347       // GLES doesn't appear to have dual source blending.
348     case Graphics::BlendFactor::SRC1_COLOR:
349       glFactor = GL_SRC_COLOR;
350       break;
351     case Graphics::BlendFactor::ONE_MINUS_SRC1_COLOR:
352       glFactor = GL_ONE_MINUS_SRC_COLOR;
353       break;
354     case Graphics::BlendFactor::SRC1_ALPHA:
355       glFactor = GL_SRC_ALPHA;
356       break;
357     case Graphics::BlendFactor::ONE_MINUS_SRC1_ALPHA:
358       glFactor = GL_ONE_MINUS_SRC_ALPHA;
359       break;
360   }
361   return glFactor;
362 }
363
364 GLenum GetBlendOp(Graphics::BlendOp blendOp)
365 {
366   GLenum op = GL_FUNC_ADD;
367   switch(blendOp)
368   {
369     case Graphics::BlendOp::ADD:
370       op = GL_FUNC_ADD;
371       break;
372     case Graphics::BlendOp::SUBTRACT:
373       op = GL_FUNC_SUBTRACT;
374       break;
375     case Graphics::BlendOp::REVERSE_SUBTRACT:
376       op = GL_FUNC_REVERSE_SUBTRACT;
377       break;
378     case Graphics::BlendOp::MIN:
379       op = GL_MIN;
380       break;
381     case Graphics::BlendOp::MAX:
382       op = GL_MAX;
383       break;
384     case Graphics::BlendOp::MULTIPLY:
385     {
386       op = GL_MULTIPLY;
387       break;
388     }
389     case Graphics::BlendOp::SCREEN:
390     {
391       op = GL_SCREEN;
392       break;
393     }
394     case Graphics::BlendOp::OVERLAY:
395     {
396       op = GL_OVERLAY;
397       break;
398     }
399     case Graphics::BlendOp::DARKEN:
400     {
401       op = GL_DARKEN;
402       break;
403     }
404     case Graphics::BlendOp::LIGHTEN:
405     {
406       op = GL_LIGHTEN;
407       break;
408     }
409     case Graphics::BlendOp::COLOR_DODGE:
410     {
411       op = GL_COLORDODGE;
412       break;
413     }
414     case Graphics::BlendOp::COLOR_BURN:
415     {
416       op = GL_COLORBURN;
417       break;
418     }
419     case Graphics::BlendOp::HARD_LIGHT:
420     {
421       op = GL_HARDLIGHT;
422       break;
423     }
424     case Graphics::BlendOp::SOFT_LIGHT:
425     {
426       op = GL_SOFTLIGHT;
427       break;
428     }
429     case Graphics::BlendOp::DIFFERENCE:
430     {
431       op = GL_DIFFERENCE;
432       break;
433     }
434     case Graphics::BlendOp::EXCLUSION:
435     {
436       op = GL_EXCLUSION;
437       break;
438     }
439     case Graphics::BlendOp::HUE:
440     {
441       op = GL_HSL_HUE;
442       break;
443     }
444     case Graphics::BlendOp::SATURATION:
445     {
446       op = GL_HSL_SATURATION;
447       break;
448     }
449     case Graphics::BlendOp::COLOR:
450     {
451       op = GL_HSL_COLOR;
452       break;
453     }
454     case Graphics::BlendOp::LUMINOSITY:
455     {
456       op = GL_HSL_LUMINOSITY;
457       break;
458     }
459   }
460   return op;
461 }
462
463 struct GLCompareOp
464 {
465   constexpr explicit GLCompareOp(Graphics::CompareOp compareOp)
466   {
467     switch(compareOp)
468     {
469       case Graphics::CompareOp::NEVER:
470         op = GL_NEVER;
471         break;
472       case Graphics::CompareOp::LESS:
473         op = GL_LESS;
474         break;
475       case Graphics::CompareOp::EQUAL:
476         op = GL_EQUAL;
477         break;
478       case Graphics::CompareOp::LESS_OR_EQUAL:
479         op = GL_LEQUAL;
480         break;
481       case Graphics::CompareOp::GREATER:
482         op = GL_GREATER;
483         break;
484       case Graphics::CompareOp::NOT_EQUAL:
485         op = GL_NOTEQUAL;
486         break;
487       case Graphics::CompareOp::GREATER_OR_EQUAL:
488         op = GL_GEQUAL;
489         break;
490       case Graphics::CompareOp::ALWAYS:
491         op = GL_ALWAYS;
492         break;
493     }
494   }
495   GLenum op{GL_LESS};
496 };
497
498 struct GLStencilOp
499 {
500   constexpr explicit GLStencilOp(Graphics::StencilOp stencilOp)
501   {
502     switch(stencilOp)
503     {
504       case Graphics::StencilOp::KEEP:
505         op = GL_KEEP;
506         break;
507       case Graphics::StencilOp::ZERO:
508         op = GL_ZERO;
509         break;
510       case Graphics::StencilOp::REPLACE:
511         op = GL_REPLACE;
512         break;
513       case Graphics::StencilOp::INCREMENT_AND_CLAMP:
514         op = GL_INCR;
515         break;
516       case Graphics::StencilOp::DECREMENT_AND_CLAMP:
517         op = GL_DECR;
518         break;
519       case Graphics::StencilOp::INVERT:
520         op = GL_INVERT;
521         break;
522       case Graphics::StencilOp::INCREMENT_AND_WRAP:
523         op = GL_INCR_WRAP;
524         break;
525       case Graphics::StencilOp::DECREMENT_AND_WRAP:
526         op = GL_DECR_WRAP;
527         break;
528     }
529   }
530   GLenum op{GL_KEEP};
531 };
532
533 class TestGraphicsMemory : public Graphics::Memory
534 {
535 public:
536   TestGraphicsMemory(TraceCallStack& callStack, TestGraphicsBuffer& buffer, uint32_t mappedOffset, uint32_t mappedSize)
537   : mCallStack(callStack),
538     mBuffer(buffer),
539     mMappedOffset(mappedOffset),
540     mMappedSize(mappedSize),
541     mLockedOffset(0u),
542     mLockedSize(0u)
543   {
544   }
545
546   void* LockRegion(uint32_t offset, uint32_t size) override
547   {
548     std::ostringstream o;
549     o << offset << ", " << size;
550     mCallStack.PushCall("Memory::LockRegion", o.str());
551
552     if(offset > mMappedOffset + mMappedSize ||
553        size + offset > mMappedOffset + mMappedSize)
554     {
555       fprintf(stderr, "TestGraphics.Memory::LockRegion() Out of bounds");
556       mBuffer.memory.resize(mMappedOffset + offset + size); // Grow to prevent memcpy from crashing
557     }
558     mLockedOffset = offset;
559     mLockedSize   = size;
560     return &mBuffer.memory[mMappedOffset + offset];
561   }
562
563   void Unlock(bool flush) override
564   {
565     mCallStack.PushCall("Memory::Unlock", (flush ? "Flush" : "NoFlush"));
566     if(flush)
567     {
568       Flush();
569     }
570   }
571
572   void Flush() override
573   {
574     mCallStack.PushCall("Memory::Flush", "");
575     mBuffer.Bind();
576     mBuffer.Upload(mMappedOffset + mLockedOffset, mLockedSize);
577     mBuffer.Unbind();
578   }
579
580   TraceCallStack&     mCallStack;
581   TestGraphicsBuffer& mBuffer;
582   uint32_t            mMappedOffset;
583   uint32_t            mMappedSize;
584   uint32_t            mLockedOffset;
585   uint32_t            mLockedSize;
586 };
587
588 TestGraphicsController::TestGraphicsController()
589 : mCallStack(false, "TestGraphicsController."),
590   mCommandBufferCallStack(false, "TestCommandBuffer."),
591   mFrameBufferCallStack(false, "TestFrameBuffer.")
592 {
593   mCallStack.Enable(true);
594   mCommandBufferCallStack.Enable(true);
595   auto& trace = mGl.GetTextureTrace();
596   trace.Enable(true);
597   trace.EnableLogging(false);
598 }
599
600 void TestGraphicsController::SubmitCommandBuffers(const Graphics::SubmitInfo& submitInfo)
601 {
602   TraceCallStack::NamedParams namedParams;
603   namedParams["submitInfo"] << "cmdBuffer[" << submitInfo.cmdBuffer.size()
604                             << "], flags:" << std::hex << submitInfo.flags;
605
606   mCallStack.PushCall("SubmitCommandBuffers", "", namedParams);
607
608   mSubmitStack.emplace_back(submitInfo);
609
610   for(auto& graphicsCommandBuffer : submitInfo.cmdBuffer)
611   {
612     auto commandBuffer = Uncast<TestGraphicsCommandBuffer>(graphicsCommandBuffer);
613     ProcessCommandBuffer(*commandBuffer);
614   }
615 }
616
617 void TestGraphicsController::ProcessCommandBuffer(TestGraphicsCommandBuffer& commandBuffer)
618 {
619   bool                     scissorEnabled = false;
620   TestGraphicsFramebuffer* currentFramebuffer{nullptr};
621   TestGraphicsPipeline*    currentPipeline{nullptr};
622
623   for(auto& cmd : commandBuffer.GetCommands())
624   {
625     // process command
626     switch(cmd.type)
627     {
628       case CommandType::FLUSH:
629       {
630         // Nothing to do here
631         break;
632       }
633       case CommandType::BIND_TEXTURES:
634       {
635         for(auto& binding : cmd.data.bindTextures.textureBindings)
636         {
637           if(binding.texture)
638           {
639             auto texture = Uncast<TestGraphicsTexture>(binding.texture);
640             texture->Bind(binding.binding);
641
642             if(binding.sampler)
643             {
644               auto sampler = Uncast<TestGraphicsSampler>(binding.sampler);
645               if(sampler)
646               {
647                 sampler->Apply(texture->GetTarget());
648               }
649             }
650
651             texture->Prepare(); // Ensure native texture is ready
652           }
653         }
654         break;
655       }
656       case CommandType::BIND_VERTEX_BUFFERS:
657       {
658         for(auto& binding : cmd.data.bindVertexBuffers.vertexBufferBindings)
659         {
660           auto graphicsBuffer = binding.buffer;
661           auto vertexBuffer   = Uncast<TestGraphicsBuffer>(graphicsBuffer);
662           vertexBuffer->Bind();
663         }
664         break;
665       }
666       case CommandType::BIND_INDEX_BUFFER:
667       {
668         auto& indexBufferBinding = cmd.data.bindIndexBuffer;
669         if(indexBufferBinding.buffer)
670         {
671           auto buffer = Uncast<TestGraphicsBuffer>(indexBufferBinding.buffer);
672           buffer->Bind();
673         }
674         break;
675       }
676       case CommandType::BIND_UNIFORM_BUFFER:
677       {
678         if(currentPipeline)
679         {
680           auto& bindings = cmd.data.bindUniformBuffers;
681           auto  buffer   = bindings.standaloneUniformsBufferBinding;
682
683           // based on reflection, issue gl calls
684           buffer.buffer->BindAsUniformBuffer(static_cast<const TestGraphicsProgram*>(currentPipeline->programState.program), bindings.standaloneUniformsBufferBinding);
685         }
686         break;
687       }
688       case CommandType::BIND_SAMPLERS:
689       {
690         break;
691       }
692       case CommandType::BIND_PIPELINE:
693       {
694         currentPipeline = Uncast<TestGraphicsPipeline>(cmd.data.bindPipeline.pipeline);
695         BindPipeline(currentPipeline);
696         break;
697       }
698       case CommandType::DRAW_NATIVE:
699       {
700         auto info = &cmd.data.draw.drawNative.drawNativeInfo;
701
702         if(info->glesNativeInfo.eglSharedContextStoragePointer)
703         {
704           auto* anyContext = reinterpret_cast<std::any*>(info->glesNativeInfo.eglSharedContextStoragePointer);
705           *anyContext      = reinterpret_cast<void*>(0x12345678u);
706         }
707
708         CallbackBase::ExecuteReturn<bool>(*info->callback, info->userData);
709         break;
710       }
711       case CommandType::DRAW:
712       {
713         if(currentPipeline)
714         {
715           if(cmd.data.draw.draw.instanceCount == 0)
716           {
717             mGl.DrawArrays(GetTopology(currentPipeline->inputAssemblyState.topology),
718                            cmd.data.draw.draw.firstVertex,
719                            cmd.data.draw.draw.vertexCount);
720           }
721           else
722           {
723             mGl.DrawArraysInstanced(GetTopology(currentPipeline->inputAssemblyState.topology),
724                                     cmd.data.draw.draw.firstVertex,
725                                     cmd.data.draw.draw.vertexCount,
726                                     cmd.data.draw.draw.instanceCount);
727           }
728         }
729         break;
730       }
731       case CommandType::DRAW_INDEXED:
732       {
733         if(currentPipeline)
734         {
735           if(cmd.data.draw.draw.instanceCount == 0)
736           {
737             mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
738                              static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
739                              GL_UNSIGNED_SHORT,
740                              reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
741           }
742           else
743           {
744             mGl.DrawElementsInstanced(GetTopology(currentPipeline->inputAssemblyState.topology),
745                                       static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
746                                       GL_UNSIGNED_SHORT,
747                                       reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex),
748                                       cmd.data.draw.drawIndexed.instanceCount);
749           }
750         }
751         break;
752       }
753       case CommandType::DRAW_INDEXED_INDIRECT:
754       {
755         if(currentPipeline)
756         {
757           mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
758                            static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
759                            GL_UNSIGNED_SHORT,
760                            reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
761         }
762         break;
763       }
764       case CommandType::SET_SCISSOR:
765       {
766         if(scissorEnabled)
767         {
768           auto& rect = cmd.data.scissor.region;
769           mGl.Scissor(rect.x, rect.y, rect.width, rect.height);
770         }
771         break;
772       }
773       case CommandType::SET_SCISSOR_TEST:
774       {
775         if(cmd.data.scissorTest.enable)
776         {
777           mGl.Enable(GL_SCISSOR_TEST);
778           scissorEnabled = true;
779         }
780         else
781         {
782           mGl.Disable(GL_SCISSOR_TEST);
783           scissorEnabled = false;
784         }
785         break;
786       }
787       case CommandType::SET_VIEWPORT_TEST:
788       {
789         break;
790       }
791       case CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
792       {
793         auto& rect = cmd.data.viewport.region;
794         mGl.Viewport(rect.x, rect.y, rect.width, rect.height);
795         break;
796       }
797
798       case CommandType::SET_COLOR_MASK:
799       {
800         // Set all channels to the same mask
801         const bool mask = cmd.data.colorMask.enabled;
802         mGl.ColorMask(mask, mask, mask, mask);
803         break;
804       }
805       case CommandType::CLEAR_STENCIL_BUFFER:
806       {
807         mGl.Clear(GL_STENCIL_BUFFER_BIT);
808         break;
809       }
810       case CommandType::CLEAR_DEPTH_BUFFER:
811       {
812         mGl.Clear(GL_DEPTH_BUFFER_BIT);
813         break;
814       }
815
816       case CommandType::SET_STENCIL_TEST_ENABLE:
817       {
818         if(cmd.data.stencilTest.enabled)
819         {
820           mGl.Enable(GL_STENCIL_TEST);
821         }
822         else
823         {
824           mGl.Disable(GL_STENCIL_TEST);
825         }
826         break;
827       }
828
829       case CommandType::SET_STENCIL_FUNC:
830       {
831         mGl.StencilFunc(GLCompareOp(cmd.data.stencilFunc.compareOp).op,
832                         cmd.data.stencilFunc.reference,
833                         cmd.data.stencilFunc.compareMask);
834         break;
835       }
836
837       case CommandType::SET_STENCIL_WRITE_MASK:
838       {
839         mGl.StencilMask(cmd.data.stencilWriteMask.mask);
840         break;
841       }
842       case CommandType::SET_STENCIL_OP:
843       {
844         mGl.StencilOp(GLStencilOp(cmd.data.stencilOp.failOp).op,
845                       GLStencilOp(cmd.data.stencilOp.depthFailOp).op,
846                       GLStencilOp(cmd.data.stencilOp.passOp).op);
847         break;
848       }
849
850       case CommandType::SET_DEPTH_COMPARE_OP:
851       {
852         mGl.DepthFunc(GLCompareOp(cmd.data.depth.compareOp).op);
853         break;
854       }
855       case CommandType::SET_DEPTH_TEST_ENABLE:
856       {
857         if(cmd.data.depth.testEnabled)
858         {
859           mGl.Enable(GL_DEPTH_TEST);
860         }
861         else
862         {
863           mGl.Disable(GL_DEPTH_TEST);
864         }
865         break;
866       }
867       case CommandType::SET_DEPTH_WRITE_ENABLE:
868       {
869         mGl.DepthMask(cmd.data.depth.writeEnabled);
870         break;
871       }
872
873       case CommandType::EXECUTE_COMMAND_BUFFERS:
874       {
875         // Process secondary command buffers
876         for(auto& buf : cmd.data.executeCommandBuffers.buffers)
877         {
878           ProcessCommandBuffer(*Uncast<TestGraphicsCommandBuffer>(buf));
879         }
880         break;
881       }
882       case CommandType::BEGIN_RENDER_PASS:
883       {
884         auto renderTarget = Uncast<TestGraphicsRenderTarget>(cmd.data.beginRenderPass.renderTarget);
885
886         if(renderTarget)
887         {
888           auto fb = renderTarget->mCreateInfo.framebuffer;
889           if(fb)
890           {
891             if(currentFramebuffer != fb)
892             {
893               currentFramebuffer = Uncast<TestGraphicsFramebuffer>(fb);
894               currentFramebuffer->Bind();
895             }
896           }
897           else
898           {
899             mGl.BindFramebuffer(GL_FRAMEBUFFER, 0);
900           }
901         }
902         else
903         {
904           mGl.BindFramebuffer(GL_FRAMEBUFFER, 0);
905         }
906
907         auto& clearValues = cmd.data.beginRenderPass.clearValues;
908         if(clearValues.size() > 0)
909         {
910           const auto renderPass = static_cast<TestGraphicsRenderPass*>(cmd.data.beginRenderPass.renderPass);
911           if(renderPass)
912           {
913             const auto& color0 = renderPass->attachments[0];
914             GLuint      mask   = 0;
915             if(color0.loadOp == Graphics::AttachmentLoadOp::CLEAR)
916             {
917               mask |= GL_COLOR_BUFFER_BIT;
918
919               // Set clear color (todo: cache it!)
920               // Something goes wrong here if Alpha mask is GL_TRUE
921               mGl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
922               mGl.ClearColor(clearValues[0].color.r,
923                              clearValues[0].color.g,
924                              clearValues[0].color.b,
925                              clearValues[0].color.a);
926             }
927
928             // check for depth stencil
929             if(renderPass->attachments.size() > 1)
930             {
931               const auto& depthStencil = renderPass->attachments.back();
932               if(depthStencil.loadOp == Graphics::AttachmentLoadOp::CLEAR)
933               {
934                 mGl.DepthMask(true);
935                 uint32_t depthClearColor = 0u;
936                 if(clearValues.size() == renderPass->attachments.size())
937                 {
938                   depthClearColor = clearValues.back().depthStencil.depth;
939                 }
940                 mGl.ClearDepthf(depthClearColor);
941                 mask |= GL_DEPTH_BUFFER_BIT;
942               }
943               if(depthStencil.stencilLoadOp == Graphics::AttachmentLoadOp::CLEAR)
944               {
945                 uint32_t stencilClearColor = 0u;
946                 if(clearValues.size() == renderPass->attachments.size())
947                 {
948                   stencilClearColor = clearValues.back().depthStencil.stencil;
949                 }
950                 mGl.ClearStencil(stencilClearColor);
951                 mGl.StencilMask(0xFF); // Clear all the bitplanes (assume 8)
952                 mask |= GL_STENCIL_BUFFER_BIT;
953               }
954             }
955
956             if(mask != 0)
957             {
958               // Test scissor area and RT size
959               const auto& area = cmd.data.beginRenderPass.renderArea;
960               if(area.x == 0 &&
961                  area.y == 0 &&
962                  renderTarget &&
963                  area.width == renderTarget->mCreateInfo.extent.width &&
964                  area.height == renderTarget->mCreateInfo.extent.height)
965               {
966                 mGl.Disable(GL_SCISSOR_TEST);
967                 mGl.Clear(mask);
968               }
969               else
970               {
971                 mGl.Enable(GL_SCISSOR_TEST);
972                 mGl.Scissor(cmd.data.beginRenderPass.renderArea.x, cmd.data.beginRenderPass.renderArea.y, cmd.data.beginRenderPass.renderArea.width, cmd.data.beginRenderPass.renderArea.height);
973                 mGl.Clear(mask);
974                 mGl.Disable(GL_SCISSOR_TEST);
975               }
976             }
977           }
978           else
979           {
980             DALI_ASSERT_DEBUG(0 && "BeginRenderPass has no render pass");
981           }
982         }
983         break;
984       }
985       case CommandType::END_RENDER_PASS:
986       {
987         if(cmd.data.endRenderPass.syncObject != nullptr)
988         {
989           auto syncObject = Uncast<TestGraphicsSyncObject>(cmd.data.endRenderPass.syncObject);
990           syncObject->InitializeResource(); // create the sync object.
991         }
992         break;
993       }
994     }
995   }
996 }
997
998 void TestGraphicsController::BindPipeline(TestGraphicsPipeline* pipeline)
999 {
1000   auto& vi = pipeline->vertexInputState;
1001   for(auto& attribute : vi.attributes)
1002   {
1003     mGl.EnableVertexAttribArray(attribute.location);
1004     uint32_t attributeOffset = attribute.offset;
1005     GLsizei  stride          = vi.bufferBindings[attribute.binding].stride;
1006
1007     auto rate = vi.bufferBindings[attribute.binding].inputRate;
1008
1009     mGl.VertexAttribPointer(attribute.location,
1010                             GetNumComponents(attribute.format),
1011                             GetGlType(attribute.format),
1012                             GL_FALSE, // Not normalized
1013                             stride,
1014                             reinterpret_cast<void*>(attributeOffset));
1015     if(rate == Graphics::VertexInputRate::PER_VERTEX)
1016     {
1017       mGl.VertexAttribDivisor(attribute.location, 0);
1018     }
1019     else if(rate == Graphics::VertexInputRate::PER_INSTANCE)
1020     {
1021       mGl.VertexAttribDivisor(attribute.location, 1);
1022     }
1023   }
1024
1025   // Cull face setup
1026   auto& rasterizationState = pipeline->rasterizationState;
1027   if(rasterizationState.cullMode == Graphics::CullMode::NONE)
1028   {
1029     mGl.Disable(GL_CULL_FACE);
1030   }
1031   else
1032   {
1033     mGl.Enable(GL_CULL_FACE);
1034     mGl.CullFace(GetCullFace(rasterizationState.cullMode));
1035   }
1036
1037   mGl.FrontFace(GetFrontFace(rasterizationState.frontFace));
1038
1039   // Blending setup
1040   auto& colorBlendState = pipeline->colorBlendState;
1041   if(colorBlendState.blendEnable)
1042   {
1043     mGl.Enable(GL_BLEND);
1044
1045     mGl.BlendFuncSeparate(GetBlendFactor(colorBlendState.srcColorBlendFactor),
1046                           GetBlendFactor(colorBlendState.dstColorBlendFactor),
1047                           GetBlendFactor(colorBlendState.srcAlphaBlendFactor),
1048                           GetBlendFactor(colorBlendState.dstAlphaBlendFactor));
1049     if(colorBlendState.colorBlendOp != colorBlendState.alphaBlendOp)
1050     {
1051       mGl.BlendEquationSeparate(GetBlendOp(colorBlendState.colorBlendOp), GetBlendOp(colorBlendState.alphaBlendOp));
1052     }
1053     else
1054     {
1055       mGl.BlendEquation(GetBlendOp(colorBlendState.colorBlendOp));
1056     }
1057     mGl.BlendColor(colorBlendState.blendConstants[0],
1058                    colorBlendState.blendConstants[1],
1059                    colorBlendState.blendConstants[2],
1060                    colorBlendState.blendConstants[3]);
1061   }
1062   else
1063   {
1064     mGl.Disable(GL_BLEND);
1065   }
1066
1067   auto* program = static_cast<const TestGraphicsProgram*>(pipeline->programState.program);
1068   mGl.UseProgram(program->mImpl->mId);
1069 }
1070
1071 /**
1072  * @brief Presents render target
1073  * @param renderTarget render target to present
1074  */
1075 void TestGraphicsController::PresentRenderTarget(Graphics::RenderTarget* renderTarget)
1076 {
1077   auto*                       rt = static_cast<const TestGraphicsRenderTarget*>(renderTarget);
1078   TraceCallStack::NamedParams namedParams;
1079   namedParams["renderTarget"] << std::hex << renderTarget;
1080   namedParams["surface"] << std::hex << rt->mCreateInfo.surface;
1081   mCallStack.PushCall("PresentRenderTarget", namedParams.str(), namedParams);
1082 }
1083
1084 /**
1085  * @brief Waits until the GPU is idle
1086  */
1087 void TestGraphicsController::WaitIdle()
1088 {
1089   mCallStack.PushCall("WaitIdle", "");
1090 }
1091
1092 /**
1093  * @brief Lifecycle pause event
1094  */
1095 void TestGraphicsController::Pause()
1096 {
1097   mCallStack.PushCall("Pause", "");
1098 }
1099
1100 /**
1101  * @brief Lifecycle resume event
1102  */
1103 void TestGraphicsController::Resume()
1104 {
1105   mCallStack.PushCall("Resume", "");
1106 }
1107
1108 void TestGraphicsController::Shutdown()
1109 {
1110   mCallStack.PushCall("Shutdown", "");
1111 }
1112
1113 void TestGraphicsController::Destroy()
1114 {
1115   mCallStack.PushCall("Destroy", "");
1116 }
1117
1118 void TestGraphicsController::UpdateTextures(const std::vector<Graphics::TextureUpdateInfo>&       updateInfoList,
1119                                             const std::vector<Graphics::TextureUpdateSourceInfo>& sourceList)
1120 {
1121   TraceCallStack::NamedParams namedParams;
1122   namedParams["updateInfoList"] << "[" << updateInfoList.size() << "]:";
1123   namedParams["sourceList"] << "[" << sourceList.size() << "]:";
1124
1125   mCallStack.PushCall("UpdateTextures", "", namedParams);
1126
1127   // Call either TexImage2D or TexSubImage2D
1128   for(unsigned int i = 0; i < updateInfoList.size(); ++i)
1129   {
1130     auto& updateInfo = updateInfoList[i];
1131     auto& source     = sourceList[i];
1132
1133     auto texture = static_cast<TestGraphicsTexture*>(updateInfo.dstTexture);
1134     texture->Bind(0); // Use first texture unit during resource update
1135     texture->Update(updateInfo, source);
1136   }
1137 }
1138
1139 void TestGraphicsController::GenerateTextureMipmaps(const Graphics::Texture& texture)
1140 {
1141   mCallStack.PushCall("GenerateTextureMipmaps", "");
1142
1143   auto gfxTexture = Uncast<TestGraphicsTexture>(&texture);
1144   mGl.BindTexture(gfxTexture->GetTarget(), 0);
1145   mGl.GenerateMipmap(gfxTexture->GetTarget());
1146 }
1147
1148 bool TestGraphicsController::EnableDepthStencilBuffer(bool enableDepth, bool enableStencil)
1149 {
1150   TraceCallStack::NamedParams namedParams;
1151   namedParams["enableDepth"] << (enableDepth ? "T" : "F");
1152   namedParams["enableStencil"] << (enableStencil ? "T" : "F");
1153   mCallStack.PushCall("EnableDepthStencilBuffer", "", namedParams);
1154   return false;
1155 }
1156
1157 void TestGraphicsController::RunGarbageCollector(size_t numberOfDiscardedRenderers)
1158 {
1159   TraceCallStack::NamedParams namedParams;
1160   namedParams["numberOfDiscardedRenderers"] << numberOfDiscardedRenderers;
1161   mCallStack.PushCall("RunGarbageCollector", "", namedParams);
1162 }
1163
1164 void TestGraphicsController::DiscardUnusedResources()
1165 {
1166   mCallStack.PushCall("DiscardUnusedResources", "");
1167 }
1168
1169 bool TestGraphicsController::IsDiscardQueueEmpty()
1170 {
1171   mCallStack.PushCall("IsDiscardQueueEmpty", "");
1172   return isDiscardQueueEmptyResult;
1173 }
1174
1175 /**
1176  * @brief Test if the graphics subsystem has resumed & should force a draw
1177  *
1178  * @return true if the graphics subsystem requires a re-draw
1179  */
1180 bool TestGraphicsController::IsDrawOnResumeRequired()
1181 {
1182   mCallStack.PushCall("IsDrawOnResumeRequired", "");
1183   return isDrawOnResumeRequiredResult;
1184 }
1185
1186 Graphics::UniquePtr<Graphics::Buffer> TestGraphicsController::CreateBuffer(const Graphics::BufferCreateInfo& createInfo, Graphics::UniquePtr<Graphics::Buffer>&& oldBuffer)
1187 {
1188   std::ostringstream oss;
1189   oss << "bufferCreateInfo:" << createInfo;
1190   mCallStack.PushCall("CreateBuffer", oss.str());
1191   return Graphics::MakeUnique<TestGraphicsBuffer>(mCallStack, mGl, createInfo.size, createInfo.usage);
1192 }
1193
1194 Graphics::UniquePtr<Graphics::CommandBuffer> TestGraphicsController::CreateCommandBuffer(const Graphics::CommandBufferCreateInfo& commandBufferCreateInfo, Graphics::UniquePtr<Graphics::CommandBuffer>&& oldCommandBuffer)
1195 {
1196   std::ostringstream oss;
1197   oss << "commandBufferCreateInfo:" << commandBufferCreateInfo;
1198   mCallStack.PushCall("CreateCommandBuffer", oss.str());
1199   return Graphics::MakeUnique<TestGraphicsCommandBuffer>(mCommandBufferCallStack, mGl);
1200 }
1201
1202 Graphics::UniquePtr<Graphics::RenderPass> TestGraphicsController::CreateRenderPass(const Graphics::RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<Graphics::RenderPass>&& oldRenderPass)
1203 {
1204   mCallStack.PushCall("CreateRenderPass", "");
1205   return Graphics::MakeUnique<TestGraphicsRenderPass>(mGl, renderPassCreateInfo);
1206 }
1207
1208 Graphics::UniquePtr<Graphics::Texture> TestGraphicsController::CreateTexture(const Graphics::TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr<Graphics::Texture>&& oldTexture)
1209 {
1210   TraceCallStack::NamedParams namedParams;
1211   namedParams["textureCreateInfo"] << textureCreateInfo;
1212   mCallStack.PushCall("CreateTexture", namedParams.str(), namedParams);
1213
1214   return Graphics::MakeUnique<TestGraphicsTexture>(mGl, textureCreateInfo);
1215 }
1216
1217 Graphics::UniquePtr<Graphics::Framebuffer> TestGraphicsController::CreateFramebuffer(
1218   const Graphics::FramebufferCreateInfo&       createInfo,
1219   Graphics::UniquePtr<Graphics::Framebuffer>&& oldFramebuffer)
1220 {
1221   TraceCallStack::NamedParams namedParams;
1222   namedParams["framebufferCreateInfo"] << createInfo;
1223   mCallStack.PushCall("Controller::CreateFramebuffer", namedParams.str(), namedParams);
1224
1225   return Graphics::MakeUnique<TestGraphicsFramebuffer>(mFrameBufferCallStack, mGl, createInfo);
1226 }
1227
1228 Graphics::UniquePtr<Graphics::Pipeline> TestGraphicsController::CreatePipeline(const Graphics::PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
1229 {
1230   mCallStack.PushCall("CreatePipeline", "");
1231   return std::make_unique<TestGraphicsPipeline>(mGl, pipelineCreateInfo);
1232 }
1233
1234 Graphics::UniquePtr<Graphics::Program> TestGraphicsController::CreateProgram(const Graphics::ProgramCreateInfo& programCreateInfo, Graphics::UniquePtr<Graphics::Program>&& oldProgram)
1235 {
1236   mCallStack.PushCall("CreateProgram", "");
1237
1238   for(auto cacheEntry : mProgramCache)
1239   {
1240     bool found = true;
1241     for(auto& shader : *(programCreateInfo.shaderState))
1242     {
1243       auto                 graphicsShader = Uncast<TestGraphicsShader>(shader.shader);
1244       std::vector<uint8_t> source;
1245       source.resize(graphicsShader->mCreateInfo.sourceSize);
1246       memcpy(&source[0], graphicsShader->mCreateInfo.sourceData, graphicsShader->mCreateInfo.sourceSize);
1247
1248       if(!std::equal(source.begin(), source.end(), cacheEntry.shaders[shader.pipelineStage].begin(), cacheEntry.shaders[shader.pipelineStage].end()))
1249       {
1250         found = false;
1251         break;
1252       }
1253     }
1254     if(found)
1255     {
1256       return Graphics::MakeUnique<TestGraphicsProgram>(cacheEntry.programImpl);
1257     }
1258   }
1259
1260   mProgramCache.emplace_back();
1261   mProgramCache.back().programImpl = new TestGraphicsProgramImpl(mGl, programCreateInfo, mVertexFormats, mCustomUniforms);
1262   for(auto& shader : *(programCreateInfo.shaderState))
1263   {
1264     auto graphicsShader = Uncast<TestGraphicsShader>(shader.shader);
1265     mProgramCache.back().shaders[shader.pipelineStage].resize(graphicsShader->mCreateInfo.sourceSize);
1266     memcpy(&mProgramCache.back().shaders[shader.pipelineStage][0], graphicsShader->mCreateInfo.sourceData, graphicsShader->mCreateInfo.sourceSize);
1267   }
1268   return Graphics::MakeUnique<TestGraphicsProgram>(mProgramCache.back().programImpl);
1269 }
1270
1271 Graphics::UniquePtr<Graphics::Shader> TestGraphicsController::CreateShader(const Graphics::ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr<Graphics::Shader>&& oldShader)
1272 {
1273   mCallStack.PushCall("CreateShader", "");
1274   return Graphics::MakeUnique<TestGraphicsShader>(mGl, shaderCreateInfo);
1275 }
1276
1277 Graphics::UniquePtr<Graphics::Sampler> TestGraphicsController::CreateSampler(const Graphics::SamplerCreateInfo& samplerCreateInfo, Graphics::UniquePtr<Graphics::Sampler>&& oldSampler)
1278 {
1279   TraceCallStack::NamedParams namedParams;
1280   namedParams["samplerCreateInfo"] << samplerCreateInfo;
1281   mCallStack.PushCall("CreateSampler", namedParams.str(), namedParams);
1282
1283   return Graphics::MakeUnique<TestGraphicsSampler>(mGl, samplerCreateInfo);
1284 }
1285
1286 Graphics::UniquePtr<Graphics::RenderTarget> TestGraphicsController::CreateRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<Graphics::RenderTarget>&& oldRenderTarget)
1287 {
1288   TraceCallStack::NamedParams namedParams;
1289   namedParams["surface"] << std::hex << renderTargetCreateInfo.surface;
1290   mCallStack.PushCall("CreateRenderTarget", namedParams.str(), namedParams);
1291
1292   return Graphics::MakeUnique<TestGraphicsRenderTarget>(mGl, renderTargetCreateInfo);
1293 }
1294
1295 Graphics::UniquePtr<Graphics::SyncObject> TestGraphicsController::CreateSyncObject(
1296   const Graphics::SyncObjectCreateInfo&       syncObjectCreateInfo,
1297   Graphics::UniquePtr<Graphics::SyncObject>&& oldSyncObject)
1298 {
1299   mCallStack.PushCall("CreateSyncObject", "");
1300   return Graphics::MakeUnique<TestGraphicsSyncObject>(mGraphicsSyncImpl, syncObjectCreateInfo);
1301 }
1302
1303 Graphics::UniquePtr<Graphics::Memory> TestGraphicsController::MapBufferRange(const Graphics::MapBufferInfo& mapInfo)
1304 {
1305   mCallStack.PushCall("MapBufferRange", "");
1306
1307   auto buffer = static_cast<TestGraphicsBuffer*>(mapInfo.buffer);
1308   buffer->memory.resize(mapInfo.offset + mapInfo.size); // For initial testing, allow writes past capacity
1309
1310   return std::make_unique<TestGraphicsMemory>(mCallStack, *buffer, mapInfo.offset, mapInfo.size);
1311 }
1312
1313 Graphics::UniquePtr<Graphics::Memory> TestGraphicsController::MapTextureRange(const Graphics::MapTextureInfo& mapInfo)
1314 {
1315   mCallStack.PushCall("MapTextureRange", "");
1316   return nullptr;
1317 }
1318
1319 void TestGraphicsController::UnmapMemory(Graphics::UniquePtr<Graphics::Memory> memory)
1320 {
1321   mCallStack.PushCall("UnmapMemory", "");
1322 }
1323
1324 Graphics::MemoryRequirements TestGraphicsController::GetTextureMemoryRequirements(Graphics::Texture& texture) const
1325 {
1326   mCallStack.PushCall("GetTextureMemoryRequirements", "");
1327   return Graphics::MemoryRequirements{};
1328 }
1329
1330 Graphics::MemoryRequirements TestGraphicsController::GetBufferMemoryRequirements(Graphics::Buffer& buffer) const
1331 {
1332   mCallStack.PushCall("GetBufferMemoryRequirements", "");
1333   return Graphics::MemoryRequirements{};
1334 }
1335
1336 Graphics::TextureProperties TestGraphicsController::GetTextureProperties(const Graphics::Texture& texture)
1337 {
1338   static Graphics::TextureProperties textureProperties{};
1339   mCallStack.PushCall("GetTextureProperties", "");
1340
1341   return textureProperties;
1342 }
1343
1344 const Graphics::Reflection& TestGraphicsController::GetProgramReflection(const Graphics::Program& program)
1345 {
1346   mCallStack.PushCall("GetProgramReflection", "");
1347
1348   return static_cast<const TestGraphicsProgram*>(&program)->GetReflection();
1349 }
1350
1351 bool TestGraphicsController::PipelineEquals(const Graphics::Pipeline& pipeline0, const Graphics::Pipeline& pipeline1) const
1352 {
1353   mCallStack.PushCall("PipelineEquals", "");
1354   return false;
1355 }
1356
1357 bool TestGraphicsController::GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData)
1358 {
1359   mCallStack.PushCall("GetProgramParameter", "");
1360   auto graphicsProgram = Uncast<TestGraphicsProgram>(&program);
1361   return graphicsProgram->GetParameter(parameterId, outData);
1362 }
1363
1364 } // namespace Dali