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