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