1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     demo_AutoTester.cpp
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: $
16  *---------------------------------------------------------------------------*/
17 
18 #include <nw/types.h>
19 #include <nw/os.h>
20 #include <nw/ut/ut_Inlines.h>
21 #include <nw/demo/demo_DebugUtility.h>
22 
23 #include <nn/fs.h>
24 
25 
26 namespace nw {
27 namespace demo {
28 
29 DebugUtility::AutoTester* DebugUtility::s_AutoTester = NULL;
30 
31 //----------------------------------------
32 DebugUtility::AutoTester*
Create(os::IAllocator * allocator,os::IAllocator * deviceAllocator)33 DebugUtility::AutoTester::Create(
34     os::IAllocator* allocator,
35     os::IAllocator* deviceAllocator
36 )
37 {
38     void* memory = allocator->Alloc(sizeof(AutoTester));
39 
40     NW_NULL_ASSERT(memory);
41 
42     AutoTester* autoTester = new(memory) AutoTester(allocator, deviceAllocator);
43 
44     return autoTester;
45 }
46 
47 //----------------------------------------
48 int
Initialize(s32 channelNumber,bool needCustom,nw::demo::RenderSystem ** renderSystem,const u32 * correctHashDisplay0,const u32 * correctHashDisplay1)49 DebugUtility::AutoTester::Initialize(
50     s32 channelNumber,
51     bool needCustom,
52     nw::demo::RenderSystem** renderSystem,
53     const u32* correctHashDisplay0,
54     const u32* correctHashDisplay1
55 )
56 {
57     m_RenderSystem = renderSystem;
58 
59     nw::demo::HioPacketChannel::Initialize(m_DeviceAllocator);
60 
61     m_HioPacketChannel = nw::demo::HioPacketChannel::Builder()
62         .ChannelNumber(channelNumber)
63         .Create(m_Allocator, m_DeviceAllocator);
64 
65     NW_NULL_ASSERT(m_HioPacketChannel);
66 
67     if (m_HioPacketChannel->Listen(needCustom ? -1 : 0)) {
68         // 接続に成功したので、カスタムテストの初期化を開始します。
69         size_t headerWrittenSize;
70         size_t dataWrittenSize;
71 
72         TestInfoHeader testInfoHeader;
73         m_HioPacketChannel->ReceivePacket(
74             &headerWrittenSize,
75             &dataWrittenSize,
76             &testInfoHeader,
77             sizeof(testInfoHeader),
78             NULL,
79             0,
80             -1
81         );
82 
83         NW_ASSERT(testInfoHeader.packetType == TestInfoHeader::PACKET_TYPE_ID);
84 
85         // シナリオを受信します
86         m_Scenario = nw::ut::MoveArray<TestEvent>(testInfoHeader.eventCount, m_Allocator);
87         m_Scenario.resize(testInfoHeader.eventCount);
88 
89         ScenarioHeader scenarioHeader;
90         m_HioPacketChannel->ReceivePacket(
91             &headerWrittenSize,
92             &dataWrittenSize,
93             &scenarioHeader,
94             sizeof(scenarioHeader),
95             &m_Scenario[0],
96             sizeof(TestEvent) * m_Scenario.size(),
97             -1
98         );
99         NW_ASSERT(scenarioHeader.packetType == ScenarioHeader::PACKET_TYPE_ID);
100 
101         DebugUtility::SetSilentMode(true);
102 
103         nw::demo::PadFactory::GetPad()->EnableTestMode(true);
104     }
105     else
106     {
107         // 接続できなかったので、デフォルトテストの初期化を開始します。
108         nw::ut::SafeDestroy(m_HioPacketChannel);
109         nw::demo::HioPacketChannel::Finalize();
110 
111         m_Scenario = nw::ut::MoveArray<TestEvent>(2, m_Allocator);
112 
113         TestEvent event;
114 
115         event.frameCount = 60;
116         event.eventType = EVENT_SCREENSHOT;
117         event.param.screenshot.display = ScreenshotParam::DISPLAY_0;
118         for (int i=0;i<5;++i)
119         {
120             if (correctHashDisplay0)
121             {
122                 event.param.screenshot.hash[i] = correctHashDisplay0[i];
123             }
124             else
125             {
126                 event.param.screenshot.hash[i] = 0;
127             }
128         }
129         m_Scenario.push_back(event);
130 
131         event.param.screenshot.display = ScreenshotParam::DISPLAY_1;
132         for (int i=0;i<5;++i)
133         {
134             if (correctHashDisplay1)
135             {
136                 event.param.screenshot.hash[i] = correctHashDisplay1[i];
137             }
138             else
139             {
140                 event.param.screenshot.hash[i] = 0;
141             }
142         }
143         m_Scenario.push_back(event);
144 
145         nw::demo::PadFactory::GetPad()->EnableTestMode(false);
146     }
147 
148     m_ScreenshotManager = nw::dev::ScreenshotManager::Create(
149         m_Allocator,
150         1,
151         nw::dev::CalcMemorySize(GL_RGBA8_OES, 400, 320)
152     );
153     NW_POINTER_ASSERT(m_ScreenshotManager);
154 
155     m_FrameCount = 0;
156     m_CurrentEvent = m_Scenario.begin();
157 
158     return 0;
159 }
160 
161 //----------------------------------------
162 void
Finalize()163 DebugUtility::AutoTester::Finalize()
164 {
165     if (m_HioPacketChannel)
166     {
167         m_HioPacketChannel->Disconnect();
168         nw::ut::SafeDestroy(m_HioPacketChannel);
169         nw::demo::HioPacketChannel::Finalize();
170     }
171 }
172 
173 //----------------------------------------
174 void
Destroy()175 DebugUtility::AutoTester::Destroy()
176 {
177     nw::os::IAllocator* allocator = m_Allocator;
178 
179     this->~AutoTester();
180     allocator->Free(this);
181 }
182 
183 //----------------------------------------
184 void
AdvanceFrame()185 DebugUtility::AutoTester::AdvanceFrame()
186 {
187     while (m_CurrentEvent != m_Scenario.end() && m_CurrentEvent->frameCount == m_FrameCount)
188     {
189         switch (m_CurrentEvent->eventType)
190         {
191         case EVENT_SCREENSHOT:
192             SendScreenshot(m_CurrentEvent->param.screenshot);
193             break;
194         case EVENT_SET_PAD_STATUS:
195             SetPadStatus(m_CurrentEvent->param.setPadStatus);
196             break;
197         case EVENT_BEACON:
198             SendBeacon(m_CurrentEvent->param.beacon);
199             break;
200         case EVENT_SEND_LOAD_METER:
201             SendLoadMeter(m_CurrentEvent->param.sendLoadMeter);
202             break;
203         case EVENT_RESET_LOAD_METER:
204             if (m_RenderSystem)
205             {
206                 (*m_RenderSystem)->ResetCumulativeLoadMeter();
207             }
208             break;
209         case EVENT_TEST_DONE:
210             NotifyDone();
211             break;
212         case EVENT_SWITCH_CPU_PROFILING_MODE:
213             SwitchCpuProfilingMode(m_CurrentEvent->param.switchCpuProfilingMode);
214             break;
215         default:
216             NW_FATAL_ERROR("Unsupported test event");
217         }
218 
219         ++m_CurrentEvent;
220     }
221 
222     ++m_FrameCount;
223 }
224 
225 //----------------------------------------
226 void
SendScreenshot(const ScreenshotParam & param)227 DebugUtility::AutoTester::SendScreenshot(
228     const ScreenshotParam& param
229 )
230 {
231     int screenshotIndex;
232 
233     switch (param.display)
234     {
235     case ScreenshotParam::DISPLAY_0:
236         screenshotIndex = m_ScreenshotManager->Take(NN_GX_DISPLAY0);
237         break;
238     case ScreenshotParam::DISPLAY_0_EXT:
239         screenshotIndex = m_ScreenshotManager->Take(NN_GX_DISPLAY0_EXT);
240         break;
241     case ScreenshotParam::DISPLAY_1:
242         screenshotIndex = m_ScreenshotManager->Take(NN_GX_DISPLAY1);
243         break;
244     case ScreenshotParam::DISPLAY_0_BOTH:
245         {
246             ScreenshotParam eachParam = param;
247             eachParam.display = ScreenshotParam::DISPLAY_0;
248             SendScreenshot(eachParam);
249             eachParam.display = ScreenshotParam::DISPLAY_0_EXT;
250             SendScreenshot(eachParam);
251             return;
252         }
253     case ScreenshotParam::DISPLAY_ALL:
254         {
255             ScreenshotParam eachParam = param;
256             eachParam.display = ScreenshotParam::DISPLAY_0;
257             SendScreenshot(eachParam);
258             eachParam.display = ScreenshotParam::DISPLAY_0_EXT;
259             SendScreenshot(eachParam);
260             eachParam.display = ScreenshotParam::DISPLAY_1;
261             SendScreenshot(eachParam);
262             return;
263         }
264     default:
265         NW_ASSERT(false);
266     }
267 
268     if (screenshotIndex < 0)
269     {
270         if (m_HioPacketChannel)
271         {
272             ScreenshotHeader header;
273             header.frameCount = m_FrameCount;
274             header.width = 0;
275             header.height = 0;
276             header.display = param.display;
277             m_HioPacketChannel->SendPacket(
278                 &header,
279                 sizeof(header),
280                 NULL,
281                 0
282             );
283         }
284         return;
285     }
286 
287     nw::dev::Screenshot* shotDisplay = m_ScreenshotManager->GetScreenshot(screenshotIndex);
288 
289     if (m_HioPacketChannel)
290     {
291         ScreenshotHeader header;
292         header.frameCount = m_FrameCount;
293         header.width = shotDisplay->GetWidth();
294         header.height = shotDisplay->GetHeight();
295         header.display = param.display;
296         m_HioPacketChannel->SendPacket(
297             &header,
298             sizeof(header),
299             shotDisplay->GetBuffer(),
300             shotDisplay->GetBufferLength()
301         );
302     }
303     else
304     {
305         if (m_CurrentEvent->param.screenshot.hash[0] ||
306             m_CurrentEvent->param.screenshot.hash[0] ||
307             m_CurrentEvent->param.screenshot.hash[0] ||
308             m_CurrentEvent->param.screenshot.hash[0] ||
309             m_CurrentEvent->param.screenshot.hash[0] )
310         {
311 
312             const bool result = shotDisplay->Equal(m_CurrentEvent->param.screenshot.hash);
313 
314             if (result)
315             {
316                 NW_DEV_LOG("NW_SCREENSHOT_TEST: OK\n");
317                 shotDisplay->DumpHash();
318             }
319             else
320             {
321                 NW_DEV_LOG("NW_SCREENSHOT_TEST: NG\n");
322                 shotDisplay->DumpHash();
323             }
324         }
325     }
326 }
327 
328 //----------------------------------------
329 void
SetPadStatus(const SetPadStatusParam & param)330 DebugUtility::AutoTester::SetPadStatus(
331     const SetPadStatusParam& param
332 )
333 {
334     nw::demo::PadFactory::GetPad()->SetTestPadStatus(param.padStatus);
335 }
336 
337 //----------------------------------------
338 void
SendBeacon(const BeaconParam & param)339 DebugUtility::AutoTester::SendBeacon(
340     const BeaconParam& param
341 )
342 {
343     NW_UNUSED_VARIABLE(param);
344     if (m_HioPacketChannel)
345     {
346         BeaconHeader header;
347         header.frameCount = m_FrameCount;
348         m_HioPacketChannel->SendPacket(
349             &header,
350             sizeof(header),
351             NULL,
352             0
353         );
354     }
355 }
356 
357 //----------------------------------------
358 void
SendLoadMeter(const SendLoadMeterParam & param)359 DebugUtility::AutoTester::SendLoadMeter(
360     const SendLoadMeterParam& param
361 )
362 {
363     NW_UNUSED_VARIABLE(param);
364     if (m_HioPacketChannel)
365     {
366         LoadMeterHeader header;
367         header.frameCount = m_FrameCount;
368 
369         LoadMeterData data;
370         if (m_RenderSystem)
371         {
372             data.callCount = (*m_RenderSystem)->GetCumulativeLoadMeter().callCount;
373             data.cpuTime = static_cast<s32>( (*m_RenderSystem)->GetCumulativeLoadMeter().cumulativeTime * 1000 );
374             data.gpuTime = static_cast<s32>( (*m_RenderSystem)->GetCumulativeLoadMeter().cumulativeGpuTime * 1000 );
375             data.otherGpuTime = 0;
376             data.cmdSize = static_cast<s32>( (*m_RenderSystem)->GetCumulativeLoadMeter().drawCommandBufferSize );
377         }
378         else
379         {
380             data.callCount = 0;
381             data.cpuTime = 0;
382             data.gpuTime = 0;
383             data.otherGpuTime = 0;
384             data.cmdSize = 0;
385         }
386 
387         m_HioPacketChannel->SendPacket(
388             &header,
389             sizeof(header),
390             &data,
391             sizeof(data)
392         );
393     }
394 }
395 
396 //----------------------------------------
397 void
NotifyDone()398 DebugUtility::AutoTester::NotifyDone()
399 {
400     if (m_HioPacketChannel)
401     {
402         DoneHeader header;
403         header.frameCount = m_FrameCount;
404         m_HioPacketChannel->SendPacket(
405             &header,
406             sizeof(header),
407             NULL,
408             0
409         );
410     }
411 }
412 
413 //----------------------------------------
414 void
SwitchCpuProfilingMode(const SwitchCpuProfilingModeParam & param)415 DebugUtility::AutoTester::SwitchCpuProfilingMode(const SwitchCpuProfilingModeParam& param)
416 {
417     DebugUtility::s_IsForceCpuProfilingMode = bool(param.isModeEnabled);
418 }
419 
420 //----------------------------------------
421 void
NotifyMemoryLeak(s32 deviceLeakSize,s32 particleLeakSize)422 DebugUtility::AutoTester::NotifyMemoryLeak(
423     s32 deviceLeakSize,
424     s32 particleLeakSize
425 )
426 {
427     if (m_HioPacketChannel)
428     {
429         MemoryLeakHeader header;
430         header.frameCount = 0;
431 
432         MemoryLeakData data;
433         data.deviceLeakSize = deviceLeakSize;
434         data.particleLeakSize = particleLeakSize;
435 
436         m_HioPacketChannel->SendPacket(
437             &header,
438             sizeof(header),
439             &data,
440             sizeof(data)
441         );
442     }
443 }
444 
445 //----------------------------------------------------------
446 void
NotifyMemoryStatus(nw::demo::DemoAllocator * deviceAllocator,nw::demo::DemoAllocator * particleAllocator,NOTIFY_TIMING timing)447 DebugUtility::AutoTester::NotifyMemoryStatus(
448     nw::demo::DemoAllocator* deviceAllocator,
449     nw::demo::DemoAllocator* particleAllocator,
450     NOTIFY_TIMING timing
451 )
452 {
453     if (m_HioPacketChannel)
454     {
455         MemoryStatusHeader header;
456         header.frameCount = 0;
457         header.timing = timing;
458 
459         MemoryStatusData data;
460         data.deviceMemoryUsed = deviceAllocator->GetTotalSize() - deviceAllocator->GetFreeSize();
461         if (particleAllocator)
462         {
463             data.particleMemoryUsed = particleAllocator->GetTotalSize() - particleAllocator->GetFreeSize();
464         }
465         else
466         {
467             data.particleMemoryUsed = 0;
468         }
469 
470         m_HioPacketChannel->SendPacket(
471             &header,
472             sizeof(header),
473             &data,
474             sizeof(data)
475             );
476     }
477 }
478 
479 //----------------------------------------
AutoTester(os::IAllocator * allocator,os::IAllocator * deviceAllocator)480 DebugUtility::AutoTester::AutoTester(
481     os::IAllocator* allocator,
482     os::IAllocator* deviceAllocator
483 )
484 : m_Allocator(allocator),
485   m_DeviceAllocator(deviceAllocator),
486   m_ScreenshotManager(NULL),
487   m_HioPacketChannel(NULL),
488   m_FrameCount(0),
489   m_RenderSystem(NULL)
490 {
491 }
492 
493 //----------------------------------------
~AutoTester()494 DebugUtility::AutoTester::~AutoTester()
495 {
496     m_ScreenshotManager->Destroy(m_Allocator);
497 }
498 
499 } // namespace demo
500 } // namespace nw
501