2 * Copyright (c) 2022 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 <dali/internal/graphics/gles-impl/egl-graphics-controller-debug.h>
21 namespace Dali::Graphics
23 #if defined(DEBUG_ENABLED)
24 std::string DumpCompareOp(Graphics::CompareOp compareOp)
28 case Graphics::CompareOp::NEVER:
29 return "Graphics::CompareOp::NEVER";
31 case Graphics::CompareOp::LESS:
32 return "Graphics::CompareOp::LESS";
34 case Graphics::CompareOp::EQUAL:
35 return "Graphics::CompareOp::EQUAL";
37 case Graphics::CompareOp::LESS_OR_EQUAL:
38 return "Graphics::CompareOp::LESS_OR_EQUAL";
40 case Graphics::CompareOp::GREATER:
41 return "Graphics::CompareOp::GREATER";
43 case Graphics::CompareOp::NOT_EQUAL:
44 return "Graphics::CompareOp::NOT_EQUAL";
46 case Graphics::CompareOp::GREATER_OR_EQUAL:
47 return "Graphics::CompareOp::GREATER_OR_EQUAL";
49 case Graphics::CompareOp::ALWAYS:
50 return "Graphics::CompareOp::ALWAYS";
56 std::string DumpStencilOp(Graphics::StencilOp stencilOp)
60 case Graphics::StencilOp::KEEP:
61 return "Graphics::StencilOp::KEEP";
63 case Graphics::StencilOp::ZERO:
64 return "Graphics::StencilOp::ZERO";
66 case Graphics::StencilOp::REPLACE:
67 return "Graphics::StencilOp::REPLACE";
69 case Graphics::StencilOp::INCREMENT_AND_CLAMP:
70 return "Graphics::StencilOp::INCREMENT_AND_CLAMP";
72 case Graphics::StencilOp::DECREMENT_AND_CLAMP:
73 return "Graphics::StencilOp::DECREMENT_AND_CLAMP";
75 case Graphics::StencilOp::INVERT:
76 return "Graphics::StencilOp::INVERT";
78 case Graphics::StencilOp::INCREMENT_AND_WRAP:
79 return "Graphics::StencilOp::INCREMENT_AND_WRAP";
81 case Graphics::StencilOp::DECREMENT_AND_WRAP:
82 return "Graphics::StencilOp::DECREMENT_AND_WRAP";
88 void DumpCommandBuffer(FILE* output, const GLES::CommandBuffer* commandBuffer)
92 const auto command = commandBuffer->GetCommands(count);
93 for(auto i = 0u; i < count; ++i)
95 auto& cmd = command[i];
104 case GLES::CommandType::FLUSH:
106 fprintf(output, "{\"Cmd\":\"FLUSH\"}\n");
109 case GLES::CommandType::BIND_TEXTURES:
111 fprintf(output, "{\"Cmd\":\"BIND_TEXTURES\"}\n");
114 case GLES::CommandType::BIND_VERTEX_BUFFERS:
116 fprintf(output, "{\"Cmd\":\"BIND_VERTEX_BUFFERS\"}\n");
119 case GLES::CommandType::BIND_UNIFORM_BUFFER:
121 fprintf(output, "{\"Cmd\":\"BIND_UNIFORM_BUFFERS\"}\n");
124 case GLES::CommandType::BIND_INDEX_BUFFER:
126 fprintf(output, "{\"Cmd\":\"BIND_INDEX_BUFFERS\"}\n");
129 case GLES::CommandType::BIND_SAMPLERS:
131 fprintf(output, "{\"Cmd\":\"BIND_SAMPLERS\"}\n");
134 case GLES::CommandType::BIND_PIPELINE:
136 fprintf(output, "{\"Cmd\":\"BIND_PIPELINE\"}\n");
139 case GLES::CommandType::DRAW:
141 fprintf(output, "{\"Cmd\":\"DRAW\"}\n");
144 case GLES::CommandType::DRAW_INDEXED:
146 fprintf(output, "{\"Cmd\":\"DRAW_INDEXED\"}\n");
149 case GLES::CommandType::DRAW_NATIVE:
151 fprintf(output, "{\"Cmd\":\"DRAW_NATIVE\"}\n");
154 case GLES::CommandType::DRAW_INDEXED_INDIRECT:
156 fprintf(output, "{\"Cmd\":\"DRAW_INDEXED_INDIRECT\"}\n");
159 case GLES::CommandType::SET_SCISSOR: // @todo Consider correcting for orientation here?
161 fprintf(output, "{\"Cmd\":\"SET_SCISSOR\",\n\"region\":[%d,%d,%d,%d]\n}\n", cmd.scissor.region.x, cmd.scissor.region.y, cmd.scissor.region.width, cmd.scissor.region.height);
164 case GLES::CommandType::SET_SCISSOR_TEST:
166 fprintf(output, "{\"Cmd\":\"SET_SCISSOR_TEST\",\n\"enable\":%s\n}\n", (cmd.scissorTest.enable ? "\"true\"" : "\"false\""));
169 case GLES::CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
171 fprintf(output, "{\"Cmd\":\"SET_VIEWPORT\",\n\"region\":[%f,%f,%f,%f]\n}\n", cmd.viewport.region.x, cmd.viewport.region.y, cmd.viewport.region.width, cmd.viewport.region.height);
174 case GLES::CommandType::SET_COLOR_MASK:
176 fprintf(output, "{\"Cmd\":\"SET_COLOR_MASK\",\n\"enable\":%s\n}\n", (cmd.colorMask.enabled ? "\"true\"" : "\"false\""));
179 case GLES::CommandType::CLEAR_STENCIL_BUFFER:
181 fprintf(output, "{\"Cmd\":\"CLEAR_STENCIL_BUFFER\"}\n");
184 case GLES::CommandType::CLEAR_DEPTH_BUFFER:
186 fprintf(output, "{\"Cmd\":\"CLEAR_DEPTH_BUFFER\"}\n");
190 case GLES::CommandType::SET_STENCIL_TEST_ENABLE:
192 fprintf(output, "{\"Cmd\":\"SET_STENCIL_TEST_ENABLE\",\n\"enable\":%s\n}\n", (cmd.stencilTest.enabled ? "\"true\"" : "\"false\""));
196 case GLES::CommandType::SET_STENCIL_FUNC:
199 "{\"Cmd\":\"STENCIL_FUNC\",\n"
200 "\"compareOp\":\"%s\",\n"
201 "\"reference\":\"0x%x\",\n"
202 "\"compareMask\":\"0x%x\"\n}",
203 DumpCompareOp(cmd.stencilFunc.compareOp).c_str(),
204 cmd.stencilFunc.reference,
205 cmd.stencilFunc.compareMask);
209 case GLES::CommandType::SET_STENCIL_WRITE_MASK:
211 fprintf(output, "{\"Cmd\":\"SET_STENCIL_WRITE_MASK\",\n\"mask\":%d\n}\n", cmd.stencilWriteMask.mask);
215 case GLES::CommandType::SET_STENCIL_OP:
218 "{\"Cmd\":\"SET_STENCIL_OP\",\n"
219 "\"failOp\":\"%s\",\n"
220 "\"depthFailOp\":\"%s\",\n"
221 "\"passOp\":\"%s\"\n}",
223 DumpStencilOp(cmd.stencilOp.failOp).c_str(),
224 DumpStencilOp(cmd.stencilOp.depthFailOp).c_str(),
225 DumpStencilOp(cmd.stencilOp.passOp).c_str());
229 case GLES::CommandType::SET_DEPTH_COMPARE_OP:
232 "{\"Cmd\":\"SET_DEPTH_COMPARE_OP\",\n"
233 "\"compareOp\":\"%s\"\n}\n",
234 DumpCompareOp(cmd.depth.compareOp).c_str());
237 case GLES::CommandType::SET_DEPTH_TEST_ENABLE:
239 fprintf(output, "{\"Cmd\":\"SET_DEPTH_TEST_ENABLE\",\n\"enable\":%s\n}\n", (cmd.depth.testEnabled ? "\"true\"" : "\"false\""));
242 case GLES::CommandType::SET_DEPTH_WRITE_ENABLE:
244 fprintf(output, "{\"Cmd\":\"SET_DEPTH_WRITE_ENABLE\",\n\"enable\":%s\n}\n", (cmd.depth.writeEnabled ? "\"true\"" : "\"false\""));
248 case GLES::CommandType::BEGIN_RENDERPASS:
251 "{\"Cmd\":\"BEGIN_RENDER_PASS\",\n"
252 "\"renderTarget\":\"%p\",\n"
253 "\"renderPass\":\"%p\",\n"
254 "\"renderArea\":[%d,%d,%d,%d],\n",
255 cmd.beginRenderPass.renderTarget,
256 cmd.beginRenderPass.renderPass,
257 cmd.beginRenderPass.renderArea.x,
258 cmd.beginRenderPass.renderArea.y,
259 cmd.beginRenderPass.renderArea.width,
260 cmd.beginRenderPass.renderArea.height);
261 fprintf(output, "\"clearValues\":[");
263 for(auto i = 0u; i < cmd.beginRenderPass.clearValuesCount; ++i)
265 auto value = cmd.beginRenderPass.clearValues.Ptr()[i];
268 fprintf(output, ",");
271 fprintf(output, "[%f,%f,%f,%f]", value.color.r, value.color.g, value.color.b, value.color.a);
273 fprintf(output, "]\n}");
276 case GLES::CommandType::END_RENDERPASS:
278 fprintf(output, "{\"Cmd\":\"END_RENDER_PASS\"}\n");
281 case GLES::CommandType::PRESENT_RENDER_TARGET:
283 fprintf(output, "{\"Cmd\":\"PRESENT_RENDER_TARGET\"}\n");
286 case GLES::CommandType::EXECUTE_COMMAND_BUFFERS:
288 fprintf(output, "{\"Cmd\":\"EXECUTE_COMMAND_BUFFERS\",\n\"buffers\":[");
290 for(auto i = 0u; i < cmd.executeCommandBuffers.buffersCount; ++i)
292 const auto buf = cmd.executeCommandBuffers.buffers.Ptr()[i];
295 fprintf(output, ", ");
298 DumpCommandBuffer(output, buf);
300 fprintf(output, "]\n}");
307 GraphicsFrameDump::GraphicsFrameDump()
308 : outputStream(nullptr, nullptr)
310 char* outfile = getenv("GRAPHICS_CMDBUF_OUTFILE");
313 outputStream = UniqueFilePtr(std::fopen(outfile, "w"), std::fclose);
314 output = outputStream.get();
320 void GraphicsFrameDump::Start()
326 fprintf(output, ", \n");
331 fprintf(output, "{\"Queue #%d\":[\n", frameCount);
335 void GraphicsFrameDump::DumpCommandBuffer(const GLES::CommandBuffer* cmdBuf)
341 fprintf(output, ", \n");
344 fprintf(output, "[\n");
345 Graphics::DumpCommandBuffer(output, cmdBuf);
346 fprintf(output, "]\n");
350 void GraphicsFrameDump::End()
354 fprintf(output, "]}\n");
357 dumpingFrame = false;
360 bool GraphicsFrameDump::IsDumpFrame()
366 dump = (frameCount < NTH_FRAME);
368 // Or, could also use an enviroment variable as a trigger
369 // e.g. if getenv(X) is set, then start dumping again, and clear X.
374 } // namespace Dali::Graphics