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