Merge branch 'devel/master' into devel/graphics
[platform/core/uifw/dali-toolkit.git] / automated-tests / src / dali-toolkit / dali-toolkit-test-utils / test-graphics-controller.cpp
1 /*
2  * Copyright (c) 2021 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-reflection.h"
22 #include "test-graphics-sampler.h"
23 #include "test-graphics-shader.h"
24 #include "test-graphics-texture.h"
25
26 #include <dali/integration-api/gl-defines.h>
27 #include <cstdio>
28 #include <iostream>
29 #include <sstream>
30
31 namespace Dali
32 {
33 template<typename T>
34 T* Uncast(const Graphics::CommandBuffer* object)
35 {
36   return const_cast<T*>(static_cast<const T*>(object));
37 }
38
39 template<typename T>
40 T* Uncast(const Graphics::Texture* object)
41 {
42   return const_cast<T*>(static_cast<const T*>(object));
43 }
44
45 template<typename T>
46 T* Uncast(const Graphics::Sampler* object)
47 {
48   return const_cast<T*>(static_cast<const T*>(object));
49 }
50
51 template<typename T>
52 T* Uncast(const Graphics::Buffer* object)
53 {
54   return const_cast<T*>(static_cast<const T*>(object));
55 }
56
57 std::ostream& operator<<(std::ostream& o, const Graphics::BufferCreateInfo& bufferCreateInfo)
58 {
59   return o << "usage:" << std::hex << bufferCreateInfo.usage << ", size:" << std::dec << bufferCreateInfo.size;
60 }
61
62 std::ostream& operator<<(std::ostream& o, const Graphics::CommandBufferCreateInfo& commandBufferCreateInfo)
63 {
64   return o << "level:" << (commandBufferCreateInfo.level == Graphics::CommandBufferLevel::PRIMARY ? "PRIMARY" : "SECONDARY")
65            << ", fixedCapacity:" << std::dec << commandBufferCreateInfo.fixedCapacity;
66 }
67
68 std::ostream& operator<<(std::ostream& o, const Graphics::TextureType& textureType)
69 {
70   switch(textureType)
71   {
72     case Graphics::TextureType::TEXTURE_2D:
73       o << "TEXTURE_2D";
74       break;
75     case Graphics::TextureType::TEXTURE_3D:
76       o << "TEXTURE_3D";
77       break;
78     case Graphics::TextureType::TEXTURE_CUBEMAP:
79       o << "TEXTURE_CUBEMAP";
80       break;
81   }
82   return o;
83 }
84
85 std::ostream& operator<<(std::ostream& o, const Graphics::Extent2D extent)
86 {
87   o << "width:" << extent.width << ", height:" << extent.height;
88   return o;
89 }
90
91 std::ostream& operator<<(std::ostream& o, const Graphics::TextureCreateInfo& createInfo)
92 {
93   o << "textureType:" << createInfo.textureType
94     << " size:" << createInfo.size
95     << " format:" << static_cast<uint32_t>(createInfo.format)
96     << " mipMapFlag:" << createInfo.mipMapFlag
97     << " layout:" << (createInfo.layout == Graphics::TextureLayout::LINEAR ? "LINEAR" : "OPTIMAL")
98     << " usageFlags:" << std::hex << createInfo.usageFlags
99     << " data:" << std::hex << createInfo.data
100     << " dataSize:" << std::dec << createInfo.dataSize
101     << " nativeImagePtr:" << std::hex << createInfo.nativeImagePtr;
102   return o;
103 }
104
105 std::ostream& operator<<(std::ostream& o, Graphics::SamplerAddressMode addressMode)
106 {
107   switch(addressMode)
108   {
109     case Graphics::SamplerAddressMode::REPEAT:
110       o << "REPEAT";
111       break;
112     case Graphics::SamplerAddressMode::MIRRORED_REPEAT:
113       o << "MIRRORED_REPEAT";
114       break;
115     case Graphics::SamplerAddressMode::CLAMP_TO_EDGE:
116       o << "CLAMP_TO_EDGE";
117       break;
118     case Graphics::SamplerAddressMode::CLAMP_TO_BORDER:
119       o << "CLAMP_TO_BORDER";
120       break;
121     case Graphics::SamplerAddressMode::MIRROR_CLAMP_TO_EDGE:
122       o << "MIRROR_CLAMP_TO_EDGE";
123       break;
124   }
125   return o;
126 }
127
128 std::ostream& operator<<(std::ostream& o, Graphics::SamplerFilter filterMode)
129 {
130   switch(filterMode)
131   {
132     case Graphics::SamplerFilter::LINEAR:
133       o << "LINEAR";
134       break;
135     case Graphics::SamplerFilter::NEAREST:
136       o << "NEAREST";
137       break;
138   }
139   return o;
140 }
141
142 std::ostream& operator<<(std::ostream& o, Graphics::SamplerMipmapMode mipmapMode)
143 {
144   switch(mipmapMode)
145   {
146     case Graphics::SamplerMipmapMode::NONE:
147       o << "NONE";
148       break;
149     case Graphics::SamplerMipmapMode::LINEAR:
150       o << "LINEAR";
151       break;
152     case Graphics::SamplerMipmapMode::NEAREST:
153       o << "NEAREST";
154       break;
155   }
156   return o;
157 }
158
159 std::ostream& operator<<(std::ostream& o, const Graphics::SamplerCreateInfo& createInfo)
160 {
161   o << "minFilter:" << createInfo.minFilter
162     << " magFilter:" << createInfo.magFilter
163     << " wrapModeU:" << createInfo.addressModeU
164     << " wrapModeV:" << createInfo.addressModeV
165     << " wrapModeW:" << createInfo.addressModeW
166     << " mipMapMode:" << createInfo.mipMapMode;
167   return o;
168 }
169
170 class TestGraphicsMemory : public Graphics::Memory
171 {
172 public:
173   TestGraphicsMemory(TraceCallStack& callStack, TestGraphicsBuffer& buffer, uint32_t mappedOffset, uint32_t mappedSize)
174   : mCallStack(callStack),
175     mBuffer(buffer),
176     mMappedOffset(mappedOffset),
177     mMappedSize(mappedSize)
178   {
179   }
180
181   void* LockRegion(uint32_t offset, uint32_t size) override
182   {
183     std::ostringstream o;
184     o << offset << ", " << size;
185     mCallStack.PushCall("Memory::LockRegion", o.str());
186
187     if(offset > mMappedOffset + mMappedSize ||
188        size + offset > mMappedOffset + mMappedSize)
189     {
190       fprintf(stderr, "TestGraphics.Memory::LockRegion() Out of bounds");
191       mBuffer.memory.resize(mMappedOffset + offset + size); // Grow to prevent memcpy from crashing
192     }
193     mLockedOffset = offset;
194     mLockedSize   = size;
195     return &mBuffer.memory[mMappedOffset + offset];
196   }
197
198   void Unlock(bool flush) override
199   {
200     mCallStack.PushCall("Memory::Unlock", (flush ? "Flush" : "NoFlush"));
201     if(flush)
202     {
203       Flush();
204     }
205   }
206
207   void Flush() override
208   {
209     mCallStack.PushCall("Memory::Flush", "");
210     mBuffer.Bind();
211     mBuffer.Upload(mMappedOffset + mLockedOffset, mLockedSize);
212     mBuffer.Unbind();
213   }
214
215   TraceCallStack&     mCallStack;
216   TestGraphicsBuffer& mBuffer;
217   uint32_t            mMappedOffset;
218   uint32_t            mMappedSize;
219   uint32_t            mLockedOffset;
220   uint32_t            mLockedSize;
221 };
222
223 TestGraphicsController::TestGraphicsController()
224 : mCallStack(true, "TestGraphicsController."),
225   mCommandBufferCallStack(true, "TestCommandBuffer.")
226 {
227   mCallStack.Enable(true);
228   mCommandBufferCallStack.Enable(true);
229   auto& trace = mGl.GetTextureTrace();
230   trace.Enable(true);
231   trace.EnableLogging(true);
232 }
233
234 int GetNumComponents(Graphics::VertexInputFormat vertexFormat)
235 {
236   switch(vertexFormat)
237   {
238     case Graphics::VertexInputFormat::UNDEFINED:
239     case Graphics::VertexInputFormat::FLOAT:
240     case Graphics::VertexInputFormat::INTEGER:
241       return 1;
242     case Graphics::VertexInputFormat::IVECTOR2:
243     case Graphics::VertexInputFormat::FVECTOR2:
244       return 2;
245     case Graphics::VertexInputFormat::IVECTOR3:
246     case Graphics::VertexInputFormat::FVECTOR3:
247       return 3;
248     case Graphics::VertexInputFormat::FVECTOR4:
249     case Graphics::VertexInputFormat::IVECTOR4:
250       return 4;
251   }
252   return 1;
253 }
254
255 GLint GetSize(Graphics::VertexInputFormat vertexFormat)
256 {
257   switch(vertexFormat)
258   {
259     case Graphics::VertexInputFormat::UNDEFINED:
260       return 1u;
261     case Graphics::VertexInputFormat::INTEGER:
262     case Graphics::VertexInputFormat::IVECTOR2:
263     case Graphics::VertexInputFormat::IVECTOR3:
264     case Graphics::VertexInputFormat::IVECTOR4:
265       return 2u;
266     case Graphics::VertexInputFormat::FLOAT:
267     case Graphics::VertexInputFormat::FVECTOR2:
268     case Graphics::VertexInputFormat::FVECTOR3:
269     case Graphics::VertexInputFormat::FVECTOR4:
270       return 4u;
271   }
272   return 1u;
273 }
274
275 GLint GetGlType(Graphics::VertexInputFormat vertexFormat)
276 {
277   switch(vertexFormat)
278   {
279     case Graphics::VertexInputFormat::UNDEFINED:
280       return GL_BYTE;
281     case Graphics::VertexInputFormat::INTEGER:
282     case Graphics::VertexInputFormat::IVECTOR2:
283     case Graphics::VertexInputFormat::IVECTOR3:
284     case Graphics::VertexInputFormat::IVECTOR4:
285       return GL_SHORT;
286     case Graphics::VertexInputFormat::FLOAT:
287     case Graphics::VertexInputFormat::FVECTOR2:
288     case Graphics::VertexInputFormat::FVECTOR3:
289     case Graphics::VertexInputFormat::FVECTOR4:
290       return GL_FLOAT;
291   }
292   return GL_BYTE;
293 }
294
295 GLenum GetTopology(Graphics::PrimitiveTopology topology)
296 {
297   switch(topology)
298   {
299     case Graphics::PrimitiveTopology::POINT_LIST:
300       return GL_POINTS;
301
302     case Graphics::PrimitiveTopology::LINE_LIST:
303       return GL_LINES;
304
305     case Graphics::PrimitiveTopology::LINE_LOOP:
306       return GL_LINE_LOOP;
307
308     case Graphics::PrimitiveTopology::LINE_STRIP:
309       return GL_LINE_STRIP;
310
311     case Graphics::PrimitiveTopology::TRIANGLE_LIST:
312       return GL_TRIANGLES;
313
314     case Graphics::PrimitiveTopology::TRIANGLE_STRIP:
315       return GL_TRIANGLE_STRIP;
316
317     case Graphics::PrimitiveTopology::TRIANGLE_FAN:
318       return GL_TRIANGLE_FAN;
319   }
320   return GL_TRIANGLES;
321 }
322
323 GLenum GetCullFace(Graphics::CullMode cullMode)
324 {
325   switch(cullMode)
326   {
327     case Graphics::CullMode::NONE:
328       return GL_NONE;
329     case Graphics::CullMode::FRONT:
330       return GL_FRONT;
331     case Graphics::CullMode::BACK:
332       return GL_BACK;
333     case Graphics::CullMode::FRONT_AND_BACK:
334       return GL_FRONT_AND_BACK;
335   }
336   return GL_NONE;
337 }
338
339 GLenum GetFrontFace(Graphics::FrontFace frontFace)
340 {
341   if(frontFace == Graphics::FrontFace::CLOCKWISE)
342   {
343     return GL_CW;
344   }
345   return GL_CCW;
346 }
347
348 GLenum GetBlendFactor(Graphics::BlendFactor blendFactor)
349 {
350   GLenum glFactor = GL_ZERO;
351
352   switch(blendFactor)
353   {
354     case Graphics::BlendFactor::ZERO:
355       glFactor = GL_ZERO;
356       break;
357     case Graphics::BlendFactor::ONE:
358       glFactor = GL_ONE;
359       break;
360     case Graphics::BlendFactor::SRC_COLOR:
361       glFactor = GL_SRC_COLOR;
362       break;
363     case Graphics::BlendFactor::ONE_MINUS_SRC_COLOR:
364       glFactor = GL_ONE_MINUS_SRC_COLOR;
365       break;
366     case Graphics::BlendFactor::DST_COLOR:
367       glFactor = GL_DST_COLOR;
368       break;
369     case Graphics::BlendFactor::ONE_MINUS_DST_COLOR:
370       glFactor = GL_ONE_MINUS_DST_COLOR;
371       break;
372     case Graphics::BlendFactor::SRC_ALPHA:
373       glFactor = GL_SRC_ALPHA;
374       break;
375     case Graphics::BlendFactor::ONE_MINUS_SRC_ALPHA:
376       glFactor = GL_ONE_MINUS_SRC_ALPHA;
377       break;
378     case Graphics::BlendFactor::DST_ALPHA:
379       glFactor = GL_DST_ALPHA;
380       break;
381     case Graphics::BlendFactor::ONE_MINUS_DST_ALPHA:
382       glFactor = GL_ONE_MINUS_DST_ALPHA;
383       break;
384     case Graphics::BlendFactor::CONSTANT_COLOR:
385       glFactor = GL_CONSTANT_COLOR;
386       break;
387     case Graphics::BlendFactor::ONE_MINUS_CONSTANT_COLOR:
388       glFactor = GL_ONE_MINUS_CONSTANT_COLOR;
389       break;
390     case Graphics::BlendFactor::CONSTANT_ALPHA:
391       glFactor = GL_CONSTANT_ALPHA;
392       break;
393     case Graphics::BlendFactor::ONE_MINUS_CONSTANT_ALPHA:
394       glFactor = GL_ONE_MINUS_CONSTANT_ALPHA;
395       break;
396     case Graphics::BlendFactor::SRC_ALPHA_SATURATE:
397       glFactor = GL_SRC_ALPHA_SATURATE;
398       break;
399       // GLES doesn't appear to have dual source blending.
400     case Graphics::BlendFactor::SRC1_COLOR:
401       glFactor = GL_SRC_COLOR;
402       break;
403     case Graphics::BlendFactor::ONE_MINUS_SRC1_COLOR:
404       glFactor = GL_ONE_MINUS_SRC_COLOR;
405       break;
406     case Graphics::BlendFactor::SRC1_ALPHA:
407       glFactor = GL_SRC_ALPHA;
408       break;
409     case Graphics::BlendFactor::ONE_MINUS_SRC1_ALPHA:
410       glFactor = GL_ONE_MINUS_SRC_ALPHA;
411       break;
412   }
413   return glFactor;
414 }
415
416 GLenum GetBlendOp(Graphics::BlendOp blendOp)
417 {
418   GLenum op = GL_FUNC_ADD;
419   switch(blendOp)
420   {
421     case Graphics::BlendOp::ADD:
422       op = GL_FUNC_ADD;
423       break;
424     case Graphics::BlendOp::SUBTRACT:
425       op = GL_FUNC_SUBTRACT;
426       break;
427     case Graphics::BlendOp::REVERSE_SUBTRACT:
428       op = GL_FUNC_REVERSE_SUBTRACT;
429       break;
430     case Graphics::BlendOp::MIN:
431       op = GL_MIN;
432       break;
433     case Graphics::BlendOp::MAX:
434       op = GL_MAX;
435       break;
436
437       // @todo Add advanced blend equations
438   }
439   return op;
440 }
441
442 void TestGraphicsController::SubmitCommandBuffers(const Graphics::SubmitInfo& submitInfo)
443 {
444   TraceCallStack::NamedParams namedParams;
445   namedParams["submitInfo"] << "cmdBuffer[" << submitInfo.cmdBuffer.size()
446                             << "], flags:" << std::hex << submitInfo.flags;
447
448   mCallStack.PushCall("SubmitCommandBuffers", "", namedParams);
449
450   mSubmitStack.emplace_back(submitInfo);
451
452   for(auto& graphicsCommandBuffer : submitInfo.cmdBuffer)
453   {
454     auto commandBuffer = Uncast<TestGraphicsCommandBuffer>(graphicsCommandBuffer);
455     for(auto& binding : commandBuffer->mTextureBindings)
456     {
457       if(binding.texture)
458       {
459         auto texture = Uncast<TestGraphicsTexture>(binding.texture);
460
461         texture->Bind(binding.binding);
462
463         if(binding.sampler)
464         {
465           auto sampler = Uncast<TestGraphicsSampler>(binding.sampler);
466           if(sampler)
467           {
468             sampler->Apply(texture->GetTarget());
469           }
470         }
471
472         texture->Prepare(); // Ensure native texture is ready
473       }
474     }
475
476     // IndexBuffer binding,
477     auto& indexBufferBinding = commandBuffer->mIndexBufferBinding;
478     if(indexBufferBinding.buffer)
479     {
480       auto buffer = Uncast<TestGraphicsBuffer>(indexBufferBinding.buffer);
481       buffer->Bind();
482     }
483
484     // VertexBuffer binding,
485     for(auto graphicsBuffer : commandBuffer->mVertexBufferBindings.buffers)
486     {
487       auto vertexBuffer = Uncast<TestGraphicsBuffer>(graphicsBuffer);
488       vertexBuffer->Bind();
489     }
490
491     // Pipeline attribute setup
492     auto& vi = commandBuffer->mPipeline->vertexInputState;
493     for(auto& attribute : vi.attributes)
494     {
495       mGl.EnableVertexAttribArray(attribute.location);
496       uint32_t attributeOffset = attribute.offset;
497       GLsizei  stride          = vi.bufferBindings[attribute.binding].stride;
498
499       mGl.VertexAttribPointer(attribute.location,
500                               GetNumComponents(attribute.format),
501                               GetGlType(attribute.format),
502                               GL_FALSE, // Not normalized
503                               stride,
504                               reinterpret_cast<void*>(attributeOffset));
505     }
506
507     // Cull face setup
508     auto& rasterizationState = commandBuffer->mPipeline->rasterizationState;
509     if(rasterizationState.cullMode == Graphics::CullMode::NONE)
510     {
511       mGl.Disable(GL_CULL_FACE);
512     }
513     else
514     {
515       mGl.Enable(GL_CULL_FACE);
516       mGl.CullFace(GetCullFace(rasterizationState.cullMode));
517     }
518
519     mGl.FrontFace(GetFrontFace(rasterizationState.frontFace));
520     // We don't modify glPolygonMode in our context/abstraction from GL_FILL (the GL default),
521     // so it isn't present in the API (and won't have any tests!)
522
523     // Blending setup
524     auto& colorBlendState = commandBuffer->mPipeline->colorBlendState;
525     if(colorBlendState.blendEnable)
526     {
527       mGl.Enable(GL_BLEND);
528
529       mGl.BlendFuncSeparate(GetBlendFactor(colorBlendState.srcColorBlendFactor),
530                             GetBlendFactor(colorBlendState.dstColorBlendFactor),
531                             GetBlendFactor(colorBlendState.srcAlphaBlendFactor),
532                             GetBlendFactor(colorBlendState.dstAlphaBlendFactor));
533       if(colorBlendState.colorBlendOp != colorBlendState.alphaBlendOp)
534       {
535         mGl.BlendEquationSeparate(GetBlendOp(colorBlendState.colorBlendOp), GetBlendOp(colorBlendState.alphaBlendOp));
536       }
537       else
538       {
539         mGl.BlendEquation(GetBlendOp(colorBlendState.colorBlendOp));
540       }
541       mGl.BlendColor(colorBlendState.blendConstants[0],
542                      colorBlendState.blendConstants[1],
543                      colorBlendState.blendConstants[2],
544                      colorBlendState.blendConstants[3]);
545     }
546     else
547     {
548       mGl.Disable(GL_BLEND);
549     }
550
551     // draw call
552     auto topology = commandBuffer->mPipeline->inputAssemblyState.topology;
553
554     if(commandBuffer->drawCommand.drawType == TestGraphicsCommandBuffer::Draw::DrawType::Indexed)
555     {
556       mGl.DrawElements(GetTopology(topology),
557                        static_cast<GLsizei>(commandBuffer->drawCommand.u.indexedDraw.indexCount),
558                        GL_UNSIGNED_SHORT,
559                        reinterpret_cast<void*>(commandBuffer->drawCommand.u.indexedDraw.firstIndex));
560     }
561     else
562     {
563       mGl.DrawArrays(GetTopology(topology), 0, commandBuffer->drawCommand.u.unindexedDraw.vertexCount);
564     }
565
566     // attribute clear
567     for(auto& attribute : vi.attributes)
568     {
569       mGl.DisableVertexAttribArray(attribute.location);
570     }
571   }
572 }
573
574 /**
575  * @brief Presents render target
576  * @param renderTarget render target to present
577  */
578 void TestGraphicsController::PresentRenderTarget(Graphics::RenderTarget* renderTarget)
579 {
580   TraceCallStack::NamedParams namedParams;
581   namedParams["renderTarget"] << std::hex << renderTarget;
582   mCallStack.PushCall("PresentRenderTarget", "", namedParams);
583 }
584
585 /**
586  * @brief Waits until the GPU is idle
587  */
588 void TestGraphicsController::WaitIdle()
589 {
590   mCallStack.PushCall("WaitIdle", "");
591 }
592
593 /**
594  * @brief Lifecycle pause event
595  */
596 void TestGraphicsController::Pause()
597 {
598   mCallStack.PushCall("Pause", "");
599 }
600
601 /**
602  * @brief Lifecycle resume event
603  */
604 void TestGraphicsController::Resume()
605 {
606   mCallStack.PushCall("Resume", "");
607 }
608
609 void TestGraphicsController::UpdateTextures(const std::vector<Graphics::TextureUpdateInfo>&       updateInfoList,
610                                             const std::vector<Graphics::TextureUpdateSourceInfo>& sourceList)
611 {
612   TraceCallStack::NamedParams namedParams;
613   namedParams["updateInfoList"] << "[" << updateInfoList.size() << "]:";
614   namedParams["sourceList"] << "[" << sourceList.size() << "]:";
615
616   mCallStack.PushCall("UpdateTextures", "", namedParams);
617
618   // Call either TexImage2D or TexSubImage2D
619   for(unsigned int i = 0; i < updateInfoList.size(); ++i)
620   {
621     auto& updateInfo = updateInfoList[i];
622     auto& source     = sourceList[i];
623
624     auto texture = static_cast<TestGraphicsTexture*>(updateInfo.dstTexture);
625     texture->Bind(0); // Use first texture unit during resource update
626     texture->Update(updateInfo, source);
627   }
628 }
629
630 bool TestGraphicsController::EnableDepthStencilBuffer(bool enableDepth, bool enableStencil)
631 {
632   TraceCallStack::NamedParams namedParams;
633   namedParams["enableDepth"] << (enableDepth ? "T" : "F");
634   namedParams["enableStencil"] << (enableStencil ? "T" : "F");
635   mCallStack.PushCall("EnableDepthStencilBuffer", "", namedParams);
636   return false;
637 }
638
639 void TestGraphicsController::RunGarbageCollector(size_t numberOfDiscardedRenderers)
640 {
641   TraceCallStack::NamedParams namedParams;
642   namedParams["numberOfDiscardedRenderers"] << numberOfDiscardedRenderers;
643   mCallStack.PushCall("RunGarbageCollector", "", namedParams);
644 }
645
646 void TestGraphicsController::DiscardUnusedResources()
647 {
648   mCallStack.PushCall("DiscardUnusedResources", "");
649 }
650
651 bool TestGraphicsController::IsDiscardQueueEmpty()
652 {
653   mCallStack.PushCall("IsDiscardQueueEmpty", "");
654   return isDiscardQueueEmptyResult;
655 }
656
657 /**
658  * @brief Test if the graphics subsystem has resumed & should force a draw
659  *
660  * @return true if the graphics subsystem requires a re-draw
661  */
662 bool TestGraphicsController::IsDrawOnResumeRequired()
663 {
664   mCallStack.PushCall("IsDrawOnResumeRequired", "");
665   return isDrawOnResumeRequiredResult;
666 }
667
668 Graphics::UniquePtr<Graphics::Buffer> TestGraphicsController::CreateBuffer(const Graphics::BufferCreateInfo& createInfo, Graphics::UniquePtr<Graphics::Buffer>&& oldBuffer)
669 {
670   std::ostringstream oss;
671   oss << "bufferCreateInfo:" << createInfo;
672   mCallStack.PushCall("CreateBuffer", oss.str());
673   return Graphics::MakeUnique<TestGraphicsBuffer>(mCallStack, mGl, createInfo.size, createInfo.usage);
674 }
675
676 Graphics::UniquePtr<Graphics::CommandBuffer> TestGraphicsController::CreateCommandBuffer(const Graphics::CommandBufferCreateInfo& commandBufferCreateInfo, Graphics::UniquePtr<Graphics::CommandBuffer>&& oldCommandBuffer)
677 {
678   std::ostringstream oss;
679   oss << "commandBufferCreateInfo:" << commandBufferCreateInfo;
680   mCallStack.PushCall("CreateCommandBuffer", oss.str());
681   return Graphics::MakeUnique<TestGraphicsCommandBuffer>(mCommandBufferCallStack, mGl);
682 }
683
684 Graphics::UniquePtr<Graphics::RenderPass> TestGraphicsController::CreateRenderPass(const Graphics::RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<Graphics::RenderPass>&& oldRenderPass)
685 {
686   mCallStack.PushCall("CreateRenderPass", "");
687   return nullptr;
688 }
689
690 Graphics::UniquePtr<Graphics::Texture> TestGraphicsController::CreateTexture(const Graphics::TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr<Graphics::Texture>&& oldTexture)
691 {
692   TraceCallStack::NamedParams namedParams;
693   namedParams["textureCreateInfo"] << textureCreateInfo;
694   mCallStack.PushCall("CreateTexture", namedParams.str(), namedParams);
695
696   return Graphics::MakeUnique<TestGraphicsTexture>(mGl, textureCreateInfo);
697 }
698
699 Graphics::UniquePtr<Graphics::Framebuffer> TestGraphicsController::CreateFramebuffer(const Graphics::FramebufferCreateInfo& framebufferCreateInfo, Graphics::UniquePtr<Graphics::Framebuffer>&& oldFramebuffer)
700 {
701   mCallStack.PushCall("CreateFramebuffer", "");
702   return nullptr;
703 }
704
705 Graphics::UniquePtr<Graphics::Pipeline> TestGraphicsController::CreatePipeline(const Graphics::PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
706 {
707   mCallStack.PushCall("CreatePipeline", "");
708   return std::make_unique<TestGraphicsPipeline>(mGl, pipelineCreateInfo);
709 }
710
711 Graphics::UniquePtr<Graphics::Program> TestGraphicsController::CreateProgram(const Graphics::ProgramCreateInfo& programCreateInfo, Graphics::UniquePtr<Graphics::Program>&& oldProgram)
712 {
713   mCallStack.PushCall("CreateProgram", "");
714   return Graphics::MakeUnique<TestGraphicsProgram>(mGl, programCreateInfo, mVertexFormats);
715 }
716
717 Graphics::UniquePtr<Graphics::Shader> TestGraphicsController::CreateShader(const Graphics::ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr<Graphics::Shader>&& oldShader)
718 {
719   mCallStack.PushCall("CreateShader", "");
720   return Graphics::MakeUnique<TestGraphicsShader>(mGl, shaderCreateInfo);
721 }
722
723 Graphics::UniquePtr<Graphics::Sampler> TestGraphicsController::CreateSampler(const Graphics::SamplerCreateInfo& samplerCreateInfo, Graphics::UniquePtr<Graphics::Sampler>&& oldSampler)
724 {
725   TraceCallStack::NamedParams namedParams;
726   namedParams["samplerCreateInfo"] << samplerCreateInfo;
727   mCallStack.PushCall("CreateSampler", namedParams.str(), namedParams);
728
729   return Graphics::MakeUnique<TestGraphicsSampler>(mGl, samplerCreateInfo);
730 }
731
732 Graphics::UniquePtr<Graphics::RenderTarget> TestGraphicsController::CreateRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<Graphics::RenderTarget>&& oldRenderTarget)
733 {
734   mCallStack.PushCall("CreateRenderTarget", "");
735   return nullptr;
736 }
737
738 Graphics::UniquePtr<Graphics::Memory> TestGraphicsController::MapBufferRange(const Graphics::MapBufferInfo& mapInfo)
739 {
740   mCallStack.PushCall("MapBufferRange", "");
741
742   auto buffer = static_cast<TestGraphicsBuffer*>(mapInfo.buffer);
743   buffer->memory.resize(mapInfo.offset + mapInfo.size); // For initial testing, allow writes past capacity
744
745   return std::make_unique<TestGraphicsMemory>(mCallStack, *buffer, mapInfo.offset, mapInfo.size);
746 }
747
748 Graphics::UniquePtr<Graphics::Memory> TestGraphicsController::MapTextureRange(const Graphics::MapTextureInfo& mapInfo)
749 {
750   mCallStack.PushCall("MapTextureRange", "");
751   return nullptr;
752 }
753
754 void TestGraphicsController::UnmapMemory(Graphics::UniquePtr<Graphics::Memory> memory)
755 {
756   mCallStack.PushCall("UnmapMemory", "");
757 }
758
759 Graphics::MemoryRequirements TestGraphicsController::GetTextureMemoryRequirements(Graphics::Texture& texture) const
760 {
761   mCallStack.PushCall("GetTextureMemoryRequirements", "");
762   return Graphics::MemoryRequirements{};
763 }
764
765 Graphics::MemoryRequirements TestGraphicsController::GetBufferMemoryRequirements(Graphics::Buffer& buffer) const
766 {
767   mCallStack.PushCall("GetBufferMemoryRequirements", "");
768   return Graphics::MemoryRequirements{};
769 }
770
771 const Graphics::TextureProperties& TestGraphicsController::GetTextureProperties(const Graphics::Texture& texture)
772 {
773   static Graphics::TextureProperties textureProperties{};
774   mCallStack.PushCall("GetTextureProperties", "");
775
776   return textureProperties;
777 }
778
779 const Graphics::Reflection& TestGraphicsController::GetProgramReflection(const Graphics::Program& program)
780 {
781   mCallStack.PushCall("GetProgramReflection", "");
782
783   return static_cast<const TestGraphicsProgram*>(&program)->GetReflection();
784 }
785
786 bool TestGraphicsController::PipelineEquals(const Graphics::Pipeline& pipeline0, const Graphics::Pipeline& pipeline1) const
787 {
788   mCallStack.PushCall("PipelineEquals", "");
789   return false;
790 }
791
792 bool TestGraphicsController::GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData )
793 {
794   mCallStack.PushCall("GetProgramParameter", "");
795   auto graphicsProgram = Uncast<TestGraphicsProgram>(&program);
796   return graphicsProgram->GetParameter(parameterId, outData);
797 }
798
799 } // namespace Dali