1 /*---------------------------------------------------------------------------*
2 Project: Horizon
3 File: gx_DrawTexture2d.cpp
4
5 Copyright (C)2009-2012 Nintendo Co., Ltd. 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 $Rev: 47228 $
14 *---------------------------------------------------------------------------*/
15
16 #include <nn.h>
17 #include <nn/types.h>
18 #include <nn/dbg.h>
19
20 #include <nn/os/os_Memory.h>
21 #include <nn/os/os_MemoryTypes.h>
22 #include <nn/fnd/fnd_ExpHeap.h>
23
24 #include <nn/gx.h>
25 #include <nn/fs.h>
26 #include <nn/applet.h>
27
28 #include "demo.h"
29
30 namespace
31 {
32 demo::RenderSystemDrawing s_RenderSystem;
33
34 nn::fnd::ExpHeap s_AppHeap;
35 uptr s_HeapForGx;
36 const u32 s_GxHeapSize = 0x400000;
37 }
38
39 typedef __packed struct BitmapFileHeader
40 {
41 u8 bfType[2];
42 u16 bfSize[2];
43 u16 bfReserved1;
44 u16 bfReserved2;
45 u16 bfOffBits[2];
46 } BitmapFileHeader;
47
48 typedef __packed struct BitmapInfoHeader
49 {
50 u32 biSize;
51 s32 biWidth;
52 s32 biHeight;
53 u16 biPlanes;
54 u16 biBitCount;
55 u32 biCompression;
56 u32 biSizeImage;
57 s32 biXPixPerMeter;
58 s32 biYPixPerMeter;
59 u32 biClrUsed;
60 u32 biClrImportant;
61 } BitmapInfoHeader;
62
63 // Texture0
64 GLuint s_BmpTexture0Id = 0;
65 u32 s_Bmp0Width = 0;
66 u32 s_Bmp0Height = 0;
67 u32 s_Texture0Width = 0;
68 u32 s_Texture0Height = 0;
69
70 // Texture1
71 GLuint s_BmpTexture1Id = 0;
72 u32 s_Bmp1Width = 0;
73 u32 s_Bmp1Height = 0;
74 u32 s_Texture1Width = 0;
75 u32 s_Texture1Height = 0;
76
77 void Initialize(void);
78 void Finalize(void);
79
80 void LoadTexture0(void);
81 void DeleteTexture0(void);
82 void LoadTexture1(void);
83 void DeleteTexture1(void);
84 u8* GetTextureData(const wchar_t* bmpRomFilename,
85 u32& bmpWidth, u32& bmpHeight, u32& textureWidth, u32& textureHeight);
86 u8* GetBmpFileData(u8* rawDataBuffer, u32& bmpWidth, u32& bmpHeight);
87 u8* GetTextureDataFromBmpFileData(const u32& bmpWidth, const u32& bmpHeight, u8* bmpDataBuffer,
88 u32& textureWidth, u32& textureHeight);
89 u32 GetTextureLength(const u32& imageLength);
90
91 bool DrawFrame(void);
92 void DrawDisplay0(void);
93 void DrawDisplay1(void);
94
95
Initialize(void)96 void Initialize(void)
97 {
98 // fs initialization
99 nn::fs::Initialize();
100
101 const size_t ROMFS_BUFFER_SIZE = 1024 * 64;
102 static char buffer[ROMFS_BUFFER_SIZE];
103 NN_UTIL_PANIC_IF_FAILED(
104 nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE));
105
106 s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(),
107 nn::os::GetDeviceMemorySize() );
108 s_HeapForGx = reinterpret_cast<uptr>(s_AppHeap.Allocate(s_GxHeapSize));
109
110 s_RenderSystem.Initialize(s_HeapForGx, s_GxHeapSize);
111
112 LoadTexture0();
113 LoadTexture1();
114 }
115
Finalize(void)116 void Finalize(void)
117 {
118 DeleteTexture0();
119 DeleteTexture1();
120
121 s_RenderSystem.Finalize();
122
123 s_AppHeap.Free(reinterpret_cast<void*>(s_HeapForGx));
124
125 s_AppHeap.Finalize();
126 }
127
LoadTexture0(void)128 void LoadTexture0(void)
129 {
130 if ( s_BmpTexture0Id != 0 )
131 {
132 DeleteTexture0();
133 }
134
135 wchar_t* bmpRomFilename = L"rom:/tulip.bmp";
136 u8* textureDataPtr = GetTextureData(bmpRomFilename,
137 s_Bmp0Width, s_Bmp0Height, s_Texture0Width, s_Texture0Height);
138
139 GLenum target = GL_TEXTURE_2D;
140 GLenum internalFormat = GL_RGB_NATIVE_DMP;
141 GLenum format = GL_RGB_NATIVE_DMP;
142 GLenum type = GL_UNSIGNED_BYTE;
143 GLuint textureId = 0;
144
145 s_RenderSystem.GenerateTexture(target,
146 internalFormat, s_Texture0Width, s_Texture0Height,
147 format, type, textureDataPtr, textureId);
148
149 if ( textureId != 0 )
150 {
151 s_BmpTexture0Id = textureId;
152 NN_LOG(" Create texture (id = %d)\n", textureId);
153 }
154
155 s_AppHeap.Free(textureDataPtr);
156 }
157
DeleteTexture0(void)158 void DeleteTexture0(void)
159 {
160 if ( s_BmpTexture0Id != 0 )
161 {
162 bool flag = s_RenderSystem.DeleteTexture(s_BmpTexture0Id);
163 if ( flag )
164 {
165 NN_LOG(" Delete texture. (id = %d)\n", s_BmpTexture0Id);
166 s_BmpTexture0Id = 0;
167 }
168 else
169 {
170 NN_TPANIC_(" Failed to delete texture. (id = %d)\n", s_BmpTexture0Id);
171 }
172 }
173 }
174
LoadTexture1(void)175 void LoadTexture1(void)
176 {
177 if ( s_BmpTexture1Id != 0 )
178 {
179 DeleteTexture1();
180 }
181
182 wchar_t* bmpRomFilename = L"rom:/dandelion.bmp";
183 u8* textureDataPtr = GetTextureData(bmpRomFilename,
184 s_Bmp1Width, s_Bmp1Height, s_Texture1Width, s_Texture1Height);
185
186 GLenum target = GL_TEXTURE_2D;
187 GLenum internalFormat = GL_RGB_NATIVE_DMP;
188 GLenum format = GL_RGB_NATIVE_DMP;
189 GLenum type = GL_UNSIGNED_BYTE;
190 GLuint textureId = 0;
191
192 s_RenderSystem.GenerateTexture(target,
193 internalFormat, s_Texture1Width, s_Texture1Height,
194 format, type, textureDataPtr, textureId);
195
196 if ( textureId != 0 )
197 {
198 s_BmpTexture1Id = textureId;
199 NN_LOG(" Create texture. (id = %d)\n", textureId);
200 }
201
202 s_AppHeap.Free(textureDataPtr);
203 }
204
DeleteTexture1(void)205 void DeleteTexture1(void)
206 {
207 if ( s_BmpTexture1Id != 0 )
208 {
209 bool flag = s_RenderSystem.DeleteTexture(s_BmpTexture1Id);
210 if ( flag )
211 {
212 NN_LOG(" Delete texture. (id = %d)\n", s_BmpTexture1Id);
213 s_BmpTexture1Id = 0;
214 }
215 else
216 {
217 NN_TPANIC_("Failed to delete texture. (id = %d)\n", s_BmpTexture1Id);
218 }
219 }
220 }
221
GetTextureData(const wchar_t * bmpRomFilename,u32 & bmpWidth,u32 & bmpHeight,u32 & textureWidth,u32 & textureHeight)222 u8* GetTextureData(const wchar_t* bmpRomFilename,
223 u32& bmpWidth, u32& bmpHeight,
224 u32& textureWidth, u32& textureHeight)
225 {
226 NN_LOG("\nReading data from ROMFS...\n");
227
228 nn::fs::FileReader file(bmpRomFilename);
229
230 size_t fileSize = file.GetSize();
231 NN_LOG(" fileSize = %d (Byte)\n", fileSize);
232 if ( fileSize == 0 )
233 {
234 NN_TPANIC_("Failed to open BMP file.\n");
235 return NULL;
236 }
237
238 void* buf = s_AppHeap.Allocate( fileSize, 4 );
239
240 s32 readSize = file.Read(buf, fileSize);
241 NN_LOG(" file readSize = %d (Byte)\n", readSize);
242 if ( readSize == 0 )
243 {
244 NN_TPANIC_("Failed to open BMP file.\n");
245 return NULL;
246 }
247
248 u8* bmpDataBuffer = NULL;
249 bmpDataBuffer = GetBmpFileData((u8*)buf, bmpWidth, bmpHeight);
250 NN_LOG(" bmpWidth = %d, bmpHeight = %d\n", bmpWidth, bmpHeight);
251
252 u8* textureDataBuffer = NULL;
253 textureDataBuffer = GetTextureDataFromBmpFileData(bmpWidth, bmpHeight, bmpDataBuffer,
254 textureWidth, textureHeight);
255 NN_LOG(" textureWidth = %d, textureHeight = %d\n", textureWidth, textureHeight);
256
257 file.Finalize();
258 s_AppHeap.Free(buf);
259
260 return textureDataBuffer;
261 }
262
GetBmpFileData(u8 * rawDataBuffer,u32 & bmpWidth,u32 & bmpHeight)263 u8* GetBmpFileData(u8* rawDataBuffer,
264 u32& bmpWidth, u32& bmpHeight)
265 {
266 BitmapInfoHeader* bmp_info_header_ptr = (BitmapInfoHeader*)(rawDataBuffer + sizeof(BitmapFileHeader));
267 bmpWidth = bmp_info_header_ptr->biWidth;
268 bmpHeight = bmp_info_header_ptr->biHeight;
269 u8* bmpDataBuffer = rawDataBuffer + sizeof(BitmapFileHeader) + sizeof(BitmapInfoHeader);
270
271 return bmpDataBuffer;
272 }
273
GetTextureDataFromBmpFileData(const u32 & bmpWidth,const u32 & bmpHeight,u8 * bmpDataBuffer,u32 & textureWidth,u32 & textureHeight)274 u8* GetTextureDataFromBmpFileData(const u32& bmpWidth, const u32& bmpHeight, u8* bmpDataBuffer,
275 u32& textureWidth, u32& textureHeight)
276 {
277 // Convert BMP to OpenGL RGB format
278 textureWidth = GetTextureLength(bmpWidth);
279 textureHeight = GetTextureLength(bmpHeight);
280 u8* textureGLDataBuffer = reinterpret_cast<u8*>( s_AppHeap.Allocate(3 * textureWidth * textureHeight) );
281
282 for (u32 y = 0; y < textureHeight; y++)
283 {
284 for (u32 x = 0; x < textureWidth; x++)
285 {
286 u8* textureDataPtr = textureGLDataBuffer;
287 textureDataPtr += 3 * ((static_cast<u32>(textureWidth) * y) + x);
288 if ( ( x >= bmpWidth ) || ( y >= bmpHeight ) )
289 {
290 (*textureDataPtr) = 0x00;
291 textureDataPtr += 1;
292
293 (*textureDataPtr) = 0x00;
294 textureDataPtr += 1;
295
296 (*textureDataPtr) = 0x00;
297 }
298 else
299 {
300 u8* bmpDataPtr = bmpDataBuffer;
301 bmpDataPtr += 3 * (bmpWidth * y + x);
302
303 (*textureDataPtr) = (*(bmpDataPtr + 2));
304 textureDataPtr += 1;
305 (*textureDataPtr) = (*(bmpDataPtr + 1));
306 textureDataPtr += 1;
307
308 (*textureDataPtr) = (*(bmpDataPtr + 0));
309 }
310 }
311 }
312
313 u8* textureDataBuffer = reinterpret_cast<u8*>( s_AppHeap.Allocate(3 * textureWidth * textureHeight) );
314
315 // Convert OpenGL RGB format to PICA Native RGB format
316 GLenum format = GL_RGB_NATIVE_DMP;
317 bool result = demo::ConvertGLTextureToNative(
318 format, textureWidth, textureHeight,
319 textureGLDataBuffer, textureDataBuffer);
320 if ( result )
321 {
322 NN_LOG(" Conversion to GL_RGB_NATIVE_DMP succeeded.\n");
323 }
324 else
325 {
326 NN_TPANIC_(" Conversion to GL_RGB_NATIVE_DMP failed.\n");
327 }
328
329 s_AppHeap.Free(textureGLDataBuffer);
330
331 return textureDataBuffer;
332 }
333
GetTextureLength(const u32 & imageLength)334 u32 GetTextureLength(const u32& imageLength)
335 {
336 u32 textureLength = 8;
337
338 // 8, 16, 32, 64, 128, 256, 512, 1024
339 for (u32 i = 0; i < 7; i++)
340 {
341 if ( imageLength > textureLength )
342 {
343 textureLength *= 2;
344 }
345 else
346 {
347 return textureLength;
348 }
349 }
350
351 return 1024;
352 }
353
DrawFrame(void)354 bool DrawFrame(void)
355 {
356 DrawDisplay0();
357 DrawDisplay1();
358
359 s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH);
360
361 return true;
362 }
363
DrawDisplay0(void)364 void DrawDisplay0(void)
365 {
366 s_RenderSystem.SetClearColor(NN_GX_DISPLAY0, 0.0f, 1.0f, 0.0f, 1.0f);
367 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0);
368 s_RenderSystem.Clear();
369
370 s_RenderSystem.SetColor(0.0f, 1.0f, 0.0f, 0.0f);
371
372 f32 windowCoordinateX = 0.0f;
373 f32 windowCoordinateY = 0.0f;
374 f32 rectangleWidth = 400.0f;
375 f32 rectangleHeight = 240.0f;
376 s_RenderSystem.FillTexturedRectangle(s_BmpTexture0Id,
377 windowCoordinateX, windowCoordinateY,
378 rectangleWidth, rectangleHeight,
379 s_Bmp0Width, s_Bmp0Height,
380 s_Texture0Width, s_Texture0Height);
381
382 s_RenderSystem.SwapBuffers();
383 }
384
DrawDisplay1(void)385 void DrawDisplay1(void)
386 {
387 s_RenderSystem.SetClearColor(NN_GX_DISPLAY1, 0.0f, 0.0f, 1.0f, 0.0f);
388 s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1);
389 s_RenderSystem.Clear();
390
391 f32 windowCoordinateX = 0.0f;
392 f32 windowCoordinateY = 0.0f;
393 f32 rectangleWidth = 320.0f;
394 f32 rectangleHeight = 240.0f;
395 s_RenderSystem.FillTexturedRectangle(s_BmpTexture1Id,
396 windowCoordinateX, windowCoordinateY,
397 rectangleWidth, rectangleHeight,
398 s_Bmp1Width, s_Bmp1Height,
399 s_Texture1Width, s_Texture1Height);
400
401 s_RenderSystem.SwapBuffers();
402 }
403
nnMain(void)404 void nnMain( void )
405 {
406 // Call only nn::applet::Enable to also allow execution from the HOME Menu
407 // HOME Menu transitions, POWER Button presses, and sleep are all unsupported
408 nn::applet::Enable();
409
410 Initialize();
411
412 bool flag = true;
413 while ( flag )
414 {
415 flag = DrawFrame();
416 }
417
418 Finalize();
419 }
420