1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: gfx_GraphicsDevice.h
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: 27679 $
14 *---------------------------------------------------------------------------*/
15
16 #ifndef NW_GFX_GRAPHICSDEVICE_H_
17 #define NW_GFX_GRAPHICSDEVICE_H_
18
19 #include <GLES2/gl2.h>
20 #include <GLES2/gl2ext.h>
21
22 #include <nw/types.h>
23 #include <nw/ut/ut_Color.h>
24 #include <nw/ut/ut_Rect.h>
25 #include <nw/gfx/gfx_Viewport.h>
26
27 // このマクロを定義するとマテリアルの個々の要素の設定に関するプロファイルを行います。
28 // #define NW_MATERIAL_PROFILE
29
30 namespace nw
31 {
32 namespace os
33 {
34 class IAllocator;
35 }
36
37 namespace gfx
38 {
39
40 //---------------------------------------------------------------------------
41 //! @brief 描画内容を GPU に設定するクラスです。
42 //---------------------------------------------------------------------------
43 class GraphicsDevice
44 {
45 public:
46 //----------------------------------------
47 //! @name ラスタライゼーション関連
48 //@{
49
50 //---------------------------------------------------------------------------
51 //! @brief ポリゴンオフセットが有効化どうかのフラグを設定します。
52 //!
53 //! @param[in] enabled ポリゴンオフセットのが有効化どうかのフラグです。
54 //---------------------------------------------------------------------------
SetPolygonOffsetEnabled(bool enabled)55 static NW_INLINE void SetPolygonOffsetEnabled(bool enabled)
56 {
57 s_PolygonOffsetEnabled = enabled;
58 }
59
60 //---------------------------------------------------------------------------
61 //! @brief ポリゴンオフセットのユニット要素を設定します。
62 //!
63 //! @param[in] polygonOffsetUnit ポリゴンオフセットのユニット要素です。
64 //---------------------------------------------------------------------------
SetPolygonOffsetUnit(f32 polygonOffsetUnit)65 static NW_INLINE void SetPolygonOffsetUnit(f32 polygonOffsetUnit)
66 {
67 s_PolygonOffsetUnit = polygonOffsetUnit;
68 }
69
70 //---------------------------------------------------------------------------
71 //! @brief ポリゴンオフセットのコマンドを発行します。
72 //---------------------------------------------------------------------------
73 static NW_INLINE void ActivatePolygonOffset();
74
75 //@}
76
77 //----------------------------------------
78 //! @name フレームバッファ関連
79 //@{
80 //@}
81
82 //----------------------------------------
83 //! @name ブレンダ関連
84 //@{
85
86 //! @brief ブレンド計算を有効または無効にします。
87 //!
88 //! @param[in] enabled ブレンド計算の有効フラグです。
89 //!
90 static NW_INLINE void SetBlendEnabled(bool enabled);
91
92 //@}
93
94 //----------------------------------------
95 //! @name フラグメントオペレーション関連
96 //@{
97
98 //! @brief フラグメントオペレーションモードを設定します。
SetFragmentOperationMode(const ResFragmentOperation::FragmentOperationMode mode)99 static NW_INLINE void SetFragmentOperationMode(const ResFragmentOperation::FragmentOperationMode mode)
100 {
101 if (s_FragOperationMode != mode)
102 {
103 s_FragOperationMode = mode;
104 s_IsFrameBufferUpdated = true;
105 }
106 }
107
108 //! @brief フラグメントオペレーションモードを設定します。
ActivateFragmentOperationMode(ResFragmentOperation::FragmentOperationMode mode)109 static NW_INLINE void ActivateFragmentOperationMode(ResFragmentOperation::FragmentOperationMode mode)
110 {
111 s_FragOperationMode = mode;
112
113 enum
114 {
115 REG_FRAGMENT_OPERATION = 0x100
116 };
117
118 const u32 HEADER = internal::MakeCommandHeader(REG_FRAGMENT_OPERATION, 1, false, 0x1);
119
120 const u32 COMMAND[] =
121 {
122 mode,
123 HEADER
124 };
125
126 s_IsFrameBufferUpdated = true;
127 ActivateFrameBuffer();
128 }
129
130 //! @brief 深度バッファリングを有効または無効にします。
131 //!
132 //! @param[in] enabled 深度バッファリングの有効フラグです。
133 //!
134 static NW_INLINE void SetDepthTestEnabled(bool enabled);
135
136 //! @brief ステンシルテストを有効または無効にします。
137 //!
138 //! @param[in] enabled ステンシルテストの有効フラグです。
139 //!
140 static NW_INLINE void SetStencilTestEnabled(bool enabled);
141
142
143 //! @brief 深度範囲を設定します。
SetDepthRange(f32 near,f32 far)144 static void SetDepthRange(f32 near, f32 far)
145 {
146 s_DepthRangeNear = nw::ut::Clamp(near, 0.0f, 1.0f);
147 s_DepthRangeFar = nw::ut::Clamp(far, 0.0f, 1.0f);
148 s_DepthRange24 = ut::Float24::Float32ToBits24(s_DepthRangeNear - s_DepthRangeFar);
149 }
150
151 //! @brief WScaleの設定をおこないます。
152 //!
153 //! @param[in] wscale wscaleの値です。
SetWScale(f32 wscale)154 static void SetWScale(f32 wscale)
155 {
156 if (wscale == 0.0f)
157 {
158 s_WScale24 = 0;
159 }
160 else
161 {
162 s_WScale24 = ut::Float24::Float32ToBits24(-wscale);
163 }
164 }
165
166 //! @brief 深度フォーマットを設定します。
167 //!
168 //! @details ここで設定された値はポリゴンオフセットの設定に使用されます。
169 //! 深度フォーマット設定が実際に設定されるわけではありません。
170 //!
171 //! @param[in] format 深度フォーマットです。
SetDepthFormat(u32 format)172 static void SetDepthFormat(u32 format)
173 {
174 s_DepthFormat = format;
175 }
176
177 //@}
178
179 //----------------------------------------
180 //! @name マスク関連
181 //@{
182
183 //! @brief カラーマスクを設定します。
184 //!
185 //! @param[in] red 赤色のマスクの有効フラグです。
186 //! @param[in] green 緑色のマスクの有効フラグです。
187 //! @param[in] blue 青色のマスクの有効フラグです。
188 //! @param[in] alpha アルファチャンネルのマスクの有効フラグです。
189 //!
190 static NW_INLINE void SetColorMask(bool red, bool green, bool blue, bool alpha);
191
192 //! @brief 深度マスクを設定します。
193 //!
194 //! @param[in] enabled マスクの有効フラグです。
195 //!
196 static NW_INLINE void SetDepthMaskEnabled(bool enabled);
197
198 //! @brief ステンシルマスクを設定します。
199 //!
200 //! @param[in] mask マスクの有効フラグです。
201 //!
202 static NW_INLINE void SetStencilMask(u8 mask);
203
204 //! フレームバッファを有効にするコマンドを発行します。
205 static NW_INLINE void ActivateFrameBuffer();
206
207 //! マスクを有効にするコマンドを発行します。
208 static NW_INLINE void ActivateMask();
209
210 //@}
211
212 //----------------------------------------
213 //! @name 参照テーブル関連
214 //@{
215
216 // TODO: Shadow と Gas には未対応ですので、グラフィックスランタイムで実装を行うときに対応します。
217 //! @brief LookupTable を設定するターゲットの定義です。
218 enum LutTarget
219 {
220 LUT_TARGET_D0, //!< D0の参照テーブルを表します。
221 LUT_TARGET_D1, //!< D1の参照テーブルを表します。
222 LUT_TARGET_SP, //!< SPの参照テーブルを表します。
223 LUT_TARGET_FR, //!< FRの参照テーブルを表します。
224 LUT_TARGET_RB, //!< RBの参照テーブルを表します。
225 LUT_TARGET_RG, //!< RGの参照テーブルを表します。
226 LUT_TARGET_RR, //!< RRの参照テーブルを表します。
227 LUT_TARGET_SP0, //!< 0番目の角度減衰テーブルを表します。
228 LUT_TARGET_SP1, //!< 1番目の角度減衰テーブルを表します。
229 LUT_TARGET_SP2, //!< 2番目の角度減衰テーブルを表します。
230 LUT_TARGET_SP3, //!< 3番目の角度減衰テーブルを表します。
231 LUT_TARGET_SP4, //!< 4番目の角度減衰テーブルを表します。
232 LUT_TARGET_SP5, //!< 5番目の角度減衰テーブルを表します。
233 LUT_TARGET_SP6, //!< 6番目の角度減衰テーブルを表します。
234 LUT_TARGET_SP7, //!< 7番目の角度減衰テーブルを表します。
235 LUT_TARGET_DA0, //!< 0番目の距離減衰テーブルを表します。
236 LUT_TARGET_DA1, //!< 1番目の距離減衰テーブルを表します。
237 LUT_TARGET_DA2, //!< 2番目の距離減衰テーブルを表します。
238 LUT_TARGET_DA3, //!< 3番目の距離減衰テーブルを表します。
239 LUT_TARGET_DA4, //!< 4番目の距離減衰テーブルを表します。
240 LUT_TARGET_DA5, //!< 5番目の距離減衰テーブルを表します。
241 LUT_TARGET_DA6, //!< 6番目の距離減衰テーブルを表します。
242 LUT_TARGET_DA7, //!< 7番目の距離減衰テーブルを表します。
243 LUT_TARGET_FOG, //!< FOGの参照テーブルを表します。
244 LUT_TARGET_COUNT //!< 定義数を表します。
245 };
246
247 //--------------------------------------------------------------------------
248 //! @brief LUTの入力が絶対値かどうかを指定します。
249 //!
250 //! @param[in] target LUTのターゲットを指定します。
251 //! @param[in] isAbs LUTの入力が絶対値かどうかを指定します。
252 //---------------------------------------------------------------------------
SetLutIsAbs(LutTarget target,bool isAbs)253 static void SetLutIsAbs(LutTarget target, bool isAbs)
254 {
255 NW_ASSERT(target < LUT_TARGET_COUNT);
256
257 if (LUT_TARGET_SP0 <= target && target <= LUT_TARGET_SP7)
258 {
259 target = LUT_TARGET_SP;
260 }
261
262 if (isAbs)
263 {
264 s_LutIsAbs &= ~(0x1 << (1 + 4 * target));
265 }
266 else
267 {
268 s_LutIsAbs |= 0x1 << (1 + 4 * target) ;
269 }
270 }
271
272 //--------------------------------------------------------------------------
273 //! @brief LUTの入力値を指定します。
274 //!
275 //! @param[in] target LUTのターゲットを指定します。
276 //! @param[in] input LUTの入力値を指定します。
277 //---------------------------------------------------------------------------
SetLutInput(LutTarget target,ResLightingLookupTable::Input input)278 static void SetLutInput( LutTarget target, ResLightingLookupTable::Input input )
279 {
280 NW_ASSERT(target < LUT_TARGET_COUNT);
281 NW_ASSERT(input < ResLightingLookupTable::INPUT_NUM);
282
283 if (LUT_TARGET_SP0 <= target && target <= LUT_TARGET_SP7)
284 {
285 target = LUT_TARGET_SP;
286 }
287
288 s_LutInput &= ~(0x7 << (4 * target));
289 s_LutInput |= input << (4 * target);
290 }
291
292 //--------------------------------------------------------------------------
293 //! @brief LUTのスケール値を指定します。
294 //!
295 //! @param[in] target LUTのターゲットを指定します。
296 //! @param[in] scale LUTのスケール値を指定します。
297 //---------------------------------------------------------------------------
SetLutScale(LutTarget target,ResLightingLookupTable::Scale scale)298 static void SetLutScale( LutTarget target, ResLightingLookupTable::Scale scale )
299 {
300 NW_ASSERT(target < LUT_TARGET_COUNT);
301 NW_ASSERT(scale <= ResLightingLookupTable::SCALE_MAX);
302
303 if (LUT_TARGET_SP0 <= target && target <= LUT_TARGET_SP7)
304 {
305 target = LUT_TARGET_SP;
306 }
307
308 s_LutScale &= ~(0x7 << (4 * target));
309 s_LutScale |= scale << (4 * target);
310 }
311
312 //--------------------------------------------------------------------------
313 //! @brief LUTのパラメータをコマンド出力します。
314 //---------------------------------------------------------------------------
ActivateLutParameters()315 static void ActivateLutParameters()
316 {
317 enum { REG_LUT_ABS = 0x1d0 };
318
319 const u32 HEADER = internal::MakeCommandHeader( REG_LUT_ABS, 3, true, 0xf );
320
321 const u32 COMMAND[] =
322 {
323 s_LutIsAbs,
324 HEADER,
325 s_LutInput,
326 s_LutScale
327 };
328
329 internal::NWUseCmdlist<sizeof(COMMAND)>( &COMMAND[0] );
330 }
331
332 //--------------------------------------------------------------------------
333 //! @brief LUTのパラメータの状態をリセットします。
334 //---------------------------------------------------------------------------
ResetLutParameters()335 static void ResetLutParameters()
336 {
337 s_LutIsAbs = 0;
338 s_LutInput = 0;
339 s_LutScale = 0;
340 }
341
342 //---------------------------------------------------------------------------
343 //! @brief 参照テーブルを参照テーブルキャッシュに設定します。
344 //!
345 //! @param[in] lookupTable 設定する参照テーブルです。
346 //! @param[in] target 設定するターゲットです。
347 //---------------------------------------------------------------------------
348 static void ActivateLookupTable(ResImageLookupTable lookupTable, LutTarget target);
349
350 //---------------------------------------------------------------------------
351 //! @brief 参照テーブルキャッシュに設定された参照テーブルを削除します。
352 //!
353 //! @param[in] lookupTable 削除する参照テーブルです。
354 //---------------------------------------------------------------------------
355 static void InvalidateLookupTable(ResImageLookupTable lookupTable);
356
357 //---------------------------------------------------------------------------
358 //! @brief 全ての参照テーブルを無効化します。
359 //---------------------------------------------------------------------------
360 static void InvalidateAllLookupTables();
361
362 //@}
363
364
365 //----------------------------------------
366 //! @name ライト関連
367 //@{
368
369 //--------------------------------------------------------------------------
370 //! @brief ライトのイネーブルフラグをリセットします。
371 //---------------------------------------------------------------------------
ResetFragmentLightEnabled()372 static void ResetFragmentLightEnabled()
373 {
374 s_LightPositionW = 0x0;
375 s_LightShadowed = 0xFF;
376 s_LightSpotEnabled = 0xFF;
377 s_LightDistanceAttnEnabled = 0xFF;
378 }
379
380 //--------------------------------------------------------------------------
381 //! @brief ポジションWの値を取得します。
382 //!
383 //! @param[in] index ライトのインデックスです。
384 //--------------------------------------------------------------------------
GetFragmentLightPositionW(int index)385 static NW_INLINE bool GetFragmentLightPositionW(int index)
386 {
387 return ((s_LightPositionW >> index) & 0x1);
388 }
389
390 //--------------------------------------------------------------------------
391 //! @brief ポジションWの値を設定します。
392 //!
393 //! @param[in] index ライトのインデックスです。
394 //! @param[in] isWZero W成分が0かどうかを表します。
395 //--------------------------------------------------------------------------
SetFragmentLightPositionW(int index,bool isWZero)396 static NW_INLINE void SetFragmentLightPositionW(int index, bool isWZero)
397 {
398 // 1: isWZero, 0: !isWZero
399 if (isWZero)
400 {
401 s_LightPositionW |= (0x1 << index);
402 }
403 else
404 {
405 s_LightPositionW &= ~(0x1 << index);
406 }
407 }
408
409 //--------------------------------------------------------------------------
410 //! @brief シャドウ減衰を有効にします。
411 //!
412 //! @param[in] index ライトのインデックスです。
413 //! @param[in] shadowed シャドウ減衰のイネーブルフラグです。
414 //--------------------------------------------------------------------------
SetFragmentLightShadowed(int index,bool shadowed)415 static void SetFragmentLightShadowed(int index, bool shadowed)
416 {
417 // 0: GL_TRUE, 1: GL_FALSE
418 if (shadowed)
419 {
420 s_LightShadowed &= ~(0x1 << index);
421 }
422 else
423 {
424 s_LightShadowed |= 0x1 << index;
425 }
426 }
427
428 //--------------------------------------------------------------------------
429 //! @brief スポットライトの有効設定をおこないます。
430 //!
431 //! @param[in] index ライトのインデックスです。
432 //! @param[in] enabled 距離減衰のイネーブルフラグです。
433 //--------------------------------------------------------------------------
SetFragmentLightSpotEnabled(int index,bool enabled)434 static void SetFragmentLightSpotEnabled(int index, bool enabled)
435 {
436 // 0: GL_TRUE, 1: GL_FALSE
437 if (enabled)
438 {
439 s_LightSpotEnabled &= ~(0x1 << index);
440 }
441 else
442 {
443 s_LightSpotEnabled |= 0x1 << index;
444 }
445 }
446
447 //--------------------------------------------------------------------------
448 //! @brief 距離減衰の有効設定をおこないます。
449 //!
450 //! @param[in] index ライトのインデックスです。
451 //! @param[in] enabled 距離減衰のイネーブルフラグです。
452 //--------------------------------------------------------------------------
SetFragmentLightDistanceAttnEnabled(int index,bool enabled)453 static void SetFragmentLightDistanceAttnEnabled(int index, bool enabled)
454 {
455 // 0: GL_TRUE, 1: GL_FALSE
456 if (enabled)
457 {
458 s_LightDistanceAttnEnabled &= ~(0x1 << index);
459 }
460 else
461 {
462 s_LightDistanceAttnEnabled |= 0x1 << index;
463 }
464 }
465
466 //--------------------------------------------------------------------------
467 //! @brief 距離減衰テーブルを設定します。
468 //!
469 //! @param[in] index ライトのインデックスです。
470 //! @param[in] lookupTable 距離減衰のLUTを指定します。
471 //--------------------------------------------------------------------------
ActivateFragmentLightDistanceAttnTable(int index,const ResImageLookupTable lookupTable)472 static NW_INLINE void ActivateFragmentLightDistanceAttnTable(int index, const ResImageLookupTable lookupTable)
473 {
474 GraphicsDevice::LutTarget tableTarget = static_cast<GraphicsDevice::LutTarget>(GraphicsDevice::LUT_TARGET_DA0 + index);
475
476 GraphicsDevice::ActivateLookupTable(lookupTable, tableTarget);
477 }
478
479 //--------------------------------------------------------------------------
480 //! @brief スポットテーブルを設定します。
481 //!
482 //! @param[in] index ライトのインデックスです。
483 //! @param[in] lookupTable スポットライトのLUTを指定します。
484 //--------------------------------------------------------------------------
ActivateFragmentLightSpotTable(int index,const ResImageLookupTable lookupTable)485 static NW_INLINE void ActivateFragmentLightSpotTable(int index, const ResImageLookupTable lookupTable)
486 {
487 GraphicsDevice::LutTarget tableTarget = static_cast<GraphicsDevice::LutTarget>(GraphicsDevice::LUT_TARGET_SP0 + index);
488
489 GraphicsDevice::ActivateLookupTable(lookupTable, tableTarget);
490 }
491
492 //--------------------------------------------------------------------------
493 //! @brief 距離減衰のスケールとバイアスのコマンドを発行します。
494 //!
495 //! @param[in] index ライトインデックスです。
496 //! @param[in] scalef20 距離減衰のスケール値です。
497 //! @param[in] biasf20 距離減衰のバイアス値です。
498 //---------------------------------------------------------------------------
ActivateFragmentLightDistanceAttnScaleBias(int index,u32 scalef20,u32 biasf20)499 static void ActivateFragmentLightDistanceAttnScaleBias(int index, u32 scalef20, u32 biasf20)
500 {
501 enum
502 {
503 REG_DISTANCE_ATTN_BIAS = 0x14a,
504 REG_DISTANCE_ATTN_SCALE = 0x14b
505 };
506
507 const u32 HEADER = internal::MakeCommandHeader(REG_DISTANCE_ATTN_BIAS, 2, true, 0x7);
508
509 u32 COMMAND[] =
510 {
511 biasf20,
512 HEADER + 0x10 * index,
513 scalef20,
514 0
515 };
516
517 internal::NWUseCmdlist<sizeof(COMMAND)>( &COMMAND[0] );
518 }
519
520 //--------------------------------------------------------------------------
521 //! @brief フラグメントライト用のコマンドを発行します。
522 //!
523 //! @param[in] index 設定するライトのインデックスです。
524 //! @param[in] pos ライトのポジションです。
525 //---------------------------------------------------------------------------
526 static NW_INLINE void
ActivateFragmentLightPosition(s32 index,const math::VEC4 & pos)527 ActivateFragmentLightPosition(s32 index, const math::VEC4& pos)
528 {
529 enum
530 {
531 REG_FRAGMENT_LIGHT_POS_BASE = 0x144
532 };
533
534 const u32 POS_HEADER = internal::MakeCommandHeader(REG_FRAGMENT_LIGHT_POS_BASE, 2, true, 0xF);
535
536 u32 LIGHT_COMMAND[4] =
537 {
538 ut::Float16(pos.y).GetFloat16Value() << 16 | ut::Float16(pos.x).GetFloat16Value(), // pos_y << 16 | pos_x
539 POS_HEADER + 0x10 * index,
540 ut::Float16(pos.z).GetFloat16Value(), // pos_z
541 0
542 };
543
544 internal::NWUseCmdlist<sizeof(LIGHT_COMMAND)>( &LIGHT_COMMAND[0] );
545 }
546
547 //--------------------------------------------------------------------------
548 //! @brief フラグメントライトの位置情報を発行します。
549 //!
550 //! @param[in] index ライトのインデックスです。
551 //! @param[in] pos ライトの位置です。
552 //! @param[in] spotDir ライトのスポット方向です。
553 //---------------------------------------------------------------------------
554 static NW_INLINE void
ActivateFragmentLightPosition(s32 index,const math::VEC4 & pos,const math::VEC3 & spotDir)555 ActivateFragmentLightPosition(s32 index, const math::VEC4& pos, const math::VEC3& spotDir)
556 {
557 enum
558 {
559 REG_FRAGMENT_LIGHT_POS_BASE = 0x144
560 };
561
562 const u32 POS_HEADER = internal::MakeCommandHeader(REG_FRAGMENT_LIGHT_POS_BASE, 4, true, 0xF);
563
564 u32 LIGHT_COMMAND[6] =
565 {
566 ut::Float16(pos.y).GetFloat16Value() << 16 | ut::Float16(pos.x).GetFloat16Value(), // pos_y << 16 | pos_x
567 POS_HEADER + 0x10 * index,
568 ut::Float16(pos.z).GetFloat16Value(), // pos_z
569 ut::Fixed13(-spotDir.y).GetFixed13Value() << 16 | ut::Fixed13(-spotDir.x).GetFixed13Value(), // dir_y << 16 | dir_x
570 ut::Fixed13(-spotDir.z).GetFixed13Value(), // dir_z
571 0
572 };
573
574 internal::NWUseCmdlist<sizeof(LIGHT_COMMAND)>( &LIGHT_COMMAND[0] );
575 }
576
577 //--------------------------------------------------------------------------
578 //! @brief フラグメントライトの有効設定のコマンドを発行します。
579 //---------------------------------------------------------------------------
ActivateFragmentLightEnabled()580 static void ActivateFragmentLightEnabled()
581 {
582 enum { REG_FRAGMENT_LIGHT_KIND = 0x1c4 };
583
584 // 0x1c4 の [22:16] はFR,D0,D1,ReflのlutEnableフラグなので、BEを外しておく。
585 const u32 HEADER = internal::MakeCommandHeader(REG_FRAGMENT_LIGHT_KIND, 1, false, 0xb);
586
587 const u32 COMMAND[] =
588 {
589 s_LightShadowed | (s_LightSpotEnabled << 8) | (s_LightDistanceAttnEnabled << 24),
590 HEADER
591 };
592
593 internal::NWUseCmdlist<sizeof(COMMAND)>(&COMMAND[0]);
594 }
595
596 //@}
597
598
599 //--------------------------------------------------------------------------
600 //! @brief レンダリングターゲットサーフェスのウィンドウのサイズを設定します。
601 //!
602 //! @param[in] viewport 設定するビューポートです。
603 //--------------------------------------------------------------------------
ActivateViewport(const Viewport & viewport)604 static void ActivateViewport(const Viewport& viewport)
605 {
606 enum
607 {
608 REG_VIEWPORT_WIDTH_HALF = 0x41,
609 REG_VIEWPORT_WIDTH_HALF_S = 0x42,
610 REG_VIEWPORT_HEIGHT_HALF = 0x43,
611 REG_VIEWPORT_HEIGHT_HALF_S = 0x44,
612 REG_VIEWPORT_XY = 0x68
613 };
614
615 u16 x16 = static_cast<u16>(viewport.GetBound().GetX());
616 u16 y16 = static_cast<u16>(viewport.GetBound().GetY());
617
618 const u32 HEADER_VIEWPORT_WIDTH_HALF = nw::gfx::internal::MakeCommandHeader( REG_VIEWPORT_WIDTH_HALF, 4, true, 0xF );
619 const u32 HEADER_VIEWPORT_XY = nw::gfx::internal::MakeCommandHeader( REG_VIEWPORT_XY, 1, false, 0xF );
620
621 u32 VIEWPORT_COMMAND[] =
622 {
623 nw::ut::Float24::Float32ToBits24( viewport.GetBound().GetWidth() / 2.f ),
624 HEADER_VIEWPORT_WIDTH_HALF,
625 (ut::Float31::Float32ToBits31( 2.f / viewport.GetBound().GetWidth() ) << 1),
626 nw::ut::Float24::Float32ToBits24( viewport.GetBound().GetHeight()/2.f ),
627 (ut::Float31::Float32ToBits31( 2.f / viewport.GetBound().GetHeight() ) << 1),
628 0,
629 (x16 | (y16 << 16)),
630 HEADER_VIEWPORT_XY
631 };
632
633 nw::gfx::internal::NWUseCmdlist<sizeof(VIEWPORT_COMMAND)>( &VIEWPORT_COMMAND[0] );
634 }
635
636 //--------------------------------------------------------------------------
637 //! @brief レンダリングバッファサイズを指定します。
638 //!
639 //! @param[in] width レンダリングバッファの幅サイズです。
640 //! @param[in] height レンダリングバッファの縦サイズです。
641 //--------------------------------------------------------------------------
SetRenderBufferSize(s32 width,s32 height)642 static void SetRenderBufferSize(s32 width, s32 height)
643 {
644 s_RenderBufferWidth = width;
645 s_RenderBufferHeight = height;
646 }
647
648 //--------------------------------------------------------------------------
649 //! @brief シザリングの矩形情報を発行します。
650 //!
651 //! @param[in] enabled シザリングが有効化どうかのフラグです。
652 //! @param[in] scissor 設定するシザリング矩形です。
653 //--------------------------------------------------------------------------
ActivateScissor(bool enabled,const ut::Rect & scissor)654 static void ActivateScissor(bool enabled, const ut::Rect& scissor)
655 {
656 enum
657 {
658 REG_SCISSOR_ENABLE = 0x65,
659 REG_SCISSOR_XY = 0x66,
660 REG_SCISSOR_WH = 0x67,
661
662 REG_SCISSOR_DISABLED = 0,
663 REG_SCISSOR_ENABLED = 3
664 };
665
666 NW_MINMAX_ASSERT(scissor.GetX(), 0, static_cast<s32>(s_RenderBufferWidth));
667 NW_MINMAX_ASSERT(scissor.GetY(), 0, static_cast<s32>(s_RenderBufferHeight));
668 NW_MINMAX_ASSERT(scissor.GetX() + scissor.GetWidth(), 0, static_cast<s32>(s_RenderBufferWidth));
669 NW_MINMAX_ASSERT(scissor.GetY() + scissor.GetHeight(), 0, static_cast<s32>(s_RenderBufferHeight));
670
671 u16 x16 = static_cast<u16>(scissor.GetX());
672 u16 w16 = static_cast<u16>(scissor.GetWidth());
673 u16 y16 = static_cast<u16>(scissor.GetY());
674 u16 h16 = static_cast<u16>(scissor.GetHeight());
675
676 const u32 HEADER_SCISSOR = nw::gfx::internal::MakeCommandHeader( REG_SCISSOR_ENABLE, 3, true, 0xF );
677
678 u32 SCISSOR_COMMAND[] =
679 {
680 enabled ? REG_SCISSOR_ENABLED : REG_SCISSOR_DISABLED,
681 HEADER_SCISSOR,
682 enabled ? (x16 | (y16 << 16)) : 0,
683 enabled ? ((x16 + w16 - 1) | ((y16 + h16 - 1) << 16)) : ((s_RenderBufferWidth - 1) | ((s_RenderBufferHeight - 1) << 16)),
684 };
685
686 nw::gfx::internal::NWUseCmdlist<sizeof(SCISSOR_COMMAND)>( &SCISSOR_COMMAND[0] );
687 }
688
689
690 //---------------------------------------------------------------------------
691 //! @brief GraphicsDevice の状態を表示します。
692 //---------------------------------------------------------------------------
693 static void Report();
694
695 private:
696 //--------------------------------------------------------------------------
697 //! @brief LUT 転送の準備コマンドを送信します。
698 //!
699 //! @param[in] target LUTのタイプです。
700 //---------------------------------------------------------------------------
701 static NW_INLINE void ActivateLutLoadSetting(LutTarget target);
702
703 //! @brief フレームバッファコマンドを更新します。
704 static NW_INLINE void UpdateFrameBufferCommand();
705
706 static ResFragmentOperation::FragmentOperationMode s_FragOperationMode;
707 static bool s_IsFrameBufferUpdated;
708 static bool s_BlendEnabled;
709 static bool s_DepthTestEnabled;
710 static bool s_StencilTestEnabled;
711 static bool s_DepthMask;
712 static bool s_PolygonOffsetEnabled;
713 static u8 s_StencilMask;
714
715 static u32 s_ColorMask;
716
717 static u32 s_RenderBufferWidth;
718 static u32 s_RenderBufferHeight;
719
720 enum
721 {
722 COLOR_READ_MASK_INDEX = 4,
723 COLOR_WRITE_MASK_INDEX = 6,
724 DEPTH_READ_MASK_INDEX = 7,
725 DEPTH_WRITE_MASK_INDEX = 8,
726 FRAME_BUFFER_COMMAND_COUNT = 10
727 };
728
729 static u32 s_FrameBufferCommand[FRAME_BUFFER_COMMAND_COUNT];
730
731 static u32 s_LutIsAbs;
732 static u32 s_LutInput;
733 static u32 s_LutScale;
734
735 static u32 s_DepthFormat;
736 static u32 s_WScale24;
737 static f32 s_DepthRangeNear;
738 static f32 s_DepthRangeFar;
739 static u32 s_DepthRange24;
740 static f32 s_PolygonOffsetUnit;
741
742 static u32 s_LightPositionW;
743 static u32 s_LightShadowed;
744 static u32 s_LightSpotEnabled;
745 static u32 s_LightDistanceAttnEnabled;
746
747 static ResImageLookupTable m_LutTargets[LUT_TARGET_COUNT];
748 };
749
750
751 //----------------------------------------
752 NW_INLINE void
SetBlendEnabled(bool enabled)753 GraphicsDevice::SetBlendEnabled(bool enabled)
754 {
755 s_IsFrameBufferUpdated = s_IsFrameBufferUpdated || (s_BlendEnabled != enabled);
756 s_BlendEnabled = enabled;
757 }
758
759 //----------------------------------------
760 NW_INLINE void
SetStencilTestEnabled(bool enabled)761 GraphicsDevice::SetStencilTestEnabled(bool enabled)
762 {
763 s_IsFrameBufferUpdated = s_IsFrameBufferUpdated || (s_StencilTestEnabled != enabled);
764 s_StencilTestEnabled = enabled;
765 }
766
767 //----------------------------------------
768 NW_INLINE void
SetDepthTestEnabled(bool enabled)769 GraphicsDevice::SetDepthTestEnabled(bool enabled)
770 {
771 s_IsFrameBufferUpdated = s_IsFrameBufferUpdated || (s_DepthTestEnabled != enabled);
772 s_DepthTestEnabled = enabled;
773 }
774
775
776 //----------------------------------------
777 NW_INLINE void
ActivateMask()778 GraphicsDevice::ActivateMask()
779 {
780 enum RegColorMask
781 {
782 REG_COLOR_MASK_ADDR = 0x107,
783 REG_COLOR_MASK_SHIFT = 8,
784 REG_DEPTH_MASK_SHIFT = 12,
785 REG_STENCIL_MASK_ADDR = 0x105,
786 REG_STENCIL_MASK_SHIFT = 8
787 };
788
789 const u32 COLOR_MASK_HEADER =
790 internal::MakeCommandHeader(REG_COLOR_MASK_ADDR, 1, false, 0x2);
791
792 const u32 STENCIL_MASK_HEADER =
793 internal::MakeCommandHeader(REG_STENCIL_MASK_ADDR, 1, false, 0x2);
794
795 const u32 COMMAND[] =
796 {
797 s_ColorMask << REG_COLOR_MASK_SHIFT | s_DepthMask << REG_DEPTH_MASK_SHIFT,
798 COLOR_MASK_HEADER,
799 s_StencilMask << REG_STENCIL_MASK_SHIFT,
800 STENCIL_MASK_HEADER
801 };
802
803 internal::NWUseCmdlist<sizeof(COMMAND)>(&COMMAND[0]);
804 }
805
806 //----------------------------------------
807 NW_INLINE void
ActivateFrameBuffer()808 GraphicsDevice::ActivateFrameBuffer()
809 {
810 if (s_IsFrameBufferUpdated)
811 {
812 s_IsFrameBufferUpdated = false;
813
814 UpdateFrameBufferCommand();
815 }
816
817 internal::NWUseCmdlist(&s_FrameBufferCommand[0], sizeof(s_FrameBufferCommand));
818 }
819
820 //----------------------------------------
821 void NW_INLINE
UpdateFrameBufferCommand()822 GraphicsDevice::UpdateFrameBufferCommand()
823 {
824 enum
825 {
826 COLOR_MASK_ALL = 0xF,
827 COLOR_ACCESS_ENABLE = 0xF,
828 DEPTH_ACCESS_ENABLE = 0x2,
829 STENCIL_ACCESS_ENABLE = 0x1
830 };
831
832 s_FrameBufferCommand[COLOR_READ_MASK_INDEX] = 0;
833 s_FrameBufferCommand[COLOR_WRITE_MASK_INDEX] = 0;
834
835 // カラーバッファのリードとライト設定
836 if (s_FragOperationMode != ResFragmentOperation::FRAGMENT_OPERATION_MODE_GL)
837 {
838 s_FrameBufferCommand[COLOR_READ_MASK_INDEX] = COLOR_ACCESS_ENABLE;
839 s_FrameBufferCommand[COLOR_WRITE_MASK_INDEX] = COLOR_ACCESS_ENABLE;
840 }
841 else if (s_ColorMask)
842 {
843 if (s_BlendEnabled || (s_ColorMask != COLOR_MASK_ALL))
844 {
845 s_FrameBufferCommand[COLOR_READ_MASK_INDEX] = COLOR_ACCESS_ENABLE;
846 }
847
848 s_FrameBufferCommand[COLOR_WRITE_MASK_INDEX] = COLOR_ACCESS_ENABLE;
849 }
850
851 s_FrameBufferCommand[DEPTH_READ_MASK_INDEX] = 0;
852 s_FrameBufferCommand[DEPTH_WRITE_MASK_INDEX] = 0;
853 if (s_FragOperationMode == ResFragmentOperation::FRAGMENT_OPERATION_MODE_GAS)
854 {
855 s_FrameBufferCommand[DEPTH_READ_MASK_INDEX] = DEPTH_ACCESS_ENABLE | STENCIL_ACCESS_ENABLE;
856 }
857 else if (s_FragOperationMode == ResFragmentOperation::FRAGMENT_OPERATION_MODE_GL)
858 {
859 // デプスバッファのリードとライト設定
860 if (s_DepthTestEnabled)
861 {
862 if (s_DepthMask)
863 {
864 s_FrameBufferCommand[DEPTH_READ_MASK_INDEX] = DEPTH_ACCESS_ENABLE;
865 s_FrameBufferCommand[DEPTH_WRITE_MASK_INDEX] = DEPTH_ACCESS_ENABLE;
866 }
867 else if (s_ColorMask)
868 {
869 s_FrameBufferCommand[DEPTH_READ_MASK_INDEX] = DEPTH_ACCESS_ENABLE;
870 }
871 }
872
873 // ステンシルバッファのリードとライト設定
874 if (s_StencilTestEnabled)
875 {
876 if (s_StencilMask)
877 {
878 s_FrameBufferCommand[DEPTH_READ_MASK_INDEX] |= STENCIL_ACCESS_ENABLE;
879 s_FrameBufferCommand[DEPTH_WRITE_MASK_INDEX] |= STENCIL_ACCESS_ENABLE;
880 }
881 else if (s_ColorMask)
882 {
883 s_FrameBufferCommand[DEPTH_READ_MASK_INDEX] |= STENCIL_ACCESS_ENABLE;
884 }
885 }
886 }
887 }
888
889 //----------------------------------------
890 NW_INLINE void
ActivateLutLoadSetting(LutTarget target)891 GraphicsDevice::ActivateLutLoadSetting(LutTarget target)
892 {
893 enum { REG_PICA_LIGHTING_LUT_SETTING = 0x1C5, REG_PICA_FOG_LUT_SETTING = 0x0e6 };
894
895 const u32 LIGHTING_HEADER = internal::MakeCommandHeader(REG_PICA_LIGHTING_LUT_SETTING, 1, false, 0xF);
896 const u32 FOG_HEADER = internal::MakeCommandHeader(REG_PICA_FOG_LUT_SETTING, 1, false, 0xF);
897
898
899 if (target == LUT_TARGET_FOG)
900 {
901 u32 LUT_COMMAND[2] =
902 {
903 0,
904 FOG_HEADER
905 };
906
907 internal::NWUseCmdlist<sizeof(LUT_COMMAND)>( &LUT_COMMAND[0] );
908 return;
909 }
910
911 int targetReg = 0;
912 // スポットと距離減衰はtarget+1のレジスタに設定する。
913 if (target < LUT_TARGET_SP0)
914 {
915 targetReg = static_cast<int>(target);
916 }
917 else
918 {
919 targetReg = static_cast<int>(target) + 1;
920 }
921
922 u32 LUT_COMMAND[2] =
923 {
924 targetReg << 8,
925 LIGHTING_HEADER
926 };
927
928 internal::NWUseCmdlist<sizeof(LUT_COMMAND)>( &LUT_COMMAND[0] );
929 }
930
931 //----------------------------------------
932 NW_INLINE void
ActivatePolygonOffset()933 GraphicsDevice::ActivatePolygonOffset()
934 {
935 // PolygonOffset の設定
936 enum
937 {
938 REG_POLYGON_OFFSET = 0x4d,
939 REG_WSCALE_ENABLE = 0x6d
940 };
941
942 const u32 OFFSET_HEADER = internal::MakeCommandHeader(REG_POLYGON_OFFSET, 2, true, 0x7);
943 const u32 WSCALE_HEADER = internal::MakeCommandHeader(REG_WSCALE_ENABLE, 1, false, 0x1);
944
945 static u32 COMMAND[] =
946 {
947 0,
948 WSCALE_HEADER,
949 0,
950 OFFSET_HEADER,
951 0,
952 0
953 };
954
955 f32 zBias;
956 f32 offset;
957
958 if (s_WScale24 == 0)
959 {
960 COMMAND[0] = 1;
961 COMMAND[2] = s_DepthRange24;
962
963 zBias = s_DepthRangeNear;
964 offset = (s_DepthRangeNear - s_DepthRangeFar) * s_PolygonOffsetUnit;
965 }
966 else
967 {
968 COMMAND[0] = 0;
969 COMMAND[2] = s_WScale24;
970
971 zBias = 0.0f;
972 offset = -s_PolygonOffsetUnit;
973 }
974
975 // DMP のドキュメントでは wScale が有効な際には PolygonOffset が効かない仕様になっていますが、
976 // W-Buffering 時にも PolygonOffset の需要がある為、Z-Buffering と同様に設定します。
977 if (s_PolygonOffsetEnabled)
978 {
979 if (s_DepthFormat == RENDER_DEPTH_FORMAT_16)
980 {
981 zBias -= offset / 65535.0f;
982 }
983 else
984 {
985 // 24bit 浮動小数(仮数16bit)の精度限界により、誤差で消えてしまう為
986 // 精度が問題にならないような定数値を掛けておく必要があります。
987 // 0.5f 付近の深度を基準として 128.0f を掛けておく事にします。
988
989 zBias -= offset * 128.0f / 16777215.0f;
990 }
991 }
992
993 COMMAND[4] = ut::Float24::Float32ToBits24(zBias);
994
995 internal::NWUseCmdlist<sizeof(COMMAND)>( &COMMAND[0] );
996 }
997
998 //----------------------------------------
999 NW_INLINE void
SetColorMask(bool red,bool green,bool blue,bool alpha)1000 GraphicsDevice::SetColorMask(bool red, bool green, bool blue, bool alpha)
1001 {
1002 u32 colorMask = u32(red) |
1003 (u32(green) << 1) |
1004 (u32(blue) << 2) |
1005 (u32(alpha) << 3);
1006
1007 s_IsFrameBufferUpdated = s_IsFrameBufferUpdated || (s_ColorMask != colorMask);
1008 s_ColorMask = colorMask;
1009 }
1010
1011 //----------------------------------------
1012 NW_INLINE void
SetDepthMaskEnabled(bool enabled)1013 GraphicsDevice::SetDepthMaskEnabled(bool enabled)
1014 {
1015 s_IsFrameBufferUpdated = s_IsFrameBufferUpdated || (s_DepthMask != enabled);
1016 s_DepthMask = enabled;
1017 }
1018
1019 //----------------------------------------
1020 NW_INLINE void
SetStencilMask(u8 mask)1021 GraphicsDevice::SetStencilMask(u8 mask)
1022 {
1023 s_IsFrameBufferUpdated = s_IsFrameBufferUpdated || (s_StencilMask != mask);
1024 s_StencilMask = mask;
1025 }
1026
1027 } // namespace gfx
1028 } // namespace nw
1029
1030 #endif // NW_GFX_GRAPHICSDEVICE_H_
1031