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