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: 30083 $ 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 MakeCommand(bit32 * command,bool isUpdateFBAccess) const51 bit32* RenderState::Blend::MakeCommand( bit32* command, bool isUpdateFBAccess ) const 52 { 53 if ( isEnable ) 54 { 55 // 0x100 56 *command++ = PICA_CMD_DATA_COLOR_OPERATION( PICA_DATA_FRAGOP_MODE_DMP, PICA_DATA_ENABLE_BLEND ); 57 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_COLOR_OPERATION, 0x3 ); 58 59 // 0x101 60 *command++ = PICA_CMD_DATA_BLEND_FUNC_SEPARATE( eqRgb, eqAlpha, srcRgb, dstRgb, srcAlpha, dstAlpha ); 61 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_BLEND_FUNC ); 62 63 // 0x102 64 *command++ = PICA_CMD_DATA_LOGIC_OP( PICA_DATA_LOGIC_NOOP ); 65 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_LOGIC_OP ); 66 67 // 0x103 68 *command++ = colorR | colorG << 8 | colorB << 16 | colorA << 24; 69 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_BLEND_COLOR ); 70 } 71 else 72 { 73 // 0x100 74 *command++ = PICA_CMD_DATA_COLOR_OPERATION( PICA_DATA_FRAGOP_MODE_DMP, PICA_DATA_ENABLE_BLEND ); 75 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_COLOR_OPERATION, 0x3 ); 76 77 // 0x101 78 *command++ = PICA_CMD_DATA_BLEND_FUNC( PICA_DATA_BLEND_EQUATION_ADD, PICA_DATA_BLEND_FUNC_ONE, PICA_DATA_BLEND_FUNC_ZERO ); 79 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_BLEND_FUNC ); 80 } 81 82 return isUpdateFBAccess ? m_RenderState.fbAccess.MakeCommand( command ) : command; 83 } 84 85 //------------------------------------------------------------------------------ 86 MakeCommand(bit32 * command,bool isUpdateFBAccess) const87 bit32* RenderState::LogicOp::MakeCommand( bit32* command, bool isUpdateFBAccess ) const 88 { 89 if ( isEnable ) 90 { 91 // 0x100 92 *command++ = PICA_CMD_DATA_COLOR_OPERATION( PICA_DATA_FRAGOP_MODE_DMP, PICA_DATA_ENABLE_COLOR_LOGIC_OP ); 93 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_COLOR_OPERATION, 0x3 ); 94 95 // 0x101 96 *command++ = PICA_CMD_DATA_LOGIC_OP_ENABLE(); 97 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_BLEND_FUNC ); 98 99 // 0x102 100 *command++ = PICA_CMD_DATA_LOGIC_OP( opCode ); 101 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_LOGIC_OP ); 102 } 103 104 return isUpdateFBAccess ? m_RenderState.fbAccess.MakeCommand( command ) : command; 105 } 106 107 //------------------------------------------------------------------------------ 108 MakeCommand(bit32 * command,bool isUpdateFBAccess) const109 bit32* RenderState::AlphaTest::MakeCommand( bit32* command, bool isUpdateFBAccess ) const 110 { 111 // 0x104 112 *command++ = PICA_CMD_DATA_FRAGOP_ALPHA_TEST( isEnable, func, refValue ); 113 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_FRAGOP_ALPHA_TEST, 0x3 ); 114 115 return isUpdateFBAccess ? m_RenderState.fbAccess.MakeCommand( command ) : command; 116 } 117 118 //------------------------------------------------------------------------------ 119 MakeCommand(bit32 * command,bool isUpdateFBAccess) const120 bit32* RenderState::StencilTest::MakeCommand( bit32* command, bool isUpdateFBAccess ) const 121 { 122 // 0x105 123 *command++ = PICA_CMD_DATA_STENCIL_TEST( isEnable, func, maskOp, ref, mask ); 124 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_STENCIL_TEST ); 125 126 // 0x106 127 *command++ = PICA_CMD_DATA_STENCIL_OP( opFail, opZFail, opZPass ); 128 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_STENCIL_OP ); 129 130 return isUpdateFBAccess ? m_RenderState.fbAccess.MakeCommand( command ) : command; 131 } 132 133 //------------------------------------------------------------------------------ 134 MakeCommand(bit32 * command,bool isUpdateFBAccess) const135 bit32* RenderState::DepthTest::MakeCommand( bit32* command, bool isUpdateFBAccess ) const 136 { 137 // 0x107の[ 0:7 ]と[12:12]がデプステストの設定で、[8:11]がカラーマスクの設定です。 138 *command++ = PICA_CMD_DATA_DEPTH_COLOR_MASK( isEnable, 139 func, 140 m_RenderState.colorMask & COLOR_MASK_R, 141 m_RenderState.colorMask & COLOR_MASK_G, 142 m_RenderState.colorMask & COLOR_MASK_B, 143 m_RenderState.colorMask & COLOR_MASK_A, 144 isEnableWrite ); 145 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_DEPTH_COLOR_MASK ); 146 147 return isUpdateFBAccess ? m_RenderState.fbAccess.MakeCommand( command ) : command; 148 } 149 150 //------------------------------------------------------------------------------ 151 MakeCommand(bit32 * command,bool isUpdateFBAccess) const152 bit32* RenderState::WBuffer::MakeCommand( bit32* command, bool isUpdateFBAccess ) const 153 { 154 // w バッファが無効のとき 155 if ( wScale == 0.f ) 156 { 157 // 0x6d 158 *command++ = 1; 159 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE ); 160 161 // 0x04d 162 *command++ = Float32ToFloat24( depthRangeNear - depthRangeFar ); 163 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE_DATA1 ); 164 165 // 0x04e 166 // ポリゴンオフセットを設定する 167 f32 zNear = isEnablePolygonOffset ? 168 depthRangeNear - (depthRangeNear - depthRangeFar) * polygonOffsetUnit / f32( (1 << depthRangeBit) - 1) : 169 depthRangeNear; 170 *command++ = Float32ToFloat24( zNear ); 171 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE_DATA2 ); 172 } 173 // w バッファが有効のとき 174 else 175 { 176 // 0x6d 177 *command++ = 0; 178 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE ); 179 180 // 0x04d 181 *command++ = Float32ToFloat24( - wScale ); 182 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE_DATA1 ); 183 184 // 0x04e 185 *command++ = isEnablePolygonOffset ? 186 ( ( depthRangeBit == 24 ) ? 187 // 24 bit float の精度限界により誤差で消えてしまうのを避けるため、 188 // 0.5f 付近の深度値を基準として、128.0f をかけておきます。 189 ( polygonOffsetUnit * 128.0f / f32( (1 << depthRangeBit) - 1 ) ) : 190 ( polygonOffsetUnit / f32( (1 << depthRangeBit) - 1 ) ) ) 191 : 0.0f; 192 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE_DATA2 ); 193 } 194 195 return isUpdateFBAccess ? m_RenderState.fbAccess.MakeCommand( command ) : command; 196 } 197 198 //------------------------------------------------------------------------------ 199 MakeCommand(bit32 * command,bool isClearFrameBufferCache) const200 bit32* RenderState::FBAccess::MakeCommand( bit32* command, bool isClearFrameBufferCache ) const 201 { 202 if ( isClearFrameBufferCache ) 203 { 204 // 0x111 205 *command++ = 0x1; 206 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_COLOR_DEPTH_BUFFER_CLEAR1 ); 207 208 // 0x110 209 *command++ = 0x1; 210 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_COLOR_DEPTH_BUFFER_CLEAR0 ); 211 } 212 213 // 0x112 214 *command++ = ( (m_RenderState.colorMask && m_RenderState.colorMask != 0xf) || 215 (m_RenderState.colorMask && m_RenderState.blend.isEnable ) || 216 (m_RenderState.colorMask && m_RenderState.logicOp.isEnable ) ) ? 0xf : 0; 217 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_COLOR_BUFFER_READ, 0x1 ); 218 219 // 0x113 220 *command++ = m_RenderState.colorMask ? 0xf : 0; 221 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_COLOR_BUFFER_WRITE, 0x1 ); 222 223 bit32 depth_stencil_read = 0; 224 bit32 depth_stencil_write = 0; 225 226 if ( m_RenderState.depthTest.isEnable ) 227 { 228 if ( m_RenderState.depthTest.isEnableWrite ) { depth_stencil_read |= 2; depth_stencil_write |= 2; } 229 else if ( m_RenderState.colorMask ) { depth_stencil_read |= 2; } 230 } 231 232 if ( m_RenderState.stencilTest.isEnable ) 233 { 234 if ( m_RenderState.stencilTest.maskOp != 0 ) { depth_stencil_read |= 1; depth_stencil_write |= 1; } 235 else if ( m_RenderState.colorMask ) { depth_stencil_read |= 1; } 236 } 237 238 // 0x114 239 *command++ = depth_stencil_read; 240 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DEPTH_STENCIL_BUFFER_READ, 0x1 ); 241 242 // 0x115 243 *command++ = depth_stencil_write; 244 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DEPTH_STENCIL_BUFFER_WRITE, 0x1 ); 245 246 return command; 247 } 248 249 //------------------------------------------------------------------------------ 250 MakeCommand(bit32 * buffer,bool isClearFrameBufferCache) const251 bit32* RenderState::RenderState::MakeCommand( bit32* buffer, bool isClearFrameBufferCache ) const 252 { 253 bit32* command = buffer; 254 255 command = cullingTest.MakeCommand( command, false ); 256 command = blend.MakeCommand( command, false ); 257 command = logicOp.MakeCommand( command, false ); 258 command = alphaTest.MakeCommand( command, false ); 259 command = stencilTest.MakeCommand( command, false ); 260 command = depthTest.MakeCommand( command, false ); 261 command = wBuffer.MakeCommand( command, false ); 262 command = fbAccess.MakeCommand( command, isClearFrameBufferCache ); 263 264 return command; 265 } 266 267 //------------------------------------------------------------------------------ 268 Culling(const RenderState & renderState_)269 RenderState::Culling::Culling( const RenderState& renderState_ ) 270 : isEnable( true ), 271 frontFace( FRONT_FACE_CCW ), 272 cullFace( CULL_FACE_BACK ), 273 m_RenderState( renderState_ ) 274 { 275 } 276 277 //------------------------------------------------------------------------------ 278 Blend(const RenderState & renderState_)279 RenderState::Blend::Blend( const RenderState& renderState_ ) 280 : isEnable( false ), 281 eqRgb ( PICA_DATA_BLEND_EQUATION_ADD ), 282 eqAlpha ( PICA_DATA_BLEND_EQUATION_ADD ), 283 srcRgb ( PICA_DATA_BLEND_FUNC_SRC_ALPHA ), 284 srcAlpha( PICA_DATA_BLEND_FUNC_SRC_ALPHA ), 285 dstRgb ( PICA_DATA_BLEND_FUNC_ONE_MINUS_SRC_ALPHA ), 286 dstAlpha( PICA_DATA_BLEND_FUNC_ONE_MINUS_SRC_ALPHA ), 287 colorR( 0xff), 288 colorG( 0xff), 289 colorB( 0xff), 290 colorA( 0xff), 291 m_RenderState( renderState_ ) 292 { 293 } 294 295 //------------------------------------------------------------------------------ 296 LogicOp(const RenderState & renderState_)297 RenderState::LogicOp::LogicOp( const RenderState& renderState_ ) 298 : isEnable( false ), 299 opCode( PICA_DATA_LOGIC_NOOP ), 300 m_RenderState( renderState_ ) 301 { 302 } 303 304 //------------------------------------------------------------------------------ 305 AlphaTest(const RenderState & renderState_)306 RenderState::AlphaTest::AlphaTest( const RenderState& renderState_ ) 307 : isEnable( false ), 308 refValue( 0 ), 309 func ( PICA_DATA_ALPHA_TEST_NEVER ), 310 m_RenderState( renderState_ ) 311 { 312 } 313 314 //------------------------------------------------------------------------------ 315 StencilTest(const RenderState & renderState_)316 RenderState::StencilTest::StencilTest( const RenderState& renderState_ ) 317 : isEnable ( false ), 318 maskOp ( 0 ), 319 func ( PICA_DATA_STENCIL_TEST_ALWAYS ), 320 ref ( 0 ), 321 mask ( 0xff ), 322 opFail ( PICA_DATA_STENCIL_OP_KEEP ), 323 opZFail ( PICA_DATA_STENCIL_OP_KEEP ), 324 opZPass ( PICA_DATA_STENCIL_OP_KEEP ), 325 m_RenderState ( renderState_ ) 326 { 327 } 328 329 //------------------------------------------------------------------------------ 330 DepthTest(const RenderState & renderState_)331 RenderState::DepthTest::DepthTest( const RenderState& renderState_ ) 332 : isEnable( true ), 333 isEnableWrite( true ), 334 func( PICA_DATA_DEPTH_TEST_LESS ), 335 m_RenderState( renderState_ ) 336 { 337 } 338 339 //------------------------------------------------------------------------------ 340 WBuffer(const RenderState & renderState_)341 RenderState::WBuffer::WBuffer( const RenderState& renderState_ ) 342 : wScale( 0.f ), 343 isEnablePolygonOffset( false ), 344 polygonOffsetUnit ( 0.f ), 345 depthRangeNear ( 0.0f ), 346 depthRangeFar ( 1.0f ), 347 depthRangeBit ( 24 ), 348 m_RenderState ( renderState_ ) 349 { 350 } 351 352 353 //------------------------------------------------------------------------------ 354 FBAccess(const RenderState & renderState_)355 RenderState::FBAccess::FBAccess( const RenderState& renderState_ ) 356 : m_RenderState( renderState_ ) 357 { 358 } 359 360 //------------------------------------------------------------------------------ 361 RenderState()362 RenderState::RenderState() : 363 blend ( *this ), 364 logicOp ( *this ), 365 alphaTest ( *this ), 366 stencilTest ( *this ), 367 colorMask ( COLOR_MASK_RGBA ), 368 depthTest ( *this ), 369 cullingTest ( *this ), 370 wBuffer ( *this ), 371 fbAccess ( *this ) 372 { 373 } 374 375 } // namespace CTR 376 } // namespace gr 377 } // namespace nn 378