1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_DisplayList.h
4 
5   Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc.  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   $Revision: 26419 $
14  *---------------------------------------------------------------------------*/
15 #ifndef NW_GFX_DISPLAYLIST_H_
16 #define NW_GFX_DISPLAYLIST_H_
17 
18 #include <nw/types.h>
19 #include <nw/ut/ut_Inlines.h>
20 #include <nw/gfx/gfx_GlImplement.h>
21 #include <nw/dev.h>
22 
23 #include <gles2/gl2.h>
24 #include <gles2/gl2ext.h>
25 #include <nn/gx.h>
26 #include <cstring>
27 
28 namespace nw {
29 namespace gfx {
30 namespace internal {
31 
32 
33 //--------------------------------------------------------------------------
34 //! @brief     プリミティブなコマンド列を生成する為のユーティリティです。
35 //---------------------------------------------------------------------------
36 class GpuCommand
37 {
38 public:
39 
40     //--------------------------------------------------------------------------
41     //! @brief        コンストラクタです。
42     //--------------------------------------------------------------------------
GpuCommand()43     GpuCommand()
44      : m_CurrentBuffer( NULL ),
45        m_StartAddress( NULL ),
46        m_CurrentHeader( NULL ),
47        m_Size(0)
48     {}
49 
50     //--------------------------------------------------------------------------
51     //! @brief        コマンドの生成を開始します。
52     //!
53     //! @param[out]   addr  コマンドを構築する先頭アドレスです。
54     //--------------------------------------------------------------------------
Begin(void * addr)55     void Begin(void* addr)
56     {
57         NW_NULL_ASSERT( addr );
58 
59         m_CurrentBuffer = reinterpret_cast<u32*>(addr);
60         m_StartAddress  = reinterpret_cast<u32*>(addr);
61     }
62 
63     //--------------------------------------------------------------------------
64     //! @brief        ひとまとまりのコマンド生成を開始します。単一アドレスへの書き込みです。
65     //!
66     //! @param[in]    regAddr        書き込み先のレジスタアドレスです。
67     //! @param[in]    byteEnable    バイトイネーブルの設定です。
68     //--------------------------------------------------------------------------
69     void WriteHeader(u32 regAddr, u8 byteEnable = 0xf)
70     {
71         this->Align8();
72 
73         m_CurrentHeader = m_CurrentBuffer + 1;
74         *m_CurrentHeader = internal::MakeCommandHeader(regAddr, 1, false, byteEnable);
75     }
76 
77     //--------------------------------------------------------------------------
78     //! @brief        ひとまとまりのコマンド生成を開始します。連続アドレスへの書き込みです。
79     //!
80     //! @param[in]    regAddr        書き込み先のレジスタアドレスです。
81     //! @param[in]    byteEnable    バイトイネーブルの設定です。
82     //--------------------------------------------------------------------------
83     void WriteHeaderIncremental(u32 regAddr, u8 byteEnable = 0xf)
84     {
85         this->Align8();
86 
87         m_CurrentHeader = m_CurrentBuffer + 1;
88         *m_CurrentHeader = internal::MakeCommandHeader(regAddr, 1, true, byteEnable);
89     }
90 
91     //--------------------------------------------------------------------------
92     //! @brief        u32フォーマットのデータを書き込みます。
93     //!
94     //! @param[in]    data    書き込むデータです。
95     //--------------------------------------------------------------------------
WriteData(u32 data)96     void WriteData(u32 data)
97     {
98         *m_CurrentBuffer = data;
99 
100         if (m_Size == 0)
101         {
102             m_Size = 2;
103             m_CurrentBuffer += 2;
104         }
105         else
106         {
107             m_Size += 1;
108             m_CurrentBuffer += 1;
109         }
110     }
111 
112     //--------------------------------------------------------------------------
113     //! @brief        データ列を書き込みます。
114     //!
115     //! @param[in]    data    データ列へのポインタです。
116     //! @param[in]    count   格納するデータ数です。
117     //--------------------------------------------------------------------------
WriteData(const void * data,int count)118     void WriteData(const void* data, int count)
119     {
120         NW_NULL_ASSERT( data );
121         NW_ASSERT( count > 0 );
122 
123         const u32* pData = reinterpret_cast<const u32*>(data);
124         int copyCount = count;
125 
126         if (m_Size == 0)
127         {
128             *m_CurrentBuffer = *pData;
129             pData += 1;
130             copyCount -= 1;
131             m_CurrentBuffer += 2;
132             m_Size = 2;
133         }
134 
135         if (copyCount > 0)
136         {
137             nw::os::MemCpy(m_CurrentBuffer, pData, copyCount * sizeof(u32));
138             m_Size += copyCount;
139             m_CurrentBuffer += copyCount;
140         }
141     }
142 
143     //--------------------------------------------------------------------------
144     //! @brief    コマンドを生成を終了します。
145     //!
146     //! @return   先頭アドレスからのデータサイズを返します。
147     //--------------------------------------------------------------------------
End()148     u32 End()
149     {
150         this->Align8();
151 
152         return reinterpret_cast<u32>(m_CurrentBuffer) - reinterpret_cast<u32>(m_StartAddress);
153     }
154 
155 private:
156 
157     //--------------------------------------------------------------------------
158     //! @brief        コマンド終端の64bitアライメントを挿入します。
159     //--------------------------------------------------------------------------
Align8()160     void Align8()
161     {
162         enum
163         {
164             SIZE_SHIFT = 20,
165             SIZE_WIDTH = 8
166         };
167 
168         // ヘッダにデータ数を保存。
169         if (m_Size > 0)
170         {
171             NW_NULL_ASSERT( m_CurrentHeader );
172 
173             // データ数は、ヘッダを除いて m_Size - 1。レジスタへは count - 1 を格納するので -2。
174             *m_CurrentHeader |= ut::internal::MakeBits(m_Size - 2, SIZE_WIDTH, SIZE_SHIFT);
175             m_CurrentHeader = NULL;
176         }
177 
178         // アライメントの挿入。
179         if ((m_Size % 2) == 1)
180         {
181             *m_CurrentBuffer = 0x0;
182             m_CurrentBuffer += 1;
183         }
184 
185         m_Size = 0;
186     }
187 
188     u32* m_CurrentBuffer;
189     u32* m_StartAddress;
190     u32* m_CurrentHeader;
191     u32  m_Size;
192 };
193 
194 
195 } // namespace internal
196 } // namespace gfx
197 } // namespace nw
198 
199 #endif // NW_GFX_DISPLAYLIST_H_
200