1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     SmRenderSystem.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: $
16  *---------------------------------------------------------------------------*/
17 
18 #include "../include/SmRenderSystem.h"
19 #include <nw/demo/demo_DisplayBufferSwapper.h>
20 
21 
22 
23 nw::demo::GraphicsMemoryAllocator s_GraphicsMemoryAllocator;
24 bool s_GetGlSystemFlag = false;
25 
26 
27 
28 //----------------------------------------
29 //
30 void
SmInitializeGraphicsSystem(nw::demo::DemoAllocator * deviceAllocator)31 SmInitializeGraphicsSystem(nw::demo::DemoAllocator* deviceAllocator)
32 {
33     nn::os::Initialize();
34     nn::fs::Initialize();
35 
36     // メインメモリとデバイスメモリを初期化します。
37     // メインメモリはユーザーが自由にアクセスできる領域となり、
38     // デバイスメモリはGPUがアクセスするFCRAM上の領域となります。
39     nw::demo::InitializeDemoMemory();
40 
41     nw::demo::InitializeDemoAllocator(deviceAllocator, nw::demo::DEMO_MEMORY_SIZE, nn::os::ALLOCATE_OPTION_LINEAR);
42 
43     // デバイスメモリを用いるグラフィックスメモリアロケータを初期化します。
44     s_GraphicsMemoryAllocator.Initialize(deviceAllocator);
45 
46     const int MAX_FILE = 256;
47     const int MAX_DIRECTORY = 16;
48 
49     s32 workingMemorySize = nn::fs::GetRomRequiredMemorySize(MAX_FILE, MAX_DIRECTORY, false);
50     void* workingMemory = nw::demo::Alloc(workingMemorySize);
51     nn::Result result = nn::fs::MountRom(MAX_FILE, MAX_DIRECTORY, workingMemory, workingMemorySize, false);
52     NW_ASSERT(result.IsSuccess());
53 
54 }
55 
56 
57 //----------------------------------------
58 //
59 void
SmFinalizeGraphicsSystem(nw::demo::DemoAllocator * deviceAllocator)60 SmFinalizeGraphicsSystem(nw::demo::DemoAllocator* deviceAllocator)
61 {
62     s_GraphicsMemoryAllocator.Finalize();
63 
64     nw::demo::FinalizeDemoAllocator(deviceAllocator);
65 }
66 
67 
68 
69 //----------------------------------------
smAllocateGraphicsMemory(GLenum area,GLenum aim,GLuint id,GLsizei size)70 void* smAllocateGraphicsMemory(GLenum area, GLenum aim, GLuint id, GLsizei size)
71 {
72     void* buffer = s_GraphicsMemoryAllocator.Allocate(area, aim, id, size);
73 
74     return buffer;
75 }
76 
77 //----------------------------------------
smDeallocateGraphicsMemory(GLenum area,GLenum aim,GLuint id,void * addr)78 void smDeallocateGraphicsMemory(GLenum area, GLenum aim, GLuint id, void* addr)
79 {
80     s_GraphicsMemoryAllocator.Deallocate(area, aim, id, addr);
81 }
82 
83 
84 
85 namespace
86 {
87 
88 
89 //----------------------------------------
90 void
CreateInternal_()91 SmRenderSystem::CreateInternal_()
92 {
93     s_GetGlSystemFlag = true;
94 
95     if (nngxInitialize( smAllocateGraphicsMemory, smDeallocateGraphicsMemory ) == GL_FALSE)
96     {
97         NW_FATAL_ERROR("nngxInitialize failed.\n");
98     }
99 
100     s_GetGlSystemFlag = false;
101 
102     // コマンドリスト生成
103     #define SM_RENDER_SYSTEM_CMD_BUFF_SIZE  0x100000
104     #define SM_RENDER_SYSTEM_CMD_REQ_SIZE   512
105 
106     nngxGenCmdlists(1, &m_CacheCmdListUpper[COMMAND_BUFFER_SIZE_0]);
107     nngxBindCmdlist(m_CacheCmdListUpper[COMMAND_BUFFER_SIZE_0]);
108     nngxCmdlistStorage(SM_RENDER_SYSTEM_CMD_BUFF_SIZE, SM_RENDER_SYSTEM_CMD_REQ_SIZE);
109     nngxSetCmdlistParameteri(NN_GX_CMDLIST_RUN_MODE, NN_GX_CMDLIST_SERIAL_RUN);
110 
111     nngxGenCmdlists(1, &m_CacheCmdListUpper[COMMAND_BUFFER_SIZE_1]);
112     nngxBindCmdlist(m_CacheCmdListUpper[COMMAND_BUFFER_SIZE_1]);
113     nngxCmdlistStorage(SM_RENDER_SYSTEM_CMD_BUFF_SIZE, SM_RENDER_SYSTEM_CMD_REQ_SIZE);
114     nngxSetCmdlistParameteri(NN_GX_CMDLIST_RUN_MODE, NN_GX_CMDLIST_SERIAL_RUN);
115 
116     nngxGenCmdlists(1, &(m_CacheCmdListLower));
117     nngxBindCmdlist(m_CacheCmdListLower);
118     nngxCmdlistStorage(SM_RENDER_SYSTEM_CMD_BUFF_SIZE, SM_RENDER_SYSTEM_CMD_REQ_SIZE);
119     nngxSetCmdlistParameteri(NN_GX_CMDLIST_RUN_MODE, NN_GX_CMDLIST_SERIAL_RUN);
120 
121     nngxRunCmdlist();
122     nngxStartLcdDisplay();
123 }
124 
125 
126 //----------------------------------------
127 // コンストラクタ
SmRenderSystem(const Description & description)128 SmRenderSystem::SmRenderSystem(
129     const Description& description
130 ) : m_RenderContext( NULL ),
131     m_UpperSwapper( NULL ),
132     m_LowerSwapper( NULL ),
133     m_ExtensionSwapper( NULL ),
134     m_CacheCmdListLower( 0 ),
135     m_StereoCamera( NULL )
136 {
137     m_CacheCmdListUpper[COMMAND_BUFFER_SIZE_0] = 0;
138     m_CacheCmdListUpper[COMMAND_BUFFER_SIZE_1] = 0;
139 
140     m_RenderContext = nw::gfx::RenderContext::Builder()
141         .Create( m_Allocator );
142 
143     CreateInternal_();
144 
145     // ディスプレイ初期化
146     {
147         m_UpperSwapper = nw::demo::DisplayBufferSwapper::Builder()
148             .BufferDescription(description.upperScreenDescription)
149             .BufferCount(description.displayBufferCount)
150             .Create(m_Allocator);
151 
152         m_LowerSwapper = nw::demo::DisplayBufferSwapper::Builder()
153             .BufferDescription(description.lowerScreenDescription)
154             .BufferCount(description.displayBufferCount)
155             .Create(m_Allocator);
156 
157         nngxSetDisplayMode(NN_GX_DISPLAYMODE_STEREO);
158 
159         nw::demo::DisplayBufferSwapper::Description extensionScreenDescription;
160         extensionScreenDescription.screenKind = nw::demo::EXTENSION_SCREEN;
161         extensionScreenDescription.width  = description.upperScreenDescription.width;
162         extensionScreenDescription.height = description.upperScreenDescription.height;
163         extensionScreenDescription.bufferCount = description.upperScreenDescription.bufferCount;
164 
165         m_ExtensionSwapper = nw::demo::DisplayBufferSwapper::Builder()
166             .BufferDescription(extensionScreenDescription)
167             .Create( m_Allocator );
168 
169         // ステレオカメラを生成する
170         void* cameraMemory = m_Allocator->Alloc(sizeof(nn::ulcd::CTR::StereoCamera));
171         nn::ulcd::CTR::StereoCamera* stereoCamera = new(cameraMemory) nn::ulcd::CTR::StereoCamera();
172         stereoCamera->Initialize();
173         m_StereoCamera = stereoCamera;
174     }
175 
176     NW_GL_ASSERT();
177 }
178 
179 
180 //----------------------------------------
181 // デストラクタ
~SmRenderSystem()182 SmRenderSystem::~SmRenderSystem()
183 {
184     if (m_StereoCamera)
185     {
186         m_StereoCamera->Finalize();
187         m_Allocator->Free(m_StereoCamera);
188     }
189 
190     nw::gfx::SafeDestroy(m_ExtensionSwapper);
191     nw::gfx::SafeDestroy(m_LowerSwapper);
192     nw::gfx::SafeDestroy(m_UpperSwapper);
193     nw::gfx::SafeDestroy( m_RenderContext);
194 
195     nngxFinalize();
196     NW_GL_ASSERT();
197 }
198 
199 
200 
201 //----------------------------------------
202 // VSync 待ちを行います。
203 void
WaitVSync(s32 screenKind)204 SmRenderSystem::WaitVSync( s32 screenKind )
205 {
206     NW_MAX_ASSERT(screenKind, (int)nw::demo::BOTH_SCREENS);
207 
208     GLenum display;
209     if (screenKind & (nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN)) { display = NN_GX_DISPLAY_BOTH; }
210     else if (screenKind & nw::demo::UPPER_SCREEN) { display = NN_GX_DISPLAY0; }
211     else if (screenKind & nw::demo::LOWER_SCREEN) { display = NN_GX_DISPLAY1; }
212 
213     {
214         nngxWaitVSync(display);
215     }
216 }
217 
218 
219 //----------------------------------------
220 // バッファのスワップを予約します。
221 void
SwapBuffer(s32 screenKind)222 SmRenderSystem::SwapBuffer( s32 screenKind )
223 {
224     GLenum display;
225     if (screenKind & (nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN))
226     {
227         m_UpperSwapper->ActivateBuffer();
228         m_LowerSwapper->ActivateBuffer();
229 
230         if (screenKind & nw::demo::EXTENSION_SCREEN)
231         {
232             m_ExtensionSwapper->ActivateBuffer();
233         }
234 
235         display = NN_GX_DISPLAY_BOTH;
236     }
237     else if (screenKind & nw::demo::UPPER_SCREEN)
238     {
239         m_UpperSwapper->ActivateBuffer();
240 
241         if (screenKind & nw::demo::EXTENSION_SCREEN)
242         {
243             m_ExtensionSwapper->ActivateBuffer();
244         }
245 
246         display = NN_GX_DISPLAY0;
247     }
248     else if (screenKind & nw::demo::LOWER_SCREEN)
249     {
250         m_LowerSwapper->ActivateBuffer();
251 
252         display = NN_GX_DISPLAY1;
253     }
254 
255     nngxSwapBuffers(display);
256     glBindFramebuffer(GL_FRAMEBUFFER, 0);
257 }
258 
259 
260 //----------------------------------------
261 // レンダターゲットを設定します。
262 void
SetRenderTarget(nw::gfx::IRenderTarget * renderTarget)263 SmRenderSystem::SetRenderTarget( nw::gfx::IRenderTarget* renderTarget )
264 {
265     m_RenderContext->SetRenderTarget(renderTarget);
266     m_RenderTarget = renderTarget;
267 }
268 
269 
270 //----------------------------------------
271 // バッファを転送します。
272 void
TransferBuffer(s32 screenKind)273 SmRenderSystem::TransferBuffer( s32 screenKind )
274 {
275     if (screenKind & nw::demo::UPPER_SCREEN)
276     {
277         m_UpperSwapper->MakeTransferBufferCommand(m_RenderContext->GetRenderTarget(), false);
278     }
279 
280     if (screenKind & nw::demo::LOWER_SCREEN)
281     {
282         m_LowerSwapper->MakeTransferBufferCommand(m_RenderContext->GetRenderTarget(), false);
283     }
284 
285     if (screenKind & nw::demo::EXTENSION_SCREEN)
286     {
287         m_ExtensionSwapper->MakeTransferBufferCommand(m_RenderContext->GetRenderTarget(), false);
288     }
289 }
290 
291 
292 //----------------------------------------
293 // コマンドリスト処理の終了待ちを行います。
294 void
WaitCommandList()295 SmRenderSystem::WaitCommandList()
296 {
297 //    nngxSplitDrawCmdlist();
298     nngxWaitCmdlistDone();
299     nngxClearCmdlist();
300 }
301 
302 
303 //----------------------------------------
304 // バッファを消去します。
305 void
ClearBuffer(nw::ut::FloatColor clearColor)306 SmRenderSystem::ClearBuffer( nw::ut::FloatColor clearColor )
307 {
308     m_RenderContext->ClearBuffer(
309         GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
310         clearColor,
311         1.0f);
312     NW_GL_ASSERT();
313 }
314 
315 //----------------------------------------
316 void
CalcStereoCamera(nw::gfx::Camera * leftCamera,nw::gfx::Camera * rightCamera,nw::gfx::Camera * baseCamera,f32 depthLevel,f32 depthRange)317 SmRenderSystem::CalcStereoCamera(
318     nw::gfx::Camera* leftCamera,
319     nw::gfx::Camera* rightCamera,
320     nw::gfx::Camera* baseCamera,
321     f32 depthLevel,
322     f32 depthRange)
323 {
324     NW_NULL_ASSERT(leftCamera);
325     NW_NULL_ASSERT(rightCamera);
326     NW_NULL_ASSERT(baseCamera);
327     nn::math::MTX44& projOriginal = baseCamera->ProjectionMatrix();
328     nn::math::MTX34& viewOriginal = baseCamera->ViewMatrix();
329     nn::math::MTX44& projL = leftCamera->ProjectionMatrix();
330     nn::math::MTX34& viewL = leftCamera->ViewMatrix();
331     nn::math::MTX44& projR = rightCamera->ProjectionMatrix();
332     nn::math::MTX34& viewR = rightCamera->ViewMatrix();
333 
334     f32 wScale = baseCamera->GetWScale();
335     leftCamera->SetWScale( wScale );
336     rightCamera->SetWScale( wScale );
337 
338     m_StereoCamera->CalculateMatrices(
339         &projL,
340         &viewL,
341         &projR,
342         &viewR,
343         &projOriginal,
344         &viewOriginal,
345         depthLevel,
346         depthRange,
347         false);
348 }
349 
350 
351 } // namespace
352 
353