/*---------------------------------------------------------------------------* Project: Horizon File: gx_DrawTexture2d.cpp Copyright (C)2009-2012 Nintendo Co., Ltd. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Rev: 47228 $ *---------------------------------------------------------------------------*/ #include #include #include #include #include #include #include #include #include #include "demo.h" namespace { demo::RenderSystemDrawing s_RenderSystem; nn::fnd::ExpHeap s_AppHeap; uptr s_HeapForGx; const u32 s_GxHeapSize = 0x400000; } typedef __packed struct BitmapFileHeader { u8 bfType[2]; u16 bfSize[2]; u16 bfReserved1; u16 bfReserved2; u16 bfOffBits[2]; } BitmapFileHeader; typedef __packed struct BitmapInfoHeader { u32 biSize; s32 biWidth; s32 biHeight; u16 biPlanes; u16 biBitCount; u32 biCompression; u32 biSizeImage; s32 biXPixPerMeter; s32 biYPixPerMeter; u32 biClrUsed; u32 biClrImportant; } BitmapInfoHeader; // Texture0 GLuint s_BmpTexture0Id = 0; u32 s_Bmp0Width = 0; u32 s_Bmp0Height = 0; u32 s_Texture0Width = 0; u32 s_Texture0Height = 0; // Texture1 GLuint s_BmpTexture1Id = 0; u32 s_Bmp1Width = 0; u32 s_Bmp1Height = 0; u32 s_Texture1Width = 0; u32 s_Texture1Height = 0; void Initialize(void); void Finalize(void); void LoadTexture0(void); void DeleteTexture0(void); void LoadTexture1(void); void DeleteTexture1(void); u8* GetTextureData(const wchar_t* bmpRomFilename, u32& bmpWidth, u32& bmpHeight, u32& textureWidth, u32& textureHeight); u8* GetBmpFileData(u8* rawDataBuffer, u32& bmpWidth, u32& bmpHeight); u8* GetTextureDataFromBmpFileData(const u32& bmpWidth, const u32& bmpHeight, u8* bmpDataBuffer, u32& textureWidth, u32& textureHeight); u32 GetTextureLength(const u32& imageLength); bool DrawFrame(void); void DrawDisplay0(void); void DrawDisplay1(void); void Initialize(void) { // fs initialization nn::fs::Initialize(); const size_t ROMFS_BUFFER_SIZE = 1024 * 64; static char buffer[ROMFS_BUFFER_SIZE]; NN_UTIL_PANIC_IF_FAILED( nn::fs::MountRom(16, 16, buffer, ROMFS_BUFFER_SIZE)); s_AppHeap.Initialize(nn::os::GetDeviceMemoryAddress(), nn::os::GetDeviceMemorySize() ); s_HeapForGx = reinterpret_cast(s_AppHeap.Allocate(s_GxHeapSize)); s_RenderSystem.Initialize(s_HeapForGx, s_GxHeapSize); LoadTexture0(); LoadTexture1(); } void Finalize(void) { DeleteTexture0(); DeleteTexture1(); s_RenderSystem.Finalize(); s_AppHeap.Free(reinterpret_cast(s_HeapForGx)); s_AppHeap.Finalize(); } void LoadTexture0(void) { if ( s_BmpTexture0Id != 0 ) { DeleteTexture0(); } wchar_t* bmpRomFilename = L"rom:/tulip.bmp"; u8* textureDataPtr = GetTextureData(bmpRomFilename, s_Bmp0Width, s_Bmp0Height, s_Texture0Width, s_Texture0Height); GLenum target = GL_TEXTURE_2D; GLenum internalFormat = GL_RGB_NATIVE_DMP; GLenum format = GL_RGB_NATIVE_DMP; GLenum type = GL_UNSIGNED_BYTE; GLuint textureId = 0; s_RenderSystem.GenerateTexture(target, internalFormat, s_Texture0Width, s_Texture0Height, format, type, textureDataPtr, textureId); if ( textureId != 0 ) { s_BmpTexture0Id = textureId; NN_LOG(" Create texture (id = %d)\n", textureId); } s_AppHeap.Free(textureDataPtr); } void DeleteTexture0(void) { if ( s_BmpTexture0Id != 0 ) { bool flag = s_RenderSystem.DeleteTexture(s_BmpTexture0Id); if ( flag ) { NN_LOG(" Delete texture. (id = %d)\n", s_BmpTexture0Id); s_BmpTexture0Id = 0; } else { NN_TPANIC_(" Failed to delete texture. (id = %d)\n", s_BmpTexture0Id); } } } void LoadTexture1(void) { if ( s_BmpTexture1Id != 0 ) { DeleteTexture1(); } wchar_t* bmpRomFilename = L"rom:/dandelion.bmp"; u8* textureDataPtr = GetTextureData(bmpRomFilename, s_Bmp1Width, s_Bmp1Height, s_Texture1Width, s_Texture1Height); GLenum target = GL_TEXTURE_2D; GLenum internalFormat = GL_RGB_NATIVE_DMP; GLenum format = GL_RGB_NATIVE_DMP; GLenum type = GL_UNSIGNED_BYTE; GLuint textureId = 0; s_RenderSystem.GenerateTexture(target, internalFormat, s_Texture1Width, s_Texture1Height, format, type, textureDataPtr, textureId); if ( textureId != 0 ) { s_BmpTexture1Id = textureId; NN_LOG(" Create texture. (id = %d)\n", textureId); } s_AppHeap.Free(textureDataPtr); } void DeleteTexture1(void) { if ( s_BmpTexture1Id != 0 ) { bool flag = s_RenderSystem.DeleteTexture(s_BmpTexture1Id); if ( flag ) { NN_LOG(" Delete texture. (id = %d)\n", s_BmpTexture1Id); s_BmpTexture1Id = 0; } else { NN_TPANIC_("Failed to delete texture. (id = %d)\n", s_BmpTexture1Id); } } } u8* GetTextureData(const wchar_t* bmpRomFilename, u32& bmpWidth, u32& bmpHeight, u32& textureWidth, u32& textureHeight) { NN_LOG("\nReading data from ROMFS...\n"); nn::fs::FileReader file(bmpRomFilename); size_t fileSize = file.GetSize(); NN_LOG(" fileSize = %d (Byte)\n", fileSize); if ( fileSize == 0 ) { NN_TPANIC_("Failed to open BMP file.\n"); return NULL; } void* buf = s_AppHeap.Allocate( fileSize, 4 ); s32 readSize = file.Read(buf, fileSize); NN_LOG(" file readSize = %d (Byte)\n", readSize); if ( readSize == 0 ) { NN_TPANIC_("Failed to open BMP file.\n"); return NULL; } u8* bmpDataBuffer = NULL; bmpDataBuffer = GetBmpFileData((u8*)buf, bmpWidth, bmpHeight); NN_LOG(" bmpWidth = %d, bmpHeight = %d\n", bmpWidth, bmpHeight); u8* textureDataBuffer = NULL; textureDataBuffer = GetTextureDataFromBmpFileData(bmpWidth, bmpHeight, bmpDataBuffer, textureWidth, textureHeight); NN_LOG(" textureWidth = %d, textureHeight = %d\n", textureWidth, textureHeight); file.Finalize(); s_AppHeap.Free(buf); return textureDataBuffer; } u8* GetBmpFileData(u8* rawDataBuffer, u32& bmpWidth, u32& bmpHeight) { BitmapInfoHeader* bmp_info_header_ptr = (BitmapInfoHeader*)(rawDataBuffer + sizeof(BitmapFileHeader)); bmpWidth = bmp_info_header_ptr->biWidth; bmpHeight = bmp_info_header_ptr->biHeight; u8* bmpDataBuffer = rawDataBuffer + sizeof(BitmapFileHeader) + sizeof(BitmapInfoHeader); return bmpDataBuffer; } u8* GetTextureDataFromBmpFileData(const u32& bmpWidth, const u32& bmpHeight, u8* bmpDataBuffer, u32& textureWidth, u32& textureHeight) { // Convert BMP to OpenGL RGB format textureWidth = GetTextureLength(bmpWidth); textureHeight = GetTextureLength(bmpHeight); u8* textureGLDataBuffer = reinterpret_cast( s_AppHeap.Allocate(3 * textureWidth * textureHeight) ); for (u32 y = 0; y < textureHeight; y++) { for (u32 x = 0; x < textureWidth; x++) { u8* textureDataPtr = textureGLDataBuffer; textureDataPtr += 3 * ((static_cast(textureWidth) * y) + x); if ( ( x >= bmpWidth ) || ( y >= bmpHeight ) ) { (*textureDataPtr) = 0x00; textureDataPtr += 1; (*textureDataPtr) = 0x00; textureDataPtr += 1; (*textureDataPtr) = 0x00; } else { u8* bmpDataPtr = bmpDataBuffer; bmpDataPtr += 3 * (bmpWidth * y + x); (*textureDataPtr) = (*(bmpDataPtr + 2)); textureDataPtr += 1; (*textureDataPtr) = (*(bmpDataPtr + 1)); textureDataPtr += 1; (*textureDataPtr) = (*(bmpDataPtr + 0)); } } } u8* textureDataBuffer = reinterpret_cast( s_AppHeap.Allocate(3 * textureWidth * textureHeight) ); // Convert OpenGL RGB format to PICA Native RGB format GLenum format = GL_RGB_NATIVE_DMP; bool result = demo::ConvertGLTextureToNative( format, textureWidth, textureHeight, textureGLDataBuffer, textureDataBuffer); if ( result ) { NN_LOG(" Conversion to GL_RGB_NATIVE_DMP succeeded.\n"); } else { NN_TPANIC_(" Conversion to GL_RGB_NATIVE_DMP failed.\n"); } s_AppHeap.Free(textureGLDataBuffer); return textureDataBuffer; } u32 GetTextureLength(const u32& imageLength) { u32 textureLength = 8; // 8, 16, 32, 64, 128, 256, 512, 1024 for (u32 i = 0; i < 7; i++) { if ( imageLength > textureLength ) { textureLength *= 2; } else { return textureLength; } } return 1024; } bool DrawFrame(void) { DrawDisplay0(); DrawDisplay1(); s_RenderSystem.WaitVsync(NN_GX_DISPLAY_BOTH); return true; } void DrawDisplay0(void) { s_RenderSystem.SetClearColor(NN_GX_DISPLAY0, 0.0f, 1.0f, 0.0f, 1.0f); s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY0); s_RenderSystem.Clear(); s_RenderSystem.SetColor(0.0f, 1.0f, 0.0f, 0.0f); f32 windowCoordinateX = 0.0f; f32 windowCoordinateY = 0.0f; f32 rectangleWidth = 400.0f; f32 rectangleHeight = 240.0f; s_RenderSystem.FillTexturedRectangle(s_BmpTexture0Id, windowCoordinateX, windowCoordinateY, rectangleWidth, rectangleHeight, s_Bmp0Width, s_Bmp0Height, s_Texture0Width, s_Texture0Height); s_RenderSystem.SwapBuffers(); } void DrawDisplay1(void) { s_RenderSystem.SetClearColor(NN_GX_DISPLAY1, 0.0f, 0.0f, 1.0f, 0.0f); s_RenderSystem.SetRenderTarget(NN_GX_DISPLAY1); s_RenderSystem.Clear(); f32 windowCoordinateX = 0.0f; f32 windowCoordinateY = 0.0f; f32 rectangleWidth = 320.0f; f32 rectangleHeight = 240.0f; s_RenderSystem.FillTexturedRectangle(s_BmpTexture1Id, windowCoordinateX, windowCoordinateY, rectangleWidth, rectangleHeight, s_Bmp1Width, s_Bmp1Height, s_Texture1Width, s_Texture1Height); s_RenderSystem.SwapBuffers(); } void nnMain( void ) { // Call only nn::applet::Enable to also allow execution from the HOME Menu // HOME Menu transitions, POWER Button presses, and sleep are all unsupported nn::applet::Enable(); Initialize(); bool flag = true; while ( flag ) { flag = DrawFrame(); } Finalize(); }