Merge "Fix svace issue - Application Destructor & egl controller debug" into devel...
[platform/core/uifw/dali-adaptor.git] / dali / internal / graphics / gles-impl / egl-graphics-controller-debug.cpp
1 /*
2  * Copyright (c) 2022 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 <dali/internal/graphics/gles-impl/egl-graphics-controller-debug.h>
18 #include <cstdio>
19 #include <queue>
20
21 namespace Dali::Graphics
22 {
23 #if defined(DEBUG_ENABLED)
24 std::string DumpCompareOp(Graphics::CompareOp compareOp)
25 {
26   switch(compareOp)
27   {
28     case Graphics::CompareOp::NEVER:
29       return "Graphics::CompareOp::NEVER";
30       break;
31     case Graphics::CompareOp::LESS:
32       return "Graphics::CompareOp::LESS";
33       break;
34     case Graphics::CompareOp::EQUAL:
35       return "Graphics::CompareOp::EQUAL";
36       break;
37     case Graphics::CompareOp::LESS_OR_EQUAL:
38       return "Graphics::CompareOp::LESS_OR_EQUAL";
39       break;
40     case Graphics::CompareOp::GREATER:
41       return "Graphics::CompareOp::GREATER";
42       break;
43     case Graphics::CompareOp::NOT_EQUAL:
44       return "Graphics::CompareOp::NOT_EQUAL";
45       break;
46     case Graphics::CompareOp::GREATER_OR_EQUAL:
47       return "Graphics::CompareOp::GREATER_OR_EQUAL";
48       break;
49     case Graphics::CompareOp::ALWAYS:
50       return "Graphics::CompareOp::ALWAYS";
51       break;
52   }
53   return "UNKNOWN";
54 }
55
56 std::string DumpStencilOp(Graphics::StencilOp stencilOp)
57 {
58   switch(stencilOp)
59   {
60     case Graphics::StencilOp::KEEP:
61       return "Graphics::StencilOp::KEEP";
62       break;
63     case Graphics::StencilOp::ZERO:
64       return "Graphics::StencilOp::ZERO";
65       break;
66     case Graphics::StencilOp::REPLACE:
67       return "Graphics::StencilOp::REPLACE";
68       break;
69     case Graphics::StencilOp::INCREMENT_AND_CLAMP:
70       return "Graphics::StencilOp::INCREMENT_AND_CLAMP";
71       break;
72     case Graphics::StencilOp::DECREMENT_AND_CLAMP:
73       return "Graphics::StencilOp::DECREMENT_AND_CLAMP";
74       break;
75     case Graphics::StencilOp::INVERT:
76       return "Graphics::StencilOp::INVERT";
77       break;
78     case Graphics::StencilOp::INCREMENT_AND_WRAP:
79       return "Graphics::StencilOp::INCREMENT_AND_WRAP";
80       break;
81     case Graphics::StencilOp::DECREMENT_AND_WRAP:
82       return "Graphics::StencilOp::DECREMENT_AND_WRAP";
83       break;
84   }
85   return "UNKNOWN";
86 }
87
88 void DumpCommandBuffer(FILE* output, const GLES::CommandBuffer* commandBuffer)
89 {
90   bool       first{true};
91   uint32_t   count   = 0u;
92   const auto command = commandBuffer->GetCommands(count);
93   for(auto i = 0u; i < count; ++i)
94   {
95     auto& cmd = command[i];
96     if(!first)
97     {
98       fprintf(output, ",");
99     }
100     first = false;
101     // process command
102     switch(cmd.type)
103     {
104       case GLES::CommandType::FLUSH:
105       {
106         fprintf(output, "{\"Cmd\":\"FLUSH\"}\n");
107         break;
108       }
109       case GLES::CommandType::BIND_TEXTURES:
110       {
111         fprintf(output, "{\"Cmd\":\"BIND_TEXTURES\"}\n");
112         break;
113       }
114       case GLES::CommandType::BIND_VERTEX_BUFFERS:
115       {
116         fprintf(output, "{\"Cmd\":\"BIND_VERTEX_BUFFERS\"}\n");
117         break;
118       }
119       case GLES::CommandType::BIND_UNIFORM_BUFFER:
120       {
121         fprintf(output, "{\"Cmd\":\"BIND_UNIFORM_BUFFERS\"}\n");
122         break;
123       }
124       case GLES::CommandType::BIND_INDEX_BUFFER:
125       {
126         fprintf(output, "{\"Cmd\":\"BIND_INDEX_BUFFERS\"}\n");
127         break;
128       }
129       case GLES::CommandType::BIND_SAMPLERS:
130       {
131         fprintf(output, "{\"Cmd\":\"BIND_SAMPLERS\"}\n");
132         break;
133       }
134       case GLES::CommandType::BIND_PIPELINE:
135       {
136         fprintf(output, "{\"Cmd\":\"BIND_PIPELINE\"}\n");
137         break;
138       }
139       case GLES::CommandType::DRAW:
140       {
141         fprintf(output, "{\"Cmd\":\"DRAW\"}\n");
142         break;
143       }
144       case GLES::CommandType::DRAW_INDEXED:
145       {
146         fprintf(output, "{\"Cmd\":\"DRAW_INDEXED\"}\n");
147         break;
148       }
149       case GLES::CommandType::DRAW_NATIVE:
150       {
151         fprintf(output, "{\"Cmd\":\"DRAW_NATIVE\"}\n");
152         break;
153       }
154       case GLES::CommandType::DRAW_INDEXED_INDIRECT:
155       {
156         fprintf(output, "{\"Cmd\":\"DRAW_INDEXED_INDIRECT\"}\n");
157         break;
158       }
159       case GLES::CommandType::SET_SCISSOR: // @todo Consider correcting for orientation here?
160       {
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);
162         break;
163       }
164       case GLES::CommandType::SET_SCISSOR_TEST:
165       {
166         fprintf(output, "{\"Cmd\":\"SET_SCISSOR_TEST\",\n\"enable\":%s\n}\n", (cmd.scissorTest.enable ? "\"true\"" : "\"false\""));
167         break;
168       }
169       case GLES::CommandType::SET_VIEWPORT: // @todo Consider correcting for orientation here?
170       {
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);
172         break;
173       }
174       case GLES::CommandType::SET_COLOR_MASK:
175       {
176         fprintf(output, "{\"Cmd\":\"SET_COLOR_MASK\",\n\"enable\":%s\n}\n", (cmd.colorMask.enabled ? "\"true\"" : "\"false\""));
177         break;
178       }
179       case GLES::CommandType::CLEAR_STENCIL_BUFFER:
180       {
181         fprintf(output, "{\"Cmd\":\"CLEAR_STENCIL_BUFFER\"}\n");
182         break;
183       }
184       case GLES::CommandType::CLEAR_DEPTH_BUFFER:
185       {
186         fprintf(output, "{\"Cmd\":\"CLEAR_DEPTH_BUFFER\"}\n");
187         break;
188       }
189
190       case GLES::CommandType::SET_STENCIL_TEST_ENABLE:
191       {
192         fprintf(output, "{\"Cmd\":\"SET_STENCIL_TEST_ENABLE\",\n\"enable\":%s\n}\n", (cmd.stencilTest.enabled ? "\"true\"" : "\"false\""));
193         break;
194       }
195
196       case GLES::CommandType::SET_STENCIL_FUNC:
197       {
198         fprintf(output,
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);
206         break;
207       }
208
209       case GLES::CommandType::SET_STENCIL_WRITE_MASK:
210       {
211         fprintf(output, "{\"Cmd\":\"SET_STENCIL_WRITE_MASK\",\n\"mask\":%d\n}\n", cmd.stencilWriteMask.mask);
212         break;
213       }
214
215       case GLES::CommandType::SET_STENCIL_OP:
216       {
217         fprintf(output,
218                 "{\"Cmd\":\"SET_STENCIL_OP\",\n"
219                 "\"failOp\":\"%s\",\n"
220                 "\"depthFailOp\":\"%s\",\n"
221                 "\"passOp\":\"%s\"\n}",
222
223                 DumpStencilOp(cmd.stencilOp.failOp).c_str(),
224                 DumpStencilOp(cmd.stencilOp.depthFailOp).c_str(),
225                 DumpStencilOp(cmd.stencilOp.passOp).c_str());
226         break;
227       }
228
229       case GLES::CommandType::SET_DEPTH_COMPARE_OP:
230       {
231         fprintf(output,
232                 "{\"Cmd\":\"SET_DEPTH_COMPARE_OP\",\n"
233                 "\"compareOp\":\"%s\"\n}\n",
234                 DumpCompareOp(cmd.depth.compareOp).c_str());
235         break;
236       }
237       case GLES::CommandType::SET_DEPTH_TEST_ENABLE:
238       {
239         fprintf(output, "{\"Cmd\":\"SET_DEPTH_TEST_ENABLE\",\n\"enable\":%s\n}\n", (cmd.depth.testEnabled ? "\"true\"" : "\"false\""));
240         break;
241       }
242       case GLES::CommandType::SET_DEPTH_WRITE_ENABLE:
243       {
244         fprintf(output, "{\"Cmd\":\"SET_DEPTH_WRITE_ENABLE\",\n\"enable\":%s\n}\n", (cmd.depth.writeEnabled ? "\"true\"" : "\"false\""));
245         break;
246       }
247
248       case GLES::CommandType::BEGIN_RENDERPASS:
249       {
250         fprintf(output,
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\":[");
262         bool firstV = true;
263         for(auto i = 0u; i < cmd.beginRenderPass.clearValuesCount; ++i)
264         {
265           auto value = cmd.beginRenderPass.clearValues.Ptr()[i];
266           if(!firstV)
267           {
268             fprintf(output, ",");
269           }
270           firstV = false;
271           fprintf(output, "[%f,%f,%f,%f]", value.color.r, value.color.g, value.color.b, value.color.a);
272         }
273         fprintf(output, "]\n}");
274         break;
275       }
276       case GLES::CommandType::END_RENDERPASS:
277       {
278         fprintf(output, "{\"Cmd\":\"END_RENDER_PASS\"}\n");
279         break;
280       }
281       case GLES::CommandType::PRESENT_RENDER_TARGET:
282       {
283         fprintf(output, "{\"Cmd\":\"PRESENT_RENDER_TARGET\"}\n");
284         break;
285       }
286       case GLES::CommandType::EXECUTE_COMMAND_BUFFERS:
287       {
288         fprintf(output, "{\"Cmd\":\"EXECUTE_COMMAND_BUFFERS\",\n\"buffers\":[");
289         bool firstBuf{true};
290         for(auto i = 0u; i < cmd.executeCommandBuffers.buffersCount; ++i)
291         {
292           const auto buf = cmd.executeCommandBuffers.buffers.Ptr()[i];
293           if(!firstBuf)
294           {
295             fprintf(output, ", ");
296           }
297           firstBuf = false;
298           DumpCommandBuffer(output, buf);
299         }
300         fprintf(output, "]\n}");
301         break;
302       }
303     }
304   }
305 }
306
307 GraphicsFrameDump::GraphicsFrameDump()
308 : outputStream(nullptr, nullptr)
309 {
310   char* outfile = getenv("GRAPHICS_CMDBUF_OUTFILE");
311   if(outfile)
312   {
313     outputStream = UniqueFilePtr(std::fopen(outfile, "w"), std::fclose);
314     output       = outputStream.get();
315   }
316   if(!output)
317     output = stderr;
318 }
319
320 void GraphicsFrameDump::Start()
321 {
322   if(IsDumpFrame())
323   {
324     if(!firstFrame)
325     {
326       fprintf(output, ", \n");
327     }
328     firstFrame   = false;
329     firstBuffer  = true;
330     dumpingFrame = true;
331     fprintf(output, "{\"Queue #%d\":[\n", frameCount);
332   }
333 }
334
335 void GraphicsFrameDump::DumpCommandBuffer(const GLES::CommandBuffer* cmdBuf)
336 {
337   if(dumpingFrame)
338   {
339     if(!firstBuffer)
340     {
341       fprintf(output, ", \n");
342     }
343     firstBuffer = false;
344     fprintf(output, "[\n");
345     Graphics::DumpCommandBuffer(output, cmdBuf);
346     fprintf(output, "]\n");
347   }
348 }
349
350 void GraphicsFrameDump::End()
351 {
352   if(dumpingFrame)
353   {
354     fprintf(output, "]}\n");
355   }
356   firstBuffer  = true;
357   dumpingFrame = false;
358 }
359
360 bool GraphicsFrameDump::IsDumpFrame()
361 {
362   bool dump = false;
363
364   frameCount++;
365
366   dump = (frameCount < NTH_FRAME);
367
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.
370
371   return dump;
372 }
373 #endif
374 } // namespace Dali::Graphics