1 /*---------------------------------------------------------------------------*
2   Project:  Horizon
3   File:     gr_FrameBuffer.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: 47820 $
14  *---------------------------------------------------------------------------*/
15 
16 #include <nn/gr/CTR/gr_FrameBuffer.h>
17 
18 namespace nn
19 {
20     namespace gr
21     {
22         namespace CTR
23         {
24 
MakeRenderBlockModeCommand(bit32 * command) const25             bit32* FrameBuffer::ColorBuffer::MakeRenderBlockModeCommand( bit32* command ) const
26             {
27                 // 0x11b
28                 *command++ = blockSize;
29                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_RENDER_BLOCK_FORMAT );
30 
31                 return command;
32             }
33 
MakeCommand(bit32 * command,bool isAddRenderBlockModeCommand) const34             bit32* FrameBuffer::ColorBuffer::MakeCommand( bit32* command, bool isAddRenderBlockModeCommand ) const
35             {
36                 // 0x117
37                 //  [1:0] color buffer pixel size format
38                 //   [18:16] color buffer format
39                 *command++ =
40                     PICA_CMD_DATA_RENDER_BUFFER_COLOR_MODE(
41                         ( ( format == PICA_DATA_COLOR_RGBA8_OES ) ||
42                           ( format == PICA_DATA_COLOR_GAS_DMP   ) ) ?
43                           PICA_DATA_COLOR_PIXEL_SIZE32 : PICA_DATA_COLOR_PIXEL_SIZE16,
44                           format );
45                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_RENDER_BUFFER_COLOR_MODE );
46 
47                 // 0x11d
48                 //    [27:0] color buffer physical address
49                 *command++ = PICA_CMD_DATA_RENDER_BUFFER_COLOR_ADDR( nngxGetPhysicalAddr( virtualAddr ) );
50                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_RENDER_BUFFER_COLOR_ADDR );
51 
52                 if ( isAddRenderBlockModeCommand )
53                 {
54                     command = MakeRenderBlockModeCommand( command );
55                 }
56 
57                 return command;
58             }
59 
60             //------------------------------------------------------------------------------
61 
MakeCommand(bit32 * command) const62             bit32* FrameBuffer::DepthStencilBuffer::MakeCommand( bit32* command ) const
63             {
64                 // 0x116
65                 //   [1:0] depth buffer format
66                 *command++ = PICA_CMD_DATA_RENDER_BUFFER_DEPTH_MODE( format );
67                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_RENDER_BUFFER_DEPTH_MODE );
68 
69                 // 0x11c
70                 //    [27:0] depth buffer physical address
71                 *command++ = PICA_CMD_DATA_RENDER_BUFFER_DEPTH_ADDR( nngxGetPhysicalAddr( virtualAddr ) );
72                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_RENDER_BUFFER_DEPTH_ADDR );
73 
74                 return command;
75             }
76 
77             //------------------------------------------------------------------------------
78 
MakeCommand(bit32 * command,const u32 bufferBit,bool isClearCache) const79             bit32* FrameBuffer::FrameBuffer::MakeCommand( bit32* command, const u32 bufferBit,
80                                                           bool isClearCache ) const
81             {
82                 // Clear the framebuffer cache
83                 if ( isClearCache )
84                 {
85                     command = MakeClearCacheCommand( command );
86                 }
87 
88                 // Generate color buffer command
89                 if ( bufferBit & COLOR_BUFFER_BIT )
90                 {
91                     command = colorBuffer.MakeCommand( command );
92                 }
93 
94                 // Generate depth buffer command
95                 if ( ( bufferBit & DEPTH_BUFFER_BIT ) || ( bufferBit & STENCIL_BUFFER_BIT ) )
96                 {
97                     command = depthStencilBuffer.MakeCommand( command );
98                 }
99 
100                 // 0x11e
101                 //   [27:12] framebuffer height
102                 //    [10:0] framebuffer width
103                 *command++ = PICA_CMD_DATA_RENDER_BUFFER_RESOLUTION( width, height );
104                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_RENDER_BUFFER_RESOLUTION0 );
105 
106                 // 0x6e
107                 //   [27:12] framebuffer height
108                 //   [10: [10:0] frame buffer width
109                 *command++ = PICA_CMD_DATA_RENDER_BUFFER_RESOLUTION( width, height );
110                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_RENDER_BUFFER_RESOLUTION1 );
111 
112                 command = MakeClearCacheCommand( command );
113 
114                 return command;
115             }
116 
117             //------------------------------------------------------------------------------
118 
ColorBuffer(const FrameBuffer & frameBuffer_)119             FrameBuffer::ColorBuffer::ColorBuffer( const FrameBuffer& frameBuffer_ )
120                 : virtualAddr( 0 ),
121                   format( PICA_DATA_COLOR_RGBA8_OES ),
122                   blockSize( BLOCK_SIZE8 ),
123                   width( 240 ), height( 400 ),
124                   m_FrameBuffer( frameBuffer_ )
125             {
126                 for (u32 index = 0; index < 4; index++)
127                 {
128                     clearColor[ index ] = 0.0f;
129                 }
130             }
131 
132             //------------------------------------------------------------------------------
133 
DepthStencilBuffer(const FrameBuffer & frameBuffer_)134             FrameBuffer::DepthStencilBuffer::DepthStencilBuffer( const FrameBuffer& frameBuffer_ )
135                 : virtualAddr( 0 ),
136                 format( PICA_DATA_DEPTH24_STENCIL8_EXT ),
137                 width( 240 ), height( 400 ),
138                 clearDepth( 1.0f ),
139                 clearStencil( 0 ),
140                 m_FrameBuffer( frameBuffer_ )
141             {
142             }
143 
144             //------------------------------------------------------------------------------
145 
FrameBuffer()146             FrameBuffer::FrameBuffer() :
147                   colorBuffer( *this ),
148                   depthStencilBuffer( *this ),
149                   width( 240 ), height( 400 )
150             {
151             }
152 
153             //------------------------------------------------------------------------------
154 
MakeClearCacheCommand(bit32 * command)155             bit32* FrameBuffer::MakeClearCacheCommand( bit32* command )
156             {
157                 // 0x111
158                 *command++ = 0x1;
159                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_COLOR_DEPTH_BUFFER_CLEAR1 );
160 
161                 // 0x110
162                 *command++ = 0x1;
163                 *command++ = PICA_CMD_HEADER_SINGLE( PICA_REG_COLOR_DEPTH_BUFFER_CLEAR0 );
164 
165                 return command;
166             }
167 
MakeClearRequest(const u32 bufferBit,bool isAddSplitDrawCmdlist)168             void FrameBuffer::FrameBuffer::MakeClearRequest( const u32 bufferBit, bool isAddSplitDrawCmdlist )
169             {
170                 // The colorByteSize fill size must be a multiple of 16.
171                 u32 colorByteSize = 0;
172                 u32 colorWidth    = 0;
173                 u32 clearColor    = 0;
174 
175                 if ( bufferBit & COLOR_BUFFER_BIT )
176                 {
177                     u8 red   = FloatToUnsignedByte( colorBuffer.clearColor[ 0 ] );
178                     u8 green = FloatToUnsignedByte( colorBuffer.clearColor[ 1 ] );
179                     u8 blue  = FloatToUnsignedByte( colorBuffer.clearColor[ 2 ] );
180 
181                     if ( colorBuffer.format == PICA_DATA_COLOR_RGBA8_OES )
182                     {
183                         u8 alpha = FloatToUnsignedByte( colorBuffer.clearColor[ 3 ] );
184 
185                         colorByteSize = colorBuffer.width * colorBuffer.height * 4;
186                         colorWidth    = 32;
187                         // Clamp float32, and convert to u8.
188                         clearColor    = ( red   << 24 ) |
189                                         ( green << 16 ) |
190                                         ( blue  <<  8 ) |
191                                         ( alpha <<  0 ) ;
192                     }
193                     else if ( colorBuffer.format == PICA_DATA_COLOR_RGB5_A1 )
194                     {
195                         u8 alpha = FloatToUnsignedByte( colorBuffer.clearColor[ 3 ] );
196 
197                         colorByteSize = colorBuffer.width * colorBuffer.height * 2;
198                         colorWidth    = 16;
199                         clearColor    = ( ( ( red   >> 3 ) & 0x1f )      << 11 ) |
200                                         ( ( ( green >> 3 ) & 0x1f )      <<  6 ) |
201                                         ( ( ( blue  >> 3 ) & 0x1f )      <<  1 ) |
202                                         ( ( ( alpha > 0x7f ) ? 0x1 : 0 ) <<  0 );
203                     }
204                     else if ( colorBuffer.format == PICA_DATA_COLOR_RGB565 )
205                     {
206                         colorByteSize = colorBuffer.width * colorBuffer.height * 2;
207                         colorWidth    = 16;
208                         clearColor    = ( ( ( red   >> 3 ) & 0x1f ) << 11 ) |
209                                         ( ( ( green >> 2 ) & 0x3f ) <<  5 ) |
210                                         ( ( ( blue  >> 3 ) & 0x1f ) <<  0 );
211                     }
212                     else if ( colorBuffer.format == PICA_DATA_COLOR_RGBA4 )
213                     {
214                         u8 alpha = FloatToUnsignedByte( colorBuffer.clearColor[ 3 ] );
215 
216                         colorByteSize = colorBuffer.width * colorBuffer.height * 2;
217                         colorWidth    = 16;
218                         clearColor    = ( ( ( red   >> 4 ) & 0xf ) << 12 ) |
219                                         ( ( ( green >> 4 ) & 0xf ) <<  8 ) |
220                                         ( ( ( blue  >> 4 ) & 0xf ) <<  4 ) |
221                                         ( ( ( alpha >> 4 ) & 0xf ) <<  0 );
222                     }
223                 }
224 
225                 // The depthByteSize fill size must be a multiple of 16.
226                 u32 depthByteSize = 0;
227                 u32 clearDepth    = 0;
228                 u32 depthWidth    = 0;
229 
230                 if ( ( bufferBit & DEPTH_BUFFER_BIT ) || ( bufferBit & STENCIL_BUFFER_BIT ) )
231                 {
232                     depthStencilBuffer.clearDepth =
233                         ( depthStencilBuffer.clearDepth > 1.0f ) ? 1.0f :
234                         ( ( depthStencilBuffer.clearDepth < 0.0f ) ? 0.0f : depthStencilBuffer.clearDepth );
235 
236                     if ( depthStencilBuffer.format == PICA_DATA_DEPTH24_STENCIL8_EXT )
237                     {
238                         depthByteSize = depthStencilBuffer.width * depthStencilBuffer.height * 4;
239                         clearDepth    = ( depthStencilBuffer.clearStencil ) << 24 |
240                                         Float32ToUnsignedFix24( depthStencilBuffer.clearDepth );
241                         depthWidth    = 32;
242                     }
243                     else if ( depthStencilBuffer.format == PICA_DATA_DEPTH_COMPONENT16 )
244                     {
245                         depthByteSize = depthStencilBuffer.width * depthStencilBuffer.height * 2;
246                         clearDepth    = Float32ToUnsignedFix16( depthStencilBuffer.clearDepth );
247                         depthWidth    = 16;
248                     }
249                     else if ( depthStencilBuffer.format == PICA_DATA_DEPTH_COMPONENT24_OES )
250                     {
251                         depthByteSize = depthStencilBuffer.width * depthStencilBuffer.height * 3;
252                         clearDepth    = Float32ToUnsignedFix24( depthStencilBuffer.clearDepth );
253                         depthWidth    = 24;
254                     }
255                 }
256 
257                 if ( ( bufferBit & COLOR_BUFFER_BIT ) || ( bufferBit & DEPTH_BUFFER_BIT ) )
258                 {
259                     if ( isAddSplitDrawCmdlist )
260                     {
261                         nngxSplitDrawCmdlist();
262                     }
263 
264                     nngxAddMemoryFillCommand(
265                         ( bufferBit & COLOR_BUFFER_BIT ) ? reinterpret_cast<GLvoid*>( colorBuffer.virtualAddr ) : 0,
266                         colorByteSize, clearColor, colorWidth,
267                         ( ( bufferBit & DEPTH_BUFFER_BIT ) ||
268                           ( bufferBit & STENCIL_BUFFER_BIT ) ||
269                           ( bufferBit & DEPTH_STENCIL_BUFFER_BIT ) ) ?
270                         reinterpret_cast<GLvoid*>( depthStencilBuffer.virtualAddr ) : 0,
271                         depthByteSize, clearDepth, depthWidth );
272                 }
273             }
274 
MakeClearRequestRaw(nngxCommandList * commandList,const u32 bufferBit,bool isAddSplitDrawCmdlist)275             void FrameBuffer::FrameBuffer::MakeClearRequestRaw( nngxCommandList* commandList, const u32 bufferBit, bool isAddSplitDrawCmdlist )
276             {
277                 // The colorByteSize fill size must be a multiple of 16.
278                 u32 colorByteSize = 0;
279                 u32 colorWidth    = 0;
280                 u32 clearColor    = 0;
281 
282                 if ( bufferBit & COLOR_BUFFER_BIT )
283                 {
284                     u8 red   = FloatToUnsignedByte( colorBuffer.clearColor[ 0 ] );
285                     u8 green = FloatToUnsignedByte( colorBuffer.clearColor[ 1 ] );
286                     u8 blue  = FloatToUnsignedByte( colorBuffer.clearColor[ 2 ] );
287 
288                     if ( colorBuffer.format == PICA_DATA_COLOR_RGBA8_OES )
289                     {
290                         u8 alpha = FloatToUnsignedByte( colorBuffer.clearColor[ 3 ] );
291 
292                         colorByteSize = colorBuffer.width * colorBuffer.height * 4;
293                         colorWidth    = 32;
294                         // Clamp float32, and convert to u8.
295                         clearColor    = ( red   << 24 ) |
296                                         ( green << 16 ) |
297                                         ( blue  <<  8 ) |
298                                         ( alpha <<  0 ) ;
299                     }
300                     else if ( colorBuffer.format == PICA_DATA_COLOR_RGB5_A1 )
301                     {
302                         u8 alpha = FloatToUnsignedByte( colorBuffer.clearColor[ 3 ] );
303 
304                         colorByteSize = colorBuffer.width * colorBuffer.height * 2;
305                         colorWidth    = 16;
306                         clearColor    = ( ( ( red   >> 3 ) & 0x1f )      << 11 ) |
307                                         ( ( ( green >> 3 ) & 0x1f )      <<  6 ) |
308                                         ( ( ( blue  >> 3 ) & 0x1f )      <<  1 ) |
309                                         ( ( ( alpha > 0x7f ) ? 0x1 : 0 ) <<  0 );
310                     }
311                     else if ( colorBuffer.format == PICA_DATA_COLOR_RGB565 )
312                     {
313                         colorByteSize = colorBuffer.width * colorBuffer.height * 2;
314                         colorWidth    = 16;
315                         clearColor    = ( ( ( red   >> 3 ) & 0x1f ) << 11 ) |
316                                         ( ( ( green >> 2 ) & 0x3f ) <<  5 ) |
317                                         ( ( ( blue  >> 3 ) & 0x1f ) <<  0 );
318                     }
319                     else if ( colorBuffer.format == PICA_DATA_COLOR_RGBA4 )
320                     {
321                         u8 alpha = FloatToUnsignedByte( colorBuffer.clearColor[ 3 ] );
322 
323                         colorByteSize = colorBuffer.width * colorBuffer.height * 2;
324                         colorWidth    = 16;
325                         clearColor    = ( ( ( red   >> 4 ) & 0xf ) << 12 ) |
326                                         ( ( ( green >> 4 ) & 0xf ) <<  8 ) |
327                                         ( ( ( blue  >> 4 ) & 0xf ) <<  4 ) |
328                                         ( ( ( alpha >> 4 ) & 0xf ) <<  0 );
329                     }
330                 }
331 
332                 // The depthByteSize fill size must be a multiple of 16.
333                 u32 depthByteSize = 0;
334                 u32 clearDepth    = 0;
335                 u32 depthWidth    = 0;
336 
337                 if ( ( bufferBit & DEPTH_BUFFER_BIT ) || ( bufferBit & STENCIL_BUFFER_BIT ) )
338                 {
339                     depthStencilBuffer.clearDepth =
340                         ( depthStencilBuffer.clearDepth > 1.0f ) ? 1.0f :
341                         ( ( depthStencilBuffer.clearDepth < 0.0f ) ? 0.0f : depthStencilBuffer.clearDepth );
342 
343                     if ( depthStencilBuffer.format == PICA_DATA_DEPTH24_STENCIL8_EXT )
344                     {
345                         depthByteSize = depthStencilBuffer.width * depthStencilBuffer.height * 4;
346                         clearDepth    = ( depthStencilBuffer.clearStencil ) << 24 |
347                                         Float32ToUnsignedFix24( depthStencilBuffer.clearDepth );
348                         depthWidth    = 32;
349                     }
350                     else if ( depthStencilBuffer.format == PICA_DATA_DEPTH_COMPONENT16 )
351                     {
352                         depthByteSize = depthStencilBuffer.width * depthStencilBuffer.height * 2;
353                         clearDepth    = Float32ToUnsignedFix16( depthStencilBuffer.clearDepth );
354                         depthWidth    = 16;
355                     }
356                     else if ( depthStencilBuffer.format == PICA_DATA_DEPTH_COMPONENT24_OES )
357                     {
358                         depthByteSize = depthStencilBuffer.width * depthStencilBuffer.height * 3;
359                         clearDepth    = Float32ToUnsignedFix24( depthStencilBuffer.clearDepth );
360                         depthWidth    = 24;
361                     }
362                 }
363 
364                 if ( ( bufferBit & COLOR_BUFFER_BIT ) || ( bufferBit & DEPTH_BUFFER_BIT ) )
365                 {
366                     if ( isAddSplitDrawCmdlist )
367                     {
368                         nngxSplitDrawCmdlistRaw(commandList);
369                     }
370 
371                     nngxAddMemoryFillCommandRaw(
372                         commandList,
373                         ( bufferBit & COLOR_BUFFER_BIT ) ? reinterpret_cast<GLvoid*>( colorBuffer.virtualAddr ) : 0,
374                         colorByteSize, clearColor, colorWidth,
375                         ( ( bufferBit & DEPTH_BUFFER_BIT ) ||
376                           ( bufferBit & STENCIL_BUFFER_BIT ) ||
377                           ( bufferBit & DEPTH_STENCIL_BUFFER_BIT ) ) ?
378                         reinterpret_cast<GLvoid*>( depthStencilBuffer.virtualAddr ) : 0,
379                         depthByteSize, clearDepth, depthWidth );
380                 }
381             }
382 
383         } // namespace CTR
384     } // namespace gr
385 } // namespace nn
386