1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     demo_RenderSystemExt.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: 46365 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "demo/Render/demo_RenderSystemExt.h"
17 
18 namespace demo
19 {
20     static GLenum s_CurrentLcdMode = NN_GX_DISPLAYMODE_NORMAL;
21     static GLenum s_NextLcdMode = NN_GX_DISPLAYMODE_NORMAL;
22 
RenderSystemExtVsyncCallback(GLenum targetDisplay)23     void RenderSystemExtVsyncCallback(GLenum targetDisplay)
24     {
25         if ( ( targetDisplay == NN_GX_DISPLAY0 ) && ( s_CurrentLcdMode != s_NextLcdMode ) )
26         {
27             // Switches the LCD mode.
28             nngxSetDisplayMode(s_NextLcdMode);
29 
30             if ( s_NextLcdMode == NN_GX_DISPLAYMODE_STEREO )
31             {
32                 nngxSwapBuffers(NN_GX_DISPLAY0);
33             }
34 
35             s_CurrentLcdMode = s_NextLcdMode;
36         }
37     }
38 
RenderSystemExt(void)39     RenderSystemExt::RenderSystemExt(void) :
40     RenderSystemDrawing(),
41     m_LcdMode(NN_GX_DISPLAYMODE_NORMAL),
42     m_DisplayBuffers0Ext(),
43     m_ChangeLcdMode(false)
44     {
45     }
46 
~RenderSystemExt(void)47     RenderSystemExt::~RenderSystemExt(void)
48     {
49         Finalize();
50     }
51 
Initialize(const uptr fcramAddress,const size_t memorySize,const u32 commandBufferSize,const u32 requestNum,const bool serialRunMode,const DisplayBuffersDescription & displayBuffers0Desc,const DisplayBuffersDescription & displayBuffers1Desc,const FrameBufferDescription & frameBuffer0Desc,const DisplayBuffersDescription & displayBuffers0ExtDesc,const bool isFillBlackLCD)52     void RenderSystemExt::Initialize(const uptr fcramAddress, const size_t memorySize,
53         const u32 commandBufferSize, const u32 requestNum,
54         const bool serialRunMode,
55         const DisplayBuffersDescription& displayBuffers0Desc,
56         const DisplayBuffersDescription& displayBuffers1Desc,
57         const FrameBufferDescription& frameBuffer0Desc,
58         const DisplayBuffersDescription& displayBuffers0ExtDesc,
59         const bool isFillBlackLCD)
60     {
61         s_CurrentLcdMode = m_LcdMode;
62         s_NextLcdMode = m_LcdMode;
63 
64         RenderSystemDrawing::Initialize(fcramAddress, memorySize,
65             commandBufferSize, requestNum, serialRunMode,
66             displayBuffers0Desc, displayBuffers1Desc,
67             frameBuffer0Desc, displayBuffers0ExtDesc, isFillBlackLCD);
68         DisplayBuffers::Create(displayBuffers0ExtDesc, m_DisplayBuffers0Ext);
69 
70         nngxSetVSyncCallback(NN_GX_DISPLAY0, RenderSystemExtVsyncCallback);
71 
72         m_InitializeFlag = true;
73     }
74 
InitializeLcdDisplay(void)75     void RenderSystemExt::InitializeLcdDisplay(void)
76     {
77         // Initializes the upper and lower screen display buffers with black.
78         // This function is called in RenderSystem::Initialize function.
79         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
80         SetRenderTarget(NN_GX_DISPLAY0);
81         Clear();
82         Transfer();
83         SwapBuffers();
84 
85         SetRenderTarget(NN_GX_DISPLAY1);
86         Clear();
87         Transfer();
88         SwapBuffers();
89 
90         SetRenderTarget(NN_GX_DISPLAY0);
91         Clear();
92         Transfer();
93         SwapBuffers();
94 
95         SetRenderTarget(NN_GX_DISPLAY1);
96         Clear();
97         Transfer();
98         SwapBuffers();
99 
100         WaitVsync(NN_GX_DISPLAY_BOTH);
101 
102         if (! m_InitializeLcdDisplayFlag )
103         {
104             nngxStartLcdDisplay();
105             m_InitializeLcdDisplayFlag = true;
106         }
107 
108         DEMO_ASSERT_GL_ERROR();
109     }
110 
Finalize(void)111     void RenderSystemExt::Finalize(void)
112     {
113         DisplayBuffers::Destroy(m_DisplayBuffers0Ext);
114         DEMO_ASSERT_GL_ERROR();
115 
116         RenderSystemDrawing::Finalize();
117     }
118 
SetLcdMode(const GLenum & lcdMode)119     void RenderSystemExt::SetLcdMode(const GLenum& lcdMode)
120     {
121         if ( ( lcdMode == NN_GX_DISPLAYMODE_NORMAL ) || ( lcdMode == NN_GX_DISPLAYMODE_STEREO ) )
122         {
123             if ( m_LcdMode != lcdMode )
124             {
125                 m_ChangeLcdMode = true;
126                 m_LcdMode = lcdMode;
127             }
128         }
129         else
130         {
131             NN_TPANIC_("Invalid LCD mode\n");
132         }
133     }
134 
GetLcdMode(void) const135     GLenum RenderSystemExt::GetLcdMode(void) const
136     {
137         return m_LcdMode;
138     }
139 
PrintLcdMode(void) const140     void RenderSystemExt::PrintLcdMode(void) const
141     {
142         if ( m_LcdMode == NN_GX_DISPLAYMODE_NORMAL )
143         {
144             NN_LOG("LCD mode: NN_GX_DISPLAYMODE_NORMAL\n");
145         }
146         else if ( m_LcdMode == NN_GX_DISPLAYMODE_STEREO )
147         {
148             NN_LOG("LCD mode: NN_GX_DISPLAYMODE_STEREO\n");
149         }
150         else
151         {
152             NN_TPANIC_("Invalid LCD mode\n");
153         }
154     }
155 
SetClearColor(const s32 display,const f32 red,const f32 green,const f32 blue,const f32 alpha)156     void RenderSystemExt::SetClearColor(const s32 display,
157         const f32 red, const f32 green, const f32 blue, const f32 alpha)
158     {
159         if ( ( display == NN_GX_DISPLAY0 ) || ( display == NN_GX_DISPLAY1 ) ||
160              ( display == NN_GX_DISPLAY_BOTH ) )
161         {
162             RenderSystemDrawing::SetClearColor(display, red, green, blue, alpha);
163         }
164 
165         if ( display == NN_GX_DISPLAY0_EXT )
166         {
167             m_ClearColorArray[2][0] = red;
168             m_ClearColorArray[2][1] = green;
169             m_ClearColorArray[2][2] = blue;
170             m_ClearColorArray[2][3] = alpha;
171         }
172     }
173 
Clear(const GLbitfield mask)174     void RenderSystemExt::Clear(const GLbitfield mask)
175     {
176         if ( ( m_TargetDisplay == NN_GX_DISPLAY0 ) || ( m_TargetDisplay == NN_GX_DISPLAY1 ) )
177         {
178             RenderSystemDrawing::Clear(mask);
179         }
180         else if ( m_TargetDisplay == NN_GX_DISPLAY0_EXT )
181         {
182             u32 displayIndex = 2;
183             glClearColor(m_ClearColorArray[displayIndex][0], m_ClearColorArray[displayIndex][1],
184                 m_ClearColorArray[displayIndex][2], m_ClearColorArray[displayIndex][3]);
185 
186             RenderSystemDrawing::Clear(mask);
187         }
188     }
189 
SetRenderTarget(const GLenum targetDisplay)190     void RenderSystemExt::SetRenderTarget(const GLenum targetDisplay)
191     {
192         if (! m_InitializeFlag )
193         {
194             NN_TPANIC_("Initialize() was not called.\n");
195         }
196 
197         if ( targetDisplay == NN_GX_DISPLAY0 )
198         {
199             m_TargetDisplay = targetDisplay;
200             m_CurrentFrameBufferPtr = &m_FrameBuffer0;
201 
202             if ( ( m_LcdMode == NN_GX_DISPLAYMODE_NORMAL ) || ( m_LcdMode == NN_GX_DISPLAYMODE_STEREO ) )
203             {
204                 m_CurrentDisplayBuffersPtr = &m_DisplayBuffers0;
205             }
206             else
207             {
208                 NN_TPANIC_("Invalid LCD mode.\n");
209             }
210         }
211         else if ( targetDisplay == NN_GX_DISPLAY1 )
212         {
213             m_TargetDisplay = targetDisplay;
214 
215             m_CurrentFrameBufferPtr = &m_FrameBuffer0;
216             m_CurrentDisplayBuffersPtr = &m_DisplayBuffers1;
217         }
218         else if ( targetDisplay == NN_GX_DISPLAY0_EXT )
219         {
220             if ( m_LcdMode == NN_GX_DISPLAYMODE_STEREO )
221             {
222                 m_TargetDisplay = targetDisplay;
223 
224                 m_CurrentFrameBufferPtr = &m_FrameBuffer0;
225                 m_CurrentDisplayBuffersPtr = &m_DisplayBuffers0Ext;
226             }
227             else
228             {
229                 NN_PANIC("LcdMode must be NN_GX_DISPLAYMODE_STEREO.\n");
230             }
231         }
232         else
233         {
234             NN_TPANIC_("Invalid display.\n");
235         }
236 
237         m_CurrentFrameBufferPtr->Bind();
238         SetViewport(0, 0, m_CurrentDisplayBuffersPtr->GetWidth(), m_CurrentDisplayBuffersPtr->GetHeight());
239     }
240 
GetFramebufferObjectId(const GLenum targetDisplay)241     GLuint RenderSystemExt::GetFramebufferObjectId(const GLenum targetDisplay)
242     {
243         if (! m_InitializeFlag )
244         {
245             NN_TPANIC_("Initialize() was not called.\n");
246         }
247 
248         if ( ( targetDisplay == NN_GX_DISPLAY0 ) || ( targetDisplay == NN_GX_DISPLAY1 ) ||
249              ( targetDisplay == NN_GX_DISPLAY0_EXT ) )
250         {
251             return m_FrameBuffer0.GetFrameBufferId();
252         }
253         else
254         {
255             NN_TPANIC_("Invalid display.\n");
256 
257             return 0;
258         }
259     }
260 
GetRenderbufferObjectId(const GLenum targetDisplay,const GLenum renderBufferType)261     GLuint RenderSystemExt::GetRenderbufferObjectId(const GLenum targetDisplay, const GLenum renderBufferType)
262     {
263         if (! m_InitializeFlag )
264         {
265             NN_TPANIC_("Initialize() was not called.\n");
266 
267             return 0;
268         }
269 
270         if ( ( targetDisplay == NN_GX_DISPLAY0 ) || ( targetDisplay == NN_GX_DISPLAY1 ) ||
271              ( targetDisplay == NN_GX_DISPLAY0_EXT ) )
272         {
273             if ( renderBufferType == GL_COLOR_ATTACHMENT0 )
274             {
275                 return m_FrameBuffer0.GetRenderBufferId(0);
276             }
277             else if ( renderBufferType == GL_DEPTH_STENCIL_ATTACHMENT )
278             {
279                 return m_FrameBuffer0.GetRenderBufferId(1);
280             }
281             else
282             {
283                 NN_TPANIC_("Invalid renderBufferType.\n");
284 
285                 return 0;
286             }
287         }
288         else
289         {
290             NN_TPANIC_("Invalid display.\n");
291 
292             return 0;
293         }
294     }
295 
296     // Since nngxSwapBuffers(NN_GX_DISPLAY0) must be executed after transferring the image to both display buffers for the upper LCD during stereo display mode, transfer the image to the display buffer with the Transfer function.
297     //
298     //
299     //
Transfer(void)300     void RenderSystemExt::Transfer(void)
301     {
302         if ( ! m_InitializeFlag )
303         {
304             return;
305         }
306 
307         CheckRenderTarget();
308 
309         RenderSystemDrawing::Flush();
310 
311         // Transfers from color buffer to display buffer
312         GLuint displayBufferId = m_CurrentDisplayBuffersPtr->GetTargetDisplayBufferId();
313         // Gets the ID of the transfer destination display buffer
314         m_CurrentDisplayBuffersPtr->Bind();
315         m_CurrentFrameBufferPtr->Transfer(displayBufferId,
316             NN_GX_ANTIALIASE_NOT_USED, GL_FALSE, 0, 0);
317         DEMO_ASSERT_GL_ERROR();
318 
319         // Execute the command list
320         m_CommandList.Run();
321         m_CommandList.Swap();
322 
323         DEMO_ASSERT_GL_ERROR();
324 
325         m_CurrentDisplayBuffersPtr->IncreaseBufferIndex();
326     }
327 
328     // After transferring the images to the display buffer with Transfer, call SwapBuffers.
329     //
SwapBuffers(void)330     void RenderSystemExt::SwapBuffers(void)
331     {
332         if ( ! m_InitializeFlag )
333         {
334             return;
335         }
336 
337         if ( ( m_TargetDisplay == NN_GX_DISPLAY0 ) &&
338              ( m_ChangeLcdMode ) && ( m_LcdMode == NN_GX_DISPLAYMODE_STEREO ) )
339         {
340             // Only when switching the mode to STEREO mode, bind the right-eye display temporarily to the left-eye display buffer.
341             //
342             GLuint displayBufferId = m_DisplayBuffers0.GetPreviousTargetDisplayBufferId();
343             nngxActiveDisplay(NN_GX_DISPLAY0_EXT);
344             nngxBindDisplaybuffer(displayBufferId);
345         }
346 
347         if ( ( m_TargetDisplay == NN_GX_DISPLAY0 ) || ( m_TargetDisplay == NN_GX_DISPLAY0_EXT ) )
348         {
349             nngxSwapBuffers(NN_GX_DISPLAY0);
350         }
351         else if ( m_TargetDisplay == NN_GX_DISPLAY1 )
352         {
353             nngxSwapBuffers(NN_GX_DISPLAY1);
354         }
355 
356         DEMO_ASSERT_GL_ERROR();
357     }
358 
WaitVsync(const GLenum targetDisplay)359     void RenderSystemExt::WaitVsync(const GLenum targetDisplay)
360     {
361         if ( m_ChangeLcdMode )
362         {
363             s_NextLcdMode = m_LcdMode;
364         }
365 
366         if ( ( targetDisplay == NN_GX_DISPLAY0 ) || ( targetDisplay == NN_GX_DISPLAY1 ) ||
367              ( targetDisplay == NN_GX_DISPLAY_BOTH ) )
368         {
369             nngxWaitVSync(targetDisplay);
370         }
371         else
372         {
373             NN_TPANIC_("Invalid display.\n");
374         }
375 
376         if ( m_ChangeLcdMode )
377         {
378             m_ChangeLcdMode = false;
379         }
380     }
381 
CheckRenderTarget(void)382     void RenderSystemExt::CheckRenderTarget(void)
383     {
384         if (! m_InitializeFlag )
385         {
386             NN_TPANIC_("Initialize() was not called.\n");
387         }
388 
389         if (! ( ( m_TargetDisplay == NN_GX_DISPLAY0 ) || ( m_TargetDisplay == NN_GX_DISPLAY1 ) ||
390                 ( m_TargetDisplay == NN_GX_DISPLAY0_EXT ) ) )
391         {
392             NN_TPANIC_("Invalid display. Call SetRenderTarget().\n");
393         }
394 
395         if ( m_CurrentDisplayBuffersPtr == NULL )
396         {
397             NN_TPANIC_("m_CurrentDisplayBufferPtr is NULL. Call SetRenderTarget().\n");
398         }
399 
400         if ( m_CurrentFrameBufferPtr == NULL )
401         {
402             NN_TPANIC_("m_CurrentFrameBufferPtr is NULL. Call SetRenderTarget().\n");
403         }
404     }
405 
406 }
407