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