1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     main.cpp
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: 23847 $
14  *---------------------------------------------------------------------------*/
15 
16 
17 //------------------------------------------------------------------
18 // デモ: ResFont
19 //
20 // 概要
21 //   nw::font::ResFont の構築と破棄のサンプルです。
22 //
23 // 操作
24 //   なし。
25 //
26 //------------------------------------------------------------------
27 
28 #include <GLES2/gl2.h>
29 #include <GLES2/gl2ext.h>
30 #include <nn.h>
31 #include <nn/math.h>
32 #include <nn/fs.h>
33 #include <nw/sdk.h>
34 #include <nw/font/font_TextWriter.h>
35 #include <nw/font/font_ResFont.h>
36 #include <nw/font/font_RectDrawer.h>
37 #include <nw/demo.h>
38 
39 namespace
40 {
41 
42 bool    s_InitAsciiString   = false;
43 u32     s_Counter           = 0;
44 u8      s_Color             = 0;
45 
46 //---------------------------------------------------------------------------
47 //! @brief      メモリを確保します。
48 //!
49 //! @param[in]  size      確保するメモリのサイズ。
50 //! @param[in]  alignment 確保するメモリのアライメント値。
51 //!
52 //! @return     確保したメモリへのポインタを返します。
53 //---------------------------------------------------------------------------
54 void*
MemAlloc(size_t size,u8 alignment=4)55 MemAlloc(
56     size_t  size,
57     u8      alignment = 4
58 )
59 {
60     return nw::demo::SimpleApp::Allocate(size, alignment);
61 }
62 
63 //---------------------------------------------------------------------------
64 //! @brief      デバイスメモリからメモリを確保します。
65 //!
66 //! @param[in]  size      確保するメモリのサイズ。
67 //! @param[in]  alignment 確保するメモリのアライメント値。
68 //!
69 //! @return     確保したメモリへのポインタを返します。
70 //---------------------------------------------------------------------------
71 void*
DevMemAlloc(size_t size,u8 alignment=4)72 DevMemAlloc(
73     size_t  size,
74     u8      alignment = 4
75 )
76 {
77     return nw::demo::SimpleApp::AllocateDeviceMemory(size, alignment);
78 }
79 
80 //---------------------------------------------------------------------------
81 //! @brief      メモリを解放します。
82 //!
83 //! @param[in]  memory 解放するメモリへのポインタ。
84 //---------------------------------------------------------------------------
85 void
MemFree(void * memory)86 MemFree(void* memory)
87 {
88     nw::demo::SimpleApp::Free(memory);
89 }
90 
91 //---------------------------------------------------------------------------
92 //! @brief      シェーダの初期化を行います。
93 //!
94 //! @param[in]  pDrawer RectDrawerオブジェクトへのポインタ。
95 //---------------------------------------------------------------------------
96 void*
InitShaders(nw::font::RectDrawer * pDrawer)97 InitShaders(nw::font::RectDrawer* pDrawer)
98 {
99     const wchar_t* shaders = NW_DEMO_FILE_PATH( NW_FONT_RECTDRAWER_SHADERBINARY );
100     nn::fs::FileReader shaderReader(shaders);
101 
102     const u32 fileSize = (u32)shaderReader.GetSize();
103 
104     void* shaderBinary = MemAlloc(fileSize);
105     NN_NULL_ASSERT(shaderBinary);
106 
107     s32 read = shaderReader.Read(shaderBinary, fileSize);
108     NN_ASSERT(read == fileSize);
109 
110     const u32 vtxBufCmdBufSize =
111         nw::font::RectDrawer::GetVertexBufferCommandBufferSize(shaderBinary, fileSize);
112     void *const vtxBufCmdBuf = DevMemAlloc(vtxBufCmdBufSize);
113     NN_NULL_ASSERT(vtxBufCmdBuf);
114     pDrawer->Initialize(vtxBufCmdBuf, shaderBinary, fileSize);
115 
116     MemFree(shaderBinary);
117 
118     return vtxBufCmdBuf;
119 }
120 
121 //---------------------------------------------------------------------------
122 //! @brief      描画の初期設定を行います。
123 //!
124 //! @param[in]  width           画面の幅。
125 //! @param[in]  height          画面の高さ。
126 //---------------------------------------------------------------------------
127 void
InitDraw(int width,int height)128 InitDraw(
129     int     width,
130     int     height
131 )
132 {
133     // カラーバッファ情報
134     // LCDの向きに合わせて、幅と高さを入れ替えています。
135     const nw::font::ColorBufferInfo colBufInfo = { height, width, PICA_DATA_DEPTH24_STENCIL8_EXT };
136 
137     const u32 screenSettingCommands[] =
138     {
139         // ビューポートの設定
140         NW_FONT_CMD_SET_VIEWPORT( 0, 0, colBufInfo.width, colBufInfo.height ),
141 
142         // シザー処理を無効
143         NW_FONT_CMD_SET_DISABLE_SCISSOR( colBufInfo ),
144 
145         // wバッファの無効化
146         // デプスレンジの設定
147         // ポリゴンオフセットの無効化
148         NW_FONT_CMD_SET_WBUFFER_DEPTHRANGE_POLYGONOFFSET(
149             0.0f,           // wScale : 0.0 でWバッファが無効
150             0.0f,           // depth range near
151             1.0f,           // depth range far
152             0,              // polygon offset units : 0.0 で ポリゴンオフセットが無効
153             colBufInfo),
154     };
155 
156     nngxAdd3DCommand(screenSettingCommands, sizeof(screenSettingCommands), true);
157 
158     static const u32 s_InitCommands[] =
159     {
160         // カリングを無効
161         NW_FONT_CMD_SET_CULL_FACE( NW_FONT_CMD_CULL_FACE_DISABLE ),
162 
163         // ステンシルテストを無効
164         NW_FONT_CMD_SET_DISABLE_STENCIL_TEST(),
165 
166         // デプステストを無効
167         // カラーバッファの全ての成分を書き込み可
168         NW_FONT_CMD_SET_DEPTH_FUNC_COLOR_MASK(
169             false,  // isDepthTestEnabled
170             0,      // depthFunc
171             true,   // depthMask
172             true,   // red
173             true,   // green
174             true,   // blue
175             true),  // alpha
176 
177         // アーリーデプステストを無効
178         NW_FONT_CMD_SET_ENABLE_EARLY_DEPTH_TEST( false ),
179 
180         // フレームバッファアクセス制御
181         NW_FONT_CMD_SET_FBACCESS(
182             true,   // colorRead
183             true,   // colorWrite
184             false,  // depthRead
185             false,  // depthWrite
186             false,  // stencilRead
187             false), // stencilWrite
188     };
189 
190     nngxAdd3DCommand(s_InitCommands, sizeof(s_InitCommands), true);
191 }
192 
193 //---------------------------------------------------------------------------
194 //! @brief      ResFontを構築します。
195 //!
196 //! @param[out] pFont    構築するフォントへのポインタ。
197 //! @param[in]  filePath ロードするフォントリソースファイル名。
198 //!
199 //! @return     ResFont構築の成否を返します。
200 //---------------------------------------------------------------------------
201 bool
InitFont(nw::font::ResFont * pFont,const wchar_t * filePath)202 InitFont(
203     nw::font::ResFont*  pFont,
204     const wchar_t*      filePath
205 )
206 {
207     // フォントリソースをロードします
208     nn::fs::FileReader fontReader(filePath);
209 
210     s32 fileSize = (s32)fontReader.GetSize();
211     if ( fileSize <= 0 )
212     {
213         return false;
214     }
215 
216     void* buffer = DevMemAlloc(fileSize, nw::font::GlyphDataAlignment);
217     if (buffer == NULL)
218     {
219         return false;
220     }
221 
222     s32 readSize = fontReader.Read(buffer, fileSize);
223     if (readSize != fileSize)
224     {
225         MemFree(buffer);
226         return false;
227     }
228 
229     // フォントリソースをセットします
230     bool bSuccess = pFont->SetResource(buffer);
231     NN_ASSERT(bSuccess);
232 
233     //--- 既にリソースをセット済みであるか,ロード済みであるか、リソースが不正な場合に失敗します。
234     if (! bSuccess)
235     {
236         MemFree(buffer);
237     }
238 
239     // 描画用バッファを設定します。
240     const u32 drawBufferSize = nw::font::ResFont::GetDrawBufferSize(buffer);
241     void* drawBuffer = MemAlloc(drawBufferSize, 4);
242     NN_NULL_ASSERT(drawBuffer);
243     pFont->SetDrawBuffer(drawBuffer);
244 
245     return bSuccess;
246 }
247 
248 //---------------------------------------------------------------------------
249 //! @brief      ResFontを破棄します。
250 //!
251 //! @param[in]  pFont           破棄するフォントへのポインタ。
252 //---------------------------------------------------------------------------
253 void
CleanupFont(nw::font::ResFont * pFont)254 CleanupFont(nw::font::ResFont* pFont)
255 {
256     // 描画用バッファの無効化
257     // 描画用バッファがセットされているなら 構築時に SetDrawBuffer に渡したバッファへの
258     // ポインタが返ってきます。
259     void *const drawBuffer = pFont->SetDrawBuffer(NULL);
260     if (drawBuffer != NULL)
261     {
262         MemFree(drawBuffer);
263     }
264 
265     // フォントがセットされているなら SetResource 時に渡したリソースへの
266     // ポインタが返ってきます。
267     void *const resource = pFont->RemoveResource();
268     if (resource != NULL)
269     {
270         MemFree(resource);
271     }
272 
273     // RemoveResource 後は再度 SetResource するまでフォントとして使用できません。
274 }
275 
276 //---------------------------------------------------------------------------
277 //! @brief      表示文字列用バッファを確保します。
278 //!
279 //! @param[in]  charMax         表示する文字列の最大文字数。
280 //!
281 //! @return     確保した表示文字列用バッファへのポインタを返します。
282 //---------------------------------------------------------------------------
283 nw::font::DispStringBuffer*
AllocDispStringBuffer(int charMax)284 AllocDispStringBuffer(int charMax)
285 {
286     const u32 DrawBufferSize = nw::font::CharWriter::GetDispStringBufferSize(charMax);
287     void *const bufMem = MemAlloc(DrawBufferSize);
288     NN_NULL_ASSERT(bufMem);
289 
290     return nw::font::CharWriter::InitDispStringBuffer(bufMem, charMax);
291 }
292 
293 //---------------------------------------------------------------------------
294 //! @brief      文字列表示用にモデルビュー行列と射影行列を設定します。
295 //!
296 //! @param[in]  pDrawer         RectDrawerオブジェクトへのポインタ。
297 //! @param[in]  width           画面の幅。
298 //! @param[in]  height          画面の高さ。
299 //---------------------------------------------------------------------------
300 void
SetupTextCamera(nw::font::RectDrawer * pDrawer,int width,int height)301 SetupTextCamera(
302     nw::font::RectDrawer*   pDrawer,
303     int                     width,
304     int                     height
305 )
306 {
307     // 射影行列を正射影に設定
308     {
309         // 左上原点とし、Y軸とZ軸の向きが逆になるように設定します。
310         nn::math::MTX44 proj;
311         f32 znear   =  0.0f;
312         f32 zfar    = -1.0f;
313         f32 t       =  0;
314         f32 b       =  static_cast<f32>(height);
315         f32 l       =  0;
316         f32 r       =  static_cast<f32>(width);
317         nn::math::MTX44OrthoPivot(&proj, l, r, b, t, znear, zfar, nn::math::PIVOT_UPSIDE_TO_TOP);
318         pDrawer->SetProjectionMtx(proj);
319     }
320 
321     // モデルビュー行列を単位行列に設定
322     {
323         nn::math::MTX34 mv;
324         nn::math::MTX34Identity(&mv);
325         pDrawer->SetViewMtxForText(mv);
326     }
327 }
328 
329 //---------------------------------------------------------------------------
330 //! @brief      ASCII文字列を描画します。
331 //!
332 //! @param[in]  pDrawer         RectDrawerオブジェクトへのポインタ。
333 //! @param[in]  pDrawStringBuf  DispStringBufferオブジェクトへのポインタ。
334 //! @param[in]  pFont           フォントへのポインタ。
335 //! @param[in]  width           画面の幅。
336 //! @param[in]  height          画面の高さ。
337 //---------------------------------------------------------------------------
338 void
DrawAscii(nw::font::RectDrawer * pDrawer,nw::font::DispStringBuffer * pDrawStringBuf,nw::font::ResFont * pFont,int width,int height)339 DrawAscii(
340     nw::font::RectDrawer*           pDrawer,
341     nw::font::DispStringBuffer*     pDrawStringBuf,
342     nw::font::ResFont*              pFont,
343     int                             width,
344     int                             height
345 )
346 {
347     nw::font::TextWriter writer;
348     writer.SetDispStringBuffer(pDrawStringBuf);
349     writer.SetFont(pFont);
350 
351     writer.SetCursor(0, 0);
352 
353     // 文字列が変更されないので、文字列の描画コマンドを一度だけ作成します。
354     if (! s_InitAsciiString)
355     {
356         writer.StartPrint();
357             (void)writer.Print("DEMO: ResFont\n");
358             (void)writer.Print("\n");
359 
360             // ASCIIの文字見本を表示
361             (void)writer.Print("All ASCII Character listing:\n");
362             (void)writer.Print("\n");
363             (void)writer.Print(" !\"#$%&'()*+,-./\n");
364             (void)writer.Print("0123456789:;<=>?\n");
365             (void)writer.Print("@ABCDEFGHIJKLMNO\n");
366             (void)writer.Print("PQRSTUVWXYZ[\\]^_\n");
367             (void)writer.Print("`abcdefghijklmno\n");
368             (void)writer.Print("pqrstuvwxyz{|}~\n");
369         writer.EndPrint();
370         pDrawer->BuildTextCommand(&writer);
371 
372         s_InitAsciiString = true;
373     }
374 
375     // 文字の色は、文字列の描画コマンドを再作成しなくても変更できます。
376     writer.SetTextColor(nw::ut::Color8(s_Color, 255, s_Color, 255));
377     s_Color++;
378 
379     pDrawer->DrawBegin();
380 
381         SetupTextCamera(pDrawer, width, height);
382         writer.UseCommandBuffer();
383 
384     pDrawer->DrawEnd();
385 }
386 
387 //---------------------------------------------------------------------------
388 //! @brief      カウンタを描画します。
389 //!
390 //! @param[in]  pDrawer         RectDrawerオブジェクトへのポインタ。
391 //! @param[in]  pDrawStringBuf  DispStringBufferオブジェクトへのポインタ。
392 //! @param[in]  pFont           フォントへのポインタ。
393 //! @param[in]  width           画面の幅。
394 //! @param[in]  height          画面の高さ。
395 //---------------------------------------------------------------------------
396 void
DrawCounter(nw::font::RectDrawer * pDrawer,nw::font::DispStringBuffer * pDrawStringBuf,nw::font::ResFont * pFont,int width,int height)397 DrawCounter(
398     nw::font::RectDrawer*           pDrawer,
399     nw::font::DispStringBuffer*     pDrawStringBuf,
400     nw::font::ResFont*              pFont,
401     int                             width,
402     int                             height
403 )
404 {
405     nw::font::TextWriter writer;
406     writer.SetDispStringBuffer(pDrawStringBuf);
407     writer.SetFont(pFont);
408 
409     writer.SetCursor(0, 0);
410     writer.SetFixedWidth(8.0f);
411     writer.EnableFixedWidth(true);
412 
413     pDrawer->DrawBegin();
414 
415         SetupTextCamera(pDrawer, width, height);
416 
417         // カウンタの描画コマンドをその都度作成して使用します。
418         writer.StartPrint();
419             (void)writer.Printf("Counter      : %d\n", s_Counter);
420         writer.EndPrint();
421         pDrawer->BuildTextCommand(&writer);
422         writer.UseCommandBuffer();
423 
424         // カウンタ1/60の描画コマンドをその都度作成して使用します。
425         writer.StartPrint();
426             (void)writer.Printf("Counter 1/60 : %d\n", s_Counter / 60);
427         writer.EndPrint();
428         pDrawer->BuildTextCommand(&writer);
429         writer.UseCommandBuffer();
430 
431     pDrawer->DrawEnd();
432 
433     s_Counter++;
434 }
435 
436 }   // namespace
437 
438 
439 //---------------------------------------------------------------------------
440 //! @brief      サンプルのメイン関数です。
441 //---------------------------------------------------------------------------
442 void
nnMain()443 nnMain()
444 {
445     // os の初期化
446     nn::os::Initialize();
447 
448     // fs の初期化
449     nn::fs::Initialize();
450 
451     nw::demo::SimpleApp& demoApp = nw::demo::SimpleApp::GetInstance();
452 
453     demoApp.Initialize();
454 
455     nw::font::ResFont font;
456 
457     // フォントの構築
458     {
459         bool bSuccess = InitFont(&font, NW_DEMO_FILE_PATH(L"tahoma.bcfnt"));
460         NN_ASSERTMSG(bSuccess, "Fail to load ResFont.");
461     }
462 
463     // 描画リソースの構築
464     nw::font::RectDrawer drawer;
465 
466     void *const drawerBuf = InitShaders(&drawer);
467 
468     // 描画文字列用バッファの確保
469     nw::font::DispStringBuffer *const pDrawStringBuf0 = AllocDispStringBuffer(512);
470     nw::font::DispStringBuffer *const pDrawStringBuf1 = AllocDispStringBuffer(128);
471 
472     const nw::ut::FloatColor clearColor(0.3f, 0.3f, 0.3f, 1.0f);
473     const f32 clearDepth = 0.0f;
474 
475     // フォント情報の表示
476     volatile bool loop = true;
477     while (loop)
478     {
479         demoApp.SetRenderingTarget(demoApp.DISPLAY0);
480         {
481             demoApp.GetFrameBufferObject().ClearBuffer(clearColor, clearDepth);
482 
483             InitDraw(demoApp.DISPLAY0_WIDTH, demoApp.DISPLAY0_HEIGHT);
484 
485             DrawAscii(&drawer, pDrawStringBuf0, &font, demoApp.DISPLAY0_WIDTH, demoApp.DISPLAY0_HEIGHT);
486         }
487 
488         demoApp.SetRenderingTarget(demoApp.DISPLAY1);
489         {
490             demoApp.GetFrameBufferObject().ClearBuffer(clearColor, clearDepth);
491 
492             InitDraw(demoApp.DISPLAY1_WIDTH, demoApp.DISPLAY1_HEIGHT);
493 
494             DrawCounter(&drawer, pDrawStringBuf1, &font, demoApp.DISPLAY1_WIDTH, demoApp.DISPLAY1_HEIGHT);
495         }
496 
497         demoApp.SwapBuffer(demoApp.DISPLAY_BOTH);
498     }
499 
500     // 描画文字列用バッファの解放
501     MemFree(pDrawStringBuf1);
502     MemFree(pDrawStringBuf0);
503 
504     drawer.Finalize();
505 
506     MemFree(drawerBuf);
507 
508     // フォントの破棄
509     CleanupFont(&font);
510 }
511