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