1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     font_RectDrawer.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 
18 #ifndef NW_FONT_RECTDRAWER_H_
19 #define NW_FONT_RECTDRAWER_H_
20 
21 //--------------------------------------
22 // 動作設定
23 
24 // glDrawArraysで描画する方が速い?
25 #define NW_FONT_RECTDRAWER_USE_DRAW_ARRAYS 1
26 
27 // Bufferにためられるなら、ためて同時描画
28 #define NW_FONT_RECTDRAWER_USE_DRAW_BUFFER 1
29 
30 
31 #include <nn/assert.h>
32 #include <nw/ut/ut_CmdCache.h>
33 #if defined(NW_PLATFORM_CTR)
34     #include <nn/gx/CTR/gx_CommandAccess.h>
35 #endif
36 
37 #include <nw/font/font_RectDrawerCommand.h>
38 
39 #define NW_FONT_COMMAND_SET_BLEND_FUNC( eq, src, dst ) \
40     PICA_CMD_DATA_COLOR_OPERATION( \
41         PICA_DATA_FRAGOP_MODE_DMP, \
42         PICA_DATA_ENABLE_BLEND ), \
43     PICA_CMD_HEADER_SINGLE( PICA_REG_COLOR_OPERATION ), \
44     PICA_CMD_DATA_BLEND_FUNC( eq, src, dst ), \
45     PICA_CMD_HEADER_SINGLE( PICA_REG_BLEND_FUNC )
46 
47 #define NW_FONT_COMMAND_SET_BLEND_DEFAULT \
48     NW_FONT_COMMAND_SET_BLEND_FUNC( \
49         PICA_DATA_BLEND_EQUATION_ADD, \
50         PICA_DATA_BLEND_FUNC_SRC_ALPHA, \
51         PICA_DATA_BLEND_FUNC_ONE_MINUS_SRC_ALPHA )
52 
53 namespace nw {
54 namespace font {
55 
56 struct DispStringBuffer;
57 class CharWriter;
58 
59 //---------------------------------------------------------------------------
60 //! @brief      文字を描画するクラスです。
61 //---------------------------------------------------------------------------
62 class RectDrawer
63 {
64 public:
65     enum
66     {
67         DONT_USE_SETUP_COMMAND = 0x1
68     };
69 
70     //! @brief      RectDrawerが必要な頂点バッファ・コマンドバッファのサイズを取得します。
71     //!
72     //! @param[in]  shaderBinary  シェーダバイナリ。
73     //! @param[in]  size          シェーダバイナリのサイズ。
74     //!
75     //! @return     頂点バッファ・コマンドバッファのメモリサイズを返します。
76     //!
77     static u32          GetVertexBufferCommandBufferSize(
78                             const void* shaderBinary,
79                             u32         size);
80 
81     //! @brief      RectDrawerが使用する頂点バッファのデータを取得します。
82     //!
83     //! @return     頂点バッファのデータを返します。
84     //!
85     static void*        GetVertexBufferData();
86 
87     //! @brief      RectDrawerが必要な頂点バッファのサイズを取得します。
88     //!
89     //! @return     頂点バッファのメモリサイズを返します。
90     //!
91     static u32          GetVertexBufferSize();
92 
93     //! @brief      RectDrawerが必要なコマンドバッファのサイズを取得します。
94     //!
95     //! @param[in]  shaderBinary  シェーダバイナリ。
96     //! @param[in]  size          シェーダバイナリのサイズ。
97     //!
98     //! @return     コマンドバッファのメモリサイズを返します。
99     //!
100     static u32          GetCommandBufferSize(
101                             const void* shaderBinary,
102                             u32         size);
103 
104     //! @name コンストラクタ/デストラクタ
105     //@{
106 
107     //! コンストラクタです。
108                         RectDrawer();
109 
110     //! @brief      デストラクタです。
111     //!
112     //! @details    Finalize() を呼び出します。
113     //!
114     //! @sa         Finalize
115     //!
116     //! @since      2010/06/02 初版。
117     //!
118     virtual             ~RectDrawer();
119 
120     //@}
121 
122     //! @name 初期化/後処理
123     //@{
124 
125     //! @brief      初期化を行います。
126     //!
127     //! @param[in]  vtxBufCmdBuf  頂点用バッファ・コマンドバッファ。
128     //! @param[in]  shaderBinary  シェーダバイナリ。
129     //! @param[in]  size          シェーダバイナリのサイズ。
130     //!
131     //! @sa         Finalize
132     //!
133     //! @since      2010/07/29 引数を変更。
134     //! @since      2010/06/02 初版。
135     //!
136     void                Initialize(
137                             void*       vtxBufCmdBuf,
138                             const void* shaderBinary,
139                             u32         size);
140 
141     //! @brief      初期化を行います。
142     //!
143     //! @param[in]  vertexBuffer  頂点用バッファ。
144     //! @param[in]  commandBuffer コマンドバッファ。
145     //! @param[in]  shaderBinary  シェーダバイナリ。
146     //! @param[in]  size          シェーダバイナリのサイズ。
147     //!
148     //! @sa         Finalize
149     //!
150     //! @since      2010/07/29 引数を変更。
151     //! @since      2010/06/02 初版。
152     //!
153     void                Initialize(
154                             void*       vertexBuffer,
155                             void*       commandBuffer,
156                             const void* shaderBinary,
157                             u32         size);
158 
159     //! @brief      終了処理を行います。
160     //!
161     //! @sa         Initialize
162     //!
163     //! @since      2010/06/02 初版。
164     //!
165     virtual void        Finalize();
166 
167     //@}
168 
169     //! @brief      描画を開始します。
170     //!
171     //! @param[in]  flag 描画を制御するフラグ。
172     //!
173     //! @sa         DrawEnd
174     //!
175     //! @since      2010/06/28 初版。
176     //!
177     virtual void        DrawBegin(u32 flag = 0);
178 
179     //! @brief      描画を終了します。
180     //!
181     //! @param[in]  flag 描画を制御するフラグ。
182     //!
183     //! @sa         DrawBegin
184     //!
185     //! @since      2010/06/28 初版。
186     //!
187     virtual void        DrawEnd(u32 flag = 0);
188 
189     //! @brief      射影行列を設定します。
190     //!
191     //! @param[in]  mtx  射影行列
192     //!
193     void                SetProjectionMtx(const nn::math::MTX44& mtx);
194 
195     //! @brief      テキスト用のビュー行列を設定します。
196     //!
197     //! @param[in]  mtx  ビュー行列
198     //!
199     void                SetViewMtxForText(const nn::math::MTX34& mtx);
200 
201     //! @brief      視差のパラメータを設定します。
202     //!
203     //! @param[in]  parallax 視差。
204     //! @param[in]  dLevel  カメラから基準面までの距離。
205     //! @param[in]  addDist カメラとの距離に追加する値。
206     //!
207     void                SetParallax(
208                             f32     parallax,
209                             f32     dLevel,
210                             f32     addDist     = 0.0f
211                         );
212 
213     //! @brief      文字列用の描画コマンドを作成します。
214     //!
215     //! @param[in]  pCharWriter CharWriter オブジェクトへのポインタ。
216     //!
217     void                BuildTextCommand(CharWriter* pCharWriter);
218 
219     //! @details :private
220     void                UniformAndDrawText(DispStringBuffer* pDispStringBuffer);
221 
222     //! @details :private
223     void                UseBeginCommand();
224 
225     //! @details :private
226     void                UseEndCommand();
227 
228 protected:
229 
230     //! @details :private
SetUniformCommand(u32 * buffer,u32 num)231     static u32          SetUniformCommand(
232                             u32*    buffer,
233                             u32     num
234                         )
235     {
236 #if defined(NW_PLATFORM_CTR)
237         buffer[2] = buffer[3];
238         buffer[3] = PICA_CMD_HEADER_VS_F32(num);
239 #else
240         NN_ASSERT(false);
241         (void)buffer;
242 #endif
243         return sizeof(u32) * (4 + 4 * num);
244     }
245 
246     //! @details :private
247     void                DisableTextures();
248 
249     //! @details :private
250     void                AddUniformMtx();
251 
252 #if defined(NW_FONT_RECTDRAWER_USE_DRAW_ARRAYS)
253     //! @details :private
254     u32                 GetVertexIndexAddressOffset(u32 vtxNum) const;
255 #endif
256 
257     //! @details :private
258     const u32*          GetDrawCommands() const;
259 
260     //! @details :private
261     u32                 GetDrawCommandSize() const;
262 
263 private:
264     static void         InitializeStatic();
265 
266     void                InitializeCMD(
267                             void*       vertexBuffer,
268                             void*       commandBuffer,
269                             const void* shaderBinary,
270                             u32         size,
271                             bool        initVertexBuffer);
272 
273     void                InitUniformBuffer(
274                             u32* __restrict buf,
275                             u32             addr);
276 
277     void                AddTextColor(
278                             math::VEC4* __restrict          dst,
279                             const ut::Color8* __restrict    src,
280                             int                             mode);
281 
282 protected:
283     ////////////////////////////// Vertex Shader Info
284 
285     //! @details :private
286     enum
287     {
288         UNIFORM_MTX_USE_MAX     =  3 /* mtx row */ + 4 /* vtx color */,
289         UNIFORM_DATA_USE_MAX    =  1 /* rect */ + 3/* TexMapMax */ * 2,
290 
291         UNIFORM_TEXT_MTX_MAX    =  3,   // mtx34 row
292 
293         UNIFORM_PROJ_NUM        =  4,   // mtx44 row
294 
295         UNIFORM_PROJ_START      =  0,
296         UNIFORM_ULCDDATA_START  = UNIFORM_PROJ_START + UNIFORM_PROJ_NUM,
297         UNIFORM_CONST_START,
298         UNIFORM_ADDR_START,
299         UNIFORM_MTX_START       = 32,
300         UNIFORM_DATA_START      = 64,
301 
302         UNIFORM_TEXTCOLOR_START = UNIFORM_MTX_START + UNIFORM_TEXT_MTX_MAX,
303 
304         UNIFORM_MAX             = 96
305     };
306 
307     //! @details :private
308     enum
309     {
310 #ifdef NW_FONT_RECTDRAWER_USE_DRAW_BUFFER
311 
312         UNIFORM_ADDR_NUM        = UNIFORM_MTX_START  - UNIFORM_ADDR_START,
313         UNIFORM_MTX_NUM         = UNIFORM_DATA_START - UNIFORM_MTX_START,
314         UNIFORM_DATA_NUM        = UNIFORM_MAX        - UNIFORM_DATA_START,
315 
316         UNIFORM_TEXTCOLOR_NUM   = (UNIFORM_DATA_START - UNIFORM_TEXTCOLOR_START) & ~((1 << 2) - 1),
317 #else
318 
319         UNIFORM_RESISTER_ADDR = 5,
320 
321         // まとめて描かないなら、最大8レジスタ
322         UNIFORM_DATA_NUM  = 8,
323 
324         UNIFORM_ADDR_NUM      = UNIFORM_DATA_NUM - UNIFORM_RESISTER_ADDR,
325 #endif
326 
327         DRAW_VTX_NUM          = 6,
328         BIND_ATTRIB_LOCATION  = 0
329     };
330 
331 
332     ////////////////////////////// Command
333 
334     //! @details :private
335     ut::internal::CmdCache
336                         m_CmdCacheDrawBegin;
337 
338     //! @details :private
339     ut::internal::CmdCache
340                         m_CmdCacheDrawEnd;
341 
342     //! @details :private
343     u8                  m_UniformAddrIndex;
344 
345     //! @details :private
346     u8                  m_UniformMtxIndex;
347 
348     //! @details :private
349     u8                  m_UniformDataIndex;
350 
351     //! @details :private
352     u8                  m_UniformTextColorIndex;
353 
354     //! @details :private
355     u32                 m_UniformProjBuffer[ 4 + 4 * (UNIFORM_PROJ_NUM + 1) ];
356 
357     //! @details :private
358     u32                 m_UniformAddrBuffer[ 4 + 4 * UNIFORM_ADDR_NUM ];
359 
360     //! @details :private
361     union
362     {
363         //! @details :private
364         u32                 m_UniformMtxBuffer[ 4 + 4 * UNIFORM_MTX_NUM  ];
365 
366         //! @details :private
367         struct
368         {
369 
370             //! @details :private
371             u32                 m_UniformTextMtxBuffer  [ 4 + 4 * UNIFORM_TEXT_MTX_MAX ];
372 
373             //! @details :private
374             u32                 m_UniformTextColorBuffer[ 4 + 4 * UNIFORM_TEXTCOLOR_NUM ];
375         };
376     };
377 
378     //! @details :private
379     u32                 m_UniformDataBuffer[ 4 + 4 * UNIFORM_DATA_NUM ];
380 
381     //! @details :private
382     struct UniformAddress
383     {
384         //! @details :private
UniformAddressUniformAddress385                             UniformAddress()
386                             :   addrMtx(0.f),
387                                 addrSizeAndVtx(0.f),
388                                 addrTexCoord(0.f),
389                                 addrColor(0.f)
390                             {}
391 
392         //! @details :private
393         f32                 addrMtx;
394 
395         //! @details :private
396         f32                 addrSizeAndVtx;
397 
398         //! @details :private
399         f32                 addrTexCoord;
400 
401         //! @details :private
402         f32                 addrColor;
403     };
404 
405     //! @details :private
406     UniformAddress      m_UniformAddress;
407 
408     //! @details :private
409     UniformAddress *const
410                         m_UniformAddr;
411 
412     //! @details :private
413     math::VEC4 *const   m_UniformMtx;
414 
415     //! @details :private
416     math::VEC4 *const   m_UniformData;
417 
418     //! @details :private
419     math::VEC4 *const   m_UniformTextColor;
420 
421     //! @details :private
422     void*               m_CommandBuffer;
423 
424     ////////////////////////////// Vertex Buufer Object
425 
426     //! @details :private
427     void*               m_VertexBufferArray;
428 
429     ////////////////////////////// Uniform
430 
431 #if defined(NW_FONT_RECTDRAWER_USE_DRAW_ARRAYS)
432     //! @details :private
433     u32                 m_VertexBufferBaseAddr;
434 #endif
435 
436     //! :private
437     //! @brief      色が変更されているかどうか
438     bool                m_IsColorDirty;
439 
440 private:
441     struct VertexBuffer
442     {
443 #if defined(NW_FONT_RECTDRAWER_USE_DRAW_ARRAYS)
444         f32                 position[UNIFORM_ADDR_NUM][DRAW_VTX_NUM][4];
445 #else
446         f32                 position[UNIFORM_ADDR_NUM][VERTEX_MAX][4];
447         u16                 indexes[UNIFORM_ADDR_NUM][DRAW_VTX_NUM];
448 #endif
449     };
450 
451     static bool         s_StaticInitialized;
452     static VertexBuffer s_VertexBuffer;
453 };
454 
455 inline
456 u32
GetVertexBufferSize()457 RectDrawer::GetVertexBufferSize()
458 {
459     return sizeof(s_VertexBuffer);
460 }
461 
462 namespace internal
463 {
464 
465 #if defined(NW_PLATFORM_CTR)
466 inline
467 u32*
SetVertexNumCmd(u32 ** pCmdPtr,u32 addrOffset,u32 vtxNum)468 SetVertexNumCmd(
469     u32**   pCmdPtr,
470     u32     addrOffset,
471     u32     vtxNum
472     )
473 {
474 #if defined(NW_FONT_RECTDRAWER_USE_DRAW_ARRAYS)
475     // 頂点インデックスのアドレス/型
476     // 0x227
477     NW_FONT_ADD_SINGLE_COMMAND_PTR(
478         *pCmdPtr,
479         PICA_CMD_HEADER_SINGLE( PICA_REG_INDEX_ARRAY_ADDR_OFFSET ),
480         PICA_CMD_DATA_INDEX_ARRAY_ADDR_OFFSET( addrOffset, 1 /* type */ ));
481 #else
482     (void)addrOffset;
483 #endif
484 
485     // 描画頂点数
486     // 0x228
487     NW_FONT_ADD_SINGLE_COMMAND_PTR(
488         *pCmdPtr,
489         PICA_CMD_HEADER_SINGLE( PICA_REG_DRAW_VERTEX_NUM ),
490         PICA_CMD_DATA_DRAW_VERTEX_NUM( vtxNum ));
491 
492     return *pCmdPtr;
493 }
494 #endif
495 
496 }   // namespace internal
497 
498 }   // namespace font
499 }   // namespace nw
500 
501 #endif //  NW_FONT_RECTDRAWER_H_
502