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