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