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