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