1 /*---------------------------------------------------------------------------* 2 Project: Horizon 3 File: gr_RenderState.cpp 4 5 Copyright (C)2010 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: 33699 $ 14 *---------------------------------------------------------------------------*/ 15 16 #include <nn/gr/CTR/gr_RenderState.h> 17 18 namespace nn 19 { 20 namespace gr 21 { 22 namespace CTR 23 { 24 MakeCommand(bit32 * command,bool isUpdateFBAccess) const25 bit32* RenderState::Culling::MakeCommand( bit32* command, bool isUpdateFBAccess ) const 26 { 27 bit32 culling = 0; 28 29 if ( isEnable ) 30 { 31 if ( ( frontFace == FRONT_FACE_CW && cullFace == CULL_FACE_FRONT ) || 32 ( frontFace == FRONT_FACE_CCW && cullFace == CULL_FACE_BACK ) ) 33 { 34 culling = 2; 35 } 36 else 37 { 38 culling = 1; 39 } 40 } 41 42 // 0x040 43 *command++ = culling; 44 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_CULL_FACE ); 45 46 return isUpdateFBAccess ? m_RenderState.fbAccess.MakeCommand( command ) : command; 47 } 48 49 //------------------------------------------------------------------------------ 50 MakeDisableCommand(bit32 * command,bool isClearFrameBufferCache)51 bit32* RenderState::Culling::MakeDisableCommand( bit32* command, bool isClearFrameBufferCache ) 52 { 53 // 0x040 54 *command++ = 0x0; 55 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_CULL_FACE, 0x1 ); 56 57 if ( isClearFrameBufferCache ) 58 { 59 command = FBAccess::MakeClearCacheCommand( command ); 60 } 61 62 return command; 63 } 64 65 //------------------------------------------------------------------------------ 66 MakeCommand(bit32 * command,bool isUpdateFBAccess) const67 bit32* RenderState::Blend::MakeCommand( bit32* command, bool isUpdateFBAccess ) const 68 { 69 if ( isEnable ) 70 { 71 // 0x100 72 *command++ = PICA_CMD_DATA_COLOR_OPERATION( PICA_DATA_FRAGOP_MODE_DMP, PICA_DATA_ENABLE_BLEND ); 73 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_COLOR_OPERATION, 0x3 ); 74 75 // 0x101 76 *command++ = PICA_CMD_DATA_BLEND_FUNC_SEPARATE( eqRgb, eqAlpha, srcRgb, dstRgb, srcAlpha, dstAlpha ); 77 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_BLEND_FUNC ); 78 79 // 0x102 80 *command++ = PICA_CMD_DATA_LOGIC_OP( PICA_DATA_LOGIC_NOOP ); 81 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_LOGIC_OP ); 82 83 // 0x103 84 *command++ = colorR | colorG << 8 | colorB << 16 | colorA << 24; 85 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_BLEND_COLOR ); 86 } 87 else 88 { 89 command = Blend::MakeDisableCommand( command, false ); 90 } 91 92 return isUpdateFBAccess ? m_RenderState.fbAccess.MakeCommand( command ) : command; 93 } 94 95 //------------------------------------------------------------------------------ 96 MakeDisableCommand(bit32 * command,bool isClearFrameBufferCache)97 bit32* RenderState::Blend::MakeDisableCommand( bit32* command, bool isClearFrameBufferCache ) 98 { 99 // 0x100 100 *command++ = PICA_CMD_DATA_COLOR_OPERATION( PICA_DATA_FRAGOP_MODE_DMP, PICA_DATA_ENABLE_BLEND ); 101 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_COLOR_OPERATION, 0x3 ); 102 103 // 0x101 104 *command++ = PICA_CMD_DATA_BLEND_FUNC( PICA_DATA_BLEND_EQUATION_ADD, PICA_DATA_BLEND_FUNC_ONE, PICA_DATA_BLEND_FUNC_ZERO ); 105 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_BLEND_FUNC ); 106 107 if ( isClearFrameBufferCache ) 108 { 109 command = FBAccess::MakeClearCacheCommand( command ); 110 } 111 112 return command; 113 } 114 115 //------------------------------------------------------------------------------ 116 MakeCommand(bit32 * command,bool isUpdateFBAccess) const117 bit32* RenderState::LogicOp::MakeCommand( bit32* command, bool isUpdateFBAccess ) const 118 { 119 if ( isEnable ) 120 { 121 // 0x100 122 *command++ = PICA_CMD_DATA_COLOR_OPERATION( PICA_DATA_FRAGOP_MODE_DMP, PICA_DATA_ENABLE_COLOR_LOGIC_OP ); 123 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_COLOR_OPERATION, 0x3 ); 124 125 // 0x101 126 *command++ = PICA_CMD_DATA_LOGIC_OP_ENABLE(); 127 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_BLEND_FUNC ); 128 129 // 0x102 130 *command++ = PICA_CMD_DATA_LOGIC_OP( opCode ); 131 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_LOGIC_OP ); 132 } 133 134 return isUpdateFBAccess ? m_RenderState.fbAccess.MakeCommand( command ) : command; 135 } 136 137 //------------------------------------------------------------------------------ 138 MakeCommand(bit32 * command,bool isUpdateFBAccess) const139 bit32* RenderState::AlphaTest::MakeCommand( bit32* command, bool isUpdateFBAccess ) const 140 { 141 // 0x104 142 *command++ = PICA_CMD_DATA_FRAGOP_ALPHA_TEST( isEnable, func, refValue ); 143 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_FRAGOP_ALPHA_TEST, 0x3 ); 144 145 return isUpdateFBAccess ? m_RenderState.fbAccess.MakeCommand( command ) : command; 146 } 147 148 //------------------------------------------------------------------------------ 149 MakeDisableCommand(bit32 * command,bool isClearFrameBufferCache)150 bit32* RenderState::AlphaTest::MakeDisableCommand( bit32* command, bool isClearFrameBufferCache ) 151 { 152 // 0x104 153 *command++ = 0x0; 154 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_FRAGOP_ALPHA_TEST, 0x1 ); 155 156 if ( isClearFrameBufferCache ) 157 { 158 command = FBAccess::MakeClearCacheCommand( command ); 159 } 160 161 return command; 162 } 163 164 //------------------------------------------------------------------------------ 165 MakeCommand(bit32 * command,bool isUpdateFBAccess) const166 bit32* RenderState::StencilTest::MakeCommand( bit32* command, bool isUpdateFBAccess ) const 167 { 168 // 0x105 169 *command++ = PICA_CMD_DATA_STENCIL_TEST( isEnable, func, maskOp, ref, mask ); 170 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_STENCIL_TEST ); 171 172 // 0x106 173 *command++ = PICA_CMD_DATA_STENCIL_OP( opFail, opZFail, opZPass ); 174 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_STENCIL_OP ); 175 176 return isUpdateFBAccess ? m_RenderState.fbAccess.MakeCommand( command ) : command; 177 } 178 179 //------------------------------------------------------------------------------ 180 MakeDisableCommand(bit32 * command,bool isClearFrameBufferCache)181 bit32* RenderState::StencilTest::MakeDisableCommand( bit32* command, bool isClearFrameBufferCache ) 182 { 183 // 0x105 184 *command++ = 0x0; 185 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_STENCIL_TEST, 0x1 ); 186 187 if ( isClearFrameBufferCache ) 188 { 189 command = FBAccess::MakeClearCacheCommand( command ); 190 } 191 192 return command; 193 } 194 195 //------------------------------------------------------------------------------ 196 MakeCommand(bit32 * command,bool isUpdateFBAccess) const197 bit32* RenderState::DepthTest::MakeCommand( bit32* command, bool isUpdateFBAccess ) const 198 { 199 // 0x107の[ 0:7 ]と[12:12]がデプステストの設定で、[8:11]がカラーマスクの設定です。 200 *command++ = PICA_CMD_DATA_DEPTH_COLOR_MASK( isEnable, 201 func, 202 m_RenderState.colorMask & COLOR_MASK_R, 203 m_RenderState.colorMask & COLOR_MASK_G, 204 m_RenderState.colorMask & COLOR_MASK_B, 205 m_RenderState.colorMask & COLOR_MASK_A, 206 isEnableWrite ); 207 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_DEPTH_COLOR_MASK ); 208 209 return isUpdateFBAccess ? m_RenderState.fbAccess.MakeCommand( command ) : command; 210 } 211 212 //------------------------------------------------------------------------------ 213 MakeDisableCommand(bit32 * command,bool isClearFrameBufferCache)214 bit32* RenderState::DepthTest::MakeDisableCommand( bit32* command, bool isClearFrameBufferCache ) 215 { 216 const bool isEnableDepth = false; 217 const PicaDataDepthTest depthFunc = PICA_DATA_DEPTH_TEST_LESS; 218 const bool colorMaskRed = true; 219 const bool colorMaskGreen = true; 220 const bool colorMaskBlue = true; 221 const bool colorMaskAlpha = true; 222 const bool isEnableDepthWrite = false; 223 224 // 0x107の[ 0:7 ]と[12:12]がデプステストの設定で、[8:11]がカラーマスクの設定です。 225 *command++ = PICA_CMD_DATA_DEPTH_COLOR_MASK( isEnableDepth, 226 depthFunc, 227 colorMaskRed, 228 colorMaskGreen, 229 colorMaskBlue, 230 colorMaskAlpha, 231 isEnableDepthWrite ); 232 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_DEPTH_COLOR_MASK ); 233 234 if ( isClearFrameBufferCache ) 235 { 236 command = FBAccess::MakeClearCacheCommand( command ); 237 } 238 239 return command; 240 } 241 242 //------------------------------------------------------------------------------ 243 MakeCommand(bit32 * command,bool isUpdateFBAccess) const244 bit32* RenderState::WBuffer::MakeCommand( bit32* command, bool isUpdateFBAccess ) const 245 { 246 // w バッファが無効のとき 247 if ( wScale == 0.f ) 248 { 249 // 0x6d 250 *command++ = 1; 251 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE ); 252 253 // 0x04d 254 *command++ = Float32ToFloat24( depthRangeNear - depthRangeFar ); 255 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE_DATA1 ); 256 257 // 0x04e 258 // ポリゴンオフセットを設定する 259 f32 zNear = isEnablePolygonOffset ? 260 depthRangeNear - (depthRangeNear - depthRangeFar) * polygonOffsetUnit / f32( (1 << depthRangeBit) - 1) : 261 depthRangeNear; 262 *command++ = Float32ToFloat24( zNear ); 263 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE_DATA2 ); 264 } 265 // w バッファが有効のとき 266 else 267 { 268 // 0x6d 269 *command++ = 0; 270 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE ); 271 272 // 0x04d 273 *command++ = Float32ToFloat24( - wScale ); 274 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE_DATA1 ); 275 276 // 0x04e 277 *command++ = isEnablePolygonOffset ? 278 ( ( depthRangeBit == 24 ) ? 279 // 24 bit float の精度限界により誤差で消えてしまうのを避けるため、 280 // 0.5f 付近の深度値を基準として、128.0f をかけておきます。 281 ( polygonOffsetUnit * 128.0f / f32( (1 << depthRangeBit) - 1 ) ) : 282 ( polygonOffsetUnit / f32( (1 << depthRangeBit) - 1 ) ) ) 283 : 0.0f; 284 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE_DATA2 ); 285 } 286 287 return isUpdateFBAccess ? m_RenderState.fbAccess.MakeCommand( command ) : command; 288 } 289 290 //------------------------------------------------------------------------------ 291 MakeCommand(bit32 * command,bool isClearFrameBufferCache) const292 bit32* RenderState::FBAccess::MakeCommand( bit32* command, bool isClearFrameBufferCache ) const 293 { 294 if ( isClearFrameBufferCache ) 295 { 296 // 0x111 297 *command++ = 0x1; 298 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_COLOR_DEPTH_BUFFER_CLEAR1 ); 299 300 // 0x110 301 *command++ = 0x1; 302 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_COLOR_DEPTH_BUFFER_CLEAR0 ); 303 } 304 305 // 0x112 306 *command++ = ( (m_RenderState.colorMask && m_RenderState.colorMask != 0xf) || 307 (m_RenderState.colorMask && m_RenderState.blend.isEnable ) || 308 (m_RenderState.colorMask && m_RenderState.logicOp.isEnable ) ) ? 0xf : 0; 309 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_COLOR_BUFFER_READ, 0x1 ); 310 311 // 0x113 312 *command++ = m_RenderState.colorMask ? 0xf : 0; 313 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_COLOR_BUFFER_WRITE, 0x1 ); 314 315 bit32 depth_stencil_read = 0; 316 bit32 depth_stencil_write = 0; 317 318 if ( m_RenderState.depthTest.isEnable ) 319 { 320 if ( m_RenderState.depthTest.isEnableWrite ) { depth_stencil_read |= 2; depth_stencil_write |= 2; } 321 else if ( m_RenderState.colorMask ) { depth_stencil_read |= 2; } 322 } 323 324 if ( m_RenderState.stencilTest.isEnable ) 325 { 326 if ( m_RenderState.stencilTest.maskOp != 0 ) { depth_stencil_read |= 1; depth_stencil_write |= 1; } 327 else if ( m_RenderState.colorMask ) { depth_stencil_read |= 1; } 328 } 329 330 // 0x114 331 *command++ = depth_stencil_read; 332 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DEPTH_STENCIL_BUFFER_READ, 0x1 ); 333 334 // 0x115 335 *command++ = depth_stencil_write; 336 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DEPTH_STENCIL_BUFFER_WRITE, 0x1 ); 337 338 return command; 339 } 340 341 //------------------------------------------------------------------------------ 342 MakeDisableCommand(bit32 * command,bool isClearFrameBufferCache)343 bit32* RenderState::FBAccess::MakeDisableCommand( bit32* command, bool isClearFrameBufferCache ) 344 { 345 if ( isClearFrameBufferCache ) 346 { 347 command = MakeClearCacheCommand( command ); 348 } 349 350 // 0x112 : Color read 351 *command++ = 0xf; 352 *command++ = PICA_CMD_HEADER_BURSTSEQ_BE( PICA_REG_COLOR_BUFFER_READ, 0x4, 0x1 ); 353 354 // 0x113 : Color write 355 *command++ = 0xf; 356 // 0x114 : Depth/Stencil read 357 *command++ = 0x0; 358 359 // 0x115 : Depth/Stencil write 360 *command++ = 0x0; 361 // padding 362 *command++ = 0x0; 363 364 return command; 365 } 366 367 //------------------------------------------------------------------------------ 368 MakeClearCacheCommand(bit32 * command)369 bit32* RenderState::FBAccess::MakeClearCacheCommand( bit32* command ) 370 { 371 // 0x111 372 *command++ = 0x1; 373 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_COLOR_DEPTH_BUFFER_CLEAR1 ); 374 375 // 0x110 376 *command++ = 0x1; 377 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_COLOR_DEPTH_BUFFER_CLEAR0 ); 378 379 return command; 380 } 381 382 //------------------------------------------------------------------------------ 383 MakeCommand(bit32 * buffer,bool isClearFrameBufferCache) const384 bit32* RenderState::RenderState::MakeCommand( bit32* buffer, bool isClearFrameBufferCache ) const 385 { 386 bit32* command = buffer; 387 388 command = cullingTest.MakeCommand( command, false ); 389 command = blend.MakeCommand( command, false ); 390 command = logicOp.MakeCommand( command, false ); 391 command = alphaTest.MakeCommand( command, false ); 392 command = stencilTest.MakeCommand( command, false ); 393 command = depthTest.MakeCommand( command, false ); 394 command = wBuffer.MakeCommand( command, false ); 395 command = fbAccess.MakeCommand( command, isClearFrameBufferCache ); 396 397 return command; 398 } 399 400 //------------------------------------------------------------------------------ 401 Culling(const RenderState & renderState_)402 RenderState::Culling::Culling( const RenderState& renderState_ ) 403 : isEnable( true ), 404 frontFace( FRONT_FACE_CCW ), 405 cullFace( CULL_FACE_BACK ), 406 m_RenderState( renderState_ ) 407 { 408 } 409 410 //------------------------------------------------------------------------------ 411 Blend(const RenderState & renderState_)412 RenderState::Blend::Blend( const RenderState& renderState_ ) 413 : isEnable( false ), 414 eqRgb ( PICA_DATA_BLEND_EQUATION_ADD ), 415 eqAlpha ( PICA_DATA_BLEND_EQUATION_ADD ), 416 srcRgb ( PICA_DATA_BLEND_FUNC_SRC_ALPHA ), 417 srcAlpha( PICA_DATA_BLEND_FUNC_SRC_ALPHA ), 418 dstRgb ( PICA_DATA_BLEND_FUNC_ONE_MINUS_SRC_ALPHA ), 419 dstAlpha( PICA_DATA_BLEND_FUNC_ONE_MINUS_SRC_ALPHA ), 420 colorR( 0xff), 421 colorG( 0xff), 422 colorB( 0xff), 423 colorA( 0xff), 424 m_RenderState( renderState_ ) 425 { 426 } 427 428 //------------------------------------------------------------------------------ 429 LogicOp(const RenderState & renderState_)430 RenderState::LogicOp::LogicOp( const RenderState& renderState_ ) 431 : isEnable( false ), 432 opCode( PICA_DATA_LOGIC_NOOP ), 433 m_RenderState( renderState_ ) 434 { 435 } 436 437 //------------------------------------------------------------------------------ 438 AlphaTest(const RenderState & renderState_)439 RenderState::AlphaTest::AlphaTest( const RenderState& renderState_ ) 440 : isEnable( false ), 441 refValue( 0 ), 442 func ( PICA_DATA_ALPHA_TEST_NEVER ), 443 m_RenderState( renderState_ ) 444 { 445 } 446 447 //------------------------------------------------------------------------------ 448 StencilTest(const RenderState & renderState_)449 RenderState::StencilTest::StencilTest( const RenderState& renderState_ ) 450 : isEnable ( false ), 451 maskOp ( 0 ), 452 func ( PICA_DATA_STENCIL_TEST_ALWAYS ), 453 ref ( 0 ), 454 mask ( 0xff ), 455 opFail ( PICA_DATA_STENCIL_OP_KEEP ), 456 opZFail ( PICA_DATA_STENCIL_OP_KEEP ), 457 opZPass ( PICA_DATA_STENCIL_OP_KEEP ), 458 m_RenderState ( renderState_ ) 459 { 460 } 461 462 //------------------------------------------------------------------------------ 463 DepthTest(const RenderState & renderState_)464 RenderState::DepthTest::DepthTest( const RenderState& renderState_ ) 465 : isEnable( true ), 466 isEnableWrite( true ), 467 func( PICA_DATA_DEPTH_TEST_LESS ), 468 m_RenderState( renderState_ ) 469 { 470 } 471 472 //------------------------------------------------------------------------------ 473 WBuffer(const RenderState & renderState_)474 RenderState::WBuffer::WBuffer( const RenderState& renderState_ ) 475 : wScale( 0.f ), 476 isEnablePolygonOffset( false ), 477 polygonOffsetUnit ( 0.f ), 478 depthRangeNear ( 0.0f ), 479 depthRangeFar ( 1.0f ), 480 depthRangeBit ( 24 ), 481 m_RenderState ( renderState_ ) 482 { 483 } 484 485 486 //------------------------------------------------------------------------------ 487 FBAccess(const RenderState & renderState_)488 RenderState::FBAccess::FBAccess( const RenderState& renderState_ ) 489 : m_RenderState( renderState_ ) 490 { 491 } 492 493 //------------------------------------------------------------------------------ 494 RenderState()495 RenderState::RenderState() : 496 blend ( *this ), 497 logicOp ( *this ), 498 alphaTest ( *this ), 499 stencilTest ( *this ), 500 colorMask ( COLOR_MASK_RGBA ), 501 depthTest ( *this ), 502 cullingTest ( *this ), 503 wBuffer ( *this ), 504 fbAccess ( *this ) 505 { 506 } 507 508 //------------------------------------------------------------------------------ 509 MakeDisableCommand(bit32 * command,bool isClearFrameBufferCache)510 bit32* RenderState::MakeDisableCommand( bit32* command, bool isClearFrameBufferCache ) 511 { 512 command = Culling::MakeDisableCommand( command, false ); 513 command = Blend::MakeDisableCommand( command, false ); 514 command = AlphaTest::MakeDisableCommand( command, false ); 515 command = StencilTest::MakeDisableCommand( command, false ); 516 command = DepthTest::MakeDisableCommand( command, false ); 517 command = FBAccess::MakeDisableCommand( command, isClearFrameBufferCache ); 518 519 return command; 520 } 521 522 } // namespace CTR 523 } // namespace gr 524 } // namespace nn 525