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