1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     font_RectDrawer.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: 27727 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "precompiled.h"
17 
18 #include <GLES2/gl2.h>
19 #include <GLES2/gl2ext.h>
20 #include <nn/types.h>
21 #include <nn/assert.h>
22 #if defined(NW_PLATFORM_CTR)
23     #include <nn/version.h>
24     #include <nn/gx/CTR/gx_CommandAccess.h>
25 #endif
26 #include <nw/font/font_RectDrawer.h>
27 #include <nw/font/font_DispStringBuffer.h>
28 
29 #define NW_FONT_ADD_COMMANDS( pStrBuf, command, size )                                                  \
30     NW_ASSERT((pStrBuf)->commandBufferSize + (size) / sizeof(u32) <= (pStrBuf)->commandBufferCapacity); \
31     std::memcpy(&(pStrBuf)->commandBuffer[(pStrBuf)->commandBufferSize], command, size );               \
32     (pStrBuf)->commandBufferSize += (size) / sizeof(u32)
33 
34 #define NW_FONT_ADD_SINGLE_COMMAND( pStrBuf, header, data )                             \
35     NW_ASSERT((pStrBuf)->commandBufferSize + 2 <= (pStrBuf)->commandBufferCapacity);    \
36     (pStrBuf)->commandBuffer[(pStrBuf)->commandBufferSize + 0] = (data);                \
37     (pStrBuf)->commandBuffer[(pStrBuf)->commandBufferSize + 1] = (header);              \
38     (pStrBuf)->commandBufferSize += 2
39 
40 // 描画APIの指定
41 // 0x253 [0:0]
42 #define NW_FONT_CMD_SET_DRAW_FUNC( func )                   \
43     PICA_CMD_DATA_DRAW_MODE1( func, 0 /* mode */ ),         \
44     PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE1, 0x1 )
45 
46 // 描画モード
47 // 0x253 [8:8]
48 #define NW_FONT_CMD_SET_DRAW_MODE1( mode )                  \
49     PICA_CMD_DATA_DRAW_MODE1( 0 /* func */, mode ),         \
50     PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE1, 0x2 )
51 
52 // ロードアレイNの要素 8-11、バイト数、要素数
53 #define NW_FONT_CMD_DATA_LOAD_ARRAY_ELEMENT8( elm8, elm9, elm10, elm11, bytes, num )    \
54       ((elm8)  & 0x0F) <<  0 | ((elm9)  & 0x0F) <<  4                                   \
55     | ((elm10) & 0x0F) <<  8 | ((elm11) & 0x0F) << 12                                   \
56     | ((bytes) & 0xFF) << 16 | ((num)   & 0x0F) << 28
57 
58 // ロードアレイNのアドレスオフセット、要素、バイト数、要素数
59 #define NW_FONT_CMD_SET_LOAD_ARRAY( offset, elm0, elm1, elm2, elm3, elm4, elm5, elm6,       \
60     elm7, elm8, elm9, elm10, elm11, bytes, num )                                            \
61     (offset) & 0x0FFFFFFF,  /* アドレスオフセット */                                        \
62     PICA_CMD_DATA_LOAD_ARRAY0_ELEMENT( elm0, elm1, elm2, elm3, elm4, elm5, elm6, elm7 ),    \
63     NW_FONT_CMD_DATA_LOAD_ARRAY_ELEMENT8( elm8, elm9, elm10, elm11, bytes, num )
64 
65 #define NW_FONT_CMD_SET_LOAD_ARRAY_ZERO()                                           \
66     NW_FONT_CMD_SET_LOAD_ARRAY(                                                     \
67         0, /* offset */                                                             \
68         PICA_DATA_VERTEX_0_ATTR, PICA_DATA_VERTEX_0_ATTR, PICA_DATA_VERTEX_0_ATTR,  \
69         PICA_DATA_VERTEX_0_ATTR, PICA_DATA_VERTEX_0_ATTR, PICA_DATA_VERTEX_0_ATTR,  \
70         PICA_DATA_VERTEX_0_ATTR, PICA_DATA_VERTEX_0_ATTR, PICA_DATA_VERTEX_0_ATTR,  \
71         PICA_DATA_VERTEX_0_ATTR, PICA_DATA_VERTEX_0_ATTR, PICA_DATA_VERTEX_0_ATTR,  \
72         0,  /* bytes */                                                             \
73         0)  /* num */
74 
75 #define NW_FONT_CMD_SET_TEXTURE_LOD_DISABLE( addr )                                               \
76     PICA_CMD_DATA_TEXTURE_LOD_LEVEL( 0 /* lodBias */, 0 /* maxLodLevel */, 0 /* minLodLevel */ ), \
77     PICA_CMD_HEADER_SINGLE( addr )
78 
79 // 頂点インデックスの内部状態のクリア
80 #define NW_FONT_CMD_SET_VERTEX_INDEX_CLEAR()                \
81     /* 0x25f */                                             \
82     PICA_CMD_DATA_START_DRAW_FUNC1( true ),                 \
83     PICA_CMD_HEADER_SINGLE( PICA_REG_START_DRAW_FUNC1 )
84 
85 #if defined(NW_PLATFORM_CTR)
86 extern unsigned* __cb_current_command_buffer;
87 #endif
88 
89 namespace nw {
90 namespace font {
91 namespace {
92 
93 #if defined(NW_PLATFORM_CTR)
94 
95 const u8    MATRIX_UNIFORM_NUM      = 3;    // 行列が使用するユニフォームの数
96 const u8    COLOR_USE_COUNT         = 4;    // 文字の色1つ当たりで使用するユニフォームの数
97 
98 // コンバイナに設定するデータ数
99 const int   TEX_ENV_DATA_NUM        = PICA_REG_TEX_ENV0_SCALE - PICA_REG_TEX_ENV0 + 1;
100 
101 // コンバイナに設定するコマンドサイズ(u32単位)
102 const int   TEX_ENV_COMMAND_SIZE    = math::RoundUp(1 + TEX_ENV_DATA_NUM, 2);
103 
104 const int   TEX_ENV_OPERAND_OFFS =
105     PICA_REG_TEX_ENV0_OPERAND - PICA_REG_TEX_ENV0;
106 
107 const int   TEX_ENV_COLOR_POS =
108     1 + ( PICA_REG_TEX_ENV0_COLOR - PICA_REG_TEX_ENV0 );
109 
110 const u32   TEX_FUNC_DATA =
111     PICA_CMD_DATA_TEXTURE_FUNC(
112         PICA_DATA_TEXTURE0_SAMPLER_TYPE_TEXTURE_2D /* texture0SamplerType */,
113         0 /* texture1SamplerType */,
114         0 /* texture2SamplerType */,
115         0 /* texture3Texcoord */,
116         0 /* texture3SamplerType */,
117         0 /* texture2Texcoord */,
118         1 /* clearTextureCache */);
119 
120 const u32   TEX_ENV_SRC3 =
121     PICA_CMD_DATA_TEX_ENV_SRC(
122         PICA_DATA_TEX_ENV_SRC_RGBA_TEXTURE0,
123         PICA_DATA_TEX_ENV_SRC_RGBA_CONSTANT,
124         PICA_DATA_TEX_ENV_SRC_RGBA_CONSTANT,
125         PICA_DATA_TEX_ENV_SRC_RGBA_TEXTURE0,
126         PICA_DATA_TEX_ENV_SRC_RGBA_CONSTANT,
127         PICA_DATA_TEX_ENV_SRC_RGBA_CONSTANT );
128 
129 const u32   TEX_ENV_SRC4 =
130     PICA_CMD_DATA_TEX_ENV_SRC(
131         PICA_DATA_TEX_ENV_SRC_RGBA_TEXTURE0,
132         PICA_DATA_TEX_ENV_SRC_RGBA_CONSTANT,
133         PICA_DATA_TEX_ENV_SRC_RGBA_PREVIOUS,
134         PICA_DATA_TEX_ENV_SRC_RGBA_TEXTURE0,
135         PICA_DATA_TEX_ENV_SRC_RGBA_CONSTANT,
136         PICA_DATA_TEX_ENV_SRC_RGBA_PREVIOUS );
137 
138 const u32   TEX_ENV_OPERAND3 =
139     PICA_CMD_DATA_TEX_ENV_OPERAND(
140         PICA_DATA_OPE_RGB_SRC_COLOR,            PICA_DATA_OPE_RGB_SRC_COLOR,    PICA_DATA_OPE_RGB_SRC_COLOR,
141         PICA_DATA_OPE_ALPHA_SRC_ALPHA,          PICA_DATA_OPE_ALPHA_SRC_ALPHA,  PICA_DATA_OPE_ALPHA_SRC_ALPHA );
142 
143 const u32   TEX_ENV_OPERAND4 =
144     PICA_CMD_DATA_TEX_ENV_OPERAND(
145         PICA_DATA_OPE_RGB_ONE_MINUS_SRC_COLOR,  PICA_DATA_OPE_RGB_SRC_COLOR,    PICA_DATA_OPE_RGB_SRC_COLOR,
146         PICA_DATA_OPE_ALPHA_ONE_MINUS_SRC_ALPHA,PICA_DATA_OPE_ALPHA_SRC_ALPHA,  PICA_DATA_OPE_ALPHA_SRC_ALPHA );
147 
148 const u32   TEX_ENV_OPERAND3_ALPHA =
149     PICA_CMD_DATA_TEX_ENV_OPERAND(
150         PICA_DATA_OPE_RGB_ONE_MINUS_SRC_COLOR,  PICA_DATA_OPE_RGB_SRC_COLOR,    PICA_DATA_OPE_RGB_SRC_COLOR,
151         PICA_DATA_OPE_ALPHA_SRC_ALPHA,          PICA_DATA_OPE_ALPHA_SRC_ALPHA,  PICA_DATA_OPE_ALPHA_SRC_ALPHA );
152 
153 const u32   TEX_ENV_OPERAND4_ALPHA =
154     PICA_CMD_DATA_TEX_ENV_OPERAND(
155         PICA_DATA_OPE_RGB_SRC_COLOR,            PICA_DATA_OPE_RGB_SRC_COLOR,    PICA_DATA_OPE_RGB_SRC_COLOR,
156         PICA_DATA_OPE_ALPHA_ONE_MINUS_SRC_ALPHA,PICA_DATA_OPE_ALPHA_SRC_ALPHA,  PICA_DATA_OPE_ALPHA_SRC_ALPHA );
157 
158 const u32   TEX_ENV_COMBINE_MODULATE =
159     PICA_CMD_DATA_TEX_ENV_COMBINE(
160         PICA_DATA_TEX_ENV_COMBINE_MODULATE,
161         PICA_DATA_TEX_ENV_COMBINE_MODULATE );
162 
163 const u32   TEX_ENV_COMBINE_MULT_ADD =
164     PICA_CMD_DATA_TEX_ENV_COMBINE(
165         PICA_DATA_TEX_ENV_COMBINE_MULT_ADD_DMP,
166         PICA_DATA_TEX_ENV_COMBINE_MULT_ADD_DMP );
167 
168 const u32   TEX_ENV_CONST_COLOR_WHITE   = 0xffffffff;
169 const u32   TEX_ENV_CONST_COLOR_BLACK   = 0x00000000;
170 
171 const u32   TEX_ENV_SCALE_1 =
172     PICA_CMD_DATA_TEX_ENV_SCALE( PICA_DATA_TEX_ENV_SCALE_1, PICA_DATA_TEX_ENV_SCALE_1 );
173 
174 
175 // バーストアクセス時の最大サイズ
176 const u32   BURST_MAX = 0x80;
177 
178 const u32   DRAW_MODE0_DEFAULT  = 0;    // glDrawElementsで、かつmodeがGL_TRIANGLESの場合、1に設定し、
179                                         // それ以外の場合では0に設定
180 
181 #if defined(NW_FONT_RECTDRAWER_USE_DRAW_ARRAYS)
182 const u32   DRAW_MODE2_DEFAULT  = 0;
183 const u32   DRAW_FUNC_DEFAULT   = 0;
184 #else
185 const u32   DRAW_MODE0_ELEMENT  = 1;
186 const u32   DRAW_MODE2_ELEMENT  = PICA_DATA_DRAW_TRIANGLES;
187 #endif
188 
189 struct ShaderBinaryFileHeader
190 {
191     u8      signature[4];
192     u32     exeCount;
193     u32     exeOffsetTop;
194 };
195 
196 struct ShaderPackageHeader
197 {
198     u8      signature[4];
199     u8      version[2];
200     u16     reserved0;
201     u32     instOffset;    // プログラムコード情報オフセット
202     u32     instCount;     // プログラムコードデータ数 (*4でバイト数)
203     u32     swizzleOffset;
204     u32     swizzleCount;
205     u32     lineOffset;
206     u32     lineCount;
207     u32     stringOffset;
208     u32     stringSize;
209 };
210 
211 struct SwizzleInfo
212 {
213     u32     value;
214     u16     usedInfo;
215     u16     reserve;
216 };
217 
218 // 実行イメージ情報ヘッダー
219 struct ExeImageHeader
220 {
221     u8      signature[4];
222 
223     u8      version[2];
224     u8      shaderType;
225     u8      mergeOutputMapsDebug;
226 
227     u32     mainAddr;
228     u32     endAddr;
229 
230     u16     inputMask;
231     u16     outputMask;
232 
233     u8      geometryDataMode;
234     u8      startIndex;
235     u8      subdPatchSize;
236     u8      constVertexNumber;
237 
238     u32     setupOffset;
239     u32     setupCount;
240     u32     labelOffset;
241     u32     labelCount;
242     u32     outmapOffset;
243     u32     outmapCount;
244     u32     bsymOffset;
245     u32     bsymCount;
246     u32     stringOffset;
247     u32     stringSize;
248 };
249 
250 struct SetupInfo
251 {
252     u16     type;
253     u16     index;
254     u32     value[4];
255 };
256 
257 struct OutmapInfo
258 {
259     u16     type;
260     u16     index;
261     u16     mask;
262     u16     reserve;
263 };
264 
265 enum
266 {
267     SHADEROUTMAPTYPE_POSITION,
268     SHADEROUTMAPTYPE_QUATERNION,
269     SHADEROUTMAPTYPE_COLOR,
270     SHADEROUTMAPTYPE_TEXCOORD0,
271     SHADEROUTMAPTYPE_TEXCOORD0W,
272     SHADEROUTMAPTYPE_TEXCOORD1,
273     SHADEROUTMAPTYPE_TEXCOORD2,
274     SHADEROUTMAPTYPE_VIEW,
275 
276     SHADEROUTMAPTYPE_MAX
277 };
278 
279 const u32   CommonCommands[] =
280 {
281     // 頂点シェーダーへ、テクスチャ座標の数の設定
282     PICA_CMD_DATA_VS_INT( 0x01, 0, 0 ),
283     PICA_CMD_HEADER_SINGLE( PICA_REG_VS_INT0 ),
284 
285     // デフォルトのブレンド設定(論理演算を無効)
286     NW_FONT_COMMAND_SET_BLEND_DEFAULT,
287 
288     // アルファテストを無効
289     PICA_CMD_DATA_FRAGOP_ALPHA_TEST_DISABLE(),
290     PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_ALPHA_TEST ),
291 
292     // 最終段のテクスチャコンバイナの設定
293     PICA_CMD_DATA_TEX_ENV_SRC(
294         PICA_DATA_TEX_ENV_SRC_RGBA_PRIMARY_COLOR,
295         PICA_DATA_TEX_ENV_SRC_RGBA_PREVIOUS,
296         PICA_DATA_TEX_ENV_SRC_RGBA_PREVIOUS,
297         PICA_DATA_TEX_ENV_SRC_RGBA_PRIMARY_COLOR,
298         PICA_DATA_TEX_ENV_SRC_RGBA_PREVIOUS,
299         PICA_DATA_TEX_ENV_SRC_RGBA_PREVIOUS ),
300     PICA_CMD_HEADER_BURSTSEQ( PICA_REG_TEX_ENV5, TEX_ENV_DATA_NUM ),
301     PICA_CMD_DATA_TEX_ENV_OPERAND(
302         PICA_DATA_OPE_RGB_SRC_COLOR,   PICA_DATA_OPE_RGB_SRC_COLOR,   PICA_DATA_OPE_RGB_SRC_COLOR,
303         PICA_DATA_OPE_ALPHA_SRC_ALPHA, PICA_DATA_OPE_ALPHA_SRC_ALPHA, PICA_DATA_OPE_ALPHA_SRC_ALPHA ),
304     TEX_ENV_COMBINE_MODULATE,
305     TEX_ENV_CONST_COLOR_BLACK,
306     TEX_ENV_SCALE_1,
307 
308     // シェーダーの出力設定
309     // テクスチャ座標0のみ出力
310     PICA_CMD_DATA_VS_GS_OUT_ATTR_CLK(
311         false,  // posZ
312         false,  // col
313         true,   // tex0
314         false,  // tex1
315         false,  // tex2
316         false,  // tex0_w
317         false), // view_quart
318     PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_OUT_ATTR_CLK, 0x2 ),
319 
320     // テクスチャユニットの設定
321     // サンプラータイプ、座標選択
322     TEX_FUNC_DATA,
323     PICA_CMD_HEADER_SINGLE_BE( PICA_REG_TEXTURE_FUNC, 0xB ),
324 };
325 
326 const u32   TexEnvOperand34Commands[] =
327 {
328     //      1段目のオペランド
329     TEX_ENV_OPERAND3,
330     PICA_CMD_HEADER_SINGLE( PICA_REG_TEX_ENV3 + TEX_ENV_OPERAND_OFFS ),
331 
332     //      2段目のオペランド
333     TEX_ENV_OPERAND4,
334     PICA_CMD_HEADER_SINGLE( PICA_REG_TEX_ENV4 + TEX_ENV_OPERAND_OFFS ),
335 };
336 
337 const u32   TexEnvOperand34AlphaCommands[] =
338 {
339     //      1段目のオペランド
340     TEX_ENV_OPERAND3_ALPHA,
341     PICA_CMD_HEADER_SINGLE( PICA_REG_TEX_ENV3 + TEX_ENV_OPERAND_OFFS ),
342 
343     //      2段目のオペランド
344     TEX_ENV_OPERAND4_ALPHA,
345     PICA_CMD_HEADER_SINGLE( PICA_REG_TEX_ENV4 + TEX_ENV_OPERAND_OFFS ),
346 };
347 
348 const u32   TexEnv34Commands[] =
349 {
350     TEX_ENV_SRC3,
351     PICA_CMD_HEADER_BURSTSEQ( PICA_REG_TEX_ENV3, TEX_ENV_DATA_NUM ),
352     TEX_ENV_OPERAND3,
353     TEX_ENV_COMBINE_MODULATE,
354     TEX_ENV_CONST_COLOR_WHITE,
355     TEX_ENV_SCALE_1,
356 
357     TEX_ENV_SRC4,
358     PICA_CMD_HEADER_BURSTSEQ( PICA_REG_TEX_ENV4, TEX_ENV_DATA_NUM ),
359     TEX_ENV_OPERAND4,
360     TEX_ENV_COMBINE_MULT_ADD,
361     TEX_ENV_CONST_COLOR_BLACK,
362     TEX_ENV_SCALE_1,
363 };
364 
365 const u32   TexEnv34AlphaCommands[] =
366 {
367     TEX_ENV_SRC3,
368     PICA_CMD_HEADER_BURSTSEQ( PICA_REG_TEX_ENV3, TEX_ENV_DATA_NUM ),
369     TEX_ENV_OPERAND3_ALPHA,
370     TEX_ENV_COMBINE_MODULATE,
371     TEX_ENV_CONST_COLOR_WHITE,
372     TEX_ENV_SCALE_1,
373 
374     TEX_ENV_SRC4,
375     PICA_CMD_HEADER_BURSTSEQ( PICA_REG_TEX_ENV4, TEX_ENV_DATA_NUM ),
376     TEX_ENV_OPERAND4_ALPHA,
377     TEX_ENV_COMBINE_MULT_ADD,
378     TEX_ENV_CONST_COLOR_BLACK,
379     TEX_ENV_SCALE_1,
380 };
381 
382 const u32   s_DrawInitCommands[] =
383 {
384     // デフォルトのブレンド設定
385     NW_FONT_COMMAND_SET_BLEND_DEFAULT,
386 
387     // アルファテスト無効化
388     // 0x104
389     PICA_CMD_DATA_FRAGOP_ALPHA_TEST_DISABLE(),
390     PICA_CMD_HEADER_SINGLE( PICA_REG_FRAGOP_ALPHA_TEST ),
391 
392     // フォグの無効化
393     // 0x0e0 [2:0] [3:3] [16:16] [25:24]
394     PICA_CMD_DATA_GAS_FOG_MODE(
395         PICA_DATA_FOG_FALSE,
396         0 /* dmp_Gas.shadingDensitySrc */,
397         0 /* dmp_Fog.zFlip */ ),
398     PICA_CMD_HEADER_SINGLE_BE( PICA_REG_GAS_FOG_MODE, 0xd ),
399 
400     // フラグメントライティングの無効化
401     // 0x08f, 0x1c6
402     PICA_CMD_SET_FRAG_LIGHT_ENABLE( false ),
403 
404     // Color Buffer Read
405     // 0x112
406     0x0000000f,
407     PICA_CMD_HEADER_SINGLE( PICA_REG_COLOR_BUFFER_READ ),
408 
409     // テクスチャ LOD 無効化
410     // 0x084
411     NW_FONT_CMD_SET_TEXTURE_LOD_DISABLE( PICA_REG_TEXTURE0_LOD ),
412     // 0x094
413     NW_FONT_CMD_SET_TEXTURE_LOD_DISABLE( PICA_REG_TEXTURE1_LOD ),
414     // 0x09c
415     NW_FONT_CMD_SET_TEXTURE_LOD_DISABLE( PICA_REG_TEXTURE2_LOD ),
416 
417     // シャドウテクスチャ無効化
418     // 0x08b
419     PICA_CMD_DATA_TEXTURE_SHADOW(
420         false,  /* perspectiveShadow */
421         0,      /* shadowZBias */
422         0),     /* shadowZScale */
423     PICA_CMD_HEADER_SINGLE( PICA_REG_TEXTURE0_SHADOW ),
424 
425 #if defined(NW_FONT_RECTDRAWER_USE_DRAW_ARRAYS)
426 // glDrawArrays 用の設定
427 // 描画モード等に関して、念のためにデフォルトにしておく。
428 
429     // 頂点開始オフセット(glDrawArraysの場合引数firstの値)
430     // 0x22a
431     PICA_CMD_DATA_DRAW_VERTEX_OFFSET(0),
432     PICA_CMD_HEADER_SINGLE( PICA_REG_DRAW_VERTEX_OFFSET ),
433 
434     // 描画モード
435     // 0x229 [8:8]
436     PICA_CMD_SET_DRAW_MODE0( DRAW_MODE0_DEFAULT ),
437 
438     // 描画APIの指定、描画モード
439     // 0x253 [0:0],[8:8]
440     PICA_CMD_SET_DRAW_MODE1( DRAW_FUNC_DEFAULT, DRAW_MODE0_DEFAULT ),
441 
442     // 描画モード
443     // 0x25e [9:8]
444     PICA_CMD_SET_DRAW_MODE2( DRAW_MODE2_DEFAULT ),
445 
446     // 頂点インデックスの内部状態のクリア
447     // glDrawArrays の GL_TRIANGLES モード時で頂点が3の倍数のときは
448     // 最初の1回だけ呼び出す。
449     NW_FONT_CMD_SET_VERTEX_INDEX_CLEAR(),
450 #else
451 // glDrawElements GL_TRIANGLES 用の設定
452 
453     // 描画モード
454     // 0x229 [8:8]
455     PICA_CMD_SET_DRAW_MODE0( DRAW_MODE0_ELEMENT ),
456 
457     // 描画APIの指定、描画モード
458     // 0x253 [0:0],[8:8]
459     PICA_CMD_SET_DRAW_MODE1( DRAW_FUNC_DEFAULT, DRAW_MODE0_ELEMENT ),
460 
461     // 描画モード
462     // 0x25e [9:8]
463     PICA_CMD_SET_DRAW_MODE2( DRAW_MODE2_ELEMENT ),
464 #endif
465 
466     // 0x111, 0x110
467     PICA_CMD_SET_COLOR_DEPTH_BUFFER_CLEAR( 1 /* data1 */, 1 /* data2 */ ),
468 };
469 
470 const u32   s_DrawFinalizeCommands[] =
471 {
472     // 0x232-0x235  固定頂点属性値
473     PICA_CMD_SET_VS_FIXED_ATTR(
474         0x0,            /* order */
475         0x3f000000,     /* c0 */
476         0x00000000,     /* c1 */
477         0x00000000),    /* c2 */
478 
479 #if ! defined(NW_FONT_RECTDRAWER_USE_DRAW_ARRAYS)
480 // 描画モード等に関して、デフォルトに戻しておく。
481     // 描画モード
482     // 0x229 [8:8]
483     PICA_CMD_SET_DRAW_MODE0( DRAW_MODE0_DEFAULT ),
484 
485     // 描画モード
486     // 0x253 [8:8]
487     NW_FONT_CMD_SET_DRAW_MODE1( DRAW_MODE0_DEFAULT ),
488 
489     // 描画モード
490     // 0x25e [9:8]
491     PICA_CMD_SET_DRAW_MODE2( DRAW_MODE2_DEFAULT ),
492 #endif
493 
494     // 0x111, 0x110
495     PICA_CMD_SET_COLOR_DEPTH_BUFFER_CLEAR( 1 /* data1 */, 1 /* data2 */ ),
496 };
497 
498 const u32   DrawCommands[] =
499 {
500 #if !defined(NW_FONT_RECTDRAWER_USE_DRAW_ARRAYS)
501     // 頂点インデックスの内部状態のクリア
502     // glDrawElements の GL_TRIANGLES モード時は必要
503     NW_FONT_CMD_SET_VERTEX_INDEX_CLEAR(),
504 #endif
505 
506 #if defined(NW_FONT_RECTDRAWER_USE_DRAW_ARRAYS)
507     NW_FONT_CMD_SET_DRAW_FUNC( 1 /* func */ ),
508 
509     PICA_CMD_SET_START_DRAW_ARRAY( 0x00000001 /* start */ ),
510 
511     NW_FONT_CMD_SET_DRAW_FUNC( 0 /* func */ ),
512 #else
513     PICA_CMD_SET_START_DRAW_ELEMENT( 0x00000001 /* start */ ),
514 #endif
515 
516     // カラー・デプスバッファのキャッシュフラッシュ
517     // 0x111
518     PICA_CMD_DATA_COLOR_DEPTH_BUFFER_CLEAR( 1 /* data */ ),
519     PICA_CMD_HEADER_SINGLE( PICA_REG_COLOR_DEPTH_BUFFER_CLEAR1 ),
520 };
521 
522 const u32   DRAWBEGIN_STATICCOMMAND_BYTES   =
523     656 + sizeof(s_DrawInitCommands)
524 #if !defined(NW_FONT_RECTDRAWER_USE_DRAW_ARRAYS)
525     + sizeof(u32) * 2 * 1
526 #endif
527     ;
528 
529 const u32   DRAWEND_STATICCOMMAND_BYTES     = 176 + sizeof(s_DrawFinalizeCommands);
530 
531 #endif
532 
533 u32
GetColorU32Raw(ut::Color8 color)534 GetColorU32Raw(ut::Color8 color)
535 {
536     return *reinterpret_cast<const u32*>(&color);
537 }
538 
539 void
NormalizeF32Colors(math::VEC4 * __restrict dst,const ut::Color8 * __restrict src)540 NormalizeF32Colors(
541     math::VEC4* __restrict          dst,
542     const ut::Color8* __restrict    src
543 )
544 {
545     register const f32 d = 1.f / 255.f;
546     register f32 colors[4];
547 
548     for (int i = 0; i < internal::TEXTCOLOR_MAX; ++i)
549     {
550         colors[0] = src[i].r * d;
551         colors[1] = src[i].g * d;
552         colors[2] = src[i].b * d;
553         colors[3] = src[i].a * d;
554 
555         dst[i].x = colors[0];
556         dst[i].y = colors[1];
557         dst[i].z = colors[2];
558         dst[i].w = colors[3];
559     }
560 }
561 
562 void
SetVertexColor(math::VEC4 * __restrict dst,const ut::Color8 * __restrict src,int mode)563 SetVertexColor(
564     math::VEC4* __restrict          dst,
565     const ut::Color8* __restrict    src,
566     int                             mode
567 )
568 {
569     math::VEC4 wkCols[internal::TEXTCOLOR_MAX];
570     NormalizeF32Colors(wkCols, src);
571     dst[VERTEX_LT] = wkCols[internal::TEXTCOLOR_START];
572     dst[VERTEX_RT] = wkCols[
573         mode != CharWriter::GRADMODE_H ? internal::TEXTCOLOR_START: internal::TEXTCOLOR_END];
574     dst[VERTEX_LB] = wkCols[
575         mode != CharWriter::GRADMODE_V ? internal::TEXTCOLOR_START: internal::TEXTCOLOR_END];
576     dst[VERTEX_RB] = wkCols[
577         mode == CharWriter::GRADMODE_NONE ? internal::TEXTCOLOR_START: internal::TEXTCOLOR_END];
578 }
579 
580 inline
581 bool
IsDrawChar(const u8 * drawFlags,int index)582 IsDrawChar(
583     const u8*   drawFlags,
584     int         index
585 )
586 {
587     return 0 != ut::internal::ReadBits(drawFlags[index / 8], 1, index % 8);
588 }
589 
590 inline
591 void
SetDrawChar(u8 * drawFlags,int index)592 SetDrawChar(
593     u8*         drawFlags,
594     int         index
595 )
596 {
597     drawFlags[index / 8] = ut::internal::WriteBits(drawFlags[index / 8], 1, 1, index % 8);
598 }
599 
600 #if defined(NW_PLATFORM_CTR)
601 const ShaderBinaryFileHeader&
GetShaderBinaryFileHeader(const void * shaderBinary)602 GetShaderBinaryFileHeader(const void* shaderBinary)
603 {
604     return *static_cast<const ShaderBinaryFileHeader*>(shaderBinary);
605 }
606 void
EnsureShaderBinaryFileHeader(const void * shaderBinary)607 EnsureShaderBinaryFileHeader(const void* shaderBinary)
608 {
609     const ShaderBinaryFileHeader& header =
610         *static_cast<const ShaderBinaryFileHeader*>(shaderBinary);
611     NN_ASSERT(  header.signature[0] == 'D' && header.signature[1] == 'V'
612              && header.signature[2] == 'L' && header.signature[3] == 'B' );
613 }
614 
615 const ShaderPackageHeader&
GetShaderPackageHeader(const void * shaderBinary)616 GetShaderPackageHeader(const void* shaderBinary)
617 {
618     const ShaderBinaryFileHeader& fileHead = GetShaderBinaryFileHeader(shaderBinary);
619     return *static_cast<const ShaderPackageHeader*>(
620             ut::AddOffsetToPtr(
621                 shaderBinary,
622                 sizeof(fileHead) + (fileHead.exeCount - 1) * sizeof(u32) ) );
623 }
624 
625 void
EnsureShaderPackageHeader(const ShaderPackageHeader & header)626 EnsureShaderPackageHeader(const ShaderPackageHeader& header)
627 {
628     (void)header;
629     NN_ASSERT(  header.signature[0] == 'D' && header.signature[1] == 'V'
630              && header.signature[2] == 'L' && header.signature[3] == 'P' );
631 }
632 
633 const ExeImageHeader*
GetExeImageHeader(const void * shaderBinary)634 GetExeImageHeader(const void* shaderBinary)
635 {
636     const ShaderBinaryFileHeader& fileHead = GetShaderBinaryFileHeader(shaderBinary);
637     return static_cast<const ExeImageHeader*>(
638             ut::AddOffsetToPtr(
639                 shaderBinary,
640                 fileHead.exeOffsetTop ) );
641 }
642 
643 void
EnsureExeImageHeader(const ExeImageHeader & header)644 EnsureExeImageHeader(const ExeImageHeader& header)
645 {
646     (void)header;
647     NN_ASSERT(  header.signature[0] == 'D' && header.signature[1] == 'V'
648              && header.signature[2] == 'L' && header.signature[3] == 'E' );
649 }
650 
651 u32
CalcInstCommandCount(u32 count)652 CalcInstCommandCount(u32 count)
653 {
654     u32 size = (count / BURST_MAX) * math::RoundUp(2 + 1 + BURST_MAX, 2);
655     if (0 != count % BURST_MAX)
656     {
657         size += math::RoundUp(2 + 1 + (count % BURST_MAX), 2);
658     }
659     return size;
660 }
661 
662 u32
CalcDrawBeginCommandBytes(const ShaderPackageHeader & header)663 CalcDrawBeginCommandBytes(const ShaderPackageHeader& header)
664 {
665     const u32 instBytes =
666           sizeof(u32)
667         * ( CalcInstCommandCount(header.instCount) + CalcInstCommandCount(header.swizzleCount) );
668     // NN_LOG("inst swizzle bytes %d\n", instBytes);
669     return DRAWBEGIN_STATICCOMMAND_BYTES + instBytes;
670 }
671 
672 // 頂点属性配列のコマンドを追加
673 void
AddVertexAttributeArrayCommand(ut::internal::CmdCache & cmdCache,u32 vboBaseAddr,uptr phyArrayBuffer,u32 vtxAttrNum)674 AddVertexAttributeArrayCommand(
675     ut::internal::CmdCache& cmdCache,
676     u32                     vboBaseAddr,
677     uptr                    phyArrayBuffer,
678     u32                     vtxAttrNum
679 )
680 {
681     const u32 fixedVtxAttrMask = 0;
682     const u32 loadAryBytes = 16;        // ロードアレイの1頂点辺りのバイト数
683     const u32 loadAryElementNum = 1;
684 
685     const u32 command200[] =
686     {
687         // 0x200  ベースアドレス
688         PICA_CMD_DATA_VERTEX_ATTR_ARRAYS_BASE_ADDR( vboBaseAddr ),
689         PICA_CMD_HEADER_BURSTSEQ( PICA_REG_VTX_ATTR_ARRAYS_BASE_ADDR, (0x202 - 0x200 + 1) + (0x205 - 0x203 + 1) * 12 ),
690 
691         // 0x201 内部頂点属性0-7の型
692         PICA_CMD_DATA_VERTEX_ATTR_ARRAYS(
693             PICA_DATA_SIZE_4_FLOAT, PICA_DATA_SIZE_1_BYTE, PICA_DATA_SIZE_1_BYTE,
694             PICA_DATA_SIZE_1_BYTE,  PICA_DATA_SIZE_1_BYTE, PICA_DATA_SIZE_1_BYTE,
695             PICA_DATA_SIZE_1_BYTE,  PICA_DATA_SIZE_1_BYTE),
696 
697         // 0x202 内部頂点属性8-11の型、固定頂点属性マスク、頂点属性数
698         PICA_DATA_SIZE_1_BYTE <<  0 | PICA_DATA_SIZE_1_BYTE <<  4
699             | PICA_DATA_SIZE_1_BYTE <<  8 | PICA_DATA_SIZE_1_BYTE << 12
700             | fixedVtxAttrMask << 16
701             | (vtxAttrNum - 1) << 28,
702 
703         // 0x203-0x205 ロードアレイ0アドレスオフセット、1-12の要素、バイト数、要素数
704         NW_FONT_CMD_SET_LOAD_ARRAY(
705             phyArrayBuffer - vboBaseAddr,
706             PICA_DATA_VERTEX_0_ATTR,
707             PICA_DATA_VERTEX_0_ATTR,
708             PICA_DATA_VERTEX_0_ATTR,
709             PICA_DATA_VERTEX_0_ATTR,
710             PICA_DATA_VERTEX_0_ATTR,
711             PICA_DATA_VERTEX_0_ATTR,
712             PICA_DATA_VERTEX_0_ATTR,
713             PICA_DATA_VERTEX_0_ATTR,
714             PICA_DATA_VERTEX_0_ATTR,
715             PICA_DATA_VERTEX_0_ATTR,
716             PICA_DATA_VERTEX_0_ATTR,
717             PICA_DATA_VERTEX_0_ATTR,
718             loadAryBytes,
719             loadAryElementNum),
720     };
721     cmdCache.Add(command200, sizeof(command200));
722 
723     static const u32 command206[] =
724     {
725         // 0x206-0x226 ロードアレイ1-11
726         NW_FONT_CMD_SET_LOAD_ARRAY_ZERO(),  // ロードアレイ1
727         NW_FONT_CMD_SET_LOAD_ARRAY_ZERO(),  // ロードアレイ2
728         NW_FONT_CMD_SET_LOAD_ARRAY_ZERO(),  // ロードアレイ3
729         NW_FONT_CMD_SET_LOAD_ARRAY_ZERO(),  // ロードアレイ4
730         NW_FONT_CMD_SET_LOAD_ARRAY_ZERO(),  // ロードアレイ5
731         NW_FONT_CMD_SET_LOAD_ARRAY_ZERO(),  // ロードアレイ6
732         NW_FONT_CMD_SET_LOAD_ARRAY_ZERO(),  // ロードアレイ7
733         NW_FONT_CMD_SET_LOAD_ARRAY_ZERO(),  // ロードアレイ8
734         NW_FONT_CMD_SET_LOAD_ARRAY_ZERO(),  // ロードアレイ9
735         NW_FONT_CMD_SET_LOAD_ARRAY_ZERO(),  // ロードアレイ10
736         NW_FONT_CMD_SET_LOAD_ARRAY_ZERO(),  // ロードアレイ11
737 
738         // 0x2bb  頂点属性の入力レジスタマップ設定レジスタ 1-8
739         PICA_CMD_DATA_VS_ATTR_IN_REG_MAP0( 0, 0, 0, 0, 0, 0, 0, 0 ),
740         PICA_CMD_HEADER_SINGLE( PICA_REG_VS_ATTR_IN_REG_MAP0 ),
741 
742         // 0x2bc  頂点属性の入力レジスタマップ設定レジスタ 9-12
743         PICA_CMD_DATA_VS_ATTR_IN_REG_MAP1( 0, 0, 0, 0 ),
744         PICA_CMD_HEADER_SINGLE( PICA_REG_VS_ATTR_IN_REG_MAP1 ),
745     };
746     cmdCache.Add(command206, sizeof(command206));
747 }
748 #endif  // #if defined(NW_PLATFORM_CTR)
749 
750 }   // namespace
751 
752 bool        RectDrawer::s_StaticInitialized     = false;
753 
754 RectDrawer::VertexBuffer
755             RectDrawer::s_VertexBuffer;
756 
757 void*
GetVertexBufferData()758 RectDrawer::GetVertexBufferData()
759 {
760     if (! s_StaticInitialized)
761     {
762         InitializeStatic();
763 
764         s_StaticInitialized = true;
765     }
766 
767     return &s_VertexBuffer;
768 }
769 
770 u32
GetCommandBufferSize(const void * shaderBinary,u32)771 RectDrawer::GetCommandBufferSize(
772     const void* shaderBinary,
773     u32         /* size */
774 )
775 {
776 #if defined(NW_PLATFORM_CTR)
777     const ShaderPackageHeader& header = GetShaderPackageHeader(shaderBinary);
778 
779     return  CalcDrawBeginCommandBytes(header)
780         +   DRAWEND_STATICCOMMAND_BYTES;
781 #else
782     NN_ASSERT(false);
783     return 0;
784 #endif
785 }
786 
787 u32
GetVertexBufferCommandBufferSize(const void * shaderBinary,u32 size)788 RectDrawer::GetVertexBufferCommandBufferSize(
789     const void* shaderBinary,
790     u32         size
791 )
792 {
793     return  GetVertexBufferSize()
794         +   GetCommandBufferSize(shaderBinary, size);
795 }
796 
RectDrawer()797 RectDrawer::RectDrawer()
798 :   m_UniformAddrIndex(0),
799     m_UniformMtxIndex(0),
800     m_UniformDataIndex(0),
801     m_UniformTextColorIndex(0),
802     m_UniformAddr(reinterpret_cast<UniformAddress*>(&m_UniformAddrBuffer[3])),
803     m_UniformMtx(reinterpret_cast<math::VEC4*>(&m_UniformMtxBuffer[3])),
804     m_UniformData(reinterpret_cast<math::VEC4*>(&m_UniformDataBuffer[3])),
805     m_UniformTextColor(reinterpret_cast<math::VEC4*>(&m_UniformTextColorBuffer[3])),
806     m_CommandBuffer(NULL),
807     m_VertexBufferArray(NULL),
808 #if defined(NW_FONT_RECTDRAWER_USE_DRAW_ARRAYS)
809     m_VertexBufferBaseAddr(0),
810 #endif
811     m_IsColorDirty(false)
812 {
813 }
814 
~RectDrawer()815 RectDrawer::~RectDrawer()
816 {
817     this->Finalize();
818 }
819 
820 void
Initialize(void * vtxBufCmdBuf,const void * shaderBinary,u32 size)821 RectDrawer::Initialize(
822     void*       vtxBufCmdBuf,
823     const void* shaderBinary,
824     u32         size
825 )
826 {
827     const u32 cmdBufSize = GetCommandBufferSize(shaderBinary, size);
828 
829     void *const vertexBuffer = ut::AddOffsetToPtr(vtxBufCmdBuf, cmdBufSize);
830 
831     InitializeCMD(vertexBuffer, vtxBufCmdBuf, shaderBinary, size, true);
832 }
833 
834 void
Initialize(void * vertexBuffer,void * commandBuffer,const void * shaderBinary,u32 size)835 RectDrawer::Initialize(
836     void*       vertexBuffer,
837     void*       commandBuffer,
838     const void* shaderBinary,
839     u32         size
840 )
841 {
842     InitializeCMD(vertexBuffer, commandBuffer, shaderBinary, size, false);
843 }
844 
845 void
Finalize()846 RectDrawer::Finalize()
847 {
848     m_CommandBuffer = NULL;
849     m_VertexBufferArray = NULL;
850 }
851 
852 void
DrawBegin(u32 flag)853 RectDrawer::DrawBegin(u32 flag)
854 {
855     NN_ASSERT(  m_UniformAddrIndex      == 0
856             &&  m_UniformDataIndex      == 0
857             &&  m_UniformMtxIndex       == 0
858             &&  m_UniformTextColorIndex == 0 );
859 
860     if (0 == (flag & DONT_USE_SETUP_COMMAND))
861     {
862         UseBeginCommand();
863     }
864 }
865 
866 void
DrawEnd(u32 flag)867 RectDrawer::DrawEnd(u32 flag)
868 {
869     if (0 == (flag & DONT_USE_SETUP_COMMAND))
870     {
871         UseEndCommand();
872     }
873 }
874 
875 void
SetProjectionMtx(const nn::math::MTX44 & mtx)876 RectDrawer::SetProjectionMtx(const nn::math::MTX44& mtx)
877 {
878 #if defined(NW_PLATFORM_CTR)
879     nn::math::MTX44 *const pDst = reinterpret_cast<nn::math::MTX44*>(&m_UniformProjBuffer[3]);
880     nn::math::MTX44Copy(pDst, &mtx);
881 
882     const u32 size = SetUniformCommand(m_UniformProjBuffer, UNIFORM_PROJ_NUM + 1);
883     NW_FONT_RECTDRAWER_ADD_COMMAND(m_UniformProjBuffer, size);
884 #else
885     NN_ASSERT(false);
886 #endif
887 }
888 
889 void
SetViewMtxForText(const nn::math::MTX34 & mtx)890 RectDrawer::SetViewMtxForText(const nn::math::MTX34& mtx)
891 {
892 #if defined(NW_PLATFORM_CTR)
893     nn::math::MTX34 *const pDst = reinterpret_cast<nn::math::MTX34*>(&m_UniformMtxBuffer[3]);
894     nn::math::MTX34Copy(pDst, &mtx);
895 
896     m_UniformMtxIndex = sizeof(mtx) / sizeof(nn::math::VEC4);
897     const u32 size = SetUniformCommand(m_UniformMtxBuffer, m_UniformMtxIndex);
898     NW_FONT_RECTDRAWER_ADD_COMMAND(m_UniformMtxBuffer, size);
899     m_UniformMtxIndex = 0;
900 #else
901     NN_ASSERT(false);
902 #endif
903 }
904 
905 void
UseBeginCommand()906 RectDrawer::UseBeginCommand()
907 {
908     DisableTextures();
909 
910     m_CmdCacheDrawBegin.Use();
911 }
912 
913 void
UseEndCommand()914 RectDrawer::UseEndCommand()
915 {
916     m_CmdCacheDrawEnd.Use();
917 }
918 
919 void
DisableTextures()920 RectDrawer::DisableTextures()
921 {
922 #if defined(NW_PLATFORM_CTR)
923     // 0x06f
924     NW_FONT_RECTDRAWER_ADD_SINGLE_COMMAND(
925         PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_OUT_ATTR_CLK, 0x2 ),
926         0 );
927 
928     // 0x080
929     // サンプラータイプ、座標選択
930     NW_FONT_RECTDRAWER_ADD_SINGLE_COMMAND(
931         PICA_CMD_HEADER_SINGLE_BE( PICA_REG_TEXTURE_FUNC, 0xB ),
932         PICA_CMD_DATA_TEXTURE_FUNC(
933             PICA_DATA_TEXTURE0_SAMPLER_TYPE_TEXTURE_FALSE /* texture0SamplerType */,
934             0 /* texture1SamplerType */,
935             0 /* texture2SamplerType */,
936             0 /* texture3Texcoord */,
937             0 /* texture3SamplerType */,
938             0 /* texture2Texcoord */,
939             0 /* clearTextureCache */));
940 #else
941     NN_ASSERT(false);
942 #endif
943 }
944 
945 void
AddUniformMtx()946 RectDrawer::AddUniformMtx()
947 {
948 #if defined(NW_PLATFORM_CTR)
949     const u32 size = SetUniformCommand(m_UniformMtxBuffer, m_UniformMtxIndex);
950     NW_FONT_RECTDRAWER_ADD_COMMAND(m_UniformMtxBuffer, size);
951 #else
952     NN_ASSERT(false);
953 #endif
954 
955     m_UniformMtxIndex = 0;
956 }
957 
958 void
SetParallax(f32 parallax,f32 dLevel,f32 addDist)959 RectDrawer::SetParallax(
960     f32     parallax,
961     f32     dLevel,
962     f32     addDist
963 )
964 {
965 #if defined(NW_PLATFORM_CTR)
966     nn::math::VEC4 *const pParallaxData =
967         reinterpret_cast<nn::math::VEC4*>(&m_UniformProjBuffer[3 + 4 * 4]);
968     pParallaxData->Set(parallax, dLevel, addDist, 0.0f);
969 #else
970     NN_ASSERT(false);
971 #endif
972 }
973 
974 void
InitializeStatic()975 RectDrawer::InitializeStatic()
976 {
977     static const int vtx[DRAW_VTX_NUM] =
978     {
979         VERTEX_RT, VERTEX_LT, VERTEX_RB,
980         VERTEX_RB, VERTEX_LT, VERTEX_LB,
981     };
982 
983 #if defined(NW_PLATFORM_CTR)
984 #if defined(NW_FONT_RECTDRAWER_USE_DRAW_ARRAYS)
985     for (int addr = 0; addr < UNIFORM_ADDR_NUM; ++addr)
986     {
987         for (int vi = 0; vi < DRAW_VTX_NUM; ++vi)
988         {
989             s_VertexBuffer.position[addr][vi][0] = addr;
990             s_VertexBuffer.position[addr][vi][1] = vtx[vi];
991             s_VertexBuffer.position[addr][vi][2] = vtx[vi] % 2 ?  1.f : 0.f; // 右左
992             s_VertexBuffer.position[addr][vi][3] = vtx[vi] / 2 ? -1.f : 0.f; // 下上
993         }
994     }
995 #else
996     for (int addr = 0; addr < UNIFORM_ADDR_NUM; ++addr)
997     {
998         for (int vi = 0; vi < DRAW_VTX_NUM; ++vi)
999         {
1000             s_VertexBuffer.indexes[addr][vi] = addr * VERTEX_MAX + vtx[vi];
1001         }
1002     }
1003 
1004     for (int addr = 0; addr < UNIFORM_ADDR_NUM; ++addr)
1005     {
1006         for (int vi = 0; vi < VERTEX_MAX; ++vi)
1007         {
1008             s_VertexBuffer.position[addr][vi][0] = addr;
1009             s_VertexBuffer.position[addr][vi][1] = vi;
1010             s_VertexBuffer.position[addr][vi][2] = vi % 2 ?  1.f : 0.f; // 右左
1011             s_VertexBuffer.position[addr][vi][3] = vi / 2 ? -1.f : 0.f; // 下上
1012         }
1013     }
1014 #endif
1015 #else
1016     NN_ASSERT(false);
1017 #endif
1018 }
1019 
1020 void
InitializeCMD(void * vertexBuffer,void * commandBuffer,const void * shaderBinary,u32,bool initVertexBuffer)1021 RectDrawer::InitializeCMD(
1022     void*       vertexBuffer,
1023     void*       commandBuffer,
1024     const void* shaderBinary,
1025     u32         /* size */,
1026     bool        initVertexBuffer
1027 )
1028 {
1029     NN_NULL_ASSERT(vertexBuffer);
1030 
1031 #if defined(NW_PLATFORM_CTR)
1032     EnsureShaderBinaryFileHeader(shaderBinary);
1033 
1034     const ShaderBinaryFileHeader& fileHead = GetShaderBinaryFileHeader(shaderBinary);
1035 
1036     NN_ASSERT(fileHead.exeCount == 1);  // 実行イメージが1つのときのみ対応
1037 
1038     const ShaderPackageHeader& pkgHead = GetShaderPackageHeader(shaderBinary);
1039 
1040     EnsureShaderPackageHeader(pkgHead);
1041 
1042     const ExeImageHeader& exeHead = GetExeImageHeader(shaderBinary)[0];
1043 
1044     EnsureExeImageHeader(exeHead);
1045 
1046     NN_ASSERT(exeHead.shaderType == 0); // 頂点シェーダのみ対応
1047 
1048     m_VertexBufferArray = vertexBuffer;
1049     if (initVertexBuffer)
1050     {
1051         std::memcpy(vertexBuffer, GetVertexBufferData(), GetVertexBufferSize());
1052         nngxUpdateBuffer(vertexBuffer, GetVertexBufferSize());
1053     }
1054 
1055     m_CommandBuffer = commandBuffer;
1056     const u32 DrawBeginCommandBytes = CalcDrawBeginCommandBytes(pkgHead);
1057     m_CmdCacheDrawBegin.Init(m_CommandBuffer, DrawBeginCommandBytes);
1058     m_CmdCacheDrawEnd.Init(
1059         ut::AddOffsetToPtr(m_CommandBuffer, DrawBeginCommandBytes),
1060         DRAWEND_STATICCOMMAND_BYTES);
1061 
1062     const u32 vtxAttrNum = 1;           // 頂点属性数
1063 
1064     // ジオメトリシェーダを使用するかどうか
1065     const bool useGeometryShader = false;
1066 
1067     // 予約ジオメトリシェーダのサブディビジョンを使用するかどうか
1068     const bool useGeometryShaderSubdivision = false;
1069 
1070     // DrawBegin() のコマンドキャッシュ生成
1071     {
1072         static const u32 commands[] =
1073         {
1074             PICA_CMD_SET_DRAW_MODE0_DUMMY_BEGIN(),
1075 
1076             // 0x229 [1:0] ジオメトリシェーダを使用しない
1077             PICA_CMD_DATA_DRAW_MODE0(
1078                 useGeometryShader,
1079                 0                   /* drawMode */,
1080                 false),             /* useGeometryShaderSubdivision */
1081             PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE0, 0x1 ),
1082 
1083             PICA_CMD_SET_DRAW_MODE0_DUMMY_END(),
1084 
1085             // 0x244 [0:0] 共用プロセッサへのコピー
1086             PICA_CMD_SET_VS_COM_MODE( useGeometryShader ),
1087         };
1088         m_CmdCacheDrawBegin.Add(commands, sizeof(commands));
1089     }
1090 
1091     {   // 頂点シェーダプログラムコード
1092         const u32* progCodes =
1093             static_cast<const u32*>(ut::AddOffsetToPtr(&pkgHead, pkgHead.instOffset));
1094 
1095         for (u32 totalCnt = 0; totalCnt < pkgHead.instCount; )
1096         {
1097             const u32 writeCnt = math::Min(BURST_MAX, pkgHead.instCount - totalCnt);
1098             const u32 commands[] =
1099             {
1100                 // 0x2cb  プログラムコードのロードアドレス
1101                 PICA_CMD_DATA_VS_PROG_ADDR( totalCnt ),
1102                 PICA_CMD_HEADER_SINGLE( PICA_REG_VS_PROG_ADDR ),
1103 
1104                 // 0x2cc  プログラムコードのデータ
1105                 progCodes[totalCnt + 0],
1106                 PICA_CMD_HEADER_BURST( PICA_REG_VS_PROG_DATA0, writeCnt ),
1107             };
1108             m_CmdCacheDrawBegin.Add(commands, sizeof(commands));
1109             m_CmdCacheDrawBegin.Add(&progCodes[totalCnt + 1], sizeof(u32) * (writeCnt - 1));
1110             m_CmdCacheDrawBegin.RoundUp(8);
1111             totalCnt += writeCnt;
1112         }
1113 
1114         {
1115             static const u32 commands[] =
1116             {
1117                 // 0x2bf  プログラム更新完了の通知
1118                 PICA_CMD_DATA_VS_PROG_END( 1 ),
1119                 PICA_CMD_HEADER_SINGLE( PICA_REG_VS_PROG_RENEWAL_END ),
1120             };
1121             m_CmdCacheDrawBegin.Add(commands, sizeof(commands));
1122         }
1123     }
1124 
1125     {   // 頂点シェーダSwizzleパターン
1126         const SwizzleInfo *const swDatas =
1127             static_cast<const SwizzleInfo*>(ut::AddOffsetToPtr(&pkgHead, pkgHead.swizzleOffset));
1128 
1129         for (u32 totalCnt = 0; totalCnt < pkgHead.swizzleCount; )
1130         {
1131             const u32 writeCnt = math::Min(BURST_MAX, pkgHead.swizzleCount - totalCnt);
1132             const u32 commands[] =
1133             {
1134                 // 0x2d5  Swizzleパターンのロードアドレス
1135                 PICA_CMD_DATA_VS_PROG_SWIZZLE_ADDR( totalCnt ),
1136                 PICA_CMD_HEADER_SINGLE( PICA_REG_VS_PROG_SWIZZLE_ADDR ),
1137 
1138                 // 0x2d6  Swizzleパターンデータ
1139                 swDatas[totalCnt + 0].value,
1140                 PICA_CMD_HEADER_BURST( PICA_REG_VS_PROG_SWIZZLE_DATA0, writeCnt ),
1141             };
1142             m_CmdCacheDrawBegin.Add(commands, sizeof(commands));
1143 
1144             for (int i = 1; i < writeCnt; ++i)
1145             {
1146                 m_CmdCacheDrawBegin.Add(&swDatas[totalCnt + i].value, sizeof(u32));
1147             }
1148 
1149             m_CmdCacheDrawBegin.RoundUp(8);
1150             totalCnt += writeCnt;
1151         }
1152     }
1153 
1154     {   // 浮動小数点定数レジスタ
1155         const SetupInfo* setupInfos =
1156             static_cast<const SetupInfo*>(
1157                 ut::AddOffsetToPtr(
1158                     &exeHead,
1159                     exeHead.setupOffset ) );
1160 
1161         for (int i = 0; i < exeHead.setupCount; ++i)
1162         {
1163             const SetupInfo& setupInfo = setupInfos[i];
1164 
1165             // 浮動小数点の場合のみ実装
1166             NN_ASSERT(setupInfo.type == 2);
1167 
1168             const int dataNum = 3;  // 24bit * 4成分
1169             const int writeCount = 1 + dataNum; // 書き込み数(アドレスとデータ分)
1170             const u32 commands[] =
1171             {
1172                 // 0x2c0
1173                 PICA_CMD_DATA_VS_FLOAT_ADDR( PICA_DATA_VS_F24, setupInfo.index ),
1174                 PICA_CMD_HEADER_BURSTSEQ( PICA_REG_VS_FLOAT_ADDR, writeCount ),
1175 
1176                 setupInfo.value[3] <<  8 | ((setupInfo.value[2] >> 16) & 0x0000FF),
1177                 setupInfo.value[2] << 16 | ((setupInfo.value[1] >>  8) & 0x00FFFF),
1178                 setupInfo.value[1] << 24 | ((setupInfo.value[0] >>  0) & 0xFFFFFF),
1179                 0,  // アライメント調整
1180             };
1181             m_CmdCacheDrawBegin.Add(commands, sizeof(commands));
1182         }
1183     }
1184 
1185     const uptr phyArrayBuffer = nngxGetPhysicalAddr(reinterpret_cast<uptr>(m_VertexBufferArray));
1186 
1187     // 頂点配列のベースアドレス
1188     // 全ての頂点アレイとインデックスアレイのアドレスよりも小さい16バイトアラインの値を設定します。
1189     const u32 vboBaseAddr = math::RoundDown(phyArrayBuffer, 16);
1190 
1191     AddVertexAttributeArrayCommand(m_CmdCacheDrawBegin, vboBaseAddr, phyArrayBuffer, vtxAttrNum);
1192 
1193     {
1194         const u32 commands[] =
1195         {
1196             // 0x229 [31:31]
1197             PICA_CMD_DATA_DRAW_MODE0(
1198                 false,                          /* useGeometryShader */
1199                 0,                              /* drawMode */
1200                 useGeometryShaderSubdivision),
1201             PICA_CMD_HEADER_SINGLE_BE( PICA_REG_DRAW_MODE0, 0x8 ),
1202 
1203             // 0x2b9  頂点シェーダに入力する頂点属性数
1204             PICA_CMD_DATA_VS_ATTR_NUM0( vtxAttrNum ),
1205             PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_ATTR_NUM0, 0xb ),
1206 
1207             // 0x2ba  頂点シェーダ開始アドレス
1208             PICA_CMD_DATA_VS_START_ADDR( exeHead.mainAddr ),
1209             PICA_CMD_HEADER_SINGLE( PICA_REG_VS_START_ADDR ),
1210         };
1211         m_CmdCacheDrawBegin.Add(commands, sizeof(commands));
1212     }
1213 
1214     {
1215         const u32 OutRegNum = 7;
1216         const int CompNum = 4;
1217         static const u8 outAttrs[SHADEROUTMAPTYPE_MAX] =
1218         {
1219             PICA_DATA_VS_OUT_ATTR_X,
1220             PICA_DATA_VS_OUT_ATTR_QUART_X,
1221             PICA_DATA_VS_OUT_ATTR_R,
1222             PICA_DATA_VS_OUT_ATTR_TEX0_U,
1223             PICA_DATA_VS_OUT_ATTR_TEX0_W,
1224             PICA_DATA_VS_OUT_ATTR_TEX1_U,
1225             PICA_DATA_VS_OUT_ATTR_TEX2_U,
1226             PICA_DATA_VS_OUT_ATTR_VIEW_X
1227         };
1228         u8 outmaps[OutRegNum][CompNum];
1229         bool useRegs[OutRegNum];
1230         u8 useOutRegTypes[SHADEROUTMAPTYPE_MAX];
1231 
1232         for (u32 i = 0; i < SHADEROUTMAPTYPE_MAX; ++i)
1233         {
1234             useOutRegTypes[i] = 0;
1235         }
1236 
1237         for (u32 j = 0; j < OutRegNum; ++j)
1238         {
1239             useRegs[j] = false;
1240             for (int i = 0; i < CompNum; ++i)
1241             {
1242                 outmaps[j][i] = PICA_DATA_VS_OUT_ATTR_INVALID;
1243             }
1244         }
1245 
1246         const OutmapInfo *const outmapInfos =
1247             static_cast<const OutmapInfo*>(
1248                 ut::AddOffsetToPtr(
1249                     &exeHead,
1250                     exeHead.outmapOffset ) );
1251         for (int j = 0; j < math::Min(exeHead.outmapCount, OutRegNum); ++j)
1252         {
1253             if (outmapInfos[j].type == 9)   // generic
1254             {
1255                 continue;
1256             }
1257 
1258             useRegs[outmapInfos[j].index] = true;
1259             u8* outmap = outmaps[outmapInfos[j].index];
1260             useOutRegTypes[outmapInfos[j].type] = static_cast<u8>(outmapInfos[j].mask);
1261             u8 ci = outAttrs[outmapInfos[j].type];
1262             for (int i = 0; i < CompNum; ++i)
1263             {
1264                 if (0 != (outmapInfos[j].mask & (1 << i)))
1265                 {
1266                     outmap[i] = ci;
1267                     ++ci;
1268                 }
1269             }
1270         }
1271 
1272         int outRegUseNum = 0;
1273         for (int j = 0; j < OutRegNum; ++j)
1274         {
1275             if (useRegs[j])
1276             {
1277                 ++outRegUseNum;
1278             }
1279         }
1280 
1281         {
1282             const u32 commands[] =
1283             {
1284                 // 0x2bd  頂点シェーダ出力レジスタのマスク
1285                 PICA_CMD_DATA_VS_OUT_MASK( exeHead.outputMask ),
1286                 PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_MASK ),
1287 
1288                 // 0x251  頂点シェーダ出力レジスタ使用数
1289                 outRegUseNum - 1,
1290                 PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM2 ),
1291 
1292                 // 0x252  ジオメトリシェーダのモード
1293                 PICA_CMD_DATA_GS_MISC_REG0( PICA_DATA_GS_OTHER_MODE ),
1294                 PICA_CMD_HEADER_SINGLE( PICA_REG_GS_MISC_REG0 ),
1295 
1296                 // 0x242  頂点シェーダに入力する頂点属性数
1297                 PICA_CMD_DATA_VS_ATTR_NUM1( vtxAttrNum ),
1298                 PICA_CMD_HEADER_SINGLE( PICA_REG_VS_ATTR_NUM1 ),
1299 
1300                 // 0x24a, 0x25e[3:0], 0x04f  頂点シェーダ出力レジスタ使用数
1301                 outRegUseNum - 1,
1302                 PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM1 ),
1303                 PICA_CMD_DATA_VS_GS_OUT_REG_NUM3( outRegUseNum, 0 /* mode */ ),
1304                 PICA_CMD_HEADER_SINGLE_BE( PICA_REG_VS_OUT_REG_NUM3, 0x1 ),
1305                 outRegUseNum,
1306                 PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_REG_NUM0 ),
1307             };
1308             m_CmdCacheDrawBegin.Add(commands, sizeof(commands));
1309         }
1310 
1311     // 0x050-0x056 頂点シェーダ出力属性
1312 
1313         {
1314             const u32 commands[] =
1315             {
1316                 *reinterpret_cast<u32*>(outmaps[0]),
1317                 PICA_CMD_HEADER_BURSTSEQ( PICA_REG_VS_OUT_ATTR0, OutRegNum ),
1318             };
1319             m_CmdCacheDrawBegin.Add(commands, sizeof(commands));
1320             m_CmdCacheDrawBegin.Add(reinterpret_cast<u32*>(outmaps[1]), sizeof(u32) * (OutRegNum - 1));
1321         }
1322 
1323         {
1324             bool usePosZ = false;
1325             {
1326                 int outCompNum = 0;
1327                 for (int i = 0; i < 4; ++i)
1328                 {
1329                     if (useOutRegTypes[SHADEROUTMAPTYPE_POSITION] & (1 << i))
1330                     {
1331                         ++outCompNum;
1332                     }
1333                 }
1334 
1335                 usePosZ = outCompNum >= 3;
1336             }
1337 
1338             const bool useViewQuaternion =
1339                     0 != useOutRegTypes[SHADEROUTMAPTYPE_VIEW]
1340                 ||  0 != useOutRegTypes[SHADEROUTMAPTYPE_QUATERNION];
1341             const u32 outAttrClk =
1342                 PICA_CMD_DATA_VS_GS_OUT_ATTR_CLK(
1343                     usePosZ,                                            /* posZ */
1344                     0 != useOutRegTypes[SHADEROUTMAPTYPE_COLOR],        /* col */
1345                     0 != useOutRegTypes[SHADEROUTMAPTYPE_TEXCOORD0],    /* tex0 */
1346                     0 != useOutRegTypes[SHADEROUTMAPTYPE_TEXCOORD1],    /* tex1 */
1347                     0 != useOutRegTypes[SHADEROUTMAPTYPE_TEXCOORD2],    /* tex2 */
1348                     0 != useOutRegTypes[SHADEROUTMAPTYPE_TEXCOORD0W],   /* tex0_w */
1349                     useViewQuaternion);                                 /* view_quart*/
1350             const u32 TexEnableBits =
1351                 PICA_CMD_DATA_VS_GS_OUT_ATTR_CLK(
1352                     false,      /* posZ */
1353                     false,      /* col */
1354                     true,       /* tex0 */
1355                     true,       /* tex1 */
1356                     true,       /* tex2 */
1357                     true,       /* tex0_w */
1358                     false);     /* view_quart*/
1359 
1360             const bool useTexCoords = 0 != (outAttrClk & TexEnableBits);
1361             const u32 outAttrMode = useTexCoords ? 1 : 0;
1362             const u32 commands[] =
1363             {
1364                 // 0x064  頂点シェーダからテクスチャ座標が出力される場合1
1365                 PICA_CMD_DATA_VS_GS_OUT_ATTR_MODE( outAttrMode ),
1366                 PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR_MODE ),
1367 
1368                 // 0x06f  頂点シェーダからの出力属性のクロック制御
1369                 outAttrClk,
1370                 PICA_CMD_HEADER_SINGLE( PICA_REG_VS_OUT_ATTR_CLK ),
1371             };
1372             m_CmdCacheDrawBegin.Add(commands, sizeof(commands));
1373         }
1374     }
1375 
1376     m_CmdCacheDrawBegin.Add(s_DrawInitCommands, sizeof(s_DrawInitCommands));
1377 
1378 #if defined(NW_FONT_RECTDRAWER_USE_DRAW_ARRAYS)
1379     m_VertexBufferBaseAddr = vboBaseAddr;
1380 #else
1381     {
1382         void *const eleArrayBuf = ut::AddOffsetToPtr(m_VertexBufferArray, sizeof(s_VertexBuffer.position));
1383         const uptr phyEleArrayBuf = nngxGetPhysicalAddr(reinterpret_cast<uptr>(eleArrayBuf));
1384         const u32 indexOffset = phyEleArrayBuf - vboBaseAddr;
1385         const u32 commands[] =
1386         {
1387             // 0x227
1388             PICA_CMD_DATA_INDEX_ARRAY_ADDR_OFFSET(
1389                 indexOffset,
1390                 1),             /* type */
1391             PICA_CMD_HEADER_SINGLE( PICA_REG_INDEX_ARRAY_ADDR_OFFSET ),
1392         };
1393         m_CmdCacheDrawBegin.Add(commands, sizeof(commands) );
1394     }
1395 #endif
1396 
1397     // m_CmdCacheDrawBegin.Dump();
1398 
1399     // DrawEnd() のコマンドキャッシュ生成
1400     AddVertexAttributeArrayCommand(m_CmdCacheDrawEnd, vboBaseAddr, phyArrayBuffer, vtxAttrNum);
1401 
1402     m_CmdCacheDrawEnd.Add(s_DrawFinalizeCommands, sizeof(s_DrawFinalizeCommands));
1403 
1404     // m_CmdCacheDrawEnd.Dump();
1405 
1406 
1407     { // Uniform コマンドの初期化
1408 
1409         // プロジェクション行列用コマンドの初期化
1410         InitUniformBuffer(m_UniformProjBuffer, UNIFORM_PROJ_START);
1411 
1412         // 視差情報用コマンドの初期化
1413         SetParallax(0.0f, 0.0f, 0.0f);
1414 
1415         // アドレスを詰めていくバッファの初期化
1416         InitUniformBuffer(m_UniformAddrBuffer, UNIFORM_ADDR_START);
1417 
1418         // 行列、頂点カラー詰めていくバッファの初期化
1419         InitUniformBuffer(m_UniformMtxBuffer, UNIFORM_MTX_START);
1420 
1421         // テクスチャ座標、を矩形情報を詰めていくバッファの初期化
1422         InitUniformBuffer(m_UniformDataBuffer, UNIFORM_DATA_START);
1423     }
1424 #else
1425     NN_ASSERT(false);
1426 #endif
1427 }
1428 
1429 void
InitUniformBuffer(u32 * __restrict buf,u32 addr)1430 RectDrawer::InitUniformBuffer(
1431     u32* __restrict buf,
1432     u32             addr
1433 )
1434 {
1435 #if defined(NW_PLATFORM_CTR)
1436     const u32 data =
1437         PICA_CMD_DATA_VS_FLOAT_ADDR( PICA_DATA_VS_F32, addr );
1438 
1439     buf[0] = data;
1440     buf[1] = PICA_CMD_HEADER_SINGLE( PICA_REG_VS_FLOAT_ADDR );
1441 #endif
1442 }
1443 
1444 void
BuildTextCommand(CharWriter * pCharWriter)1445 RectDrawer::BuildTextCommand(CharWriter* pCharWriter)
1446 {
1447 #if defined(NW_PLATFORM_CTR)
1448     NN_ASSERT(  m_UniformAddrIndex      == 0
1449             &&  m_UniformDataIndex      == 0
1450             &&  m_UniformMtxIndex       == 0
1451             &&  m_UniformTextColorIndex == 0 );
1452 
1453     DispStringBuffer* __restrict pStringBuffer = pCharWriter->GetDispStringBuffer();
1454     pStringBuffer->commandBufferSize = 0;
1455     pStringBuffer->textColorCommandOffset = 0;
1456     pStringBuffer->generatedCommand = true;     // コマンドを生成済みにします。
1457 
1458     const u16 charCount = math::Min(pStringBuffer->charCount, pStringBuffer->GetDrawCharCount());
1459 
1460     // 描画する文字数が0のときは抜けます。
1461     if (charCount == 0)
1462     {
1463         return;
1464     }
1465 
1466     m_UniformAddress.addrMtx = 0;
1467     m_IsColorDirty = false;
1468 
1469     // テキストカラーを詰めていくバッファの初期化
1470     InitUniformBuffer(m_UniformTextColorBuffer, UNIFORM_TEXTCOLOR_START);
1471 
1472     NW_FONT_ADD_COMMANDS(pStringBuffer, CommonCommands, sizeof(CommonCommands));
1473 
1474     // 頂点カラーの設定
1475     ut::Color8 vtxColors[internal::TEXTCOLOR_MAX] =
1476     {
1477         pCharWriter->GetGradationStartColor(),
1478         pCharWriter->GetGradationEndColor(),
1479     };
1480 
1481     AddTextColor(
1482         &m_UniformTextColor[m_UniformTextColorIndex],
1483         vtxColors,
1484         pCharWriter->GetGradationMode());
1485 
1486     // 描画したかどうかをあらわすフラグ
1487     u8 *const drawFlags = pStringBuffer->drawFlags;
1488     for (int i = math::RoundUp(charCount, 8) / 8; i > 0; --i)
1489     {
1490         drawFlags[i - 1] = 0;
1491 
1492         /*
1493          * std::memset(drawFlags, 0, charCount);
1494          * よりも、ループの方が速かった
1495          */
1496     }
1497 
1498     u32 addr = 0;
1499     u32 size = 0;
1500     u32 format = 0xFFFFFFFF;
1501     u32 texFilter = 0xFFFFFFFF;
1502     u32 startCharIndex = 0;
1503     internal::CharAttribute* __restrict charAttrs = pStringBuffer->GetCharAttrs();
1504 
1505     for (u32 drawCharCount = 0; drawCharCount < charCount; )
1506     {
1507         u32 i = startCharIndex;
1508         for ( ; IsDrawChar(drawFlags, i); ++i)
1509         {
1510             ;
1511         }
1512         startCharIndex = i + 1;     // 次の探索開始位置
1513 
1514         u32 cmdTexAddr = charAttrs[i].pTexObj->GetImage();
1515         if (addr != cmdTexAddr)
1516         {
1517             addr = cmdTexAddr;
1518 
1519             // テクスチャを切り替えるので、バッファを書き出す
1520             if (drawCharCount > 0 && m_UniformAddrIndex > 0)
1521             {
1522                 UniformAndDrawText(pStringBuffer);
1523             }
1524 
1525             if (format != charAttrs[i].pTexObj->GetFormat())
1526             {
1527                 const u32 newFormat = charAttrs[i].pTexObj->GetFormat();
1528 
1529                 const bool isNewAlpha  = newFormat == FONT_SHEET_FORMAT_A4 || newFormat == FONT_SHEET_FORMAT_A8;
1530                 const u32* commands = NULL;
1531                 u32 commandSize = 0;
1532                 if (format == 0xFFFFFFFF)   // 最初のとき
1533                 {
1534                     // テクスチャコンバイナ3、4段の設定を全て積む
1535                     if (isNewAlpha)
1536                     {
1537                         commands = TexEnv34AlphaCommands;
1538                         commandSize = sizeof(TexEnv34AlphaCommands);
1539                     }
1540                     else
1541                     {
1542                         commands = TexEnv34Commands;
1543                         commandSize = sizeof(TexEnv34Commands);
1544                     }
1545                     NW_FONT_ADD_COMMANDS(pStringBuffer, commands, commandSize);
1546                 }
1547                 else
1548                 {
1549                     // テクスチャコンバイナの変更分だけを積む
1550                     const bool isCrntAlpha = format == FONT_SHEET_FORMAT_A4 || format == FONT_SHEET_FORMAT_A8;
1551 
1552                     if (isCrntAlpha != isNewAlpha)
1553                     {
1554                         if (isNewAlpha)
1555                         {
1556                             commands = TexEnvOperand34AlphaCommands;
1557                             commandSize = sizeof(TexEnvOperand34AlphaCommands);
1558                         }
1559                         else
1560                         {
1561                             commands = TexEnvOperand34Commands;
1562                             commandSize = sizeof(TexEnvOperand34Commands);
1563                         }
1564                         NW_FONT_ADD_COMMANDS(pStringBuffer, commands, commandSize);
1565                     }
1566                 }
1567 
1568                 format = newFormat;
1569 
1570                 NW_FONT_ADD_SINGLE_COMMAND(
1571                     pStringBuffer,
1572                     PICA_CMD_HEADER_SINGLE(PICA_REG_TEXTURE0_FORMAT),
1573                     format);
1574             }
1575 
1576             // テクスチャキャッシュのクリア
1577             NW_FONT_ADD_SINGLE_COMMAND(
1578                 pStringBuffer,
1579                 PICA_CMD_HEADER_SINGLE_BE(PICA_REG_TEXTURE_FUNC, 0x4),
1580                 TEX_FUNC_DATA);
1581 
1582             // テクスチャアドレス
1583             NW_FONT_ADD_SINGLE_COMMAND(
1584                 pStringBuffer,
1585                 PICA_CMD_HEADER_SINGLE(PICA_REG_TEXTURE0_ADDR1),
1586                 addr);
1587 
1588             // テクスチャサイズ
1589             if (size != charAttrs[i].pTexObj->GetSize().size)
1590             {
1591                 size = charAttrs[i].pTexObj->GetSize().size;
1592                 NW_FONT_ADD_SINGLE_COMMAND(
1593                     pStringBuffer,
1594                     PICA_CMD_HEADER_SINGLE(PICA_REG_TEXTURE0_SIZE),
1595                     size);
1596             }
1597 
1598             const u32 crntTexFilter = charAttrs[i].pTexObj->GetWrapFilter();
1599             if (texFilter != crntTexFilter)
1600             {
1601                 texFilter = crntTexFilter;
1602                 NW_FONT_ADD_SINGLE_COMMAND(
1603                     pStringBuffer,
1604                     PICA_CMD_HEADER_SINGLE(PICA_REG_TEXTURE0_WRAP_FILTER),
1605                     texFilter);
1606             }
1607         }
1608 
1609         for ( ; i < charCount; ++i)
1610         {
1611             if (IsDrawChar(drawFlags, i) || addr != charAttrs[i].pTexObj->GetImage())
1612             {
1613                 continue;
1614             }
1615 
1616             const internal::CharAttribute& charAttr= pStringBuffer->GetCharAttrs()[i];
1617             if ( vtxColors[internal::TEXTCOLOR_START] != charAttr.color[internal::TEXTCOLOR_START]
1618               || vtxColors[internal::TEXTCOLOR_END  ] != charAttr.color[internal::TEXTCOLOR_END  ]
1619             )
1620             { // 頂点カラーの設定
1621                 vtxColors[internal::TEXTCOLOR_START] = charAttr.color[internal::TEXTCOLOR_START];
1622                 vtxColors[internal::TEXTCOLOR_END  ] = charAttr.color[internal::TEXTCOLOR_END  ];
1623                 AddTextColor(
1624                     &m_UniformTextColor[m_UniformTextColorIndex],
1625                     vtxColors,
1626                     pCharWriter->GetGradationMode());
1627             }
1628 
1629             { // テクスチャ座標の設定
1630                 m_UniformAddress.addrTexCoord = m_UniformDataIndex;
1631                 math::VEC4* __restrict pTexCoord = &m_UniformData[m_UniformDataIndex];
1632                 *pTexCoord = charAttr.tex;
1633 
1634                 ++m_UniformDataIndex;
1635             }
1636 
1637             { // 矩形の設定
1638 
1639                 m_UniformAddress.addrSizeAndVtx = m_UniformDataIndex;
1640                 math::VEC4* __restrict pQuadInfo = &m_UniformData[m_UniformDataIndex];
1641                 *pQuadInfo = charAttr.pos;
1642 
1643                 ++m_UniformDataIndex;
1644             }
1645 
1646             SetDrawChar(drawFlags, i);
1647             ++drawCharCount;
1648 
1649             m_UniformAddr[m_UniformAddrIndex] = m_UniformAddress;
1650             ++m_UniformAddrIndex;
1651 
1652 #ifdef NW_FONT_RECTDRAWER_USE_DRAW_BUFFER
1653             if ( m_UniformAddrIndex + 1                  > UNIFORM_ADDR_NUM
1654               || m_UniformDataIndex + 1 + 1              > UNIFORM_DATA_NUM
1655               || m_UniformTextColorIndex + COLOR_USE_COUNT > UNIFORM_TEXTCOLOR_NUM
1656             )
1657             {
1658                 UniformAndDrawText(pStringBuffer);
1659             }
1660 #else
1661             UniformAndDrawText(pStringBuffer);
1662 #endif
1663         }
1664     }
1665 
1666     if (m_UniformAddrIndex > 0)
1667     {
1668         UniformAndDrawText(pStringBuffer);
1669     }
1670     m_UniformTextColorIndex = 0;
1671 #else
1672     NN_ASSERT(false);
1673 #endif
1674 }
1675 
1676 void
UniformAndDrawText(DispStringBuffer * pStringBuffer)1677 RectDrawer::UniformAndDrawText(DispStringBuffer* pStringBuffer)
1678 {
1679 #if defined(NW_PLATFORM_CTR)
1680     NN_ASSERT(m_UniformAddrIndex > 0);
1681 
1682     const int vtxNum = DRAW_VTX_NUM * m_UniformAddrIndex;   // 描画頂点数
1683 
1684     // uUniformAddr へのUniform
1685     {
1686         u32 size = SetUniformCommand(m_UniformAddrBuffer, m_UniformAddrIndex);
1687         NW_FONT_ADD_COMMANDS(pStringBuffer, m_UniformAddrBuffer, size);
1688         m_UniformAddrIndex = 0;
1689     }
1690 
1691     if (m_IsColorDirty)
1692     { // uUniformMtx への頂点カラーのUniform
1693         // テキストカラーのコマンド位置を保存
1694         if (pStringBuffer->textColorCommandOffset == 0)
1695         {
1696             pStringBuffer->textColorCommandOffset = pStringBuffer->commandBufferSize;
1697         }
1698 
1699         u32 size = SetUniformCommand(m_UniformTextColorBuffer, m_UniformTextColorIndex);
1700         NW_FONT_ADD_COMMANDS(pStringBuffer, m_UniformTextColorBuffer, size);
1701 
1702         const u8 lastColorIdx = m_UniformTextColorIndex - VERTEX_MAX;
1703         if (lastColorIdx > 0)
1704         {
1705             // 色が2つ以上のときは、最後の色を先頭に持ってくる。
1706             for (int i = 0; i < VERTEX_MAX; ++i)
1707             {
1708                 m_UniformTextColor[i] = m_UniformTextColor[lastColorIdx + i];
1709             }
1710             m_IsColorDirty = true;
1711         }
1712         else
1713         {
1714             // 色が1つだったときは、そのまま。ただし、ヘッダと入れ替えた値を戻しておく。
1715             m_UniformTextColorBuffer[3] = m_UniformTextColorBuffer[2];
1716             m_IsColorDirty = false;
1717         }
1718         m_UniformAddress.addrColor = MATRIX_UNIFORM_NUM;
1719         m_UniformTextColorIndex = VERTEX_MAX;
1720     }
1721 
1722     if (m_UniformDataIndex > 0)
1723     { // uUniformData へのUniform
1724 
1725         u32 size = SetUniformCommand(m_UniformDataBuffer, m_UniformDataIndex);
1726         NW_FONT_ADD_COMMANDS(pStringBuffer, m_UniformDataBuffer, size);
1727         m_UniformDataIndex = 0;
1728     }
1729 
1730     // コマンドリストに描画コマンドを積む
1731 #if defined(NW_FONT_RECTDRAWER_USE_DRAW_ARRAYS)
1732     const u32 addrOffset = GetVertexIndexAddressOffset(vtxNum);
1733 #else
1734     const u32 addrOffset = 0;   // dummy
1735 #endif
1736 
1737     u32* cmdPtr = &pStringBuffer->commandBuffer[pStringBuffer->commandBufferSize];
1738     internal::SetVertexNumCmd(&cmdPtr, addrOffset, vtxNum);
1739     pStringBuffer->commandBufferSize = cmdPtr - &pStringBuffer->commandBuffer[0];
1740 
1741     NW_FONT_ADD_COMMANDS( pStringBuffer, GetDrawCommands(), GetDrawCommandSize() );
1742 #else
1743     NN_ASSERT(false);
1744 #endif
1745 }
1746 
1747 #if defined(NW_FONT_RECTDRAWER_USE_DRAW_ARRAYS)
1748 u32
GetVertexIndexAddressOffset(u32 vtxNum) const1749 RectDrawer::GetVertexIndexAddressOffset(u32 vtxNum) const
1750 {
1751     return (((vtxNum > 0x10 ? (vtxNum - 0x10) * 2: 0) + m_VertexBufferBaseAddr) & 0xFFF) >= 0xFE0 ? 0x20: 0;
1752 }
1753 #endif
1754 
1755 const u32*
GetDrawCommands() const1756 RectDrawer::GetDrawCommands() const
1757 {
1758 #if defined(NW_PLATFORM_CTR)
1759     return DrawCommands;
1760 #else
1761     return NULL;
1762 #endif
1763 }
1764 
1765 u32
GetDrawCommandSize() const1766 RectDrawer::GetDrawCommandSize() const
1767 {
1768 #if defined(NW_PLATFORM_CTR)
1769     return sizeof(DrawCommands);
1770 #else
1771     return 0;
1772 #endif
1773 }
1774 
1775 void
AddTextColor(math::VEC4 * __restrict dst,const ut::Color8 * __restrict src,int mode)1776 RectDrawer::AddTextColor(
1777     math::VEC4* __restrict          dst,
1778     const ut::Color8* __restrict    src,
1779     int                             mode
1780 )
1781 {
1782 #if defined(NW_PLATFORM_CTR)
1783     SetVertexColor(dst, src, mode);
1784     m_UniformAddress.addrColor = static_cast<f32>(MATRIX_UNIFORM_NUM + m_UniformTextColorIndex);
1785     m_UniformTextColorIndex += COLOR_USE_COUNT;
1786     m_IsColorDirty = true;
1787 #else
1788     NN_ASSERT(false);
1789 #endif
1790 }
1791 
1792 // ---- 以下、 RectDrawer クラス以外のコード ----
1793 
1794 u32
CalcCommandBufferCapacity(u32 charNum)1795 DispStringBuffer::CalcCommandBufferCapacity(u32 charNum)
1796 {
1797 #if defined(NW_PLATFORM_CTR)
1798     NN_ASSERT(sizeof(TexEnv34Commands) == sizeof(TexEnv34AlphaCommands));
1799     NN_ASSERT(sizeof(TexEnvOperand34Commands) == sizeof(TexEnvOperand34AlphaCommands));
1800 
1801     const int UniformComponents = 4;    // ユニフォームの成分の個数(xyzw)
1802     const int SingleCommand = 2;        // シングルコマンド
1803     // Uniform転送用コマンドのヘッダ分
1804     const int UniformHeader = math::RoundUp(SingleCommand + 1, 2);
1805 
1806     return
1807                   sizeof(CommonCommands) / sizeof(u32)      // ブレンド・コンバイナ・シェーダー設定
1808                 + UniformComponents * COLOR_USE_COUNT       // 初期文字色
1809                 + sizeof(TexEnv34Commands) / sizeof(u32)    // コンバイナ設定
1810                 + charNum *
1811                     (
1812                           sizeof(TexEnvOperand34Commands) / sizeof(u32)     // コンバイナの変更分
1813                         + SingleCommand * 5     // テクスチャ用シングルコマンド4つ
1814                                                 // (アドレス、サイズ、フォーマット、フィルタ、キャッシュクリア)
1815                         + UniformHeader + UniformComponents * 1                 // アドレス
1816                         + UniformHeader + UniformComponents * COLOR_USE_COUNT   // 文字色
1817                         + UniformHeader + UniformComponents * (1 + 1)   // テクスチャ座標と矩形情報
1818 #if defined(NW_FONT_RECTDRAWER_USE_DRAW_ARRAYS)
1819                         + SingleCommand * 1     // 頂点インデックスオフセット
1820 #endif
1821                         + SingleCommand * 1     // 頂点数
1822                         + sizeof(DrawCommands) / sizeof(u32)    // 描画コマンド
1823                     )
1824             ;
1825 #else
1826     return 0;
1827 #endif
1828 }
1829 
1830 void
UseCommandBuffer()1831 CharWriter::UseCommandBuffer()
1832 {
1833 #if defined(NW_PLATFORM_CTR)
1834     NN_NULL_ASSERT(m_pDispStringBuffer);
1835     NN_NULL_ASSERT(m_pDispStringBuffer->commandBuffer);
1836     NN_ASSERT(m_pDispStringBuffer->IsGeneratedCommand());
1837 
1838     if (m_pDispStringBuffer->IsCommandEmpty())
1839     {
1840         return;
1841     }
1842 
1843     // 頂点カラーの設定
1844     {
1845         NN_ASSERT(m_pDispStringBuffer->textColorCommandOffset != 0);
1846 
1847         u32 *const cmdBuf =
1848             &m_pDispStringBuffer->commandBuffer[m_pDispStringBuffer->textColorCommandOffset];
1849         const u32 header = cmdBuf[3];
1850 
1851         math::VEC4 *const dstCol = reinterpret_cast<math::VEC4*>(&cmdBuf[3]);
1852         SetVertexColor(dstCol, m_TextColors, GetGradationMode());
1853 
1854         cmdBuf[2] = cmdBuf[3];
1855         cmdBuf[3] = header;
1856     }
1857 
1858     // 白黒補間カラーの設定
1859     {
1860         const u32 alpha = m_Alpha;
1861         ut::Color8 white = m_ColorMapping.max;
1862         ut::Color8 black = m_ColorMapping.min;
1863         white.a = static_cast<u8>(white.a * alpha / 255);
1864         black.a = static_cast<u8>(black.a * alpha / 255);
1865 
1866         u32 *const cmdBuf =
1867             &m_pDispStringBuffer->commandBuffer[(sizeof(CommonCommands) / sizeof(u32))];
1868         cmdBuf[0                    + TEX_ENV_COLOR_POS] = GetColorU32Raw(white);
1869         cmdBuf[TEX_ENV_COMMAND_SIZE + TEX_ENV_COLOR_POS] = GetColorU32Raw(black);
1870     }
1871 
1872     NW_FONT_RECTDRAWER_ADD_COMMAND(
1873         m_pDispStringBuffer->commandBuffer,
1874         m_pDispStringBuffer->commandBufferSize * sizeof(u32));
1875 #else
1876     NN_ASSERT(false);
1877 #endif
1878 }
1879 
1880 }   // namespace font
1881 }   // namespace nw
1882 
1883