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