1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     dev_Screenshot.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: 31311 $
16  *---------------------------------------------------------------------------*/
17 
18 #include <nw/dev/dev_Screenshot.h>
19 #include <nn/gx.h>
20 #include <nw/os/os_Memory.h>
21 
22 #if defined(NW_DEV_ENABLED) && defined(NW_PLATFORM_CTR)
23 
24 namespace nw
25 {
26 
27 namespace dev
28 {
29 
30 //--------------------------------------------------------------------------
31 Screenshot*
Create(nw::os::IAllocator * allocator,size_t maxLength)32 Screenshot::Create(
33     nw::os::IAllocator* allocator,
34     size_t maxLength)
35 {
36     const int HASH_LENGTH = 20;
37 
38     u32* hash = allocator->AllocAndFill(HASH_LENGTH, static_cast<u32>(0));
39     NW_NULL_ASSERT(hash);
40 
41     NW_ASSERT(maxLength != 0);
42     u8* copyScreen = allocator->AllocAndFill(maxLength, static_cast<u8>(0));
43     NW_NULL_ASSERT(copyScreen);
44 
45     void* memory = allocator->Alloc(sizeof(Screenshot));
46     NW_NULL_ASSERT(memory);
47 
48     return new(memory) Screenshot(
49         allocator,
50         copyScreen,
51         maxLength,
52         hash);
53 }
54 
55 //--------------------------------------------------------------------------
~Screenshot()56 Screenshot::~Screenshot()
57 {
58     if (this->m_Allocator)
59     {
60         if (this->m_CopyScreen)
61         {
62             (this->m_Allocator)->Free(this->m_CopyScreen);
63         }
64 
65         if (this->m_Hash)
66         {
67             (this->m_Allocator)->Free(this->m_Hash);
68         }
69     }
70 }
71 
72 //--------------------------------------------------------------------------
73 void
Set(const DisplayDescription & displayDescription,void * srcScreen,int length,int width,int height)74 Screenshot::Set(const DisplayDescription& displayDescription, void* srcScreen, int length, int width, int height)
75 {
76     std::memcpy(m_CopyScreen, srcScreen, length);
77     this->m_DisplayDescription = displayDescription;
78     this->m_Length = length;
79     this->m_Writed = true;
80     this->m_Width = width;
81     this->m_Height = height;
82 
83     nn::crypto::CalculateSha1(this->m_Hash, m_CopyScreen, m_Length);
84 }
85 
86 //--------------------------------------------------------------------------
87 void
DumpHash() const88 Screenshot::DumpHash() const
89 {
90     const char* DISPLAY_0     = "NN_GX_DISPLAY0   ";
91     const char* DISPLAY_0_EXT = "NN_GX_DISPLAY0EXT";
92     const char* DISPLAY_1     = "NN_GX_DISPLAY1   ";
93 
94     const char* display;
95 
96     switch (this->m_DisplayDescription.display)
97     {
98     case NN_GX_DISPLAY0:
99         display = DISPLAY_0;
100         break;
101     case NN_GX_DISPLAY0_EXT:
102         display = DISPLAY_0_EXT;
103         break;
104     case NN_GX_DISPLAY1:
105         display = DISPLAY_1;
106         break;
107     default:
108         NW_FATAL_ERROR("Unsupported display type");
109     }
110 
111     NW_DEV_LOG("|%s|0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x|\n", display, m_Hash[0], m_Hash[1], m_Hash[2], m_Hash[3], m_Hash[4]);
112 }
113 
114 //--------------------------------------------------------------------------
115 ScreenshotManager*
Create(nw::os::IAllocator * allocator,int maxScreenshot,int memorySize)116 ScreenshotManager::Create(
117     nw::os::IAllocator* allocator,
118     int maxScreenshot,
119     int memorySize
120 )
121 {
122     NW_UNUSED_VARIABLE(maxScreenshot);
123 
124     void* memory = allocator->Alloc(sizeof(Screenshot));
125     ScreenshotArray screenshots = ScreenshotArray(maxScreenshot, allocator);
126 
127     for (int i = 0; i < maxScreenshot; i++)
128     {
129         screenshots.push_back(Screenshot::Create(allocator, memorySize));
130     }
131 
132     return new(memory) ScreenshotManager(allocator, screenshots);
133 }
134 
135 //--------------------------------------------------------------------------
136 void
Destroy(nw::os::IAllocator * allocator)137 ScreenshotManager::Destroy(nw::os::IAllocator* allocator)
138 {
139     this->~ScreenshotManager();
140     allocator->Free(this);
141 }
142 
143 //--------------------------------------------------------------------------
ScreenshotManager(nw::os::IAllocator * allocator,ScreenshotArray screenshots)144 ScreenshotManager::ScreenshotManager(
145     nw::os::IAllocator* allocator,
146     ScreenshotArray screenshots
147 )
148 : m_Allocator(allocator),
149   m_Screenshots(screenshots),
150   m_NextWrited(0)
151 {
152 }
153 
154 //--------------------------------------------------------------------------
~ScreenshotManager()155 ScreenshotManager::~ScreenshotManager()
156 {
157     this->ClearScreenshots();
158 }
159 
160 //--------------------------------------------------------------------------
161 int
Take(GLenum display,int offsetX,int offsetY)162 ScreenshotManager::Take(
163     GLenum display,
164     int offsetX,
165     int offsetY)
166 {
167     DisplayDescription displayDescription;
168     displayDescription.display = display;
169 
170     nngxActiveDisplay(display);
171 
172     GLint address;
173     nngxGetDisplaybufferParameteri(NN_GX_DISPLAYBUFFER_ADDRESS, &address);
174     void* srcArea = reinterpret_cast<void*>(address);
175     nngxGetDisplaybufferParameteri(NN_GX_DISPLAYBUFFER_FORMAT, &displayDescription.format);
176     nngxGetDisplaybufferParameteri(NN_GX_DISPLAYBUFFER_WIDTH, &displayDescription.width);
177     nngxGetDisplaybufferParameteri(NN_GX_DISPLAYBUFFER_HEIGHT, &displayDescription.height);
178 
179     displayDescription.offsetX = offsetX;
180     displayDescription.offsetY = offsetY;
181 
182     if (displayDescription.format == 0 || displayDescription.width == 0 || displayDescription.height == 0)
183     {
184         return -1;
185     }
186 
187     int length = CalcMemorySize(displayDescription.format, displayDescription.width, displayDescription.height);
188 
189     ScreenshotRange range  = this->GetScreenshots();
190 
191     if (m_NextWrited < m_Screenshots.size())
192     {
193         Screenshot* screenshot = m_Screenshots[m_NextWrited];
194         screenshot->Set(displayDescription, srcArea, length, displayDescription.width, displayDescription.height);
195     }
196     else
197     {
198         return -1;
199     }
200 
201     ++m_NextWrited;
202     if (m_NextWrited >= m_Screenshots.size())
203     {
204         m_NextWrited = 0;
205     }
206 
207     return m_NextWrited;
208 }
209 
210 //--------------------------------------------------------------------------
211 void
ClearScreenshots()212 ScreenshotManager::ClearScreenshots()
213 {
214     ScreenshotRange range  = this->GetScreenshots();
215 
216     for (ScreenshotArray::iterator iter = range.first;
217          iter != range.second;
218          ++iter)
219     {
220         Screenshot* screenshot = *iter;
221         if (screenshot != NULL)
222         {
223             screenshot->~Screenshot();
224             m_Allocator->Free(screenshot);
225         }
226     }
227 
228     this->m_Screenshots.clear();
229 }
230 
231 } // namespace nw::dev
232 } // namespace nw
233 
234 #endif // NW_DEV_ENABLED
235