/*---------------------------------------------------------------------------* Project: NintendoWare File: gfx_ResShape.cpp Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Revision: 16971 $ *---------------------------------------------------------------------------*/ #include "../precompiled.h" #include #include #include #include #include #include #include #include #include #include #include namespace nw { namespace gfx { namespace res { typedef void (*SetupFunc)(nw::os::IAllocator* allocator, ResShape resShape); typedef void (*CleanupFunc)(ResShape resShape); static void ResShape_Setup(nw::os::IAllocator* allocator, ResShape resShape); static void ResSeparateDataShape_Setup(nw::os::IAllocator* allocator, ResShape resShape); static void ResParticleShape_Setup(nw::os::IAllocator* allocator, ResShape resShape); static void ResShape_Cleanup(ResShape resShape); static void ResSeparateDataShape_Cleanup(ResShape resShape); static void ResParticleShape_Cleanup(ResShape resShape); static SetupFunc sShape_SetupTable[] = { ResSeparateDataShape_Setup, ResParticleShape_Setup }; static CleanupFunc sShape_CleanupTable[] = { ResSeparateDataShape_Cleanup, ResParticleShape_Cleanup }; //--------------------------------------------------------------------------- //! @brief 必要であれば頂点バッファのコピー用のメモリを確保し、転送をおこないます。 //! //! @param[in] bufferID メモリ確保用の頂点バッファIDです。 //! @param[in] resStream 頂点ストリームリソースです。 //! @param[in] loadFlag 頂点バッファの配置メモリフラグです。 //--------------------------------------------------------------------------- static void BufferData( u32 bufferID, ResIndexStream resStream, u32 loadFlag ) { u32 size = resStream.GetStreamCount(); GLenum transtype = loadFlag & 0xFFFF0000; void* address = NULL; const u32 NN_GX_MEM_MASK = 0x00030000; switch (transtype) { case (NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP): nngxUpdateBuffer( resStream.GetStream(), size ); break; case (NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP): case (NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP): { GLuint area = (transtype & NN_GX_MEM_MASK); address = __dmpgl_allocator(area, NN_GX_MEM_VERTEXBUFFER, bufferID, size); nngxUpdateBuffer( resStream.GetStream(), size ); internal::nwgfxAddVramDmaCommand( resStream.GetStream(), address, size ); resStream.SetLocationAddress( address ); resStream.ref().m_MemoryArea = area; } break; case (NN_GX_MEM_FCRAM | GL_COPY_FCRAM_DMP): { address = __dmpgl_allocator(NN_GX_MEM_FCRAM, NN_GX_MEM_VERTEXBUFFER, bufferID, size); nw::os::MemCpy( address, resStream.GetStream(), size ); nngxUpdateBuffer( address, size ); resStream.SetLocationAddress( address ); resStream.ref().m_MemoryArea = NN_GX_MEM_FCRAM; } break; case (NN_GX_MEM_VRAMA | GL_COPY_FCRAM_DMP): case (NN_GX_MEM_VRAMB | GL_COPY_FCRAM_DMP): NW_FATAL_ERROR("GL_COPY_DMA is not supported!"); break; default: break; } } //--------------------------------------------------------------------------- //! @brief コピーした頂点情報を開放します。 //! //! @param[in] bufferID バッファオブジェクトIDです。 //! @param[in] resStream //--------------------------------------------------------------------------- static void DeleteBuffer( u32 bufferID, ResIndexStream resStream ) { GLuint area = resStream.ref().m_MemoryArea; if (area != ResIndexStreamData::AREA_NO_MALLOC) { void* address = reinterpret_cast( resStream.GetLocationAddress() ); __dmpgl_deallocator( area, NN_GX_MEM_VERTEXBUFFER, bufferID, address ); resStream.SetLocationAddress( static_cast(NULL) ); } } //---------------------------------------- Result ResShape::Setup(nw::os::IAllocator* allocator) { Result result = RESOURCE_RESULT_OK; switch ( this->ref().typeInfo ) { case ResSeparateDataShape::TYPE_INFO: { sShape_SetupTable[0]( allocator, *this ); this->SetFlags(ut::EnableFlag(this->GetFlags(), ResShape::FLAG_HAS_BEEN_SETUP)); } break; case ResParticleShape::TYPE_INFO: { sShape_SetupTable[1]( allocator, *this ); this->SetFlags(ut::EnableFlag(this->GetFlags(), ResShape::FLAG_HAS_BEEN_SETUP)); } break; default: { } } return result; } /*!--------------------------------------------------------------------------* Name: ResShape_Setup @brief シェイプのリソース初期化をおこないます。 @param[in] resShape シェイプリソースです。 @return なし。 *---------------------------------------------------------------------------*/ static void ResShape_Setup(nw::os::IAllocator* allocator, ResShape resShape) { s32 primSetNum = resShape.GetPrimitiveSetsCount(); for ( s32 i = 0; i < primSetNum; ++i ) { resShape.GetPrimitiveSets( i ).Setup(allocator); } } /*!--------------------------------------------------------------------------* Name: ResSeparateDataShape_Setup @brief 複数属性シェイプのリソース初期化をおこないます。 @param[in] resShape シェイプリソースです。 @return なし。 *---------------------------------------------------------------------------*/ static void ResSeparateDataShape_Setup(nw::os::IAllocator* allocator, ResShape resShape) { ResShape_Setup( allocator, resShape ); ResSeparateDataShape resSeparateShape = ResStaticCast( resShape ); s32 vtxAttrNum = resSeparateShape.GetVertexAttributesCount(); for ( s32 i = 0; i < vtxAttrNum; ++ i ) { resSeparateShape.GetVertexAttributes( i ).Setup(); } } /*!--------------------------------------------------------------------------* Name: ResParticleShape_Setup @brief パーティクルシェイプのリソース初期化をおこないます。 @param[in] resShape シェイプリソースです。 @return なし。 *---------------------------------------------------------------------------*/ static void ResParticleShape_Setup(nw::os::IAllocator* allocator, ResShape resShape) { NW_UNUSED_VARIABLE(resShape); NW_UNUSED_VARIABLE(allocator); } /*!--------------------------------------------------------------------------* Name: ResPrimitiveSet::Setup @brief リソースの初期化をおこないます。 @return なし。 *---------------------------------------------------------------------------*/ void ResPrimitiveSet::Setup(nw::os::IAllocator* allocator) { NW_ASSERT( this->IsValid() ); ResPrimitiveArray primitiveArray = this->GetPrimitives(); for (ResPrimitiveArray::iterator it = primitiveArray.begin(); it != primitiveArray.end(); ++it) { (*it).Setup(allocator); } } /*!--------------------------------------------------------------------------* Name: ResPrimitive::Setup @brief リソースの初期化をおこないます。 @return なし。 *---------------------------------------------------------------------------*/ void ResPrimitive::Setup(nw::os::IAllocator* allocator) { NW_ASSERT( this->IsValid() ); if (allocator == NULL) { allocator = CommandCacheManager::GetAllocator(); } this->ref().m_CommandAllocator = allocator; u32 streamNum = this->GetIndexStreamsCount(); GLuint* bufferObjects = reinterpret_cast( this->GetBufferObjects() ); for ( uint i = 0; i < streamNum; ++i ) { ResIndexStream resStream = this->GetIndexStreams( u32(i) ); bufferObjects[ i ] = reinterpret_cast(resStream.ptr()); s32 commandSize = internal::CalcSetupDrawIndexStreamCommand( resStream ); resStream.ref().m_CommandCache = allocator->Alloc(commandSize, 4); resStream.ref().m_CommandCacheSize = commandSize; if (resStream.GetLocationAddress() != NULL) { resStream.ref().m_MemoryArea = ResIndexStreamData::AREA_NO_MALLOC; continue; } u32 size = resStream.GetStreamCount(); void* buf = resStream.GetStream(); // 頂点インデックスバッファのメモリへの読み込み指定 int loadFlag = resStream.GetLocationFlag(); // デフォルトは、FCRAM から NO_COPY。 if (loadFlag == 0) { loadFlag = NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP; } BufferData( bufferObjects[ i ], resStream, loadFlag ); } } //---------------------------------------- void ResPrimitive::SetupDrawCommand(bool hasGeometryShader) { ResIndexStreamArray indexStreams = this->GetIndexStreams(); ResIndexStreamArray::iterator end = indexStreams.end(); for (ResIndexStreamArray::iterator stream = indexStreams.begin(); stream != end; ++stream) { ResIndexStream indexStream = *stream; NW_NULL_ASSERT( indexStream.ref().m_CommandCache ); internal::CommandBufferInfo bufferInfo( indexStream.ref().m_CommandCache, indexStream.ref().m_CommandCacheSize ); s32 resultSize = internal::SetupDrawIndexStreamCommand(bufferInfo, indexStream, hasGeometryShader); NW_ASSERT( resultSize == indexStream.ref().m_CommandCacheSize ); } ref().m_Flags |= ResPrimitive::FLAG_COMMAND_HAS_BEEN_SETUP; } //---------------------------------------- void ResShape::Cleanup() { switch ( this->ref().typeInfo ) { case ResSeparateDataShape::TYPE_INFO: { sShape_CleanupTable[0]( *this ); this->SetFlags(ut::DisableFlag(this->GetFlags(), ResShape::FLAG_HAS_BEEN_SETUP)); } break; case ResParticleShape::TYPE_INFO: { sShape_CleanupTable[1]( *this ); this->SetFlags(ut::DisableFlag(this->GetFlags(), ResShape::FLAG_HAS_BEEN_SETUP)); } break; default: { } } } //---------------------------------------- static void ResShape_Cleanup(ResShape resShape) { s32 primSetNum = resShape.GetPrimitiveSetsCount(); for ( s32 i = 0; i < primSetNum; ++i ) { resShape.GetPrimitiveSets( i ).Cleanup(); } } //---------------------------------------- static void ResSeparateDataShape_Cleanup(ResShape resShape) { ResSeparateDataShape resSeparateShape = ResStaticCast( resShape ); s32 vtxAttrNum = resSeparateShape.GetVertexAttributesCount(); for ( s32 i = 0; i < vtxAttrNum; ++ i ) { resSeparateShape.GetVertexAttributes( i ).Cleanup(); } ResShape_Cleanup( resShape ); } //---------------------------------------- static void ResParticleShape_Cleanup(ResShape resShape) { ResParticleShape resParticleShape = ResStaticCast( resShape ); } //------------------------------------------------------------------------------ void ResPrimitiveSet::Cleanup() { NW_ASSERT( this->IsValid() ); ResPrimitiveArray primitiveArray = this->GetPrimitives(); for (ResPrimitiveArray::iterator it = primitiveArray.begin(); it != primitiveArray.end(); ++it) { (*it).Cleanup(); } } //------------------------------------------------------------------------------ void ResPrimitive::Cleanup() { NW_ASSERT( this->IsValid() ); u32 streamNum = this->GetIndexStreamsCount(); GLuint* bufferObjects = reinterpret_cast( this->GetBufferObjects() ); for ( uint i = 0; i < streamNum; ++i ) { ResIndexStream resStream = this->GetIndexStreams( u32(i) ); if (resStream.IsValid() && resStream.ref().m_CommandCache) { this->ref().m_CommandAllocator->Free(resStream.ref().m_CommandCache); resStream.ref().m_CommandCache = NULL; resStream.ref().m_CommandCacheSize = 0; } DeleteBuffer( bufferObjects[ i ], resStream ); } std::memset( bufferObjects, 0, sizeof(GLuint) * streamNum ); ref().m_CommandAllocator = NULL; ref().m_Flags &= ~FLAG_COMMAND_HAS_BEEN_SETUP; } } /* namespace res */ } /* namespace gfx */ } /* namespace nw */