/*---------------------------------------------------------------------------* Project: NintendoWare File: gfx_ResVertex.cpp Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo and/or its licensed developers and are protected by national and international copyright laws. 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. The content herein is highly confidential and should be handled accordingly. $Revision: $ *---------------------------------------------------------------------------*/ #include "../precompiled.h" #include #include #include #include #include #include #include namespace nw { namespace gfx { namespace res { //--------------------------------------------------------------------------- //! @brief 必要であれば頂点バッファのコピー用のメモリを確保し、転送をおこないます。 //! //! @param[in] bufferID メモリ確保用の頂点バッファIDです。 //! @param[in] resStream 頂点ストリームリソースです。 //! @param[in] loadFlag 頂点バッファの配置メモリフラグです。 //--------------------------------------------------------------------------- static void BufferData( u32 bufferID, ResVertexStreamBase 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); nngxAddVramDmaCommand( 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; } } static void DeleteBuffer( u32 bufferID, ResVertexStreamBase resStream ) { GLuint area = resStream.ref().m_MemoryArea; if (area != ResVertexStreamBaseData::AREA_NO_MALLOC) { void* address = reinterpret_cast( resStream.GetLocationAddress() ); __dmpgl_deallocator( area, NN_GX_MEM_VERTEXBUFFER, bufferID, address ); resStream.SetLocationAddress( static_cast(NULL) ); } } //----------------------------------------------------------------------------- void ResVertexAttribute::Setup() { NW_ASSERT( this->IsValid() ); if ( this->GetFlags() & ResVertexAttributeData::FLAG_VERTEX_PARAM ) { ResStaticCast( *this ).Setup(); } else if ( this->GetFlags() & ResVertexAttributeData::FLAG_INTERLEAVE ) { ResStaticCast( *this ).Setup(); } else { ResStaticCast( *this ).Setup(); } } //----------------------------------------------------------------------------- void ResVertexAttribute::Cleanup() { NW_ASSERT( this->IsValid() ); if ( this->GetFlags() & ResVertexAttributeData::FLAG_VERTEX_PARAM ) { ResStaticCast( *this ).Cleanup(); } else if ( this->GetFlags() & ResVertexAttributeData::FLAG_INTERLEAVE ) { ResStaticCast(*this).Cleanup(); } else { ResStaticCast(*this).Cleanup(); } } //---------------------------------------------------------- u32 ResVertexAttribute::GetVertexCount() { NW_ASSERT( this->IsValid() ); if ( this->GetFlags() & ResVertexAttributeData::FLAG_VERTEX_PARAM ) { // 頂点を持っていないので 0 を返す。 return 0; } else if ( this->GetFlags() & ResVertexAttributeData::FLAG_INTERLEAVE ) { ResInterleavedVertexStream stream = ResStaticCast( *this ); return stream.GetStreamCount() / stream.GetStride(); } else { ResVertexStream stream = ResStaticCast( *this ); size_t sizePerVertex; switch (stream.GetFormatType()) { case GL_BYTE: case GL_UNSIGNED_BYTE: sizePerVertex = 1; break; case GL_SHORT: // case GL_UNSIGNED_SHORT: 対応していない。 sizePerVertex = 2; break; case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: sizePerVertex = 4; break; default: NW_FATAL_ERROR("Unsupported format\n"); } sizePerVertex *= stream.GetDimension(); return stream.GetStreamCount() / sizePerVertex; } } //----------------------------------------------------------------------------- void ResVertexParamAttribute::Setup() { } //----------------------------------------------------------------------------- void ResVertexParamAttribute::Cleanup() { } //----------------------------------------------------------------------------- void ResVertexStream::Setup() { if (ref().m_BufferObject) { return; } ResVertexStreamData* dataPtr = ptr(); u32 bufferID = reinterpret_cast( dataPtr ); this->ref().m_BufferObject = bufferID; // 既にアドレスが設定されている場合にはデータのコピーをおこなわない。 if (this->GetLocationAddress() != NULL) { ref().m_MemoryArea = ResVertexStreamBaseData::AREA_NO_MALLOC; return; } u32 size = this->GetStreamCount(); // 頂点バッファのメモリへの読み込み指定 int loadFlag = this->GetLocationFlag(); // デフォルトは、FCRAM から NO_COPY。 if (loadFlag == 0) { loadFlag = NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP; } BufferData( bufferID, *this, loadFlag ); } //----------------------------------------------------------------------------- void ResVertexStream::Cleanup() { GLuint bufferID = this->GetBufferObject(); if ( bufferID == 0 ) { return; } DeleteBuffer( bufferID, *this ); this->SetBufferObject( 0 ); } //----------------------------------------------------------------------------- void ResInterleavedVertexStream::Setup() { if (ref().m_BufferObject) { return; } u32 bufferID = reinterpret_cast( this->ptr() ); this->ref().m_BufferObject = bufferID; // 既にアドレスが設定されている場合にはデータのコピーをおこなわない。 if ( this->GetLocationAddress() != NULL ) { ref().m_MemoryArea = ResVertexStreamBaseData::AREA_NO_MALLOC; return; } u32 size = this->GetStreamCount(); // 頂点バッファのメモリへの読み込み指定 int loadFlag = this->GetLocationFlag(); // デフォルトは、FCRAM から NO_COPY。 if (loadFlag == 0) { loadFlag = NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP; } BufferData( bufferID, *this, loadFlag ); } //----------------------------------------------------------------------------- void ResInterleavedVertexStream::Cleanup() { GLuint bufferID = this->GetBufferObject(); if ( bufferID == 0 ) { return; } DeleteBuffer( bufferID, *this ); this->SetBufferObject( 0 ); } //---------------------------------------------------------- u32 ResIndexStream::GetVertexCount() { NW_ASSERT( this->IsValid() ); size_t sizePerVertex; switch (this->GetFormatType()) { case GL_BYTE: case GL_UNSIGNED_BYTE: sizePerVertex = 1; break; case GL_SHORT: // case GL_UNSIGNED_SHORT: 対応していない。 sizePerVertex = 2; break; case GL_INT: case GL_UNSIGNED_INT: case GL_FLOAT: sizePerVertex = 4; break; default: NW_FATAL_ERROR("Unsupported format\n"); } return this->GetStreamCount() / sizePerVertex; } } /* namespace res */ } /* namespace gfx */ } /* namespace nw */