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: 25760 $
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(u32 * command,bool isUpdateFBAccess) const25             u32* RenderState::Culling::MakeCommand( u32* command, bool isUpdateFBAccess ) const
26             {
27                 u32 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(u32 * command,bool isUpdateFBAccess) const51             u32* RenderState::Blend::MakeCommand( u32* 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(u32 * command,bool isUpdateFBAccess) const87             u32* RenderState::LogicOp::MakeCommand( u32* 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(u32 * command,bool isUpdateFBAccess) const109             u32* RenderState::AlphaTest::MakeCommand( u32* 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(u32 * command,bool isUpdateFBAccess) const120             u32* RenderState::StencilTest::MakeCommand( u32* command, bool isUpdateFBAccess ) const
121             {
122                 // 0x105
123                 *command++ = PICA_CMD_DATA_STENCIL_TEST( isEnable, func, isEnableWrite, 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(u32 * command,bool isUpdateFBAccess) const135             u32* RenderState::DepthTest::MakeCommand( u32* 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(u32 * command,bool isUpdateFBAccess) const152             u32* RenderState::WBuffer::MakeCommand( u32* command, bool isUpdateFBAccess ) const
153             {
154                 if ( wScale == 0.f )
155                 {
156                     // 0x6d
157                     *command++ = 1;
158                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE );
159 
160                     // 0x04d
161                     *command++ = Float32ToFloat24( depthRangeNear - depthRangeFar );
162                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE_DATA1 );
163 
164                     // 0x04e
165                     f32 zNear = isEnablePolygonOffset ? depthRangeNear - (depthRangeNear - depthRangeFar) * polygonOffsetUnit / f32(1 << depthRangeBit - 1) : depthRangeNear;
166                     *command++ = Float32ToFloat24( zNear );
167                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE_DATA2 );
168                 }
169                 else
170                 {
171                     // 0x6d
172                     *command++ = 0;
173                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE );
174 
175                     // 0x04d
176                     *command++ = Float32ToFloat24( -wScale );
177                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE_DATA1 );
178 
179                     // 0x04e
180                     *command++ = 0;
181                     *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_WSCALE_DATA2 );
182                 }
183 
184                 return isUpdateFBAccess ? m_RenderState.fbAccess.MakeCommand( command ) : command;
185             }
186 
187             //------------------------------------------------------------------------------
188 
MakeCommand(u32 * command) const189             u32* RenderState::FBAccess::MakeCommand( u32* command ) const
190             {
191                 // 0x111
192                 *command++ = 1;
193                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_COLOR_DEPTH_BUFFER_CLEAR1 );
194 
195                 // 0x110
196                 *command++ = 1;
197                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_COLOR_DEPTH_BUFFER_CLEAR0 );
198 
199                 // 0x112
200                 *command++ = ( (m_RenderState.colorMask && m_RenderState.colorMask != 0xf)  ||
201                                (m_RenderState.colorMask && m_RenderState.blend.isEnable ) ||
202                                (m_RenderState.colorMask && m_RenderState.logicOp.isEnable ) ) ? 0xf : 0;
203                 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_COLOR_BUFFER_READ, 0x1 );
204 
205                 // 0x113
206                 *command++ = m_RenderState.colorMask ? 0xf : 0;
207                 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_COLOR_BUFFER_WRITE, 0x1 );
208 
209                 u32 depth_stencil_read = 0;
210                 u32 depth_stencil_write = 0;
211 
212                 if ( m_RenderState.depthTest.isEnable )
213                 {
214                     if ( m_RenderState.depthTest.isEnableWrite )   { depth_stencil_read  |= 2;  depth_stencil_write |= 2;  }
215                     else if ( m_RenderState.colorMask )            { depth_stencil_read  |= 2; }
216                 }
217 
218                 if ( m_RenderState.stencilTest.isEnable )
219                 {
220                     if ( m_RenderState.stencilTest.isEnableWrite ) { depth_stencil_read  |= 1;  depth_stencil_write |= 1;  }
221                     else if ( m_RenderState.colorMask )            { depth_stencil_read  |= 1; }
222                 }
223 
224                 // 0x114
225                 *command++ = depth_stencil_read;
226                 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DEPTH_STENCIL_BUFFER_READ,  0x1 );
227 
228                 // 0x115
229                 *command++ = depth_stencil_write;
230                 *command++ = PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DEPTH_STENCIL_BUFFER_WRITE, 0x1 );
231 
232                 return command;
233             }
234 
235             //------------------------------------------------------------------------------
236 
MakeCommand(u32 * buffer) const237             u32* RenderState::RenderState::MakeCommand( u32* buffer ) const
238             {
239                 u32* command = buffer;
240 
241                 command = cullingTest.MakeCommand( command, false );
242                 command = blend.MakeCommand( command, false );
243                 command = logicOp.MakeCommand( command, false );
244                 command = alphaTest.MakeCommand( command, false );
245                 command = stencilTest.MakeCommand( command, false );
246                 command = depthTest.MakeCommand( command, false );
247                 command = wBuffer.MakeCommand( command, false );
248                 command = fbAccess.MakeCommand( command );
249 
250                 return command;
251             }
252 
253             //------------------------------------------------------------------------------
254 
Culling(const RenderState & renderState_)255             RenderState::Culling::Culling( const RenderState& renderState_ )
256                 : isEnable( true ),
257                   frontFace( FRONT_FACE_CCW ),
258                   cullFace(  CULL_FACE_BACK ),
259                   m_RenderState( renderState_ )
260             {
261             }
262 
263             //------------------------------------------------------------------------------
264 
Blend(const RenderState & renderState_)265             RenderState::Blend::Blend( const RenderState& renderState_ )
266                 : isEnable( false ),
267                   eqRgb   ( PICA_DATA_BLEND_EQUATION_ADD ),
268                   eqAlpha ( PICA_DATA_BLEND_EQUATION_ADD ),
269                   srcRgb  ( PICA_DATA_BLEND_FUNC_SRC_ALPHA ),
270                   srcAlpha( PICA_DATA_BLEND_FUNC_SRC_ALPHA ),
271                   dstRgb  ( PICA_DATA_BLEND_FUNC_ONE_MINUS_SRC_ALPHA ),
272                   dstAlpha( PICA_DATA_BLEND_FUNC_ONE_MINUS_SRC_ALPHA ),
273                   colorR( 0xff),
274                   colorG( 0xff),
275                   colorB( 0xff),
276                   colorA( 0xff),
277                   m_RenderState( renderState_ )
278             {
279             }
280 
281             //------------------------------------------------------------------------------
282 
LogicOp(const RenderState & renderState_)283             RenderState::LogicOp::LogicOp( const RenderState& renderState_ )
284                 : isEnable( false ),
285                   opCode( PICA_DATA_LOGIC_NOOP ),
286                   m_RenderState( renderState_ )
287             {
288             }
289 
290             //------------------------------------------------------------------------------
291 
AlphaTest(const RenderState & renderState_)292             RenderState::AlphaTest::AlphaTest( const RenderState& renderState_ )
293                 : isEnable( false ),
294                   refValue( 0 ),
295                   func ( PICA_DATA_ALPHA_TEST_NEVER ),
296                   m_RenderState( renderState_ )
297             {
298             }
299 
300             //------------------------------------------------------------------------------
301 
StencilTest(const RenderState & renderState_)302             RenderState::StencilTest::StencilTest( const RenderState& renderState_ )
303                 : isEnable     ( false ),
304                   isEnableWrite( false ),
305                   func         ( PICA_DATA_STENCIL_TEST_ALWAYS ),
306                   ref          ( 0 ),
307                   mask         ( 0xff ),
308                   opFail       ( PICA_DATA_STENCIL_OP_KEEP ),
309                   opZFail      ( PICA_DATA_STENCIL_OP_KEEP ),
310                   opZPass      ( PICA_DATA_STENCIL_OP_KEEP ),
311                   m_RenderState  ( renderState_ )
312             {
313             }
314 
315             //------------------------------------------------------------------------------
316 
DepthTest(const RenderState & renderState_)317             RenderState::DepthTest::DepthTest( const RenderState& renderState_ )
318                 : isEnable( true ),
319                   isEnableWrite( true ),
320                   func( PICA_DATA_DEPTH_TEST_LESS ),
321                   m_RenderState( renderState_ )
322             {
323             }
324 
325             //------------------------------------------------------------------------------
326 
WBuffer(const RenderState & renderState_)327             RenderState::WBuffer::WBuffer( const RenderState& renderState_ )
328                 : wScale( 0.f ),
329                   isEnablePolygonOffset( false ),
330                   polygonOffsetUnit    ( 0.f ),
331                   depthRangeNear       ( 0.0f ),
332                   depthRangeFar        ( 1.0f ),
333                   depthRangeBit        ( 24 ),
334                   m_RenderState        ( renderState_ )
335             {
336             }
337 
338 
339             //------------------------------------------------------------------------------
340 
FBAccess(const RenderState & renderState_)341             RenderState::FBAccess::FBAccess( const RenderState& renderState_ )
342                 : m_RenderState( renderState_ )
343             {
344             }
345 
346             //------------------------------------------------------------------------------
347 
RenderState()348             RenderState::RenderState() :
349                   blend       ( *this ),
350                   logicOp     ( *this ),
351                   alphaTest   ( *this ),
352                   stencilTest ( *this ),
353                   colorMask   ( COLOR_MASK_RGBA ),
354                   depthTest   ( *this ),
355                   cullingTest ( *this ),
356                   wBuffer     ( *this ),
357                   fbAccess    ( *this )
358             {
359             }
360 
361         } // namespace CTR
362     } // namespace gr
363 } // namespace nn
364