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