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