1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: gfx_FrameBuffer.cpp
4
5 Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Revision: 13145 $
14 *---------------------------------------------------------------------------*/
15
16 #include "precompiled.h"
17
18 #include <gles2/gl2.h>
19 #include <nn/gx.h>
20 #include <nn/gx/CTR/gx_MacroReg.h>
21 #include <nw/gfx/gfx_FrameBuffer.h>
22 #include <nw/gfx/gfx_GlImplement.h>
23
24 namespace nw {
25 namespace gfx {
26
27 //---------------------------------------------------------------------------
28 //! @brief FloatColor から RGBA8 へ変換します。
29 //!
30 //! @param[in] color FloatColor の値です。
31 //!
32 //! @return RGBA8 の値です。
33 //---------------------------------------------------------------------------
34 static inline u32
ColorToRGBA8(const ut::FloatColor & color)35 ColorToRGBA8( const ut::FloatColor& color )
36 {
37 // RGBA8 の Picaネイティブフォーマットではエンディアンを反転する必要がある。
38
39 u8 red = static_cast<u8>( 0.5f + nw::ut::Clamp(color.r, 0.0f, 1.0f) * 255.f );
40 u8 green = static_cast<u8>( 0.5f + nw::ut::Clamp(color.g, 0.0f, 1.0f) * 255.f );
41 u8 blue = static_cast<u8>( 0.5f + nw::ut::Clamp(color.b, 0.0f, 1.0f) * 255.f );
42 u8 alpha = static_cast<u8>( 0.5f + nw::ut::Clamp(color.a, 0.0f, 1.0f) * 255.f );
43
44 return (alpha) | (blue << 8) | (green << 16) | (red << 24);
45 }
46
47
48 //---------------------------------------------------------------------------
49 //! @brief FloatColor から RGB5A1 へ変換します。
50 //!
51 //! @param[in] color FloatColor の値です。
52 //!
53 //! @return RGB5A1 の値です。
54 //---------------------------------------------------------------------------
55 static inline u16
ColorToRGB5A1(const ut::FloatColor & color)56 ColorToRGB5A1( const ut::FloatColor& color )
57 {
58 u8 red = static_cast<u8>( 0.5f + nw::ut::Clamp(color.r, 0.0f, 1.0f) * 31.f );
59 u8 green = static_cast<u8>( 0.5f + nw::ut::Clamp(color.g, 0.0f, 1.0f) * 31.f );
60 u8 blue = static_cast<u8>( 0.5f + nw::ut::Clamp(color.b, 0.0f, 1.0f) * 31.f );
61 u8 alpha = static_cast<u8>( 0.5f + nw::ut::Clamp(color.a, 0.0f, 1.0f) * 1.f );
62
63 return static_cast<u16>( (alpha) | (blue << 1) | (green << 6) | (red << 11) );
64 }
65
66
67 //---------------------------------------------------------------------------
68 //! @brief FloatColor から RGB565 へ変換します。
69 //!
70 //! @param[in] color FloatColor の値です。
71 //!
72 //! @return RGB565 の値です。
73 //---------------------------------------------------------------------------
74 static inline u16
ColorToRGB565(const ut::FloatColor & color)75 ColorToRGB565( const ut::FloatColor& color )
76 {
77 u8 red = static_cast<u8>( 0.5f + nw::ut::Clamp(color.r, 0.0f, 1.0f) * 31.f );
78 u8 green = static_cast<u8>( 0.5f + nw::ut::Clamp(color.g, 0.0f, 1.0f) * 63.f );
79 u8 blue = static_cast<u8>( 0.5f + nw::ut::Clamp(color.b, 0.0f, 1.0f) * 31.f );
80
81 return static_cast<u16>( (blue) | (green << 5) | (red << 11) );
82 }
83
84
85 //---------------------------------------------------------------------------
86 //! @brief FloatColor から RGBA4 へ変換します。
87 //!
88 //! @param[in] color FloatColor の値です。
89 //!
90 //! @return RGBA4 の値です。
91 //---------------------------------------------------------------------------
92 static inline u16
ColorToRGBA4(const ut::FloatColor & color)93 ColorToRGBA4( const ut::FloatColor& color )
94 {
95 u8 red = static_cast<u8>( 0.5f + nw::ut::Clamp(color.r, 0.0f, 1.0f) * 15.f );
96 u8 green = static_cast<u8>( 0.5f + nw::ut::Clamp(color.g, 0.0f, 1.0f) * 15.f );
97 u8 blue = static_cast<u8>( 0.5f + nw::ut::Clamp(color.b, 0.0f, 1.0f) * 15.f );
98 u8 alpha = static_cast<u8>( 0.5f + nw::ut::Clamp(color.a, 0.0f, 1.0f) * 15.f );
99
100 return static_cast<u16>( (alpha) | (blue << 4) | (green << 8) | (red << 12) );
101 }
102
103
104 //---------------------------------------------------------------------------
105 void
SetDescription(const Description & description)106 FrameBufferObject::SetDescription(const Description& description)
107 {
108 m_Description = description;
109
110 if (description.fboID == 0)
111 {
112 this->SetFboID(description.fboID);
113 }
114 else
115 {
116 m_Description = description;
117 }
118 }
119
120 //---------------------------------------------------------------------------
121 void
SetFboID(GLuint fboID)122 FrameBufferObject::SetFboID(GLuint fboID)
123 {
124 m_Description.fboID = fboID;
125
126 if (fboID != 0)
127 {
128 internal::GetFrameBufferState(
129 m_Description.fboID,
130 &m_Description.colorAddress,
131 &m_Description.depthAddress
132 );
133 }
134 }
135
136
137 //---------------------------------------------------------------------------
138 void
ActivateBuffer() const139 FrameBufferObject::ActivateBuffer() const
140 {
141 const FrameBufferObject::Description& description = this->GetDescription();
142
143 #if 0
144 // 後で gl で描画する場合の事を考慮していたが、
145 // gl を使って描画する場合には自前で、glBindFramebuffer も呼んでもらうことにする。
146 if ( description.fboID != 0 )
147 {
148 glBindFramebuffer( GL_FRAMEBUFFER, description.fboID );
149 }
150 #endif
151
152 {
153 NW_ALIGN_ASSERT( description.depthAddress, 0x8 );
154 NW_ALIGN_ASSERT( description.colorAddress, 0x8 );
155 NW_ALIGN_ASSERT( description.height, 0x8 );
156 NW_ALIGN_ASSERT( description.width, 0x8 );
157 NW_ASSERT( description.height <= 1024 );
158 NW_ASSERT( description.width <= 1024 );
159
160 u32 depthFormat = 0;
161 u32 colorFormat = 0;
162
163 switch ( description.depthFormat )
164 {
165 case GL_DEPTH_COMPONENT16: depthFormat = 0; break;
166 case GL_DEPTH_COMPONENT24_OES: depthFormat = 2; break;
167 case GL_DEPTH24_STENCIL8_EXT: depthFormat = 3; break;
168 default:
169 // デプスバッファを使用しない場合のみ、ここを通る。
170 NW_ASSERTMSG( description.depthAddress == NULL, "Unknown depth format" );
171 }
172
173 switch ( description.colorFormat )
174 {
175 case GL_RGBA8_OES: colorFormat = (0 << 16) | 0x2; break;
176 case GL_GAS_DMP: colorFormat = (0 << 16) | 0x2; break;
177 case GL_RGB5_A1: colorFormat = (2 << 16); break;
178 case GL_RGB565: colorFormat = (3 << 16); break;
179 case GL_RGBA4: colorFormat = (4 << 16); break;
180 default:
181 // カラーバッファを使用しない場合のみ、ここを通る。
182 NW_ASSERTMSG( description.colorAddress == NULL, "Unknown color format" );
183 }
184
185 if (description.depthAddress == NULL)
186 {
187 u32 COMMAND[] =
188 {
189 0x1,
190 internal::MakeCommandHeader( PICA_REG_COLOR_DEPTH_BUFFER_CLEAR1, 1, false, 0xf ),
191 0x1,
192 internal::MakeCommandHeader( PICA_REG_COLOR_DEPTH_BUFFER_CLEAR0, 1, false, 0xf ),
193
194 colorFormat,
195 internal::MakeCommandHeader( PICA_REG_RENDER_BUFFER_COLOR_MODE, 1, false, 0xf ),
196
197 (description.colorAddress != NULL) ? (nngxGetPhysicalAddr( description.colorAddress ) >> 3) : 0,
198 internal::MakeCommandHeader( PICA_REG_RENDER_BUFFER_COLOR_ADDR, 1, false, 0xf ),
199
200 description.width | ((description.height - 1) << 12) | 0x01000000,
201 internal::MakeCommandHeader( PICA_REG_RENDER_BUFFER_RESOLUTION0, 1, false, 0xf ),
202
203 description.width | ((description.height - 1) << 12) | 0x01000000,
204 internal::MakeCommandHeader( PICA_REG_RENDER_BUFFER_RESOLUTION1, 1, false, 0xf ),
205
206 (description.useBlock32)? 1 : 0,
207 internal::MakeCommandHeader( PICA_REG_RENDER_BLOCK_FORMAT, 1, false, 0xf ),
208 };
209
210 internal::NWUseCmdlist<sizeof(COMMAND)>( &COMMAND[0] );
211 }
212 else
213 {
214 u32 COMMAND[] =
215 {
216 0x1,
217 internal::MakeCommandHeader( PICA_REG_COLOR_DEPTH_BUFFER_CLEAR1, 1, false, 0xf ),
218 0x1,
219 internal::MakeCommandHeader( PICA_REG_COLOR_DEPTH_BUFFER_CLEAR0, 1, false, 0xf ),
220
221 (description.depthAddress != NULL) ? (nngxGetPhysicalAddr( description.depthAddress ) >> 3) : 0,
222 internal::MakeCommandHeader( PICA_REG_RENDER_BUFFER_DEPTH_ADDR, 3, true, 0xf ),
223 (description.colorAddress != NULL) ? (nngxGetPhysicalAddr( description.colorAddress ) >> 3) : 0,
224 description.width | ((description.height - 1) << 12) | 0x01000000,
225
226 description.width | ((description.height - 1) << 12) | 0x01000000,
227 internal::MakeCommandHeader( PICA_REG_RENDER_BUFFER_RESOLUTION1, 1, false, 0xf ),
228
229 depthFormat,
230 internal::MakeCommandHeader( PICA_REG_RENDER_BUFFER_DEPTH_MODE, 1, false, 0xf ),
231
232 colorFormat,
233 internal::MakeCommandHeader( PICA_REG_RENDER_BUFFER_COLOR_MODE, 1, false, 0xf ),
234
235 (description.useBlock32)? 1 : 0,
236 internal::MakeCommandHeader( PICA_REG_RENDER_BLOCK_FORMAT, 1, false, 0xf ),
237 };
238
239 internal::NWUseCmdlist<sizeof(COMMAND)>( &COMMAND[0] );
240 }
241 }
242 }
243
244 //---------------------------------------------------------------------------
245 void
ClearBuffer(u32 mask,const ut::FloatColor & clearColor,f32 clearDepth,u8 clearStencil) const246 FrameBufferObject::ClearBuffer(
247 u32 mask,
248 const ut::FloatColor& clearColor,
249 f32 clearDepth,
250 u8 clearStencil /* = 0 */
251 ) const
252 {
253 const FrameBufferObject::Description& description = this->GetDescription();
254
255 u32 colorAddress = 0;
256 u32 depthAddress = 0;
257 u32 colorWidth = 0;
258 u32 depthWidth = 0;
259 u32 clearColorHW = 0;
260 u32 clearDepthHW = 0;
261 u32 colorSize = 0;
262 u32 depthSize = 0;
263
264 if ( mask & CLEAR_MASK_COLOR )
265 {
266 colorAddress = description.colorAddress;
267
268 switch ( description.colorFormat )
269 {
270 case GL_RGBA8_OES:
271 {
272 colorWidth = 32;
273 clearColorHW = ColorToRGBA8( clearColor );
274 }
275 break;
276 case GL_GAS_DMP:
277 {
278 colorWidth = 32;
279 // clearColorHW = clearColor.ToPicaU32();
280 clearColorHW = ColorToRGBA8( clearColor );
281 }
282 break;
283 case GL_RGB5_A1:
284 {
285 colorWidth = 16;
286 clearColorHW = ColorToRGB5A1( clearColor );
287 clearColorHW = (clearColorHW << 16) | clearColorHW;
288 }
289 break;
290 case GL_RGB565:
291 {
292 colorWidth = 16;
293 clearColorHW = ColorToRGB565( clearColor );
294 clearColorHW = (clearColorHW << 16) | clearColorHW;
295 }
296 break;
297 case GL_RGBA4:
298 {
299 colorWidth = 16;
300 clearColorHW = ColorToRGBA4( clearColor );
301 clearColorHW = (clearColorHW << 16) | clearColorHW;
302 }
303 break;
304 default:
305 NW_FATAL_ERROR("Unknown color format");
306 }
307
308 colorSize = description.height * description.width * colorWidth / 8;
309 }
310
311 if (mask & CLEAR_MASK_DEPTH)
312 {
313 depthAddress = description.depthAddress;
314
315 if ( depthAddress == 0 )
316 {
317 depthWidth = 0;
318 clearDepthHW = 0;
319 }
320 else
321 {
322 switch ( description.depthFormat )
323 {
324 case GL_DEPTH_COMPONENT16:
325 {
326 depthWidth = 16;
327 clearDepthHW = static_cast<u16>( nw::ut::Clamp(clearDepth, 0.0f, 1.0f) * static_cast<f32>(0xFFFF) );
328 clearDepthHW = (clearDepthHW << 16) | clearDepthHW;
329 }
330 break;
331 case GL_DEPTH_COMPONENT24_OES:
332 {
333 depthWidth = 24;
334 clearDepthHW = static_cast<u32>( nw::ut::Clamp(clearDepth, 0.0f, 1.0f) * static_cast<f32>(0xFFFFFF) );
335 }
336 break;
337 case GL_DEPTH24_STENCIL8_EXT:
338 {
339 depthWidth = 32;
340 clearDepthHW = static_cast<u32>( nw::ut::Clamp(clearDepth, 0.0f, 1.0f) * static_cast<f32>(0xFFFFFF) );
341 clearDepthHW |= clearStencil << 24;
342 }
343 break;
344 default:
345 NW_FATAL_ERROR("Unknown depth format");
346 }
347 }
348
349 depthSize = description.height * description.width * depthWidth / 8;
350 }
351
352 internal::nwgfxClear( colorAddress, colorSize, clearColorHW, colorWidth,
353 depthAddress, depthSize, clearDepthHW, depthWidth );
354 }
355
356
357 } // namespace gfx
358 } // namespace nw
359