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