2 * Copyright (c) 2023 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "test-graphics-controller.h"
19 #include <dali/graphics-api/graphics-types.h>
20 #include "test-graphics-buffer.h"
21 #include "test-graphics-command-buffer.h"
22 #include "test-graphics-framebuffer.h"
23 #include "test-graphics-reflection.h"
24 #include "test-graphics-render-pass.h"
25 #include "test-graphics-render-target.h"
26 #include "test-graphics-sampler.h"
27 #include "test-graphics-shader.h"
28 #include "test-graphics-sync-object.h"
29 #include "test-graphics-texture.h"
31 #include <dali/integration-api/gl-defines.h>
43 struct TestGraphicsDeleter
45 TestGraphicsDeleter() = default;
46 void operator()(T* object)
49 object->DiscardResource();
55 std::ostream& operator<<(std::ostream& o, const Graphics::BufferCreateInfo& bufferCreateInfo)
57 return o << "usage:" << std::hex << bufferCreateInfo.usage << ", size:" << std::dec << bufferCreateInfo.size;
60 std::ostream& operator<<(std::ostream& o, const Graphics::CommandBufferCreateInfo& commandBufferCreateInfo)
62 return o << "level:" << (commandBufferCreateInfo.level == Graphics::CommandBufferLevel::PRIMARY ? "PRIMARY" : "SECONDARY")
63 << ", fixedCapacity:" << std::dec << commandBufferCreateInfo.fixedCapacity;
66 std::ostream& operator<<(std::ostream& o, const Graphics::TextureType& textureType)
70 case Graphics::TextureType::TEXTURE_2D:
73 case Graphics::TextureType::TEXTURE_3D:
76 case Graphics::TextureType::TEXTURE_CUBEMAP:
77 o << "TEXTURE_CUBEMAP";
83 std::ostream& operator<<(std::ostream& o, const Graphics::Extent2D extent)
85 o << "width:" << extent.width << ", height:" << extent.height;
89 std::ostream& operator<<(std::ostream& o, const Graphics::TextureCreateInfo& createInfo)
91 o << "textureType:" << createInfo.textureType
92 << " size:" << createInfo.size
93 << " format:" << static_cast<uint32_t>(createInfo.format)
94 << " mipMapFlag:" << createInfo.mipMapFlag
95 << " layout:" << (createInfo.layout == Graphics::TextureLayout::LINEAR ? "LINEAR" : "OPTIMAL")
96 << " usageFlags:" << std::hex << createInfo.usageFlags
97 << " data:" << std::hex << createInfo.data
98 << " dataSize:" << std::dec << createInfo.dataSize
99 << " nativeImagePtr:" << std::hex << createInfo.nativeImagePtr.Get();
103 std::ostream& operator<<(std::ostream& o, Graphics::SamplerAddressMode addressMode)
107 case Graphics::SamplerAddressMode::REPEAT:
110 case Graphics::SamplerAddressMode::MIRRORED_REPEAT:
111 o << "MIRRORED_REPEAT";
113 case Graphics::SamplerAddressMode::CLAMP_TO_EDGE:
114 o << "CLAMP_TO_EDGE";
116 case Graphics::SamplerAddressMode::CLAMP_TO_BORDER:
117 o << "CLAMP_TO_BORDER";
119 case Graphics::SamplerAddressMode::MIRROR_CLAMP_TO_EDGE:
120 o << "MIRROR_CLAMP_TO_EDGE";
126 std::ostream& operator<<(std::ostream& o, Graphics::SamplerFilter filterMode)
130 case Graphics::SamplerFilter::LINEAR:
133 case Graphics::SamplerFilter::NEAREST:
140 std::ostream& operator<<(std::ostream& o, Graphics::SamplerMipmapMode mipmapMode)
144 case Graphics::SamplerMipmapMode::NONE:
147 case Graphics::SamplerMipmapMode::LINEAR:
150 case Graphics::SamplerMipmapMode::NEAREST:
157 std::ostream& operator<<(std::ostream& o, const Graphics::SamplerCreateInfo& createInfo)
159 o << "minFilter:" << createInfo.minFilter
160 << " magFilter:" << createInfo.magFilter
161 << " wrapModeU:" << createInfo.addressModeU
162 << " wrapModeV:" << createInfo.addressModeV
163 << " wrapModeW:" << createInfo.addressModeW
164 << " mipMapMode:" << createInfo.mipMapMode;
168 std::ostream& operator<<(std::ostream& o, const Graphics::ColorAttachment& colorAttachment)
170 o << "attachmentId:" << colorAttachment.attachmentId
171 << " layerId:" << colorAttachment.layerId
172 << " levelId:" << colorAttachment.levelId
173 << " texture:" << colorAttachment.texture;
177 std::ostream& operator<<(std::ostream& o, const Graphics::DepthStencilAttachment& depthStencilAttachment)
179 o << "depthTexture:" << depthStencilAttachment.depthTexture
180 << "depthLevel:" << depthStencilAttachment.depthLevel
181 << "stencilTexture:" << depthStencilAttachment.stencilTexture
182 << "stencilLevel:" << depthStencilAttachment.stencilLevel;
186 std::ostream& operator<<(std::ostream& o, const Graphics::FramebufferCreateInfo& createInfo)
188 o << "colorAttachments:";
189 for(auto i = 0u; i < createInfo.colorAttachments.size(); ++i)
191 o << "[" << i << "]=" << createInfo.colorAttachments[i] << " ";
193 o << "depthStencilAttachment:" << createInfo.depthStencilAttachment;
194 o << "size: " << createInfo.size;
198 int GetNumComponents(Graphics::VertexInputFormat vertexFormat)
202 case Graphics::VertexInputFormat::UNDEFINED:
203 case Graphics::VertexInputFormat::FLOAT:
204 case Graphics::VertexInputFormat::INTEGER:
206 case Graphics::VertexInputFormat::IVECTOR2:
207 case Graphics::VertexInputFormat::FVECTOR2:
209 case Graphics::VertexInputFormat::IVECTOR3:
210 case Graphics::VertexInputFormat::FVECTOR3:
212 case Graphics::VertexInputFormat::FVECTOR4:
213 case Graphics::VertexInputFormat::IVECTOR4:
219 GLint GetSize(Graphics::VertexInputFormat vertexFormat)
223 case Graphics::VertexInputFormat::UNDEFINED:
225 case Graphics::VertexInputFormat::INTEGER:
226 case Graphics::VertexInputFormat::IVECTOR2:
227 case Graphics::VertexInputFormat::IVECTOR3:
228 case Graphics::VertexInputFormat::IVECTOR4:
230 case Graphics::VertexInputFormat::FLOAT:
231 case Graphics::VertexInputFormat::FVECTOR2:
232 case Graphics::VertexInputFormat::FVECTOR3:
233 case Graphics::VertexInputFormat::FVECTOR4:
239 GLint GetGlType(Graphics::VertexInputFormat vertexFormat)
243 case Graphics::VertexInputFormat::UNDEFINED:
245 case Graphics::VertexInputFormat::INTEGER:
246 case Graphics::VertexInputFormat::IVECTOR2:
247 case Graphics::VertexInputFormat::IVECTOR3:
248 case Graphics::VertexInputFormat::IVECTOR4:
250 case Graphics::VertexInputFormat::FLOAT:
251 case Graphics::VertexInputFormat::FVECTOR2:
252 case Graphics::VertexInputFormat::FVECTOR3:
253 case Graphics::VertexInputFormat::FVECTOR4:
259 GLenum GetTopology(Graphics::PrimitiveTopology topology)
263 case Graphics::PrimitiveTopology::POINT_LIST:
266 case Graphics::PrimitiveTopology::LINE_LIST:
269 case Graphics::PrimitiveTopology::LINE_LOOP:
272 case Graphics::PrimitiveTopology::LINE_STRIP:
273 return GL_LINE_STRIP;
275 case Graphics::PrimitiveTopology::TRIANGLE_LIST:
278 case Graphics::PrimitiveTopology::TRIANGLE_STRIP:
279 return GL_TRIANGLE_STRIP;
281 case Graphics::PrimitiveTopology::TRIANGLE_FAN:
282 return GL_TRIANGLE_FAN;
287 GLenum GetCullFace(Graphics::CullMode cullMode)
291 case Graphics::CullMode::NONE:
293 case Graphics::CullMode::FRONT:
295 case Graphics::CullMode::BACK:
297 case Graphics::CullMode::FRONT_AND_BACK:
298 return GL_FRONT_AND_BACK;
303 GLenum GetFrontFace(Graphics::FrontFace frontFace)
305 if(frontFace == Graphics::FrontFace::CLOCKWISE)
312 GLenum GetBlendFactor(Graphics::BlendFactor blendFactor)
314 GLenum glFactor = GL_ZERO;
318 case Graphics::BlendFactor::ZERO:
321 case Graphics::BlendFactor::ONE:
324 case Graphics::BlendFactor::SRC_COLOR:
325 glFactor = GL_SRC_COLOR;
327 case Graphics::BlendFactor::ONE_MINUS_SRC_COLOR:
328 glFactor = GL_ONE_MINUS_SRC_COLOR;
330 case Graphics::BlendFactor::DST_COLOR:
331 glFactor = GL_DST_COLOR;
333 case Graphics::BlendFactor::ONE_MINUS_DST_COLOR:
334 glFactor = GL_ONE_MINUS_DST_COLOR;
336 case Graphics::BlendFactor::SRC_ALPHA:
337 glFactor = GL_SRC_ALPHA;
339 case Graphics::BlendFactor::ONE_MINUS_SRC_ALPHA:
340 glFactor = GL_ONE_MINUS_SRC_ALPHA;
342 case Graphics::BlendFactor::DST_ALPHA:
343 glFactor = GL_DST_ALPHA;
345 case Graphics::BlendFactor::ONE_MINUS_DST_ALPHA:
346 glFactor = GL_ONE_MINUS_DST_ALPHA;
348 case Graphics::BlendFactor::CONSTANT_COLOR:
349 glFactor = GL_CONSTANT_COLOR;
351 case Graphics::BlendFactor::ONE_MINUS_CONSTANT_COLOR:
352 glFactor = GL_ONE_MINUS_CONSTANT_COLOR;
354 case Graphics::BlendFactor::CONSTANT_ALPHA:
355 glFactor = GL_CONSTANT_ALPHA;
357 case Graphics::BlendFactor::ONE_MINUS_CONSTANT_ALPHA:
358 glFactor = GL_ONE_MINUS_CONSTANT_ALPHA;
360 case Graphics::BlendFactor::SRC_ALPHA_SATURATE:
361 glFactor = GL_SRC_ALPHA_SATURATE;
363 // GLES doesn't appear to have dual source blending.
364 case Graphics::BlendFactor::SRC1_COLOR:
365 glFactor = GL_SRC_COLOR;
367 case Graphics::BlendFactor::ONE_MINUS_SRC1_COLOR:
368 glFactor = GL_ONE_MINUS_SRC_COLOR;
370 case Graphics::BlendFactor::SRC1_ALPHA:
371 glFactor = GL_SRC_ALPHA;
373 case Graphics::BlendFactor::ONE_MINUS_SRC1_ALPHA:
374 glFactor = GL_ONE_MINUS_SRC_ALPHA;
380 GLenum GetBlendOp(Graphics::BlendOp blendOp)
382 GLenum op = GL_FUNC_ADD;
385 case Graphics::BlendOp::ADD:
388 case Graphics::BlendOp::SUBTRACT:
389 op = GL_FUNC_SUBTRACT;
391 case Graphics::BlendOp::REVERSE_SUBTRACT:
392 op = GL_FUNC_REVERSE_SUBTRACT;
394 case Graphics::BlendOp::MIN:
397 case Graphics::BlendOp::MAX:
400 case Graphics::BlendOp::MULTIPLY:
405 case Graphics::BlendOp::SCREEN:
410 case Graphics::BlendOp::OVERLAY:
415 case Graphics::BlendOp::DARKEN:
420 case Graphics::BlendOp::LIGHTEN:
425 case Graphics::BlendOp::COLOR_DODGE:
430 case Graphics::BlendOp::COLOR_BURN:
435 case Graphics::BlendOp::HARD_LIGHT:
440 case Graphics::BlendOp::SOFT_LIGHT:
445 case Graphics::BlendOp::DIFFERENCE:
450 case Graphics::BlendOp::EXCLUSION:
455 case Graphics::BlendOp::HUE:
460 case Graphics::BlendOp::SATURATION:
462 op = GL_HSL_SATURATION;
465 case Graphics::BlendOp::COLOR:
470 case Graphics::BlendOp::LUMINOSITY:
472 op = GL_HSL_LUMINOSITY;
481 constexpr explicit GLCompareOp(Graphics::CompareOp compareOp)
485 case Graphics::CompareOp::NEVER:
488 case Graphics::CompareOp::LESS:
491 case Graphics::CompareOp::EQUAL:
494 case Graphics::CompareOp::LESS_OR_EQUAL:
497 case Graphics::CompareOp::GREATER:
500 case Graphics::CompareOp::NOT_EQUAL:
503 case Graphics::CompareOp::GREATER_OR_EQUAL:
506 case Graphics::CompareOp::ALWAYS:
516 constexpr explicit GLStencilOp(Graphics::StencilOp stencilOp)
520 case Graphics::StencilOp::KEEP:
523 case Graphics::StencilOp::ZERO:
526 case Graphics::StencilOp::REPLACE:
529 case Graphics::StencilOp::INCREMENT_AND_CLAMP:
532 case Graphics::StencilOp::DECREMENT_AND_CLAMP:
535 case Graphics::StencilOp::INVERT:
538 case Graphics::StencilOp::INCREMENT_AND_WRAP:
541 case Graphics::StencilOp::DECREMENT_AND_WRAP:
549 class TestGraphicsMemory : public Graphics::Memory
552 TestGraphicsMemory(TraceCallStack& callStack, TestGraphicsBuffer& buffer, uint32_t mappedOffset, uint32_t mappedSize)
553 : mCallStack(callStack),
555 mMappedOffset(mappedOffset),
556 mMappedSize(mappedSize),
562 void* LockRegion(uint32_t offset, uint32_t size) override
564 std::ostringstream o;
565 o << offset << ", " << size;
566 mCallStack.PushCall("Memory::LockRegion", o.str());
568 if(offset > mMappedOffset + mMappedSize ||
569 size + offset > mMappedOffset + mMappedSize)
571 fprintf(stderr, "TestGraphics.Memory::LockRegion() Out of bounds");
572 mBuffer.memory.resize(mMappedOffset + offset + size); // Grow to prevent memcpy from crashing
574 mLockedOffset = offset;
576 return &mBuffer.memory[mMappedOffset + offset];
579 void Unlock(bool flush) override
581 mCallStack.PushCall("Memory::Unlock", (flush ? "Flush" : "NoFlush"));
588 void Flush() override
590 mCallStack.PushCall("Memory::Flush", "");
592 mBuffer.Upload(mMappedOffset + mLockedOffset, mLockedSize);
596 TraceCallStack& mCallStack;
597 TestGraphicsBuffer& mBuffer;
598 uint32_t mMappedOffset;
599 uint32_t mMappedSize;
600 uint32_t mLockedOffset;
601 uint32_t mLockedSize;
604 TestGraphicsController::TestGraphicsController()
605 : mCallStack(false, "TestGraphicsController."),
606 mCommandBufferCallStack(false, "TestCommandBuffer."),
607 mFrameBufferCallStack(false, "TestFrameBuffer.")
609 mCallStack.Enable(true);
610 mCommandBufferCallStack.Enable(true);
611 auto& trace = mGl.GetTextureTrace();
613 trace.EnableLogging(false);
616 void TestGraphicsController::SubmitCommandBuffers(const Graphics::SubmitInfo& submitInfo)
618 TraceCallStack::NamedParams namedParams;
619 namedParams["submitInfo"] << "cmdBuffer[" << submitInfo.cmdBuffer.size()
620 << "], flags:" << std::hex << submitInfo.flags;
622 mCallStack.PushCall("SubmitCommandBuffers", "", namedParams);
624 mSubmitStack.emplace_back(submitInfo);
626 for(auto& graphicsCommandBuffer : submitInfo.cmdBuffer)
628 auto commandBuffer = Uncast<TestGraphicsCommandBuffer>(graphicsCommandBuffer);
629 ProcessCommandBuffer(*commandBuffer);
633 void TestGraphicsController::ProcessCommandBuffer(TestGraphicsCommandBuffer& commandBuffer)
635 bool scissorEnabled = false;
636 TestGraphicsFramebuffer* currentFramebuffer{nullptr};
637 TestGraphicsPipeline* currentPipeline{nullptr};
639 for(auto& cmd : commandBuffer.GetCommands())
644 case CommandType::FLUSH:
646 // Nothing to do here
649 case CommandType::BIND_TEXTURES:
651 for(auto& binding : cmd.data.bindTextures.textureBindings)
655 auto texture = Uncast<TestGraphicsTexture>(binding.texture);
656 texture->Bind(binding.binding);
660 auto sampler = Uncast<TestGraphicsSampler>(binding.sampler);
663 sampler->Apply(texture->GetTarget());
667 texture->Prepare(); // Ensure native texture is ready
672 case CommandType::BIND_VERTEX_BUFFERS:
674 for(auto& binding : cmd.data.bindVertexBuffers.vertexBufferBindings)
676 auto graphicsBuffer = binding.buffer;
677 auto vertexBuffer = Uncast<TestGraphicsBuffer>(graphicsBuffer);
678 vertexBuffer->Bind();
682 case CommandType::BIND_INDEX_BUFFER:
684 auto& indexBufferBinding = cmd.data.bindIndexBuffer;
685 if(indexBufferBinding.buffer)
687 auto buffer = Uncast<TestGraphicsBuffer>(indexBufferBinding.buffer);
692 case CommandType::BIND_UNIFORM_BUFFER:
696 auto& bindings = cmd.data.bindUniformBuffers;
697 auto buffer = bindings.standaloneUniformsBufferBinding;
699 // based on reflection, issue gl calls
700 buffer.buffer->BindAsUniformBuffer(static_cast<const TestGraphicsProgram*>(currentPipeline->programState.program), bindings.standaloneUniformsBufferBinding);
704 case CommandType::BIND_SAMPLERS:
708 case CommandType::BIND_PIPELINE:
710 currentPipeline = Uncast<TestGraphicsPipeline>(cmd.data.bindPipeline.pipeline);
711 BindPipeline(currentPipeline);
714 case CommandType::DRAW_NATIVE:
716 auto info = &cmd.data.draw.drawNative.drawNativeInfo;
718 if(info->glesNativeInfo.eglSharedContextStoragePointer)
720 auto* anyContext = reinterpret_cast<std::any*>(info->glesNativeInfo.eglSharedContextStoragePointer);
721 *anyContext = reinterpret_cast<void*>(0x12345678u);
724 CallbackBase::ExecuteReturn<bool>(*info->callback, info->userData);
727 case CommandType::DRAW:
731 if(cmd.data.draw.draw.instanceCount == 0)
733 mGl.DrawArrays(GetTopology(currentPipeline->inputAssemblyState.topology),
734 cmd.data.draw.draw.firstVertex,
735 cmd.data.draw.draw.vertexCount);
739 mGl.DrawArraysInstanced(GetTopology(currentPipeline->inputAssemblyState.topology),
740 cmd.data.draw.draw.firstVertex,
741 cmd.data.draw.draw.vertexCount,
742 cmd.data.draw.draw.instanceCount);
747 case CommandType::DRAW_INDEXED:
751 if(cmd.data.draw.draw.instanceCount == 0)
753 mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
754 static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
756 reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
760 mGl.DrawElementsInstanced(GetTopology(currentPipeline->inputAssemblyState.topology),
761 static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
763 reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex),
764 cmd.data.draw.drawIndexed.instanceCount);
769 case CommandType::DRAW_INDEXED_INDIRECT:
773 mGl.DrawElements(GetTopology(currentPipeline->inputAssemblyState.topology),
774 static_cast<GLsizei>(cmd.data.draw.drawIndexed.indexCount),
776 reinterpret_cast<void*>(cmd.data.draw.drawIndexed.firstIndex));
780 case CommandType::SET_SCISSOR:
784 auto& rect = cmd.data.scissor.region;
785 mGl.Scissor(rect.x, rect.y, rect.width, rect.height);
789 case CommandType::SET_SCISSOR_TEST:
791 if(cmd.data.scissorTest.enable)
793 mGl.Enable(GL_SCISSOR_TEST);
794 scissorEnabled = true;
798 mGl.Disable(GL_SCISSOR_TEST);
799 scissorEnabled = false;
803 case CommandType::SET_VIEWPORT_TEST:
807 case CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
809 auto& rect = cmd.data.viewport.region;
810 mGl.Viewport(rect.x, rect.y, rect.width, rect.height);
814 case CommandType::SET_COLOR_MASK:
816 // Set all channels to the same mask
817 const bool mask = cmd.data.colorMask.enabled;
818 mGl.ColorMask(mask, mask, mask, mask);
821 case CommandType::CLEAR_STENCIL_BUFFER:
823 mGl.Clear(GL_STENCIL_BUFFER_BIT);
826 case CommandType::CLEAR_DEPTH_BUFFER:
828 mGl.Clear(GL_DEPTH_BUFFER_BIT);
832 case CommandType::SET_STENCIL_TEST_ENABLE:
834 if(cmd.data.stencilTest.enabled)
836 mGl.Enable(GL_STENCIL_TEST);
840 mGl.Disable(GL_STENCIL_TEST);
845 case CommandType::SET_STENCIL_FUNC:
847 mGl.StencilFunc(GLCompareOp(cmd.data.stencilFunc.compareOp).op,
848 cmd.data.stencilFunc.reference,
849 cmd.data.stencilFunc.compareMask);
853 case CommandType::SET_STENCIL_WRITE_MASK:
855 mGl.StencilMask(cmd.data.stencilWriteMask.mask);
858 case CommandType::SET_STENCIL_OP:
860 mGl.StencilOp(GLStencilOp(cmd.data.stencilOp.failOp).op,
861 GLStencilOp(cmd.data.stencilOp.depthFailOp).op,
862 GLStencilOp(cmd.data.stencilOp.passOp).op);
866 case CommandType::SET_DEPTH_COMPARE_OP:
868 mGl.DepthFunc(GLCompareOp(cmd.data.depth.compareOp).op);
871 case CommandType::SET_DEPTH_TEST_ENABLE:
873 if(cmd.data.depth.testEnabled)
875 mGl.Enable(GL_DEPTH_TEST);
879 mGl.Disable(GL_DEPTH_TEST);
883 case CommandType::SET_DEPTH_WRITE_ENABLE:
885 mGl.DepthMask(cmd.data.depth.writeEnabled);
889 case CommandType::EXECUTE_COMMAND_BUFFERS:
891 // Process secondary command buffers
892 for(auto& buf : cmd.data.executeCommandBuffers.buffers)
894 ProcessCommandBuffer(*Uncast<TestGraphicsCommandBuffer>(buf));
898 case CommandType::BEGIN_RENDER_PASS:
900 auto renderTarget = Uncast<TestGraphicsRenderTarget>(cmd.data.beginRenderPass.renderTarget);
904 auto fb = renderTarget->mCreateInfo.framebuffer;
907 if(currentFramebuffer != fb)
909 currentFramebuffer = Uncast<TestGraphicsFramebuffer>(fb);
910 currentFramebuffer->Bind();
915 mGl.BindFramebuffer(GL_FRAMEBUFFER, 0);
920 mGl.BindFramebuffer(GL_FRAMEBUFFER, 0);
923 auto& clearValues = cmd.data.beginRenderPass.clearValues;
924 if(clearValues.size() > 0)
926 const auto renderPass = static_cast<TestGraphicsRenderPass*>(cmd.data.beginRenderPass.renderPass);
929 const auto& color0 = renderPass->attachments[0];
931 if(color0.loadOp == Graphics::AttachmentLoadOp::CLEAR)
933 mask |= GL_COLOR_BUFFER_BIT;
935 // Set clear color (todo: cache it!)
936 // Something goes wrong here if Alpha mask is GL_TRUE
937 mGl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
938 mGl.ClearColor(clearValues[0].color.r,
939 clearValues[0].color.g,
940 clearValues[0].color.b,
941 clearValues[0].color.a);
944 // check for depth stencil
945 if(renderPass->attachments.size() > 1)
947 const auto& depthStencil = renderPass->attachments.back();
948 if(depthStencil.loadOp == Graphics::AttachmentLoadOp::CLEAR)
951 uint32_t depthClearColor = 0u;
952 if(clearValues.size() == renderPass->attachments.size())
954 depthClearColor = clearValues.back().depthStencil.depth;
956 mGl.ClearDepthf(depthClearColor);
957 mask |= GL_DEPTH_BUFFER_BIT;
959 if(depthStencil.stencilLoadOp == Graphics::AttachmentLoadOp::CLEAR)
961 uint32_t stencilClearColor = 0u;
962 if(clearValues.size() == renderPass->attachments.size())
964 stencilClearColor = clearValues.back().depthStencil.stencil;
966 mGl.ClearStencil(stencilClearColor);
967 mGl.StencilMask(0xFF); // Clear all the bitplanes (assume 8)
968 mask |= GL_STENCIL_BUFFER_BIT;
974 // Test scissor area and RT size
975 const auto& area = cmd.data.beginRenderPass.renderArea;
979 area.width == renderTarget->mCreateInfo.extent.width &&
980 area.height == renderTarget->mCreateInfo.extent.height)
982 mGl.Disable(GL_SCISSOR_TEST);
987 mGl.Enable(GL_SCISSOR_TEST);
988 mGl.Scissor(cmd.data.beginRenderPass.renderArea.x, cmd.data.beginRenderPass.renderArea.y, cmd.data.beginRenderPass.renderArea.width, cmd.data.beginRenderPass.renderArea.height);
990 mGl.Disable(GL_SCISSOR_TEST);
996 DALI_ASSERT_DEBUG(0 && "BeginRenderPass has no render pass");
1001 case CommandType::END_RENDER_PASS:
1003 if(cmd.data.endRenderPass.syncObject != nullptr)
1005 auto syncObject = Uncast<TestGraphicsSyncObject>(cmd.data.endRenderPass.syncObject);
1006 syncObject->InitializeResource(); // create the sync object.
1014 void TestGraphicsController::BindPipeline(TestGraphicsPipeline* pipeline)
1016 auto& vi = pipeline->vertexInputState;
1017 for(auto& attribute : vi.attributes)
1019 mGl.EnableVertexAttribArray(attribute.location);
1020 uint32_t attributeOffset = attribute.offset;
1021 GLsizei stride = vi.bufferBindings[attribute.binding].stride;
1023 auto rate = vi.bufferBindings[attribute.binding].inputRate;
1025 mGl.VertexAttribPointer(attribute.location,
1026 GetNumComponents(attribute.format),
1027 GetGlType(attribute.format),
1028 GL_FALSE, // Not normalized
1030 reinterpret_cast<void*>(attributeOffset));
1031 if(rate == Graphics::VertexInputRate::PER_VERTEX)
1033 mGl.VertexAttribDivisor(attribute.location, 0);
1035 else if(rate == Graphics::VertexInputRate::PER_INSTANCE)
1037 mGl.VertexAttribDivisor(attribute.location, 1);
1042 auto& rasterizationState = pipeline->rasterizationState;
1043 if(rasterizationState.cullMode == Graphics::CullMode::NONE)
1045 mGl.Disable(GL_CULL_FACE);
1049 mGl.Enable(GL_CULL_FACE);
1050 mGl.CullFace(GetCullFace(rasterizationState.cullMode));
1053 mGl.FrontFace(GetFrontFace(rasterizationState.frontFace));
1056 auto& colorBlendState = pipeline->colorBlendState;
1057 if(colorBlendState.blendEnable)
1059 mGl.Enable(GL_BLEND);
1061 mGl.BlendFuncSeparate(GetBlendFactor(colorBlendState.srcColorBlendFactor),
1062 GetBlendFactor(colorBlendState.dstColorBlendFactor),
1063 GetBlendFactor(colorBlendState.srcAlphaBlendFactor),
1064 GetBlendFactor(colorBlendState.dstAlphaBlendFactor));
1065 if(colorBlendState.colorBlendOp != colorBlendState.alphaBlendOp)
1067 mGl.BlendEquationSeparate(GetBlendOp(colorBlendState.colorBlendOp), GetBlendOp(colorBlendState.alphaBlendOp));
1071 mGl.BlendEquation(GetBlendOp(colorBlendState.colorBlendOp));
1073 mGl.BlendColor(colorBlendState.blendConstants[0],
1074 colorBlendState.blendConstants[1],
1075 colorBlendState.blendConstants[2],
1076 colorBlendState.blendConstants[3]);
1080 mGl.Disable(GL_BLEND);
1083 auto* program = static_cast<const TestGraphicsProgram*>(pipeline->programState.program);
1084 mGl.UseProgram(program->mImpl->mId);
1088 * @brief Presents render target
1089 * @param renderTarget render target to present
1091 void TestGraphicsController::PresentRenderTarget(Graphics::RenderTarget* renderTarget)
1093 auto* rt = static_cast<const TestGraphicsRenderTarget*>(renderTarget);
1094 TraceCallStack::NamedParams namedParams;
1095 namedParams["renderTarget"] << std::hex << renderTarget;
1096 namedParams["surface"] << std::hex << rt->mCreateInfo.surface;
1097 mCallStack.PushCall("PresentRenderTarget", namedParams.str(), namedParams);
1101 * @brief Waits until the GPU is idle
1103 void TestGraphicsController::WaitIdle()
1105 mCallStack.PushCall("WaitIdle", "");
1109 * @brief Lifecycle pause event
1111 void TestGraphicsController::Pause()
1113 mCallStack.PushCall("Pause", "");
1117 * @brief Lifecycle resume event
1119 void TestGraphicsController::Resume()
1121 mCallStack.PushCall("Resume", "");
1124 void TestGraphicsController::Shutdown()
1126 mCallStack.PushCall("Shutdown", "");
1129 void TestGraphicsController::Destroy()
1131 mCallStack.PushCall("Destroy", "");
1134 void TestGraphicsController::UpdateTextures(const std::vector<Graphics::TextureUpdateInfo>& updateInfoList,
1135 const std::vector<Graphics::TextureUpdateSourceInfo>& sourceList)
1137 TraceCallStack::NamedParams namedParams;
1138 namedParams["updateInfoList"] << "[" << updateInfoList.size() << "]:";
1139 namedParams["sourceList"] << "[" << sourceList.size() << "]:";
1141 mCallStack.PushCall("UpdateTextures", "", namedParams);
1143 // Call either TexImage2D or TexSubImage2D
1144 for(unsigned int i = 0; i < updateInfoList.size(); ++i)
1146 auto& updateInfo = updateInfoList[i];
1147 auto& source = sourceList[i];
1149 auto texture = static_cast<TestGraphicsTexture*>(updateInfo.dstTexture);
1150 texture->Bind(0); // Use first texture unit during resource update
1151 texture->Update(updateInfo, source);
1155 void TestGraphicsController::GenerateTextureMipmaps(const Graphics::Texture& texture)
1157 mCallStack.PushCall("GenerateTextureMipmaps", "");
1159 auto gfxTexture = Uncast<TestGraphicsTexture>(&texture);
1160 mGl.BindTexture(gfxTexture->GetTarget(), 0);
1161 mGl.GenerateMipmap(gfxTexture->GetTarget());
1164 bool TestGraphicsController::EnableDepthStencilBuffer(bool enableDepth, bool enableStencil)
1166 TraceCallStack::NamedParams namedParams;
1167 namedParams["enableDepth"] << (enableDepth ? "T" : "F");
1168 namedParams["enableStencil"] << (enableStencil ? "T" : "F");
1169 mCallStack.PushCall("EnableDepthStencilBuffer", "", namedParams);
1173 void TestGraphicsController::RunGarbageCollector(size_t numberOfDiscardedRenderers)
1175 TraceCallStack::NamedParams namedParams;
1176 namedParams["numberOfDiscardedRenderers"] << numberOfDiscardedRenderers;
1177 mCallStack.PushCall("RunGarbageCollector", "", namedParams);
1180 void TestGraphicsController::DiscardUnusedResources()
1182 mCallStack.PushCall("DiscardUnusedResources", "");
1185 bool TestGraphicsController::IsDiscardQueueEmpty()
1187 mCallStack.PushCall("IsDiscardQueueEmpty", "");
1188 return isDiscardQueueEmptyResult;
1192 * @brief Test if the graphics subsystem has resumed & should force a draw
1194 * @return true if the graphics subsystem requires a re-draw
1196 bool TestGraphicsController::IsDrawOnResumeRequired()
1198 mCallStack.PushCall("IsDrawOnResumeRequired", "");
1199 return isDrawOnResumeRequiredResult;
1202 Graphics::UniquePtr<Graphics::Buffer> TestGraphicsController::CreateBuffer(const Graphics::BufferCreateInfo& createInfo, Graphics::UniquePtr<Graphics::Buffer>&& oldBuffer)
1204 TraceCallStack::NamedParams namedParams;
1205 namedParams["usage"] << "0x" << std::hex << createInfo.usage;
1206 namedParams["propertiesFlags"] << createInfo.propertiesFlags;
1207 namedParams["size"] << createInfo.size;
1208 mCallStack.PushCall("CreateBuffer", namedParams.str(), namedParams);
1210 auto ptr = Graphics::MakeUnique<TestGraphicsBuffer, TestGraphicsDeleter<TestGraphicsBuffer>>(createInfo, *this, mGl, mCallStack);
1211 mAllocatedBuffers.push_back(ptr.get());
1215 void TestGraphicsController::DiscardBuffer(TestGraphicsBuffer* buffer)
1217 auto iter = std::find(mAllocatedBuffers.begin(), mAllocatedBuffers.end(), buffer);
1218 if(iter != mAllocatedBuffers.end())
1220 mAllocatedBuffers.erase(iter);
1225 Graphics::UniquePtr<Graphics::CommandBuffer> TestGraphicsController::CreateCommandBuffer(const Graphics::CommandBufferCreateInfo& commandBufferCreateInfo, Graphics::UniquePtr<Graphics::CommandBuffer>&& oldCommandBuffer)
1227 std::ostringstream oss;
1228 oss << "commandBufferCreateInfo:" << commandBufferCreateInfo;
1229 mCallStack.PushCall("CreateCommandBuffer", oss.str());
1230 return Graphics::MakeUnique<TestGraphicsCommandBuffer>(mCommandBufferCallStack, mGl);
1233 Graphics::UniquePtr<Graphics::RenderPass> TestGraphicsController::CreateRenderPass(const Graphics::RenderPassCreateInfo& renderPassCreateInfo, Graphics::UniquePtr<Graphics::RenderPass>&& oldRenderPass)
1235 mCallStack.PushCall("CreateRenderPass", "");
1236 return Graphics::MakeUnique<TestGraphicsRenderPass>(mGl, renderPassCreateInfo);
1239 Graphics::UniquePtr<Graphics::Texture> TestGraphicsController::CreateTexture(const Graphics::TextureCreateInfo& textureCreateInfo, Graphics::UniquePtr<Graphics::Texture>&& oldTexture)
1241 TraceCallStack::NamedParams namedParams;
1242 namedParams["textureCreateInfo"] << textureCreateInfo;
1243 mCallStack.PushCall("CreateTexture", namedParams.str(), namedParams);
1245 return Graphics::MakeUnique<TestGraphicsTexture>(mGl, textureCreateInfo);
1248 Graphics::UniquePtr<Graphics::Framebuffer> TestGraphicsController::CreateFramebuffer(
1249 const Graphics::FramebufferCreateInfo& createInfo,
1250 Graphics::UniquePtr<Graphics::Framebuffer>&& oldFramebuffer)
1252 TraceCallStack::NamedParams namedParams;
1253 namedParams["framebufferCreateInfo"] << createInfo;
1254 mCallStack.PushCall("Controller::CreateFramebuffer", namedParams.str(), namedParams);
1256 return Graphics::MakeUnique<TestGraphicsFramebuffer>(mFrameBufferCallStack, mGl, createInfo);
1259 Graphics::UniquePtr<Graphics::Pipeline> TestGraphicsController::CreatePipeline(const Graphics::PipelineCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Pipeline>&& oldPipeline)
1261 mCallStack.PushCall("CreatePipeline", "");
1262 return std::make_unique<TestGraphicsPipeline>(mGl, pipelineCreateInfo);
1265 Graphics::UniquePtr<Graphics::Program> TestGraphicsController::CreateProgram(const Graphics::ProgramCreateInfo& programCreateInfo, Graphics::UniquePtr<Graphics::Program>&& oldProgram)
1267 mCallStack.PushCall("CreateProgram", "");
1269 for(auto cacheEntry : mProgramCache)
1272 for(auto& shader : *(programCreateInfo.shaderState))
1274 auto graphicsShader = Uncast<TestGraphicsShader>(shader.shader);
1275 std::vector<uint8_t> source;
1276 source.resize(graphicsShader->mCreateInfo.sourceSize);
1277 memcpy(&source[0], graphicsShader->mCreateInfo.sourceData, graphicsShader->mCreateInfo.sourceSize);
1279 if(!std::equal(source.begin(), source.end(), cacheEntry.shaders[shader.pipelineStage].begin(), cacheEntry.shaders[shader.pipelineStage].end()))
1287 return Graphics::MakeUnique<TestGraphicsProgram>(cacheEntry.programImpl);
1291 mProgramCache.emplace_back();
1292 mProgramCache.back().programImpl = new TestGraphicsProgramImpl(mGl, programCreateInfo, mVertexFormats, mCustomUniforms, mCustomUniformBlocks);
1294 for(auto& shader : *(programCreateInfo.shaderState))
1296 auto graphicsShader = Uncast<TestGraphicsShader>(shader.shader);
1297 mProgramCache.back().shaders[shader.pipelineStage].resize(graphicsShader->mCreateInfo.sourceSize);
1298 memcpy(&mProgramCache.back().shaders[shader.pipelineStage][0], graphicsShader->mCreateInfo.sourceData, graphicsShader->mCreateInfo.sourceSize);
1300 return Graphics::MakeUnique<TestGraphicsProgram>(mProgramCache.back().programImpl);
1303 Graphics::UniquePtr<Graphics::Shader> TestGraphicsController::CreateShader(const Graphics::ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr<Graphics::Shader>&& oldShader)
1305 mCallStack.PushCall("CreateShader", "");
1306 return Graphics::MakeUnique<TestGraphicsShader>(mGl, shaderCreateInfo);
1309 Graphics::UniquePtr<Graphics::Sampler> TestGraphicsController::CreateSampler(const Graphics::SamplerCreateInfo& samplerCreateInfo, Graphics::UniquePtr<Graphics::Sampler>&& oldSampler)
1311 TraceCallStack::NamedParams namedParams;
1312 namedParams["samplerCreateInfo"] << samplerCreateInfo;
1313 mCallStack.PushCall("CreateSampler", namedParams.str(), namedParams);
1315 return Graphics::MakeUnique<TestGraphicsSampler>(mGl, samplerCreateInfo);
1318 Graphics::UniquePtr<Graphics::RenderTarget> TestGraphicsController::CreateRenderTarget(const Graphics::RenderTargetCreateInfo& renderTargetCreateInfo, Graphics::UniquePtr<Graphics::RenderTarget>&& oldRenderTarget)
1320 TraceCallStack::NamedParams namedParams;
1321 namedParams["surface"] << std::hex << renderTargetCreateInfo.surface;
1322 mCallStack.PushCall("CreateRenderTarget", namedParams.str(), namedParams);
1324 return Graphics::MakeUnique<TestGraphicsRenderTarget>(mGl, renderTargetCreateInfo);
1327 Graphics::UniquePtr<Graphics::SyncObject> TestGraphicsController::CreateSyncObject(
1328 const Graphics::SyncObjectCreateInfo& syncObjectCreateInfo,
1329 Graphics::UniquePtr<Graphics::SyncObject>&& oldSyncObject)
1331 mCallStack.PushCall("CreateSyncObject", "");
1332 return Graphics::MakeUnique<TestGraphicsSyncObject>(mGraphicsSyncImpl, syncObjectCreateInfo);
1335 Graphics::UniquePtr<Graphics::Memory> TestGraphicsController::MapBufferRange(const Graphics::MapBufferInfo& mapInfo)
1337 mCallStack.PushCall("MapBufferRange", "");
1339 auto buffer = static_cast<TestGraphicsBuffer*>(mapInfo.buffer);
1340 buffer->memory.resize(mapInfo.offset + mapInfo.size); // For initial testing, allow writes past capacity
1342 return std::make_unique<TestGraphicsMemory>(mCallStack, *buffer, mapInfo.offset, mapInfo.size);
1345 Graphics::UniquePtr<Graphics::Memory> TestGraphicsController::MapTextureRange(const Graphics::MapTextureInfo& mapInfo)
1347 mCallStack.PushCall("MapTextureRange", "");
1351 void TestGraphicsController::UnmapMemory(Graphics::UniquePtr<Graphics::Memory> memory)
1353 mCallStack.PushCall("UnmapMemory", "");
1356 Graphics::MemoryRequirements TestGraphicsController::GetTextureMemoryRequirements(Graphics::Texture& texture) const
1358 mCallStack.PushCall("GetTextureMemoryRequirements", "");
1359 return Graphics::MemoryRequirements{};
1362 Graphics::MemoryRequirements TestGraphicsController::GetBufferMemoryRequirements(Graphics::Buffer& buffer) const
1364 static GLint uniformAlign{0};
1366 Graphics::MemoryRequirements reqs{};
1367 mCallStack.PushCall("GetBufferMemoryRequirements", "");
1369 auto gfxBuffer = Uncast<TestGraphicsBuffer>(&buffer);
1370 if(gfxBuffer->mCreateInfo.usage & (0 | Graphics::BufferUsage::UNIFORM_BUFFER))
1374 // Throw off the shackles of constness
1375 auto& gl = *const_cast<TestGlAbstraction*>(&mGl);
1376 gl.GetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &uniformAlign);
1378 reqs.size = gfxBuffer->mCreateInfo.size;
1379 reqs.alignment = uint32_t(uniformAlign);
1384 Graphics::TextureProperties TestGraphicsController::GetTextureProperties(const Graphics::Texture& texture)
1386 static Graphics::TextureProperties textureProperties{};
1387 mCallStack.PushCall("GetTextureProperties", "");
1389 return textureProperties;
1392 const Graphics::Reflection& TestGraphicsController::GetProgramReflection(const Graphics::Program& program)
1394 mCallStack.PushCall("GetProgramReflection", "");
1396 return static_cast<const TestGraphicsProgram*>(&program)->GetReflection();
1399 bool TestGraphicsController::PipelineEquals(const Graphics::Pipeline& pipeline0, const Graphics::Pipeline& pipeline1) const
1401 mCallStack.PushCall("PipelineEquals", "");
1405 bool TestGraphicsController::GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData)
1407 mCallStack.PushCall("GetProgramParameter", "");
1408 auto graphicsProgram = Uncast<TestGraphicsProgram>(&program);
1409 return graphicsProgram->GetParameter(parameterId, outData);