1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     gr_FragmentLight.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: 46347 $
14  *---------------------------------------------------------------------------*/
15 
16 #include <nn/gr/CTR/gr_FragmentLight.h>
17 
18 namespace nn
19 {
20     namespace gr
21     {
22         namespace CTR
23         {
24 
MakeAllCommand(bit32 * command) const25             bit32* FragmentLight::Source::MakeAllCommand( bit32* command ) const
26             {
27                 bit32 reg = PICA_REG_FRAG_LIGHT_START + id * PICA_FRAG_LIGHT_STRIDE;
28 
29                 *command++ = specular0B | specular0G << 10 | specular0R << 20;     // specular0
30                 *command++ = PICA_CMD_HEADER_BURSTSEQ( reg, 12 );                  // Header
31                 *command++ = specular1B | specular1G << 10 | specular1R << 20;     // specular1
32                 *command++ = diffuseB   | diffuseG   << 10 | diffuseR   << 20;     // Diffuse
33                 *command++ = ambientB   | ambientG   << 10 | ambientR   << 20;     // Ambient
34                 *command++ = posXY;
35                 *command++ = posZ;
36                 *command++ = spotDirectionXY;
37                 *command++ = spotDirectionZ;
38                 *command++ = 0;
39                 *command++ = isInfinity | ( isEnableTwoSideDiffuse ? 1 : 0 ) << 1 |
40                              ( isEnableGeomFactor0 ? 1 : 0 ) << 2 | ( isEnableGeomFactor1 ? 1 : 0 ) << 3;
41                 *command++ = distAttnBias;
42                 *command++ = distAttnScale;
43                 *command++ = 0;
44 
45                 return command;
46             }
47 
48             //------------------------------------------------------------------------------
49 
MakeCommand(bit32 * command) const50             bit32* FragmentLight::Source::MakeCommand( bit32* command ) const
51             {
52                 return MakeAllCommand( command );
53             }
54 
55             //------------------------------------------------------------------------------
56 
MakeColorCommand(bit32 * command) const57             bit32* FragmentLight::Source::MakeColorCommand( bit32* command ) const
58             {
59                 bit32 reg = PICA_REG_FRAG_LIGHT_START + id * PICA_FRAG_LIGHT_STRIDE;
60 
61                 *command++ = specular0B | specular0G << 10 | specular0R << 20; // specular0
62                 *command++ = PICA_CMD_HEADER_BURSTSEQ( reg, 4 );               // Header
63 
64                 *command++ = specular1B | specular1G << 10 | specular1R << 20; // specular1
65                 *command++ = diffuseB   | diffuseG   << 10 | diffuseR   << 20; // Diffuse
66 
67                 *command++ = ambientB   | ambientG   << 10 | ambientR   << 20; // Ambient
68                 *command++ = 0;
69 
70                 return command;
71             }
72 
73             //------------------------------------------------------------------------------
74 
MakeGeometryCommand(bit32 * command) const75             bit32* FragmentLight::Source::MakeGeometryCommand( bit32* command ) const
76             {
77                 bit32 reg = PICA_REG_FRAG_LIGHT_START + id * PICA_FRAG_LIGHT_STRIDE + 0x4;
78 
79                 *command++ = posXY;
80                 *command++ = PICA_CMD_HEADER_BURSTSEQ( reg, 8 );
81 
82                 *command++ = posZ;
83                 *command++ = spotDirectionXY;
84 
85                 *command++ = spotDirectionZ;
86                 *command++ = 0;
87 
88                 *command++ = isInfinity                              |
89                              ( isEnableTwoSideDiffuse ? 1 : 0 ) << 1 |
90                              ( isEnableGeomFactor0 ? 1 : 0 )    << 2 |
91                              ( isEnableGeomFactor1 ? 1 : 0 )    << 3;
92                 *command++ = distAttnBias;
93 
94                 *command++ = distAttnScale;
95                 *command++ = 0;
96 
97                 return command;
98             }
99 
100             //------------------------------------------------------------------------------
101 
Source()102             FragmentLight::Source::Source()
103                 : id( 0 ),
104                   isEnableTwoSideDiffuse( false ),
105                   isEnableGeomFactor0( false ),
106                   isEnableGeomFactor1( false ),
107                   diffuseR( 255 ),
108                   diffuseG( 255 ),
109                   diffuseB( 255 ),
110                   ambientR(   0 ),
111                   ambientG(   0 ),
112                   ambientB(   0 ),
113                   specular0R( 255 ),
114                   specular0G( 255 ),
115                   specular0B( 255 ),
116                   specular1R( 255 ),
117                   specular1G( 255 ),
118                   specular1B( 255 ),
119                   posXY( 0 ),
120                   posZ( 0 ),
121                   isInfinity( 0 ),
122                   distAttnBias( 0 ),
123                   distAttnScale( 0 ),
124                   spotDirectionXY( 0 ),
125                   spotDirectionZ( 0 )
126             {
127             }
128 
129             //------------------------------------------------------------------------------
130 
MakeLutConfigCommand(bit32 * command) const131             bit32* FragmentLight::MakeLutConfigCommand( bit32* command ) const
132             {
133                 // 0x1d0
134                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_ABSLUTINPUT(
135                     lutConfigD0.isAbs,
136                     lutConfigD1.isAbs,
137                     lutConfigSP.isAbs,
138                     lutConfigFR.isAbs,
139                     lutConfigRB.isAbs,
140                     lutConfigRG.isAbs,
141                     lutConfigRR.isAbs );
142                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_ABSLUTINPUT );
143 
144                 // 0x1d1
145                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_LUTINPUT(
146                     lutConfigD0.input,
147                     lutConfigD1.input,
148                     lutConfigSP.input,
149                     lutConfigFR.input,
150                     lutConfigRB.input,
151                     lutConfigRG.input,
152                     lutConfigRR.input );
153                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_LUTINPUT );
154 
155                 // 0x1d2
156                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_LUTSCALE(
157                     lutConfigD0.scale,
158                     lutConfigD1.scale,
159                     lutConfigSP.scale,
160                     lutConfigFR.scale,
161                     lutConfigRB.scale,
162                     lutConfigRG.scale,
163                     lutConfigRR.scale );
164                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_LUTSCALE );
165 
166                 return command;
167             }
168 
169             //------------------------------------------------------------------------------
170 
MakeLightEnvCommand(bit32 * command,bool isAddDummyCommand) const171             bit32* FragmentLight::MakeLightEnvCommand( bit32* command, bool isAddDummyCommand ) const
172             {
173                 bit32 regLightEnable     = 0xff00ffff;
174                 bit32 regLightEnableEach = 0;
175                 s32 count = 0;
176 
177                 regLightEnable |= PICA_CMD_DATA_FRAG_LIGHT_FUNC_MODE1_LUT(
178                     isEnableLutD0,
179                     isEnableLutD1,
180                     fresnelSelector,
181                     isEnableLutRefl );
182 
183                 for ( int i = 0; i < LIGHT_SOURCE_MAX; ++i )
184                 {
185                     if ( isEnable[ i ] == false )
186                     {
187                         continue;
188                     }
189 
190                     if ( isShadowed[ i ] )
191                     {
192                         regLightEnable &= ~( 1 << i );
193                     }
194 
195                     if ( isEnableSpot[ i ] )
196                     {
197                         regLightEnable &= ~( 1 << ( 8 + i ) );
198                     }
199 
200                     if ( isEnableDistAttn[ i ] )
201                     {
202                         regLightEnable &= ~( 1 << ( 24 + i ) );
203                     }
204 
205                     regLightEnableEach |= ( i << ( count++ * 4 ) );
206                 }
207 
208                 // Before converting 0x08f, send dummy command
209                 if ( isAddDummyCommand )
210                 {
211                     *command++ = 0x0;
212                     *command++ = PICA_CMD_HEADER_BURST_BE( PICA_REG_TEXTURE_FUNC, 0x3, 0x0 );
213                     *command++ = 0x0;
214                     *command++ = 0x0;
215                 }
216 
217                 // Set whether the 0x08f light is enabled or disabled
218                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_EN( count );
219                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_EN0 );
220 
221                 // 0x1c0 global ambient settings
222                 *command++ = globalAmbientB | globalAmbientG << 10 | globalAmbientR << 20;
223                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_AMBIENT );
224 
225                 // 0x1c2 number of light source setting
226                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_NUM( count );
227                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_SRC_NUM );
228 
229                 // 0x1c3
230                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_FUNC_MODE0(
231                     fresnelSelector,
232                     layerConfig,
233                     isEnableShadowPrimary,
234                     isEnableShadowSecondary,
235                     isInvertShadow,
236                     isEnableShadowAlpha,
237                     bumpSelector,
238                     shadowSelector,
239                     isEnableClampHighLights,
240                     bumpMode,
241                     isEnableBumpRenorm );
242                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_FUNC_MODE0 );
243 
244                 // 0x1c4
245                 *command++ = regLightEnable;
246                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_FUNC_MODE1 );
247 
248                 // Set whether the 0x1c6 light is enabled or disabled
249                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_EN_INV( count );
250                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_EN1 );
251 
252                 // 0x1d9
253                 *command++ = regLightEnableEach;
254                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_SRC_EN_ID );
255                 return command;
256             }
257 
258             //------------------------------------------------------------------------------
259 
MakeLightSourceCommand(bit32 * command) const260             bit32* FragmentLight::MakeLightSourceCommand( bit32* command ) const
261             {
262                 // Sets for each light source
263                 for ( int i = 0; i < LIGHT_SOURCE_MAX; ++i )
264                 {
265                     if ( isEnable[ i ] == false ) continue;
266 
267                     command = source[ i ].MakeCommand( command );
268                 }
269 
270                 return command;
271             }
272 
273             //------------------------------------------------------------------------------
274 
MakeAllCommand(bit32 * command,bool isAddDummyCommand) const275             bit32* FragmentLight::MakeAllCommand( bit32* command, bool isAddDummyCommand ) const
276             {
277             #if defined( NN_GR_FRAGMENT_LIGHT_DUMP ) // For debugging
278                 bit32 * start = command;
279             #endif
280 
281                 command = MakeLutConfigCommand( command );
282 
283                 command = MakeLightEnvCommand( command, isAddDummyCommand );
284 
285                 command = MakeLightSourceCommand( command );
286 
287 
288             #if defined( NN_GR_FRAGMENT_LIGHT_DUMP ) // For debugging
289                 static int a = 0;
290                 if ( ++a == 10 )
291                 {
292                     for ( u32* i = start; i != command; i +=2 )
293                     {
294                         NN_LOG( "0x%08x 0x%08x\n", *i, *(i+1) );
295                     }
296                 }
297             #endif
298 
299                 return command;
300             }
301 
302                 //------------------------------------------------------------------------------
303 
MakeDisableCommand(bit32 * command,bool isAddDummyCommand)304             bit32* FragmentLight::MakeDisableCommand( bit32* command, bool isAddDummyCommand )
305             {
306                 const u32 lightNum = 0;
307 
308                 // Before converting 0x08f, send dummy command
309                 if ( isAddDummyCommand )
310                 {
311                     *command++ = 0x0;
312                     *command++ = PICA_CMD_HEADER_BURST_BE( PICA_REG_TEXTURE_FUNC, 0x3, 0x0 );
313 
314                     *command++ = 0x0;
315                     *command++ = 0x0;
316                 }
317 
318                 // Sets 0x08f light to disabled
319                 *command++ = 0;
320                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_EN0 );
321 
322                 // Sets 0x1c6 light to disabled
323                 *command++ = PICA_CMD_DATA_FRAG_LIGHT_EN_INV( lightNum );
324                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_EN1 );
325 
326                 // Sets the number of 0x1c2 light sources to 0
327                 *command++ = lightNum;
328                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_FRAG_LIGHT_SRC_NUM );
329 
330                 return command;
331             }
332 
333             //------------------------------------------------------------------------------
334 
FragmentLight()335             FragmentLight::FragmentLight()
336                 : globalAmbientR( 0 ),
337                   globalAmbientG( 0 ),
338                   globalAmbientB( 0 ),
339                   layerConfig( PICA_DATA_FRAG_LIGHT_ENV_LAYER_CONFIG0 ),
340                   fresnelSelector( PICA_DATA_FRAG_LIGHT_ENV_NO_FRESNEL ),
341                   shadowSelector( PICA_DATA_FRAG_LIGHT_ENV_TEXTURE0 ),
342                   bumpMode( PICA_DATA_FRAG_LIGHT_ENV_BUMP_NOT_USED_DMP ),
343                   bumpSelector( PICA_DATA_FRAG_LIGHT_ENV_TEXTURE0 ),
344                   isEnableShadowPrimary( false ),
345                   isEnableShadowSecondary( false ),
346                   isEnableShadowAlpha( false ),
347                   isInvertShadow( false ),
348                   isEnableBumpRenorm( false ),
349                   isEnableClampHighLights( true ),
350                   isEnableLutD0( false ),
351                   isEnableLutD1( false ),
352                   isEnableLutRefl( true )
353             {
354                 for ( int i = 0; i < LIGHT_SOURCE_MAX; ++i )
355                 {
356                     isEnable[ i ]         = false;
357                     isEnableSpot[ i ]     = false;
358                     isEnableDistAttn[ i ] = false;
359                     isShadowed[ i ]       = false;
360                     source[ i ].id        = i;
361                 }
362             }
363 
364             //------------------------------------------------------------------------------
365 
LutConfig()366             FragmentLight::LutConfig::LutConfig()
367                 : input( PICA_DATA_FRAG_LIGHT_ENV_NH_DMP ),
368                   isAbs( false ),
369                   scale( PICA_DATA_FRAG_LIGHT_ENV_LUTSCALE_1_0 )
370             {
371             }
372 
373         } // namespace CTR
374     } // namespace gr
375 } // namespace nn
376