/*---------------------------------------------------------------------------* Project: NintendoWare File: gfx_DisplayList.h 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: 31311 $ *---------------------------------------------------------------------------*/ #ifndef NW_GFX_DISPLAYLIST_H_ #define NW_GFX_DISPLAYLIST_H_ #include #include #include #include #include #include #include #include namespace nw { namespace gfx { namespace internal { //-------------------------------------------------------------------------- //! @brief プリミティブなコマンド列を生成する為のユーティリティです。 //--------------------------------------------------------------------------- class GpuCommand { public: //-------------------------------------------------------------------------- //! @brief コンストラクタです。 //-------------------------------------------------------------------------- GpuCommand() : m_CurrentBuffer( NULL ), m_StartAddress( NULL ), m_CurrentHeader( NULL ), m_Size(0) {} //-------------------------------------------------------------------------- //! @brief コマンドの生成を開始します。 //! //! @param[out] addr コマンドを構築する先頭アドレスです。 //-------------------------------------------------------------------------- void Begin(void* addr) { NW_NULL_ASSERT( addr ); m_CurrentBuffer = reinterpret_cast(addr); m_StartAddress = reinterpret_cast(addr); } //-------------------------------------------------------------------------- //! @brief ひとまとまりのコマンド生成を開始します。単一アドレスへの書き込みです。 //! //! @param[in] regAddr 書き込み先のレジスタアドレスです。 //! @param[in] byteEnable バイトイネーブルの設定です。 //-------------------------------------------------------------------------- void WriteHeader(u32 regAddr, u8 byteEnable = 0xf) { this->Align8(); m_CurrentHeader = m_CurrentBuffer + 1; *m_CurrentHeader = internal::MakeCommandHeader(regAddr, 1, false, byteEnable); } //-------------------------------------------------------------------------- //! @brief ひとまとまりのコマンド生成を開始します。連続アドレスへの書き込みです。 //! //! @param[in] regAddr 書き込み先のレジスタアドレスです。 //! @param[in] byteEnable バイトイネーブルの設定です。 //-------------------------------------------------------------------------- void WriteHeaderIncremental(u32 regAddr, u8 byteEnable = 0xf) { this->Align8(); m_CurrentHeader = m_CurrentBuffer + 1; *m_CurrentHeader = internal::MakeCommandHeader(regAddr, 1, true, byteEnable); } //-------------------------------------------------------------------------- //! @brief u32フォーマットのデータを書き込みます。 //! //! @param[in] data 書き込むデータです。 //-------------------------------------------------------------------------- void WriteData(u32 data) { *m_CurrentBuffer = data; if (m_Size == 0) { m_Size = 2; m_CurrentBuffer += 2; } else { m_Size += 1; m_CurrentBuffer += 1; } } //-------------------------------------------------------------------------- //! @brief データ列を書き込みます。 //! //! @param[in] data データ列へのポインタです。 //! @param[in] count 格納するデータ数です。 //-------------------------------------------------------------------------- void WriteData(const void* data, int count) { NW_NULL_ASSERT( data ); NW_ASSERT( count > 0 ); const u32* pData = reinterpret_cast(data); int copyCount = count; if (m_Size == 0) { *m_CurrentBuffer = *pData; pData += 1; copyCount -= 1; m_CurrentBuffer += 2; m_Size = 2; } if (copyCount > 0) { nw::os::MemCpy(m_CurrentBuffer, pData, copyCount * sizeof(u32)); m_Size += copyCount; m_CurrentBuffer += copyCount; } } //-------------------------------------------------------------------------- //! @brief コマンドを生成を終了します。 //! //! @return 先頭アドレスからのデータサイズを返します。 //-------------------------------------------------------------------------- u32 End() { this->Align8(); return reinterpret_cast(m_CurrentBuffer) - reinterpret_cast(m_StartAddress); } private: //-------------------------------------------------------------------------- //! @brief コマンド終端の64bitアライメントを挿入します。 //-------------------------------------------------------------------------- void Align8() { enum { SIZE_SHIFT = 20, SIZE_WIDTH = 8 }; // ヘッダにデータ数を保存。 if (m_Size > 0) { NW_NULL_ASSERT( m_CurrentHeader ); // データ数は、ヘッダを除いて m_Size - 1。レジスタへは count - 1 を格納するので -2。 *m_CurrentHeader |= ut::internal::MakeBits(m_Size - 2, SIZE_WIDTH, SIZE_SHIFT); m_CurrentHeader = NULL; } // アライメントの挿入。 if ((m_Size % 2) == 1) { *m_CurrentBuffer = 0x0; m_CurrentBuffer += 1; } m_Size = 0; } u32* m_CurrentBuffer; u32* m_StartAddress; u32* m_CurrentHeader; u32 m_Size; }; } // namespace internal } // namespace gfx } // namespace nw #endif // NW_GFX_DISPLAYLIST_H_