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