1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     gr_FrameBuffer.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_FrameBuffer.h>
17 
18 namespace nn
19 {
20     namespace gr
21     {
22         namespace CTR
23         {
24 
MakeCommand(bit32 * command) const25             bit32* FrameBuffer::ColorBuffer::MakeCommand( bit32* command ) const
26             {
27                 // 0x117
28                 //   [ 1: 0] カラーバッファのピクセルサイズのフォーマット
29                 //   [18:16] カラーバッファのフォーマット
30                 *command++ =
31                     PICA_CMD_DATA_RENDER_BUFFER_COLOR_MODE(
32                         ( ( format == PICA_DATA_COLOR_RGBA8_OES ) ||
33                           ( format == PICA_DATA_COLOR_GAS_DMP   ) ) ?
34                           PICA_DATA_COLOR_PIXEL_SIZE32 : PICA_DATA_COLOR_PIXEL_SIZE16,
35                           format );
36                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_RENDER_BUFFER_COLOR_MODE );
37 
38                 // 0x11d
39                 //   [27: 0]  カラーバッファの物理アドレス
40                 *command++ = PICA_CMD_DATA_RENDER_BUFFER_COLOR_ADDR( nngxGetPhysicalAddr( virtualAddr ) );
41                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_RENDER_BUFFER_COLOR_ADDR );
42 
43                 return command;
44             }
45 
46             //------------------------------------------------------------------------------
47 
MakeCommand(bit32 * command) const48             bit32* FrameBuffer::DepthStencilBuffer::MakeCommand( bit32* command ) const
49             {
50                 // 0x116
51                 //   [ 1: 0] デプスバッファのフォーマット
52                 *command++ = PICA_CMD_DATA_RENDER_BUFFER_DEPTH_MODE( format );
53                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_RENDER_BUFFER_DEPTH_MODE );
54 
55                 // 0x11c
56                 //   [27: 0] デプスバッファの物理アドレス
57                 *command++ = PICA_CMD_DATA_RENDER_BUFFER_DEPTH_ADDR( nngxGetPhysicalAddr( virtualAddr ) );
58                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_RENDER_BUFFER_DEPTH_ADDR );
59 
60                 return command;
61             }
62 
63             //------------------------------------------------------------------------------
64 
MakeCommand(bit32 * command,const u32 bufferBit,bool isClearCache) const65             bit32* FrameBuffer::FrameBuffer::MakeCommand( bit32* command, const u32 bufferBit,
66                                                           bool isClearCache ) const
67             {
68                 // フレームバッファのキャッシュクリア
69                 if ( isClearCache )
70                 {
71                     command = MakeClearCacheCommand( command );
72                 }
73 
74                 // カラーバッファのコマンドの生成
75                 if ( bufferBit & COLOR_BUFFER_BIT )
76                 {
77                     command = colorBuffer.MakeCommand( command );
78                 }
79 
80                 // デプスバッファのコマンドの生成
81                 if ( ( bufferBit & DEPTH_BUFFER_BIT ) || ( bufferBit & STENCIL_BUFFER_BIT ) )
82                 {
83                     command = depthStencilBuffer.MakeCommand( command );
84                 }
85 
86                 // 0x11e
87                 //   [27:12] フレームバッファの高さ
88                 //   [10: 0] フレームバッファの幅
89                 *command++ = PICA_CMD_DATA_RENDER_BUFFER_RESOLUTION( width, height );
90                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_RENDER_BUFFER_RESOLUTION0 );
91 
92                 // 0x6e
93                 //   [27:12] フレームバッファの高さ
94                 //   [10: 0] フレームバッファの幅
95                 *command++ = PICA_CMD_DATA_RENDER_BUFFER_RESOLUTION( width, height );
96                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_RENDER_BUFFER_RESOLUTION1 );
97 
98                 command = MakeClearCacheCommand( command );
99 
100                 return command;
101             }
102 
103             //------------------------------------------------------------------------------
104 
ColorBuffer(const FrameBuffer & frameBuffer_)105             FrameBuffer::ColorBuffer::ColorBuffer( const FrameBuffer& frameBuffer_ )
106                 : virtualAddr( 0 ),
107                   format( PICA_DATA_COLOR_RGBA8_OES ),
108                   blockSize( BLOCK_SIZE8 ),
109                   width( 240 ), height( 400 ),
110                   m_FrameBuffer( frameBuffer_ )
111             {
112                 for (u32 index = 0; index < 4; index++)
113                 {
114                     clearColor[ index ] = 0.0f;
115                 }
116             }
117 
118             //------------------------------------------------------------------------------
119 
DepthStencilBuffer(const FrameBuffer & frameBuffer_)120             FrameBuffer::DepthStencilBuffer::DepthStencilBuffer( const FrameBuffer& frameBuffer_ )
121                 : virtualAddr( 0 ),
122                 format( PICA_DATA_DEPTH24_STENCIL8_EXT ),
123                 width( 240 ), height( 400 ),
124                 clearDepth( 1.0f ),
125                 clearStencil( 0 ),
126                 m_FrameBuffer( frameBuffer_ )
127             {
128             }
129 
130             //------------------------------------------------------------------------------
131 
FrameBuffer()132             FrameBuffer::FrameBuffer() :
133                   colorBuffer( *this ),
134                   depthStencilBuffer( *this ),
135                   width( 240 ), height( 400 )
136             {
137             }
138 
139             //------------------------------------------------------------------------------
140 
MakeClearCacheCommand(bit32 * command)141             bit32* FrameBuffer::MakeClearCacheCommand( bit32* command )
142             {
143                 // 0x111
144                 *command++ = 0x1;
145                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_COLOR_DEPTH_BUFFER_CLEAR1 );
146 
147                 // 0x110
148                 *command++ = 0x1;
149                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_COLOR_DEPTH_BUFFER_CLEAR0 );
150 
151                 return command;
152             }
153 
MakeClearRequest(const u32 bufferBit,bool isAddSplitDrawCmdlist)154             void FrameBuffer::FrameBuffer::MakeClearRequest( const u32 bufferBit, bool isAddSplitDrawCmdlist )
155             {
156                 // フィルするサイズ colorByteSize は 16 の倍数である必要があります。
157                 u32 colorByteSize = 0;
158                 u32 colorWidth    = 0;
159                 u32 clearColor    = 0;
160 
161                 if ( bufferBit & COLOR_BUFFER_BIT )
162                 {
163                     u8 red   = FloatToUnsignedByte( colorBuffer.clearColor[ 0 ] );
164                     u8 green = FloatToUnsignedByte( colorBuffer.clearColor[ 1 ] );
165                     u8 blue  = FloatToUnsignedByte( colorBuffer.clearColor[ 2 ] );
166 
167                     if ( colorBuffer.format == PICA_DATA_COLOR_RGBA8_OES )
168                     {
169                         u8 alpha = FloatToUnsignedByte( colorBuffer.clearColor[ 3 ] );
170 
171                         colorByteSize = colorBuffer.width * colorBuffer.height * 4;
172                         colorWidth    = 32;
173                         // float32 をクランプして、 u8 に変換します。
174                         clearColor    = ( red   << 24 ) |
175                                         ( green << 16 ) |
176                                         ( blue  <<  8 ) |
177                                         ( alpha <<  0 ) ;
178                     }
179                     else if ( colorBuffer.format == PICA_DATA_COLOR_RGB5_A1 )
180                     {
181                         u8 alpha = FloatToUnsignedByte( colorBuffer.clearColor[ 3 ] );
182 
183                         colorByteSize = colorBuffer.width * colorBuffer.height * 2;
184                         colorWidth    = 16;
185                         clearColor    = ( ( ( red   >> 3 ) & 0x1f )      << 11 ) |
186                                         ( ( ( green >> 3 ) & 0x1f )      <<  6 ) |
187                                         ( ( ( blue  >> 3 ) & 0x1f )      <<  1 ) |
188                                         ( ( ( alpha > 0x7f ) ? 0x1 : 0 ) <<  0 );
189                     }
190                     else if ( colorBuffer.format == PICA_DATA_COLOR_RGB565 )
191                     {
192                         colorByteSize = colorBuffer.width * colorBuffer.height * 2;
193                         colorWidth    = 16;
194                         clearColor    = ( ( ( red   >> 3 ) & 0x1f ) << 11 ) |
195                                         ( ( ( green >> 2 ) & 0x3f ) <<  5 ) |
196                                         ( ( ( blue  >> 3 ) & 0x1f ) <<  0 );
197                     }
198                     else if ( colorBuffer.format == PICA_DATA_COLOR_RGBA4 )
199                     {
200                         u8 alpha = FloatToUnsignedByte( colorBuffer.clearColor[ 3 ] );
201 
202                         colorByteSize = colorBuffer.width * colorBuffer.height * 2;
203                         colorWidth    = 16;
204                         clearColor    = ( ( ( red   >> 4 ) & 0xf ) << 12 ) |
205                                         ( ( ( green >> 4 ) & 0xf ) <<  8 ) |
206                                         ( ( ( blue  >> 4 ) & 0xf ) <<  4 ) |
207                                         ( ( ( alpha >> 4 ) & 0xf ) <<  0 );
208                     }
209                 }
210 
211                 // フィルするサイズ depthByteSize は 16 の倍数である必要があります。
212                 u32 depthByteSize = 0;
213                 u32 clearDepth    = 0;
214                 u32 depthWidth    = 0;
215 
216                 if ( ( bufferBit & DEPTH_BUFFER_BIT ) || ( bufferBit & STENCIL_BUFFER_BIT ) )
217                 {
218                     depthStencilBuffer.clearDepth =
219                         ( depthStencilBuffer.clearDepth > 1.0f ) ? 1.0f :
220                         ( ( depthStencilBuffer.clearDepth < 0.0f ) ? 0.0f : depthStencilBuffer.clearDepth );
221 
222                     if ( depthStencilBuffer.format == PICA_DATA_DEPTH24_STENCIL8_EXT )
223                     {
224                         depthByteSize = depthStencilBuffer.width * depthStencilBuffer.height * 4;
225                         clearDepth    = ( depthStencilBuffer.clearStencil ) << 24 |
226                                         Float32ToUnsignedFix24( depthStencilBuffer.clearDepth );
227                         depthWidth    = 32;
228                     }
229                     else if ( depthStencilBuffer.format == PICA_DATA_DEPTH_COMPONENT16 )
230                     {
231                         depthByteSize = depthStencilBuffer.width * depthStencilBuffer.height * 2;
232                         clearDepth    = Float32ToUnsignedFix16( depthStencilBuffer.clearDepth );
233                         depthWidth    = 16;
234                     }
235                     else if ( depthStencilBuffer.format == PICA_DATA_DEPTH_COMPONENT24_OES )
236                     {
237                         depthByteSize = depthStencilBuffer.width * depthStencilBuffer.height * 3;
238                         clearDepth    = Float32ToUnsignedFix24( depthStencilBuffer.clearDepth );
239                         depthWidth    = 24;
240                     }
241                 }
242 
243                 if ( ( bufferBit & COLOR_BUFFER_BIT ) || ( bufferBit & DEPTH_BUFFER_BIT ) )
244                 {
245                     if ( isAddSplitDrawCmdlist )
246                     {
247                         nngxSplitDrawCmdlist();
248                     }
249 
250                     nngxAddMemoryFillCommand(
251                         ( bufferBit & COLOR_BUFFER_BIT ) ? reinterpret_cast<GLvoid*>( colorBuffer.virtualAddr ) : 0,
252                         colorByteSize, clearColor, colorWidth,
253                         ( ( bufferBit & DEPTH_BUFFER_BIT ) ||
254                           ( bufferBit & STENCIL_BUFFER_BIT ) ||
255                           ( bufferBit & DEPTH_STENCIL_BUFFER_BIT ) ) ?
256                         reinterpret_cast<GLvoid*>( depthStencilBuffer.virtualAddr ) : 0,
257                         depthByteSize, clearDepth, depthWidth );
258                 }
259             }
260 
261         } // namespace CTR
262     } // namespace gr
263 } // namespace nn
264