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