1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     gfx_ResShape.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: 16971 $
14  *---------------------------------------------------------------------------*/
15 
16 #include "../precompiled.h"
17 
18 #include <nw/ut/ut_ResUtil.h>
19 #include <nw/ut/ut_ResDictionary.h>
20 #include <nw/gfx/gfx_SceneObject.h>
21 #include <nw/gfx/res/gfx_ResShape.h>
22 #include <nw/gfx/res/gfx_ResParticleShape.h>
23 #include <nw/gfx/res/gfx_ResTexture.h>
24 #include <nw/gfx/gfx_Common.h>
25 #include <GLES2/gl2.h>
26 #include <GLES2/gl2ext.h>
27 #include <nw/gfx/gfx_CommandUtil.h>
28 
29 #include <nn/gx.h>
30 
31 namespace nw {
32 namespace gfx {
33 namespace res {
34 
35 typedef void (*BindFunc)(ResShape resShape);
36 
37 static void ResShape_Setup(ResShape resShape);
38 static void ResSeparateDataShape_Setup(ResShape resShape);
39 static void ResParticleShape_Setup(ResShape resShape);
40 
41 static void ResShape_Cleanup(ResShape resShape);
42 static void ResSeparateDataShape_Cleanup(ResShape resShape);
43 static void ResParticleShape_Cleanup(ResShape resShape);
44 
45 static BindFunc sShape_SetupTable[] =
46 {
47     ResSeparateDataShape_Setup,
48     ResParticleShape_Setup
49 };
50 
51 static BindFunc sShape_CleanupTable[] =
52 {
53     ResSeparateDataShape_Cleanup,
54     ResParticleShape_Cleanup
55 };
56 
57 
58 
59 //---------------------------------------------------------------------------
60 //! @brief        必要であれば頂点バッファのコピー用のメモリを確保し、転送をおこないます。
61 //!
62 //! @param[in]    bufferID     メモリ確保用の頂点バッファIDです。
63 //! @param[in]    resStream    頂点ストリームリソースです。
64 //! @param[in]    loadFlag     頂点バッファの配置メモリフラグです。
65 //---------------------------------------------------------------------------
66 static void
BufferData(u32 bufferID,ResIndexStream resStream,u32 loadFlag)67 BufferData( u32 bufferID, ResIndexStream resStream, u32 loadFlag )
68 {
69     u32 size = resStream.GetStreamCount();
70     GLenum transtype = loadFlag & 0xFFFF0000;
71     void* address = NULL;
72     const u32 NN_GX_MEM_MASK = 0x00030000;
73 
74     switch (transtype)
75     {
76     case (NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP):
77         nngxUpdateBuffer( resStream.GetStream(), size );
78         break;
79 
80     case (NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP):
81     case (NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP):
82         {
83             GLuint area = (transtype & NN_GX_MEM_MASK);
84             address = __dmpgl_allocator(area, NN_GX_MEM_VERTEXBUFFER, bufferID, size);
85             nngxUpdateBuffer( resStream.GetStream(), size );
86             internal::nwgfxAddVramDmaCommand( resStream.GetStream(), address, size );
87 
88             resStream.SetLocationAddress( address );
89             resStream.ref().m_MemoryArea = area;
90         }
91         break;
92 
93     case (NN_GX_MEM_FCRAM | GL_COPY_FCRAM_DMP):
94         {
95             address = __dmpgl_allocator(NN_GX_MEM_FCRAM, NN_GX_MEM_VERTEXBUFFER, bufferID, size);
96             std::memcpy( address, resStream.GetStream(), size );
97             nngxUpdateBuffer( address, size );
98 
99             resStream.SetLocationAddress( address );
100             resStream.ref().m_MemoryArea = NN_GX_MEM_FCRAM;
101         }
102         break;
103 
104     case (NN_GX_MEM_VRAMA | GL_COPY_FCRAM_DMP):
105     case (NN_GX_MEM_VRAMB | GL_COPY_FCRAM_DMP):
106         NW_FATAL_ERROR("GL_COPY_DMA is not supported!");
107         break;
108 
109     default:
110         break;
111     }
112 }
113 
114 //---------------------------------------------------------------------------
115 //! @brief        コピーした頂点情報を開放します。
116 //!
117 //! @param[in]    bufferID  バッファオブジェクトIDです。
118 //! @param[in]    resStream
119 //---------------------------------------------------------------------------
120 static void
DeleteBuffer(u32 bufferID,ResIndexStream resStream)121 DeleteBuffer( u32 bufferID, ResIndexStream resStream )
122 {
123     GLuint area = resStream.ref().m_MemoryArea;
124 
125     if (area != ResIndexStreamData::AREA_NO_MALLOC)
126     {
127         void* address = reinterpret_cast<void*>( resStream.GetLocationAddress() );
128         __dmpgl_deallocator( area, NN_GX_MEM_VERTEXBUFFER, bufferID, address );
129         resStream.SetLocationAddress( static_cast<u32>(NULL) );
130     }
131 }
132 
133 
134 //----------------------------------------
135 Result
Setup()136 ResShape::Setup()
137 {
138     Result result = RESOURCE_RESULT_OK;
139     switch ( this->ref().typeInfo )
140     {
141     case ResSeparateDataShape::TYPE_INFO:
142         {
143             sShape_SetupTable[0]( *this );
144             this->SetFlags(ut::EnableFlag(this->GetFlags(), ResShape::FLAG_HAS_BEEN_SETUP));
145         }
146         break;
147     case ResParticleShape::TYPE_INFO:
148         {
149             sShape_SetupTable[1]( *this );
150             this->SetFlags(ut::EnableFlag(this->GetFlags(), ResShape::FLAG_HAS_BEEN_SETUP));
151         }
152         break;
153     default:
154         {
155         }
156     }
157     return result;
158 }
159 
160 
161 /*!--------------------------------------------------------------------------*
162   Name:         ResShape_Setup
163 
164   @brief        シェイプのリソース初期化をおこないます。
165 
166   @param[in]    resShape シェイプリソースです。
167 
168   @return       なし。
169  *---------------------------------------------------------------------------*/
170 static void
ResShape_Setup(ResShape resShape)171 ResShape_Setup(ResShape resShape)
172 {
173     s32 primSetNum = resShape.GetPrimitiveSetsCount();
174 
175     for ( s32 i = 0; i < primSetNum; ++i )
176     {
177         resShape.GetPrimitiveSets( i ).Setup();
178     }
179 }
180 
181 
182 /*!--------------------------------------------------------------------------*
183   Name:         ResSeparateDataShape_Setup
184 
185   @brief        複数属性シェイプのリソース初期化をおこないます。
186 
187   @param[in]    resShape シェイプリソースです。
188 
189   @return       なし。
190  *---------------------------------------------------------------------------*/
191 static void
ResSeparateDataShape_Setup(ResShape resShape)192 ResSeparateDataShape_Setup(ResShape resShape)
193 {
194     ResShape_Setup( resShape );
195 
196     ResSeparateDataShape resSeparateShape = ResStaticCast<ResSeparateDataShape>( resShape );
197 
198     s32 vtxAttrNum = resSeparateShape.GetVertexAttributesCount();
199     for ( s32 i = 0; i < vtxAttrNum; ++ i )
200     {
201         resSeparateShape.GetVertexAttributes( i ).Setup();
202     }
203 }
204 
205 
206 /*!--------------------------------------------------------------------------*
207   Name:         ResParticleShape_Setup
208 
209   @brief        パーティクルシェイプのリソース初期化をおこないます。
210 
211   @param[in]    resShape シェイプリソースです。
212 
213   @return       なし。
214  *---------------------------------------------------------------------------*/
215 static void
ResParticleShape_Setup(ResShape resShape)216 ResParticleShape_Setup(ResShape resShape)
217 {
218     NW_UNUSED_VARIABLE(resShape);
219 }
220 
221 
222 /*!--------------------------------------------------------------------------*
223   Name:         ResPrimitiveSet::Setup
224 
225   @brief        リソースの初期化をおこないます。
226 
227   @return       なし。
228  *---------------------------------------------------------------------------*/
229 void
Setup()230 ResPrimitiveSet::Setup()
231 {
232     NW_ASSERT( this->IsValid() );
233 
234     ResPrimitiveArray primitiveArray = this->GetPrimitives();
235 
236     for (ResPrimitiveArray::iterator it = primitiveArray.begin(); it != primitiveArray.end(); ++it)
237     {
238         (*it).Setup();
239     }
240 }
241 
242 
243 /*!--------------------------------------------------------------------------*
244   Name:         ResPrimitive::Setup
245 
246   @brief        リソースの初期化をおこないます。
247 
248   @return       なし。
249  *---------------------------------------------------------------------------*/
250 void
Setup()251 ResPrimitive::Setup()
252 {
253     NW_ASSERT( this->IsValid() );
254 
255     u32 streamNum = this->GetIndexStreamsCount();
256 
257     GLuint* bufferObjects = reinterpret_cast<GLuint*>( this->GetBufferObjects() );
258 
259     for ( uint i = 0; i < streamNum; ++i )
260     {
261         ResIndexStream resStream = this->GetIndexStreams( u32(i) );
262         bufferObjects[ i ] = reinterpret_cast<u32>(resStream.ptr());
263 
264         if (resStream.GetLocationAddress() != NULL)
265         {
266             resStream.ref().m_MemoryArea = ResIndexStreamData::AREA_NO_MALLOC;
267             continue;
268         }
269 
270         u32   size = resStream.GetStreamCount();
271         void* buf  = resStream.GetStream();
272 
273         // 頂点インデックスバッファのメモリへの読み込み指定
274         int loadFlag = resStream.GetLocationFlag();
275 
276         // デフォルトは、FCRAM から NO_COPY。
277         if (loadFlag == 0)
278         {
279             loadFlag = NN_GX_MEM_FCRAM | GL_NO_COPY_FCRAM_DMP;
280         }
281 
282         BufferData( bufferObjects[ i ], resStream, loadFlag );
283     }
284     NW_GL_ASSERT();
285 }
286 
287 
288 //----------------------------------------
289 void
Cleanup()290 ResShape::Cleanup()
291 {
292     switch ( this->ref().typeInfo )
293     {
294     case ResSeparateDataShape::TYPE_INFO:
295         {
296             sShape_CleanupTable[0]( *this );
297             this->SetFlags(ut::DisableFlag(this->GetFlags(), ResShape::FLAG_HAS_BEEN_SETUP));
298         }
299         break;
300     case ResParticleShape::TYPE_INFO:
301         {
302             sShape_CleanupTable[1]( *this );
303             this->SetFlags(ut::DisableFlag(this->GetFlags(), ResShape::FLAG_HAS_BEEN_SETUP));
304         }
305         break;
306     default:
307         {
308         }
309     }
310 }
311 
312 //----------------------------------------
313 static void
ResShape_Cleanup(ResShape resShape)314 ResShape_Cleanup(ResShape resShape)
315 {
316     s32 primSetNum = resShape.GetPrimitiveSetsCount();
317 
318     for ( s32 i = 0; i < primSetNum; ++i )
319     {
320         resShape.GetPrimitiveSets( i ).Cleanup();
321     }
322 }
323 
324 //----------------------------------------
325 static void
ResSeparateDataShape_Cleanup(ResShape resShape)326 ResSeparateDataShape_Cleanup(ResShape resShape)
327 {
328     ResSeparateDataShape resSeparateShape = ResStaticCast<ResSeparateDataShape>( resShape );
329 
330     s32 vtxAttrNum = resSeparateShape.GetVertexAttributesCount();
331 
332     for ( s32 i = 0; i < vtxAttrNum; ++ i )
333     {
334         resSeparateShape.GetVertexAttributes( i ).Cleanup();
335     }
336 
337     ResShape_Cleanup( resShape );
338 }
339 
340 //----------------------------------------
341 static void
ResParticleShape_Cleanup(ResShape resShape)342 ResParticleShape_Cleanup(ResShape resShape)
343 {
344     ResParticleShape resParticleShape = ResStaticCast<ResParticleShape>( resShape );
345 }
346 
347 
348 //------------------------------------------------------------------------------
349 void
Cleanup()350 ResPrimitiveSet::Cleanup()
351 {
352     NW_ASSERT( this->IsValid() );
353 
354     ResPrimitiveArray primitiveArray = this->GetPrimitives();
355 
356     for (ResPrimitiveArray::iterator it = primitiveArray.begin(); it != primitiveArray.end(); ++it)
357     {
358         (*it).Cleanup();
359     }
360 }
361 
362 
363 //------------------------------------------------------------------------------
364 void
Cleanup()365 ResPrimitive::Cleanup()
366 {
367     NW_ASSERT( this->IsValid() );
368 
369     u32 streamNum = this->GetIndexStreamsCount();
370 
371     GLuint* bufferObjects = reinterpret_cast<GLuint*>( this->GetBufferObjects() );
372 
373     for ( uint i = 0; i < streamNum; ++i )
374     {
375         ResIndexStream resStream = this->GetIndexStreams( u32(i) );
376         if (resStream.IsValid() && resStream.ref().m_CommandCache)
377         {
378             CommandCacheManager::Free(resStream.ref().m_CommandCache);
379             resStream.ref().m_CommandCache = NULL;
380             resStream.ref().m_CommandCacheSize = 0;
381         }
382 
383         DeleteBuffer( bufferObjects[ i ], resStream );
384     }
385 
386     std::memset( bufferObjects, 0, sizeof(GLuint) * streamNum );
387 }
388 
389 } /* namespace res */
390 } /* namespace gfx */
391 } /* namespace nw */
392 
393