/*---------------------------------------------------------------------------* Project: NintendoWare File: SmRenderSystem.cpp Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo and/or its licensed developers and are protected by national and international copyright laws. 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. The content herein is highly confidential and should be handled accordingly. $Revision: $ *---------------------------------------------------------------------------*/ #include "../include/SmRenderSystem.h" #include nw::demo::GraphicsMemoryAllocator s_GraphicsMemoryAllocator; bool s_GetGlSystemFlag = false; //---------------------------------------- // void SmInitializeGraphicsSystem(nw::demo::DemoAllocator* deviceAllocator) { nn::os::Initialize(); nn::fs::Initialize(); // メインメモリとデバイスメモリを初期化します。 // メインメモリはユーザーが自由にアクセスできる領域となり、 // デバイスメモリはGPUがアクセスするFCRAM上の領域となります。 nw::demo::InitializeDemoMemory(); nw::demo::InitializeDemoAllocator(deviceAllocator, nw::demo::DEMO_MEMORY_SIZE, nn::os::ALLOCATE_OPTION_LINEAR); // デバイスメモリを用いるグラフィックスメモリアロケータを初期化します。 s_GraphicsMemoryAllocator.Initialize(deviceAllocator); const int MAX_FILE = 256; const int MAX_DIRECTORY = 16; s32 workingMemorySize = nn::fs::GetRomRequiredMemorySize(MAX_FILE, MAX_DIRECTORY, false); void* workingMemory = nw::demo::Alloc(workingMemorySize); nn::Result result = nn::fs::MountRom(MAX_FILE, MAX_DIRECTORY, workingMemory, workingMemorySize, false); NW_ASSERT(result.IsSuccess()); } //---------------------------------------- // void SmFinalizeGraphicsSystem(nw::demo::DemoAllocator* deviceAllocator) { s_GraphicsMemoryAllocator.Finalize(); nw::demo::FinalizeDemoAllocator(deviceAllocator); } //---------------------------------------- void* smAllocateGraphicsMemory(GLenum area, GLenum aim, GLuint id, GLsizei size) { void* buffer = s_GraphicsMemoryAllocator.Allocate(area, aim, id, size); return buffer; } //---------------------------------------- void smDeallocateGraphicsMemory(GLenum area, GLenum aim, GLuint id, void* addr) { s_GraphicsMemoryAllocator.Deallocate(area, aim, id, addr); } namespace { //---------------------------------------- void SmRenderSystem::CreateInternal_() { s_GetGlSystemFlag = true; if (nngxInitialize( smAllocateGraphicsMemory, smDeallocateGraphicsMemory ) == GL_FALSE) { NW_FATAL_ERROR("nngxInitialize failed.\n"); } s_GetGlSystemFlag = false; // コマンドリスト生成 #define SM_RENDER_SYSTEM_CMD_BUFF_SIZE 0x100000 #define SM_RENDER_SYSTEM_CMD_REQ_SIZE 512 nngxGenCmdlists(1, &m_CacheCmdListUpper[COMMAND_BUFFER_SIZE_0]); nngxBindCmdlist(m_CacheCmdListUpper[COMMAND_BUFFER_SIZE_0]); nngxCmdlistStorage(SM_RENDER_SYSTEM_CMD_BUFF_SIZE, SM_RENDER_SYSTEM_CMD_REQ_SIZE); nngxSetCmdlistParameteri(NN_GX_CMDLIST_RUN_MODE, NN_GX_CMDLIST_SERIAL_RUN); nngxGenCmdlists(1, &m_CacheCmdListUpper[COMMAND_BUFFER_SIZE_1]); nngxBindCmdlist(m_CacheCmdListUpper[COMMAND_BUFFER_SIZE_1]); nngxCmdlistStorage(SM_RENDER_SYSTEM_CMD_BUFF_SIZE, SM_RENDER_SYSTEM_CMD_REQ_SIZE); nngxSetCmdlistParameteri(NN_GX_CMDLIST_RUN_MODE, NN_GX_CMDLIST_SERIAL_RUN); nngxGenCmdlists(1, &(m_CacheCmdListLower)); nngxBindCmdlist(m_CacheCmdListLower); nngxCmdlistStorage(SM_RENDER_SYSTEM_CMD_BUFF_SIZE, SM_RENDER_SYSTEM_CMD_REQ_SIZE); nngxSetCmdlistParameteri(NN_GX_CMDLIST_RUN_MODE, NN_GX_CMDLIST_SERIAL_RUN); nngxRunCmdlist(); nngxStartLcdDisplay(); } //---------------------------------------- // コンストラクタ SmRenderSystem::SmRenderSystem( const Description& description ) : m_RenderContext( NULL ), m_UpperSwapper( NULL ), m_LowerSwapper( NULL ), m_ExtensionSwapper( NULL ), m_CacheCmdListLower( 0 ), m_StereoCamera( NULL ) { m_CacheCmdListUpper[COMMAND_BUFFER_SIZE_0] = 0; m_CacheCmdListUpper[COMMAND_BUFFER_SIZE_1] = 0; m_RenderContext = nw::gfx::RenderContext::Builder() .Create( m_Allocator ); CreateInternal_(); // ディスプレイ初期化 { m_UpperSwapper = nw::demo::DisplayBufferSwapper::Builder() .BufferDescription(description.upperScreenDescription) .BufferCount(description.displayBufferCount) .Create(m_Allocator); m_LowerSwapper = nw::demo::DisplayBufferSwapper::Builder() .BufferDescription(description.lowerScreenDescription) .BufferCount(description.displayBufferCount) .Create(m_Allocator); nngxSetDisplayMode(NN_GX_DISPLAYMODE_STEREO); nw::demo::DisplayBufferSwapper::Description extensionScreenDescription; extensionScreenDescription.screenKind = nw::demo::EXTENSION_SCREEN; extensionScreenDescription.width = description.upperScreenDescription.width; extensionScreenDescription.height = description.upperScreenDescription.height; extensionScreenDescription.bufferCount = description.upperScreenDescription.bufferCount; m_ExtensionSwapper = nw::demo::DisplayBufferSwapper::Builder() .BufferDescription(extensionScreenDescription) .Create( m_Allocator ); // ステレオカメラを生成する void* cameraMemory = m_Allocator->Alloc(sizeof(nn::ulcd::CTR::StereoCamera)); nn::ulcd::CTR::StereoCamera* stereoCamera = new(cameraMemory) nn::ulcd::CTR::StereoCamera(); stereoCamera->Initialize(); m_StereoCamera = stereoCamera; } NW_GL_ASSERT(); } //---------------------------------------- // デストラクタ SmRenderSystem::~SmRenderSystem() { if (m_StereoCamera) { m_StereoCamera->Finalize(); m_Allocator->Free(m_StereoCamera); } nw::gfx::SafeDestroy(m_ExtensionSwapper); nw::gfx::SafeDestroy(m_LowerSwapper); nw::gfx::SafeDestroy(m_UpperSwapper); nw::gfx::SafeDestroy( m_RenderContext); nngxFinalize(); NW_GL_ASSERT(); } //---------------------------------------- // VSync 待ちを行います。 void SmRenderSystem::WaitVSync( s32 screenKind ) { NW_MAX_ASSERT(screenKind, (int)nw::demo::BOTH_SCREENS); GLenum display; if (screenKind & (nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN)) { display = NN_GX_DISPLAY_BOTH; } else if (screenKind & nw::demo::UPPER_SCREEN) { display = NN_GX_DISPLAY0; } else if (screenKind & nw::demo::LOWER_SCREEN) { display = NN_GX_DISPLAY1; } { nngxWaitVSync(display); } } //---------------------------------------- // バッファのスワップを予約します。 void SmRenderSystem::SwapBuffer( s32 screenKind ) { GLenum display; if (screenKind & (nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN)) { m_UpperSwapper->ActivateBuffer(); m_LowerSwapper->ActivateBuffer(); if (screenKind & nw::demo::EXTENSION_SCREEN) { m_ExtensionSwapper->ActivateBuffer(); } display = NN_GX_DISPLAY_BOTH; } else if (screenKind & nw::demo::UPPER_SCREEN) { m_UpperSwapper->ActivateBuffer(); if (screenKind & nw::demo::EXTENSION_SCREEN) { m_ExtensionSwapper->ActivateBuffer(); } display = NN_GX_DISPLAY0; } else if (screenKind & nw::demo::LOWER_SCREEN) { m_LowerSwapper->ActivateBuffer(); display = NN_GX_DISPLAY1; } nngxSwapBuffers(display); glBindFramebuffer(GL_FRAMEBUFFER, 0); } //---------------------------------------- // レンダターゲットを設定します。 void SmRenderSystem::SetRenderTarget( nw::gfx::IRenderTarget* renderTarget ) { m_RenderContext->SetRenderTarget(renderTarget); m_RenderTarget = renderTarget; } //---------------------------------------- // バッファを転送します。 void SmRenderSystem::TransferBuffer( s32 screenKind ) { if (screenKind & nw::demo::UPPER_SCREEN) { m_UpperSwapper->MakeTransferBufferCommand(m_RenderContext->GetRenderTarget(), false); } if (screenKind & nw::demo::LOWER_SCREEN) { m_LowerSwapper->MakeTransferBufferCommand(m_RenderContext->GetRenderTarget(), false); } if (screenKind & nw::demo::EXTENSION_SCREEN) { m_ExtensionSwapper->MakeTransferBufferCommand(m_RenderContext->GetRenderTarget(), false); } } //---------------------------------------- // コマンドリスト処理の終了待ちを行います。 void SmRenderSystem::WaitCommandList() { // nngxSplitDrawCmdlist(); nngxWaitCmdlistDone(); nngxClearCmdlist(); } //---------------------------------------- // バッファを消去します。 void SmRenderSystem::ClearBuffer( nw::ut::FloatColor clearColor ) { m_RenderContext->ClearBuffer( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, clearColor, 1.0f); NW_GL_ASSERT(); } //---------------------------------------- void SmRenderSystem::CalcStereoCamera( nw::gfx::Camera* leftCamera, nw::gfx::Camera* rightCamera, nw::gfx::Camera* baseCamera, f32 depthLevel, f32 depthRange) { NW_NULL_ASSERT(leftCamera); NW_NULL_ASSERT(rightCamera); NW_NULL_ASSERT(baseCamera); nn::math::MTX44& projOriginal = baseCamera->ProjectionMatrix(); nn::math::MTX34& viewOriginal = baseCamera->ViewMatrix(); nn::math::MTX44& projL = leftCamera->ProjectionMatrix(); nn::math::MTX34& viewL = leftCamera->ViewMatrix(); nn::math::MTX44& projR = rightCamera->ProjectionMatrix(); nn::math::MTX34& viewR = rightCamera->ViewMatrix(); f32 wScale = baseCamera->GetWScale(); leftCamera->SetWScale( wScale ); rightCamera->SetWScale( wScale ); m_StereoCamera->CalculateMatrices( &projL, &viewL, &projR, &viewR, &projOriginal, &viewOriginal, depthLevel, depthRange, false); } } // namespace